summaryrefslogtreecommitdiff
path: root/src/lib/evas/gesture
diff options
context:
space:
mode:
authorsmohanty <smohantty@gmail.com>2017-09-19 17:11:31 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-10-19 10:33:12 +0900
commit9da7a7f0d23f0240a1af721fd771667b9e0de3ba (patch)
tree88ef1773666b537fb21670cef2139dedc06cb921 /src/lib/evas/gesture
parent4b997e89e5609e07c4ea88516495db34abc39f7d (diff)
evas/gesture: Added gesture manager implementaion.
Diffstat (limited to 'src/lib/evas/gesture')
-rw-r--r--src/lib/evas/gesture/efl_gesture_manager.c350
1 files changed, 350 insertions, 0 deletions
diff --git a/src/lib/evas/gesture/efl_gesture_manager.c b/src/lib/evas/gesture/efl_gesture_manager.c
new file mode 100644
index 0000000..5936ded
--- /dev/null
+++ b/src/lib/evas/gesture/efl_gesture_manager.c
@@ -0,0 +1,350 @@
1#include "efl_gesture_private.h"
2
3#define MY_CLASS EFL_GESTURE_MANAGER_CLASS
4
5typedef struct _Object_Gesture
6{
7 Eo *object;
8 const Efl_Event_Description *type;
9 Efl_Gesture *gesture;
10 Efl_Gesture_Recognizer *recognizer;
11}Object_Gesture;
12
13typedef struct _Efl_Gesture_Manager_Data
14{
15 // keeps track of all the gesture request for a particular target
16 Eina_Hash *m_gesture_contex; // (*target, *event_desc)
17 // keeps all the event directed to this particular object from touch_begin till touch_end
18 Eina_Hash *m_object_events; // (*target, *efl_gesture_touch)
19 // keeps all the recognizer registered to gesture manager
20 Eina_Hash *m_recognizers; // (*gesture_type, *recognizer)
21 // keeps track of all current object gestures.
22 Eina_List *m_object_gestures; //(List of *object_gesture)
23 // lazy deletion of gestures
24 Eina_List *m_gestures_to_delete;
25
26 Eina_Hash *m_config;
27} Efl_Gesture_Manager_Data;
28
29static void _cleanup_cached_gestures(Efl_Gesture_Manager_Data *pd,
30 Eo *target, const Efl_Event_Description *type);
31static Efl_Gesture*
32_get_state(Efl_Gesture_Manager_Data *pd, Eo *target,
33 Efl_Gesture_Recognizer *recognizer, const Efl_Event_Description *type);
34
35static void
36_cleanup_object(Eina_List *list)
37{
38 Eina_List *l;
39 Eo *obj;
40
41 if (!list) return;
42
43 EINA_LIST_FOREACH(list, l, obj)
44 efl_del(obj);
45
46 eina_list_free(list);
47}
48
49static void
50_hash_free_cb(Eo *obj)
51{
52 efl_del(obj);
53}
54
55EOLIAN static Efl_Object *
56_efl_gesture_manager_efl_object_constructor(Eo *obj, Efl_Gesture_Manager_Data *pd EINA_UNUSED)
57{
58 obj = efl_constructor(efl_super(obj, MY_CLASS));
59
60 pd->m_recognizers = eina_hash_pointer_new(EINA_FREE_CB(_hash_free_cb));
61 pd->m_gesture_contex = eina_hash_pointer_new(NULL);
62 pd->m_object_events = eina_hash_pointer_new(EINA_FREE_CB(_hash_free_cb));
63 pd->m_object_gestures = NULL;
64 pd->m_gestures_to_delete = NULL;
65
66 pd->m_config = eina_hash_string_superfast_new(EINA_FREE_CB(eina_value_free));
67
68 efl_gesture_manager_recognizer_register(obj, efl_add(EFL_GESTURE_RECOGNIZER_TAP_CLASS, obj));
69 return obj;
70}
71
72
73EOLIAN static Eina_Value *
74_efl_gesture_manager_config_get(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd, const char *name)
75{
76 return eina_hash_find(pd->m_config, name);
77}
78
79EOLIAN static void
80_efl_gesture_manager_config_set(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd, const char *name, Eina_Value *value)
81{
82 Eina_Value *v = eina_value_new(eina_value_type_get(value));
83 eina_value_copy(value, v);
84 eina_hash_add(pd->m_config, name, v);
85}
86
87EOLIAN static void
88_efl_gesture_manager_efl_object_destructor(Eo *obj, Efl_Gesture_Manager_Data *pd EINA_UNUSED)
89{
90 eina_hash_free(pd->m_recognizers);
91 eina_hash_free(pd->m_gesture_contex);
92 eina_hash_free(pd->m_object_events);
93 _cleanup_object(pd->m_gestures_to_delete);
94 efl_destructor(efl_super(obj, MY_CLASS));
95}
96
97void
98_efl_gesture_manager_callback_add_hook(Eo *obj, Eo *target, const Efl_Event_Description *type)
99{
100 Efl_Gesture_Manager_Data *pd = efl_data_scope_get(obj, MY_CLASS);
101 // if there is a recognizer registered for that event then add it to the gesture context
102 Efl_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
103 if (recognizer)
104 {
105 // add it to the gesture context.
106 eina_hash_list_append(pd->m_gesture_contex, &target, type);
107 }
108
109}
110
111void
112_efl_gesture_manager_callback_del_hook(Eo *obj, Eo *target, const Efl_Event_Description *type)
113{
114 Efl_Gesture_Manager_Data *pd = efl_data_scope_get(obj, MY_CLASS);
115 // if there is a recognizer registered for that event then add it to the gesture context
116 Efl_Gesture_Recognizer *recognizer = eina_hash_find (pd->m_recognizers, &type);
117 if (recognizer)
118 {
119 eina_hash_list_remove(pd->m_gesture_contex, &target, type);
120 _cleanup_cached_gestures(pd, target, type);
121 }
122}
123
124void
125_efl_gesture_manager_filter_event(Eo *obj, Eo *target, void *event)
126{
127 Eina_List *l, *gesture_context;
128 Efl_Gesture_Manager_Data *pd;
129 const Efl_Event_Description *gesture_type;
130 Efl_Gesture_Recognizer *recognizer;
131 Efl_Gesture *gesture;
132 Efl_Gesture_Recognizer_Result recog_result;
133 Efl_Gesture_Recognizer_Result recog_state;
134 Efl_Gesture_Touch *touch_event;
135 Efl_Input_Pointer_Data *pointer_data = efl_data_scope_get(event, EFL_INPUT_POINTER_CLASS);
136
137 pd = efl_data_scope_get(obj, MY_CLASS);
138 gesture_context = eina_hash_find(pd->m_gesture_contex, &target);
139 if (gesture_context)
140 {
141 // get the touch event for this particular widget
142 touch_event = eina_hash_find(pd->m_object_events, &target);
143 if (touch_event)
144 {
145 efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
146 pointer_data->timestamp, pointer_data->action);
147 }
148 else
149 {
150 touch_event = efl_add(EFL_GESTURE_TOUCH_CLASS, NULL);
151 efl_gesture_touch_point_record(touch_event, pointer_data->tool, pointer_data->cur.x, pointer_data->cur.y,
152 pointer_data->timestamp, pointer_data->action);
153 eina_hash_add(pd->m_object_events, &target, touch_event);
154 }
155
156 if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_UNKNOWN)
157 return;
158
159 EINA_LIST_FOREACH(gesture_context, l, gesture_type)
160 {
161 recognizer = eina_hash_find(pd->m_recognizers, &gesture_type);
162 gesture = _get_state(pd, target, recognizer, gesture_type);
163 if (!gesture)
164 continue;
165 recog_result = efl_gesture_recognizer_recognize(recognizer, gesture, target, touch_event);
166 recog_state = recog_result & EFL_GESTURE_RESULT_MASK;
167 if (recog_state == EFL_GESTURE_TRIGGER)
168 {
169 if (efl_gesture_state_get(gesture) == EFL_GESTURE_NONE)
170 efl_gesture_state_set(gesture, EFL_GESTURE_STARTED);
171 else
172 efl_gesture_state_set(gesture, EFL_GESTURE_UPDATED);
173 }
174 else if (recog_state == EFL_GESTURE_FINISH)
175 {
176 efl_gesture_state_set(gesture, EFL_GESTURE_FINISHED);
177 }
178 else if (recog_state == EFL_GESTURE_MAYBE)
179 {
180 continue;
181 }
182 else if (recog_state == EFL_GESTURE_CANCEL)
183 {
184 if (efl_gesture_state_get(gesture) != EFL_GESTURE_NONE)
185 {
186 efl_gesture_state_set(gesture, EFL_GESTURE_CANCELED);
187 }
188 else
189 continue;
190 }
191 else if (recog_state == EFL_GESTURE_IGNORE)
192 {
193 continue;
194 }
195 efl_event_callback_call(target, gesture_type, gesture);
196 }
197
198 if (efl_gesture_touch_state_get(touch_event) == EFL_GESTURE_TOUCH_END)
199 {
200 EINA_LIST_FOREACH(gesture_context, l, gesture_type)
201 _cleanup_cached_gestures(pd, target, gesture_type);
202
203 eina_hash_del(pd->m_object_events, &target, NULL);
204 // free gesture_to_delete list
205 _cleanup_object(pd->m_gestures_to_delete);
206 pd->m_gestures_to_delete = NULL;
207 }
208 }
209}
210
211EOLIAN static const Efl_Event_Description *
212_efl_gesture_manager_recognizer_register(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
213 Efl_Gesture_Recognizer *recognizer)
214{
215 Efl_Gesture_Recognizer_Data *rpd;
216 Efl_Gesture *dummy = efl_gesture_recognizer_create(recognizer, 0);
217
218 if (!dummy)
219 return NULL;
220
221 const Efl_Event_Description *type = efl_gesture_type_get(dummy);
222
223 // Add the recognizer to the m_recognizers
224 eina_hash_add(pd->m_recognizers, &type, recognizer);
225 // update the manager
226 rpd = efl_data_scope_get(recognizer, EFL_GESTURE_RECOGNIZER_CLASS);
227 rpd->manager = obj;
228
229 efl_del(dummy);
230
231 return type;
232}
233
234EOLIAN static void
235_efl_gesture_manager_recognizer_unregister(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
236 Efl_Gesture_Recognizer *recognizer)
237{
238 Eina_List *l, *l_next;
239 Object_Gesture *object_gesture;
240 const Efl_Event_Description *type;
241 Efl_Gesture *dummy;
242
243 if (!recognizer) return;
244
245 // find the type of the recognizer
246 dummy = efl_gesture_recognizer_create(recognizer, 0);
247 if (!dummy)return;
248
249 type = efl_gesture_type_get(dummy);
250 efl_del(dummy);
251
252 // check if its already registered
253 recognizer = eina_hash_find(pd->m_recognizers, &type);
254
255 if (!recognizer) return;
256
257 // remove that gesture from the list of object gestures
258 EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
259 {
260 if (object_gesture->type == type)
261 {
262 pd->m_gestures_to_delete = eina_list_append(pd->m_gestures_to_delete, object_gesture->gesture);
263 free(object_gesture);
264 pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
265 }
266 }
267 eina_hash_del(pd->m_recognizers, &type, NULL);
268}
269
270// EOLIAN static void
271// _efl_gesture_manager_ungrab_all(Eo *obj EINA_UNUSED, Efl_Gesture_Manager_Data *pd,
272// Eo *target)
273// {
274// const Efl_Event_Description *type;
275// Eina_List *l;
276
277// Eina_List *gesture_type_list = eina_hash_find(pd->m_gesture_contex, &target);
278
279// if (!gesture_type_list) return;
280
281// EINA_LIST_FOREACH(gesture_type_list, l, type)
282// {
283// _cleanup_cached_gestures(obj, pd, target, type);
284// }
285// eina_hash_del(pd->m_gesture_contex, &target, NULL);
286// }
287
288// get or create a gesture object that will represent the state for a given object, used by the recognizer
289Efl_Gesture*
290_get_state(Efl_Gesture_Manager_Data *pd,
291 Eo *target, Efl_Gesture_Recognizer *recognizer, const Efl_Event_Description *type)
292{
293 Eina_List *l;
294 Object_Gesture *object_gesture;
295 Efl_Gesture *gesture;
296
297 // if the widget is being deleted we should be careful not to
298 // create a new state.
299 if (efl_destructed_is(target))
300 return 0;
301
302 //TODO find a optimized way of looking for gesture
303 EINA_LIST_FOREACH(pd->m_object_gestures, l, object_gesture)
304 {
305 if (object_gesture->object == target &&
306 object_gesture->recognizer == recognizer &&
307 object_gesture->type == type)
308 {
309 // the gesture is already processed waiting for cleanup
310 if ((efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_FINISHED) ||
311 (efl_gesture_state_get(object_gesture->gesture) == EFL_GESTURE_CANCELED))
312 return NULL;
313 return object_gesture->gesture;
314 }
315 }
316
317 gesture = efl_gesture_recognizer_create(recognizer, target);
318 if (!gesture)
319 return 0;
320 object_gesture = calloc(1, sizeof(Object_Gesture));
321 object_gesture->object = target;
322 object_gesture->recognizer = recognizer;
323 object_gesture->type = type;
324 object_gesture->gesture = gesture;
325
326 pd->m_object_gestures = eina_list_append(pd->m_object_gestures, object_gesture);
327
328 return gesture;
329}
330
331static void
332_cleanup_cached_gestures(Efl_Gesture_Manager_Data *pd,
333 Eo *target, const Efl_Event_Description *type)
334{
335 Eina_List *l, *l_next;
336 Object_Gesture *object_gesture;
337
338 EINA_LIST_FOREACH_SAFE(pd->m_object_gestures, l, l_next, object_gesture)
339 {
340 if ( (object_gesture->type == type) && (target == object_gesture->object))
341 {
342 pd->m_gestures_to_delete = eina_list_append(pd->m_gestures_to_delete, object_gesture->gesture);
343 free(object_gesture);
344 pd->m_object_gestures = eina_list_remove_list(pd->m_object_gestures, l);
345 }
346 }
347}
348
349
350#include "efl_gesture_manager.eo.c"