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