elementary : Focus movement is possible with arrow keys. You can check
authorwoohyun <woohyun@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 5 Aug 2011 08:25:07 +0000 (08:25 +0000)
committerwoohyun <woohyun@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 5 Aug 2011 08:25:07 +0000 (08:25 +0000)
this feature in elementary_test -> focus.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/elementary@62125 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/test_focus.c
src/lib/Elementary.h.in
src/lib/elm_widget.c
src/lib/elm_widget.h
src/lib/elm_win.c

index 34bc94c..721cadc 100644 (file)
@@ -91,7 +91,8 @@ test_focus(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info
           {
              Evas_Object *lb = elm_label_add(win);
              elm_object_text_set(lb,
-                                 "<b>Use Tab and Shift+Tab</b>"
+                                 "<b>Use Tab, Shift+Tab, and<br>"
+                                                                "Arrow Keys</b>"
                                 );
              evas_object_size_hint_weight_set(lb, 0.0, 0.0);
              evas_object_size_hint_align_set(lb, EVAS_HINT_FILL,
index d519bde..0b62776 100644 (file)
@@ -320,7 +320,11 @@ extern "C" {
    typedef enum _Elm_Focus_Direction
      {
         ELM_FOCUS_PREVIOUS,
-        ELM_FOCUS_NEXT
+        ELM_FOCUS_NEXT,
+        ELM_FOCUS_UP,
+        ELM_FOCUS_DOWN,
+        ELM_FOCUS_LEFT,
+        ELM_FOCUS_RIGHT
      } Elm_Focus_Direction;
 
    typedef enum _Elm_Text_Format
index ecdf0f2..a87dc35 100644 (file)
@@ -158,6 +158,10 @@ static void _if_focused_revert(Evas_Object *obj,
 static Evas_Object *_newest_focus_order_get(Evas_Object  *obj,
                                             unsigned int *newest_focus_order,
                                             Eina_Bool     can_focus_only);
+static Eina_Bool _focus_list_direction_nearest_get(Evas_Object        *obj,
+                                                Eina_List          *list,
+                                                Elm_Focus_Direction dir,
+                                                Evas_Object       **nearest);
 
 /* local subsystem globals */
 static Evas_Smart *_e_smart = NULL;
@@ -399,6 +403,96 @@ _elm_widget_focus_region_show(const Evas_Object *obj)
      }
 }
 
+static Eina_Bool
+_focus_list_direction_nearest_get(Evas_Object        *obj,
+                                  Eina_List          *list,
+                                  Elm_Focus_Direction dir,
+                                  Evas_Object       **nearest)
+{
+   Evas_Object *cur, *next = NULL;
+   Eina_List *l;
+   double weight = 0.0;
+   Evas_Coord x, y, w, h, cx, cy;
+
+   if (!nearest) return EINA_FALSE;
+   *nearest =  NULL;
+
+   evas_object_geometry_get(obj, &x, &y, &w, &h);
+   cx = x + (w / 2);
+   cy = y + (h / 2);
+
+   EINA_LIST_FOREACH(list, l, cur)
+     {
+        if (obj == cur) continue;
+        Evas_Coord cur_x, cur_y, cur_w, cur_h;
+        int w_gap = 0, h_gap = 0;
+        double cur_weight = 0.0;
+
+        evas_object_geometry_get(cur, &cur_x, &cur_y, &cur_w, &cur_h);
+
+        if (dir == ELM_FOCUS_LEFT)
+          {
+             if (x < (cur_x + cur_w)) continue;
+             w_gap = x - (cur_x + cur_w);
+             if ((cy >= cur_y) && (cy <= (cur_y + cur_h)))
+               h_gap = 0;
+             else if (cy > (cur_y + cur_h))
+               h_gap = cy - (cur_y + cur_h);
+             else if (cy < (cur_y))
+               h_gap = cur_y - cy;
+          }
+        else if (dir == ELM_FOCUS_RIGHT)
+          {
+             if ((x + w) > cur_x) continue;
+             w_gap = cur_x - (x + w);
+             if ((cy >= cur_y) && (cy <= (cur_y + cur_h)))
+               h_gap = 0;
+             else if (cy > (cur_y + cur_h))
+               h_gap = cy - (cur_y + cur_h);
+             else if (cy < (cur_y))
+               h_gap = cur_y - cy;
+          }
+        else if (dir == ELM_FOCUS_UP)
+          {
+             if (y < (cur_y + cur_h)) continue;
+             h_gap = y - (cur_y + cur_h);
+             if ((cx >= cur_x) && (cx <= (cur_x + cur_w)))
+               w_gap = 0;
+             else if (cx < cur_x)
+               w_gap = cur_x - cx;
+             else if (cx > (cur_x + cur_w))
+               w_gap = cur_x + cur_w - cx;
+          }
+        else if (dir == ELM_FOCUS_DOWN)
+          {
+             if ((y + h) > cur_y) continue;
+             h_gap = cur_y - (y + h);
+             if ((cx >= cur_x) && (cx <= (cur_x + cur_w))) w_gap = 0;
+             else if (cx < cur_x)
+               w_gap = cur_x - cx;
+             else if (cx > (cur_x + cur_w))
+               w_gap = cur_x + cur_w - cx;
+          }
+        cur_weight = (w_gap * w_gap) + (h_gap * h_gap);
+
+        if (cur_weight == 0.0)
+          {
+             *nearest = cur;
+             return EINA_TRUE;
+          }
+        cur_weight = 1.0 / cur_weight;
+        if (cur_weight > weight)
+          {
+             weight = cur_weight;
+             next = cur;
+          }
+     }
+   if (!next) return EINA_FALSE;
+   *nearest = next;
+   return EINA_TRUE;
+}
+
+
 /**
  * @defgroup Widget Widget
  *
@@ -1147,6 +1241,47 @@ elm_widget_tree_unfocusable_get(const Evas_Object *obj)
    return sd->tree_unfocusable;
 }
 
+/**
+ * @internal
+ *
+ * Get the list of focusable child objects.
+ *
+ * This function retruns list of child objects which can get focus.
+ *
+ * @param obj The parent widget
+ * @retrun list of focusable child objects.
+ *
+ * @ingroup Widget
+ */
+EAPI Eina_List *
+elm_widget_can_focus_child_list_get(const Evas_Object *obj)
+{
+   API_ENTRY return NULL;
+
+   const Eina_List *l;
+   Eina_List *child_list = NULL;
+   Evas_Object *child;
+
+   if (sd->subobjs)
+     {
+        EINA_LIST_FOREACH(sd->subobjs, l, child)
+          {
+             if ((elm_widget_can_focus_get(child)) &&
+                 (evas_object_visible_get(child)) &&
+                 (!elm_widget_disabled_get(child)))
+               child_list = eina_list_append(child_list, child);
+             else if (elm_widget_is(child))
+               {
+                  Eina_List *can_focus_list;
+                  can_focus_list = elm_widget_can_focus_child_list_get(child);
+                  if (can_focus_list)
+                    child_list = eina_list_merge(child_list, can_focus_list);
+               }
+          }
+     }
+   return child_list;
+}
+
 EAPI void
 elm_widget_highlight_ignore_set(Evas_Object *obj,
                                 Eina_Bool    ignore)
@@ -1598,7 +1733,7 @@ elm_widget_focus_list_next_get(const Evas_Object  *obj,
                                Elm_Focus_Direction dir,
                                Evas_Object       **next)
 {
-   Eina_List *(*list_next)(const Eina_List * list);
+   Eina_List *(*list_next)(const Eina_List * list) = NULL;
 
    if (!next)
      return EINA_FALSE;
@@ -1617,64 +1752,110 @@ elm_widget_focus_list_next_get(const Evas_Object  *obj,
         list_next = eina_list_prev;
      }
    else if (dir == ELM_FOCUS_NEXT)
-     list_next = eina_list_next;
+     {
+        list_next = eina_list_next;
+     }
+   else if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_RIGHT) ||
+            (dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_DOWN))
+     {
+        list_next = eina_list_next;
+     }
    else
      return EINA_FALSE;
 
-   const Eina_List *l = items;
+   if ((dir == ELM_FOCUS_PREVIOUS) || (dir == ELM_FOCUS_NEXT))
+     {
+        const Eina_List *l = items;
 
-   /* Recovery last focused sub item */
-   if (elm_widget_focus_get(obj))
-     for (; l; l = list_next(l))
-       {
-          Evas_Object *cur = list_data_get(l);
-          if (elm_widget_focus_get(cur)) break;
-       }
+        /* Recovery last focused sub item */
+        if (elm_widget_focus_get(obj))
+          for (; l; l = list_next(l))
+            {
+               Evas_Object *cur = list_data_get(l);
+               if (elm_widget_focus_get(cur)) break;
+            }
 
-   const Eina_List *start = l;
-   Evas_Object *to_focus = NULL;
+        const Eina_List *start = l;
+        Evas_Object *to_focus = NULL;
 
-   /* Interate sub items */
-   /* Go to end of list */
-   for (; l; l = list_next(l))
-     {
-        Evas_Object *tmp = NULL;
-        Evas_Object *cur = list_data_get(l);
+        /* Interate sub items */
+        /* Go to end of list */
+        for (; l; l = list_next(l))
+          {
+             Evas_Object *tmp = NULL;
+             Evas_Object *cur = list_data_get(l);
 
-        if (elm_widget_parent_get(cur) != obj)
-          continue;
+             if (elm_widget_parent_get(cur) != obj)
+               continue;
 
-        /* Try Focus cycle in subitem */
-        if (elm_widget_focus_next_get(cur, dir, &tmp))
-          {
-             *next = tmp;
-             return EINA_TRUE;
+             /* Try Focus cycle in subitem */
+             if (elm_widget_focus_next_get(cur, dir, &tmp))
+               {
+                  *next = tmp;
+                  return EINA_TRUE;
+               }
+             else if ((tmp) && (!to_focus))
+               to_focus = tmp;
           }
-        else if ((tmp) && (!to_focus))
-          to_focus = tmp;
-     }
 
-   l = items;
+        l = items;
+
+        /* Get First possible */
+        for (; l != start; l = list_next(l))
+          {
+             Evas_Object *tmp = NULL;
+             Evas_Object *cur = list_data_get(l);
+
+             if (elm_widget_parent_get(cur) != obj)
+               continue;
 
-   /* Get First possible */
-   for (; l != start; l = list_next(l))
+             /* Try Focus cycle in subitem */
+             elm_widget_focus_next_get(cur, dir, &tmp);
+             if (tmp)
+               {
+                  *next = tmp;
+                  return EINA_FALSE;
+               }
+          }
+
+        *next = to_focus;
+        return EINA_FALSE;
+     }
+   else if ((dir == ELM_FOCUS_LEFT) || (dir == ELM_FOCUS_RIGHT) ||
+            (dir == ELM_FOCUS_UP) || (dir == ELM_FOCUS_DOWN))
      {
+        Eina_List *can_focus_list;
         Evas_Object *tmp = NULL;
-        Evas_Object *cur = list_data_get(l);
-
-        if (elm_widget_parent_get(cur) != obj)
-          continue;
+        Evas_Object *cur;
 
-        /* Try Focus cycle in subitem */
-        elm_widget_focus_next_get(cur, dir, &tmp);
-        if (tmp)
+        can_focus_list = elm_widget_can_focus_child_list_get(obj);
+        if (can_focus_list)
           {
-             *next = tmp;
-             return EINA_FALSE;
+             Eina_List *l;
+             EINA_LIST_FOREACH(can_focus_list, l, cur)
+               {
+                  if (elm_widget_focus_get(cur))
+                    {
+                       if (_focus_list_direction_nearest_get(cur, can_focus_list, dir, &tmp))
+                         {
+                            *next = tmp;
+                            return EINA_TRUE;
+                         }
+                       else
+                         {
+                            *next = cur;
+                            return EINA_FALSE;
+                         }
+                    }
+               }
+             if (elm_widget_focus_get(obj))
+               {
+                  *next = list_data_get(can_focus_list);
+                  return EINA_FALSE;
+               }
           }
      }
 
-   *next = to_focus;
    return EINA_FALSE;
 }
 
index 2165e1d..fb90163 100644 (file)
@@ -269,6 +269,7 @@ EAPI void            *elm_widget_signal_callback_del(Evas_Object *obj, const cha
 EAPI void             elm_widget_can_focus_set(Evas_Object *obj, Eina_Bool can_focus);
 EAPI Eina_Bool        elm_widget_can_focus_get(const Evas_Object *obj);
 EAPI Eina_Bool        elm_widget_child_can_focus_get(const Evas_Object *obj);
+EAPI Eina_List       *elm_widget_can_focus_child_list_get(const Evas_Object *obj);
 EAPI void             elm_widget_tree_unfocusable_set(Evas_Object *obj, Eina_Bool tree_unfocusable);
 EAPI Eina_Bool        elm_widget_tree_unfocusable_get(const Evas_Object *obj);
 EAPI void             elm_widget_highlight_ignore_set(Evas_Object *obj, Eina_Bool ignore);
index fa8a83d..b471ac0 100644 (file)
@@ -397,6 +397,34 @@ _elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_T
              ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
              return EINA_TRUE;
           }
+        else if ((!strcmp(ev->keyname, "Left")) ||
+                 (!strcmp(ev->keyname, "KP_Left")))
+          {
+             elm_widget_focus_cycle(obj, ELM_FOCUS_LEFT);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!strcmp(ev->keyname, "Right")) ||
+                 (!strcmp(ev->keyname, "KP_Right")))
+          {
+             elm_widget_focus_cycle(obj, ELM_FOCUS_RIGHT);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!strcmp(ev->keyname, "Up")) ||
+                 (!strcmp(ev->keyname, "KP_Up")))
+          {
+             elm_widget_focus_cycle(obj, ELM_FOCUS_UP);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
+        else if ((!strcmp(ev->keyname, "Down")) ||
+                 (!strcmp(ev->keyname, "KP_Down")))
+          {
+             elm_widget_focus_cycle(obj, ELM_FOCUS_DOWN);
+             ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
+             return EINA_TRUE;
+          }
      }
 
    return EINA_FALSE;