2 * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
4 * This file is a modified version of BSD licensed file and
5 * licensed under the Flora License, Version 1.1 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://floralicense.org/license/
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an AS IS BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * Please, see the LICENSE file for the original copyright owner and
21 #include "screen_reader_gestures.h"
25 #include <Ecore_Input.h>
28 static GestureCB _global_cb;
29 static void *_global_data;
31 struct _Gestures_Config
33 // minimal required length of flick gesture (in pixels)
34 int one_finger_flick_min_length;
35 // maximal time of gesture
36 int one_finger_flick_max_time;
37 // timeout period to activate hover gesture (first longpress timeout)
38 double one_finger_hover_longpress_timeout;
39 // tap timeout - maximal ammount of time allowed between seqiential taps
40 double two_fingers_hover_longpress_timeout;
41 // tap timeout - maximal ammount of time allowed between seqiential taps
42 double one_finger_tap_timeout;
43 // tap radius(in pixels)
44 int one_finger_tap_radius;
46 typedef struct _Gestures_Config Gestures_Config;
50 FLICK_DIRECTION_UNDEFINED,
54 FLICK_DIRECTION_RIGHT,
55 FLICK_DIRECTION_DOWN_RETURN,
56 FLICK_DIRECTION_UP_RETURN,
57 FLICK_DIRECTION_LEFT_RETURN,
58 FLICK_DIRECTION_RIGHT_RETURN,
63 GESTURE_NOT_STARTED = 0, // Gesture is ready to start
64 GESTURE_ONGOING, // Gesture in progress.
65 GESTURE_FINISHED, // Gesture finished - should be emited
66 GESTURE_ABORTED // Gesture aborted
71 ONE_FINGER_GESTURE = 1,
78 Ecore_X_Window win; /**< Input window covering given zone */
79 unsigned int n_taps; /**< Number of fingers touching screen */
80 unsigned int event_time;
84 gesture_state_e state; // current state of gesture
85 unsigned int timestamp[3]; // time of gesture;
86 int finger[3]; // finger number which initiates gesture
87 int x_org[3], y_org[3]; // coorinates of finger down event
88 int x_end[3], y_end[3]; // coorinates of finger up event
89 flick_direction_e dir; // direction of flick
90 int n_fingers; // number of fingers in gesture
91 int n_fingers_left; // number of fingers in gesture
92 // still touching screen
93 Eina_Bool finger_out[3]; // finger is out of the finger boundary
94 Eina_Bool return_flick[3];
99 gesture_state_e state; // currest gesture state
103 unsigned int timestamp; // time of gesture;
104 unsigned int last_emission_time; // last time of gesture emission
106 Eina_Bool longpressed;
111 Eina_Bool started; // indicates if taps recognition process has started
112 Eina_Bool pressed; // indicates if finger is down
113 int n_taps; // number of taps captures in sequence
114 int finger[3]; // device id of finget
115 Ecore_Timer *timer; // sequence expiration timer
116 int x_org[3], y_org[3]; // coordinates of first tap
117 gesture_type_e tap_type;
120 typedef struct _Cover Cover;
122 Gestures_Config *_e_mod_config;
123 static Ecore_X_Window scrolled_win;
125 static Eina_List *handlers;
127 static int win_angle;
129 static void _hover_event_emit(Cover *cov, int state);
131 static void _event_emit(Gesture g, int x, int y, int x_e, int y_e, int state, int event_time)
133 Gesture_Info *info = calloc(sizeof(Gesture_Info), 1);
134 EINA_SAFETY_ON_NULL_RETURN(info);
142 info->event_time = event_time;
145 _global_cb(_global_data, info);
150 _flick_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
152 if (cov->flick_gesture.state == GESTURE_NOT_STARTED)
154 cov->flick_gesture.state = GESTURE_ONGOING;
155 cov->flick_gesture.finger[0] = ev->multi.device;
156 cov->flick_gesture.x_org[0] = ev->root.x;
157 cov->flick_gesture.y_org[0] = ev->root.y;
158 cov->flick_gesture.timestamp[0] = ev->timestamp;
159 cov->flick_gesture.n_fingers = 1;
160 cov->flick_gesture.n_fingers_left = 1;
161 cov->flick_gesture.dir = FLICK_DIRECTION_UNDEFINED;
162 cov->flick_gesture.finger_out[0] = EINA_FALSE;
163 cov->flick_gesture.return_flick[0] = EINA_FALSE;
165 else if (cov->flick_gesture.state == GESTURE_ONGOING)
167 // abort gesture if too many fingers touched screen
168 if ((cov->n_taps > 3) || (cov->flick_gesture.n_fingers > 2))
170 cov->flick_gesture.state = GESTURE_ABORTED;
174 cov->flick_gesture.x_org[cov->flick_gesture.n_fingers] = ev->root.x;
175 cov->flick_gesture.y_org[cov->flick_gesture.n_fingers] = ev->root.y;
176 cov->flick_gesture.timestamp[cov->flick_gesture.n_fingers] = ev->timestamp;
177 cov->flick_gesture.finger[cov->flick_gesture.n_fingers] = ev->multi.device;
178 cov->flick_gesture.n_fingers++;
179 cov->flick_gesture.n_fingers_left++;
180 if (cov->flick_gesture.n_fingers < 3) /* n_fingers == 3 makes out of bounds write */
182 cov->flick_gesture.finger_out[cov->flick_gesture.n_fingers] = EINA_FALSE;
183 cov->flick_gesture.return_flick[cov->flick_gesture.n_fingers] = EINA_FALSE;
189 _flick_gesture_time_check(unsigned int event_time, unsigned int gesture_time)
191 DEBUG("Flick time: %d", event_time - gesture_time);
192 if ((event_time - gesture_time) < _e_mod_config->one_finger_flick_max_time * 2) //Double time because of the possible of return flick
199 _flick_gesture_length_check(int x, int y, int x_org, int y_org)
204 if ((dx * dx + dy * dy) > (_e_mod_config->one_finger_flick_min_length *
205 _e_mod_config->one_finger_flick_min_length))
211 static flick_direction_e
212 _flick_gesture_direction_get(int x, int y, int x_org, int y_org)
232 if ((dy < 0) && (abs(dx) < -dy))
233 return FLICK_DIRECTION_UP;
234 if ((dy > 0) && (abs(dx) < dy))
235 return FLICK_DIRECTION_DOWN;
236 if ((dx > 0) && (dx > abs(dy)))
237 return FLICK_DIRECTION_RIGHT;
238 if ((dx < 0) && (-dx > abs(dy)))
239 return FLICK_DIRECTION_LEFT;
241 return FLICK_DIRECTION_UNDEFINED;
245 _flick_event_emit(Cover *cov)
247 int ax, ay, axe, aye, i, type = -1;
248 ax = ay = axe = aye = 0;
250 for (i = 0; i < cov->flick_gesture.n_fingers; i++)
252 ax += cov->flick_gesture.x_org[i];
253 ay += cov->flick_gesture.y_org[i];
254 axe += cov->flick_gesture.x_end[i];
255 aye += cov->flick_gesture.y_end[i];
258 ax /= cov->flick_gesture.n_fingers;
259 ay /= cov->flick_gesture.n_fingers;
260 axe /= cov->flick_gesture.n_fingers;
261 aye /= cov->flick_gesture.n_fingers;
263 if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT)
265 if (cov->flick_gesture.n_fingers == 1)
266 type = ONE_FINGER_FLICK_LEFT;
267 if (cov->flick_gesture.n_fingers == 2)
268 type = TWO_FINGERS_FLICK_LEFT;
269 if (cov->flick_gesture.n_fingers == 3)
270 type = THREE_FINGERS_FLICK_LEFT;
272 else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT)
274 if (cov->flick_gesture.n_fingers == 1)
275 type = ONE_FINGER_FLICK_RIGHT;
276 if (cov->flick_gesture.n_fingers == 2)
277 type = TWO_FINGERS_FLICK_RIGHT;
278 if (cov->flick_gesture.n_fingers == 3)
279 type = THREE_FINGERS_FLICK_RIGHT;
281 else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP)
283 if (cov->flick_gesture.n_fingers == 1)
284 type = ONE_FINGER_FLICK_UP;
285 if (cov->flick_gesture.n_fingers == 2)
286 type = TWO_FINGERS_FLICK_UP;
287 if (cov->flick_gesture.n_fingers == 3)
288 type = THREE_FINGERS_FLICK_UP;
290 else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN)
292 if (cov->flick_gesture.n_fingers == 1)
293 type = ONE_FINGER_FLICK_DOWN;
294 if (cov->flick_gesture.n_fingers == 2)
295 type = TWO_FINGERS_FLICK_DOWN;
296 if (cov->flick_gesture.n_fingers == 3)
297 type = THREE_FINGERS_FLICK_DOWN;
299 else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN)
301 if (cov->flick_gesture.n_fingers == 1)
302 type = ONE_FINGER_FLICK_DOWN_RETURN;
303 if (cov->flick_gesture.n_fingers == 2)
304 type = TWO_FINGERS_FLICK_DOWN_RETURN;
305 if (cov->flick_gesture.n_fingers == 3)
306 type = THREE_FINGERS_FLICK_DOWN_RETURN;
308 else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN)
310 if (cov->flick_gesture.n_fingers == 1)
311 type = ONE_FINGER_FLICK_UP_RETURN;
312 if (cov->flick_gesture.n_fingers == 2)
313 type = TWO_FINGERS_FLICK_UP_RETURN;
314 if (cov->flick_gesture.n_fingers == 3)
315 type = THREE_FINGERS_FLICK_UP_RETURN;
317 else if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN)
319 if (cov->flick_gesture.n_fingers == 1)
320 type = ONE_FINGER_FLICK_LEFT_RETURN;
321 if (cov->flick_gesture.n_fingers == 2)
322 type = TWO_FINGERS_FLICK_LEFT_RETURN;
323 if (cov->flick_gesture.n_fingers == 3)
324 type = THREE_FINGERS_FLICK_LEFT_RETURN;
326 else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN)
328 if (cov->flick_gesture.n_fingers == 1)
329 type = ONE_FINGER_FLICK_RIGHT_RETURN;
330 if (cov->flick_gesture.n_fingers == 2)
331 type = TWO_FINGERS_FLICK_RIGHT_RETURN;
332 if (cov->flick_gesture.n_fingers == 3)
333 type = THREE_FINGERS_FLICK_RIGHT_RETURN;
335 DEBUG("FLICK GESTURE: N: %d F: %d", cov->flick_gesture.n_fingers, cov->flick_gesture.dir);
336 _event_emit(type, ax, ay, axe, aye, 2, cov->event_time);
340 _flick_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
342 if (cov->flick_gesture.state == GESTURE_ONGOING)
345 // check if fingers match
346 for (i = 0; i < cov->flick_gesture.n_fingers; i++)
348 if (cov->flick_gesture.finger[i] == ev->multi.device)
351 if (i == cov->flick_gesture.n_fingers)
353 DEBUG("Finger id not recognized. Gesture aborted.");
354 cov->flick_gesture.state = GESTURE_ABORTED;
358 // check if flick for given finger is valid
359 if (!_flick_gesture_time_check(ev->timestamp,
360 cov->flick_gesture.timestamp[i]))
362 DEBUG("finger flick gesture timeout expired. Gesture aborted.");
363 cov->flick_gesture.state = GESTURE_ABORTED;
367 // check minimal flick length
368 if (!_flick_gesture_length_check(ev->root.x, ev->root.y,
369 cov->flick_gesture.x_org[i],
370 cov->flick_gesture.y_org[i]))
372 if (!cov->flick_gesture.finger_out[i])
374 DEBUG("Minimal gesture length not reached and no return flick. Gesture aborted.");
375 cov->flick_gesture.state = GESTURE_ABORTED;
378 cov->flick_gesture.return_flick[i] = EINA_TRUE;
381 flick_direction_e s = cov->flick_gesture.return_flick[i] ?
382 cov->flick_gesture.dir :
383 _flick_gesture_direction_get(ev->root.x, ev->root.y,
384 cov->flick_gesture.x_org[i],
385 cov->flick_gesture.y_org[i]);
387 cov->flick_gesture.n_fingers_left--;
389 if ((cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
390 cov->flick_gesture.dir > FLICK_DIRECTION_RIGHT)
391 && cov->flick_gesture.return_flick[i] == EINA_FALSE)
393 DEBUG("Flick gesture");
394 cov->flick_gesture.dir = s;
397 // gesture is valid only if all flicks are in same direction
398 if (cov->flick_gesture.dir != s)
400 DEBUG("Flick in different direction. Gesture aborted.");
401 cov->flick_gesture.state = GESTURE_ABORTED;
405 cov->flick_gesture.x_end[i] = ev->root.x;
406 cov->flick_gesture.y_end[i] = ev->root.y;
408 if (!cov->flick_gesture.n_fingers_left)
410 _flick_event_emit(cov);
411 cov->flick_gesture.state = GESTURE_NOT_STARTED;
416 // if no finger is touching a screen, gesture will be reseted.
417 if ((cov->flick_gesture.state == GESTURE_ABORTED) && (cov->n_taps == 0))
419 DEBUG("Restet flick gesture");
420 cov->flick_gesture.state = GESTURE_NOT_STARTED;
425 _flick_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
427 if (cov->flick_gesture.state == GESTURE_ONGOING)
430 for(i = 0; i < cov->flick_gesture.n_fingers; ++i)
432 if (cov->flick_gesture.finger[i] == ev->multi.device)
435 if (i == cov->flick_gesture.n_fingers)
437 if (cov->flick_gesture.n_fingers >= 3) //that is because of the EFL bug. Mouse move event before mouse down(!)
439 ERROR("Finger id not recognized. Gesture aborted.");
440 cov->flick_gesture.state = GESTURE_ABORTED;
444 if(!cov->flick_gesture.finger_out[i])
446 int dx = ev->root.x - cov->flick_gesture.x_org[i];
447 int dy = ev->root.y - cov->flick_gesture.y_org[i];
464 if (abs(dx) > _e_mod_config->one_finger_flick_min_length)
466 cov->flick_gesture.finger_out[i] = EINA_TRUE;
469 if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
470 cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN)
472 cov->flick_gesture.dir = FLICK_DIRECTION_RIGHT_RETURN;
476 ERROR("Invalid direction, abort");
477 cov->flick_gesture.state = GESTURE_ABORTED;
482 if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
483 cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN)
485 cov->flick_gesture.dir = FLICK_DIRECTION_LEFT_RETURN;
489 ERROR("Invalid direction, abort");
490 cov->flick_gesture.state = GESTURE_ABORTED;
496 else if (abs(dy) > _e_mod_config->one_finger_flick_min_length)
498 cov->flick_gesture.finger_out[i] = EINA_TRUE;
501 if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
502 cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN)
504 cov->flick_gesture.dir = FLICK_DIRECTION_DOWN_RETURN;
508 ERROR("Invalid direction, abort");
509 cov->flick_gesture.state = GESTURE_ABORTED;
514 if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
515 cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN)
517 cov->flick_gesture.dir = FLICK_DIRECTION_UP_RETURN;
521 ERROR("Invalid direction, abort");
522 cov->flick_gesture.state = GESTURE_ABORTED;
533 _on_hover_timeout(void *data)
536 DEBUG("Hover timer expierd");
538 cov->hover_gesture.longpressed = EINA_TRUE;
539 cov->hover_gesture.timer = NULL;
541 if (cov->hover_gesture.last_emission_time == -1)
543 _hover_event_emit(cov, 0);
544 cov->hover_gesture.last_emission_time = cov->event_time;
550 _hover_gesture_timer_reset(Cover *cov, double time)
552 DEBUG("Hover timer reset");
553 cov->hover_gesture.longpressed = EINA_FALSE;
554 if (cov->hover_gesture.timer)
556 ecore_timer_reset(cov->hover_gesture.timer);
559 cov->hover_gesture.timer = ecore_timer_add(time, _on_hover_timeout, cov);
563 _hover_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
565 if (cov->hover_gesture.state == GESTURE_NOT_STARTED &&
568 cov->hover_gesture.state = GESTURE_ONGOING;
569 cov->hover_gesture.timestamp = ev->timestamp;
570 cov->hover_gesture.last_emission_time = -1;
571 cov->hover_gesture.x[0] = ev->root.x;
572 cov->hover_gesture.y[0] = ev->root.y;
573 cov->hover_gesture.finger[0] = ev->multi.device;
574 cov->hover_gesture.n_fingers = 1;
575 _hover_gesture_timer_reset(cov, _e_mod_config->one_finger_hover_longpress_timeout);
577 if (cov->hover_gesture.state == GESTURE_ONGOING &&
580 if (cov->hover_gesture.longpressed)
582 _hover_event_emit(cov, 2);
585 cov->hover_gesture.timestamp = -1;
586 cov->hover_gesture.last_emission_time = -1;
587 cov->hover_gesture.x[1] = ev->root.x;
588 cov->hover_gesture.y[1] = ev->root.y;
589 cov->hover_gesture.finger[1] = ev->multi.device;
590 cov->hover_gesture.n_fingers = 2;
591 _hover_gesture_timer_reset(cov, _e_mod_config->one_finger_hover_longpress_timeout);
593 // abort gesture if more then 2 fingers touched screen
594 if ((cov->hover_gesture.state == GESTURE_ONGOING) &&
597 DEBUG("More then 2 finged. Abort hover gesture");
598 _hover_event_emit(cov, 2);
604 cov->hover_gesture.state = GESTURE_ABORTED;
605 if (cov->hover_gesture.timer)
606 ecore_timer_del(cov->hover_gesture.timer);
607 cov->hover_gesture.timer = NULL;
611 _hover_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
614 if (cov->hover_gesture.state == GESTURE_ONGOING)
617 for (i = 0; i < cov->hover_gesture.n_fingers; i++)
619 if (cov->hover_gesture.finger[i] == ev->multi.device)
622 if (i == cov->hover_gesture.n_fingers)
624 DEBUG("Invalid finger id: %d", ev->multi.device);
629 cov->hover_gesture.state = GESTURE_ABORTED;
630 if (cov->hover_gesture.timer)
631 ecore_timer_del(cov->hover_gesture.timer);
632 cov->hover_gesture.timer = NULL;
633 // aditionally emit event to complete sequence
634 if (cov->hover_gesture.longpressed)
635 _hover_event_emit(cov, 2);
638 // reset gesture only if user released all his fingers
639 if (cov->n_taps == 0)
640 cov->hover_gesture.state = GESTURE_NOT_STARTED;
643 static void _get_root_coords(Ecore_X_Window win, int *x, int *y)
645 Ecore_X_Window root = ecore_x_window_root_first_get();
646 Ecore_X_Window parent = ecore_x_window_parent_get(win);
652 while (parent && (root != parent))
654 ecore_x_window_geometry_get(parent, &wx, &wy, NULL, NULL);
657 parent = ecore_x_window_parent_get(parent);
662 start_scroll(int x, int y)
664 Ecore_X_Window under = ecore_x_window_at_xy_get(x, y);
665 _get_root_coords(under, &rx, &ry);
666 DEBUG("Send down: %d %d", x - rx, y - ry);
667 ecore_x_mouse_in_send(under, x - rx, y - ry);
668 ecore_x_window_focus(under);
669 ecore_x_mouse_down_send(under, x - rx, y - ry, 1);
670 scrolled_win = under;
674 continue_scroll(int x, int y)
676 DEBUG("Send move: %d %d", x - rx, y - ry);
677 ecore_x_mouse_move_send(scrolled_win, x - rx, y - ry);
681 end_scroll(int x, int y)
683 DEBUG("Send up: %d %d", x - rx, y - ry);
684 ecore_x_mouse_up_send(scrolled_win, x - rx, y - ry, 1);
685 ecore_x_mouse_out_send(scrolled_win, x - rx, y - ry);
691 Ecore_X_Window root, first_root;
695 unsigned char *prop_data = NULL;
697 first_root = ecore_x_window_root_first_get();
698 root = ecore_x_window_root_get(first_root);
699 ret = ecore_x_window_prop_property_get(root, ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE,
700 ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
702 if (ret && prop_data)
703 memcpy (&angle, prop_data, sizeof (int));
712 _hover_event_emit(Cover *cov, int state)
715 int ax = 0, ay = 0, j, tmp, w, h;
717 for (j = 0; j < cov->hover_gesture.n_fingers; j++)
719 ax += cov->hover_gesture.x[j];
720 ay += cov->hover_gesture.y[j];
723 ax /= cov->hover_gesture.n_fingers;
724 ay /= cov->hover_gesture.n_fingers;
726 win_angle = _win_angle_get();
730 root = ecore_x_window_root_first_get();
731 ecore_x_window_geometry_get(root, NULL, NULL, &w, &h);
738 root = ecore_x_window_root_first_get();
739 ecore_x_window_geometry_get(root, NULL, NULL, &w, &h);
746 switch (cov->hover_gesture.n_fingers)
749 INFO("ONE FINGER HOVER");
750 _event_emit(ONE_FINGER_HOVER, ax, ay, ax, ay, state, cov->event_time);
753 INFO("TWO FINGERS HOVER");
754 _event_emit(TWO_FINGERS_HOVER, ax, ay, ax, ay, state, cov->event_time);
756 start_scroll(ax, ay);
758 continue_scroll(ax, ay);
768 _hover_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
770 if (cov->hover_gesture.state == GESTURE_ONGOING)
774 if (!cov->hover_gesture.longpressed)
777 for (i = 0; i < cov->hover_gesture.n_fingers; i++)
779 if (cov->hover_gesture.finger[i] == ev->multi.device)
782 if (i == cov->hover_gesture.n_fingers)
784 DEBUG("Invalid finger id: %d", ev->multi.device);
787 cov->hover_gesture.x[i] = ev->root.x;
788 cov->hover_gesture.y[i] = ev->root.y;
789 _hover_event_emit(cov, 1);
794 _tap_event_emit(Cover *cov, int state)
796 switch (cov->tap_gesture_data.n_taps)
799 if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
801 DEBUG("ONE_FINGER_SINGLE_TAP");
802 _event_emit(ONE_FINGER_SINGLE_TAP,
803 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
804 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
805 state, cov->event_time);
807 else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
809 DEBUG("TWO_FINGERS_SINGLE_TAP");
810 _event_emit(TWO_FINGERS_SINGLE_TAP,
811 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
812 cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1],
813 state, cov->event_time);
815 else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
817 DEBUG("THREE_FINGERS_SINGLE_TAP");
818 _event_emit(THREE_FINGERS_SINGLE_TAP,
819 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
820 cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2],
821 state, cov->event_time);
825 ERROR("Unknown tap");
829 if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
831 DEBUG("ONE_FINGER_DOUBLE_TAP");
832 _event_emit(ONE_FINGER_DOUBLE_TAP,
833 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
834 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
835 state, cov->event_time);
837 else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
839 DEBUG("TWO_FINGERS_DOUBLE_TAP");
840 _event_emit(TWO_FINGERS_DOUBLE_TAP,
841 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
842 cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1],
843 state, cov->event_time);
845 else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
847 DEBUG("THREE_FINGERS_DOUBLE_TAP");
848 _event_emit(THREE_FINGERS_DOUBLE_TAP,
849 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
850 cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2],
851 state, cov->event_time);
855 ERROR("Unknown tap");
859 if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
861 DEBUG("ONE_FINGER_TRIPLE_TAP");
862 _event_emit(ONE_FINGER_TRIPLE_TAP,
863 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
864 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
865 state, cov->event_time);
867 else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
869 DEBUG("TWO_FINGERS_TRIPLE_TAP");
870 _event_emit(TWO_FINGERS_TRIPLE_TAP,
871 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
872 cov->tap_gesture_data.x_org[1], cov->tap_gesture_data.y_org[1],
873 state, cov->event_time);
875 else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
877 DEBUG("THREE_FINGERS_TRIPLE_TAP");
878 _event_emit(THREE_FINGERS_TRIPLE_TAP,
879 cov->tap_gesture_data.x_org[0], cov->tap_gesture_data.y_org[0],
880 cov->tap_gesture_data.x_org[2], cov->tap_gesture_data.y_org[2],
881 state, cov->event_time);
885 ERROR("Unknown tap");
889 ERROR("Unknown tap");
895 _on_tap_timer_expire(void *data)
898 DEBUG("Timer expired");
900 if (cov->tap_gesture_data.started && !cov->tap_gesture_data.pressed)
901 _tap_event_emit(cov,2);
903 _tap_event_emit(cov,3);
906 cov->tap_gesture_data.started = EINA_FALSE;
907 cov->tap_gesture_data.timer = NULL;
908 cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE;
909 cov->tap_gesture_data.finger[0] = -1;
910 cov->tap_gesture_data.finger[1] = -1;
911 cov->tap_gesture_data.finger[2] = -1;
916 static int _tap_gesture_finger_check(Cover *cov, int x, int y)
918 int dx = x - cov->tap_gesture_data.x_org[0];
919 int dy = y - cov->tap_gesture_data.y_org[0];
921 if (cov->tap_gesture_data.finger[0] != -1 &&
922 (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius *
923 _e_mod_config->one_finger_tap_radius))
928 dx = x - cov->tap_gesture_data.x_org[1];
929 dy = y - cov->tap_gesture_data.y_org[1];
930 if (cov->tap_gesture_data.finger[1] != -1 &&
931 (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius *
932 _e_mod_config->one_finger_tap_radius))
937 dx = x - cov->tap_gesture_data.x_org[2];
938 dy = y - cov->tap_gesture_data.y_org[2];
939 if (cov->tap_gesture_data.finger[2] != -1 &&
940 (dx * dx + dy * dy < _e_mod_config->one_finger_tap_radius *
941 _e_mod_config->one_finger_tap_radius))
950 _tap_gestures_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
954 ERROR("Too many fingers");
958 cov->tap_gesture_data.pressed = EINA_TRUE;
960 if (cov->tap_gesture_data.started == EINA_FALSE)
962 DEBUG("First finger down");
963 cov->tap_gesture_data.started = EINA_TRUE;
964 cov->tap_gesture_data.finger[0] = ev->multi.device;
965 cov->tap_gesture_data.x_org[0] = ev->root.x;
966 cov->tap_gesture_data.y_org[0] = ev->root.y;
967 cov->tap_gesture_data.finger[1] = -1;
968 cov->tap_gesture_data.finger[2] = -1;
969 cov->tap_gesture_data.n_taps = 0;
970 cov->tap_gesture_data.timer = ecore_timer_add(
971 _e_mod_config->one_finger_tap_timeout,
972 _on_tap_timer_expire, cov);
973 cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE;
978 if (ev->multi.device == cov->tap_gesture_data.finger[0])
980 DEBUG("First finger down");
982 if (_tap_gesture_finger_check(cov, ev->root.x, ev->root.y) == -1)
984 ERROR("Abort gesture");
985 cov->tap_gesture_data.started = EINA_FALSE;
986 ecore_timer_del(cov->tap_gesture_data.timer);
987 cov->tap_gesture_data.timer = NULL;
988 cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE;
989 cov->tap_gesture_data.finger[0] = -1;
990 cov->tap_gesture_data.finger[1] = -1;
991 cov->tap_gesture_data.finger[2] = -1;
992 _tap_gestures_mouse_down(ev, cov);
996 cov->tap_gesture_data.x_org[0] = ev->root.x;
997 cov->tap_gesture_data.y_org[0] = ev->root.y;
999 else if (cov->tap_gesture_data.finger[1] == -1 ||
1000 cov->tap_gesture_data.finger[1] == ev->multi.device)
1002 DEBUG("Second finger down");
1003 cov->tap_gesture_data.finger[1] = ev->multi.device;
1005 cov->tap_gesture_data.x_org[1] = ev->root.x;
1006 cov->tap_gesture_data.y_org[1] = ev->root.y;
1007 if (cov->tap_gesture_data.tap_type < TWO_FINGERS_GESTURE)
1008 cov->tap_gesture_data.tap_type = TWO_FINGERS_GESTURE;
1010 else if (cov->tap_gesture_data.finger[2] == -1 ||
1011 cov->tap_gesture_data.finger[2] == ev->multi.device)
1013 DEBUG("Third finger down");
1014 cov->tap_gesture_data.finger[2] = ev->multi.device;
1016 cov->tap_gesture_data.x_org[2] = ev->root.x;
1017 cov->tap_gesture_data.y_org[2] = ev->root.y;
1018 if (cov->tap_gesture_data.tap_type < THREE_FINGERS_GESTURE)
1019 cov->tap_gesture_data.tap_type = THREE_FINGERS_GESTURE;
1023 ERROR("Unknown finger down");
1025 ecore_timer_reset(cov->tap_gesture_data.timer);
1030 _tap_gestures_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
1032 if (cov->tap_gesture_data.timer)
1034 cov->tap_gesture_data.pressed = EINA_FALSE;
1036 if (ev->multi.device == cov->tap_gesture_data.finger[0])
1038 DEBUG("First finger up");
1040 int dx = ev->root.x - cov->tap_gesture_data.x_org[0];
1041 int dy = ev->root.y - cov->tap_gesture_data.y_org[0];
1043 if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1044 _e_mod_config->one_finger_tap_radius)
1046 if (cov->n_taps == 0)
1048 cov->tap_gesture_data.n_taps++;
1053 ERROR("Abort gesture");
1054 cov->tap_gesture_data.started = EINA_FALSE;
1057 else if (ev->multi.device == cov->tap_gesture_data.finger[1])
1059 DEBUG("Second finger up");
1061 int dx = ev->root.x - cov->tap_gesture_data.x_org[1];
1062 int dy = ev->root.y - cov->tap_gesture_data.y_org[1];
1064 if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1065 _e_mod_config->one_finger_tap_radius)
1067 if (cov->n_taps == 0)
1069 cov->tap_gesture_data.n_taps++;
1074 ERROR("Abort gesture");
1075 cov->tap_gesture_data.started = EINA_FALSE;
1078 else if (ev->multi.device == cov->tap_gesture_data.finger[2])
1080 DEBUG("Third finger up");
1082 int dx = ev->root.x - cov->tap_gesture_data.x_org[2];
1083 int dy = ev->root.y - cov->tap_gesture_data.y_org[2];
1085 if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1086 _e_mod_config->one_finger_tap_radius)
1088 if (cov->n_taps == 0)
1090 cov->tap_gesture_data.n_taps++;
1095 ERROR("Abort gesture");
1096 cov->tap_gesture_data.started = EINA_FALSE;
1101 ERROR("Unknown finger up, abort gesture");
1102 cov->tap_gesture_data.started = EINA_FALSE;
1108 _tap_gestures_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
1111 for (i = 0; i < sizeof(cov->tap_gesture_data.finger)/sizeof(cov->tap_gesture_data.finger[0]); i++)
1113 if (ev->multi.device == cov->tap_gesture_data.finger[i])
1115 int dx = ev->root.x - cov->tap_gesture_data.x_org[i];
1116 int dy = ev->root.y - cov->tap_gesture_data.y_org[i];
1118 if((dx * dx + dy * dy) > _e_mod_config->one_finger_tap_radius *
1119 _e_mod_config->one_finger_tap_radius)
1121 DEBUG("abort tap gesutre");
1122 cov->tap_gesture_data.started = EINA_FALSE;
1123 ecore_timer_del(cov->tap_gesture_data.timer);
1124 cov->tap_gesture_data.timer = NULL;
1125 cov->tap_gesture_data.tap_type = ONE_FINGER_GESTURE;
1126 cov->tap_gesture_data.finger[0] = -1;
1127 cov->tap_gesture_data.finger[1] = -1;
1128 cov->tap_gesture_data.finger[2] = -1;
1136 _cb_mouse_down(void *data EINA_UNUSED,
1137 int type EINA_UNUSED,
1140 Ecore_Event_Mouse_Button *ev = event;
1143 cov->event_time = ev->timestamp;
1145 DEBUG("mouse down: multi.device: %d, taps: %d", ev->multi.device, cov->n_taps);
1147 win_angle = _win_angle_get();
1149 _flick_gesture_mouse_down(ev, cov);
1150 _hover_gesture_mouse_down(ev, cov);
1151 _tap_gestures_mouse_down(ev, cov);
1153 return ECORE_CALLBACK_PASS_ON;
1157 _cb_mouse_up(void *data EINA_UNUSED,
1158 int type EINA_UNUSED,
1161 Ecore_Event_Mouse_Button *ev = event;
1164 cov->event_time = ev->timestamp;
1166 DEBUG("mouse up, multi.device: %d, taps: %d", ev->multi.device, cov->n_taps);
1168 _flick_gesture_mouse_up(ev, cov);
1169 _hover_gesture_mouse_up(ev, cov);
1170 _tap_gestures_mouse_up(ev, cov);
1172 return ECORE_CALLBACK_PASS_ON;
1176 _cb_mouse_move(void *data EINA_UNUSED,
1177 int type EINA_UNUSED,
1180 Ecore_Event_Mouse_Move *ev = event;
1182 cov->event_time = ev->timestamp;
1184 _flick_gesture_mouse_move(ev, cov);
1185 _hover_gesture_mouse_move(ev, cov);
1186 _tap_gestures_move(ev, cov);
1188 return ECORE_CALLBACK_PASS_ON;
1191 Eina_Bool screen_reader_gestures_init(void)
1196 if (!ecore_x_pointer_grab(ecore_x_window_root_first_get()))
1198 ERROR("Failed to grab pointer on: %x", ecore_x_window_root_first_get());
1201 if (!ecore_x_input_touch_devices_grab(ecore_x_window_root_first_get()))
1203 ERROR("Failed to grab devices on: %x", ecore_x_window_root_first_get());
1204 ecore_x_pointer_ungrab();
1208 ecore_x_input_multi_select(ecore_x_window_root_first_get());
1209 _e_mod_config = calloc(sizeof(Gestures_Config), 1);
1210 cov = calloc(sizeof(Cover), 1);
1212 _e_mod_config->one_finger_flick_min_length = 100;
1213 _e_mod_config->one_finger_flick_max_time = 400;
1214 _e_mod_config->one_finger_hover_longpress_timeout = 0.81;
1215 _e_mod_config->two_fingers_hover_longpress_timeout = 0.1;
1216 _e_mod_config->one_finger_tap_timeout = 0.4;
1217 _e_mod_config->one_finger_tap_radius = 100;
1219 handlers = eina_list_append(NULL, ecore_event_handler_add(ECORE_EVENT_MOUSE_MOVE, _cb_mouse_move, NULL));
1220 handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, _cb_mouse_up, NULL));
1221 handlers = eina_list_append(handlers, ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _cb_mouse_down, NULL));
1226 void screen_reader_gestures_shutdown(void)
1228 Ecore_Event_Handler *hdlr;
1229 EINA_LIST_FREE(handlers, hdlr)
1231 ecore_event_handler_del(hdlr);
1234 ecore_x_input_touch_devices_ungrab();
1235 ecore_x_pointer_ungrab();
1238 free(_e_mod_config);
1242 void screen_reader_gestures_tracker_register(GestureCB cb, void *data)
1245 _global_data = data;