elm_focus: keep all focused states to be consistent when win loses and gets focus

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
This commit is contained in:
WooHyun Jung 2016-04-16 13:47:13 +09:00
parent f24dce9bc9
commit 1c6f3fd966
2 changed files with 45 additions and 30 deletions

View File

@ -77,6 +77,13 @@ _is_focusable(Evas_Object *obj)
return sd->can_focus || (sd->child_can_focus);
}
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)
{
@ -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

View 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