summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2019-09-04 21:18:18 +0200
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-09-11 10:37:21 +0200
commit6028952894030de48a199f1633ad83367d33e63e (patch)
tree46c19458c3daef676a648e59fedd98cc5d884cd7
parentf684e85453a5ecc13d8ab8e05ba009366b3ad478 (diff)
downloadefl-6028952894030de48a199f1633ad83367d33e63e.tar.gz
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
-rw-r--r--src/lib/evas/canvas/evas_callbacks.c52
-rw-r--r--src/lib/evas/canvas/evas_object_main.c76
-rw-r--r--src/lib/evas/include/evas_private.h6
3 files changed, 102 insertions, 32 deletions
diff --git a/src/lib/evas/canvas/evas_callbacks.c b/src/lib/evas/canvas/evas_callbacks.c
index 0e9be65f05..1ef776fcc2 100644
--- a/src/lib/evas/canvas/evas_callbacks.c
+++ b/src/lib/evas/canvas/evas_callbacks.c
@@ -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);
-}
diff --git a/src/lib/evas/canvas/evas_object_main.c b/src/lib/evas/canvas/evas_object_main.c
index c5f7b2f61c..95ee8a21d5 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -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"
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index a5ea99e958..2050a487e3 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -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);