1 #include "efl_canvas_gesture_private.h"
2 
3 #define MY_CLASS     EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS
4 
5 #define TAP_TIME_OUT 0.33
6 
7 EOLIAN static const Efl_Class *
_efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_type_get(const Eo * obj EINA_UNUSED,Efl_Canvas_Gesture_Recognizer_Double_Tap_Data * pd EINA_UNUSED)8 _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_type_get(const Eo *obj EINA_UNUSED, Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd EINA_UNUSED)
9 {
10    return EFL_CANVAS_GESTURE_DOUBLE_TAP_CLASS;
11 }
12 
13 EOLIAN static void
_efl_canvas_gesture_recognizer_double_tap_efl_object_destructor(Eo * obj,Efl_Canvas_Gesture_Recognizer_Double_Tap_Data * pd)14 _efl_canvas_gesture_recognizer_double_tap_efl_object_destructor(Eo *obj,
15                                                                 Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd)
16 {
17    if (pd->timeout)
18      ecore_timer_del(pd->timeout);
19 
20    efl_destructor(efl_super(obj, MY_CLASS));
21 }
22 
23 static Eina_Bool
_tap_timeout_cb(void * data)24 _tap_timeout_cb(void *data)
25 {
26    Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd;
27 
28    pd = efl_data_scope_get(data, EFL_CANVAS_GESTURE_RECOGNIZER_DOUBLE_TAP_CLASS);
29 
30    efl_gesture_state_set(pd->gesture, EFL_GESTURE_STATE_CANCELED);
31    efl_event_callback_call(pd->target, EFL_EVENT_GESTURE_DOUBLE_TAP, pd->gesture);
32 
33    efl_gesture_manager_recognizer_cleanup(efl_provider_find(data, EFL_CANVAS_GESTURE_MANAGER_CLASS), data,
34      pd->target);
35 
36    pd->timeout = NULL;
37    pd->tap_count = 0;
38 
39    return ECORE_CALLBACK_CANCEL;
40 }
41 
42 EOLIAN static Efl_Canvas_Gesture_Recognizer_Result
_efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recognize(Eo * obj,Efl_Canvas_Gesture_Recognizer_Double_Tap_Data * pd,Efl_Canvas_Gesture * gesture,Efl_Object * watched,Efl_Canvas_Gesture_Touch * event)43 _efl_canvas_gesture_recognizer_double_tap_efl_canvas_gesture_recognizer_recognize(Eo *obj,
44                                                                                   Efl_Canvas_Gesture_Recognizer_Double_Tap_Data *pd,
45                                                                                   Efl_Canvas_Gesture *gesture, Efl_Object *watched,
46                                                                                   Efl_Canvas_Gesture_Touch *event)
47 {
48    double length, start_timeout = pd->start_timeout;
49    double timeout = TAP_TIME_OUT;
50    Eina_Position2D pos;
51    Eina_Vector2 dist;
52    Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
53 
54    pd->target = watched;
55    pd->gesture = gesture;
56 
57    if (!EINA_DBL_NONZERO(start_timeout))
58      {
59         double time;
60         Eina_Value *val = _recognizer_config_get(obj, "glayer_double_tap_timeout");
61 
62         if (val)
63           {
64              eina_value_get(val, &time);
65              pd->start_timeout = timeout = time;
66           }
67      }
68    else
69      timeout = start_timeout;
70 
71    switch (efl_gesture_touch_state_get(event))
72      {
73       case EFL_GESTURE_TOUCH_STATE_BEGIN:
74       {
75          pos = efl_gesture_touch_start_point_get(event);
76          efl_gesture_hotspot_set(gesture, pos);
77 
78          if (pd->timeout)
79            ecore_timer_reset(pd->timeout);
80          else
81            pd->timeout = ecore_timer_add(timeout, _tap_timeout_cb, obj);
82 
83          result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
84 
85          break;
86       }
87 
88       case EFL_GESTURE_TOUCH_STATE_UPDATE:
89       {
90         /* multi-touch */
91         if (efl_gesture_touch_current_data_get(event)->action == EFL_POINTER_ACTION_DOWN)
92           {
93              /* a second finger was pressed at the same time-ish as the first: combine into same event */
94              if (efl_gesture_touch_current_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
95                {
96                   result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
97                   break;
98                }
99           }
100          result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
101 
102          if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
103              !_event_multi_touch_get(event))
104            {
105               dist = efl_gesture_touch_distance(event, efl_gesture_touch_current_data_get(event)->id);
106               length = fabs(dist.x) + fabs(dist.y);
107 
108               if (length > pd->finger_size)
109                 {
110                    if (pd->timeout)
111                      {
112                         ecore_timer_del(pd->timeout);
113                         pd->timeout = NULL;
114                      }
115 
116                    result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
117 
118                    pd->tap_count = 0;
119                 }
120            }
121 
122          break;
123       }
124 
125       case EFL_GESTURE_TOUCH_STATE_END:
126       {
127          if (efl_gesture_state_get(gesture) != EFL_GESTURE_STATE_NONE &&
128              !_event_multi_touch_get(event))
129            {
130               if (efl_gesture_touch_previous_data_get(event))
131                 {
132                    Efl_Pointer_Action prev_act = efl_gesture_touch_previous_data_get(event)->action;
133                    /* multi-touch */
134                    if ((prev_act == EFL_POINTER_ACTION_UP) || (prev_act == EFL_POINTER_ACTION_CANCEL))
135                      {
136                         /* a second finger was pressed at the same time-ish as the first: combine into same event */
137                         if (efl_gesture_touch_current_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
138                           {
139                              result = EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
140                              break;
141                           }
142                      }
143                 }
144               dist = efl_gesture_touch_distance(event, efl_gesture_touch_current_data_get(event)->id);
145               length = fabs(dist.x) + fabs(dist.y);
146 
147               if (length <= pd->finger_size)
148                 {
149                    pd->tap_count++;
150                    if (pd->tap_count == 1)
151                      {
152                         if (pd->timeout)
153                           ecore_timer_reset(pd->timeout);
154 
155                         result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
156                      }
157                    else
158                      {
159                         if (pd->timeout)
160                           {
161                              ecore_timer_del(pd->timeout);
162                              pd->timeout = NULL;
163                           }
164 
165                         if (efl_gesture_touch_state_get(event) == EFL_GESTURE_TOUCH_STATE_END)
166                           result = EFL_GESTURE_RECOGNIZER_RESULT_FINISH;
167                         else
168                           result = EFL_GESTURE_RECOGNIZER_RESULT_TRIGGER;
169 
170                         pd->tap_count = 0;
171                      }
172                 }
173               else
174                 {
175                    if (pd->timeout)
176                      {
177                         ecore_timer_del(pd->timeout);
178                         pd->timeout = NULL;
179                      }
180 
181                    result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
182 
183                    pd->tap_count = 0;
184                 }
185            }
186 
187          break;
188       }
189 
190       default:
191 
192         break;
193      }
194 
195    return result;
196 }
197 
198 #include "efl_canvas_gesture_recognizer_double_tap.eo.c"
199