Elm Glayer: Added ABORT on move to long-tap gesture
[framework/uifw/elementary.git] / src / lib / elm_gesture_layer.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 /** @defgroup Elm_Gesture_Layer Gesture Layer */
4
5 /* Some defaults */
6 #define ELM_MOUSE_DEVICE 0
7 /* ELM_GESTURE_NEGATIVE_ANGLE - magic number says we didn't compute this yet */
8 #define ELM_GESTURE_NEGATIVE_ANGLE (-1.0) /* Magic number */
9 #define ELM_GESTURE_MOMENTUM_TIMEOUT 50
10 #define ELM_GESTURE_MULTI_TIMEOUT 50
11
12 /* Some Trigo values */
13 #define RAD_90DEG  M_PI_2
14 #define RAD_180DEG M_PI
15 #define RAD_270DEG (M_PI_2 * 3)
16 #define RAD_360DEG (M_PI * 2)
17 /* #define DEBUG_GESTURE_LAYER 1 */
18
19 static void *
20 _glayer_bufdup(void *buf, size_t size)
21 {
22    void *p;
23    p = malloc(size);
24    memcpy(p, buf, size);
25    return p;
26 }
27 #define COPY_EVENT_INFO(EV) _glayer_bufdup(EV, sizeof(*EV))
28
29
30 #define SET_TEST_BIT(P) do { \
31    P->test = P->fn[ELM_GESTURE_STATE_START].cb || P->fn[ELM_GESTURE_STATE_MOVE].cb || P->fn[ELM_GESTURE_STATE_END].cb || P->fn[ELM_GESTURE_STATE_ABORT].cb; \
32 } while (0)
33
34 #define IS_TESTED(T) ((wd->gesture[T]) ? wd->gesture[T]->test : EINA_FALSE)
35
36 /**
37  * @internal
38  *
39  * @struct _Func_Data
40  * Struct holds callback information.
41  *
42  * @ingroup Elm_Gesture_Layer
43  */
44 struct _Func_Data
45 {
46    void *user_data; /**< Holds user data to CB (like sd) */
47    Elm_Gesture_Event_Cb cb;
48 };
49
50 /**
51  * @internal
52  *
53  * @typedef Func_Data
54  * type for callback information
55  *
56  * @ingroup Elm_Gesture_Layer
57  */
58 typedef struct _Func_Data Func_Data;
59
60 /**
61  * @internal
62  *
63  * @struct _Gesture_Info
64  * Struct holds gesture info
65  *
66  * @ingroup Elm_Gesture_Layer
67  */
68 struct _Gesture_Info
69 {
70   Evas_Object *obj;
71   void *data; /**< Holds gesture intemidiate processing data */
72   Func_Data fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */
73   Elm_Gesture_Types g_type;  /**< gesture type */
74   Elm_Gesture_State state;  /**< gesture state */
75   void *info;                        /**< Data for the state callback */
76   Eina_Bool test; /**< if true this gesture should be tested on input */
77 };
78
79 /**
80  * @internal
81  *
82  * @typedef Gesture_Info
83  * Type for _Gesture_Info
84  *
85  * @ingroup Elm_Gesture_Layer
86  */
87 typedef struct _Gesture_Info Gesture_Info;
88
89 /**
90  * @internal
91  *
92  * @struct _Event_History
93  * Struct holds event history.
94  * These events are repeated if no gesture found.
95  *
96  * @ingroup Elm_Gesture_Layer
97  */
98 struct _Event_History
99 {
100    EINA_INLIST;
101    void *event;
102    Evas_Callback_Type event_type;
103 };
104
105 /**
106  * @internal
107  *
108  * @typedef Event_History
109  * Type for _Event_History
110  *
111  * @ingroup Elm_Gesture_Layer
112  */
113 typedef struct _Event_History Event_History;
114
115 /**
116  * @internal
117  *
118  * @struct _Pointer_Event
119  * Struct holds pointer-event info
120  * This is a generic pointer event structure
121  *
122  * @ingroup Elm_Gesture_Layer
123  */
124 struct _Pointer_Event
125 {
126    Evas_Coord x, y;
127    unsigned int timestamp;
128    int device;
129    Evas_Callback_Type event_type;
130 };
131
132 /**
133  * @internal
134  *
135  * @typedef Pointer_Event
136  * Type for generic pointer event structure
137  *
138  * @ingroup Elm_Gesture_Layer
139  */
140 typedef struct _Pointer_Event Pointer_Event;
141
142 /* All *Type structs hold result for the user in 'info' field
143  * The rest is gesture processing intermediate data.
144  * NOTE: info field must be FIRST in the struct.
145  * This is used when reporting ABORT in event_history_clear() */
146 struct _Taps_Type
147 {
148    Elm_Gesture_Taps_Info info;
149    unsigned int sum_x;
150    unsigned int sum_y;
151    unsigned int n_taps_needed;
152    unsigned int n_taps;
153    Eina_List *l;
154 };
155 typedef struct _Taps_Type Taps_Type;
156
157 struct _Long_Tap_Type
158 {
159    Elm_Gesture_Taps_Info info;
160    Evas_Coord center_x;
161    Evas_Coord center_y;
162    unsigned int max_touched;
163    Ecore_Timer *timeout; /* When this expires, long tap STARTed */
164    Eina_List *touched;
165 };
166 typedef struct _Long_Tap_Type Long_Tap_Type;
167
168 struct _Momentum_Type
169 {  /* Fields used by _line_test() */
170    Elm_Gesture_Momentum_Info info;
171    Evas_Coord_Point line_st;
172    Evas_Coord_Point line_end;
173    unsigned int t_st_x;  /* Time start on X */
174    unsigned int t_st_y;  /* Time start on Y */
175    unsigned int t_end;   /* Time end        */
176    unsigned int t_up; /* Recent up event time */
177    int n_fingers;
178    int xdir, ydir;
179 };
180 typedef struct _Momentum_Type Momentum_Type;
181
182 struct _Line_Data
183 {
184    Evas_Coord_Point line_st;
185    Evas_Coord_Point line_end;
186    Evas_Coord line_length;
187    unsigned int t_st;  /* Time start */
188    unsigned int t_end; /* Time end   */
189    int device;
190    double line_angle;  /* Current angle of line */
191 };
192 typedef struct _Line_Data Line_Data;
193
194 struct _Line_Type
195 {  /* Fields used by _line_test() */
196    Elm_Gesture_Line_Info info;
197    Eina_List *list; /* List of Line_Data */
198 };
199 typedef struct _Line_Type Line_Type;
200
201 struct _Zoom_Type
202 {  /* Fields used by _zoom_test() */
203    Elm_Gesture_Zoom_Info info;
204    Pointer_Event zoom_st;
205    Pointer_Event zoom_mv;
206    Pointer_Event zoom_st1;
207    Pointer_Event zoom_mv1;
208    Evas_Event_Mouse_Wheel *zoom_wheel;
209    Evas_Coord zoom_base;  /* Holds gap between fingers on zoom-start  */
210    Evas_Coord zoom_distance_tolerance;
211    Elm_Gesture_Momentum_Info momentum1;      /* For continues gesture */
212    Elm_Gesture_Momentum_Info momentum2;      /* For continues gesture */
213    double next_step;
214 };
215 typedef struct _Zoom_Type Zoom_Type;
216
217 struct _Rotate_Type
218 {  /* Fields used by _rotation_test() */
219    Elm_Gesture_Rotate_Info info;
220    Pointer_Event rotate_st;
221    Pointer_Event rotate_mv;
222    Pointer_Event rotate_st1;
223    Pointer_Event rotate_mv1;
224    double rotate_angular_tolerance;
225    double next_step;
226    Elm_Gesture_Momentum_Info momentum1;      /* For continues gesture */
227    Elm_Gesture_Momentum_Info momentum2;      /* For continues gesture */
228 };
229 typedef struct _Rotate_Type Rotate_Type;
230
231 struct _Widget_Data
232 {
233    Evas_Object *target;  /* Target Widget */
234    Event_History *event_history_list;
235
236    int line_min_length;
237    Evas_Coord zoom_distance_tolerance;
238    Evas_Coord line_distance_tolerance;
239    double line_angular_tolerance;
240    double zoom_wheel_factor; /* mouse wheel zoom steps */
241    double zoom_finger_factor; /* used for zoom factor */
242    double rotate_angular_tolerance;
243    unsigned int flick_time_limit_ms;
244    double long_tap_start_timeout;
245    Eina_Bool glayer_continues_enable;
246
247    double zoom_step;
248    double rotate_step;
249
250    Gesture_Info *gesture[ELM_GESTURE_LAST];
251    Ecore_Timer *dbl_timeout; /* When this expires, dbl click/taps ABORTed  */
252    Eina_List *pending; /* List of devices need to refeed *UP event */
253    Eina_List *touched;  /* Information  of touched devices   */
254    Eina_List *recent_device_event;  /* Information  of recent pe event of each device */
255
256    Eina_Bool repeat_events : 1;
257 };
258 typedef struct _Widget_Data Widget_Data;
259
260 static const char *widtype = NULL;
261 static void _del_hook(Evas_Object *obj);
262
263 static Eina_Bool _event_history_clear(Evas_Object *obj);
264 static void _reset_states(Widget_Data *wd);
265 static void _key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
266 static void _key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
267 static void _zoom_with_wheel_test(Evas_Object *obj, void *event_info, Evas_Callback_Type event_type, Elm_Gesture_Types g_type);
268 static void _mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
269 static void _mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
270 static void _mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
271 static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
272
273 static void _multi_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
274 static void _multi_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
275 static void _multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
276
277 /* START - Functions to manage touched-device list */
278 /**
279  * @internal
280  * This function is used to find if device is touched
281  *
282  * @ingroup Elm_Gesture_Layer
283  */
284 static int
285 compare_device(const void *data1, const void *data2)
286 {  /* Compare the two device numbers */
287    return (((Pointer_Event *) data1)->device -((Pointer_Event *) data2)->device);
288 }
289
290 /**
291  * @internal
292  *
293  * Remove Pointer Event from touched device list
294  * @param list Pointer to touched device list.
295  * @param Pointer_Event Pointer to PE.
296  *
297  * @ingroup Elm_Gesture_Layer
298  */
299 static Eina_List *
300 _remove_touched_device(Eina_List *list, Pointer_Event *pe)
301 {
302    Pointer_Event *p = eina_list_search_unsorted(list, compare_device, pe);
303    if (p)
304      {
305         free(p);
306         return eina_list_remove(list, p);
307      }
308
309    return list;
310 }
311
312 /**
313  * @internal
314  *
315  * Recoed Pointer Event in touched device list
316  * Note: This fuction allocates memory for PE event
317  * This memory is released in _remove_touched_device()
318  * @param list Pointer to touched device list.
319  * @param Pointer_Event Pointer to PE.
320  *
321  * @ingroup Elm_Gesture_Layer
322  */
323 static Eina_List *
324 _add_touched_device(Eina_List *list, Pointer_Event *pe)
325 {
326    Pointer_Event *p = eina_list_search_unsorted(list, compare_device, pe);
327    if (p)
328      {  /* We like to track device touch-position, overwrite info */
329         memcpy(p, pe, sizeof(Pointer_Event));
330         return list;
331      }
332
333    p = malloc(sizeof(Pointer_Event));
334    memcpy(p, pe, sizeof(Pointer_Event)); /* Freed in _remove_touched_device() */
335    return eina_list_append(list, p);
336 }
337 /* END   - Functions to manage touched-device list */
338
339 /* START - Functions to manage recent device event list */
340 /* This list holds the recent-event for each device     */
341 /* it will hold a single recent-event for each device   */
342 /* We are using those PE events of this list to         */
343 /* send them later to test funcs to restart gestures    */
344 /* We only keep DOWN, MOVE events in this list.         */
345 /* So when no touch this list is empty.                 */
346 /**
347  * @internal
348  *
349  * Recoed Pointer Event in touched device list
350  * Note: This fuction allocates memory for PE event
351  * This memory is released here when device untouched
352  * or in cleanup.
353  * @param list Pointer to touched device list.
354  * @param Pointer_Event Pointer to PE.
355  *
356  * @ingroup Elm_Gesture_Layer
357  */
358 static Eina_List *
359 _add_recent_device_event(Eina_List *list, Pointer_Event *pe)
360 {
361    void *data = eina_list_search_sorted(list, compare_device, pe);
362    Eina_List *l = list;
363    Pointer_Event *p = NULL;
364    if(data)   /* First remove recent event for this device */
365      l = eina_list_remove(list, data);
366
367
368    switch(pe->event_type)
369      {
370       case EVAS_CALLBACK_MOUSE_DOWN:
371       case EVAS_CALLBACK_MOUSE_MOVE:
372       case EVAS_CALLBACK_MULTI_DOWN:
373       case EVAS_CALLBACK_MULTI_MOVE:
374          p = malloc(sizeof(Pointer_Event));
375          memcpy(p, pe, sizeof(Pointer_Event)); /* Freed in here or on cleanup */
376          l =  eina_list_sorted_insert(l, compare_device, p);
377          break;
378
379       /* Kept those cases for referance */
380       case EVAS_CALLBACK_MOUSE_IN:
381       case EVAS_CALLBACK_MOUSE_OUT:
382       case EVAS_CALLBACK_MOUSE_WHEEL:
383       case EVAS_CALLBACK_MOUSE_UP:
384       case EVAS_CALLBACK_MULTI_UP:
385       case EVAS_CALLBACK_KEY_DOWN:
386       case EVAS_CALLBACK_KEY_UP:
387          break;
388
389       default:
390          return l;
391      }
392
393    return l;
394 }
395 /* END   - Functions to manage recent device event list */
396
397 /**
398  * @internal
399  *
400  * Get event flag
401  * @param event_info pointer to event.
402  *
403  * @ingroup Elm_Gesture_Layer
404  */
405 static Evas_Event_Flags
406 _get_event_flag(void *event_info, Evas_Callback_Type event_type)
407 {
408    switch(event_type)
409      {
410       case EVAS_CALLBACK_MOUSE_IN:
411          return ((Evas_Event_Mouse_In *) event_info)->event_flags;
412       case EVAS_CALLBACK_MOUSE_OUT:
413          return ((Evas_Event_Mouse_Out *) event_info)->event_flags;
414       case EVAS_CALLBACK_MOUSE_DOWN:
415          return ((Evas_Event_Mouse_Down *) event_info)->event_flags;
416       case EVAS_CALLBACK_MOUSE_MOVE:
417          return ((Evas_Event_Mouse_Move *) event_info)->event_flags;
418       case EVAS_CALLBACK_MOUSE_UP:
419          return ((Evas_Event_Mouse_Up *) event_info)->event_flags;
420       case EVAS_CALLBACK_MOUSE_WHEEL:
421          return ((Evas_Event_Mouse_Wheel *) event_info)->event_flags;
422       case EVAS_CALLBACK_MULTI_DOWN:
423          return ((Evas_Event_Multi_Down *) event_info)->event_flags;
424       case EVAS_CALLBACK_MULTI_MOVE:
425          return ((Evas_Event_Multi_Move *) event_info)->event_flags;
426       case EVAS_CALLBACK_MULTI_UP:
427          return ((Evas_Event_Multi_Up *) event_info)->event_flags;
428       case EVAS_CALLBACK_KEY_DOWN:
429          return ((Evas_Event_Key_Down *) event_info)->event_flags;
430       case EVAS_CALLBACK_KEY_UP:
431          return ((Evas_Event_Key_Up *) event_info)->event_flags;
432       default:
433          return EVAS_EVENT_FLAG_NONE;
434      }
435 }
436
437 /**
438  * @internal
439  *
440  * Sets event flag to value returned from user callback
441  * @param wd Widget Data
442  * @param event_info pointer to event.
443  * @param event_type what type was ev (mouse down, etc...)
444  * @param ev_flags event flags
445  *
446  * @ingroup Elm_Gesture_Layer
447  */
448 static void
449 consume_event(Widget_Data *wd, void *event_info,
450       Evas_Callback_Type event_type, Evas_Event_Flags ev_flags)
451 {  /* Mark EVAS_EVENT_FLAG_ON_HOLD on events that are used by gesture layer */
452    /* ev_flags != EVAS_EVENT_FLAG_NONE means target used event and g-layer  */
453    /* should not refeed this event.                                         */
454    if(!event_info)
455      return;  /* This happens when restarting gestures  */
456
457    if ((ev_flags) || (!wd->repeat_events))
458      {
459         switch(event_type)
460           {
461            case EVAS_CALLBACK_MOUSE_DOWN:
462               ((Evas_Event_Mouse_Down *) event_info)->event_flags |= ev_flags;
463               break;
464            case EVAS_CALLBACK_MOUSE_MOVE:
465               ((Evas_Event_Mouse_Move *) event_info)->event_flags |= ev_flags;
466               break;
467            case EVAS_CALLBACK_MOUSE_UP:
468               ((Evas_Event_Mouse_Up *) event_info)->event_flags |= ev_flags;
469               break;
470            case EVAS_CALLBACK_MOUSE_WHEEL:
471               ((Evas_Event_Mouse_Wheel *) event_info)->event_flags |= ev_flags;
472               break;
473            case EVAS_CALLBACK_MULTI_DOWN:
474               ((Evas_Event_Multi_Down *) event_info)->event_flags |= ev_flags;
475               break;
476            case EVAS_CALLBACK_MULTI_MOVE:
477               ((Evas_Event_Multi_Move *) event_info)->event_flags |= ev_flags;
478               break;
479            case EVAS_CALLBACK_MULTI_UP:
480               ((Evas_Event_Multi_Up *) event_info)->event_flags |= ev_flags;
481               break;
482            case EVAS_CALLBACK_KEY_DOWN:
483               ((Evas_Event_Key_Down *) event_info)->event_flags |= ev_flags;
484               break;
485            case EVAS_CALLBACK_KEY_UP:
486               ((Evas_Event_Key_Up *) event_info)->event_flags |= ev_flags;
487               break;
488            default:
489               return;
490           }
491      }
492 }
493
494 /**
495  * @internal
496  *
497  * Report current state of a gesture by calling user callback.
498  * @param gesture what gesture state we report.
499  * @param info inforamtion for user callback
500  *
501  * @ingroup Elm_Gesture_Layer
502  */
503 static Evas_Event_Flags
504 _report_state(Gesture_Info *gesture, void *info)
505 {  /* We report current state (START, MOVE, END, ABORT), once */
506 #if defined(DEBUG_GESTURE_LAYER)
507    printf("%s reporting gesture=<%d> state=<%d>\n" , __func__, gesture->g_type,
508          gesture->state);
509 #endif
510    if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
511          (gesture->fn[gesture->state].cb))
512      {  /* Fill state-info struct and send ptr to user callback */
513         return gesture->fn[gesture->state].cb(
514               gesture->fn[gesture->state].user_data, info);
515      }
516
517    return EVAS_EVENT_FLAG_NONE;
518 }
519
520 /**
521  * @internal
522  *
523  * Update state for a given gesture.
524  * We may update gesture state to:
525  * UNDEFINED - current input did not start gesure yet.
526  * START - gesture started according to input.
527  * MOVE - gusture in progress.
528  * END - gesture completed according to input.
529  * ABORT - input does not matches gesure.
530  * note that we may move from UNDEFINED to ABORT
531  * because we may detect that gesture will not START
532  * with a given input.
533  *
534  * @param g given gesture to change state.
535  * @param s gesure new state.
536  * @param info buffer to be sent to user callback on report_state.
537  * @param force makes report_state to report the new-state even
538  * if its same as current state. Works for MOVE - gesture in progress.
539  *
540  * @ingroup Elm_Gesture_Layer
541  */
542 static Evas_Event_Flags
543 _set_state(Gesture_Info *g, Elm_Gesture_State s,
544       void *info, Eina_Bool force)
545 {
546    Elm_Gesture_State old_state;
547    if ((g->state == s) && (!force))
548      return EVAS_EVENT_FLAG_NONE;
549
550    old_state = g->state;
551
552    g->state = s;
553    g->info = info;  /* Information for user callback */
554    if ((g->state == ELM_GESTURE_STATE_ABORT) ||
555          (g->state == ELM_GESTURE_STATE_END))
556      g->test = EINA_FALSE;
557
558    if ((g->state != ELM_GESTURE_STATE_UNDEFINED) &&
559          (!((old_state == ELM_GESTURE_STATE_UNDEFINED) &&
560             (s == ELM_GESTURE_STATE_ABORT))))
561      return _report_state(g, g->info);
562
563    return EVAS_EVENT_FLAG_NONE;
564 }
565
566 /**
567  * @internal
568  *
569  * This resets all gesture states and sets test-bit.
570  * this is used for restarting gestures to listen to input.
571  * happens after we complete a gesture or no gesture was detected.
572  * @param wd Widget data of the gesture-layer object.
573  *
574  * @ingroup Elm_Gesture_Layer
575  */
576 static void
577 _reset_states(Widget_Data *wd)
578 {
579    int i;
580    Gesture_Info *p;
581    for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
582      {
583         p = wd->gesture[i];
584         if (p)
585           {
586              _set_state(p, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
587              SET_TEST_BIT(p);
588           }
589      }
590 }
591
592 /**
593  * @internal
594  *
595  * if gesture was NOT detected AND we only have gestures in ABORT state
596  * we clear history immediately to be ready for input.
597  *
598  * @param obj The gesture-layer object.
599  * @return TRUE on event history_clear
600  *
601  * @ingroup Elm_Gesture_Layer
602  */
603 static Eina_Bool
604 _clear_if_finished(Evas_Object *obj)
605 {
606    Widget_Data *wd = elm_widget_data_get(obj);
607    if (!wd) return EINA_FALSE;
608    int i;
609
610    /* Clear history if all we have aborted gestures */
611    Eina_Bool reset_s = EINA_TRUE, all_undefined = EINA_TRUE;
612    for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
613      {  /* If no gesture started and all we have aborted gestures, reset all */
614         Gesture_Info *p = wd->gesture[i];
615         if ((p) && (p->state != ELM_GESTURE_STATE_UNDEFINED))
616           {
617              if ((p->state == ELM_GESTURE_STATE_START) ||
618                    (p->state == ELM_GESTURE_STATE_MOVE))
619                reset_s = EINA_FALSE;
620
621              all_undefined = EINA_FALSE;
622           }
623      }
624
625    if (reset_s && (!all_undefined))
626      return _event_history_clear(obj);
627
628    return EINA_FALSE;
629 }
630
631 static Eina_Bool
632 _inside(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
633 {
634    int w = elm_finger_size_get() >> 1; /* Finger size devided by 2 */
635    if (x1 < (x2 - w))
636      return EINA_FALSE;
637
638    if (x1 > (x2 + w))
639      return EINA_FALSE;
640
641    if (y1 < (y2 - w))
642      return EINA_FALSE;
643
644    if (y1 > (y2 + w))
645      return EINA_FALSE;
646
647    return EINA_TRUE;
648 }
649
650 /* All *test_reset() funcs are called to clear
651  * gesture intermediate data.
652  * This happens when we need to reset our tests.
653  * for example when gesture is detected or all ABORTed. */
654 static void
655 _tap_gestures_test_reset(Gesture_Info *gesture)
656 {
657    if (!gesture)
658      return;
659
660    Widget_Data *wd = elm_widget_data_get(gesture->obj);
661    wd->dbl_timeout = NULL;
662    Eina_List *data;
663    Pointer_Event *pe;
664
665    if (!gesture->data)
666      return;
667
668    EINA_LIST_FREE(((Taps_Type *) gesture->data)->l, data)
669       EINA_LIST_FREE(data, pe)
670          free(pe);
671
672   memset(gesture->data, 0, sizeof(Taps_Type));
673 }
674
675 /* All *test_reset() funcs are called to clear
676  * gesture intermediate data.
677  * This happens when we need to reset our tests.
678  * for example when gesture is detected or all ABORTed. */
679 static void
680 _n_long_tap_test_reset(Gesture_Info *gesture)
681 {
682    if (!gesture)
683      return;
684
685    if (!gesture->data)
686      return;
687
688    Long_Tap_Type *st = gesture->data;
689    Eina_List *l;
690    Pointer_Event *p;
691    EINA_LIST_FOREACH(st->touched, l, p)
692       free(p);
693
694    eina_list_free(st->touched);
695    if (st->timeout) ecore_timer_del(st->timeout);
696    memset(gesture->data, 0, sizeof(Long_Tap_Type));
697 }
698
699 static void
700 _momentum_test_reset(Gesture_Info *gesture)
701 {
702    if (!gesture)
703      return;
704
705    if (!gesture->data)
706      return;
707
708    memset(gesture->data, 0, sizeof(Momentum_Type));
709 }
710
711 static void
712 _line_data_reset(Line_Data *st)
713 {
714    if (!st)
715      return;
716
717    memset(st, 0, sizeof(Line_Data));
718    st->line_angle = ELM_GESTURE_NEGATIVE_ANGLE;
719 }
720
721 static void
722 _line_test_reset(Gesture_Info *gesture)
723 {
724    if (!gesture)
725      return;
726
727    if (!gesture->data)
728      return;
729
730    Line_Type *st = gesture->data;
731    Eina_List *list = st->list;
732    Eina_List *l;
733    Line_Data *t_line;
734    EINA_LIST_FOREACH(list, l, t_line)
735       free(t_line);
736
737    eina_list_free(list);
738    st->list = NULL;
739 }
740
741 static void
742 _zoom_test_reset(Gesture_Info *gesture)
743 {
744    if (!gesture)
745      return;
746
747    if (!gesture->data)
748      return;
749
750    Widget_Data *wd = elm_widget_data_get(gesture->obj);
751    Zoom_Type *st = gesture->data;
752    Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
753          evas_object_evas_get(wd->target), "Control");
754    evas_object_key_ungrab(wd->target, "Control_L", mask, 0);
755    evas_object_key_ungrab(wd->target, "Control_R", mask, 0);
756
757    memset(st, 0, sizeof(Zoom_Type));
758    st->zoom_distance_tolerance = wd->zoom_distance_tolerance;
759    st->info.zoom = 1.0;
760 }
761
762 static void
763 _rotate_test_reset(Gesture_Info *gesture)
764 {
765    if (!gesture)
766      return;
767
768    if (!gesture->data)
769      return;
770
771    Widget_Data *wd = elm_widget_data_get(gesture->obj);
772    Rotate_Type *st = gesture->data;
773
774    memset(st, 0, sizeof(Rotate_Type));
775    st->info.base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
776    st->rotate_angular_tolerance = wd->rotate_angular_tolerance;
777 }
778
779
780 /**
781  * @internal
782  *
783  * We register callbacks when gesture layer is attached to an object
784  * or when its enabled after disable.
785  *
786  * @param obj The gesture-layer object.
787  *
788  * @ingroup Elm_Gesture_Layer
789  */
790 static void
791 _register_callbacks(Evas_Object *obj)
792 {
793    Widget_Data *wd = elm_widget_data_get(obj);
794    if (!wd) return;
795
796    if (wd->target)
797      {
798         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_DOWN,
799               _mouse_down, obj);
800         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_MOVE,
801               _mouse_move, obj);
802         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_UP,
803               _mouse_up, obj);
804
805         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_WHEEL,
806               _mouse_wheel, obj);
807
808         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_DOWN,
809               _multi_down, obj);
810         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_MOVE,
811               _multi_move, obj);
812         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_UP,
813               _multi_up, obj);
814
815         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_KEY_DOWN,
816               _key_down_cb, obj);
817         evas_object_event_callback_add(wd->target, EVAS_CALLBACK_KEY_UP,
818               _key_up_cb, obj);
819      }
820 }
821
822 /**
823  * @internal
824  *
825  * We unregister callbacks when gesture layer is disabled.
826  *
827  * @param obj The gesture-layer object.
828  *
829  * @ingroup Elm_Gesture_Layer
830  */
831 static void
832 _unregister_callbacks(Evas_Object *obj)
833 {
834    Widget_Data *wd = elm_widget_data_get(obj);
835    if (!wd) return;
836
837    if (wd->target)
838      {
839         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_DOWN,
840               _mouse_down);
841         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_MOVE,
842               _mouse_move);
843         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_UP,
844               _mouse_up);
845
846         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_WHEEL,
847               _mouse_wheel);
848
849         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_DOWN,
850               _multi_down);
851
852         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_MOVE,
853               _multi_move);
854
855         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_UP,
856               _multi_up);
857
858         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_KEY_DOWN,
859               _key_down_cb);
860         evas_object_event_callback_del(wd->target, EVAS_CALLBACK_KEY_UP,
861               _key_up_cb);
862      }
863 }
864
865 /* START - Event history list handling functions */
866 /**
867  * @internal
868  * This function is used to find if device number
869  * is found in a list of devices.
870  * The list contains devices for refeeding *UP event
871  *
872  * @ingroup Elm_Gesture_Layer
873  */
874 static int
875 device_in_pending_list(const void *data1, const void *data2)
876 {  /* Compare the two device numbers */
877    return (((intptr_t) data1) - ((intptr_t) data2));
878 }
879
880 /**
881  * @internal
882  *
883  * This functions adds device to refeed-pending device list
884  * @ingroup Elm_Gesture_Layer
885  */
886 static Eina_List *
887 _add_device_pending(Eina_List *list, void *event, Evas_Callback_Type event_type)
888 {
889    int device = ELM_MOUSE_DEVICE;
890    switch(event_type)
891      {
892       case EVAS_CALLBACK_MOUSE_DOWN:
893          break;
894       case EVAS_CALLBACK_MULTI_DOWN:
895          device = ((Evas_Event_Multi_Down *) event)->device;
896          break;
897       default:
898          return list;
899      }
900
901    if (!eina_list_search_unsorted_list(list, device_in_pending_list,
902             (intptr_t*) device))
903      {
904         return eina_list_append(list, (intptr_t*) device);
905      }
906
907    return list;
908 }
909
910 /**
911  * @internal
912  *
913  * This functions returns pending-device node
914  * @ingroup Elm_Gesture_Layer
915  */
916 static Eina_List *
917 _device_is_pending(Eina_List *list, void *event, Evas_Callback_Type event_type)
918 {
919    int device = ELM_MOUSE_DEVICE;
920    switch(event_type)
921      {
922       case EVAS_CALLBACK_MOUSE_UP:
923          break;
924       case EVAS_CALLBACK_MULTI_UP:
925          device = ((Evas_Event_Multi_Up *) event)->device;
926          break;
927       default:
928         return NULL;
929      }
930
931    return eina_list_search_unsorted_list(list, device_in_pending_list,
932          (intptr_t *) device);
933 }
934
935 /**
936  * @internal
937  *
938  * This function reports ABORT to all none-detected gestures
939  * Then resets test bits for all desired gesures
940  * and clears input-events history.
941  * note: if no gesture was detected, events from history list
942  * are streamed to the widget because it's unused by layer.
943  * user may cancel refeed of events by setting repeat events.
944  *
945  * @param obj The gesture-layer object.
946  *
947  * @ingroup Elm_Gesture_Layer
948  */
949 static Eina_Bool
950 _event_history_clear(Evas_Object *obj)
951 {
952    Widget_Data *wd = elm_widget_data_get(obj);
953    if (!wd) return EINA_FALSE;
954
955    int i;
956    Gesture_Info *p;
957    Evas *e = evas_object_evas_get(obj);
958    Eina_Bool gesture_found = EINA_FALSE;
959    for (i = ELM_GESTURE_FIRST ; i < ELM_GESTURE_LAST; i++)
960      {
961         p = wd->gesture[i];
962         if (p)
963           {
964              if (p->state == ELM_GESTURE_STATE_END)
965                gesture_found = EINA_TRUE;
966              else
967                {  /* Report ABORT to all gestures that still not finished */
968                   _set_state(p, ELM_GESTURE_STATE_ABORT, wd->gesture[i]->info,
969                         EINA_FALSE);
970                }
971           }
972      }
973
974    _reset_states(wd); /* we are ready to start testing for gestures again */
975
976    /* Clear all gestures intermediate data */
977    if (IS_TESTED(ELM_GESTURE_N_LONG_TAPS))
978      {  /* We do not clear a long-tap gesture if fingers still on surface */
979         /* and gesture timer still pending to test gesture state          */
980         Long_Tap_Type *st = wd->gesture[ELM_GESTURE_N_LONG_TAPS]->data;
981         if ((st) &&  /* st not allocated if clear occurs before 1st input */
982               ((!eina_list_count(st->touched)) || (!st->timeout)))
983           _n_long_tap_test_reset(wd->gesture[ELM_GESTURE_N_LONG_TAPS]);
984      }
985
986    if (wd->dbl_timeout)
987      {
988         ecore_timer_del(wd->dbl_timeout);
989         wd->dbl_timeout = NULL;
990      }
991
992    _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_TAPS]);
993    _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
994    _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
995    _momentum_test_reset(wd->gesture[ELM_GESTURE_MOMENTUM]);
996    _line_test_reset(wd->gesture[ELM_GESTURE_N_LINES]);
997    _line_test_reset(wd->gesture[ELM_GESTURE_N_FLICKS]);
998    _zoom_test_reset(wd->gesture[ELM_GESTURE_ZOOM]);
999    _rotate_test_reset(wd->gesture[ELM_GESTURE_ROTATE]);
1000
1001    /* Disable gesture layer so refeeded events won't be consumed by it */
1002    _unregister_callbacks(obj);
1003    while (wd->event_history_list)
1004      {
1005         Event_History *t;
1006         t = wd->event_history_list;
1007         Eina_List *pending = _device_is_pending(wd->pending,
1008               wd->event_history_list->event,
1009               wd->event_history_list->event_type);
1010
1011         /* Refeed events if no gesture matched input */
1012         if (pending || ((!gesture_found) && (!wd->repeat_events)))
1013           {
1014              evas_event_refeed_event(e, wd->event_history_list->event,
1015                    wd->event_history_list->event_type);
1016
1017              if (pending)
1018                {
1019                wd->pending = eina_list_remove_list(wd->pending, pending);
1020                int device = ELM_MOUSE_DEVICE;
1021                if (wd->event_history_list->event_type == EVAS_CALLBACK_MULTI_UP)
1022                  device = ((Evas_Event_Multi_Up *)
1023                        (wd->event_history_list->event))->device;
1024                }
1025              else
1026                wd->pending = _add_device_pending(wd->pending,
1027                      wd->event_history_list->event,
1028                      wd->event_history_list->event_type);
1029           }
1030
1031         free(wd->event_history_list->event);
1032         wd->event_history_list = (Event_History *) eina_inlist_remove(
1033               EINA_INLIST_GET(wd->event_history_list),
1034               EINA_INLIST_GET(wd->event_history_list));
1035         free(t);
1036      }
1037    _register_callbacks(obj);
1038    return EINA_TRUE;
1039 }
1040
1041 /**
1042  * @internal
1043  *
1044  * This function copies input events.
1045  * We copy event info before adding it to history.
1046  * The memory is freed when we clear history.
1047  *
1048  * @param event the event to copy
1049  * @param event_type event type to copy
1050  *
1051  * @ingroup Elm_Gesture_Layer
1052  */
1053 static void *
1054 _copy_event_info(void *event, Evas_Callback_Type event_type)
1055 {
1056    switch(event_type)
1057      {
1058       case EVAS_CALLBACK_MOUSE_DOWN:
1059          return COPY_EVENT_INFO((Evas_Event_Mouse_Down *) event);
1060          break;
1061       case EVAS_CALLBACK_MOUSE_MOVE:
1062          return COPY_EVENT_INFO((Evas_Event_Mouse_Move *) event);
1063          break;
1064       case EVAS_CALLBACK_MOUSE_UP:
1065          return COPY_EVENT_INFO((Evas_Event_Mouse_Up *) event);
1066          break;
1067       case EVAS_CALLBACK_MOUSE_WHEEL:
1068          return COPY_EVENT_INFO((Evas_Event_Mouse_Wheel *) event);
1069          break;
1070       case EVAS_CALLBACK_MULTI_DOWN:
1071          return COPY_EVENT_INFO((Evas_Event_Multi_Down *) event);
1072          break;
1073       case EVAS_CALLBACK_MULTI_MOVE:
1074          return COPY_EVENT_INFO((Evas_Event_Multi_Move *) event);
1075          break;
1076       case EVAS_CALLBACK_MULTI_UP:
1077          return COPY_EVENT_INFO((Evas_Event_Multi_Up *) event);
1078          break;
1079       case EVAS_CALLBACK_KEY_DOWN:
1080          return COPY_EVENT_INFO((Evas_Event_Key_Down *) event);
1081          break;
1082       case EVAS_CALLBACK_KEY_UP:
1083          return COPY_EVENT_INFO((Evas_Event_Key_Up *) event);
1084          break;
1085       default:
1086          return NULL;
1087      }
1088 }
1089
1090 static Eina_Bool
1091 _event_history_add(Evas_Object *obj, void *event, Evas_Callback_Type event_type)
1092 {
1093    Widget_Data *wd = elm_widget_data_get(obj);
1094    Event_History *ev;
1095    if (!wd) return EINA_FALSE;
1096
1097    ev = malloc(sizeof(Event_History));
1098    ev->event = _copy_event_info(event, event_type);  /* Freed on event_history_clear */
1099    ev->event_type = event_type;
1100    wd->event_history_list = (Event_History *) eina_inlist_append(
1101          EINA_INLIST_GET(wd->event_history_list), EINA_INLIST_GET(ev));
1102
1103    return EINA_TRUE;
1104 }
1105 /* END - Event history list handling functions */
1106
1107 static void
1108 _del_hook(Evas_Object *obj)
1109 {
1110    Widget_Data *wd = elm_widget_data_get(obj);
1111    if (!wd) return;
1112
1113    _event_history_clear(obj);
1114    eina_list_free(wd->pending);
1115
1116    Pointer_Event *data;
1117    EINA_LIST_FREE(wd->touched, data)
1118       free(data);
1119
1120    EINA_LIST_FREE(wd->recent_device_event, data)
1121       free(data);
1122
1123    if (!elm_widget_disabled_get(obj))
1124      _unregister_callbacks(obj);
1125
1126    /* Free all gestures internal data structures */
1127    int i;
1128    for (i = 0; i < ELM_GESTURE_LAST; i++)
1129      if (wd->gesture[i])
1130        {
1131           if (wd->gesture[i]->data)
1132             free(wd->gesture[i]->data);
1133
1134           free(wd->gesture[i]);
1135        }
1136
1137    free(wd);
1138 }
1139
1140 static int
1141 compare_match_fingers(const void *data1, const void *data2)
1142 {  /* Compare coords of first item in list to cur coords */
1143    const Pointer_Event *pe1 = eina_list_data_get(data1);
1144    const Pointer_Event *pe2 = data2;
1145
1146    if (_inside(pe1->x, pe1->y, pe2->x, pe2->y))
1147      return 0;
1148    else if (pe1->x < pe2->x)
1149      return -1;
1150    else
1151      {
1152         if (pe1->x == pe2->x)
1153           return pe1->y - pe2->y;
1154         else
1155           return 1;
1156      }
1157 }
1158
1159 static int
1160 compare_pe_device(const void *data1, const void *data2)
1161 {  /* Compare coords of first item in list to cur coords */
1162    const Pointer_Event *pe1 = eina_list_data_get(eina_list_last(data1));
1163    const Pointer_Event *pe2 = data2;
1164
1165    /* Only match if last was a down event */
1166    if ((pe1->event_type != EVAS_CALLBACK_MULTI_DOWN) &&
1167          (pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN))
1168      return 1;
1169
1170
1171    if (pe1->device == pe2->device)
1172      return 0;
1173    else if (pe1->device < pe2->device)
1174      return -1;
1175    else
1176      return 1;
1177 }
1178
1179 static Eina_List*
1180 _record_pointer_event(Taps_Type *st, Eina_List *pe_list, Pointer_Event *pe,
1181       Widget_Data *wd, void *event_info, Evas_Callback_Type event_type)
1182 {  /* Keep copy of pe and record it in list */
1183    Pointer_Event *p = malloc(sizeof(Pointer_Event));
1184    memcpy(p, pe, sizeof(Pointer_Event));
1185    consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
1186
1187    st->sum_x += pe->x;
1188    st->sum_y += pe->y;
1189    st->n_taps++;
1190
1191    /* This will also update middle-point to report to user later */
1192    st->info.x = st->sum_x / st->n_taps;
1193    st->info.y = st->sum_y / st->n_taps;
1194    st->info.timestamp = pe->timestamp;
1195
1196    if (!pe_list)
1197      {
1198         pe_list = eina_list_append(pe_list, p);
1199         st->l = eina_list_append(st->l, pe_list);
1200      }
1201    else
1202      pe_list = eina_list_append(pe_list, p);
1203
1204    return pe_list;
1205 }
1206
1207 /**
1208  * @internal
1209  *
1210  * This function sets state a tap-gesture to END or ABORT
1211  *
1212  * @param data gesture info pointer
1213  *
1214  * @ingroup Elm_Gesture_Layer
1215  */
1216 static void
1217 _tap_gesture_finish(void *data)
1218 {  /* This function will test each tap gesture when timer expires */
1219    Gesture_Info *gesture = data;
1220    Elm_Gesture_State s = ELM_GESTURE_STATE_END;
1221    /* Here we check if taps-gesture was completed successfuly */
1222    /* Count how many taps were recieved on each device then   */
1223    /* determine if it matches n_taps_needed defined on START  */
1224    Taps_Type *st = gesture->data;
1225    Eina_List *l;
1226    Eina_List *pe_list;
1227    EINA_LIST_FOREACH(st->l, l, pe_list)
1228      {
1229         if (eina_list_count(pe_list) != st->n_taps_needed)
1230           {  /* No match taps number on device, ABORT */
1231              s = ELM_GESTURE_STATE_ABORT;
1232              break;
1233           }
1234      }
1235
1236    st->info.n = eina_list_count(st->l);
1237    _set_state(gesture, s, gesture->info, EINA_FALSE);
1238    _tap_gestures_test_reset(gesture);
1239 }
1240
1241 /**
1242  * @internal
1243  *
1244  * when this timer expires we finish tap gestures.
1245  *
1246  * @param data The gesture-layer object.
1247  * @return cancles callback for this timer.
1248  *
1249  * @ingroup Elm_Gesture_Layer
1250  */
1251 static Eina_Bool
1252 _multi_tap_timeout(void *data)
1253 {
1254    Widget_Data *wd = elm_widget_data_get(data);
1255    if (!wd) return EINA_FALSE;
1256
1257    if (IS_TESTED(ELM_GESTURE_N_TAPS))
1258      _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TAPS]);
1259
1260    if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
1261    _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
1262
1263    if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
1264    _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
1265
1266    _clear_if_finished(data);
1267    wd->dbl_timeout = NULL;
1268    return ECORE_CALLBACK_CANCEL;
1269 }
1270
1271 /**
1272  * @internal
1273  *
1274  * when this timer expires we START long tap gesture
1275  *
1276  * @param data The gesture-layer object.
1277  * @return cancles callback for this timer.
1278  *
1279  * @ingroup Elm_Gesture_Layer
1280  */
1281 static Eina_Bool
1282 _long_tap_timeout(void *data)
1283 {
1284    Gesture_Info *gesture = data;
1285    Long_Tap_Type *st = gesture->data;
1286    st->timeout = NULL;
1287
1288    _set_state(gesture, ELM_GESTURE_STATE_START,
1289          gesture->data, EINA_FALSE);
1290
1291    return ECORE_CALLBACK_CANCEL;
1292 }
1293
1294
1295 /**
1296  * @internal
1297  *
1298  * This function checks if a tap gesture should start
1299  *
1300  * @param wd Gesture Layer Widget Data.
1301  * @param pe The recent input event as stored in pe struct.
1302  * @param event_info Original input event pointer.
1303  * @param event_type Type of original input event.
1304  * @param gesture what gesture is tested
1305  * @param how many taps for this gesture (1, 2 or 3)
1306  *
1307  * @return Flag to determine if we need to set a timer for finish
1308  *
1309  * @ingroup Elm_Gesture_Layer
1310  */
1311 static Eina_Bool
1312 _tap_gesture_start(Widget_Data *wd, Pointer_Event *pe,
1313       void *event_info, Evas_Callback_Type event_type,
1314       Gesture_Info *gesture, int taps)
1315 {  /* Here we fill Tap struct */
1316    Taps_Type *st = gesture->data;
1317    if (!st)
1318      {  /* Allocated once on first time */
1319         st = calloc(1, sizeof(Taps_Type));
1320         gesture->data = st;
1321         _tap_gestures_test_reset(gesture);
1322      }
1323
1324    Eina_List *pe_list = NULL;
1325    Pointer_Event *pe_down = NULL;
1326    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1327    switch (pe->event_type)
1328      {
1329       case EVAS_CALLBACK_MULTI_DOWN:
1330       case EVAS_CALLBACK_MOUSE_DOWN:
1331          pe_list = eina_list_search_unsorted(st->l, compare_match_fingers, pe);
1332          pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type);
1333          if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
1334            {  /* This is the first mouse down we got */
1335               ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
1336                     &st->info, EINA_FALSE);
1337               consume_event(wd, event_info, event_type, ev_flag);
1338
1339               st->n_taps_needed = taps * 2; /* count DOWN and UP */
1340
1341               return EINA_TRUE;
1342            }
1343
1344          break;
1345
1346       case EVAS_CALLBACK_MULTI_UP:
1347       case EVAS_CALLBACK_MOUSE_UP:
1348          pe_list = eina_list_search_unsorted(st->l, compare_pe_device, pe);
1349          if (!pe_list)
1350            return EINA_FALSE;
1351
1352          pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type);
1353          break;
1354
1355       case EVAS_CALLBACK_MULTI_MOVE:
1356       case EVAS_CALLBACK_MOUSE_MOVE:
1357          /* Get first event in first list, this has to be a Mouse Down event  */
1358          /* and verify that user didn't move out of this area before next tap */
1359          pe_list = eina_list_search_unsorted(st->l, compare_pe_device, pe);
1360          if (pe_list)
1361            {
1362               pe_down = eina_list_data_get(pe_list);
1363               if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
1364                 {
1365                    ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
1366                          &st->info, EINA_FALSE);
1367                    consume_event(wd, event_info, event_type, ev_flag);
1368                 }
1369            }
1370          break;
1371
1372       default:
1373          return EINA_FALSE;
1374      }
1375
1376    return EINA_FALSE;
1377 }
1378
1379
1380 /**
1381  * @internal
1382  *
1383  * This function checks all click/tap and double/triple taps
1384  *
1385  * @param obj The gesture-layer object.
1386  * @param pe The recent input event as stored in pe struct.
1387  * @param event_info Original input event pointer.
1388  * @param event_type Type of original input event.
1389  *
1390  * @ingroup Elm_Gesture_Layer
1391  */
1392 static void
1393 _tap_gestures_test(Evas_Object *obj, Pointer_Event *pe,
1394       void *event_info, Evas_Callback_Type event_type)
1395 {  /* Here we fill Recent_Taps struct and fire-up click/tap timers */
1396    Eina_Bool need_timer = EINA_FALSE;
1397    Widget_Data *wd = elm_widget_data_get(obj);
1398    if (!wd) return;
1399
1400    if (!pe)   /* this happens when unhandled event arrived */
1401      return;  /* see _make_pointer_event function */
1402
1403    if (IS_TESTED(ELM_GESTURE_N_TAPS))
1404      need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1405            wd->gesture[ELM_GESTURE_N_TAPS], 1);
1406
1407    if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
1408      need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1409            wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS], 2);
1410
1411    if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
1412      need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1413            wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS], 3);
1414
1415    if ((need_timer) && (!wd->dbl_timeout))
1416      {  /* Set a timer to finish these gestures */
1417         wd->dbl_timeout = ecore_timer_add(0.4, _multi_tap_timeout,
1418               obj);
1419      }
1420 }
1421
1422 /**
1423  * @internal
1424  *
1425  * This function computes center-point for  long-tap gesture
1426  *
1427  * @param st Long Tap gesture info pointer
1428  * @param pe The recent input event as stored in pe struct.
1429  *
1430  * @ingroup Elm_Gesture_Layer
1431  */
1432 static void
1433 _compute_taps_center(Long_Tap_Type *st,
1434       Evas_Coord *x_out, Evas_Coord *y_out, Pointer_Event *pe)
1435 {
1436    if(!eina_list_count(st->touched))
1437      return;
1438
1439    Eina_List *l;
1440    Pointer_Event *p;
1441    Evas_Coord x = 0, y = 0;
1442    EINA_LIST_FOREACH(st->touched, l, p)
1443      {  /* Accumulate all then take avarage */
1444         if (p->device == pe->device)
1445           {  /* This will take care of values coming from MOVE event */
1446              x += pe->x;
1447              y += pe->y;
1448           }
1449         else
1450           {
1451              x += p->x;
1452              y += p->y;
1453           }
1454      }
1455
1456    *x_out = x / eina_list_count(st->touched);
1457    *y_out = y / eina_list_count(st->touched);
1458 }
1459
1460 /**
1461  * @internal
1462  *
1463  * This function checks N long-tap gesture.
1464  *
1465  * @param obj The gesture-layer object.
1466  * @param pe The recent input event as stored in pe struct.
1467  * @param event_info Original input event pointer.
1468  * @param event_type Type of original input event.
1469  * @param g_type what Gesture we are testing.
1470  * @param taps How many click/taps we test for.
1471  *
1472  * @ingroup Elm_Gesture_Layer
1473  */
1474 static void
1475 _n_long_tap_test(Evas_Object *obj, Pointer_Event *pe,
1476       void *event_info, Evas_Callback_Type event_type,
1477       Elm_Gesture_Types g_type)
1478 {  /* Here we fill Recent_Taps struct and fire-up click/tap timers */
1479    Widget_Data *wd = elm_widget_data_get(obj);
1480    if (!wd) return;
1481
1482    if (!pe)   /* this happens when unhandled event arrived */
1483      return;  /* see _make_pointer_event function */
1484    Gesture_Info *gesture = wd->gesture[g_type];
1485    if (!gesture) return;
1486
1487    Long_Tap_Type *st = gesture->data;
1488    if (!st)
1489      {  /* Allocated once on first time */
1490         st = calloc(1, sizeof(Long_Tap_Type));
1491         gesture->data = st;
1492         _n_long_tap_test_reset(gesture);
1493      }
1494
1495    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1496    switch (pe->event_type)
1497      {
1498       case EVAS_CALLBACK_MULTI_DOWN:
1499       case EVAS_CALLBACK_MOUSE_DOWN:
1500          st->touched = _add_touched_device(st->touched, pe);
1501          st->info.n = eina_list_count(st->touched);
1502          if (st->info.n > st->max_touched)
1503            st->max_touched = st->info.n;
1504          else
1505            {  /* User removed finger from touch, then put back - ABORT */
1506               if ((gesture->state == ELM_GESTURE_STATE_START) ||
1507                     (gesture->state == ELM_GESTURE_STATE_MOVE))
1508                 {
1509                    ev_flag =_set_state(gesture, ELM_GESTURE_STATE_ABORT,
1510                          &st->info, EINA_FALSE);
1511                    consume_event(wd, event_info, event_type, ev_flag);
1512                 }
1513            }
1514
1515          if ((pe->device == 0) && (eina_list_count(st->touched) == 1))
1516            {  /* This is the first mouse down we got */
1517               st->info.timestamp = pe->timestamp;
1518
1519               /* To test long tap */
1520               /* When this timer expires, gesture STARTED */
1521               if (!st->timeout)
1522                 st->timeout = ecore_timer_add(wd->long_tap_start_timeout,
1523                       _long_tap_timeout, gesture);
1524            }
1525
1526          consume_event(wd, event_info, event_type, ev_flag);
1527          _compute_taps_center(st, &st->info.x, &st->info.y, pe);
1528          st->center_x = st->info.x;
1529          st->center_y = st->info.y;
1530          break;
1531
1532       case EVAS_CALLBACK_MULTI_UP:
1533       case EVAS_CALLBACK_MOUSE_UP:
1534          st->touched = _remove_touched_device(st->touched, pe);
1535          _compute_taps_center(st, &st->center_x, &st->center_y, pe);
1536          if (st->info.n &&
1537                ((gesture->state == ELM_GESTURE_STATE_START) ||
1538                 (gesture->state == ELM_GESTURE_STATE_MOVE)))
1539            {  /* Report END only for gesture that STARTed */
1540               if (eina_list_count(st->touched) == 0)
1541                 {  /* Report END only at last release event */
1542                    ev_flag =_set_state(gesture, ELM_GESTURE_STATE_END,
1543                          &st->info, EINA_FALSE);
1544                    consume_event(wd, event_info, event_type, ev_flag);
1545                 }
1546            }
1547          else
1548            {  /* Stop test, user lifts finger before long-start */
1549               if (st->timeout) ecore_timer_del(st->timeout);
1550               st->timeout = NULL;
1551               ev_flag =_set_state(gesture, ELM_GESTURE_STATE_ABORT,
1552                     &st->info, EINA_FALSE);
1553               consume_event(wd, event_info, event_type, ev_flag);
1554            }
1555
1556          break;
1557
1558       case EVAS_CALLBACK_MULTI_MOVE:
1559       case EVAS_CALLBACK_MOUSE_MOVE:
1560          if(st->info.n &&
1561                ((gesture->state == ELM_GESTURE_STATE_START) ||
1562                 (gesture->state == ELM_GESTURE_STATE_MOVE)))
1563            {  /* Report MOVE only if STARTED */
1564               Evas_Coord x;
1565               Evas_Coord y;
1566               Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
1567
1568               _compute_taps_center(st, &x, &y, pe);
1569               /* ABORT if user moved fingers out of tap area */
1570 #if defined(DEBUG_GESTURE_LAYER)
1571               printf("%s x,y=(%d,%d) st->info.x,st->info.y=(%d,%d)\n",__func__,x,y,st->info.x,st->info.y);
1572 #endif
1573               if (!_inside(x, y, st->center_x, st->center_y))
1574                 state_to_report = ELM_GESTURE_STATE_ABORT;
1575
1576               /* Report MOVE if gesture started */
1577               ev_flag = _set_state(gesture, state_to_report,
1578                     &st->info, EINA_TRUE);
1579               consume_event(wd, event_info, event_type, ev_flag);
1580            }
1581          break;
1582
1583       default:
1584          return;
1585      }
1586 }
1587
1588 /**
1589  * @internal
1590  *
1591  * This function computes momentum for MOMENTUM, LINE and FLICK gestures
1592  * This momentum value will be sent to widget when gesture is completed.
1593  *
1594  * @param momentum pointer to buffer where we record momentum value.
1595  * @param x1 x coord where user started gesture.
1596  * @param y1 y coord where user started gesture.
1597  * @param x2 x coord where user completed gesture.
1598  * @param y2 y coord where user completed gesture.
1599  * @param t1x timestamp for X, when user started gesture.
1600  * @param t1y timestamp for Y, when user started gesture.
1601  * @param t2  timestamp when user completed gesture.
1602  *
1603  * @ingroup Elm_Gesture_Layer
1604  */
1605 static void
1606 _set_momentum(Elm_Gesture_Momentum_Info *momentum, Evas_Coord x1, Evas_Coord y1,
1607       Evas_Coord x2, Evas_Coord y2, unsigned int t1x, unsigned int t1y,
1608       unsigned int t2)
1609 {
1610    Evas_Coord velx = 0, vely = 0, vel;
1611    Evas_Coord dx = x2 - x1;
1612    Evas_Coord dy = y2 - y1;
1613    int dtx = t2 - t1x;
1614    int dty = t2 - t1y;
1615    if (dtx > 0)
1616      velx = (dx * 1000) / dtx;
1617
1618    if (dty > 0)
1619      vely = (dy * 1000) / dty;
1620
1621    vel = sqrt((velx * velx) + (vely * vely));
1622
1623    if ((_elm_config->thumbscroll_friction > 0.0) &&
1624          (vel > _elm_config->thumbscroll_momentum_threshold))
1625      {  /* report momentum */
1626         momentum->mx = velx;
1627         momentum->my = vely;
1628      }
1629    else
1630      {
1631         momentum->mx = 0;
1632         momentum->my = 0;
1633      }
1634 }
1635
1636 /**
1637  * @internal
1638  *
1639  * This function is used for computing rotation angle (DEG).
1640  *
1641  * @param x1 first finger x location.
1642  * @param y1 first finger y location.
1643  * @param x2 second finger x location.
1644  * @param y2 second finger y location.
1645  *
1646  * @return angle of the line between (x1,y1), (x2,y2) in Radians.
1647  *
1648  * @ingroup Elm_Gesture_Layer
1649  */
1650 static double
1651 get_angle(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
1652 {
1653    double a, xx, yy;
1654    xx = fabs(x2 - x1);
1655    yy = fabs(y2 - y1);
1656
1657    if (((int) xx) && ((int) yy))
1658      {
1659         a = atan(yy / xx);
1660         if (x1 < x2)
1661           {
1662              if (y1 < y2)
1663                {
1664                   return RAD_360DEG - a;
1665                }
1666              else
1667                {
1668                   return (a);
1669                }
1670           }
1671         else
1672           {
1673              if (y1 < y2)
1674                {
1675                   return RAD_180DEG + a;
1676                }
1677              else
1678                {
1679                   return RAD_180DEG - a;
1680                }
1681           }
1682      }
1683
1684    if (((int) xx))
1685      {  /* Horizontal line */
1686         if (x2 < x1)
1687           {
1688              return RAD_180DEG;
1689           }
1690         else
1691           {
1692              return 0.0;
1693           }
1694      }
1695
1696    /* Vertical line */
1697    if (y2 < y1)
1698      {
1699         return RAD_90DEG;
1700      }
1701    else
1702      {
1703         return RAD_270DEG;
1704      }
1705 }
1706
1707 /**
1708  * @internal
1709  *
1710  * This function is used for computing the magnitude and direction
1711  * of vector between two points.
1712  *
1713  * @param x1 first finger x location.
1714  * @param y1 first finger y location.
1715  * @param x2 second finger x location.
1716  * @param y2 second finger y location.
1717  * @param l length computed (output)
1718  * @param a angle computed (output)
1719  *
1720  * @ingroup Elm_Gesture_Layer
1721  */
1722 static void
1723 get_vector(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2,
1724       Evas_Coord *l, double *a)
1725 {
1726    Evas_Coord xx, yy;
1727    xx = x2 - x1;
1728    yy = y2 - y1;
1729    *l = (Evas_Coord) sqrt(xx*xx + yy*yy);
1730    *a = get_angle(x1, y1, x2, y2);
1731 }
1732
1733 static int
1734 _get_direction(Evas_Coord x1, Evas_Coord x2)
1735 {
1736    if (x1 == x2)
1737      return 0;
1738    else if (x2 < x1)
1739      return -1;
1740    else
1741      return 1;
1742 }
1743 /**
1744  * @internal
1745  *
1746  * This function tests momentum gesture.
1747  * @param obj The gesture-layer object.
1748  * @param pe The recent input event as stored in pe struct.
1749  * @param event_info recent input event.
1750  * @param event_type recent event type.
1751  * @param g_type what Gesture we are testing.
1752  *
1753  * @ingroup Elm_Gesture_Layer
1754  */
1755 static void
1756 _momentum_test(Evas_Object *obj, Pointer_Event *pe,
1757       void *event_info, Evas_Callback_Type event_type,
1758       Elm_Gesture_Types g_type)
1759 {
1760    Widget_Data *wd = elm_widget_data_get(obj);
1761    if (!wd) return;
1762    Gesture_Info *gesture = wd->gesture[g_type];
1763    if (!gesture ) return;
1764
1765    Momentum_Type *st = gesture->data;
1766    Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
1767    if (!st)
1768      {  /* Allocated once on first time */
1769         st = calloc(1, sizeof(Momentum_Type));
1770         gesture->data = st;
1771         _momentum_test_reset(gesture);
1772      }
1773
1774    if (!pe)
1775      return;
1776
1777    /* First make avarage of all touched devices to determine center point */
1778    Eina_List *l;
1779    Pointer_Event *p;
1780    Pointer_Event pe_local = *pe;  /* Copy pe event info to local */
1781    int cnt = 1;    /* We start counter counting current pe event */
1782    EINA_LIST_FOREACH(wd->touched, l, p)
1783       if (p->device != pe_local.device)
1784         {
1785            pe_local.x += p->x;
1786            pe_local.y += p->y;
1787            cnt++;
1788         }
1789
1790
1791    /* Compute avarage to get center point */
1792    pe_local.x /= cnt;
1793    pe_local.y /= cnt;
1794
1795    /* If user added finger - reset gesture */
1796    if ((st->n_fingers) && (st->n_fingers < cnt))
1797      state_to_report = ELM_GESTURE_STATE_ABORT;
1798
1799    st->n_fingers = cnt;
1800
1801    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1802    switch (event_type)
1803      {
1804       case EVAS_CALLBACK_MOUSE_DOWN:
1805       case EVAS_CALLBACK_MULTI_DOWN:
1806       case EVAS_CALLBACK_MOUSE_MOVE:
1807       case EVAS_CALLBACK_MULTI_MOVE:
1808          if (!st->t_st_x)
1809            {
1810               if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
1811                     (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
1812                     (wd->glayer_continues_enable)) /* start also on MOVE */
1813                 {  /* We start on MOVE when cont-enabled only */
1814                    st->line_st.x = st->line_end.x = pe_local.x;
1815                    st->line_st.y = st->line_end.y = pe_local.y;
1816                    st->t_st_x = st->t_st_y = st->t_end = pe_local.timestamp;
1817                    st->xdir = st->ydir = 0;
1818                    st->info.x2 = st->info.x1 = pe_local.x;
1819                    st->info.y2 = st->info.y1 = pe_local.y;
1820                    st->info.tx = st->info.ty = pe_local.timestamp;
1821                    ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
1822                          &st->info, EINA_FALSE);
1823                    consume_event(wd, event_info, event_type, ev_flag);
1824                 }
1825
1826               return;
1827            }
1828
1829
1830          /* ABORT gesture if got DOWN or MOVE event after UP+timeout */
1831          if ((st->t_up) &&
1832          ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp))
1833            state_to_report = ELM_GESTURE_STATE_ABORT;
1834
1835          if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
1836            {  /*  Too long of a wait, reset all values */
1837               st->line_st.x = pe_local.x;
1838               st->line_st.y = pe_local.y;
1839               st->t_st_y = st->t_st_x = pe_local.timestamp;
1840               st->info.tx = st->t_st_x;
1841               st->info.ty = st->t_st_y;
1842               st->xdir = st->ydir = 0;
1843            }
1844          else
1845            {
1846               int xdir, ydir;
1847               xdir = _get_direction(st->line_st.x, pe_local.x);
1848               ydir = _get_direction(st->line_st.y, pe_local.y);
1849               if (!xdir || (xdir == (-st->xdir)))
1850                 {
1851                    st->line_st.x = st->line_end.x;
1852                    st->info.tx = st->t_st_x = st->t_end;
1853                    st->xdir = xdir;
1854                 }
1855
1856               if (!ydir || (ydir == (-st->ydir)))
1857                 {
1858                    st->line_st.y = st->line_end.y;
1859                    st->info.ty = st->t_st_y = st->t_end;
1860                    st->ydir = ydir;
1861                 }
1862            }
1863
1864          st->info.x2 = st->line_end.x = pe_local.x;
1865          st->info.y2 = st->line_end.y = pe_local.y;
1866          st->t_end = pe_local.timestamp;
1867          _set_momentum(&st->info, st->line_st.x, st->line_st.y, pe_local.x, pe_local.y,
1868                st->t_st_x, st->t_st_y, pe_local.timestamp);
1869          ev_flag = _set_state(gesture, state_to_report, &st->info,
1870                EINA_TRUE);
1871          consume_event(wd, event_info, event_type, ev_flag);
1872          break;
1873
1874
1875       case EVAS_CALLBACK_MOUSE_UP:
1876       case EVAS_CALLBACK_MULTI_UP:
1877          st->t_up = pe_local.timestamp;       /* Record recent up event time */
1878          if ((cnt > 1) ||     /* Ignore if more fingers touch surface        */
1879                (!st->t_st_x)) /* IGNORE if info was cleared, long press,move */
1880            return;
1881
1882          if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
1883            {  /* Too long of a wait, reset all values */
1884               st->line_st.x = pe_local.x;
1885               st->line_st.y = pe_local.y;
1886               st->t_st_y = st->t_st_x = pe_local.timestamp;
1887               st->xdir = st->ydir = 0;
1888            }
1889
1890          st->info.x2 = pe_local.x;
1891          st->info.y2 = pe_local.y;
1892          st->line_end.x = pe_local.x;
1893          st->line_end.y = pe_local.y;
1894          st->t_end = pe_local.timestamp;
1895
1896          _set_momentum(&st->info, st->line_st.x, st->line_st.y, pe_local.x, pe_local.y,
1897                st->t_st_x, st->t_st_y, pe_local.timestamp);
1898
1899          ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END, &st->info,
1900                EINA_FALSE);
1901          consume_event(wd, event_info, event_type, ev_flag);
1902          return;
1903
1904       default:
1905          return;
1906      }
1907 }
1908
1909 static int
1910 compare_line_device(const void *data1, const void *data2)
1911 {  /* Compare device component of line struct */
1912    const Line_Data *ln1 = data1;
1913    const int *device = data2;
1914
1915    if (ln1->t_st) /* Compare only with lines that started */
1916      return (ln1->device - (*device));
1917
1918    return (-1);
1919 }
1920
1921 /**
1922  * @internal
1923  *
1924  * This function construct line struct from input.
1925  * @param info pointer to store line momentum.
1926  * @param st line info to store input data.
1927  * @param pe The recent input event as stored in pe struct.
1928  *
1929  * @ingroup Elm_Gesture_Layer
1930  */
1931 static Eina_Bool
1932 _single_line_process(Elm_Gesture_Line_Info *info, Line_Data *st,
1933       Pointer_Event *pe, Evas_Callback_Type event_type)
1934 {  /* Record events and set momentum for line pointed by st */
1935    if (!pe)
1936      return EINA_FALSE;
1937
1938    switch (event_type)
1939      {
1940       case EVAS_CALLBACK_MOUSE_DOWN:
1941       case EVAS_CALLBACK_MOUSE_MOVE:
1942       case EVAS_CALLBACK_MULTI_DOWN:
1943       case EVAS_CALLBACK_MULTI_MOVE:
1944          if (!st->t_st)
1945            {  /* This happens only when line starts */
1946               st->line_st.x = pe->x;
1947               st->line_st.y = pe->y;
1948               st->t_st = pe->timestamp;
1949               st->device = pe->device;
1950               info->momentum.x1 = pe->x;
1951               info->momentum.y1 = pe->y;
1952               info->momentum.tx = pe->timestamp;
1953               info->momentum.ty = pe->timestamp;
1954
1955               return EINA_TRUE;
1956            }
1957
1958          break;
1959
1960       case EVAS_CALLBACK_MOUSE_UP:
1961       case EVAS_CALLBACK_MULTI_UP:
1962          /* IGNORE if line info was cleared, like long press, move */
1963          if (!st->t_st)
1964            return EINA_FALSE;
1965
1966          st->line_end.x = pe->x;
1967          st->line_end.y = pe->y;
1968          st->t_end = pe->timestamp;
1969          break;
1970
1971       default:
1972          return EINA_FALSE;
1973      }
1974
1975    if (!st->t_st)
1976      {
1977         _line_data_reset(st);
1978         return EINA_FALSE;
1979      }
1980
1981    info->momentum.x2 = pe->x;
1982    info->momentum.y2 = pe->y;
1983    _set_momentum(&info->momentum, st->line_st.x, st->line_st.y, pe->x, pe->y,
1984          st->t_st, st->t_st, pe->timestamp);
1985
1986    return EINA_TRUE;
1987 }
1988
1989 /**
1990  * @internal
1991  *
1992  * This function test for (n) line gesture.
1993  * @param obj The gesture-layer object.
1994  * @param pe The recent input event as stored in pe struct.
1995  * @param event_info Original input event pointer.
1996  * @param event_type Type of original input event.
1997  * @param g_type what Gesture we are testing.
1998  *
1999  * @ingroup Elm_Gesture_Layer
2000  */
2001 static void
2002 _n_line_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
2003       Evas_Callback_Type event_type, Elm_Gesture_Types g_type)
2004 {
2005    if (!pe)
2006      return;
2007    Widget_Data *wd = elm_widget_data_get(obj);
2008    if (!wd) return;
2009    Gesture_Info *gesture = wd->gesture[g_type];
2010    if (!gesture ) return;
2011
2012    Line_Type *st = gesture->data;
2013    if (!st)
2014      {
2015         st = calloc(1, sizeof(Line_Type));
2016         gesture->data = st;
2017      }
2018
2019    Line_Data *line = NULL;
2020    Eina_List *list = st->list;
2021    unsigned cnt = eina_list_count(list);
2022
2023    if (cnt)
2024      {  /* list is not empty, locate this device on list */
2025         line = (Line_Data *) eina_list_search_unsorted(st->list,
2026               compare_line_device, &pe->device);
2027      }
2028
2029    if (!line)
2030      {  /* List is empty or device not found, new line-struct on START only */
2031         if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2032               (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
2033               ((wd->glayer_continues_enable) && /* START on MOVE also */
2034                ((event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
2035                 (event_type == EVAS_CALLBACK_MULTI_MOVE))))
2036           {  /* Allocate new item on START only */
2037              line = calloc(1, sizeof(Line_Data));
2038              _line_data_reset(line);
2039              list = eina_list_append(list, line);
2040              st->list = list;
2041           }
2042      }
2043
2044    if (!line)  /* This may happen on MOVE that comes before DOWN      */
2045      return;   /* No line-struct to work with, can't continue testing */
2046
2047    if (_single_line_process(&st->info, line, pe, event_type)) /* update st with input */
2048      consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
2049
2050    /* Get direction and magnitude of the line */
2051    double angle;
2052    get_vector(line->line_st.x, line->line_st.y, pe->x, pe->y,
2053          &line->line_length, &angle);
2054
2055    /* These are used later to compare lines length */
2056    Evas_Coord shortest_line_len = line->line_length;
2057    Evas_Coord longest_line_len = line->line_length;
2058    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2059
2060    /* Now update line-state */
2061    if (line->t_st)
2062      {  /* Analyze line only if line started */
2063         if (line->line_angle >= 0.0)
2064           {  /* if line direction was set, we test if broke tolerance */
2065              double a = fabs(angle - line->line_angle);
2066
2067              double d = (tan(a)) * line->line_length; /* Distance from line */
2068 #if defined(DEBUG_GESTURE_LAYER)
2069              printf("%s a=<%f> d=<%f>\n", __func__, (a * 57.295779513), d);
2070 #endif
2071              if ((d > wd->line_distance_tolerance) || (a > wd->line_angular_tolerance))
2072                {  /* Broke tolerance: abort line and start a new one */
2073                   ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2074                         &st->info, EINA_FALSE);
2075                   consume_event(wd, event_info, event_type, ev_flag);
2076                   return;
2077                }
2078
2079              if (wd->glayer_continues_enable)
2080                {  /* We may finish line if momentum is zero */
2081                   /* This is for continues-gesture */
2082                   if ((!st->info.momentum.mx) && (!st->info.momentum.my))
2083                     {  /* Finish line on zero momentum for continues gesture */
2084                        line->line_end.x = pe->x;
2085                        line->line_end.y = pe->y;
2086                        line->t_end = pe->timestamp;
2087                     }
2088                }
2089           }
2090         else
2091           {  /* Record the line angle as it broke minimum length for line */
2092              if (line->line_length >= wd->line_min_length)
2093                st->info.angle = line->line_angle = angle;
2094           }
2095
2096
2097         if (line->t_end)
2098           {
2099              if (line->line_angle < 0.0)
2100                { /* it's not a line, too short more close to a tap */
2101                   ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2102                         &st->info, EINA_FALSE);
2103                   consume_event(wd, event_info, event_type, ev_flag);
2104                   return;
2105                }
2106           }
2107      }
2108
2109    /* Count how many lines already started / ended */
2110    int started = 0;
2111    int ended = 0;
2112    unsigned int tm_start = pe->timestamp;
2113    unsigned int tm_end = pe->timestamp;
2114    Eina_List *l;
2115    Line_Data *t_line;
2116    double base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
2117    Eina_Bool lines_parallel = EINA_TRUE;
2118    EINA_LIST_FOREACH(list, l, t_line)
2119      {
2120         if (base_angle < 0)
2121           base_angle = t_line->line_angle;
2122         else
2123           {
2124              if (t_line->line_angle >= 0)
2125                {  /* Compare angle only with lines with direction defined */
2126                   if (fabs(base_angle - t_line->line_angle) >
2127                         wd->line_angular_tolerance)
2128                     lines_parallel = EINA_FALSE;
2129                }
2130           }
2131
2132         if (t_line->line_length)
2133           {  /* update only if this line is used */
2134              if (shortest_line_len > t_line->line_length)
2135                shortest_line_len = t_line->line_length;
2136
2137              if (longest_line_len < t_line->line_length)
2138                longest_line_len = t_line->line_length;
2139           }
2140
2141         if (t_line->t_st)
2142           {
2143              started++;
2144              if (t_line->t_st < tm_start)
2145                tm_start = t_line->t_st;
2146           }
2147
2148         if (t_line->t_end)
2149           {
2150              ended++;
2151              if (t_line->t_end < tm_end)
2152                tm_end = t_line->t_end;
2153           }
2154      }
2155
2156    st->info.n = started;
2157
2158
2159    if (ended &&
2160          ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2161           (event_type == EVAS_CALLBACK_MULTI_DOWN)))
2162      {  /* user lift one finger then starts again without line-end - ABORT */
2163         ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2164               EINA_FALSE);
2165         consume_event(wd, event_info, event_type, ev_flag);
2166         return;
2167      }
2168
2169    if (!lines_parallel)
2170      { /* Lines are NOT at same direction, abort this gesture */
2171         ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2172               EINA_FALSE);
2173         consume_event(wd, event_info, event_type, ev_flag);
2174         return;
2175      }
2176
2177
2178    /* We report ABORT if lines length are NOT matching when fingers are up */
2179    if ((longest_line_len - shortest_line_len) > (elm_finger_size_get()*2))
2180      {
2181         ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2182               EINA_FALSE);
2183         consume_event(wd, event_info, event_type, ev_flag);
2184         return;
2185      }
2186
2187    if ((g_type == ELM_GESTURE_N_FLICKS) && ((tm_end - tm_start) > wd->flick_time_limit_ms))
2188      {  /* We consider FLICK as a fast line.ABORT if take too long to finish */
2189         ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2190               EINA_FALSE);
2191         consume_event(wd, event_info, event_type, ev_flag);
2192         return;
2193      }
2194
2195    switch (event_type)
2196      {
2197       case EVAS_CALLBACK_MOUSE_UP:
2198       case EVAS_CALLBACK_MULTI_UP:
2199          if ((started) && (started == ended))
2200            {
2201               ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2202                     &st->info, EINA_FALSE);
2203               consume_event(wd, event_info, event_type, ev_flag);
2204            }
2205
2206          return;
2207
2208       case EVAS_CALLBACK_MOUSE_DOWN:
2209       case EVAS_CALLBACK_MULTI_DOWN:
2210       case EVAS_CALLBACK_MOUSE_MOVE:
2211       case EVAS_CALLBACK_MULTI_MOVE:
2212          if (started)
2213            {
2214               if (wd->glayer_continues_enable && (started == ended))
2215                 {  /* For continues gesture */
2216                    ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2217                          &st->info, EINA_FALSE);
2218                    consume_event(wd, event_info, event_type, ev_flag);
2219                 }
2220               else
2221                 {  /* When continues, may START on MOVE event too */
2222                    Elm_Gesture_State s = ELM_GESTURE_STATE_MOVE;
2223
2224                    /* This happens when: on n > 1 lines then one finger up */
2225                    /* caused abort, then put finger down.                  */
2226                    /* This will stop line from starting again.             */
2227                    /* Number of lines, MUST match touched-device in list   */
2228                    if ((!wd->glayer_continues_enable) &&
2229                          (eina_list_count(st->list) < eina_list_count(wd->touched)))
2230                      s = ELM_GESTURE_STATE_ABORT;
2231
2232                    if (gesture->state == ELM_GESTURE_STATE_UNDEFINED)
2233                      s = ELM_GESTURE_STATE_START;
2234
2235                    ev_flag = _set_state(gesture, s, &st->info, EINA_TRUE);
2236                    consume_event(wd, event_info, event_type, ev_flag);
2237                 }
2238            }
2239          break;
2240
2241       default:
2242          return;  /* Unhandeld event type */
2243      }
2244 }
2245
2246 /**
2247  * @internal
2248  *
2249  * This function is used to check if rotation gesture started.
2250  * @param st Contains current rotation values from user input.
2251  * @return TRUE/FALSE if we need to set rotation START.
2252  *
2253  * @ingroup Elm_Gesture_Layer
2254  */
2255 static Eina_Bool
2256 rotation_broke_tolerance(Rotate_Type *st)
2257 {
2258    if (st->info.base_angle < 0)
2259      return EINA_FALSE; /* Angle has to be computed first */
2260
2261    if (st->rotate_angular_tolerance < 0)
2262      return EINA_TRUE;
2263
2264    double low  = st->info.base_angle - st->rotate_angular_tolerance;
2265    double high = st->info.base_angle + st->rotate_angular_tolerance;
2266    double t = st->info.angle;
2267
2268    if (low < 0)
2269      {
2270         low += RAD_180DEG;
2271         high += RAD_180DEG;
2272
2273         if (t < RAD_180DEG)
2274           t += RAD_180DEG;
2275         else
2276           t -= RAD_180DEG;
2277      }
2278
2279    if (high > RAD_360DEG)
2280      {
2281         low -= RAD_180DEG;
2282         high -= RAD_180DEG;
2283
2284         if (t < RAD_180DEG)
2285           t += RAD_180DEG;
2286         else
2287           t -= RAD_180DEG;
2288      }
2289
2290 #if defined(DEBUG_GESTURE_LAYER)
2291    printf("%s angle=<%f> low=<%f> high=<%f>\n", __func__, t, low, high);
2292 #endif
2293    if ((t < low) || (t > high))
2294      {  /* This marks that roation action has started */
2295         st->rotate_angular_tolerance = ELM_GESTURE_NEGATIVE_ANGLE;
2296         st->info.base_angle = st->info.angle; /* Avoid jump in angle value */
2297         return EINA_TRUE;
2298      }
2299
2300    return EINA_FALSE;
2301 }
2302
2303 /**
2304  * @internal
2305  *
2306  * This function is used for computing the gap between fingers.
2307  * It returns the length and center point between fingers.
2308  *
2309  * @param x1 first finger x location.
2310  * @param y1 first finger y location.
2311  * @param x2 second finger x location.
2312  * @param y2 second finger y location.
2313  * @param x  Gets center point x cord (output)
2314  * @param y  Gets center point y cord (output)
2315  *
2316  * @return length of the line between (x1,y1), (x2,y2) in pixels.
2317  *
2318  * @ingroup Elm_Gesture_Layer
2319  */
2320 static Evas_Coord
2321 get_finger_gap_length(Evas_Coord x1, Evas_Coord y1, Evas_Coord x2,
2322       Evas_Coord y2, Evas_Coord *x, Evas_Coord *y)
2323 {
2324    double a, b, xx, yy, gap;
2325    xx = fabs(x2 - x1);
2326    yy = fabs(y2 - y1);
2327    gap = sqrt(xx*xx + yy*yy);
2328
2329    /* START - Compute zoom center point */
2330    /* The triangle defined as follows:
2331     *             B
2332     *           / |
2333     *          /  |
2334     *     gap /   | a
2335     *        /    |
2336     *       A-----C
2337     *          b
2338     * http://en.wikipedia.org/wiki/Trigonometric_functions
2339     *************************************/
2340    if (((int) xx) && ((int) yy))
2341      {
2342         double A = atan((yy / xx));
2343 #if defined(DEBUG_GESTURE_LAYER)
2344         printf("xx=<%f> yy=<%f> A=<%f>\n", xx, yy, A);
2345 #endif
2346         a = (Evas_Coord) ((gap / 2) * sin(A));
2347         b = (Evas_Coord) ((gap / 2) * cos(A));
2348         *x = (Evas_Coord) ((x2 > x1) ? (x1 + b) : (x2 + b));
2349         *y = (Evas_Coord) ((y2 > y1) ? (y1 + a) : (y2 + a));
2350      }
2351    else
2352      {
2353         if ((int) xx)
2354           {  /* horiz line, take half width */
2355 #if defined(DEBUG_GESTURE_LAYER)
2356              printf("==== HORIZ ====\n");
2357 #endif
2358              *x = (Evas_Coord) (xx / 2);
2359              *y = (Evas_Coord) (y1);
2360           }
2361
2362         if ((int) yy)
2363           {  /* vert line, take half width */
2364 #if defined(DEBUG_GESTURE_LAYER)
2365              printf("==== VERT ====\n");
2366 #endif
2367              *x = (Evas_Coord) (x1);
2368              *y = (Evas_Coord) (yy / 2);
2369           }
2370      }
2371    /* END   - Compute zoom center point */
2372
2373    return (Evas_Coord) gap;
2374 }
2375
2376 /**
2377  * @internal
2378  *
2379  * This function is used for computing zoom value.
2380  *
2381  * @param st Pointer to zoom data based on user input.
2382  * @param x1 first finger x location.
2383  * @param y1 first finger y location.
2384  * @param x2 second finger x location.
2385  * @param y2 second finger y location.
2386  * @param factor zoom-factor, used to determine how fast zoom works.
2387  *
2388  * @return zoom value, when 1.0 means no zoom, 0.5 half size...
2389  *
2390  * @ingroup Elm_Gesture_Layer
2391  */
2392 /* FIXME change float to double */
2393 static double
2394 compute_zoom(Zoom_Type *st, Evas_Coord x1, Evas_Coord y1, unsigned int tm1,
2395       Evas_Coord x2, Evas_Coord y2, unsigned int tm2, double zoom_finger_factor)
2396 {
2397    double rt = 1.0;
2398    Evas_Coord diam = get_finger_gap_length(x1, y1, x2, y2,
2399          &st->info.x, &st->info.y);
2400
2401    st->info.radius = diam / 2;
2402
2403    if (!st->zoom_base)
2404      {
2405         st->zoom_base = diam;
2406         return st->info.zoom;
2407      }
2408
2409    if (st->zoom_distance_tolerance)
2410      {  /* zoom tolerance <> ZERO, means zoom action NOT started yet */
2411         if (diam < (st->zoom_base - st->zoom_distance_tolerance))
2412           {  /* avoid jump with zoom value when break tolerance */
2413              st->zoom_base -= st->zoom_distance_tolerance;
2414              st->zoom_distance_tolerance = 0;
2415           }
2416
2417         if (diam > (st->zoom_base + st->zoom_distance_tolerance))
2418           {  /* avoid jump with zoom value when break tolerance */
2419              st->zoom_base += st->zoom_distance_tolerance;
2420              st->zoom_distance_tolerance = 0;
2421           }
2422
2423         return rt;
2424      }
2425
2426    /* We use factor only on the difference between gap-base   */
2427    /* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */
2428    rt = ((1.0) + ((((float) diam - (float) st->zoom_base) /
2429                (float) st->zoom_base) * zoom_finger_factor));
2430
2431 #if 0
2432    /* Momentum: zoom per second: (NOT YET SUPPORTED) */
2433    st->info.momentum = (((rt - 1.0) * 1000) / (tm2 - tm1));
2434 #else
2435    (void) tm1;
2436    (void) tm2;
2437 #endif
2438    return rt;
2439 }
2440
2441 /**
2442  * @internal
2443  *
2444  * This function handles zoom with mouse wheel.
2445  * thats a combination of wheel + CTRL key.
2446  * @param obj The gesture-layer object.
2447  * @param event_info Original input event pointer.
2448  * @param event_type Type of original input event.
2449  * @param g_type what Gesture we are testing.
2450  *
2451  * @ingroup Elm_Gesture_Layer
2452  */
2453 static void
2454 _zoom_with_wheel_test(Evas_Object *obj, void *event_info,
2455       Evas_Callback_Type event_type, Elm_Gesture_Types g_type)
2456 {
2457    Widget_Data *wd = elm_widget_data_get(obj);
2458    if (!wd) return;
2459    if (!wd->gesture[g_type]) return;
2460
2461    Gesture_Info *gesture_zoom = wd->gesture[g_type];
2462    Zoom_Type *st = gesture_zoom->data;
2463    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2464    if (!st)
2465      {  /* Allocated once on first time, used for zoom intermediate data */
2466         st = calloc(1, sizeof(Zoom_Type));
2467         gesture_zoom->data = st;
2468         _zoom_test_reset(gesture_zoom);
2469      }
2470
2471    switch (event_type)
2472      {
2473       case EVAS_CALLBACK_KEY_UP:
2474            {
2475               Evas_Event_Key_Up *p = event_info;
2476               if ((!strcmp(p->keyname, "Control_L")) ||
2477                     (!strcmp(p->keyname, "Control_R")))
2478                 {  /* Test if we ended a zoom gesture when releasing CTRL */
2479                    if ((st->zoom_wheel) &&
2480                          ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
2481                           (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
2482                      {  /* User released CTRL after zooming */
2483                         ev_flag = _set_state(gesture_zoom,
2484                               ELM_GESTURE_STATE_END, &st->info, EINA_FALSE);
2485                         consume_event(wd, event_info, event_type, ev_flag);
2486
2487                         return;
2488                      }
2489                 }
2490               break;
2491            }
2492
2493       case EVAS_CALLBACK_MOUSE_WHEEL:
2494            {
2495               Eina_Bool force;
2496               Elm_Gesture_State s;
2497               if (!evas_key_modifier_is_set(
2498                        ((Evas_Event_Mouse_Wheel *) event_info)->modifiers,
2499                        "Control"))
2500                 {  /* if using wheel witout CTRL after starting zoom */
2501                    if ((st->zoom_wheel) &&
2502                          ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
2503                           (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
2504                      {
2505                         ev_flag = _set_state(gesture_zoom,
2506                               ELM_GESTURE_STATE_END, &st->info, EINA_FALSE);
2507                         consume_event(wd, event_info, event_type, ev_flag);
2508
2509                         return;
2510                      }
2511                    else
2512                      return; /* Ignore mouse-wheel without control */
2513                 }
2514
2515               /* Using mouse wheel with CTRL for zoom */
2516               if (st->zoom_wheel || (st->zoom_distance_tolerance == 0))
2517                 {  /* when (zoom_wheel == NULL) and (zoom_distance_tolerance == 0)
2518                       we continue a zoom gesture */
2519                    force = EINA_TRUE;
2520                    s = ELM_GESTURE_STATE_MOVE;
2521                 }
2522               else
2523                 {  /* On first wheel event, report START */
2524                    Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
2525                             evas_object_evas_get(wd->target), "Control");
2526                    force = EINA_FALSE;
2527                    s = ELM_GESTURE_STATE_START;
2528                    if (!evas_object_key_grab(wd->target, "Control_L", mask, 0, EINA_FALSE))
2529                      ERR("Failed to Grabbed CTRL_L");
2530                    if (!evas_object_key_grab(wd->target, "Control_R", mask, 0, EINA_FALSE))
2531                      ERR("Failed to Grabbed CTRL_R");
2532                 }
2533
2534               st->zoom_distance_tolerance = 0; /* Cancel tolerance */
2535               st->zoom_wheel = (Evas_Event_Mouse_Wheel *) event_info;
2536               st->info.x  = st->zoom_wheel->canvas.x;
2537               st->info.y  = st->zoom_wheel->canvas.y;
2538
2539               if (st->zoom_wheel->z < 0) /* zoom in */
2540                 st->info.zoom += (wd->zoom_finger_factor * wd->zoom_wheel_factor);
2541
2542               if (st->zoom_wheel->z > 0) /* zoom out */
2543                 st->info.zoom -= (wd->zoom_finger_factor * wd->zoom_wheel_factor);
2544
2545               if (st->info.zoom < 0.0)
2546                 st->info.zoom = 0.0;
2547
2548               ev_flag = _set_state(gesture_zoom, s, &st->info, force);
2549               consume_event(wd, event_info, event_type, ev_flag);
2550               break;
2551            }
2552
2553       default:
2554            return;
2555      }
2556 }
2557
2558 /**
2559  * @internal
2560  *
2561  * This function is used to test zoom gesture.
2562  * user may combine zoom, rotation together.
2563  * so its possible that both will be detected from input.
2564  * (both are two-finger movement-oriented gestures)
2565  *
2566  * @param obj The gesture-layer object.
2567  * @param event_info Pointer to recent input event.
2568  * @param event_type Recent input event type.
2569  * @param g_type what Gesture we are testing.
2570  *
2571  * @ingroup Elm_Gesture_Layer
2572  */
2573 static void
2574 _zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
2575       Evas_Callback_Type event_type, Elm_Gesture_Types g_type)
2576 {
2577    if (!pe)
2578      return;
2579    Widget_Data *wd = elm_widget_data_get(obj);
2580    if (!wd) return;
2581    if (!wd->gesture[g_type]) return;
2582
2583    Gesture_Info *gesture_zoom = wd->gesture[g_type];
2584    Zoom_Type *st = gesture_zoom->data;
2585
2586    if (!st)
2587      {  /* Allocated once on first time, used for zoom data */
2588         st = calloc(1, sizeof(Zoom_Type));
2589         gesture_zoom->data = st;
2590         _zoom_test_reset(gesture_zoom);
2591      }
2592
2593
2594    /* Start - new zoom testing, letting all fingers start */
2595    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2596    switch (event_type)
2597      {
2598       case EVAS_CALLBACK_MOUSE_MOVE:
2599       case EVAS_CALLBACK_MULTI_MOVE:
2600          /* if non-continues mode and gesture NOT started, ignore MOVE */
2601          if ((!wd->glayer_continues_enable) &&
2602                (!st->zoom_st.timestamp))
2603            return;
2604
2605       case EVAS_CALLBACK_MOUSE_DOWN:
2606       case EVAS_CALLBACK_MULTI_DOWN:
2607            {  /* Here we take care of zoom-start and zoom move */
2608               Eina_List *l;
2609               Pointer_Event *p;
2610
2611               if(eina_list_count(wd->touched) > 2)
2612                 {  /* Process zoom only when 2 fingers on surface */
2613                    ev_flag = _set_state(gesture_zoom,
2614                          ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2615                    consume_event(wd, event_info, event_type, ev_flag);
2616
2617                    return;
2618                 }
2619
2620               if (!st->zoom_st.timestamp)
2621                 {  /* Now scan touched-devices list and find other finger */
2622                    EINA_LIST_FOREACH(wd->touched, l, p)
2623                      {  /* Device of other finger <> pe device */
2624                         if (p->device != pe->device)
2625                           break;
2626                      }
2627
2628                    if (!p)  /* Single finger on touch */
2629                         return;
2630
2631                    /* Record down fingers */
2632                    consume_event(wd, event_info, event_type, ev_flag);
2633                    memcpy(&st->zoom_st, pe, sizeof(Pointer_Event));
2634                    memcpy(&st->zoom_st1, p, sizeof(Pointer_Event));
2635
2636                    /* Set mv field as well to be ready for MOVE events  */
2637                    memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
2638                    memcpy(&st->zoom_mv1, p, sizeof(Pointer_Event));
2639
2640                    /* Here we have zoom_st, zoom_st1 set, report START  */
2641                    /* Set zoom-base after BOTH down events  recorded    */
2642                    /* Compute length of line between fingers zoom start */
2643                    st->info.zoom = 1.0;
2644                    st->zoom_base = get_finger_gap_length(st->zoom_st1.x,
2645                          st->zoom_st1.y, st->zoom_st.x,  st->zoom_st.y,
2646                          &st->info.x, &st->info.y);
2647
2648                    st->info.radius = st->zoom_base / 2;
2649
2650                    if ((gesture_zoom->state != ELM_GESTURE_STATE_START) &&
2651                          (gesture_zoom->state != ELM_GESTURE_STATE_MOVE))
2652                      {  /* zoom started with mouse-wheel, don't report twice */
2653                         ev_flag = _set_state(gesture_zoom,
2654                               ELM_GESTURE_STATE_START, &st->info, EINA_FALSE);
2655                         consume_event(wd, event_info, event_type, ev_flag);
2656                      }
2657
2658                    return;  /* Zoom started */
2659                 }  /* End of ZOOM_START handling */
2660
2661
2662               /* if we got here, we have (exacally) two fingers on surfce */
2663               /* we also after START, report MOVE */
2664               /* First detect which finger moved  */
2665               if (pe->device == st->zoom_mv.device)
2666                 memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
2667               else if (pe->device == st->zoom_mv1.device)
2668                 memcpy(&st->zoom_mv1, pe, sizeof(Pointer_Event));
2669
2670               /* Compute change in zoom as fingers move */
2671                 st->info.zoom = compute_zoom(st,
2672                       st->zoom_mv.x, st->zoom_mv.y, st->zoom_mv.timestamp,
2673                       st->zoom_mv1.x, st->zoom_mv1.y, st->zoom_mv1.timestamp,
2674                       wd->zoom_finger_factor);
2675
2676               if (!st->zoom_distance_tolerance)
2677                 {  /* Zoom broke tolerance, report move */
2678                    double d = st->info.zoom - st->next_step;
2679                    if (d < 0.0)
2680                      d = (-d);
2681
2682                    if (d >= wd->zoom_step)
2683                      {  /* Report move in steps */
2684                         st->next_step = st->info.zoom;
2685
2686                         ev_flag = _set_state(gesture_zoom,
2687                               ELM_GESTURE_STATE_MOVE,
2688                               &st->info, EINA_TRUE);
2689                         consume_event(wd, event_info, event_type, ev_flag);
2690                      }
2691                 }  /* End of ZOOM_MOVE handling */
2692
2693               return;
2694            }
2695
2696       case EVAS_CALLBACK_MOUSE_UP:
2697       case EVAS_CALLBACK_MULTI_UP:
2698          /* Reset timestamp of finger-up.This is used later
2699             by _zoom_test_reset() to retain finger-down data */
2700          consume_event(wd, event_info, event_type, ev_flag);
2701          if (((st->zoom_wheel) || (st->zoom_base)) &&
2702                (st->zoom_distance_tolerance == 0))
2703            {
2704               ev_flag = _set_state(gesture_zoom, ELM_GESTURE_STATE_END,
2705                     &st->info, EINA_FALSE);
2706               consume_event(wd, event_info, event_type, ev_flag);
2707
2708               return;
2709            }
2710
2711          /* if we got here not a ZOOM */
2712          if (gesture_zoom->state != ELM_GESTURE_STATE_UNDEFINED)
2713            {  /* Must be != undefined, if gesture started */
2714               ev_flag = _set_state(gesture_zoom,
2715                     ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2716               consume_event(wd, event_info, event_type, ev_flag);
2717            }
2718
2719          _zoom_test_reset(gesture_zoom);
2720
2721          return;
2722
2723       default:
2724          return;
2725        }
2726 }
2727
2728 static void
2729 _get_rotate_properties(Rotate_Type *st,
2730       Evas_Coord x1, Evas_Coord y1, unsigned int tm1,
2731       Evas_Coord x2, Evas_Coord y2, unsigned int tm2,
2732       double *angle)
2733 {
2734    st->info.radius = get_finger_gap_length(x1, y1, x2, y2,
2735          &st->info.x, &st->info.y) / 2;
2736
2737    *angle = get_angle(x1, y1, x2, y2);
2738 #if 0 /* (NOT YET SUPPORTED) */
2739    if (angle == &st->info.angle)
2740      {  /* Compute momentum: TODO: bug when breaking 0, 360 values */
2741         st->info.momentum = (((*angle) - st->info.base_angle) /
2742            (fabs(tm2 - tm1))) * 1000;
2743      }
2744    else
2745      st->info.momentum = 0;
2746 #else
2747    (void) tm1;
2748    (void) tm2;
2749 #endif
2750 }
2751
2752 /**
2753  * @internal
2754  *
2755  * This function is used to test rotation gesture.
2756  * user may combine zoom, rotation together.
2757  * so its possible that both will be detected from input.
2758  * (both are two-finger movement-oriented gestures)
2759  *
2760  * @param obj The gesture-layer object.
2761  * @param event_info Pointer to recent input event.
2762  * @param event_type Recent input event type.
2763  * @param g_type what Gesture we are testing.
2764  *
2765  * @ingroup Elm_Gesture_Layer
2766  */
2767 static void
2768 _rotate_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
2769       Evas_Callback_Type event_type, Elm_Gesture_Types g_type)
2770 {
2771    if (!pe)
2772      return;
2773
2774    Widget_Data *wd = elm_widget_data_get(obj);
2775    if (!wd) return;
2776    if (!wd->gesture[g_type]) return;
2777
2778    Gesture_Info *gesture = wd->gesture[g_type];
2779    Rotate_Type *st = gesture->data;
2780    if (gesture)
2781    {
2782       st = gesture->data;
2783       if (!st)
2784         {  /* Allocated once on first time */
2785            st = calloc(1, sizeof(Rotate_Type));
2786            gesture->data = st;
2787            _rotate_test_reset(gesture);
2788         }
2789    }
2790
2791    Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2792    switch (event_type)
2793      {
2794       case EVAS_CALLBACK_MOUSE_MOVE:
2795       case EVAS_CALLBACK_MULTI_MOVE:
2796          /* if non-continues mode and gesture NOT started, ignore MOVE */
2797          if ((!wd->glayer_continues_enable) &&
2798                (!st->rotate_st.timestamp))
2799            return;
2800
2801       case EVAS_CALLBACK_MOUSE_DOWN:
2802       case EVAS_CALLBACK_MULTI_DOWN:
2803            {  /* Here we take care of rotate-start and rotate move */
2804               Eina_List *l;
2805               Pointer_Event *p;
2806
2807               if(eina_list_count(wd->touched) > 2)
2808                 {  /* Process rotate only when 2 fingers on surface */
2809                    ev_flag = _set_state(gesture,
2810                          ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2811                    consume_event(wd, event_info, event_type, ev_flag);
2812
2813                    return;
2814                 }
2815
2816               if (!st->rotate_st.timestamp)
2817                 {  /* Now scan touched-devices list and find other finger */
2818                    EINA_LIST_FOREACH(wd->touched, l, p)
2819                      {  /* Device of other finger <> pe device */
2820                         if (p->device != pe->device)
2821                           break;
2822                      }
2823
2824                    if (!p)
2825                         return;  /* Single finger on touch */
2826
2827                    /* Record down fingers */
2828                    consume_event(wd, event_info, event_type, ev_flag);
2829                    memcpy(&st->rotate_st, pe, sizeof(Pointer_Event));
2830                    memcpy(&st->rotate_st1, p, sizeof(Pointer_Event));
2831
2832                    /* Set mv field as well to be ready for MOVE events  */
2833                    memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
2834                    memcpy(&st->rotate_mv1, p, sizeof(Pointer_Event));
2835
2836                    /* Here we have rotate_st, rotate_st1 set, report START  */
2837                    /* Set rotate-base after BOTH down events  recorded    */
2838                    /* Compute length of line between fingers rotate start */
2839                    _get_rotate_properties(st,
2840                          st->rotate_st.x, st->rotate_st.y,
2841                          st->rotate_st.timestamp,
2842                          st->rotate_st1.x, st->rotate_st1.y,
2843                          st->rotate_st1.timestamp, &st->info.base_angle);
2844
2845                    ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
2846                          &st->info, EINA_FALSE);
2847                    consume_event(wd, event_info, event_type, ev_flag);
2848
2849                    return;  /* Rotate started */
2850                 }  /* End of ROTATE_START handling */
2851
2852
2853               /* if we got here, we have (exacally) two fingers on surfce */
2854               /* we also after START, report MOVE */
2855               /* First detect which finger moved  */
2856               if (pe->device == st->rotate_mv.device)
2857                 memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
2858               else if (pe->device == st->rotate_mv1.device)
2859                 memcpy(&st->rotate_mv1, pe, sizeof(Pointer_Event));
2860
2861               /* Compute change in rotate as fingers move */
2862               _get_rotate_properties(st,
2863                     st->rotate_mv.x, st->rotate_mv.y,
2864                     st->rotate_mv.timestamp,
2865                     st->rotate_mv1.x, st->rotate_mv1.y,
2866                     st->rotate_mv1.timestamp, &st->info.angle);
2867
2868               if (rotation_broke_tolerance(st))
2869                 {  /* Rotation broke tolerance, report move */
2870                    double d = st->info.angle - st->next_step;
2871                    if (d < 0.0)
2872                      d = (-d);
2873
2874                    if (d >= wd->rotate_step)
2875                      {  /* Report move in steps */
2876                         st->next_step = st->info.angle;
2877
2878                         ev_flag = _set_state(gesture,
2879                               ELM_GESTURE_STATE_MOVE, &st->info, EINA_TRUE);
2880                         consume_event(wd, event_info, event_type, ev_flag);
2881                      }
2882                 }  /* End of ROTATE_MOVE handling */
2883
2884               return;
2885            }
2886
2887       case EVAS_CALLBACK_MOUSE_UP:
2888       case EVAS_CALLBACK_MULTI_UP:
2889            consume_event(wd, event_info, event_type, ev_flag);
2890            /* Reset timestamp of finger-up.This is used later
2891               by rotate_test_reset() to retain finger-down data */
2892            if (st->rotate_angular_tolerance < 0)
2893              {
2894                 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2895                       &st->info, EINA_FALSE);
2896                 consume_event(wd, event_info, event_type, ev_flag);
2897
2898                 return;
2899              }
2900
2901            if (gesture->state != ELM_GESTURE_STATE_UNDEFINED)
2902              {  /* Must be != undefined, if gesture started */
2903                 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2904                       &st->info, EINA_FALSE);
2905                 consume_event(wd, event_info, event_type, ev_flag);
2906              }
2907
2908            _rotate_test_reset(gesture);
2909            return;
2910
2911       default:
2912          return;
2913        }
2914 }
2915
2916 /**
2917  * @internal
2918  *
2919  * This function is used to save input events in an abstract struct
2920  * to be used later by getsure-testing functions.
2921  *
2922  * @param data The gesture-layer object.
2923  * @param event_info Pointer to recent input event.
2924  * @param event_type Recent input event type.
2925  * @param pe The abstract data-struct (output).
2926  *
2927  * @ingroup Elm_Gesture_Layer
2928  */
2929 static Eina_Bool
2930 _make_pointer_event(void *data, void *event_info,
2931       Evas_Callback_Type event_type, Pointer_Event *pe)
2932 {
2933    Widget_Data *wd = elm_widget_data_get(data);
2934    if (!wd) return EINA_FALSE;
2935
2936    memset(pe, '\0', sizeof(*pe));
2937    switch (event_type)
2938      {
2939       case EVAS_CALLBACK_MOUSE_DOWN:
2940            pe->x = ((Evas_Event_Mouse_Down *) event_info)->canvas.x;
2941            pe->y = ((Evas_Event_Mouse_Down *) event_info)->canvas.y;
2942            pe->timestamp = ((Evas_Event_Mouse_Down *) event_info)->timestamp;
2943            pe->device = ELM_MOUSE_DEVICE;
2944            break;
2945
2946       case EVAS_CALLBACK_MOUSE_UP:
2947            pe->x = ((Evas_Event_Mouse_Up *) event_info)->canvas.x;
2948            pe->y = ((Evas_Event_Mouse_Up *) event_info)->canvas.y;
2949            pe->timestamp = ((Evas_Event_Mouse_Up *) event_info)->timestamp;
2950            pe->device = ELM_MOUSE_DEVICE;
2951            break;
2952
2953       case EVAS_CALLBACK_MOUSE_MOVE:
2954            pe->x = ((Evas_Event_Mouse_Move *) event_info)->cur.canvas.x;
2955            pe->y = ((Evas_Event_Mouse_Move *) event_info)->cur.canvas.y;
2956            pe->timestamp = ((Evas_Event_Mouse_Move *) event_info)->timestamp;
2957            pe->device = ELM_MOUSE_DEVICE;
2958            break;
2959
2960       case EVAS_CALLBACK_MULTI_DOWN:
2961            pe->x = ((Evas_Event_Multi_Down *) event_info)->canvas.x;
2962            pe->y = ((Evas_Event_Multi_Down *) event_info)->canvas.y;
2963            pe->timestamp = ((Evas_Event_Multi_Down *) event_info)->timestamp;
2964            pe->device = ((Evas_Event_Multi_Down *) event_info)->device;
2965            break;
2966
2967       case EVAS_CALLBACK_MULTI_UP:
2968            pe->x = ((Evas_Event_Multi_Up *) event_info)->canvas.x;
2969            pe->y = ((Evas_Event_Multi_Up *) event_info)->canvas.y;
2970            pe->timestamp = ((Evas_Event_Multi_Up *) event_info)->timestamp;
2971            pe->device = ((Evas_Event_Multi_Up *) event_info)->device;
2972            break;
2973
2974       case EVAS_CALLBACK_MULTI_MOVE:
2975            pe->x = ((Evas_Event_Multi_Move *) event_info)->cur.canvas.x;
2976            pe->y = ((Evas_Event_Multi_Move *) event_info)->cur.canvas.y;
2977            pe->timestamp = ((Evas_Event_Multi_Move *) event_info)->timestamp;
2978            pe->device = ((Evas_Event_Multi_Move *) event_info)->device;
2979            break;
2980
2981       default:
2982            return EINA_FALSE;
2983      }
2984
2985    pe->event_type = event_type;
2986    return EINA_TRUE;
2987 }
2988
2989 /**
2990  * @internal
2991  *
2992  * This function restartes line, flick, zoom and rotate gestures
2993  * when gesture-layer continues-gestures enabled.
2994  * Example of continues-gesture:
2995  * When doing a line, user stops moving finger but keeps fingers on touch.
2996  * This will cause line-end, then as user continues moving his finger
2997  * it re-starts line gesture.
2998  * When continue mode is disabled, user has to lift finger from touch
2999  * to end a gesture. Them touch-again to start a new one.
3000  *
3001  * @param data The gesture-layer object.
3002  * @param wd gesture layer widget data.
3003  * @param states_reset flag that marks gestures were reset in history clear.
3004  *
3005  * @ingroup Elm_Gesture_Layer
3006  */
3007 void continues_gestures_restart(void *data, Eina_Bool states_reset)
3008 {
3009    Widget_Data *wd = elm_widget_data_get(data);
3010    if (!wd) return;
3011
3012    /* Run through events to restart gestures */
3013    Gesture_Info *g;
3014    Eina_Bool n_lines, n_flicks, zoom, rotate;
3015    /* We turn-on flag for finished, aborted, not-started gestures */
3016    g = wd->gesture[ELM_GESTURE_N_LINES];
3017    n_lines = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3018          && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3019    if (n_lines)
3020      {
3021         _line_test_reset(wd->gesture[ELM_GESTURE_N_LINES]);
3022         _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3023         SET_TEST_BIT(g);
3024      }
3025
3026    g = wd->gesture[ELM_GESTURE_N_FLICKS];
3027    n_flicks = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3028          && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3029    if (n_flicks)
3030      {
3031         _line_test_reset(wd->gesture[ELM_GESTURE_N_FLICKS]);
3032         _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3033         SET_TEST_BIT(g);
3034      }
3035
3036    g = wd->gesture[ELM_GESTURE_ZOOM];
3037    zoom = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3038          && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3039    if (zoom)
3040      {
3041         _zoom_test_reset(wd->gesture[ELM_GESTURE_ZOOM]);
3042         _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3043         SET_TEST_BIT(g);
3044      }
3045
3046    g = wd->gesture[ELM_GESTURE_ROTATE];
3047    rotate = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3048          && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3049    if (rotate)
3050      {
3051         _rotate_test_reset(wd->gesture[ELM_GESTURE_ROTATE]);
3052         _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3053         SET_TEST_BIT(g);
3054      }
3055 }
3056
3057 /**
3058  * @internal
3059  *
3060  * This function the core-function where input handling is done.
3061  * Here we get user input and stream it to gesture testing.
3062  * We notify user about any gestures with new state:
3063  * Valid states are:
3064  * START - gesture started.
3065  * MOVE - gesture is ongoing.
3066  * END - gesture was completed.
3067  * ABORT - gesture was aborted after START, MOVE (will NOT be completed)
3068  *
3069  * We also check if a gesture was detected, then reset event history
3070  * If no gestures were found we reset gesture test flag
3071  * after streaming event-history to widget.
3072  * (stream to the widget all events not consumed as a gesture)
3073  *
3074  * @param data The gesture-layer object.
3075  * @param event_info Pointer to recent input event.
3076  * @param event_type Recent input event type.
3077  *
3078  * @ingroup Elm_Gesture_Layer
3079  */
3080 static void
3081 _event_process(void *data, Evas_Object *obj __UNUSED__,
3082       void *event_info, Evas_Callback_Type event_type)
3083 {
3084    Pointer_Event _pe;
3085    Pointer_Event *pe = NULL;
3086    Widget_Data *wd = elm_widget_data_get(data);
3087    if (!wd) return;
3088
3089 #if defined(DEBUG_GESTURE_LAYER)
3090    int i;
3091    Gesture_Info *g;
3092    printf("Gesture | State | is tested\n");
3093    for(i = ELM_GESTURE_N_TAPS; i < ELM_GESTURE_LAST; i++)
3094      {
3095         g = wd->gesture[i];
3096         if(g)
3097           printf("   %d       %d       %d\n", i, g->state, g->test);
3098      }
3099 #endif
3100
3101    /* Start testing candidate gesture from here */
3102    if (_make_pointer_event(data, event_info, event_type, &_pe))
3103      pe = &_pe;
3104
3105    if (IS_TESTED(ELM_GESTURE_N_LONG_TAPS))
3106      _n_long_tap_test(data, pe, event_info, event_type,
3107            ELM_GESTURE_N_LONG_TAPS);
3108
3109    /* This takes care of single, double and tripple tap */
3110    _tap_gestures_test(data, pe, event_info, event_type);
3111
3112    if (IS_TESTED(ELM_GESTURE_MOMENTUM))
3113      _momentum_test(data, pe, event_info, event_type,
3114            ELM_GESTURE_MOMENTUM);
3115
3116    if (IS_TESTED(ELM_GESTURE_N_LINES))
3117      _n_line_test(data, pe, event_info, event_type, ELM_GESTURE_N_LINES);
3118
3119    if (IS_TESTED(ELM_GESTURE_N_FLICKS))
3120      _n_line_test(data, pe, event_info, event_type, ELM_GESTURE_N_FLICKS);
3121
3122    if (IS_TESTED(ELM_GESTURE_ZOOM))
3123      _zoom_test(data, pe, event_info, event_type, ELM_GESTURE_ZOOM);
3124
3125    if (IS_TESTED(ELM_GESTURE_ZOOM))
3126      _zoom_with_wheel_test(data, event_info, event_type, ELM_GESTURE_ZOOM);
3127
3128    if (IS_TESTED(ELM_GESTURE_ROTATE))
3129      _rotate_test(data, pe, event_info, event_type, ELM_GESTURE_ROTATE);
3130
3131    if (_get_event_flag(event_info, event_type) & EVAS_EVENT_FLAG_ON_HOLD)
3132      _event_history_add(data, event_info, event_type);
3133    else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
3134          (event_type == EVAS_CALLBACK_MULTI_UP))
3135      {
3136         Eina_List *pending = _device_is_pending(wd->pending, event_info, event_type);
3137         if (pending)
3138           {
3139              consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_ON_HOLD);
3140              _event_history_add(data, event_info, event_type);
3141           }
3142      }
3143
3144    /* Log event to restart gestures */
3145    wd->recent_device_event = _add_recent_device_event(wd->recent_device_event, &_pe);
3146
3147    /* we maintain list of touched devices              */
3148    /* We also use move to track current device x.y pos */
3149    if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
3150          (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
3151          (event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
3152          (event_type == EVAS_CALLBACK_MULTI_MOVE))
3153      {
3154         wd->touched = _add_touched_device(wd->touched, pe);
3155      }
3156    else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
3157          (event_type == EVAS_CALLBACK_MULTI_UP))
3158      {
3159         wd->touched = _remove_touched_device(wd->touched, pe);
3160      }
3161
3162    /* Report current states and clear history if needed */
3163    Eina_Bool states_reset = _clear_if_finished(data);
3164    if (wd->glayer_continues_enable)
3165      continues_gestures_restart(data, states_reset);
3166 }
3167
3168
3169 /**
3170  * For all _mouse_* / multi_* functions wethen send this event to
3171  * _event_process function.
3172  *
3173  * @param data The gesture-layer object.
3174  * @param event_info Pointer to recent input event.
3175  *
3176  * @ingroup Elm_Gesture_Layer
3177  */
3178 static void
3179 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3180       void *event_info)
3181 {
3182    Widget_Data *wd = elm_widget_data_get(data);
3183    if (!wd) return;
3184    if (((Evas_Event_Mouse_Down *) event_info)->button != 1)
3185      return; /* We only process left-click at the moment */
3186
3187    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_DOWN);
3188 }
3189
3190 static void
3191 _mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3192       void *event_info)
3193 {
3194    Widget_Data *wd = elm_widget_data_get(data);
3195    if (!wd) return;
3196
3197    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
3198 }
3199
3200 static void
3201 _key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3202       void *event_info)
3203 {
3204    Widget_Data *wd = elm_widget_data_get(data);
3205    if (!wd) return;
3206
3207    _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
3208 }
3209
3210 static void
3211 _key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3212       void *event_info)
3213 {
3214    Widget_Data *wd = elm_widget_data_get(data);
3215    if (!wd) return;
3216
3217    _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
3218 }
3219
3220 static void
3221 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3222       void *event_info)
3223 {
3224    Widget_Data *wd = elm_widget_data_get(data);
3225    if (!wd) return;
3226
3227    if (((Evas_Event_Mouse_Up *) event_info)->button != 1)
3228      return; /* We only process left-click at the moment */
3229
3230    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_UP);
3231 }
3232
3233 static void
3234 _mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3235       void *event_info)
3236 {
3237    Widget_Data *wd = elm_widget_data_get(data);
3238    if (!wd) return;
3239
3240    _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
3241 }
3242
3243 static void
3244 _multi_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3245       void *event_info)
3246 {
3247    Widget_Data *wd = elm_widget_data_get(data);
3248    if (!wd) return;
3249
3250    _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_DOWN);
3251 }
3252
3253 static void
3254 _multi_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3255       void *event_info)
3256 {
3257    Widget_Data *wd = elm_widget_data_get(data);
3258    if (!wd) return;
3259
3260    _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_MOVE);
3261 }
3262
3263 static void
3264 _multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3265       void *event_info)
3266 {
3267    Widget_Data *wd = elm_widget_data_get(data);
3268    if (!wd) return;
3269
3270    _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
3271 }
3272
3273 EAPI Eina_Bool
3274 elm_gesture_layer_hold_events_get(Evas_Object *obj)
3275 {
3276    Widget_Data *wd = elm_widget_data_get(obj);
3277    if (!wd) return EINA_FALSE;
3278
3279    return !wd->repeat_events;
3280 }
3281
3282 EAPI void
3283 elm_gesture_layer_hold_events_set(Evas_Object *obj, Eina_Bool r)
3284 {
3285    Widget_Data *wd = elm_widget_data_get(obj);
3286    if (!wd) return;
3287
3288    wd->repeat_events = !r;
3289 }
3290
3291 EAPI void
3292 elm_gesture_layer_zoom_step_set(Evas_Object *obj, double s)
3293 {
3294    Widget_Data *wd = elm_widget_data_get(obj);
3295    if (!wd) return;
3296
3297    if (s < 0.0)
3298      return;
3299
3300    wd->zoom_step = s;
3301 }
3302
3303 EAPI void
3304 elm_gesture_layer_rotate_step_set(Evas_Object *obj, double s)
3305 {
3306    Widget_Data *wd = elm_widget_data_get(obj);
3307    if (!wd) return;
3308
3309    if (s < 0.0)
3310      return;
3311
3312    wd->rotate_step = s;
3313 }
3314
3315 EAPI Eina_Bool
3316 elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *t)
3317 {
3318    Widget_Data *wd = elm_widget_data_get(obj);
3319    if (!wd) return EINA_FALSE;
3320
3321    if (!t)
3322      return EINA_FALSE;
3323
3324    /* if was attached before, unregister callbacks first */
3325    if (wd->target)
3326      _unregister_callbacks(obj);
3327
3328    wd->target = t;
3329
3330    _register_callbacks(obj);
3331    return EINA_TRUE;
3332 }
3333
3334 EAPI void
3335 elm_gesture_layer_cb_set(Evas_Object *obj, Elm_Gesture_Types idx,
3336       Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
3337 {
3338    Widget_Data *wd = elm_widget_data_get(obj);
3339    Gesture_Info *p;
3340    if (!wd) return;
3341
3342    if (!wd->gesture[idx])
3343      wd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
3344    if (!wd->gesture[idx]) return;
3345
3346    p = wd->gesture[idx];
3347    p->obj = obj;
3348    p->g_type = idx;
3349    p->fn[cb_type].cb = cb;
3350    p->fn[cb_type].user_data = data;
3351    p->state = ELM_GESTURE_STATE_UNDEFINED;
3352    SET_TEST_BIT(p);
3353 }
3354
3355 static void
3356 _disable_hook(Evas_Object *obj)
3357 {
3358    if (elm_widget_disabled_get(obj))
3359      _unregister_callbacks(obj);
3360    else
3361      _register_callbacks(obj);
3362 }
3363
3364 EAPI Evas_Object *
3365 elm_gesture_layer_add(Evas_Object *parent)
3366 {
3367    Evas_Object *obj;
3368    Evas *e;
3369    Widget_Data *wd;
3370
3371    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
3372
3373    wd = ELM_NEW(Widget_Data);
3374    e = evas_object_evas_get(parent);
3375    if (!e) return NULL;
3376    obj = elm_widget_add(e);
3377    ELM_SET_WIDTYPE(widtype, "gesture_layer");
3378    elm_widget_type_set(obj, "gesture_layer");
3379    elm_widget_sub_object_add(parent, obj);
3380    elm_widget_data_set(obj, wd);
3381    elm_widget_del_hook_set(obj, _del_hook);
3382    elm_widget_disable_hook_set(obj, _disable_hook);
3383
3384    wd->target = NULL;
3385    wd->line_min_length =_elm_config->glayer_line_min_length * elm_finger_size_get();
3386    wd->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance * elm_finger_size_get();
3387    wd->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance * elm_finger_size_get();
3388    wd->zoom_finger_factor = _elm_config->glayer_zoom_finger_factor;
3389    wd->zoom_wheel_factor = _elm_config->glayer_zoom_wheel_factor; /* mouse wheel zoom steps */
3390    wd->rotate_angular_tolerance = _elm_config->glayer_rotate_angular_tolerance;
3391    wd->line_angular_tolerance = _elm_config->glayer_line_angular_tolerance;
3392    wd->flick_time_limit_ms = _elm_config->glayer_flick_time_limit_ms;
3393    wd->long_tap_start_timeout = _elm_config->glayer_long_tap_start_timeout;
3394    wd->repeat_events = EINA_TRUE;
3395    wd->glayer_continues_enable = _elm_config->glayer_continues_enable;
3396
3397 #if defined(DEBUG_GESTURE_LAYER)
3398    printf("size of Gestures = <%d>\n", sizeof(wd->gesture));
3399    printf("initial values:\n\tzoom_finger_factor=<%f>\n\tzoom_distance_tolerance=<%d>\n\tline_min_length=<%d>\n\tline_distance_tolerance=<%d>\n\tzoom_wheel_factor=<%f>\n\trotate_angular_tolerance=<%f>\n\twd->line_angular_tolerance=<%f>\n\twd->flick_time_limit_ms=<%d>\n\twd->long_tap_start_timeout=<%f>\n\twd->zoom_step=<%f>\n\twd->rotate_step=<%f>\n\twd->glayer_continues_enable=<%d>\n ", wd->zoom_finger_factor, wd->zoom_distance_tolerance, wd->line_min_length, wd->line_distance_tolerance, wd->zoom_wheel_factor, wd->rotate_angular_tolerance, wd->line_angular_tolerance, wd->flick_time_limit_ms, wd->long_tap_start_timeout, wd->zoom_step, wd->rotate_step, wd->glayer_continues_enable);
3400 #endif
3401    memset(wd->gesture, 0, sizeof(wd->gesture));
3402
3403    return obj;
3404 }