2 #include "services/e_service_gesture.h"
5 #define E_SERVICE_GESTURE_KEY "e_service_gesture_enabled"
9 POL_GESTURE_STATUS_NONE,
10 POL_GESTURE_STATUS_READY,
11 POL_GESTURE_STATUS_ACTIVE,
12 POL_GESTURE_STATUS_CANCEL
13 } E_Policy_Gesture_Status;
15 struct _E_Policy_Gesture
18 E_Policy_Gesture_Type type;
20 E_Policy_Gesture_Status status;
22 unsigned int set_fingers;
27 Ecore_Timer *waiting_timer;
32 unsigned int timestamp;
33 Evas_Coord_Point c_start;
37 Eina_Bool pressed; /* to avoid processing that happened mouse move right after mouse up */
39 Evas_Coord_Point start;
41 } touch_info[MAX_FINGERS];
45 E_Policy_Gesture_Start_Cb start;
46 E_Policy_Gesture_Move_Cb move;
47 E_Policy_Gesture_End_Cb end;
53 _gesture_util_center_start_point_get(E_Policy_Gesture *gesture, int *cx, int *cy)
56 Evas_Coord_Point total_point = {0, };
58 if (!gesture->pressed_fingers) return;
60 for (i = 0; i < gesture->pressed_fingers; i++)
62 total_point.x += gesture->touch_info[i].start.x;
63 total_point.y += gesture->touch_info[i].start.y;
66 total_point.x = (int)(total_point.x / gesture->pressed_fingers);
67 total_point.y = (int)(total_point.y / gesture->pressed_fingers);
74 _gesture_util_center_cur_point_get(E_Policy_Gesture *gesture, int *cx, int *cy)
77 Evas_Coord_Point total_point = {0, };
79 if (!gesture->pressed_fingers) return;
81 touch_num = gesture->pressed_fingers;
83 for (i = 0; i < touch_num; i++)
85 if (!gesture->touch_info[i].pressed)
90 total_point.x += gesture->touch_info[i].cur.x;
91 total_point.y += gesture->touch_info[i].cur.y;
94 total_point.x = (int)(total_point.x / gesture->pressed_fingers);
95 total_point.y = (int)(total_point.y / gesture->pressed_fingers);
101 static E_Policy_Gesture_Status
102 _gesture_line_check(E_Policy_Gesture *gesture, int x, int y, int sensitivity)
106 dx = x - gesture->c_start.x;
107 dy = y - gesture->c_start.y;
109 if (gesture->angle == 0 || gesture->angle == 180)
111 if (abs(dy) < sensitivity)
112 return POL_GESTURE_STATUS_READY;
114 else if (gesture->angle == 90 || gesture->angle == 270)
116 if (abs(dx) < sensitivity)
117 return POL_GESTURE_STATUS_READY;
121 if ((abs(dy) < sensitivity) &&
122 (abs(dx) < sensitivity))
123 return POL_GESTURE_STATUS_READY;
126 return POL_GESTURE_STATUS_ACTIVE;
129 static E_Policy_Gesture_Status
130 _gesture_flick_check(E_Policy_Gesture *gesture, Evas_Object *obj, int x, int y, unsigned int timestamp)
136 const float sensitivity = 0.25; /* FIXME: hard coded, it sould be configurable. */
138 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
139 if (!E_INSIDE(x, y, ox, oy, ow, oh))
140 return POL_GESTURE_STATUS_READY;
142 dy = y - gesture->c_start.y;
143 dt = timestamp - gesture->timestamp;
145 return POL_GESTURE_STATUS_READY;
147 vel = (float)dy / (float)dt;
148 if (fabs(vel) < sensitivity)
149 return POL_GESTURE_STATUS_READY;
151 return POL_GESTURE_STATUS_ACTIVE;
154 static E_Policy_Gesture_Status
155 _gesture_check(E_Policy_Gesture *gesture, Evas_Object *obj, int x, int y, unsigned int timestamp)
157 E_Policy_Gesture_Status ret = POL_GESTURE_STATUS_READY;
159 if (gesture->waiting_timer)
161 // All waiting fingers are not pressed. So waiting other fingers
165 switch (gesture->type)
167 case POL_GESTURE_TYPE_NONE:
168 ret = POL_GESTURE_STATUS_ACTIVE;
170 case POL_GESTURE_TYPE_LINE:
171 /* FIXME: sensitivity is hard coded, it sould be configurable. */
172 ret = _gesture_line_check(gesture, x, y, 50);
174 case POL_GESTURE_TYPE_FLICK:
175 ret = _gesture_flick_check(gesture, obj, x, y, timestamp);
178 WRN("Unknown gesture type %d", gesture->type);
182 if ((ret == POL_GESTURE_STATUS_ACTIVE) &&
183 !gesture->gesture_fingers)
185 gesture->gesture_fingers = gesture->pressed_fingers;
192 _gesture_cleanup(E_Policy_Gesture *gesture)
194 gesture->pressed_fingers = 0;
195 gesture->gesture_fingers = 0;
196 gesture->status = POL_GESTURE_STATUS_READY;
197 if (gesture->waiting_timer)
199 ecore_timer_del(gesture->waiting_timer);
200 gesture->waiting_timer = NULL;
205 _gesture_cancel(E_Policy_Gesture *gesture)
207 gesture->status = POL_GESTURE_STATUS_CANCEL;
211 _gesture_start(E_Policy_Gesture *gesture)
213 if (gesture->set_fingers & (1 << gesture->pressed_fingers))
215 if (gesture->set_fingers < (1 << (gesture->pressed_fingers + 1)))
217 // All of waiting fingers are come. Stop waiting other fingers
218 if (gesture->waiting_timer)
220 ecore_timer_del(gesture->waiting_timer);
221 gesture->waiting_timer = NULL;
228 _gesture_waiting_timer(void *data)
230 E_Policy_Gesture *gesture = data;
231 unsigned int timestamp;
233 ecore_timer_del(gesture->waiting_timer);
234 gesture->waiting_timer = NULL;
236 if (gesture->set_fingers & (1 << gesture->pressed_fingers))
238 timestamp = e_util_timestamp_get();
239 gesture->status = _gesture_check(gesture, gesture->obj, gesture->c_start.x, gesture->c_start.y, timestamp);
240 if (gesture->status == POL_GESTURE_STATUS_ACTIVE)
242 if (gesture->cb.start)
244 gesture->cb.start(gesture->cb.data, gesture->obj, gesture->gesture_fingers, gesture->c_start.x, gesture->c_start.y, timestamp);
247 gesture->gesture_fingers = gesture->pressed_fingers;
251 _gesture_cancel(gesture);
254 return ECORE_CALLBACK_CANCEL;
258 _gesture_touch_up(E_Policy_Gesture *gesture, Evas_Object *obj, int idx, int x, int y, int timestamp)
262 switch (gesture->status)
264 case POL_GESTURE_STATUS_READY:
265 gesture->touch_info[idx].pressed = EINA_FALSE;
266 _gesture_cancel(gesture);
269 case POL_GESTURE_STATUS_ACTIVE:
270 gesture->touch_info[idx].pressed = EINA_FALSE;
271 gesture->touch_info[idx].cur.x = x;
272 gesture->touch_info[idx].cur.y = y;
273 _gesture_util_center_cur_point_get(gesture, &cx, &cy);
275 if (gesture->pressed_fingers <= 0)
279 gesture->cb.end(gesture->cb.data, obj, gesture->gesture_fingers, cx, cy, timestamp);
284 case POL_GESTURE_STATUS_CANCEL:
291 if (gesture->pressed_fingers <= 0)
293 _gesture_cleanup(gesture);
298 _gesture_touch_move(E_Policy_Gesture *gesture, Evas_Object *obj, int idx, int x, int y, int timestamp)
302 switch (gesture->status)
304 case POL_GESTURE_STATUS_READY:
305 gesture->touch_info[idx].cur.x = x;
306 gesture->touch_info[idx].cur.y = y;
308 _gesture_util_center_cur_point_get(gesture, &cx, &cy);
309 if (gesture->waiting_timer)
311 if (_gesture_line_check(gesture, cx, cy, gesture->wait_dist) == POL_GESTURE_STATUS_ACTIVE)
313 ecore_timer_del(gesture->waiting_timer);
314 gesture->waiting_timer = NULL;
315 if (!(gesture->set_fingers & (1 << gesture->pressed_fingers)))
317 _gesture_cancel(gesture);
323 gesture->status = _gesture_check(gesture, obj, cx, cy, timestamp);
324 if (gesture->status == POL_GESTURE_STATUS_ACTIVE)
326 if (gesture->cb.start)
328 gesture->cb.start(gesture->cb.data, obj, gesture->gesture_fingers, gesture->c_start.x, gesture->c_start.y, timestamp);
335 case POL_GESTURE_STATUS_ACTIVE:
336 gesture->touch_info[idx].cur.x = x;
337 gesture->touch_info[idx].cur.y = y;
339 _gesture_util_center_cur_point_get(gesture, &cx, &cy);
342 case POL_GESTURE_STATUS_CANCEL:
349 if (gesture->cb.move)
350 gesture->cb.move(gesture->cb.data, obj, gesture->gesture_fingers, cx, cy, timestamp);
354 _gesture_touch_down(E_Policy_Gesture *gesture, Evas_Object *obj, int idx, Evas_Coord x, Evas_Coord y, unsigned int timestamp)
358 switch (gesture->status)
360 case POL_GESTURE_STATUS_READY:
361 gesture->touch_info[idx].pressed = EINA_TRUE;
362 gesture->touch_info[idx].cur.x = gesture->touch_info[idx].start.x = x;
363 gesture->touch_info[idx].cur.y = gesture->touch_info[idx].start.y = y;
365 if (gesture->set_fingers < (1 << (idx + 1)))
367 // too many fingers are touched
368 _gesture_cancel(gesture);
372 if (gesture->gesture_fingers)
374 // already gesture is begin(or definited), so ignore meaningless touch.
378 gesture->timestamp = timestamp;
380 if (gesture->pressed_fingers == 1)
382 gesture->c_start.x = x;
383 gesture->c_start.y = y;
384 if (gesture->set_fingers > 2)
385 gesture->waiting_timer = ecore_timer_add(gesture->wait_time, _gesture_waiting_timer, (void *)gesture);
389 _gesture_util_center_start_point_get(gesture, &cx, &cy);
390 gesture->c_start.x = cx;
391 gesture->c_start.y = cy;
394 _gesture_start(gesture);
396 gesture->status = _gesture_check(gesture, obj, x, y, timestamp);
397 if (gesture->status == POL_GESTURE_STATUS_ACTIVE)
399 if (gesture->cb.start)
400 gesture->cb.start(gesture->cb.data, obj, gesture->gesture_fingers, gesture->c_start.x, gesture->c_start.y, timestamp);
404 case POL_GESTURE_STATUS_ACTIVE:
405 gesture->touch_info[idx].pressed = EINA_TRUE;
408 case POL_GESTURE_STATUS_CANCEL:
417 _gesture_obj_cb_mouse_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
419 E_Policy_Gesture *gesture = data;
420 Evas_Event_Mouse_Up *ev = event;
422 gesture->pressed_fingers--;
423 _gesture_touch_up(gesture, obj, 0, ev->canvas.x, ev->canvas.y, ev->timestamp);
427 _gesture_obj_cb_mouse_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
429 E_Policy_Gesture *gesture = data;
430 Evas_Event_Mouse_Move *ev = event;
432 if (!gesture->touch_info[0].pressed)
435 _gesture_touch_move(gesture, obj, 0, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
439 _gesture_obj_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
441 E_Policy_Gesture *gesture = data;
442 Evas_Event_Mouse_Down *ev = event;
444 gesture->pressed_fingers++;
445 _gesture_touch_down(data, obj, 0, ev->canvas.x, ev->canvas.y, ev->timestamp);
449 _gesture_obj_cb_multi_up(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
451 E_Policy_Gesture *gesture = data;
452 Evas_Event_Multi_Up *ev = event;
454 if (gesture->gesture_fingers &&
455 (gesture->gesture_fingers < (ev->device + 1)))
457 // already gesture is begin(or definited), so ignore meaningless touch
461 if (!gesture->touch_info[ev->device].pressed)
466 gesture->pressed_fingers--;
467 _gesture_touch_up(gesture, obj, ev->device, ev->canvas.x, ev->canvas.y, ev->timestamp);
471 _gesture_obj_cb_multi_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
473 E_Policy_Gesture *gesture = data;
474 Evas_Event_Multi_Move *ev = event;
476 if (!gesture->touch_info[ev->device].pressed)
479 _gesture_touch_move(gesture, obj, ev->device, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
483 _gesture_obj_cb_multi_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event)
485 E_Policy_Gesture *gesture = data;
486 Evas_Event_Multi_Down *ev = event;
488 if (gesture->gesture_fingers &&
489 (gesture->gesture_fingers < (ev->device + 1)))
491 // already gesture is begin(or definited), so ignore meaningless touch
495 if (gesture->pressed_fingers <= 0)
497 // 1st finger's event didn't come, so ignore meaningless touch
501 gesture->pressed_fingers++;
503 _gesture_touch_down(data, obj, ev->device, ev->canvas.x, ev->canvas.y, ev->timestamp);
506 E_API E_Policy_Gesture *
507 e_service_gesture_add(Evas_Object *obj, E_Policy_Gesture_Type type, int nfingers)
509 E_Policy_Gesture *gesture;
511 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
513 if (evas_object_data_get(obj, E_SERVICE_GESTURE_KEY))
515 WRN("obj(%p) is already added gesture.\n", obj);
519 gesture = E_NEW(E_Policy_Gesture, 1);
520 if (EINA_UNLIKELY(gesture == NULL))
524 gesture->type = type;
525 gesture->set_fingers |= 1 << nfingers;
527 // attempt to get wait_time and wait_dist to config file.
528 // but if failed, set default VALUE
531 if (e_config->gesture_service.wait_time)
532 gesture->wait_time = e_config->gesture_service.wait_time;
533 if (e_config->gesture_service.wait_dist)
534 gesture->wait_dist = e_config->gesture_service.wait_dist;
536 if (!gesture->wait_time)
537 gesture->wait_time = 0.1;
538 if (!gesture->wait_dist)
539 gesture->wait_dist = 50;
540 gesture->status = POL_GESTURE_STATUS_READY;
542 /* we should to repeat mouse event to below object
543 * until we can make sure gesture */
544 if (type != POL_GESTURE_TYPE_NONE)
545 evas_object_repeat_events_set(obj, EINA_TRUE);
547 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
548 _gesture_obj_cb_mouse_down, gesture);
549 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
550 _gesture_obj_cb_mouse_move, gesture);
551 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
552 _gesture_obj_cb_mouse_up, gesture);
553 evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_DOWN,
554 _gesture_obj_cb_multi_down, gesture);
555 evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_MOVE,
556 _gesture_obj_cb_multi_move, gesture);
557 evas_object_event_callback_add(obj, EVAS_CALLBACK_MULTI_UP,
558 _gesture_obj_cb_multi_up, gesture);
560 evas_object_data_set(obj, E_SERVICE_GESTURE_KEY, (void *)1);
566 e_service_gesture_del(E_Policy_Gesture *gesture)
568 EINA_SAFETY_ON_NULL_RETURN(gesture);
570 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_DOWN,
571 _gesture_obj_cb_mouse_down);
572 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_MOVE,
573 _gesture_obj_cb_mouse_move);
574 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MOUSE_UP,
575 _gesture_obj_cb_mouse_up);
576 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MULTI_DOWN,
577 _gesture_obj_cb_multi_down);
578 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MULTI_MOVE,
579 _gesture_obj_cb_multi_move);
580 evas_object_event_callback_del(gesture->obj, EVAS_CALLBACK_MULTI_UP,
581 _gesture_obj_cb_multi_up);
583 evas_object_data_del(gesture->obj, E_SERVICE_GESTURE_KEY);
585 E_FREE_FUNC(gesture->waiting_timer, ecore_timer_del);
591 e_service_gesture_type_set(E_Policy_Gesture *gesture, E_Policy_Gesture_Type type)
593 EINA_SAFETY_ON_NULL_RETURN(gesture);
595 if (gesture->type == type)
598 gesture->type = type;
599 if (type == POL_GESTURE_TYPE_NONE)
600 evas_object_repeat_events_set(gesture->obj, EINA_FALSE);
602 evas_object_repeat_events_set(gesture->obj, EINA_TRUE);
606 e_service_gesture_cb_set(E_Policy_Gesture *gesture, E_Policy_Gesture_Start_Cb cb_start, E_Policy_Gesture_Move_Cb cb_move, E_Policy_Gesture_End_Cb cb_end, void *data)
608 EINA_SAFETY_ON_NULL_RETURN(gesture);
610 gesture->cb.start = cb_start;
611 gesture->cb.move = cb_move;
612 gesture->cb.end = cb_end;
613 gesture->cb.data = data;
617 e_service_gesture_angle_set(E_Policy_Gesture *gesture, int angle)
619 EINA_SAFETY_ON_NULL_RETURN(gesture);
620 gesture->angle = angle;
624 e_service_gesture_fingers_set(E_Policy_Gesture *gesture, int nfingers)
626 EINA_SAFETY_ON_NULL_RETURN(gesture);
628 if (gesture->set_fingers & (1 << nfingers))
630 gesture->set_fingers |= 1 << nfingers;
634 e_service_gesture_wait_time_set(E_Policy_Gesture *gesture, double wait_time)
636 EINA_SAFETY_ON_NULL_RETURN(gesture);
637 gesture->wait_time = wait_time;
641 e_service_gesture_wait_dist_set(E_Policy_Gesture *gesture, int wait_dist)
643 EINA_SAFETY_ON_NULL_RETURN(gesture);
644 gesture->wait_dist = wait_dist;