elm_focus: keep all focused states to be consistent when win loses and gets focus
authorWooHyun Jung <wh0705.jung@samsung.com>
Sat, 16 Apr 2016 04:47:13 +0000 (13:47 +0900)
committerWooHyun Jung <wh0705.jung@samsung.com>
Sat, 16 Apr 2016 04:47:13 +0000 (13:47 +0900)
Since focus_clear removed all the focused traces, focus was not reverted well
whenever win lost and got focus repeatedly.
For instance,
1. set focus to button1
2. set focus to button2
3. win focus out and in
4. remove button2
5. focus is on win not on button1

So, focus logic changes to not clear focused states when win loses focus.

@fix

src/lib/elementary/elm_widget.c
src/lib/elementary/elm_win.c

index 1746844..b3096c9 100644 (file)
@@ -78,6 +78,13 @@ _is_focusable(Evas_Object *obj)
 }
 
 static inline Eina_Bool
+_is_focused(Evas_Object *obj)
+{
+   API_ENTRY return EINA_FALSE;
+   return sd->focused;
+}
+
+static inline Eina_Bool
 _elm_scrollable_is(const Evas_Object *obj)
 {
    INTERNAL_ENTRY EINA_FALSE;
@@ -246,7 +253,7 @@ _on_sub_obj_del(void *data, const Eo_Event *event)
 
    if (_elm_widget_is(event->obj))
      {
-        if (elm_widget_focus_get(event->obj)) _parents_unfocus(sd->obj);
+        if (_is_focused(event->obj)) _parents_unfocus(sd->obj);
      }
    if (event->obj == sd->resize_obj)
      {
@@ -383,11 +390,11 @@ _if_focused_revert(Evas_Object *obj,
                   ELM_WIDGET_DATA_GET(newest, sd2);
                   if (!sd2) return;
 
-                  if (!elm_widget_focus_get(newest))
+                  if (!_is_focused(newest))
                     elm_widget_focus_steal(newest, NULL);
                   else
                     {
-                       if (sd2->resize_obj && elm_widget_focus_get(sd2->resize_obj))
+                       if (sd2->resize_obj && _is_focused(sd2->resize_obj))
                          elm_widget_focused_object_clear(sd2->resize_obj);
                        else
                          {
@@ -396,7 +403,7 @@ _if_focused_revert(Evas_Object *obj,
                             EINA_LIST_FOREACH(sd2->subobjs, l, child)
                               {
                                  if (!_elm_widget_is(child)) continue;
-                                 if (elm_widget_focus_get(child))
+                                 if (_is_focused(child))
                                    {
                                       elm_widget_focused_object_clear(child);
                                       break;
@@ -826,12 +833,10 @@ _parent_focus(Evas_Object *obj, Elm_Object_Item *item)
 
    focus_order++;
    sd->focus_order = focus_order;
+   sd->focused = EINA_TRUE;
 
    if (sd->top_win_focused)
-     {
-        sd->focused = EINA_TRUE;
-        elm_obj_widget_on_focus(obj, item);
-     }
+     elm_obj_widget_on_focus(obj, item);
    sd->focus_order_on_calc = EINA_FALSE;
 
    if (_elm_config->access_mode == ELM_ACCESS_MODE_ON)
@@ -1194,7 +1199,7 @@ _elm_widget_sub_object_add(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj
                elm_widget_theme(sobj);
           }
 
-        if (elm_widget_focus_get(sobj)) _parents_focus(obj);
+        if (_is_focused(sobj)) _parents_focus(obj);
 
         elm_widget_display_mode_set(sobj,
               evas_object_size_hint_display_mode_get(obj));
@@ -1242,7 +1247,7 @@ _elm_widget_sub_object_del(Eo *obj, Elm_Widget_Smart_Data *sd, Evas_Object *sobj
 
    if (_elm_widget_is(sobj))
      {
-        if (elm_widget_focus_get(sobj))
+        if (_is_focused(sobj))
           {
              elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
              elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
@@ -1320,7 +1325,7 @@ _elm_widget_resize_object_set(Eo *obj, Elm_Widget_Smart_Data *sd,
 
         if (_elm_widget_is(sd->resize_obj))
           {
-             if (elm_widget_focus_get(sd->resize_obj)) _parents_unfocus(obj);
+             if (_is_focused(sd->resize_obj)) _parents_unfocus(obj);
           }
         elm_widget_sub_object_del(obj, sd->resize_obj);
      }
@@ -1568,7 +1573,7 @@ _elm_widget_access_highlight_in_theme_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_
 EOLIAN static Eina_Bool
 _elm_widget_focus_get(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *sd)
 {
-   return sd->focused;
+   return (sd->focused && sd->top_win_focused);
 }
 
 EOLIAN static Eina_Bool
@@ -1583,7 +1588,7 @@ _elm_widget_focused_object_get(Eo *obj, Elm_Widget_Smart_Data *sd)
    const Evas_Object *subobj;
    const Eina_List *l;
 
-   if (!sd->focused) return NULL;
+   if (!sd->focused || !sd->top_win_focused) return NULL;
    EINA_LIST_FOREACH(sd->subobjs, l, subobj)
      {
         Evas_Object *fobj;
@@ -1921,7 +1926,7 @@ _elm_widget_focus_direction_go(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED,
    double weight = 0.0;
 
    if (!_elm_widget_is(obj)) return EINA_FALSE;
-   if (!elm_widget_focus_get(obj)) return EINA_FALSE;
+   if (!_is_focused(obj)) return EINA_FALSE;
 
    current_focused = elm_widget_focused_object_get(obj);
 
@@ -2300,7 +2305,7 @@ _elm_widget_focus_direction_get(const Eo *obj, Elm_Widget_Smart_Data *sd, const
         return int_ret;
      }
 
-   if (!elm_widget_can_focus_get(obj) || elm_widget_focus_get(obj))
+   if (!elm_widget_can_focus_get(obj) || _is_focused((Eo *)obj))
      return EINA_FALSE;
 
    c_weight = _elm_widget_focus_direction_weight_get(base, obj, degree);
@@ -2416,7 +2421,7 @@ _elm_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_D
      {
         Eina_Bool int_ret = EINA_FALSE;
         int_ret = elm_obj_widget_focus_next((Eo *)obj, dir, next, next_item);
-        if (!int_ret && elm_widget_focus_get(obj))
+        if (!int_ret && _is_focused((Eo *)obj))
           {
              Evas_Object *o = NULL;
              if (dir == ELM_FOCUS_PREVIOUS)
@@ -2473,7 +2478,7 @@ _elm_widget_focus_next_get(const Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Focus_D
    else if (!elm_widget_can_focus_get(obj))
      return EINA_FALSE;
 
-   if (elm_widget_focus_get(obj))
+   if (_is_focused((Eo *)obj))
      {
         if (dir == ELM_FOCUS_PREVIOUS)
           *next_item = sd->item_focus_previous;
@@ -2647,7 +2652,7 @@ _elm_widget_focus_list_next_get(const Eo *obj, Elm_Widget_Smart_Data *_pd EINA_U
                  || (dir == ELM_FOCUS_RIGHT)
                  || (dir == ELM_FOCUS_LEFT))
           {
-             if (tmp && elm_widget_focus_get(cur))
+             if (tmp && _is_focused(cur))
                {
                   *next = tmp;
                   *next_item = tmp_item;
@@ -2917,7 +2922,7 @@ static void
 _focused_object_clear(Elm_Widget_Smart_Data *sd)
 {
    if (sd->resize_obj && elm_widget_is(sd->resize_obj) &&
-         elm_widget_focus_get(sd->resize_obj))
+       _is_focused(sd->resize_obj))
      {
         elm_obj_widget_focused_object_clear(sd->resize_obj);
      }
@@ -2927,7 +2932,7 @@ _focused_object_clear(Elm_Widget_Smart_Data *sd)
         Evas_Object *child;
         EINA_LIST_FOREACH(sd->subobjs, l, child)
           {
-             if (_elm_widget_is(child) && elm_widget_focus_get(child))
+             if (_elm_widget_is(child) && _is_focused(child))
                {
                   elm_obj_widget_focused_object_clear(child);
                   break;
@@ -2942,7 +2947,8 @@ _elm_widget_focused_object_clear(Eo *obj, Elm_Widget_Smart_Data *sd)
    if (!sd->focused) return;
    _focused_object_clear(sd);
    sd->focused = EINA_FALSE;
-   elm_obj_widget_on_focus(obj, NULL);
+   if (sd->top_win_focused)
+     elm_obj_widget_on_focus(obj, NULL);
 }
 
 EOLIAN static void
@@ -2980,6 +2986,17 @@ _elm_widget_focus_steal(Eo *obj, Elm_Widget_Smart_Data *sd, Elm_Object_Item *ite
    return;
 }
 
+static void
+_parents_on_focus(Evas_Object *obj)
+{
+   API_ENTRY return;
+   if (!sd->focused || !sd->top_win_focused) return;
+
+   Evas_Object *o = elm_widget_parent_get(obj);
+   if (o) _parents_on_focus(o);
+   elm_obj_widget_on_focus(obj, NULL);
+}
+
 EOLIAN static void
 _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
 {
@@ -2988,10 +3005,7 @@ _elm_widget_focus_restore(Eo *obj, Elm_Widget_Smart_Data *_pd EINA_UNUSED)
 
    newest = elm_widget_newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
    if (newest)
-     {
-        elm_object_focus_set(newest, EINA_FALSE);
-        elm_object_focus_set(newest, EINA_TRUE);
-     }
+     _parents_on_focus(newest);
 }
 
 void
@@ -3016,6 +3030,9 @@ _elm_widget_top_win_focused_set(Evas_Object *obj,
           _elm_widget_top_win_focused_set(child, top_win_focused);
      }
    sd->top_win_focused = top_win_focused;
+
+   if (sd->focused && !sd->top_win_focused)
+     elm_obj_widget_on_focus(obj, NULL);
 }
 
 Eina_Bool
index ba8089b..8576cb4 100644 (file)
@@ -1086,7 +1086,6 @@ _elm_win_focus_in(Ecore_Evas *ee)
 {
    Elm_Win_Data *sd = _elm_win_associate_get(ee);
    Evas_Object *obj;
-   unsigned int order = 0;
 
    if ((!sd) || (sd->modal_count)) return;
 
@@ -1095,8 +1094,7 @@ _elm_win_focus_in(Ecore_Evas *ee)
    _elm_widget_top_win_focused_set(obj, EINA_TRUE);
    if (sd->type != ELM_WIN_FAKE)
      {
-        if (!elm_widget_focus_order_get(obj)
-            || (obj == elm_widget_newest_focus_order_get(obj, &order, EINA_TRUE)))
+        if (!elm_widget_focus_order_get(obj))
           {
              elm_widget_focus_steal(obj, NULL);
           }
@@ -1107,7 +1105,8 @@ _elm_win_focus_in(Ecore_Evas *ee)
 
              newest = elm_widget_newest_focus_order_get
                 (obj, &newest_focus_order, EINA_TRUE);
-             if (newest && _elm_widget_onscreen_is(newest))
+             if (newest &&
+                 (_elm_widget_onscreen_is(newest) || (newest == obj)))
                elm_widget_focus_restore(obj);
              else
                evas_object_focus_set(obj, EINA_TRUE);
@@ -1145,7 +1144,6 @@ _elm_win_focus_out(Ecore_Evas *ee)
 
    obj = sd->obj;
 
-   elm_object_focus_set(obj, EINA_FALSE);
    _elm_widget_top_win_focused_set(obj, EINA_FALSE);
    // FIXME: the event is deprecated but still in use.
    // Has to be removed in EFL2.0