1 #define EFL_CANVAS_GESTURE_PROTECTED
2 #define EFL_CANVAS_GESTURE_CUSTOM_PROTECTED
3 #include "efl_canvas_gesture_private.h"
4 
5 #define MY_CLASS EFL_CANVAS_GESTURE_MANAGER_CLASS
6 
7 typedef struct _Object_Gesture
8 {
9    Eo                            *object;
10    const Efl_Event_Description   *type;
11    Efl_Canvas_Gesture            *gesture;
12    Efl_Canvas_Gesture_Recognizer *recognizer;
13 } Object_Gesture;
14 
15 typedef struct _Efl_Canvas_Gesture_Manager_Data
16 {
17    //Keeps track of all the gesture request for a particular target
18    Eina_Hash *m_gesture_contex;     // (*target, Eina_Hash(type, int))
19    //Keeps all the event directed to this particular object from touch_begin till touch_end
20    Eina_Hash *m_object_events;     // (*recognizer, *efl_gesture_touch)
21    //Keeps all the recognizer registered to gesture manager
22    Eina_Hash *m_recognizers;    // (*gesture_type, *recognizer)
23    Eina_List *custom_recognizers;
24    //Keeps track of all current object gestures.
25    Eina_List *m_object_gestures;    //(List of *object_gesture)
26    //Lazy deletion of gestures
27    Eina_Array *m_gestures_to_delete;
28    //Kepps config values for gesture recognize
29    Eina_Bool processing : 1;
30 } Efl_Canvas_Gesture_Manager_Data;
31 
32 static void _cleanup_cached_gestures(Efl_Canvas_Gesture_Manager_Data *pd,
33                                       const Eo *target, const Efl_Event_Description *type, const Efl_Canvas_Gesture_Recognizer *recognizer);
34 static Efl_Canvas_Gesture *
35             _get_state(Efl_Canvas_Gesture_Manager_Data *pd, Eo *target,
36            Efl_Canvas_Gesture_Recognizer *recognizer, const Efl_Event_Description *type);
37 
38 static const Efl_Event_Description *
_gesture_recognizer_event_type_get(const Efl_Canvas_Gesture_Recognizer * recognizer)39 _gesture_recognizer_event_type_get(const Efl_Canvas_Gesture_Recognizer *recognizer)
40 {
41    const Efl_Class *type = efl_gesture_recognizer_type_get(recognizer);
42 
43    if (type == EFL_CANVAS_GESTURE_TAP_CLASS)
44      return EFL_EVENT_GESTURE_TAP;
45    if (type == EFL_CANVAS_GESTURE_DOUBLE_TAP_CLASS)
46      return EFL_EVENT_GESTURE_DOUBLE_TAP;
47    if (type == EFL_CANVAS_GESTURE_TRIPLE_TAP_CLASS)
48      return EFL_EVENT_GESTURE_TRIPLE_TAP;
49    if (type == EFL_CANVAS_GESTURE_LONG_PRESS_CLASS)
50      return EFL_EVENT_GESTURE_LONG_PRESS;
51    if (type == EFL_CANVAS_GESTURE_MOMENTUM_CLASS)
52      return EFL_EVENT_GESTURE_MOMENTUM;
53    if (type == EFL_CANVAS_GESTURE_FLICK_CLASS)
54      return EFL_EVENT_GESTURE_FLICK;
55    if (type == EFL_CANVAS_GESTURE_ROTATE_CLASS)
56      return EFL_EVENT_GESTURE_ROTATE;
57    if (type == EFL_CANVAS_GESTURE_ZOOM_CLASS)
58      return EFL_EVENT_GESTURE_ZOOM;
59    return EFL_EVENT_GESTURE_CUSTOM;
60 }
61 
62 static void
_cleanup_object(Eina_Array * arr)63 _cleanup_object(Eina_Array *arr)
64 {
65    Eo *obj;
66 
67    if (!eina_array_count(arr)) return;
68 
69    while ((obj = eina_array_pop(arr)))
70      efl_del(obj);
71 }
72 
73 static void
_hash_unref_cb(Eo * obj)74 _hash_unref_cb(Eo *obj)
75 {
76    efl_unref(obj);
77 }
78 
79 /* updates the data for in-tree recognizers without needing to watch events */
80 static void
_update_finger_sizes(Efl_Canvas_Gesture_Manager_Data * pd,int finger_size)81 _update_finger_sizes(Efl_Canvas_Gesture_Manager_Data *pd, int finger_size)
82 {
83    Efl_Canvas_Gesture_Recognizer *r;
84    Efl_Canvas_Gesture_Recognizer_Tap_Data *td;
85    Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *dtd;
86    Efl_Canvas_Gesture_Recognizer_Triple_Tap_Data *ttd;
87    Efl_Canvas_Gesture_Recognizer_Long_Press_Data *ltd;
88    Efl_Canvas_Gesture_Recognizer_Flick_Data *fd;
89    Efl_Canvas_Gesture_Recognizer_Rotate_Data *rd;
90    Efl_Canvas_Gesture_Recognizer_Zoom_Data *zd;
91    const Efl_Event_Description *type;
92 
93    type = EFL_EVENT_GESTURE_TAP;
94    r = eina_hash_find(pd->m_recognizers, &type);
95    td = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS);
96    td->finger_size = finger_size;
97 
98    type = EFL_EVENT_GESTURE_DOUBLE_TAP;
99    r = eina_hash_find(pd->m_recognizers, &type);
100    dtd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS);
101    dtd->finger_size = finger_size;
102 
103    type = EFL_EVENT_GESTURE_TRIPLE_TAP;
104    r = eina_hash_find(pd->m_recognizers, &type);
105    ttd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS);
106    ttd->finger_size = finger_size;
107 
108    type = EFL_EVENT_GESTURE_LONG_PRESS;
109    r = eina_hash_find(pd->m_recognizers, &type);
110    ltd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_LONG_PRESS_CLASS);
111    ltd->finger_size = finger_size;
112 
113    type = EFL_EVENT_GESTURE_FLICK;
114    r = eina_hash_find(pd->m_recognizers, &type);
115    fd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS);
116    fd->finger_size = finger_size;
117 
118    type = EFL_EVENT_GESTURE_ROTATE;
119    r = eina_hash_find(pd->m_recognizers, &type);
120    rd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_ROTATE_CLASS);
121    rd->finger_size = finger_size;
122 
123    type = EFL_EVENT_GESTURE_ZOOM;
124    r = eina_hash_find(pd->m_recognizers, &type);
125    zd = efl_data_scope_get(r, EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS);
126    zd->finger_size = finger_size;
127 }
128 
129 static void
_gesture_manager_config_changed(void * data,const Efl_Event * ev)130 _gesture_manager_config_changed(void *data, const Efl_Event *ev)
131 {
132    Efl_Canvas_Gesture_Manager_Data *pd = data;
133 
134    if ((!ev->info) || eina_streq(ev->info, "glayer_tap_finger_size"))
135      _update_finger_sizes(pd, efl_config_int_get(ev->object, "glayer_tap_finger_size"));
136 }
137 
138 EOLIAN static Efl_Object *
_efl_canvas_gesture_manager_efl_object_constructor(Eo * obj,Efl_Canvas_Gesture_Manager_Data * pd)139 _efl_canvas_gesture_manager_efl_object_constructor(Eo *obj, Efl_Canvas_Gesture_Manager_Data *pd)
140 {
141    Eo *config;
142    int finger_size = 0;
143    obj = efl_constructor(efl_super(obj, MY_CLASS));
144 
145    pd->m_recognizers = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
146    pd->m_gesture_contex = eina_hash_pointer_new(EINA_FREE_CB(eina_hash_free));
147    pd->m_object_events = eina_hash_pointer_new(EINA_FREE_CB(_hash_unref_cb));
148    pd->m_object_gestures = NULL;
149    pd->m_gestures_to_delete = eina_array_new(1);;
150 
151    /* this needs to always be present */
152    config = efl_provider_find(efl_main_loop_get(), EFL_CONFIG_INTERFACE);
153    efl_event_callback_add(config, EFL_CONFIG_EVENT_CONFIG_CHANGED, _gesture_manager_config_changed, pd);
154 
155    //Register all types of recognizers at very first time.
156    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_TAP_CLASS, obj));
157    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_LONG_PRESS_CLASS, obj));
158    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS, obj));
159    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_TRIPLE_TAP_CLASS, obj));
160    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_MOMENTUM_CLASS, obj));
161    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_FLICK_CLASS, obj));
162    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_ROTATE_CLASS, obj));
163    efl_gesture_manager_recognizer_register(obj, efl_add(EFL_CANVAS_GESTURE_RECOGNIZER_ZOOM_CLASS, obj));
164    /* realistically this will never fail, but the whole gesture layer breaks if this is 0 */
165    if (!getenv("EFL_RUN_IN_TREE"))
166      finger_size = efl_config_int_get(config, "glayer_tap_finger_size");
167    if (finger_size < 1) finger_size = 10;
168    _update_finger_sizes(pd, finger_size);
169 
170    return obj;
171 }
172 
173 EOLIAN static void
_efl_canvas_gesture_manager_efl_object_destructor(Eo * obj,Efl_Canvas_Gesture_Manager_Data * pd)174 _efl_canvas_gesture_manager_efl_object_destructor(Eo *obj, Efl_Canvas_Gesture_Manager_Data *pd)
175 {
176    Efl_Canvas_Gesture_Recognizer *recognizer;
177    void *ptr;
178    Eo *config = efl_provider_find(efl_main_loop_get(), EFL_CONFIG_INTERFACE);
179    if (config)
180      efl_event_callback_del(config, EFL_CONFIG_EVENT_CONFIG_CHANGED, _gesture_manager_config_changed, pd);
181 
182    eina_hash_free(pd->m_recognizers);
183    EINA_LIST_FREE(pd->custom_recognizers, recognizer)
184      efl_unref(recognizer);
185    eina_hash_free(pd->m_gesture_contex);
186    eina_hash_free(pd->m_object_events);
187    _cleanup_object(pd->m_gestures_to_delete);
188    eina_array_free(pd->m_gestures_to_delete);
189    EINA_LIST_FREE(pd->m_object_gestures, ptr)
190      free(ptr);
191    efl_destructor(efl_super(obj, MY_CLASS));
192 }
193 
194 void
_efl_canvas_gesture_manager_callback_add_hook(void * data,Eo * target,const Efl_Event_Description * type)195 _efl_canvas_gesture_manager_callback_add_hook(void *data, Eo *target, const Efl_Event_Description *type)
196 {
197    Efl_Canvas_Gesture_Manager_Data *pd = data;
198    //If there is a recognizer registered for that event then add it to the gesture context
199    Efl_Canvas_Gesture_Recognizer *recognizer;
200 
201    if (type == EFL_EVENT_GESTURE_CUSTOM)
202      recognizer = eina_list_data_get(pd->custom_recognizers);
203    else
204      recognizer = eina_hash_find(pd->m_recognizers, &type);
205    if (recognizer)
206      {
207         //Add it to the gesture context.
208         Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
209         intptr_t count = 0;
210         /* already present */
211         if (thisisreallystupid)
212           count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
213         else
214           {
215              thisisreallystupid = eina_hash_pointer_new(NULL);
216              eina_hash_set(pd->m_gesture_contex, &target, thisisreallystupid);
217           }
218         count++;
219         eina_hash_set(thisisreallystupid, &type, (intptr_t*)count);
220      }
221 }
222 
223 void
_efl_canvas_gesture_manager_callback_del_hook(void * data,Eo * target,const Efl_Event_Description * type)224 _efl_canvas_gesture_manager_callback_del_hook(void *data, Eo *target, const Efl_Event_Description *type)
225 {
226    Efl_Canvas_Gesture_Manager_Data *pd = data;
227    //If there is a recognizer registered for that event then add it to the gesture context
228    Efl_Canvas_Gesture_Recognizer *recognizer;
229 
230    if (type == EFL_EVENT_GESTURE_CUSTOM)
231      recognizer = eina_list_data_get(pd->custom_recognizers);
232    else
233      recognizer = eina_hash_find(pd->m_recognizers, &type);
234    if (recognizer)
235      {
236         Eina_Hash *thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
237         intptr_t count;
238 
239         if (!thisisreallystupid) return;
240         count = (intptr_t)eina_hash_find(thisisreallystupid, &type);
241         if (!count) return;
242         count--;
243         eina_hash_set(thisisreallystupid, &type, (intptr_t*)count);
244         if (count) return;
245         eina_hash_del_by_key(thisisreallystupid, &type);
246         if (eina_hash_population(thisisreallystupid)) return;
247         eina_hash_del_by_key(pd->m_gesture_contex, &target);
248         _cleanup_cached_gestures(pd, target, type, NULL);
249      }
250 }
251 
252 static void
_recognizer_cleanup_internal(Efl_Canvas_Gesture_Manager_Data * pd,const Efl_Canvas_Gesture_Recognizer * recognizer,const Eo * target,const Efl_Event_Description * type)253 _recognizer_cleanup_internal(Efl_Canvas_Gesture_Manager_Data *pd, const Efl_Canvas_Gesture_Recognizer *recognizer, const Eo *target, const Efl_Event_Description *type)
254 {
255    _cleanup_cached_gestures(pd, target, type, recognizer);
256    eina_hash_del(pd->m_object_events, &recognizer, NULL);
257    //FIXME: delete it by object not list.
258    _cleanup_object(pd->m_gestures_to_delete);
259 }
260 
261 static void
_gesture_recognizer_process_internal(Efl_Canvas_Gesture_Manager_Data * pd,Efl_Canvas_Gesture_Recognizer * recognizer,Eo * target,const Efl_Event_Description * gesture_type,void * event)262 _gesture_recognizer_process_internal(Efl_Canvas_Gesture_Manager_Data *pd, Efl_Canvas_Gesture_Recognizer *recognizer,
263                                      Eo *target, const Efl_Event_Description *gesture_type, void *event)
264 {
265    Efl_Canvas_Gesture_Recognizer_Result recog_result;
266    Efl_Canvas_Gesture_Recognizer_Result recog_state = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
267    Efl_Canvas_Gesture_Touch *touch_event;
268    Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(recognizer, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
269    //If the gesture canceled or already finished by recognizer.
270    Efl_Canvas_Gesture *gesture = _get_state(pd, target, recognizer, gesture_type);
271    if (!gesture) return;
272 
273    //Check there is already created event exist or not.
274    touch_event = eina_hash_find(pd->m_object_events, &recognizer);
275 
276    if (!touch_event)
277      {
278         touch_event = efl_add_ref(EFL_CANVAS_GESTURE_TOUCH_CLASS, NULL);
279         eina_hash_add(pd->m_object_events, &recognizer, touch_event);
280      }
281 
282    efl_gesture_touch_point_record(touch_event, event);
283 
284    //This is for handling the case that mouse event pairs dont match.
285    //Such as the case of canceling gesture recognition after a mouse down.
286    if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_STATE_UNKNOWN)
287      return;
288    if ((!rd->continues) && ((efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_CANCELED) ||
289        (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_FINISHED)))
290      goto post_event;
291 
292    /* this is the "default" value for the event, recognizers may modify it if necessary */
293    efl_gesture_touch_count_set(gesture, efl_gesture_touch_points_count_get(touch_event));
294 
295    //Gesture detecting.
296    recog_result = efl_gesture_recognizer_recognize(recognizer, gesture, target, touch_event);
297    recog_state = recog_result & EFL_GESTURE_RECOGNIZER_RESULT_RESULT_MASK;
298 
299    if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER)
300      {
301         if (efl_gesture_state_get(gesture) == EFL_GESTURE_STATE_NONE)
302           efl_gesture_state_set(gesture, EFL_GESTURE_STATE_STARTED);
303         else
304           efl_gesture_state_set(gesture, EFL_GESTURE_STATE_UPDATED);
305      }
306    else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH)
307      {
308         efl_gesture_state_set(gesture, EFL_GESTURE_STATE_FINISHED);
309      }
310    else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_MAYBE)
311      {
312         return;
313      }
314    else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)
315      {
316         if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE)
317           efl_gesture_state_set(gesture, EFL_GESTURE_STATE_CANCELED);
318         else
319           {
320              if (rd->continues)
321                return;
322              goto post_event;
323           }
324      }
325    else if (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_IGNORE)
326      {
327         return;
328      }
329 
330    efl_gesture_timestamp_set(gesture, efl_gesture_touch_current_timestamp_get(touch_event));
331    efl_event_callback_call(target, gesture_type, gesture);
332 post_event:
333    /* avoid destroying touch tracking before gesture has ended */
334    if ((!rd->continues) &&
335         ((efl_gesture_touch_state_get(touch_event) != EFL_GESTURE_TOUCH_STATE_END) || efl_gesture_touch_points_count_get(touch_event)))
336      return;
337    //If the current event recognizes the gesture continuously, dont delete gesture.
338    if (((recog_state == EFL_GESTURE_RECOGNIZER_RESULT_FINISH) || (recog_state == EFL_GESTURE_RECOGNIZER_RESULT_CANCEL)) &&
339        !rd->continues)
340      _recognizer_cleanup_internal(pd, recognizer, target, gesture_type);
341 }
342 
343 void
_efl_canvas_gesture_manager_filter_event(void * data,Eo * target,void * event)344 _efl_canvas_gesture_manager_filter_event(void *data, Eo *target, void *event)
345 {
346    Efl_Canvas_Gesture_Manager_Data *pd = data;
347    Eina_Hash *thisisreallystupid;
348    Eina_Iterator *it;
349    Eina_Hash_Tuple *tup;
350    Efl_Canvas_Gesture_Recognizer *recognizer;
351 
352    thisisreallystupid = eina_hash_find(pd->m_gesture_contex, &target);
353    if (!thisisreallystupid) return;
354    pd->processing = EINA_TRUE;
355    it = eina_hash_iterator_tuple_new(thisisreallystupid);
356    EINA_ITERATOR_FOREACH(it, tup)
357      {
358         const Efl_Event_Description *gesture_type = *(void**)tup->key;
359 
360         if (gesture_type == EFL_EVENT_GESTURE_CUSTOM)
361           {
362              Eina_List *l;
363              EINA_LIST_FOREACH(pd->custom_recognizers, l, recognizer)
364                _gesture_recognizer_process_internal(pd, recognizer, target, gesture_type, event);
365           }
366         else
367           {
368              recognizer = eina_hash_find(pd->m_recognizers, &gesture_type);
369              _gesture_recognizer_process_internal(pd, recognizer, target, gesture_type, event);
370           }
371      }
372    eina_iterator_free(it);
373    pd->processing = EINA_FALSE;
374 }
375 
376 EOLIAN static void
_efl_canvas_gesture_manager_recognizer_register(Eo * obj EINA_UNUSED,Efl_Canvas_Gesture_Manager_Data * pd,Efl_Canvas_Gesture_Recognizer * recognizer)377 _efl_canvas_gesture_manager_recognizer_register(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd,
378                                                 Efl_Canvas_Gesture_Recognizer *recognizer)
379 {
380    const Efl_Event_Description *type = _gesture_recognizer_event_type_get(recognizer);
381    //Add the recognizer to the m_recognizers
382    if (type == EFL_EVENT_GESTURE_CUSTOM)
383      {
384         EINA_SAFETY_ON_TRUE_RETURN(pd->custom_recognizers && eina_list_data_find(pd->custom_recognizers, recognizer));
385         pd->custom_recognizers = eina_list_append(pd->custom_recognizers, efl_ref(recognizer));
386      }
387    else
388      {
389         EINA_SAFETY_ON_TRUE_RETURN(!!eina_hash_find(pd->m_recognizers, &type));
390         eina_hash_add(pd->m_recognizers, &type, efl_ref(recognizer));
391      }
392 
393 }
394 
395 EOLIAN static void
_efl_canvas_gesture_manager_recognizer_unregister(Eo * obj EINA_UNUSED,Efl_Canvas_Gesture_Manager_Data * pd,Efl_Canvas_Gesture_Recognizer * recognizer)396 _efl_canvas_gesture_manager_recognizer_unregister(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd,
397                                                   Efl_Canvas_Gesture_Recognizer *recognizer)
398 {
399    Eina_List *l, *l_next;
400    Object_Gesture *object_gesture;
401    const Efl_Event_Description *type;
402 
403    if (!recognizer) return;
404 
405    //Find the type of the recognizer
406    type = _gesture_recognizer_event_type_get(recognizer);
407    //Check if its already registered
408    if (type == EFL_EVENT_GESTURE_CUSTOM)
409      {
410         EINA_SAFETY_ON_TRUE_RETURN((!pd->custom_recognizers) || (!eina_list_data_find(pd->custom_recognizers, recognizer)));
411         pd->custom_recognizers = eina_list_remove(pd->custom_recognizers, recognizer);
412         eina_hash_del_by_key(pd->m_object_events, &recognizer);
413         efl_unref(recognizer);
414      }
415    else
416      {
417         EINA_SAFETY_ON_TRUE_RETURN(!eina_hash_find(pd->m_recognizers, &type));
418         eina_hash_del_by_key(pd->m_object_events, &recognizer);
419         eina_hash_del_by_key(pd->m_recognizers, &type);
420      }
421 
422    //Remove that gesture from the list of object gestures
423    EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
424      {
425         if ((object_gesture->type == type) && (object_gesture->recognizer == recognizer))
426           {
427              eina_array_push(pd->m_gestures_to_delete, object_gesture->gesture);
428              free(object_gesture);
429              pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
430           }
431      }
432    if (pd->processing) return;
433    _cleanup_object(pd->m_gestures_to_delete);
434 }
435 
436 // EOLIAN static void
437 // _efl_canvas_gesture_manager_ungrab_all(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd,
438 //                                    Eo *target)
439 // {
440 //    const Efl_Event_Description *type;
441 //    Eina_List *l;
442 
443 //    Eina_List *gesture_type_list = eina_hash_find(pd->m_gesture_contex, &target);
444 
445 //    if (!gesture_type_list) return;
446 
447 //    EINA_LIST_FOREACH(gesture_type_list, l, type)
448 //      {
449 //         _cleanup_cached_gestures(obj, pd, target, type);
450 //      }
451 //    eina_hash_del(pd->m_gesture_contex, &target, NULL);
452 // }
453 
454 //Get or create a gesture object that will represent the state for a given object, used by the recognizer
455 Efl_Canvas_Gesture *
_get_state(Efl_Canvas_Gesture_Manager_Data * pd,Eo * target,Efl_Canvas_Gesture_Recognizer * recognizer,const Efl_Event_Description * type)456 _get_state(Efl_Canvas_Gesture_Manager_Data *pd,
457            Eo *target, Efl_Canvas_Gesture_Recognizer *recognizer, const Efl_Event_Description *type)
458 {
459    Eina_List *l;
460    Object_Gesture *object_gesture;
461    Efl_Canvas_Gesture *gesture;
462 
463    //If the widget is being deleted we should be careful not to
464    //Create a new state.
465    if (efl_destructed_is(target))
466      return 0;
467 
468    //TODO find a optimized way of looking for gesture
469    EINA_LIST_FOREACH(pd->m_object_gestures, l, object_gesture)
470      {
471         if (object_gesture->object == target &&
472             object_gesture->recognizer == recognizer &&
473             object_gesture->type == type)
474           {
475              return object_gesture->gesture;
476           }
477      }
478 
479    gesture = efl_add(efl_gesture_recognizer_type_get(recognizer), recognizer);
480    if (!gesture)
481      return 0;
482 
483    object_gesture = calloc(1, sizeof(Object_Gesture));
484    object_gesture->object = target;
485    object_gesture->recognizer = recognizer;
486    object_gesture->type = type;
487    object_gesture->gesture = gesture;
488    if (type == EFL_EVENT_GESTURE_CUSTOM)
489      efl_gesture_custom_gesture_name_set(gesture, efl_gesture_recognizer_custom_gesture_name_get(recognizer));
490 
491    pd->m_object_gestures = eina_list_append(pd->m_object_gestures, object_gesture);
492 
493    return gesture;
494 }
495 
496 static void
_cleanup_cached_gestures(Efl_Canvas_Gesture_Manager_Data * pd,const Eo * target,const Efl_Event_Description * type,const Efl_Canvas_Gesture_Recognizer * recognizer)497 _cleanup_cached_gestures(Efl_Canvas_Gesture_Manager_Data *pd,
498                          const Eo *target, const Efl_Event_Description *type, const Efl_Canvas_Gesture_Recognizer *recognizer)
499 {
500    Eina_List *l, *l_next;
501    Object_Gesture *object_gesture;
502 
503    EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
504      {
505         if ((object_gesture->type == type) && (target == object_gesture->object) &&
506             ((!recognizer) || (object_gesture->recognizer == recognizer)))
507           {
508              eina_array_push(pd->m_gestures_to_delete, object_gesture->gesture);
509              free(object_gesture);
510              pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
511           }
512      }
513 }
514 
515 EOLIAN static void
_efl_canvas_gesture_manager_recognizer_cleanup(Eo * obj EINA_UNUSED,Efl_Canvas_Gesture_Manager_Data * pd,const Efl_Canvas_Gesture_Recognizer * recognizer,const Eo * target)516 _efl_canvas_gesture_manager_recognizer_cleanup(Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Manager_Data *pd, const Efl_Canvas_Gesture_Recognizer *recognizer, const Eo *target)
517 {
518    const Efl_Event_Description *type;
519 
520    EINA_SAFETY_ON_NULL_RETURN(recognizer);
521 
522    //Find the type of the recognizer
523    type = _gesture_recognizer_event_type_get(recognizer);
524    _recognizer_cleanup_internal(pd, recognizer, target, type);
525 }
526 
527 #include "efl_canvas_gesture_manager.eo.c"
528