evas_callbacks: make the callback protection a little bit safer

the problem here is that we might subscribe to an event before
evas_object_callbacks_init has happened. This sounds like something
which might not happen. However, with the interfaces project this
definitly will start to happen because someone will some day overwrite
the evas object and do something before the constructor, which will not
raise a error or something but will simply just not work.

With this commit we are not listening to the event callbacks via event
emission but rather via inheritance. With this there is no "earlier than
we listend" point, and the issue in the task is solved by itself.

fix T8202

Reviewed-by: Jaehyun Cho <jae_hyun.cho@samsung.com>
Reviewed-by: Cedric BAIL <cedric.bail@free.fr>
Differential Revision: https://phab.enlightenment.org/D9841
This commit is contained in:
Marcel Hollerbach 2019-09-04 21:18:18 +02:00
parent f684e85453
commit 6028952894
3 changed files with 102 additions and 32 deletions

View File

@ -800,18 +800,30 @@ _animator_repeater(void *data, const Efl_Event *event)
DBG("Emitting animator tick on %p.", obj->object);
}
static void
_check_event_catcher_add(void *data, const Efl_Event *event)
void
evas_object_callbacks_finalized(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
{
if (obj->animator_ref > 0)
{
if (obj->layer && obj->layer->evas)
{
efl_event_callback_add(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
DBG("Registering an animator tick on canvas %p for object %p.",
obj->layer->evas->evas, obj->object);
}
}
}
void
evas_object_callbacks_event_catcher_add(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array)
{
const Efl_Callback_Array_Item_Full *array = event->info;
Evas_Object_Protected_Data *obj = data;
Evas_Callback_Type type = EVAS_CALLBACK_LAST;
void *gd = NULL;
int i;
for (i = 0; array[i].desc != NULL; i++)
{
if (obj->layer->evas->gesture_manager)
if (obj->layer && obj->layer->evas && obj->layer->evas->gesture_manager)
{
if (!gd) gd = _efl_canvas_gesture_manager_private_data_get(obj->layer->evas->gesture_manager);
@ -822,9 +834,12 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
{
if (obj->animator_ref++ > 0) break;
efl_event_callback_add(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
DBG("Registering an animator tick on canvas %p for object %p.",
obj->layer->evas->evas, obj->object);
if (efl_finalized_get(eo_obj))
{
efl_event_callback_add(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
DBG("Registering an animator tick on canvas %p for object %p.",
obj->layer->evas->evas, obj->object);
}
}
else if ((type = _legacy_evas_callback_type(array[i].desc)) != EVAS_CALLBACK_LAST)
{
@ -838,11 +853,9 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
}
}
static void
_check_event_catcher_del(void *data, const Efl_Event *event)
void
evas_object_callbacks_event_catcher_del(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array)
{
const Efl_Callback_Array_Item_Full *array = event->info;
Evas_Object_Protected_Data *obj = data;
void *gd = NULL;
int i;
@ -870,18 +883,3 @@ _check_event_catcher_del(void *data, const Efl_Event *event)
}
}
EFL_CALLBACKS_ARRAY_DEFINE(event_catcher_watch,
{ EFL_EVENT_CALLBACK_ADD, _check_event_catcher_add },
{ EFL_EVENT_CALLBACK_DEL, _check_event_catcher_del });
void
evas_object_callback_init(Efl_Canvas_Object *eo_obj, Evas_Object_Protected_Data *obj)
{
efl_event_callback_array_add(eo_obj, event_catcher_watch(), obj);
}
void
evas_object_callback_shutdown(Efl_Canvas_Object *eo_obj, Evas_Object_Protected_Data *obj)
{
efl_event_callback_array_del(eo_obj, event_catcher_watch(), obj);
}

View File

@ -225,7 +225,6 @@ _efl_canvas_object_efl_object_constructor(Eo *eo_obj, Evas_Object_Protected_Data
obj->events = eina_cow_alloc(evas_object_events_cow);
evas_object_inject(eo_obj, obj, evas);
evas_object_callback_init(eo_obj, obj);
return eo_obj;
@ -255,6 +254,7 @@ _efl_canvas_object_efl_object_finalize(Eo *eo_obj, Evas_Object_Protected_Data *o
e->finalize_objects = eina_list_prepend(e->finalize_objects, eo_obj);
end:
evas_object_callbacks_finalized(eo_obj, obj);
return efl_finalize(efl_super(eo_obj, MY_CLASS));
}
@ -475,7 +475,6 @@ evas_object_free(Evas_Object_Protected_Data *obj, Eina_Bool clean_layer)
if (!obj) return ;
eo_obj = obj->object;
evas_object_callback_shutdown(eo_obj, obj);
if (efl_isa(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS))
_evas_object_image_free(eo_obj);
evas_object_map_set(eo_obj, NULL);
@ -2431,6 +2430,73 @@ _efl_canvas_object_coords_inside_get(const Eo *eo_obj EINA_UNUSED, Evas_Object_P
return RECTS_INTERSECT(pos.x, pos.y, 1, 1, c.x, c.y, c.w, c.h);
}
EOLIAN static Eina_Bool
_efl_canvas_object_efl_object_event_callback_priority_add(Eo *obj, Evas_Object_Protected_Data *pd,
const Efl_Event_Description *desc,
Efl_Callback_Priority priority,
Efl_Event_Cb func,
const void *user_data)
{
Efl_Callback_Array_Item full[2] = {
{desc, func},
{NULL, NULL}
};
if (efl_event_callback_priority_add(efl_super(obj, MY_CLASS), desc, priority, func, user_data))
{
evas_object_callbacks_event_catcher_add(obj, pd, full);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_canvas_object_efl_object_event_callback_del(Eo *obj, Evas_Object_Protected_Data *pd,
const Efl_Event_Description *desc,
Efl_Event_Cb func,
const void *user_data)
{
Efl_Callback_Array_Item full[2] = {
{desc, func},
{NULL, NULL}
};
if (efl_event_callback_del(efl_super(obj, MY_CLASS), desc, func, user_data))
{
evas_object_callbacks_event_catcher_del(obj, pd, full);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_canvas_object_efl_object_event_callback_array_priority_add(Eo *obj, Evas_Object_Protected_Data *pd,
const Efl_Callback_Array_Item *array,
Efl_Callback_Priority priority,
const void *user_data)
{
if (efl_event_callback_array_priority_add(efl_super(obj, MY_CLASS), array, priority, user_data))
{
evas_object_callbacks_event_catcher_add(obj, pd, array);
return EINA_TRUE;
}
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_canvas_object_efl_object_event_callback_array_del(Eo *obj, Evas_Object_Protected_Data *pd,
const Efl_Callback_Array_Item *array,
const void *user_data)
{
if (efl_event_callback_array_del(efl_super(obj, MY_CLASS), array, user_data))
{
evas_object_callbacks_event_catcher_del(obj, pd, array);
return EINA_TRUE;
}
return EINA_FALSE;
}
static void
_is_frame_flag_set(Evas_Object_Protected_Data *obj, Eina_Bool is_frame)
{
@ -2699,7 +2765,11 @@ EOAPI EFL_VOID_FUNC_BODYV(efl_canvas_object_type_set, EFL_FUNC_CALL(type), const
EFL_OBJECT_OP_FUNC(efl_canvas_object_is_frame_object_set, _efl_canvas_object_is_frame_object_set), \
EFL_OBJECT_OP_FUNC(efl_canvas_object_is_frame_object_get, _efl_canvas_object_is_frame_object_get), \
EFL_OBJECT_OP_FUNC(efl_canvas_object_legacy_ctor, _efl_canvas_object_legacy_ctor), \
EFL_OBJECT_OP_FUNC(efl_canvas_object_type_set, _efl_canvas_object_type_set)
EFL_OBJECT_OP_FUNC(efl_canvas_object_type_set, _efl_canvas_object_type_set), \
EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_canvas_object_efl_object_event_callback_priority_add), \
EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_canvas_object_efl_object_event_callback_array_priority_add), \
EFL_OBJECT_OP_FUNC(efl_event_callback_del, _efl_canvas_object_efl_object_event_callback_del), \
EFL_OBJECT_OP_FUNC(efl_event_callback_array_del, _efl_canvas_object_efl_object_event_callback_array_del)
#include "canvas/efl_canvas_object.eo.c"
#include "canvas/efl_canvas_object_eo.legacy.c"

View File

@ -1603,8 +1603,10 @@ void evas_object_clip_across_check(Evas_Object *obj, Evas_Object_Protected_Data
void evas_object_clip_across_clippees_check(Evas_Object *obj, Evas_Object_Protected_Data *pd);
void evas_object_mapped_clip_across_mark(Evas_Object *obj, Evas_Object_Protected_Data *pd);
void evas_event_callback_call(Evas *e, Evas_Callback_Type type, void *event_info);
void evas_object_callback_init(Efl_Canvas_Object *eo_obj, Evas_Object_Protected_Data *obj);
void evas_object_callback_shutdown(Efl_Canvas_Object *eo_obj, Evas_Object_Protected_Data *obj);
void evas_object_callbacks_finalized(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj);
void evas_object_callbacks_event_catcher_add(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array);
void evas_object_callbacks_event_catcher_del(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array);
void evas_object_event_callback_call(Evas_Object *obj, Evas_Object_Protected_Data *pd, Evas_Callback_Type type, void *event_info, int event_id, const Efl_Event_Description *efl_event_desc);
Eina_List *evas_event_objects_event_list(Evas *e, Evas_Object *stop, int x, int y);
void evas_debug_error(void);