focus: item focus moves by geometry. 38/48238/3
authorJaehwan Kim <jae.hwan.kim@samsung.com>
Thu, 13 Aug 2015 04:45:21 +0000 (13:45 +0900)
committerJaehwan Kim <jae.hwan.kim@samsung.com>
Wed, 16 Sep 2015 13:55:22 +0000 (06:55 -0700)
In the widget code, focus origin is added. It can know
the focus movement is originated by which action.
The widgets can choose the item focus moves to last focused item
or geometrically nearby item by focus origin.
In gengrid, focus moves to last focused item if focus origin is
ELM_FOCUS_REVERT. It moves to nearby item if focus origin is from
ELM_FOCUS_UP to ELM_FOCUS_LEFT.

TODO: widgets have items should add the direction feature if it
want the focus to move to nearby item.

@feature

Conflicts:
src/lib/elm_widget.c
src/lib/elm_widget.eo
src/lib/elm_widget.h

Change-Id: If2378a0700af1e075e0d4c625c26251c836ae20e
origin: upstream

src/lib/elm_focus.h
src/lib/elm_gengrid.c
src/lib/elm_widget.c
src/lib/elm_widget.eo
src/lib/elm_widget.h
src/lib/elm_win.c

index aa03636300274946c2557bacb453329d72449750..9552cdb57589ff9bb56a32a98feb6f48a967c17e 100644 (file)
@@ -45,7 +45,9 @@ typedef enum
    ELM_FOCUS_UP,       /**< up direction */
    ELM_FOCUS_DOWN,     /**< down direction */
    ELM_FOCUS_RIGHT,    /**< right direction */
-   ELM_FOCUS_LEFT      /**< left direction */
+   ELM_FOCUS_LEFT,      /**< left direction */
+   ELM_FOCUS_MOUSE,      /**< direction is from mouse */
+   ELM_FOCUS_REVERT      /**< direction is from focus revert */
 } Elm_Focus_Direction;
 
 /**
index c6035b57f5710635b83f3e9c61257656ce170774..d1519ac55afe6fc2bf088f5258570fcdf1ace41a 100644 (file)
@@ -3142,12 +3142,47 @@ _elm_gengrid_nearest_visible_item_get(Evas_Object *obj, Elm_Object_Item *eo_it)
    return eo_it;
 }
 
+static Elm_Object_Item *
+_elm_gengrid_direction_item_get(Evas_Object *obj, Elm_Focus_Direction dir)
+{
+   double max_weight = 0.0, weight = 0.0;
+   Eina_List *item_list = NULL, *l = NULL;
+   Elm_Object_Item *eo_item = NULL, *best_item = NULL;
+   Evas_Object *fobj = _elm_widget_focus_highlight_object_get(obj);
+
+   double degree = 0.0;
+   if (dir == ELM_FOCUS_UP) degree = 0.0;
+   else if (dir == ELM_FOCUS_DOWN) degree = 180.0;
+   else if (dir == ELM_FOCUS_RIGHT) degree = 90.0;
+   else if (dir == ELM_FOCUS_LEFT) degree = 270.0;
+
+   item_list = elm_gengrid_realized_items_get(obj);
+   best_item = elm_gengrid_first_item_get(obj);
+
+   EINA_LIST_FOREACH(item_list, l, eo_item)
+     {
+        ELM_GENGRID_ITEM_DATA_GET(eo_item, item);
+        weight = _elm_widget_focus_direction_weight_get(fobj, VIEW(item), degree);
+        if ((weight == -1.0) ||
+            ((weight != 0.0) && (max_weight != -1.0) &&
+             ((int)(max_weight * 100000000) < (int)(weight * 100000000))))
+          {
+             best_item = eo_item;
+             max_weight = weight;
+          }
+     }
+   eina_list_free(item_list);
+
+   return best_item;
+}
+
 EOLIAN static Eina_Bool
 _elm_gengrid_elm_widget_on_focus(Eo *obj, Elm_Gengrid_Data *sd)
 {
    Eina_Bool int_ret = EINA_FALSE;
    Elm_Object_Item *eo_it = NULL;
    Eina_Bool is_sel = EINA_FALSE;
+   Elm_Focus_Direction focus_origin;
 
    eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_on_focus());
    if (!int_ret) return EINA_FALSE;
@@ -3161,7 +3196,10 @@ _elm_gengrid_elm_widget_on_focus(Eo *obj, Elm_Gengrid_Data *sd)
 
    if (elm_widget_focus_get(obj) && !sd->mouse_down)
      {
-        if (sd->last_focused_item)
+        focus_origin = elm_widget_focus_origin_get(obj);
+        if (focus_origin >= ELM_FOCUS_UP && focus_origin <= ELM_FOCUS_LEFT)
+          eo_it = _elm_gengrid_direction_item_get(obj, focus_origin);
+        else if (sd->last_focused_item)
           eo_it = sd->last_focused_item;
         else if (sd->last_selected_item)
           eo_it = sd->last_selected_item;
index 2aba765cd9e332d700785a9ae53af12a5d8e5dfe..26944b27c9d98f29111594fba5b3baea486b2172 100644 (file)
@@ -63,6 +63,7 @@ struct _Elm_Translate_String_Data
 
 /* local subsystem globals */
 static unsigned int focus_order = 0;
+Elm_Focus_Direction focus_origin = -1;
 
 static inline Eina_Bool
 _elm_widget_is(const Evas_Object *obj)
@@ -200,6 +201,16 @@ _elm_widget_focus_highlight_signal_callback_del(Evas_Object *obj, const char *em
      _elm_win_focus_highlight_signal_callback_del(top, emission, source, _focus_highlight_signal_cb);
 }
 
+Evas_Object *
+_elm_widget_focus_highlight_object_get(const Evas_Object *obj)
+{
+       Evas_Object *top = elm_widget_top_get(obj);
+
+       if (top && eo_isa(top, ELM_WIN_CLASS))
+               return _elm_win_focus_highlight_object_get(top);
+       return NULL;
+}
+
 EAPI Eina_Bool
 elm_widget_focus_highlight_enabled_get(const Evas_Object *obj)
 {
@@ -412,6 +423,7 @@ _if_focused_revert(Evas_Object *obj,
    if (!sd->focused) return;
    if (!sd->parent_obj) return;
 
+   focus_origin = ELM_FOCUS_REVERT;
    top = elm_widget_top_get(sd->parent_obj);
    if (top)
      {
@@ -1853,6 +1865,7 @@ _elm_widget_focus_cycle(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED, Elm_Foc
    Evas_Object *target = NULL;
    if (!_elm_widget_is(obj))
      return;
+   focus_origin = dir;
    elm_widget_focus_next_get(obj, dir, &target);
    if (target)
      {
@@ -1910,8 +1923,8 @@ _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED,
    return EINA_FALSE;
 }
 
-static double
-_direction_weight_get(const Evas_Object *obj1,
+double
+_elm_widget_focus_direction_weight_get(const Evas_Object *obj1,
                       const Evas_Object *obj2,
                       double degree)
 {
@@ -2278,7 +2291,7 @@ _elm_widget_focus_direction_get(Eo *obj, Elm_Widget_Smart_Data *sd, const Evas_O
    if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
      return EINA_FALSE;
 
-   c_weight = _direction_weight_get(base, obj, degree);
+   c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
    if ((c_weight == -1.0) ||
        ((c_weight != 0.0) && (*weight != -1.0) &&
         ((int)(*weight * 1000000) <= (int)(c_weight * 1000000))))
@@ -2371,6 +2384,7 @@ _elm_widget_focus_next_get(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_Directi
      return EINA_FALSE;
    *next = NULL;
 
+   focus_origin = dir;
    /* Ignore if disabled */
    if (_elm_config->access_mode && _elm_access_auto_highlight_get())
      {
@@ -4006,6 +4020,12 @@ _elm_widget_focused_item_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EIN
    return NULL;
 }
 
+EOLIAN static Elm_Focus_Direction
+_elm_widget_focus_origin_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
+{
+   return focus_origin;
+}
+
 EOLIAN static void
 _elm_widget_focus_region_show_mode_set(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *_pd, Elm_Focus_Region_Show_Mode mode)
 {
index 429fdb323282316e8837c8aa0f4ee5d19d2847b1..437e85e3b60406bca34cb5b8e4f053ca0697973f 100644 (file)
@@ -419,6 +419,11 @@ abstract Elm_Widget (Evas.Object_Smart, Elm_Interface_Atspi_Accessible, Elm_Inte
             return: Evas_Object *;
          }
       }
+      focus_origin {
+         get {
+            return: Elm_Focus_Direction;
+         }
+      }
       parent2 {
          set {
             /*@ No description supplied by the EAPI. */
index 351ff9050fee32dbc7b694d97fb9152a8ea8d9d5..ca8bf554914da68d3873c9b7701a8fe7f2bc3275 100644 (file)
@@ -540,6 +540,9 @@ void                  _elm_win_focus_highlight_in_theme_update(Evas_Object *obj,
 void                  _elm_win_focus_highlight_signal_emit(Evas_Object *obj, const char *emission, const char *source);
 void                  _elm_win_focus_highlight_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb _focus_highlight_signal_cb, void *data);
 void                  _elm_win_focus_highlight_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb _focus_highlight_signal_cb);
+Evas_Object          *_elm_win_focus_highlight_object_get(Evas_Object *obj);
+void                  _elm_win_focus_auto_show(Evas_Object *obj);
+void                  _elm_win_focus_auto_hide(Evas_Object *obj);
 
 EAPI void             _elm_access_clear(Elm_Access_Info *ac);
 EAPI void             _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text);
@@ -694,6 +697,8 @@ EAPI Evas_Object     *elm_widget_newest_focus_order_get(const Evas_Object *obj,
 EAPI void             elm_widget_display_mode_set(Evas_Object *obj, Evas_Display_Mode dispmode);
 EAPI Eina_Bool        elm_widget_focus_highlight_enabled_get(const Evas_Object *obj);
 EAPI void             elm_widget_focus_highlight_focus_part_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
+Evas_Object          *_elm_widget_focus_highlight_object_get(const Evas_Object *obj);
+double                _elm_widget_focus_direction_weight_get(const Evas_Object *obj1, const Evas_Object *obj2, double degree);
 EAPI const Elm_Widget_Smart_Class *elm_widget_smart_class_get(void);
 
 /**
@@ -780,6 +785,7 @@ EAPI void             elm_widget_focus_move_policy_set(Evas_Object *obj, Elm_Foc
 EAPI Elm_Focus_Move_Policy elm_widget_focus_move_policy_get(const Evas_Object *obj);
 EAPI void             elm_widget_focus_region_show_mode_set(Evas_Object *obj, Elm_Focus_Region_Show_Mode mode);
 EAPI Elm_Focus_Region_Show_Mode elm_widget_focus_region_show_mode_get(const Evas_Object *obj);
+EAPI Elm_Focus_Direction elm_widget_focus_origin_get(const Evas_Object *obj);
 
 /**
  * Function to operate on a given widget's scrollabe children when necessary.
index b4a25e3c411360a876452dc0979a3b9fad431892..d41b509b9b1a376e4c8055ae6238dbd489f35dc6 100644 (file)
@@ -845,6 +845,14 @@ _elm_win_focus_highlight_visible_set(Elm_Win_Data *sd,
      }
 }
 
+Evas_Object *
+_elm_win_focus_highlight_object_get(Evas_Object *obj)
+{
+   ELM_WIN_DATA_GET(obj, sd);
+
+   return sd->focus_highlight.fobj;
+}
+
 static void
 _elm_win_focus_highlight_anim_setup(Elm_Win_Data *sd,
                                     Evas_Object *obj)
@@ -956,7 +964,15 @@ _elm_win_focus_highlight_reconfigure_job(void *data)
      elm_widget_signal_emit(target, sig, "elm");
 
    if ((!target) || (!common_visible) || (sd->focus_highlight.cur.in_theme))
-     goto the_end;
+     {
+        if (target)
+          {
+             Elm_Focus_Direction focus_origin = elm_widget_focus_origin_get(target);
+             if (focus_origin >= ELM_FOCUS_UP && focus_origin <= ELM_FOCUS_LEFT)
+               _elm_win_focus_highlight_simple_setup(sd, fobj);
+          }
+        goto the_end;
+     }
 
    if (previous)
      focus_style_previous = elm_widget_focus_highlight_style_get(previous);