From 0516cdc0f9dc0969ac96df6984af2413680cad01 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Wed, 14 Jun 2017 12:42:25 -0700 Subject: [PATCH] evas: use Eina_List instead of Eina_CList for event grabber. Eina_Clist can actually change the pointer in the cell next bypassing the CoW infrastructure leading to trouble. Considering the case here, using the optimization of Eina_Clist is not necessary and if performance issue arise, can be fixed by using a dichotomic search when removing data. I don't think it is necessary to add this complexity without a real life case. --- .../canvas/efl_canvas_object_event_grabber.c | 150 ++++++++---------- src/lib/evas/canvas/evas_callbacks.c | 4 +- src/lib/evas/canvas/evas_events.c | 56 +++---- src/lib/evas/include/evas_private.h | 13 +- 4 files changed, 90 insertions(+), 133 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_object_event_grabber.c b/src/lib/evas/canvas/efl_canvas_object_event_grabber.c index 30d3f88521..0292de0f9d 100644 --- a/src/lib/evas/canvas/efl_canvas_object_event_grabber.c +++ b/src/lib/evas/canvas/efl_canvas_object_event_grabber.c @@ -10,7 +10,8 @@ struct _Efl_Object_Event_Grabber_Data { Eo *rect; - Eina_Clist contained; + Eina_List *contained; + Eina_Bool vis : 1; }; @@ -18,35 +19,25 @@ typedef struct Efl_Object_Event_Grabber_Iterator { Eina_Iterator iterator; - Eina_Clist *head; - Eina_Clist *current; + Eina_Iterator *itl; Eo *parent; } Efl_Object_Event_Grabber_Iterator; static Eina_Bool -_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_next(Efl_Object_Event_Grabber_Iterator *it, void **data) +_efl_canvas_group_group_iterator_next(Efl_Object_Event_Grabber_Iterator *it, void **data) { - Evas_Object_Protected_Data *obj; - - if (!eina_clist_next(it->head, it->current)) return EINA_FALSE; - - obj = EINA_CLIST_ENTRY(eina_clist_head(it->current), Evas_Object_Protected_Data, events->event.member); - if (data) *data = obj->object; - - it->current = eina_clist_next(it->head, it->current); - - return EINA_TRUE; + return eina_iterator_next(it->itl, data); } static Evas_Object * -_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_get_container(Efl_Object_Event_Grabber_Iterator *it) +_efl_canvas_group_group_iterator_get_container(Efl_Object_Event_Grabber_Iterator *it) { return it->parent; } static void -_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_free(Efl_Object_Event_Grabber_Iterator *it) +_efl_canvas_group_group_iterator_free(Efl_Object_Event_Grabber_Iterator *it) { efl_unref(it->parent); free(it); @@ -57,18 +48,18 @@ _efl_canvas_object_event_grabber_efl_canvas_group_group_children_iterate(const E { Efl_Object_Event_Grabber_Iterator *it; - if (eina_clist_empty(&pd->contained)) return NULL; + if (!pd->contained) return NULL; it = calloc(1, sizeof(Efl_Object_Event_Grabber_Iterator)); if (!it) return NULL; EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); it->parent = efl_ref(eo_obj); - it->head = it->current = &pd->contained; + it->itl = eina_list_iterator_new(pd->contained); - it->iterator.next = FUNC_ITERATOR_NEXT(_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_next); - it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_get_container); - it->iterator.free = FUNC_ITERATOR_FREE(_efl_canvas_object_event_grabber_efl_canvas_group_group_iterator_free); + it->iterator.next = FUNC_ITERATOR_NEXT(_efl_canvas_group_group_iterator_next); + it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_canvas_group_group_iterator_get_container); + it->iterator.free = FUNC_ITERATOR_FREE(_efl_canvas_group_group_iterator_free); return &it->iterator; } @@ -99,60 +90,42 @@ _stacking_verify(Efl_Object_Event_Grabber_Data *pd, Evas_Object_Protected_Data * } } -static void -_child_add_after(Evas_Object_Protected_Data *a, Evas_Object_Events_Data *events) -{ - EINA_COW_WRITE_BEGIN(evas_object_events_cow, a->events, Evas_Object_Events_Data, evs) - eina_clist_add_after(&evs->event.member, &events->event.member); - EINA_COW_WRITE_END(evas_object_events_cow, a->events, evs); -} - static void _child_insert(Efl_Object_Event_Grabber_Data *pd, Evas_Object_Protected_Data *obj) { Evas_Object_Protected_Data *a, *i; - - if (eina_clist_empty(&pd->contained)) - { - /* pd->rect case */ - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - eina_clist_add_head(&pd->contained, &events->event.member); - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); - return; - } + Eina_List *l; + Eina_Bool found = EINA_FALSE; if (pd->vis) _stacking_verify(pd, obj); - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) + + EINA_LIST_REVERSE_FOREACH(pd->contained, l, a) { - EINA_CLIST_FOR_EACH_ENTRY_REV(a, &pd->contained, Evas_Object_Protected_Data, events->event.member) + if (a->object == pd->rect) { - if (a->object == pd->rect) + found = EINA_TRUE; + break; + } + if (a->layer->layer > obj->layer->layer) continue; + if (a->layer->layer < obj->layer->layer) + { + found = EINA_TRUE; + break; + } + EINA_INLIST_FOREACH(EINA_INLIST_GET(a->layer->objects), i) + { + if (a == i || obj == i) { - _child_add_after(a, events); - return; - } - if (a->layer->layer > obj->layer->layer) continue; - if (a->layer->layer < obj->layer->layer) - { - _child_add_after(a, events); - return; - } - EINA_INLIST_FOREACH(EINA_INLIST_GET(a->layer->objects), i) - { - if (a == i) - { - _child_add_after(a, events); - return; - } - if (obj == i) - { - _child_add_after(a, events); - return; - } + found = EINA_TRUE; + break; } } } - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); + + if (found) + pd->contained = eina_list_append_relative(pd->contained, obj, a); + else + pd->contained = eina_list_prepend(pd->contained, obj); } static void @@ -161,10 +134,7 @@ _efl_canvas_object_event_grabber_child_restack(void *data, const Efl_Event *even Efl_Object_Event_Grabber_Data *pd = data; Evas_Object_Protected_Data *obj = efl_data_scope_get(event->object, EFL_CANVAS_OBJECT_CLASS); - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - eina_clist_remove(&events->event.member); - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); - + pd->contained = eina_list_remove(pd->contained, obj); _child_insert(pd, obj); } @@ -214,11 +184,11 @@ _efl_canvas_object_event_grabber_efl_canvas_group_group_member_add(Eo *eo_obj, E return; } } - if (obj->events->event.parent == eo_obj) return; + if (obj->events->parent == eo_obj) return; - if (obj->smart.parent || obj->events->event.parent) evas_object_smart_member_del(member); + if (obj->smart.parent || obj->events->parent) evas_object_smart_member_del(member); EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - events->event.parent = eo_obj; + events->parent = eo_obj; EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); _child_insert(pd, obj); efl_event_callback_add(member, EFL_EVENT_DEL, _efl_canvas_object_event_grabber_child_del, pd); @@ -227,17 +197,16 @@ _efl_canvas_object_event_grabber_efl_canvas_group_group_member_add(Eo *eo_obj, E } EOLIAN static void -_efl_canvas_object_event_grabber_efl_canvas_group_group_member_del(Eo *eo_obj EINA_UNUSED, Efl_Object_Event_Grabber_Data *pd EINA_UNUSED, Eo *member) +_efl_canvas_object_event_grabber_efl_canvas_group_group_member_del(Eo *eo_obj EINA_UNUSED, Efl_Object_Event_Grabber_Data *pd, Eo *member) { Evas_Object_Protected_Data *obj = efl_data_scope_get(member, EFL_CANVAS_OBJECT_CLASS); efl_event_callback_del(member, EFL_EVENT_DEL, _efl_canvas_object_event_grabber_child_del, pd); efl_event_callback_del(member, EFL_GFX_EVENT_RESTACK, _efl_canvas_object_event_grabber_child_restack, pd); + pd->contained = eina_list_remove(pd->contained, obj); + EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - { - eina_clist_remove(&events->event.member); - events->event.parent = NULL; - } + events->parent = NULL; EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); } @@ -285,8 +254,9 @@ _efl_canvas_object_event_grabber_efl_gfx_visible_set(Eo *eo_obj EINA_UNUSED, Efl if (set) { Evas_Object_Protected_Data *obj; + Eina_List *l; - EINA_CLIST_FOR_EACH_ENTRY(obj, &pd->contained, Evas_Object_Protected_Data, events->event.member) + EINA_LIST_FOREACH(pd->contained, l, obj) if (obj->object != pd->rect) _stacking_verify(pd, obj); } pd->vis = !!set; @@ -303,21 +273,25 @@ _efl_canvas_object_event_grabber_efl_gfx_stack_layer_set(Eo *eo_obj, Efl_Object_ static void _efl_canvas_object_event_grabber_restack(void *data, const Efl_Event *event) { + Evas_Object_Protected_Data *obj; Efl_Object_Event_Grabber_Data *pd = data; + Evas_Object_Protected_Data *root = NULL; Eina_List *list = NULL; - Evas_Object_Protected_Data *obj, *nobj; evas_object_layer_set(pd->rect, evas_object_layer_get(event->object)); evas_object_stack_below(pd->rect, event->object); - EINA_CLIST_FOR_EACH_ENTRY_SAFE(obj, nobj, &pd->contained, Evas_Object_Protected_Data, events->event.member) + EINA_LIST_FREE(pd->contained, obj) { - if (obj->object == pd->rect) continue; + if (obj->object == pd->rect) + { + root = obj; + continue; + } list = eina_list_append(list, obj); - EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, Evas_Object_Events_Data, events) - eina_clist_remove(&events->event.member); - EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events); } + + pd->contained = eina_list_append(pd->contained, root); EINA_LIST_FREE(list, obj) _child_insert(pd, obj); } @@ -332,7 +306,7 @@ _efl_canvas_object_event_grabber_efl_object_constructor(Eo *eo_obj, Efl_Object_E obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); obj->is_event_parent = 1; obj->is_smart = 0; - eina_clist_init(&pd->contained); + efl_event_callback_add(eo_obj, EFL_GFX_EVENT_RESTACK, _efl_canvas_object_event_grabber_restack, pd); pd->rect = evas_object_rectangle_add(efl_parent_get(eo_obj)); evas_object_pointer_mode_set(pd->rect, EVAS_OBJECT_POINTER_MODE_NOGRAB); @@ -345,8 +319,10 @@ _efl_canvas_object_event_grabber_efl_object_constructor(Eo *eo_obj, Efl_Object_E EOLIAN static void _efl_canvas_object_event_grabber_efl_object_destructor(Eo *eo_obj, Efl_Object_Event_Grabber_Data *pd) { - Evas_Object_Protected_Data *obj, *nobj; - EINA_CLIST_FOR_EACH_ENTRY_SAFE(obj, nobj, &pd->contained, Evas_Object_Protected_Data, events->event.member) + Evas_Object_Protected_Data *obj; + Eina_List *l, *ln; + + EINA_LIST_FOREACH_SAFE(pd->contained, l, ln, obj) efl_canvas_group_member_del(eo_obj, obj->object); efl_canvas_group_del(eo_obj); efl_destructor(efl_super(eo_obj, MY_CLASS)); @@ -358,11 +334,11 @@ _efl_canvas_object_event_grabber_class_constructor(Efl_Class *klass) evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass); } -const Eina_Clist * +const Eina_List * evas_object_event_grabber_members_list(const Eo *eo_obj) { Efl_Object_Event_Grabber_Data *pd = efl_data_scope_get(eo_obj, MY_CLASS); - return &pd->contained; + return pd->contained; } EAPI Evas_Object * diff --git a/src/lib/evas/canvas/evas_callbacks.c b/src/lib/evas/canvas/evas_callbacks.c index 28ca6d2d3e..554502b1d1 100644 --- a/src/lib/evas/canvas/evas_callbacks.c +++ b/src/lib/evas/canvas/evas_callbacks.c @@ -436,13 +436,13 @@ evas_object_event_callback_call(Evas_Object *eo_obj, Evas_Object_Protected_Data nothing_here: if (!obj->no_propagate) { - if ((obj->smart.parent || obj->events->event.parent) && (type != EVAS_CALLBACK_FREE) && + if ((obj->smart.parent || obj->events->parent) && (type != EVAS_CALLBACK_FREE) && (type <= EVAS_CALLBACK_KEY_UP)) { Evas_Object_Protected_Data *parent_obj; Eo *parent; - parent = obj->events->event.parent ?: obj->smart.parent; + parent = obj->events->parent ?: obj->smart.parent; parent_obj = efl_data_scope_get(parent, EFL_CANVAS_OBJECT_CLASS); evas_object_event_callback_call(parent, parent_obj, type, event_info, event_id, efl_event_desc); } diff --git a/src/lib/evas/canvas/evas_events.c b/src/lib/evas/canvas/evas_events.c index 12f0665690..98538d9888 100644 --- a/src/lib/evas/canvas/evas_events.c +++ b/src/lib/evas/canvas/evas_events.c @@ -10,8 +10,7 @@ int _evas_event_counter = 0; static Eina_List * _evas_event_object_list_in_get(Evas *eo_e, Eina_List *in, - const Eina_Inlist *list, - const Eina_Clist *clist, + const Eina_Inlist *ilist, const Eina_List *list, Evas_Object *stop, int x, int y, int *no_rep, Eina_Bool source); @@ -263,7 +262,6 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data (eo_e, in, evas_object_smart_members_get_direct(eo_obj), NULL, - NULL, stop, obj->cur->geometry.x + obj->map->cur.map->mx, obj->cur->geometry.y + obj->map->cur.map->my, @@ -290,7 +288,7 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data obj->cur->geometry.y <= y && obj->cur->geometry.y + obj->cur->geometry.h >= y)) in = _evas_event_object_list_in_get - (eo_e, in, evas_object_smart_members_get_direct(eo_obj), NULL, NULL, + (eo_e, in, evas_object_smart_members_get_direct(eo_obj), NULL, stop, x, y, &norep, source); } if (norep) @@ -310,7 +308,7 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data { int norep = 0; in = _evas_event_object_list_in_get(eo_e, in, - NULL, evas_object_event_grabber_members_list(eo_obj), NULL, + NULL, evas_object_event_grabber_members_list(eo_obj), stop, x, y, &norep, source); if (norep) { @@ -372,19 +370,17 @@ _evas_event_object_list_raw_in_get_single(Evas *eo_e, Evas_Object_Protected_Data static Eina_List * _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, const Eina_Inlist *ilist, - const Eina_Clist *clist, const Eina_List *list, Evas_Object *stop, int x, int y, int *no_rep, Eina_Bool source) { Evas_Object_Protected_Data *obj = NULL; - Evas_Object_Protected_Data *nobj; #ifdef DDD_DO static int spaces = 0; #endif - if ((!ilist) && (!clist) && (!list)) return in; + if ((!ilist) && (!list)) return in; #ifdef DDD_DO spaces++; #endif @@ -394,19 +390,7 @@ _evas_event_object_list_raw_in_get(Evas *eo_e, Eina_List *in, obj; obj = _EINA_INLIST_CONTAINER(obj, EINA_INLIST_GET(obj)->prev)) { - if (obj->events->event.parent) continue; - in = _evas_event_object_list_raw_in_get_single(eo_e, obj, in, stop, x, y, no_rep, source -#ifdef DDD_DO - ,&spaces -#endif - ); - if (*no_rep) return in; - } - } - else if (clist) - { - EINA_CLIST_FOR_EACH_ENTRY_SAFE_REV(obj, nobj, clist, Evas_Object_Protected_Data, events->event.member) - { + if (obj->events->parent) continue; in = _evas_event_object_list_raw_in_get_single(eo_e, obj, in, stop, x, y, no_rep, source #ifdef DDD_DO ,&spaces @@ -512,14 +496,14 @@ _evas_event_source_mouse_down_events(Evas_Object *eo_obj, Evas *eo_e, { proxy_write->src_event_in = _evas_event_object_list_raw_in_get (eo_e, proxy_write->src_event_in, - evas_object_smart_members_get_direct(eo_src), NULL, NULL, + evas_object_smart_members_get_direct(eo_src), NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else if (src->is_event_parent) { proxy_write->src_event_in = _evas_event_object_list_raw_in_get (eo_e, proxy_write->src_event_in, - NULL, evas_object_event_grabber_members_list(eo_src), NULL, + NULL, evas_object_event_grabber_members_list(eo_src), NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else @@ -696,13 +680,14 @@ _evas_event_source_mouse_move_events(Evas_Object *eo_obj, Evas *eo_e, { int no_rep = 0; ins = _evas_event_object_list_raw_in_get(eo_e, ins, evas_object_smart_members_get_direct(eo_src), - NULL, NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); + NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else if (src->is_event_parent) { int no_rep = 0; - ins = _evas_event_object_list_raw_in_get(eo_e, ins, NULL, evas_object_event_grabber_members_list(eo_src), - NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); + ins = _evas_event_object_list_raw_in_get(eo_e, ins, NULL, + evas_object_event_grabber_members_list(eo_src), + NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else ins = eina_list_append(ins, eo_src); @@ -1143,14 +1128,14 @@ _evas_event_source_multi_move_events(Evas_Object_Protected_Data *obj, Evas_Publi { int no_rep = 0; ins = _evas_event_object_list_raw_in_get - (eo_e, ins, evas_object_smart_members_get_direct(eo_src), NULL, NULL, NULL, + (eo_e, ins, evas_object_smart_members_get_direct(eo_src), NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } if (src->is_event_parent) { int no_rep = 0; ins = _evas_event_object_list_raw_in_get - (eo_e, ins, NULL, evas_object_event_grabber_members_list(eo_src), NULL, NULL, + (eo_e, ins, NULL, evas_object_event_grabber_members_list(eo_src), NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else @@ -1236,14 +1221,14 @@ _evas_event_source_mouse_in_events(Evas_Object *eo_obj, Evas *eo_e, { int no_rep = 0; ins = _evas_event_object_list_raw_in_get(eo_e, ins, evas_object_smart_members_get_direct(eo_src), - NULL, NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); + NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else if (src->is_event_parent) { int no_rep = 0; ins = _evas_event_object_list_raw_in_get(eo_e, ins, NULL, evas_object_event_grabber_members_list(eo_src), - NULL, NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); + NULL, ev->cur.x, ev->cur.y, &no_rep, EINA_TRUE); } else @@ -1348,12 +1333,11 @@ _evas_event_source_mouse_out_events(Evas_Object *eo_obj, Evas *eo_e, static Eina_List * _evas_event_object_list_in_get(Evas *eo_e, Eina_List *in, const Eina_Inlist *ilist, - const Eina_Clist *clist, const Eina_List *list, Evas_Object *stop, int x, int y, int *no_rep, Eina_Bool source) { - return _evas_event_object_list_raw_in_get(eo_e, in, ilist, clist, list, stop, x, y, + return _evas_event_object_list_raw_in_get(eo_e, in, ilist, list, stop, x, y, no_rep, source); } @@ -1372,7 +1356,7 @@ _evas_event_objects_event_list_no_frozen_check(Evas *eo_e, Evas_Object *stop, in int no_rep = 0; D("############################# check layer %i\n", lay->layer); in = _evas_event_object_list_in_get(eo_e, in, - EINA_INLIST_GET(lay->objects), NULL, NULL, + EINA_INLIST_GET(lay->objects), NULL, stop, x, y, &no_rep, EINA_FALSE); if (no_rep) return in; } @@ -2367,9 +2351,9 @@ nogrep: Evas_Object_Protected_Data *below_obj = efl_data_scope_get(eo_below_obj, EFL_CANVAS_OBJECT_CLASS); int norep = 0; ins = _evas_event_object_list_raw_in_get(eo_e, NULL, - EINA_INLIST_GET(below_obj), NULL, NULL, - pdata->seat->x, pdata->seat->y, - &norep, EINA_FALSE); + EINA_INLIST_GET(below_obj), NULL, NULL, + pdata->seat->x, pdata->seat->y, + &norep, EINA_FALSE); } EINA_LIST_FOREACH(copy, l, eo_obj) diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index d54814a41d..7cd3b6fde6 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1099,15 +1099,12 @@ struct _Evas_Object_Events_Data The list below contain the seats (Efl.Input.Devices) which this object allows events to be reported (Mouse, Keybord and focus events). */ - Eina_List *events_whitelist; + Eina_List *events_whitelist; - Eina_List *focused_by_seats; - Eina_Inlist *pointer_grabs; + Eina_List *focused_by_seats; + Eina_Inlist *pointer_grabs; - struct { - Evas_Object *parent; - Eina_Clist member; - } event; + Evas_Object *parent; }; struct _Evas_Object_Protected_State @@ -1703,7 +1700,7 @@ void evas_object_smart_render_cache_clear(Evas_Object *eo_obj); void *evas_object_smart_render_cache_get(const Evas_Object *eo_obj); void evas_object_smart_render_cache_set(Evas_Object *eo_obj, void *data); -const Eina_Clist *evas_object_event_grabber_members_list(const Eo *eo_obj); +const Eina_List *evas_object_event_grabber_members_list(const Eo *eo_obj); const Eina_Inlist *evas_object_smart_members_get_direct(const Evas_Object *obj); void _efl_canvas_group_group_members_all_del(Evas_Object *eo_obj);