bu5hm4n pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6028952894030de48a199f1633ad83367d33e63e

commit 6028952894030de48a199f1633ad83367d33e63e
Author: Marcel Hollerbach <m...@marcel-hollerbach.de>
Date:   Wed Sep 4 21:18:18 2019 +0200

    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....@samsung.com>
    Reviewed-by: Cedric BAIL <cedric.b...@free.fr>
    Differential Revision: https://phab.enlightenment.org/D9841
---
 src/lib/evas/canvas/evas_callbacks.c   | 52 +++++++++++------------
 src/lib/evas/canvas/evas_object_main.c | 76 ++++++++++++++++++++++++++++++++--
 src/lib/evas/include/evas_private.h    |  6 ++-
 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);

-- 


Reply via email to