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