efl_ui_widget: optimize focus

this commit ensures 2 things:
1. This ensures that the parent is not evaluated when there was no state
changed, this cuts down roughly 30% of the calls to full_eval
2. This ensures that we only listen to parent manager changes when we
are actaully registered. This reduces the amount spend in event emission
a lot.
This commit is contained in:
Marcel Hollerbach 2019-07-04 15:24:22 +02:00 committed by Marcel Hollerbach
parent e776f5f0d7
commit a94c72f4de
1 changed files with 20 additions and 10 deletions

View File

@ -303,13 +303,16 @@ static void _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd);
static void static void
_manager_changed_cb(void *data, const Efl_Event *event EINA_UNUSED) _manager_changed_cb(void *data, const Efl_Event *event EINA_UNUSED)
{ {
if (!efl_alive_get(data))
return;
ELM_WIDGET_DATA_GET(data, pd); ELM_WIDGET_DATA_GET(data, pd);
_full_eval(data, pd); _full_eval(data, pd);
} }
static Efl_Ui_Focus_Object* static Efl_Ui_Focus_Object*
_focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd) _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool want, Eina_Bool should)
{ {
Evas_Object *provider = NULL; Evas_Object *provider = NULL;
Evas_Object *parent; Evas_Object *parent;
@ -326,7 +329,7 @@ _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
provider = parent; provider = parent;
} }
if (new != pd->manager.manager ) if (new != pd->manager.manager)
{ {
old = pd->manager.manager; old = pd->manager.manager;
@ -335,8 +338,12 @@ _focus_manager_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
pd->manager.manager = new; pd->manager.manager = new;
pd->manager.provider = provider; pd->manager.provider = provider;
}
if (pd->manager.provider) if (pd->manager.provider)
{
if (!want && !should)
efl_event_callback_del(pd->manager.provider, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, _manager_changed_cb, obj);
else
efl_event_callback_add(pd->manager.provider, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, _manager_changed_cb, obj); efl_event_callback_add(pd->manager.provider, EFL_UI_FOCUS_OBJECT_EVENT_FOCUS_MANAGER_CHANGED, _manager_changed_cb, obj);
} }
@ -457,7 +464,7 @@ _focus_state_eval(Eo *obj, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Boo
} }
static Efl_Ui_Focus_Object* static Efl_Ui_Focus_Object*
_logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool should) _logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool should, Eina_Bool *state_change_to_parent)
{ {
Efl_Ui_Widget *parent; Efl_Ui_Widget *parent;
Efl_Ui_Focus_Parent_Provider *provider; Efl_Ui_Focus_Parent_Provider *provider;
@ -494,6 +501,10 @@ _logical_parent_eval(Eo *obj EINA_UNUSED, Elm_Widget_Smart_Data *pd, Eina_Bool s
{ {
ELM_WIDGET_DATA_GET_OR_RETURN(parent, parent_wd, NULL); ELM_WIDGET_DATA_GET_OR_RETURN(parent, parent_wd, NULL);
parent_wd->logical.child_count ++; parent_wd->logical.child_count ++;
if (parent_wd->logical.child_count == 1)
{
*state_change_to_parent = EINA_TRUE;
}
} }
pd->logical.parent = parent; pd->logical.parent = parent;
efl_weak_ref(&pd->logical.parent); efl_weak_ref(&pd->logical.parent);
@ -508,12 +519,11 @@ _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
{ {
Efl_Ui_Focus_Object *old_parent; Efl_Ui_Focus_Object *old_parent;
Efl_Ui_Focus_Object *old_registered_parent, *old_registered_manager; Efl_Ui_Focus_Object *old_registered_parent, *old_registered_manager;
Eina_Bool should, want_full; Eina_Bool should, want_full, state_change_to_parent = EINA_FALSE;
_eval_registration_candidate(obj, pd, &should, &want_full); _eval_registration_candidate(obj, pd, &should, &want_full);
old_parent = _logical_parent_eval(obj, pd, should); old_parent = _logical_parent_eval(obj, pd, should, &state_change_to_parent);
if (efl_isa(old_parent, EFL_UI_WIDGET_CLASS)) if (efl_isa(old_parent, EFL_UI_WIDGET_CLASS))
{ {
@ -522,13 +532,13 @@ _full_eval(Eo *obj, Elm_Widget_Smart_Data *pd)
_full_eval(old_parent, old_pd); _full_eval(old_parent, old_pd);
} }
if (efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS)) if (state_change_to_parent && efl_isa(pd->logical.parent, EFL_UI_WIDGET_CLASS))
{ {
ELM_WIDGET_DATA_GET(pd->logical.parent, new_pd); ELM_WIDGET_DATA_GET(pd->logical.parent, new_pd);
_full_eval(pd->logical.parent, new_pd); _full_eval(pd->logical.parent, new_pd);
} }
_focus_manager_eval(obj, pd); _focus_manager_eval(obj, pd, want_full, should);
old_registered_parent = pd->focus.parent; old_registered_parent = pd->focus.parent;
old_registered_manager = pd->focus.manager; old_registered_manager = pd->focus.manager;