edje: Reduce duplicated item obj creations and deletions.

Summary:
When text is changed, all of objects for item tag are deleted
and recreated. It is unnecessary work and can cause performance
issues. Actually, many of application developers wonder why
item provider callback functions are called every text changes.
@fix

Test Plan:
Run elementary_test -to "entry emoticon"
When you make a very little change on text,
36 emoticon objects are recreated.

Reviewers: woohyun, jaehwan, herdsman, tasn

Reviewed By: tasn

Subscribers: cedric, jpeg

Differential Revision: https://phab.enlightenment.org/D3537
This commit is contained in:
Youngbok Shin 2016-01-12 13:20:19 +00:00 committed by Tom Hacohen
parent a4785c66c3
commit 6b12ae1e03
1 changed files with 103 additions and 9 deletions

View File

@ -12,6 +12,7 @@ static Eina_Bool _edje_entry_imf_retrieve_selection_cb(void *data, Ecore_IMF_Con
typedef struct _Entry Entry;
typedef struct _Sel Sel;
typedef struct _Anchor Anchor;
typedef struct _Item_Obj Item_Obj;
static void _edje_entry_imf_cursor_location_set(Entry *en);
static void _edje_entry_imf_cursor_info_set(Entry *en);
@ -35,6 +36,7 @@ struct _Entry
Eina_List *anchorlist;
Eina_List *itemlist;
Eina_List *seq;
Item_Obj *item_objs;
char *selection;
Edje_Input_Panel_Lang input_panel_lang;
Eina_Bool composing : 1;
@ -70,6 +72,14 @@ struct _Anchor
Eina_Bool item : 1;
};
struct _Item_Obj
{
EINA_INLIST;
Anchor *an;
char *name;
Evas_Object *obj;
};
#ifdef HAVE_ECORE_IMF
static void
_preedit_clear(Entry *en)
@ -913,6 +923,89 @@ _edje_anchor_mouse_out_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA
ev->event_flags |= rp->part->mask_flags;
}
static void
_item_obj_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
{
Item_Obj *io = data;
Anchor *an = io->an;
Entry *en;
if (!an)
{
ERR("Failed to free item object struct. Anchor is NULL!");
return;
}
en = an->en;
en->item_objs = (Item_Obj *)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
EINA_INLIST_GET(io));
io->an = NULL;
free(io->name);
free(io);
}
static Evas_Object *
_item_obj_get(Anchor *an, Evas_Object *o, Evas_Object *smart, Evas_Object *clip)
{
Evas_Object *obj;
Item_Obj *io;
Entry *en = an->en;
Edje *ed = en->ed;
EINA_INLIST_FOREACH(en->item_objs, io)
{
if (!io->an && io->name && !strcmp(an->name, io->name))
{
io->an = an;
return io->obj;
}
}
io = calloc(1, sizeof(Item_Obj));
obj = ed->item_provider.func
(ed->item_provider.data, smart,
en->rp->part->name, an->name);
evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL, _item_obj_del_cb, io);
evas_object_smart_member_add(obj, smart);
evas_object_stack_above(obj, o);
evas_object_clip_set(obj, clip);
evas_object_pass_events_set(obj, EINA_TRUE);
evas_object_show(obj);
io->an = an;
io->name = strdup(an->name);
io->obj = obj;
en->item_objs = (Item_Obj *)eina_inlist_append(EINA_INLIST_GET(en->item_objs),
EINA_INLIST_GET(io));
return io->obj;
}
static void
_unused_item_objs_free(Entry *en)
{
Item_Obj *io;
Eina_Inlist *l;
EINA_INLIST_FOREACH_SAFE(en->item_objs, l, io)
{
if (!io->an)
{
if (io->obj)
{
evas_object_event_callback_del_full(io->obj, EVAS_CALLBACK_DEL, _item_obj_del_cb, io);
evas_object_del(io->obj);
}
en->item_objs = (Item_Obj *)eina_inlist_remove(EINA_INLIST_GET(en->item_objs),
EINA_INLIST_GET(io));
free(io->name);
free(io);
}
}
}
static void
_anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
{
@ -944,14 +1037,7 @@ _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
if (ed->item_provider.func)
{
ob = ed->item_provider.func
(ed->item_provider.data, smart,
en->rp->part->name, an->name);
evas_object_smart_member_add(ob, smart);
evas_object_stack_above(ob, o);
evas_object_clip_set(ob, clip);
evas_object_pass_events_set(ob, EINA_TRUE);
evas_object_show(ob);
ob = _item_obj_get(an, o, smart, clip);
sel->obj = ob;
}
}
@ -1058,6 +1144,8 @@ _anchors_update(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o, Entry *en)
}
}
}
_unused_item_objs_free(en);
}
static void
@ -1100,6 +1188,8 @@ _anchors_need_update(Edje_Real_Part *rp)
static void
_anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED, Entry *en)
{
Item_Obj *io;
while (en->anchorlist)
{
free(en->anchorlist->data);
@ -1119,7 +1209,7 @@ _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED,
Sel *sel = an->sel->data;
if (sel->obj_bg) evas_object_del(sel->obj_bg);
if (sel->obj_fg) evas_object_del(sel->obj_fg);
if (sel->obj) evas_object_del(sel->obj);
if (!an->item && sel->obj) evas_object_del(sel->obj);
free(sel);
an->sel = eina_list_remove_list(an->sel, an->sel);
}
@ -1129,6 +1219,9 @@ _anchors_clear(Evas_Textblock_Cursor *c EINA_UNUSED, Evas_Object *o EINA_UNUSED,
free(an);
en->anchors = eina_list_remove_list(en->anchors, en->anchors);
}
EINA_INLIST_FOREACH(en->item_objs, io)
io->an = NULL;
}
/* FIXME: This is horrible. It's just a copy&paste (with some adjustments)
@ -2671,6 +2764,7 @@ _edje_entry_real_part_shutdown(Edje *ed, Edje_Real_Part *rp)
rp->typedata.text->entry_data = NULL;
_sel_clear(ed, en->cursor, rp->object, en);
_anchors_clear(en->cursor, rp->object, en);
_unused_item_objs_free(en);
#ifdef HAVE_ECORE_IMF
_preedit_clear(en);
#endif