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