1 
2 #include "evas_common_private.h"
3 #include "evas_private.h"
4 
5 EVAS_MEMPOOL(_mp_pc);
6 
7 extern Eina_Hash* signals_hash_table;
8 
9 /* Legacy events, do not use anywhere */
10 void _evas_object_smart_callback_call_internal(Evas_Object *eo_obj, const Efl_Event_Description *efl_event_desc);
11 static const Efl_Event_Description _EVAS_OBJECT_EVENT_FREE = EFL_EVENT_DESCRIPTION("free");
12 static const Efl_Event_Description _EVAS_OBJECT_EVENT_DEL = EFL_EVENT_DESCRIPTION("del");
13 #define EVAS_OBJECT_EVENT_FREE (&(_EVAS_OBJECT_EVENT_FREE))
14 #define EVAS_OBJECT_EVENT_DEL (&(_EVAS_OBJECT_EVENT_DEL))
15 
16 /**
17  * Evas events descriptions for Eo.
18  */
19 #define DEFINE_EVAS_CALLBACKS(FUNC, LAST, ...)                          \
20   static const Efl_Event_Description *FUNC(unsigned int index)          \
21   {                                                                     \
22      static const Efl_Event_Description *internals[LAST] = { NULL };    \
23                                                                         \
24      if (index >= LAST) return NULL;                                    \
25      if (internals[0] == NULL)                                          \
26        {                                                                \
27           memcpy(internals,                                             \
28                  ((const Efl_Event_Description*[]) { __VA_ARGS__ }),    \
29                  sizeof ((const Efl_Event_Description *[]) { __VA_ARGS__ })); \
30        }                                                                \
31      return internals[index];                                           \
32   }
33 
34 DEFINE_EVAS_CALLBACKS(_legacy_evas_callback_table, EVAS_CALLBACK_LAST,
35                       EFL_EVENT_POINTER_IN,
36                       EFL_EVENT_POINTER_OUT,
37                       EFL_EVENT_POINTER_DOWN,
38                       EFL_EVENT_POINTER_UP,
39                       EFL_EVENT_POINTER_MOVE,
40                       EFL_EVENT_POINTER_WHEEL,
41                       EFL_EVENT_FINGER_DOWN,
42                       EFL_EVENT_FINGER_UP,
43                       EFL_EVENT_FINGER_MOVE,
44                       EVAS_OBJECT_EVENT_FREE,
45                       EFL_EVENT_KEY_DOWN,
46                       EFL_EVENT_KEY_UP,
47                       EFL_EVENT_FOCUS_IN,
48                       EFL_EVENT_FOCUS_OUT,
49                       EFL_GFX_ENTITY_EVENT_SHOW,
50                       EFL_GFX_ENTITY_EVENT_HIDE,
51                       EFL_GFX_ENTITY_EVENT_POSITION_CHANGED,
52                       EFL_GFX_ENTITY_EVENT_SIZE_CHANGED,
53                       EFL_GFX_ENTITY_EVENT_STACKING_CHANGED,
54                       EVAS_OBJECT_EVENT_DEL,
55                       EFL_EVENT_HOLD,
56                       EFL_GFX_ENTITY_EVENT_HINTS_CHANGED,
57                       EFL_GFX_IMAGE_EVENT_IMAGE_PRELOAD,
58                       EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_IN,
59                       EFL_CANVAS_SCENE_EVENT_SCENE_FOCUS_OUT,
60                       EVAS_CANVAS_EVENT_RENDER_FLUSH_PRE,
61                       EVAS_CANVAS_EVENT_RENDER_FLUSH_POST,
62                       EFL_CANVAS_SCENE_EVENT_OBJECT_FOCUS_IN,
63                       EFL_CANVAS_SCENE_EVENT_OBJECT_FOCUS_OUT,
64                       EFL_GFX_IMAGE_EVENT_IMAGE_UNLOAD,
65                       EFL_CANVAS_SCENE_EVENT_RENDER_PRE,
66                       EFL_CANVAS_SCENE_EVENT_RENDER_POST,
67                       EFL_GFX_IMAGE_EVENT_IMAGE_RESIZED,
68                       EFL_CANVAS_SCENE_EVENT_DEVICE_CHANGED,
69                       EFL_EVENT_POINTER_AXIS,
70                       EVAS_CANVAS_EVENT_VIEWPORT_RESIZE );
71 
72 static inline Evas_Callback_Type
_legacy_evas_callback_type(const Efl_Event_Description * desc)73 _legacy_evas_callback_type(const Efl_Event_Description *desc)
74 {
75    Evas_Callback_Type type;
76 
77    for (type = 0; type < EVAS_CALLBACK_LAST; type++)
78      {
79         if (_legacy_evas_callback_table(type) == desc)
80           return type;
81      }
82 
83    return EVAS_CALLBACK_LAST;
84 }
85 
86 typedef enum {
87    EFL_EVENT_TYPE_NULL,
88    EFL_EVENT_TYPE_OBJECT,
89    EFL_EVENT_TYPE_STRUCT,
90    EFL_EVENT_TYPE_POINTER,
91    EFL_EVENT_TYPE_KEY,
92    EFL_EVENT_TYPE_HOLD,
93    EFL_EVENT_TYPE_FOCUS
94 } Efl_Event_Info_Type;
95 
96 typedef struct
97 {
98    EINA_INLIST;
99    union {
100       Evas_Event_Cb         evas_cb;
101       Evas_Object_Event_Cb  object_cb;
102    } func;
103    void                    *data;
104    Evas_Callback_Type       type;
105    Efl_Event_Info_Type      efl_event_type;
106    Evas_Callback_Priority   priority;
107 } Evas_Event_Cb_Wrapper_Info;
108 
109 static int
_evas_event_efl_event_info_type(Evas_Callback_Type type)110 _evas_event_efl_event_info_type(Evas_Callback_Type type)
111 {
112    switch (type)
113      {
114       case EVAS_CALLBACK_MOUSE_IN:
115       case EVAS_CALLBACK_MOUSE_OUT:
116       case EVAS_CALLBACK_MOUSE_DOWN:
117       case EVAS_CALLBACK_MOUSE_UP:
118       case EVAS_CALLBACK_MOUSE_MOVE:
119       case EVAS_CALLBACK_MOUSE_WHEEL:
120       case EVAS_CALLBACK_MULTI_DOWN:
121       case EVAS_CALLBACK_MULTI_UP:
122       case EVAS_CALLBACK_MULTI_MOVE:
123       case EVAS_CALLBACK_AXIS_UPDATE:
124         return EFL_EVENT_TYPE_POINTER;
125 
126       case EVAS_CALLBACK_KEY_DOWN:
127       case EVAS_CALLBACK_KEY_UP:
128         return EFL_EVENT_TYPE_KEY;
129 
130       case EVAS_CALLBACK_HOLD:
131         return EFL_EVENT_TYPE_HOLD;
132 
133       case EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN:
134       case EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT: /* Efl.Canvas.Object */
135         return EFL_EVENT_TYPE_OBJECT;
136 
137       case EVAS_CALLBACK_RENDER_POST: /* Efl_Gfx_Event_Render_Post */
138         return EFL_EVENT_TYPE_STRUCT;
139 
140       case EVAS_CALLBACK_DEVICE_CHANGED: /* Efl.Input.Device */
141         return EFL_EVENT_TYPE_OBJECT;
142 
143       case EVAS_CALLBACK_FOCUS_IN:
144       case EVAS_CALLBACK_FOCUS_OUT:
145           return EFL_EVENT_TYPE_FOCUS;
146 
147       default:
148         return EFL_EVENT_TYPE_NULL;
149      }
150 }
151 
152 static void
_eo_evas_object_cb(void * data,const Efl_Event * event)153 _eo_evas_object_cb(void *data, const Efl_Event *event)
154 {
155    Evas_Event_Flags *event_flags = NULL, evflags = EVAS_EVENT_FLAG_NONE;
156    Efl_Input_Event *efl_event_info = event->info;
157    Evas_Event_Cb_Wrapper_Info *info = data;
158    void *event_info;
159    Evas *evas;
160 
161    if (!info->func.object_cb) return;
162    evas = evas_object_evas_get(event->object);
163 
164    event_info = event->info;
165    switch (info->efl_event_type)
166      {
167       case EFL_EVENT_TYPE_POINTER:
168         event_info = efl_input_pointer_legacy_info_fill(evas, efl_event_info, info->type, &event_flags);
169         break;
170 
171       case EFL_EVENT_TYPE_KEY:
172         event_info = efl_input_key_legacy_info_fill(efl_event_info, &event_flags);
173         break;
174 
175       case EFL_EVENT_TYPE_HOLD:
176         event_info = efl_input_hold_legacy_info_fill(efl_event_info, &event_flags);
177         break;
178 
179       case EFL_EVENT_TYPE_FOCUS:
180       case EFL_EVENT_TYPE_NULL:
181          info->func.object_cb(info->data, evas, event->object, NULL);
182          return;
183 
184       case EFL_EVENT_TYPE_STRUCT:
185       case EFL_EVENT_TYPE_OBJECT:
186         info->func.object_cb(info->data, evas, event->object, event_info);
187         return;
188 
189       default: return;
190      }
191 
192    if (!event_info) return;
193    if (event_flags) evflags = *event_flags;
194    info->func.object_cb(info->data, evas, event->object, event_info);
195    if (event_flags && (evflags != *event_flags))
196      efl_input_event_flags_set(efl_event_info,
197                                (Efl_Input_Flags)*event_flags);
198 }
199 
200 static void
_eo_evas_cb(void * data,const Efl_Event * event)201 _eo_evas_cb(void *data, const Efl_Event *event)
202 {
203    Evas_Event_Cb_Wrapper_Info *info = data;
204    Efl_Input_Event *efl_event_info = event->info;
205    Evas *evas = event->object;
206    void *event_info;
207 
208    if (!info->func.evas_cb) return;
209 
210    if (event->desc == EFL_CANVAS_SCENE_EVENT_OBJECT_FOCUS_IN ||
211        event->desc == EFL_CANVAS_SCENE_EVENT_OBJECT_FOCUS_OUT)
212      {
213         event_info = efl_input_focus_object_get(efl_event_info);
214         goto emit;
215      }
216 
217    event_info = event->info;
218    switch (info->efl_event_type)
219      {
220       case EFL_EVENT_TYPE_POINTER:
221         event_info = efl_input_pointer_legacy_info_fill(evas, efl_event_info, info->type, NULL);
222         break;
223 
224       case EFL_EVENT_TYPE_KEY:
225         event_info = efl_input_key_legacy_info_fill(efl_event_info, NULL);
226         break;
227 
228       case EFL_EVENT_TYPE_HOLD:
229         event_info = efl_input_hold_legacy_info_fill(efl_event_info, NULL);
230         break;
231 
232       case EFL_EVENT_TYPE_FOCUS:
233       case EFL_EVENT_TYPE_NULL:
234         event_info = NULL;
235         break;
236 
237       case EFL_EVENT_TYPE_STRUCT:
238       case EFL_EVENT_TYPE_OBJECT:
239         break;
240      }
241 
242 emit:
243    info->func.evas_cb(info->data, event->object, event_info);
244 }
245 
246 void
_evas_post_event_callback_call_real(Evas * eo_e,Evas_Public_Data * e,int min_event_id)247 _evas_post_event_callback_call_real(Evas *eo_e, Evas_Public_Data *e, int min_event_id)
248 {
249    Evas_Post_Callback *pc;
250    Eina_List *l, *l_next;
251    int skip = 0;
252 
253    if (e->delete_me) return;
254 
255    _evas_walk(e);
256    e->running_post_events++;
257    EINA_LIST_FOREACH_SAFE(e->post_events, l, l_next, pc)
258      {
259         if ((unsigned int) pc->event_id < (unsigned int) min_event_id) break;
260         e->post_events = eina_list_remove_list(e->post_events, l);
261         if ((!skip) && (!e->delete_me) && (!pc->delete_me))
262           {
263              if (!pc->func((void*)pc->data, eo_e)) skip = 1;
264           }
265         EVAS_MEMPOOL_FREE(_mp_pc, pc);
266      }
267    e->running_post_events--;
268    _evas_unwalk(e);
269 
270    if (!e->running_post_events && e->post_events
271        && (e->current_event == EVAS_CALLBACK_LAST))
272      {
273         WRN("Not all post-event callbacks have been processed!");
274         _evas_post_event_callback_call_real(eo_e, e, 0);
275      }
276 }
277 
278 void
_evas_post_event_callback_free(Evas * eo_e)279 _evas_post_event_callback_free(Evas *eo_e)
280 {
281    Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
282    Evas_Post_Callback *pc;
283 
284    if (EINA_LIKELY(!e->post_events)) return;
285 
286    EINA_LIST_FREE(e->post_events, pc)
287      {
288         EVAS_MEMPOOL_FREE(_mp_pc, pc);
289      }
290 }
291 
292 void
evas_object_event_callback_all_del(Evas_Object * eo_obj)293 evas_object_event_callback_all_del(Evas_Object *eo_obj)
294 {
295    Evas_Event_Cb_Wrapper_Info *info;
296    Eina_Inlist *itr;
297    Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
298 
299    if (!obj) return;
300    if (!obj->callbacks) return;
301    EINA_INLIST_FOREACH_SAFE(obj->callbacks, itr, info)
302      {
303         efl_event_callback_del(eo_obj, _legacy_evas_callback_table(info->type), _eo_evas_object_cb, info);
304 
305         obj->callbacks =
306            eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
307         free(info);
308      }
309 }
310 
311 void
evas_object_event_callback_cleanup(Evas_Object * eo_obj)312 evas_object_event_callback_cleanup(Evas_Object *eo_obj)
313 {
314    evas_object_event_callback_all_del(eo_obj);
315 }
316 
317 void
evas_event_callback_all_del(Evas * eo_e)318 evas_event_callback_all_del(Evas *eo_e)
319 {
320    Evas_Event_Cb_Wrapper_Info *info;
321    Eina_Inlist *itr;
322    Evas_Public_Data *e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);
323 
324    if (!e) return;
325    if (!e->callbacks) return;
326 
327    EINA_INLIST_FOREACH_SAFE(e->callbacks, itr, info)
328      {
329         efl_event_callback_del(eo_e, _legacy_evas_callback_table(info->type), _eo_evas_cb, info);
330 
331         e->callbacks =
332            eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
333         free(info);
334      }
335 }
336 
337 void
evas_event_callback_cleanup(Evas * eo_e)338 evas_event_callback_cleanup(Evas *eo_e)
339 {
340    evas_event_callback_all_del(eo_e);
341 }
342 
343 void
evas_event_callback_call(Evas * eo_e,Evas_Callback_Type type,void * event_info)344 evas_event_callback_call(Evas *eo_e, Evas_Callback_Type type, void *event_info)
345 {
346    efl_event_callback_legacy_call(eo_e, _legacy_evas_callback_table(type), event_info);
347 }
348 
349 static void
_evas_callback_legacy_smart_compatibility_do_it(Evas_Object * eo_obj,const Efl_Event_Description * efl_event_desc,void * event_info)350 _evas_callback_legacy_smart_compatibility_do_it(Evas_Object *eo_obj, const Efl_Event_Description *efl_event_desc, void *event_info)
351 {
352    /* this is inverted: the base call is the legacy compat and this is the new event */
353    if ((efl_event_desc == EFL_GFX_ENTITY_EVENT_SHOW) || (efl_event_desc == EFL_GFX_ENTITY_EVENT_HIDE))
354      efl_event_callback_call(eo_obj, EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED, event_info);
355    else if ((efl_event_desc == EFL_GFX_IMAGE_EVENT_IMAGE_PRELOAD) || (efl_event_desc == EFL_GFX_IMAGE_EVENT_IMAGE_UNLOAD))
356      efl_event_callback_call(eo_obj, EFL_GFX_IMAGE_EVENT_IMAGE_PRELOAD_STATE_CHANGED, event_info);
357 }
358 
359 
360 void
evas_object_event_callback_call(Evas_Object * eo_obj,Evas_Object_Protected_Data * obj,Evas_Callback_Type type,void * event_info,int event_id,const Efl_Event_Description * efl_event_desc)361 evas_object_event_callback_call(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
362                                 Evas_Callback_Type type, void *event_info, int event_id,
363                                 const Efl_Event_Description *efl_event_desc)
364 {
365    /* MEM OK */
366    const Evas_Button_Flags CLICK_MASK = EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK;
367    Evas_Button_Flags flags = EVAS_BUTTON_NONE;
368    Evas_Callback_Type prev_type;
369    Evas_Public_Data *e;
370 
371    if (!obj) return;
372    if ((obj->delete_me) || (!obj->layer)) return;
373    if ((obj->last_event_id == event_id) &&
374        (obj->last_event_type == type)) return;
375    if (obj->last_event_id > event_id)
376      {
377         if ((obj->last_event_type == EVAS_CALLBACK_MOUSE_OUT) &&
378             ((type >= EVAS_CALLBACK_MOUSE_DOWN) &&
379              (type <= EVAS_CALLBACK_MULTI_MOVE)))
380           {
381              return;
382           }
383      }
384    obj->last_event_id = event_id;
385    obj->last_event_type = type;
386    if (!(e = obj->layer->evas)) return;
387 
388    _evas_walk(e);
389 
390    // gesture hook
391    if ( type == EVAS_CALLBACK_MOUSE_MOVE ||
392         type == EVAS_CALLBACK_MULTI_MOVE ||
393         type == EVAS_CALLBACK_MOUSE_DOWN ||
394         type == EVAS_CALLBACK_MULTI_DOWN ||
395         type == EVAS_CALLBACK_MOUSE_UP ||
396         type == EVAS_CALLBACK_MULTI_UP)
397      _efl_canvas_gesture_manager_filter_event(e->gmd, eo_obj, event_info);
398 
399    if (obj->is_smart)
400      _evas_object_smart_callback_call_internal(eo_obj, efl_event_desc);
401 
402    if (!_evas_object_callback_has_by_type(obj, type))
403      goto nothing_here;
404 
405    if ((type == EVAS_CALLBACK_MOUSE_DOWN) || (type == EVAS_CALLBACK_MOUSE_UP))
406      {
407         flags = (Evas_Button_Flags)efl_input_pointer_button_flags_get(event_info);
408         if (flags & CLICK_MASK)
409           {
410              if (obj->last_mouse_down_counter < (e->last_mouse_down_counter - 1))
411                efl_input_pointer_button_flags_set(event_info, flags & ~CLICK_MASK);
412           }
413         obj->last_mouse_down_counter = e->last_mouse_down_counter;
414      }
415 
416    if (!efl_event_desc)
417      {
418         /* This can happen for DEL and FREE which are defined only in here */
419         efl_event_desc = _legacy_evas_callback_table(type);
420      }
421 
422    prev_type = e->current_event;
423    e->current_event = type;
424 
425    efl_event_callback_legacy_call(eo_obj, efl_event_desc, event_info);
426    _evas_callback_legacy_smart_compatibility_do_it(eo_obj, efl_event_desc, event_info);
427 
428    /* multi events with finger 0 - only for eo callbacks */
429    if (type == EVAS_CALLBACK_MOUSE_DOWN)
430      {
431         if (_evas_object_callback_has_by_type(obj, EVAS_CALLBACK_MULTI_DOWN))
432           {
433              e->current_event = EVAS_CALLBACK_MULTI_DOWN;
434              efl_event_callback_call(eo_obj, EFL_EVENT_FINGER_DOWN, event_info);
435           }
436         efl_input_pointer_button_flags_set(event_info, (Efl_Pointer_Flags) flags);
437      }
438    else if (type == EVAS_CALLBACK_MOUSE_UP)
439      {
440         if (_evas_object_callback_has_by_type(obj, EVAS_CALLBACK_MULTI_UP))
441           {
442              e->current_event = EVAS_CALLBACK_MULTI_UP;
443              efl_event_callback_call(eo_obj, EFL_EVENT_FINGER_UP, event_info);
444           }
445         efl_input_pointer_button_flags_set(event_info, (Efl_Pointer_Flags)flags);
446      }
447    else if (type == EVAS_CALLBACK_MOUSE_MOVE)
448      {
449         if (_evas_object_callback_has_by_type(obj, EVAS_CALLBACK_MULTI_MOVE))
450           {
451              e->current_event = EVAS_CALLBACK_MULTI_MOVE;
452              efl_event_callback_call(eo_obj, EFL_EVENT_FINGER_MOVE, event_info);
453           }
454      }
455 
456    e->current_event = prev_type;
457 
458 nothing_here:
459    if (!obj->no_propagate)
460      {
461         if ((obj->smart.parent || ((obj->events) && obj->events->parent)) &&
462             (type != EVAS_CALLBACK_FREE) &&
463             (type <= EVAS_CALLBACK_KEY_UP))
464           {
465              Evas_Object_Protected_Data *parent_obj;
466              Eo *parent;
467 
468              parent = ((obj->events) && obj->events->parent) ?
469                obj->events->parent: obj->smart.parent;
470              parent_obj = efl_data_scope_get(parent, EFL_CANVAS_OBJECT_CLASS);
471              evas_object_event_callback_call(parent, parent_obj, type, event_info, event_id, efl_event_desc);
472           }
473      }
474    _evas_unwalk(e);
475 }
476 
477 EAPI void
evas_object_event_callback_add(Evas_Object * eo_obj,Evas_Callback_Type type,Evas_Object_Event_Cb func,const void * data)478 evas_object_event_callback_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
479 {
480    evas_object_event_callback_priority_add(eo_obj, type,
481                                            EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
482 }
483 
484 EAPI void
evas_object_event_callback_priority_add(Evas_Object * eo_obj,Evas_Callback_Type type,Evas_Callback_Priority priority,Evas_Object_Event_Cb func,const void * data)485 evas_object_event_callback_priority_add(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Object_Event_Cb func, const void *data)
486 {
487    Evas_Object_Protected_Data *obj;
488    Evas_Event_Cb_Wrapper_Info *cb_info;
489    const Efl_Event_Description *desc;
490 
491    EINA_SAFETY_ON_NULL_RETURN(eo_obj);
492    EINA_SAFETY_ON_NULL_RETURN(func);
493 
494    EINA_SAFETY_ON_TRUE_RETURN(efl_invalidated_get(eo_obj));
495 
496    obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
497    EINA_SAFETY_ON_NULL_RETURN(obj);
498 
499    cb_info = calloc(1, sizeof(*cb_info));
500    cb_info->func.object_cb = func;
501    cb_info->data = (void *)data;
502    cb_info->type = type;
503    cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
504 
505    desc = _legacy_evas_callback_table(type);
506    efl_event_callback_priority_add(eo_obj, desc, priority, _eo_evas_object_cb, cb_info);
507 
508    obj->callbacks =
509       eina_inlist_append(obj->callbacks, EINA_INLIST_GET(cb_info));
510 }
511 
512 EAPI void *
evas_object_event_callback_del(Evas_Object * eo_obj,Evas_Callback_Type type,Evas_Object_Event_Cb func)513 evas_object_event_callback_del(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func)
514 {
515    Evas_Object_Protected_Data *obj;
516    Evas_Event_Cb_Wrapper_Info *info;
517 
518    if (!eo_obj) return NULL;
519    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
520 
521    obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
522    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
523 
524    if (!obj->callbacks) return NULL;
525 
526    EINA_INLIST_REVERSE_FOREACH(obj->callbacks, info)
527      {
528         if ((info->func.object_cb == func) && (info->type == type))
529           {
530              void *tmp = info->data;
531              efl_event_callback_del(eo_obj, _legacy_evas_callback_table(type), _eo_evas_object_cb, info);
532 
533              obj->callbacks =
534                 eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
535              free(info);
536              return tmp;
537           }
538      }
539    return NULL;
540 }
541 
542 EAPI void *
evas_object_event_callback_del_full(Evas_Object * eo_obj,Evas_Callback_Type type,Evas_Object_Event_Cb func,const void * data)543 evas_object_event_callback_del_full(Evas_Object *eo_obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
544 {
545    Evas_Object_Protected_Data *obj;
546    Evas_Event_Cb_Wrapper_Info *info;
547 
548    if (!eo_obj) return NULL;
549    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
550 
551    obj = efl_data_scope_safe_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
552    EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
553 
554    if (!obj->callbacks) return NULL;
555 
556    EINA_INLIST_FOREACH(obj->callbacks, info)
557      {
558         if ((info->func.object_cb == func) && (info->type == type) && info->data == data)
559           {
560              void *tmp = info->data;
561              efl_event_callback_del(eo_obj, _legacy_evas_callback_table(type), _eo_evas_object_cb, info);
562 
563              obj->callbacks =
564                 eina_inlist_remove(obj->callbacks, EINA_INLIST_GET(info));
565              free(info);
566              return tmp;
567           }
568      }
569    return NULL;
570 }
571 
572 EAPI void
evas_event_callback_add(Evas * eo_e,Evas_Callback_Type type,Evas_Event_Cb func,const void * data)573 evas_event_callback_add(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
574 {
575    evas_event_callback_priority_add(eo_e, type, EVAS_CALLBACK_PRIORITY_DEFAULT,
576                                     func, data);
577 }
578 
579 void
_deferred_callbacks_process(Evas * eo_e,Evas_Public_Data * e)580 _deferred_callbacks_process(Evas *eo_e, Evas_Public_Data *e)
581 {
582    Evas_Event_Cb_Wrapper_Info *cb_info;
583    const Efl_Event_Description *desc;
584 
585    while (e->deferred_callbacks)
586      {
587         cb_info = EINA_INLIST_CONTAINER_GET(e->deferred_callbacks,
588                                             Evas_Event_Cb_Wrapper_Info);
589         e->deferred_callbacks = eina_inlist_remove(e->deferred_callbacks,
590                                                    e->deferred_callbacks);
591         desc = _legacy_evas_callback_table(cb_info->type);
592         efl_event_callback_priority_add(eo_e, desc, cb_info->priority, _eo_evas_cb, cb_info);
593         e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
594      }
595 }
596 
597 EAPI void
evas_event_callback_priority_add(Evas * eo_e,Evas_Callback_Type type,Evas_Callback_Priority priority,Evas_Event_Cb func,const void * data)598 evas_event_callback_priority_add(Evas *eo_e, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
599 {
600    Evas_Public_Data *e;
601    Evas_Event_Cb_Wrapper_Info *cb_info;
602    const Efl_Event_Description *desc;
603 
604    EINA_SAFETY_ON_NULL_RETURN(eo_e);
605    EINA_SAFETY_ON_NULL_RETURN(func);
606 
607    EINA_SAFETY_ON_TRUE_RETURN(efl_invalidated_get(eo_e));
608 
609    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
610    EINA_SAFETY_ON_NULL_RETURN(e);
611 
612    cb_info = calloc(1, sizeof(*cb_info));
613    cb_info->func.evas_cb = func;
614    cb_info->data = (void *)data;
615    cb_info->priority = priority;
616    cb_info->type = type;
617    cb_info->efl_event_type = _evas_event_efl_event_info_type(type);
618 
619    if ((e->rendering || e->inside_post_render) && type == EVAS_CALLBACK_RENDER_POST)
620      {
621         e->deferred_callbacks = eina_inlist_append(e->deferred_callbacks,
622                                                    EINA_INLIST_GET(cb_info));
623      }
624    else
625      {
626         desc = _legacy_evas_callback_table(type);
627         efl_event_callback_priority_add(eo_e, desc, priority, _eo_evas_cb, cb_info);
628 
629         e->callbacks = eina_inlist_append(e->callbacks, EINA_INLIST_GET(cb_info));
630      }
631 }
632 
633 EAPI void *
evas_event_callback_del(Evas * eo_e,Evas_Callback_Type type,Evas_Event_Cb func)634 evas_event_callback_del(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func)
635 {
636    Evas_Public_Data *e;
637    Evas_Event_Cb_Wrapper_Info *info;
638 
639    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_e, NULL);
640    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
641 
642    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
643    EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
644 
645    if (!e->callbacks) return NULL;
646 
647    if (type == EVAS_CALLBACK_RENDER_POST)
648      EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
649        {
650           if (info->func.evas_cb == func)
651             {
652                void *tmp = info->data;
653 
654                e->deferred_callbacks =
655                   eina_inlist_remove(e->deferred_callbacks, EINA_INLIST_GET(info));
656                free(info);
657                return tmp;
658             }
659        }
660 
661    EINA_INLIST_REVERSE_FOREACH(e->callbacks, info)
662      {
663         if ((info->func.evas_cb == func) && (info->type == type))
664           {
665              void *tmp = info->data;
666              efl_event_callback_del(eo_e, _legacy_evas_callback_table(type), _eo_evas_cb, info);
667 
668              e->callbacks =
669                 eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
670              free(info);
671              return tmp;
672           }
673      }
674    return NULL;
675 }
676 
677 EAPI void *
evas_event_callback_del_full(Evas * eo_e,Evas_Callback_Type type,Evas_Event_Cb func,const void * data)678 evas_event_callback_del_full(Evas *eo_e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
679 {
680    Evas_Public_Data *e;
681    Evas_Event_Cb_Wrapper_Info *info;
682 
683    EINA_SAFETY_ON_NULL_RETURN_VAL(eo_e, NULL);
684    EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
685 
686    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
687    EINA_SAFETY_ON_NULL_RETURN_VAL(e, NULL);
688 
689    if (!e->callbacks) return NULL;
690 
691    if (type == EVAS_CALLBACK_RENDER_POST)
692      EINA_INLIST_REVERSE_FOREACH(e->deferred_callbacks, info)
693        {
694           if ((info->func.evas_cb == func) && (info->data == data))
695             {
696                void *tmp = info->data;
697 
698                e->deferred_callbacks =
699                   eina_inlist_remove(e->deferred_callbacks, EINA_INLIST_GET(info));
700                free(info);
701                return tmp;
702             }
703        }
704 
705    EINA_INLIST_FOREACH(e->callbacks, info)
706      {
707         if ((info->func.evas_cb == func) && (info->type == type) && (info->data == data))
708           {
709              void *tmp = info->data;
710              efl_event_callback_del(eo_e, _legacy_evas_callback_table(type), _eo_evas_cb, info);
711 
712              e->callbacks =
713                 eina_inlist_remove(e->callbacks, EINA_INLIST_GET(info));
714              free(info);
715              return tmp;
716           }
717      }
718    return NULL;
719 }
720 
721 EAPI void
evas_post_event_callback_push(Evas * eo_e,Evas_Object_Event_Post_Cb func,const void * data)722 evas_post_event_callback_push(Evas *eo_e, Evas_Object_Event_Post_Cb func, const void *data)
723 {
724    Evas_Public_Data *e;
725    Evas_Post_Callback *pc;
726 
727    EINA_SAFETY_ON_NULL_RETURN(eo_e);
728    EINA_SAFETY_ON_TRUE_RETURN(efl_invalidated_get(eo_e));
729 
730    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
731    EINA_SAFETY_ON_NULL_RETURN(e);
732    if (e->delete_me) return;
733    if (e->current_event == EVAS_CALLBACK_LAST)
734      {
735         ERR("%s() can only be called from an input event callback!", __func__);
736         return;
737      }
738    EVAS_MEMPOOL_INIT(_mp_pc, "evas_post_callback", Evas_Post_Callback, 64, );
739    pc = EVAS_MEMPOOL_ALLOC(_mp_pc, Evas_Post_Callback);
740    if (!pc) return;
741    EVAS_MEMPOOL_PREP(_mp_pc, pc, Evas_Post_Callback);
742 
743    pc->func = func;
744    pc->data = data;
745    pc->type = e->current_event;
746    pc->event_id = _evas_event_counter;
747    e->post_events = eina_list_prepend(e->post_events, pc);
748 }
749 
750 EAPI void
evas_post_event_callback_remove(Evas * eo_e,Evas_Object_Event_Post_Cb func)751 evas_post_event_callback_remove(Evas *eo_e, Evas_Object_Event_Post_Cb func)
752 {
753    Evas_Public_Data *e;
754    Evas_Post_Callback *pc;
755    Eina_List *l;
756 
757    EINA_SAFETY_ON_NULL_RETURN(eo_e);
758 
759    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
760    EINA_SAFETY_ON_NULL_RETURN(e);
761    EINA_LIST_FOREACH(e->post_events, l, pc)
762      {
763         if (pc->func == func)
764           {
765              pc->delete_me = 1;
766              return;
767           }
768      }
769 }
770 
771 EAPI void
evas_post_event_callback_remove_full(Evas * eo_e,Evas_Object_Event_Post_Cb func,const void * data)772 evas_post_event_callback_remove_full(Evas *eo_e, Evas_Object_Event_Post_Cb func, const void *data)
773 {
774    Evas_Public_Data *e;
775    Evas_Post_Callback *pc;
776    Eina_List *l;
777 
778    EINA_SAFETY_ON_NULL_RETURN(eo_e);
779 
780    e = efl_data_scope_safe_get(eo_e, EVAS_CANVAS_CLASS);
781    EINA_SAFETY_ON_NULL_RETURN(e);
782    EINA_LIST_FOREACH(e->post_events, l, pc)
783      {
784         if ((pc->func == func) && (pc->data == data))
785           {
786              pc->delete_me = 1;
787              return;
788           }
789      }
790 }
791 
792 static void
_animator_repeater(void * data,const Efl_Event * event)793 _animator_repeater(void *data, const Efl_Event *event)
794 {
795    Evas_Object_Protected_Data *obj = data;
796 
797    efl_event_callback_legacy_call(obj->object, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, event->info);
798    DBG("Emitting animator tick on %p.", obj->object);
799 }
800 
801 void
evas_object_callbacks_finalized(Eo * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)802 evas_object_callbacks_finalized(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
803 {
804    EINA_SAFETY_ON_NULL_RETURN(obj);
805 
806    if (obj->animator_ref > 0)
807      {
808        if (obj->layer && obj->layer->evas)
809          {
810             efl_event_callback_add(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
811             DBG("Registering an animator tick on canvas %p for object %p.",
812                 obj->layer->evas->evas, obj->object);
813          }
814      }
815 }
816 
817 void
evas_object_callbacks_event_catcher_add(Eo * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,const Efl_Callback_Array_Item * array)818 evas_object_callbacks_event_catcher_add(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array)
819 {
820    Evas_Callback_Type type = EVAS_CALLBACK_LAST;
821    int i;
822 
823    for (i = 0; array[i].desc != NULL; i++)
824      {
825         if (obj->layer && obj->layer->evas && obj->layer->evas->gesture_manager)
826           _efl_canvas_gesture_manager_callback_add_hook(obj->layer->evas->gmd, obj->object, array[i].desc);
827 
828         if (array[i].desc == EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK)
829           {
830              if (obj->animator_ref++ > 0) break;
831 
832              if (efl_finalized_get(eo_obj))
833                {
834                   efl_event_callback_add(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
835                   DBG("Registering an animator tick on canvas %p for object %p.",
836                       obj->layer->evas->evas, obj->object);
837                }
838           }
839         else if ((type = _legacy_evas_callback_type(array[i].desc)) != EVAS_CALLBACK_LAST)
840           {
841              obj->callback_mask |= (((uint64_t)1) << type);
842           }
843         else if (array[i].desc == EFL_GFX_ENTITY_EVENT_VISIBILITY_CHANGED)
844           {
845              obj->callback_mask |= (((uint64_t)1) << EVAS_CALLBACK_SHOW);
846              obj->callback_mask |= (((uint64_t)1) << EVAS_CALLBACK_HIDE);
847           }
848      }
849 }
850 
851 void
evas_object_callbacks_event_catcher_del(Eo * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj,const Efl_Callback_Array_Item * array)852 evas_object_callbacks_event_catcher_del(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, const Efl_Callback_Array_Item *array)
853 {
854    int i;
855 
856    if (!obj->layer ||
857        !obj->layer->evas)
858      return ;
859 
860    for (i = 0; array[i].desc != NULL; i++)
861      {
862         if (obj->layer->evas->gesture_manager)
863           _efl_canvas_gesture_manager_callback_del_hook(obj->layer->evas->gmd, obj->object, array[i].desc);
864 
865         if (array[i].desc == EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK)
866           {
867              if ((--obj->animator_ref) > 0) break;
868 
869              efl_event_callback_del(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
870              DBG("Unregistering an animator tick on canvas %p for object %p.",
871                  obj->layer->evas->evas, obj->object);
872           }
873      }
874 }
875 
876 void
evas_object_callbacks_shutdown(Eo * eo_obj EINA_UNUSED,Evas_Object_Protected_Data * obj)877 evas_object_callbacks_shutdown(Eo *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj)
878 {
879    if (obj->animator_ref > 0)
880      efl_event_callback_del(obj->layer->evas->evas, EFL_CANVAS_OBJECT_EVENT_ANIMATOR_TICK, _animator_repeater, obj);
881    obj->animator_ref = 0;
882 }
883