genlist: rework the focus model for performance

Summary:
the focus model before was more meant for simplicity and not for
performance, this now is more made for performance.

The performance boost is achived by not using composition anymore,
but rather register realized items by hand. This keeps the amount
of items bound to the size of the viewport.

Additionally item realization that is followed by unrealization
immediately is not resulting in focus calls.

This solves the performance issue from T6580 in regards of focus.

perf results after this:
http://www.enlightenment.org/ss/e-5b61b50657f3c3.82619729.png

Reviewers: ManMower, zmike

Reviewed By: zmike

Subscribers: cedric, #committers, zmike

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D6720
This commit is contained in:
Marcel Hollerbach 2018-08-02 09:42:06 -04:00 committed by Mike Blumenkrantz
parent 868e3308b1
commit 0e462d5f5a
3 changed files with 80 additions and 23 deletions

View File

@ -400,7 +400,8 @@ _item_content_realize(Elm_Gen_Item *it,
Evas_Object *target,
Eina_List **contents,
const char *src,
const char *parts)
const char *parts,
Eina_Bool calc)
{
Evas_Object *content;
char buf[256];
@ -469,7 +470,8 @@ _item_content_realize(Elm_Gen_Item *it,
if (elm_widget_is(content))
{
_elm_widget_full_eval(content);
if (!calc)
_elm_widget_full_eval(content);
}
}
*contents = eina_list_append(*contents, content);
@ -739,8 +741,19 @@ _item_block_unrealize(Item_Block *itb)
}
if (!dragging)
{
Eina_List *n;
itb->realized = EINA_FALSE;
itb->want_unrealize = EINA_TRUE;
efl_ui_focus_manager_calc_unregister(itb->sd->obj, itb->adapter);
efl_del(itb->adapter);
itb->adapter = NULL;
EINA_LIST_FOREACH(itb->items, n, it)
{
efl_ui_focus_manager_calc_unregister(itb->sd->obj, EO_OBJ(it));
}
}
else
itb->want_unrealize = EINA_FALSE;
@ -1339,11 +1352,11 @@ _elm_genlist_item_state_update(Elm_Gen_Item *it)
}
static void
_view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, Eina_List **contents)
_view_inflate(Evas_Object *view, Elm_Gen_Item *it, Eina_List **sources, Eina_List **contents, Eina_Bool calc)
{
if (!view) return;
if (sources) _item_text_realize(it, view, sources, NULL);
if (contents) _item_content_realize(it, view, contents, "contents", NULL);
if (contents) _item_content_realize(it, view, contents, "contents", NULL, calc);
_item_state_realize(it, view, NULL);
}
@ -1432,7 +1445,7 @@ _decorate_all_item_realize(Elm_Gen_Item *it,
if (it->flipped)
edje_object_signal_emit
(it->deco_all_view, SIGNAL_FLIP_ENABLED, "elm");
_view_inflate(it->deco_all_view, it, NULL, &(it->item->deco_all_contents));
_view_inflate(it->deco_all_view, it, NULL, &(it->item->deco_all_contents), EINA_FALSE);
edje_object_part_swallow
(it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
@ -1898,7 +1911,7 @@ _item_realize(Elm_Gen_Item *it, const int index, Eina_Bool calc)
ERR_ABORT("If you see this error, please notify us and we"
"will fix it");
_view_inflate(VIEW(it), it, &it->texts, &it->contents);
_view_inflate(VIEW(it), it, &it->texts, &it->contents, calc);
if (it->has_contents != (!!it->contents))
it->item->mincalcd = EINA_FALSE;
it->has_contents = !!it->contents;
@ -1906,7 +1919,7 @@ _item_realize(Elm_Gen_Item *it, const int index, Eina_Bool calc)
{
edje_object_signal_emit(VIEW(it), SIGNAL_FLIP_ENABLED, "elm");
_item_content_realize(it, VIEW(it), &it->item->flip_contents,
"flips", NULL);
"flips", NULL, EINA_FALSE);
}
/* access: unregister item which have no text and content */
@ -2496,13 +2509,43 @@ _item_block_position(Item_Block *itb, const int blk_idx)
evas_event_thaw_eval(evas_object_evas_get((itb->sd)->obj));
}
static inline void
_flush_block_order(Elm_Genlist_Data *sd)
{
Item_Block *itb;
Eina_List *blocks = NULL;
EINA_INLIST_FOREACH(sd->blocks, itb)
{
if (itb->adapter)
blocks = eina_list_append(blocks, itb->adapter);
}
efl_ui_focus_manager_calc_update_order(sd->obj, sd->obj, blocks);
}
static void
_item_block_realize(Item_Block *itb)
{
Elm_Gen_Item *it;
Eina_List *n;
if (itb->realized) return;
itb->realized = EINA_TRUE;
itb->want_unrealize = EINA_FALSE;
if (!itb->adapter)
{
itb->adapter = efl_add(EFL_UI_FOCUS_COMPOSITION_ADAPTER_CLASS, itb->sd->obj);
efl_ui_focus_manager_calc_register_logical(itb->sd->obj, itb->adapter, itb->sd->obj, NULL);
_flush_block_order(itb->sd);
}
EINA_LIST_FOREACH(itb->items, n, it)
{
efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(it), itb->adapter, NULL);
}
}
static Eina_Bool
@ -4314,6 +4357,24 @@ _item_block_new(Elm_Genlist_Data *sd,
return itb;
}
static void
_update_block_registration(Item_Block *itb, Elm_Gen_Item *element)
{
Elm_Gen_Item *it = NULL;
Eina_List *order = NULL;
if (!itb->realized) return;
efl_ui_focus_manager_calc_register_logical(itb->sd->obj, EO_OBJ(element), itb->adapter, NULL);
EINA_INLIST_FOREACH(itb->items, it)
{
order = eina_list_append(order, EO_OBJ(it));
}
efl_ui_focus_manager_calc_update_order(itb->sd->obj, itb->adapter, order);
}
/**
* @internal
*
@ -4343,6 +4404,7 @@ newblock:
sd->blocks =
eina_inlist_append(sd->blocks, EINA_INLIST_GET(itb));
itb->items = eina_list_append(itb->items, it);
_update_block_registration(itb, it);
itb->position_update = EINA_TRUE;
it->position = eina_list_count(itb->items);
it->position_update = EINA_TRUE;
@ -4415,7 +4477,7 @@ newblock:
if (!itb) return EINA_FALSE;
}
itb->items = eina_list_prepend(itb->items, it);
_update_block_registration(itb, it);
_item_position_update(itb->items, 0);
}
// item move_after, append, insert_after, sorted_insert without before
@ -4436,6 +4498,7 @@ newblock:
if (!itb) return EINA_FALSE;
}
itb->items = eina_list_append(itb->items, it);
_update_block_registration(itb, it);
it->position = eina_list_count(itb->items);
}
}
@ -4467,12 +4530,14 @@ newblock:
if (it->item->before)
{
itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
_update_block_registration(itb, it);
_item_position_update
(eina_list_prev(tmp), it->item->rel->position);
}
else
{
itb->items = eina_list_append_relative_list(itb->items, it, tmp);
_update_block_registration(itb, it);
_item_position_update
(eina_list_next(tmp), it->item->rel->position + 1);
}
@ -4666,8 +4731,6 @@ _queue_process(Elm_Genlist_Data *sd)
t0 = ecore_time_get();
if (sd->queue) efl_ui_focus_composition_prepare(sd->obj);
for (n = 0; (sd->queue) && (n < ITEM_QUEUE_MAX); n++)
{
Elm_Gen_Item *it;
@ -5478,7 +5541,7 @@ _decorate_item_realize(Elm_Gen_Item *it)
it);
_view_inflate(it->item->deco_it_view, it, &it->item->deco_it_texts,
&it->item->deco_it_contents);
&it->item->deco_it_contents, EINA_FALSE);
edje_object_part_swallow
(it->item->deco_it_view,
edje_object_data_get(it->item->deco_it_view, "mode_part"), VIEW(it));
@ -5804,9 +5867,6 @@ _elm_genlist_efl_object_constructor(Eo *obj, Elm_Genlist_Data *sd)
efl_ui_focus_parent_provider_gen_container_set(efl_added, obj),
efl_ui_focus_parent_provider_gen_content_item_map_set(efl_added, sd->content_item_map));
efl_ui_focus_composition_custom_manager_set(obj, obj);
efl_ui_focus_composition_logical_mode_set(obj, EINA_TRUE);
sd->obj = obj;
efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
@ -6197,8 +6257,6 @@ _elm_genlist_item_new(Elm_Genlist_Data *sd,
it->item->expanded_depth = depth;
sd->item_count++;
efl_ui_focus_composition_dirty(sd->obj);
return it;
}
@ -7234,23 +7292,23 @@ _elm_genlist_item_fields_update(Eo *eo_item EINA_UNUSED, Elm_Gen_Item *it,
}
if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
{
_item_content_realize(it, VIEW(it), &it->contents, "contents", parts);
_item_content_realize(it, VIEW(it), &it->contents, "contents", parts, EINA_FALSE);
if (it->flipped)
{
_item_content_realize(it, VIEW(it), &it->item->flip_contents,
"flips", parts);
"flips", parts, EINA_FALSE);
}
if (it->item->deco_it_view)
{
_item_content_realize(it, it->item->deco_it_view,
&it->item->deco_it_contents,
"contents", parts);
"contents", parts, EINA_FALSE);
}
if (it->item->wsd->decorate_all_mode)
{
_item_content_realize(it, it->deco_all_view,
&it->item->deco_all_contents,
"contents", parts);
"contents", parts, EINA_FALSE);
}
if (it->has_contents != (!!it->contents))
it->item->mincalcd = EINA_FALSE;
@ -8754,7 +8812,6 @@ _elm_genlist_efl_ui_focus_composition_prepare(Eo *obj, Elm_Genlist_Data *pd)
efl_ui_focus_object_prepare_logical(item->base->eo_obj);
}
}
EOLIAN static void

View File

@ -1,6 +1,6 @@
import elm_general;
class Elm.Genlist (Efl.Ui.Layout.Object, Efl.Ui.Focus.Composition, Elm.Interface_Scrollable, Efl.Ui.Clickable,
class Elm.Genlist (Efl.Ui.Layout.Object, Elm.Interface_Scrollable, Efl.Ui.Clickable,
Efl.Access.Widget.Action, Efl.Access.Selection,
Efl.Ui.Selectable, Efl.Ui.Legacy)
{
@ -553,7 +553,6 @@ class Elm.Genlist (Efl.Ui.Layout.Object, Efl.Ui.Focus.Composition, Elm.Interface
Efl.Access.Selection.is_child_selected;
Efl.Access.Selection.all_children_select;
Efl.Access.Selection.access_selection_clear;
Efl.Ui.Focus.Composition.prepare;
Efl.Ui.Widget.focus_state_apply;
Efl.Ui.Focus.Manager.setup_on_first_touch;
}

View File

@ -268,6 +268,7 @@ struct _Item_Block
Evas_Coord x, y, w, h, minw, minh;
int position;
int item_position_stamp;
Eo *adapter;
Eina_Bool position_update : 1;
Eina_Bool want_unrealize : 1;