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