[LICENSE] change to Flora-1.1 license
[profile/tv/apps/native/screen-reader.git] / src / screen_reader_gestures.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
3  *
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
8  *
9  *     http://floralicense.org/license/
10  *
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.
16  *
17  * Please, see the LICENSE file for the original copyright owner and
18  * license.
19  */
20
21 #include "screen_reader_gestures.h"
22 #include "logger.h"
23
24 #include <Ecore.h>
25 #include <Ecore_Input.h>
26 #include <Ecore_X.h>
27
28 static GestureCB _global_cb;
29 static void *_global_data;
30
31 struct _Gestures_Config
32 {
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;
45 };
46 typedef struct _Gestures_Config Gestures_Config;
47
48 typedef enum
49 {
50    FLICK_DIRECTION_UNDEFINED,
51    FLICK_DIRECTION_DOWN,
52    FLICK_DIRECTION_UP,
53    FLICK_DIRECTION_LEFT,
54    FLICK_DIRECTION_RIGHT,
55    FLICK_DIRECTION_DOWN_RETURN,
56    FLICK_DIRECTION_UP_RETURN,
57    FLICK_DIRECTION_LEFT_RETURN,
58    FLICK_DIRECTION_RIGHT_RETURN,
59 } flick_direction_e;
60
61 typedef enum
62 {
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
67 } gesture_state_e;
68
69 typedef enum
70 {
71    ONE_FINGER_GESTURE = 1,
72    TWO_FINGERS_GESTURE,
73    THREE_FINGERS_GESTURE
74 } gesture_type_e;
75
76 struct _Cover
77 {
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;
81
82    struct
83    {
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];
95    } flick_gesture;
96
97    struct
98    {
99       gesture_state_e state;   // currest gesture state
100       int x[2], y[2];
101       int n_fingers;
102       int finger[2];
103       unsigned int timestamp; // time of gesture;
104       unsigned int last_emission_time; // last time of gesture emission
105       Ecore_Timer *timer;
106       Eina_Bool longpressed;
107    } hover_gesture;
108
109    struct
110    {
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;
118    } tap_gesture_data;
119 };
120 typedef struct _Cover Cover;
121
122 Gestures_Config *_e_mod_config;
123 static Ecore_X_Window scrolled_win;
124 static int rx, ry;
125 static Eina_List *handlers;
126 static Cover *cov;
127 static int win_angle;
128
129 static void _hover_event_emit(Cover *cov, int state);
130
131 static void _event_emit(Gesture g, int x, int y, int x_e, int y_e, int state, int event_time)
132 {
133    Gesture_Info *info = calloc(sizeof(Gesture_Info), 1);
134    EINA_SAFETY_ON_NULL_RETURN(info);
135
136    info->type = g;
137    info->x_beg = x;
138    info->x_end = x_e;
139    info->y_beg = y;
140    info->y_end = y_e;
141    info->state = state;
142    info->event_time = event_time;
143
144    if (_global_cb)
145       _global_cb(_global_data, info);
146    free(info);
147 }
148
149 static void
150 _flick_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
151 {
152    if (cov->flick_gesture.state == GESTURE_NOT_STARTED)
153       {
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;
164       }
165    else if (cov->flick_gesture.state == GESTURE_ONGOING)
166       {
167          // abort gesture if too many fingers touched screen
168          if ((cov->n_taps > 3) || (cov->flick_gesture.n_fingers > 2))
169             {
170                cov->flick_gesture.state = GESTURE_ABORTED;
171                return;
172             }
173
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 */
181            {
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;
184            }
185       }
186 }
187
188 static Eina_Bool
189 _flick_gesture_time_check(unsigned int event_time, unsigned int gesture_time)
190 {
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
193       return EINA_TRUE;
194    else
195       return EINA_FALSE;
196 }
197
198 static Eina_Bool
199 _flick_gesture_length_check(int x, int y, int x_org, int y_org)
200 {
201    int dx = x - x_org;
202    int dy = y - y_org;
203
204    if ((dx * dx + dy * dy) > (_e_mod_config->one_finger_flick_min_length *
205                               _e_mod_config->one_finger_flick_min_length))
206       return EINA_TRUE;
207    else
208       return EINA_FALSE;
209 }
210
211 static flick_direction_e
212 _flick_gesture_direction_get(int x, int y, int x_org, int y_org)
213 {
214    int dx = x - x_org;
215    int dy = y - y_org;
216    int tmp;
217
218    switch(win_angle)
219       {
220       case 90:
221          tmp = dx;
222          dx = -dy;
223          dy = tmp;
224          break;
225       case 270:
226          tmp = dx;
227          dx = dy;
228          dy = -tmp;
229          break;
230       }
231
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;
240
241    return FLICK_DIRECTION_UNDEFINED;
242 }
243
244 static void
245 _flick_event_emit(Cover *cov)
246 {
247    int ax, ay, axe, aye, i, type = -1;
248    ax = ay = axe = aye = 0;
249
250    for (i = 0; i < cov->flick_gesture.n_fingers; i++)
251       {
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];
256       }
257
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;
262
263    if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT)
264       {
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;
271       }
272    else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT)
273       {
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;
280       }
281    else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP)
282       {
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;
289       }
290    else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN)
291       {
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;
298       }
299    else if (cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN)
300       {
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;
307       }
308    else if (cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN)
309       {
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;
316       }
317    else if (cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN)
318       {
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;
325       }
326    else if (cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN)
327       {
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;
334       }
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);
337 }
338
339 static void
340 _flick_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
341 {
342    if (cov->flick_gesture.state == GESTURE_ONGOING)
343       {
344          int i;
345          // check if fingers match
346          for (i = 0; i < cov->flick_gesture.n_fingers; i++)
347             {
348                if (cov->flick_gesture.finger[i] == ev->multi.device)
349                   break;
350             }
351          if (i == cov->flick_gesture.n_fingers)
352             {
353                DEBUG("Finger id not recognized. Gesture aborted.");
354                cov->flick_gesture.state = GESTURE_ABORTED;
355                goto end;
356             }
357
358          // check if flick for given finger is valid
359          if (!_flick_gesture_time_check(ev->timestamp,
360                                         cov->flick_gesture.timestamp[i]))
361             {
362                DEBUG("finger flick gesture timeout expired. Gesture aborted.");
363                cov->flick_gesture.state = GESTURE_ABORTED;
364                goto end;
365             }
366
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]))
371             {
372                if (!cov->flick_gesture.finger_out[i])
373                   {
374                      DEBUG("Minimal gesture length not reached and no return flick. Gesture aborted.");
375                      cov->flick_gesture.state = GESTURE_ABORTED;
376                      goto end;
377                   }
378                cov->flick_gesture.return_flick[i] = EINA_TRUE;
379             }
380
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]);
386
387          cov->flick_gesture.n_fingers_left--;
388
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)
392             {
393                DEBUG("Flick gesture");
394                cov->flick_gesture.dir = s;
395             }
396
397          // gesture is valid only if all flicks are in same direction
398          if (cov->flick_gesture.dir != s)
399             {
400                DEBUG("Flick in different direction. Gesture aborted.");
401                cov->flick_gesture.state = GESTURE_ABORTED;
402                goto end;
403             }
404
405          cov->flick_gesture.x_end[i] = ev->root.x;
406          cov->flick_gesture.y_end[i] = ev->root.y;
407
408          if (!cov->flick_gesture.n_fingers_left)
409             {
410                _flick_event_emit(cov);
411                cov->flick_gesture.state = GESTURE_NOT_STARTED;
412             }
413       }
414
415 end:
416    // if no finger is touching a screen, gesture will be reseted.
417    if ((cov->flick_gesture.state == GESTURE_ABORTED) && (cov->n_taps == 0))
418       {
419          DEBUG("Restet flick gesture");
420          cov->flick_gesture.state = GESTURE_NOT_STARTED;
421       }
422 }
423
424 static void
425 _flick_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
426 {
427    if (cov->flick_gesture.state == GESTURE_ONGOING)
428       {
429          int i;
430          for(i = 0; i < cov->flick_gesture.n_fingers; ++i)
431             {
432                if (cov->flick_gesture.finger[i] == ev->multi.device)
433                   break;
434             }
435          if (i == cov->flick_gesture.n_fingers)
436             {
437                if (cov->flick_gesture.n_fingers >= 3)   //that is because of the EFL bug. Mouse move event before mouse down(!)
438                   {
439                      ERROR("Finger id not recognized. Gesture aborted.");
440                      cov->flick_gesture.state = GESTURE_ABORTED;
441                      return;
442                   }
443             }
444          if(!cov->flick_gesture.finger_out[i])
445             {
446                int dx = ev->root.x - cov->flick_gesture.x_org[i];
447                int dy = ev->root.y - cov->flick_gesture.y_org[i];
448                int tmp;
449
450                switch(win_angle)
451                   {
452                   case 90:
453                      tmp = dx;
454                      dx = -dy;
455                      dy = tmp;
456                      break;
457                   case 270:
458                      tmp = dx;
459                      dx = dy;
460                      dy = -tmp;
461                      break;
462                   }
463
464                if (abs(dx) > _e_mod_config->one_finger_flick_min_length)
465                   {
466                      cov->flick_gesture.finger_out[i] = EINA_TRUE;
467                      if (dx > 0)
468                         {
469                            if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
470                                  cov->flick_gesture.dir == FLICK_DIRECTION_RIGHT_RETURN)
471                               {
472                                  cov->flick_gesture.dir = FLICK_DIRECTION_RIGHT_RETURN;
473                               }
474                            else
475                               {
476                                  ERROR("Invalid direction, abort");
477                                  cov->flick_gesture.state = GESTURE_ABORTED;
478                               }
479                         }
480                      else
481                         {
482                            if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
483                                  cov->flick_gesture.dir == FLICK_DIRECTION_LEFT_RETURN)
484                               {
485                                  cov->flick_gesture.dir = FLICK_DIRECTION_LEFT_RETURN;
486                               }
487                            else
488                               {
489                                  ERROR("Invalid direction, abort");
490                                  cov->flick_gesture.state = GESTURE_ABORTED;
491                               }
492                         }
493                      return;
494                   }
495
496                else if (abs(dy) > _e_mod_config->one_finger_flick_min_length)
497                   {
498                      cov->flick_gesture.finger_out[i] = EINA_TRUE;
499                      if (dy > 0)
500                         {
501                            if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
502                                  cov->flick_gesture.dir == FLICK_DIRECTION_DOWN_RETURN)
503                               {
504                                  cov->flick_gesture.dir = FLICK_DIRECTION_DOWN_RETURN;
505                               }
506                            else
507                               {
508                                  ERROR("Invalid direction, abort");
509                                  cov->flick_gesture.state = GESTURE_ABORTED;
510                               }
511                         }
512                      else
513                         {
514                            if (cov->flick_gesture.dir == FLICK_DIRECTION_UNDEFINED ||
515                                  cov->flick_gesture.dir == FLICK_DIRECTION_UP_RETURN)
516                               {
517                                  cov->flick_gesture.dir = FLICK_DIRECTION_UP_RETURN;
518                               }
519                            else
520                               {
521                                  ERROR("Invalid direction, abort");
522                                  cov->flick_gesture.state = GESTURE_ABORTED;
523                               }
524                         }
525                      return;
526                   }
527             }
528       }
529    return;
530 }
531
532 static Eina_Bool
533 _on_hover_timeout(void *data)
534 {
535    Cover *cov = data;
536    DEBUG("Hover timer expierd");
537
538    cov->hover_gesture.longpressed = EINA_TRUE;
539    cov->hover_gesture.timer = NULL;
540
541    if (cov->hover_gesture.last_emission_time == -1)
542       {
543          _hover_event_emit(cov, 0);
544          cov->hover_gesture.last_emission_time = cov->event_time;
545       }
546    return EINA_FALSE;
547 }
548
549 static void
550 _hover_gesture_timer_reset(Cover *cov, double time)
551 {
552    DEBUG("Hover timer reset");
553    cov->hover_gesture.longpressed = EINA_FALSE;
554    if (cov->hover_gesture.timer)
555       {
556          ecore_timer_reset(cov->hover_gesture.timer);
557          return;
558       }
559    cov->hover_gesture.timer = ecore_timer_add(time, _on_hover_timeout, cov);
560 }
561
562 static void
563 _hover_gesture_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
564 {
565    if (cov->hover_gesture.state == GESTURE_NOT_STARTED &&
566          cov->n_taps == 1)
567       {
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);
576       }
577    if (cov->hover_gesture.state == GESTURE_ONGOING &&
578          cov->n_taps == 2)
579       {
580          if (cov->hover_gesture.longpressed)
581             {
582                _hover_event_emit(cov, 2);
583                goto abort;
584             }
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);
592       }
593    // abort gesture if more then 2 fingers touched screen
594    if ((cov->hover_gesture.state == GESTURE_ONGOING) &&
595          cov->n_taps > 2)
596       {
597          DEBUG("More then 2 finged. Abort hover gesture");
598          _hover_event_emit(cov, 2);
599          goto abort;
600       }
601    return;
602
603 abort:
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;
608 }
609
610 static void
611 _hover_gesture_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
612 {
613    int i;
614    if (cov->hover_gesture.state == GESTURE_ONGOING)
615       {
616
617          for (i = 0; i < cov->hover_gesture.n_fingers; i++)
618             {
619                if (cov->hover_gesture.finger[i] == ev->multi.device)
620                   break;
621             }
622          if (i == cov->hover_gesture.n_fingers)
623             {
624                DEBUG("Invalid finger id: %d", ev->multi.device);
625                return;
626             }
627          else
628             {
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);
636             }
637       }
638    // reset gesture only if user released all his fingers
639    if (cov->n_taps == 0)
640       cov->hover_gesture.state = GESTURE_NOT_STARTED;
641 }
642
643 static void _get_root_coords(Ecore_X_Window win, int *x, int *y)
644 {
645    Ecore_X_Window root = ecore_x_window_root_first_get();
646    Ecore_X_Window parent = ecore_x_window_parent_get(win);
647    int wx, wy;
648
649    if (x) *x = 0;
650    if (y) *y = 0;
651
652    while (parent && (root != parent))
653       {
654          ecore_x_window_geometry_get(parent, &wx, &wy, NULL, NULL);
655          if (x) *x += wx;
656          if (y) *y += wy;
657          parent = ecore_x_window_parent_get(parent);
658       }
659 }
660
661 void
662 start_scroll(int x, int y)
663 {
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;
671 }
672
673 void
674 continue_scroll(int x, int y)
675 {
676    DEBUG("Send move: %d %d", x - rx, y - ry);
677    ecore_x_mouse_move_send(scrolled_win, x - rx, y - ry);
678 }
679
680 void
681 end_scroll(int x, int y)
682 {
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);
686 }
687
688 static unsigned int
689 _win_angle_get(void)
690 {
691    Ecore_X_Window root, first_root;
692    int ret;
693    int count;
694    int angle = 0;
695    unsigned char *prop_data = NULL;
696
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);
701
702    if (ret && prop_data)
703       memcpy (&angle, prop_data, sizeof (int));
704
705    if (prop_data)
706       free (prop_data);
707
708    return angle;
709 }
710
711 static void
712 _hover_event_emit(Cover *cov, int state)
713 {
714    Ecore_X_Window root;
715    int ax = 0, ay = 0, j, tmp, w, h;
716
717    for (j = 0; j < cov->hover_gesture.n_fingers; j++)
718       {
719          ax += cov->hover_gesture.x[j];
720          ay += cov->hover_gesture.y[j];
721       }
722
723    ax /= cov->hover_gesture.n_fingers;
724    ay /= cov->hover_gesture.n_fingers;
725
726    win_angle = _win_angle_get();
727    switch(win_angle)
728       {
729       case 90:
730          root = ecore_x_window_root_first_get();
731          ecore_x_window_geometry_get(root, NULL, NULL, &w, &h);
732          tmp = ax;
733          ax = h - ay;
734          ay = tmp;
735          break;
736
737       case 270:
738          root = ecore_x_window_root_first_get();
739          ecore_x_window_geometry_get(root, NULL, NULL, &w, &h);
740          tmp = ax;
741          ax = ay;
742          ay = w - tmp;
743          break;
744       }
745
746    switch (cov->hover_gesture.n_fingers)
747       {
748       case 1:
749          INFO("ONE FINGER HOVER");
750          _event_emit(ONE_FINGER_HOVER, ax, ay, ax, ay, state, cov->event_time);
751          break;
752       case 2:
753          INFO("TWO FINGERS HOVER");
754          _event_emit(TWO_FINGERS_HOVER, ax, ay, ax, ay, state, cov->event_time);
755          if (state == 0)
756             start_scroll(ax, ay);
757          else if (state == 1)
758             continue_scroll(ax, ay);
759          else if (state == 2)
760             end_scroll(ax, ay);
761          break;
762       default:
763          break;
764       }
765 }
766
767 static void
768 _hover_gesture_mouse_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
769 {
770    if (cov->hover_gesture.state == GESTURE_ONGOING)
771       {
772          // check fingers
773          int i;
774          if (!cov->hover_gesture.longpressed)
775             return;
776
777          for (i = 0; i < cov->hover_gesture.n_fingers; i++)
778             {
779                if (cov->hover_gesture.finger[i] == ev->multi.device)
780                   break;
781             }
782          if (i == cov->hover_gesture.n_fingers)
783             {
784                DEBUG("Invalid finger id: %d", ev->multi.device);
785                return;
786             }
787          cov->hover_gesture.x[i] = ev->root.x;
788          cov->hover_gesture.y[i] = ev->root.y;
789          _hover_event_emit(cov, 1);
790       }
791 }
792
793 static void
794 _tap_event_emit(Cover *cov, int state)
795 {
796    switch (cov->tap_gesture_data.n_taps)
797       {
798       case 1:
799          if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
800             {
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);
806             }
807          else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
808             {
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);
814             }
815          else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
816             {
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);
822             }
823          else
824             {
825                ERROR("Unknown tap");
826             }
827          break;
828       case 2:
829          if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
830             {
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);
836             }
837          else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
838             {
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);
844             }
845          else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
846             {
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);
852             }
853          else
854             {
855                ERROR("Unknown tap");
856             }
857          break;
858       case 3:
859          if(cov->tap_gesture_data.tap_type == ONE_FINGER_GESTURE)
860             {
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);
866             }
867          else if(cov->tap_gesture_data.tap_type == TWO_FINGERS_GESTURE)
868             {
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);
874             }
875          else if(cov->tap_gesture_data.tap_type == THREE_FINGERS_GESTURE)
876             {
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);
882             }
883          else
884             {
885                ERROR("Unknown tap");
886             }
887          break;
888       default:
889          ERROR("Unknown tap");
890          break;
891       }
892 }
893
894 static Eina_Bool
895 _on_tap_timer_expire(void *data)
896 {
897    Cover *cov = data;
898    DEBUG("Timer expired");
899
900    if (cov->tap_gesture_data.started && !cov->tap_gesture_data.pressed)
901       _tap_event_emit(cov,2);
902    else
903       _tap_event_emit(cov,3);
904
905    // finish gesture
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;
912
913    return EINA_FALSE;
914 }
915
916 static int _tap_gesture_finger_check(Cover *cov, int x, int y)
917 {
918    int dx = x - cov->tap_gesture_data.x_org[0];
919    int dy = y - cov->tap_gesture_data.y_org[0];
920
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))
924       {
925          return 0;
926       }
927
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))
933       {
934          return 1;
935       }
936
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))
942       {
943          return 2;
944       }
945
946    return -1;
947 }
948
949 static void
950 _tap_gestures_mouse_down(Ecore_Event_Mouse_Button *ev, Cover *cov)
951 {
952    if (cov->n_taps > 4)
953       {
954          ERROR("Too many fingers");
955          return;
956       }
957
958    cov->tap_gesture_data.pressed = EINA_TRUE;
959
960    if (cov->tap_gesture_data.started == EINA_FALSE)
961       {
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;
974       }
975
976    else
977       {
978          if (ev->multi.device == cov->tap_gesture_data.finger[0])
979             {
980                DEBUG("First finger down");
981
982                if (_tap_gesture_finger_check(cov, ev->root.x, ev->root.y) == -1)
983                   {
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);
993                      return;
994                   }
995
996                cov->tap_gesture_data.x_org[0] = ev->root.x;
997                cov->tap_gesture_data.y_org[0] = ev->root.y;
998             }
999          else if (cov->tap_gesture_data.finger[1] == -1 ||
1000                   cov->tap_gesture_data.finger[1] == ev->multi.device)
1001             {
1002                DEBUG("Second finger down");
1003                cov->tap_gesture_data.finger[1] = ev->multi.device;
1004
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;
1009             }
1010          else if (cov->tap_gesture_data.finger[2] == -1 ||
1011                   cov->tap_gesture_data.finger[2] == ev->multi.device)
1012             {
1013                DEBUG("Third finger down");
1014                cov->tap_gesture_data.finger[2] = ev->multi.device;
1015
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;
1020             }
1021          else
1022             {
1023                ERROR("Unknown finger down");
1024             }
1025          ecore_timer_reset(cov->tap_gesture_data.timer);
1026       }
1027 }
1028
1029 static void
1030 _tap_gestures_mouse_up(Ecore_Event_Mouse_Button *ev, Cover *cov)
1031 {
1032    if (cov->tap_gesture_data.timer)
1033       {
1034          cov->tap_gesture_data.pressed = EINA_FALSE;
1035
1036          if (ev->multi.device == cov->tap_gesture_data.finger[0])
1037             {
1038                DEBUG("First finger up");
1039
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];
1042
1043                if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1044                      _e_mod_config->one_finger_tap_radius)
1045                   {
1046                      if (cov->n_taps == 0)
1047                         {
1048                            cov->tap_gesture_data.n_taps++;
1049                         }
1050                   }
1051                else
1052                   {
1053                      ERROR("Abort gesture");
1054                      cov->tap_gesture_data.started = EINA_FALSE;
1055                   }
1056             }
1057          else if (ev->multi.device == cov->tap_gesture_data.finger[1])
1058             {
1059                DEBUG("Second finger up");
1060
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];
1063
1064                if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1065                      _e_mod_config->one_finger_tap_radius)
1066                   {
1067                      if (cov->n_taps == 0)
1068                         {
1069                            cov->tap_gesture_data.n_taps++;
1070                         }
1071                   }
1072                else
1073                   {
1074                      ERROR("Abort gesture");
1075                      cov->tap_gesture_data.started = EINA_FALSE;
1076                   }
1077             }
1078          else if (ev->multi.device == cov->tap_gesture_data.finger[2])
1079             {
1080                DEBUG("Third finger up");
1081
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];
1084
1085                if((dx * dx + dy * dy) < _e_mod_config->one_finger_tap_radius *
1086                      _e_mod_config->one_finger_tap_radius)
1087                   {
1088                      if (cov->n_taps == 0)
1089                         {
1090                            cov->tap_gesture_data.n_taps++;
1091                         }
1092                   }
1093                else
1094                   {
1095                      ERROR("Abort gesture");
1096                      cov->tap_gesture_data.started = EINA_FALSE;
1097                   }
1098             }
1099          else
1100             {
1101                ERROR("Unknown finger up, abort gesture");
1102                cov->tap_gesture_data.started = EINA_FALSE;
1103             }
1104       }
1105 }
1106
1107 static void
1108 _tap_gestures_move(Ecore_Event_Mouse_Move *ev, Cover *cov)
1109 {
1110    int i;
1111    for (i = 0; i < sizeof(cov->tap_gesture_data.finger)/sizeof(cov->tap_gesture_data.finger[0]); i++)
1112       {
1113          if (ev->multi.device == cov->tap_gesture_data.finger[i])
1114             {
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];
1117
1118                if((dx * dx + dy * dy) > _e_mod_config->one_finger_tap_radius *
1119                      _e_mod_config->one_finger_tap_radius)
1120                   {
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;
1129                   }
1130                break;
1131             }
1132       }
1133 }
1134
1135 static Eina_Bool
1136 _cb_mouse_down(void    *data EINA_UNUSED,
1137                int      type EINA_UNUSED,
1138                void    *event)
1139 {
1140    Ecore_Event_Mouse_Button *ev = event;
1141
1142    cov->n_taps++;
1143    cov->event_time = ev->timestamp;
1144
1145    DEBUG("mouse down: multi.device: %d, taps: %d", ev->multi.device, cov->n_taps);
1146
1147    win_angle = _win_angle_get();
1148
1149    _flick_gesture_mouse_down(ev, cov);
1150    _hover_gesture_mouse_down(ev, cov);
1151    _tap_gestures_mouse_down(ev, cov);
1152
1153    return ECORE_CALLBACK_PASS_ON;
1154 }
1155
1156 static Eina_Bool
1157 _cb_mouse_up(void    *data EINA_UNUSED,
1158              int      type EINA_UNUSED,
1159              void    *event)
1160 {
1161    Ecore_Event_Mouse_Button *ev = event;
1162
1163    cov->n_taps--;
1164    cov->event_time = ev->timestamp;
1165
1166    DEBUG("mouse up, multi.device: %d, taps: %d", ev->multi.device, cov->n_taps);
1167
1168    _flick_gesture_mouse_up(ev, cov);
1169    _hover_gesture_mouse_up(ev, cov);
1170    _tap_gestures_mouse_up(ev, cov);
1171
1172    return ECORE_CALLBACK_PASS_ON;
1173 }
1174
1175 static Eina_Bool
1176 _cb_mouse_move(void    *data EINA_UNUSED,
1177                int      type EINA_UNUSED,
1178                void    *event)
1179 {
1180    Ecore_Event_Mouse_Move *ev = event;
1181
1182    cov->event_time = ev->timestamp;
1183
1184    _flick_gesture_mouse_move(ev, cov);
1185    _hover_gesture_mouse_move(ev, cov);
1186    _tap_gestures_move(ev, cov);
1187
1188    return ECORE_CALLBACK_PASS_ON;
1189 }
1190
1191 Eina_Bool screen_reader_gestures_init(void)
1192 {
1193    ecore_init();
1194    ecore_x_init(NULL);
1195
1196    if (!ecore_x_pointer_grab(ecore_x_window_root_first_get()))
1197       {
1198          ERROR("Failed to grab pointer on: %x", ecore_x_window_root_first_get());
1199          return EINA_FALSE;
1200       }
1201    if (!ecore_x_input_touch_devices_grab(ecore_x_window_root_first_get()))
1202       {
1203          ERROR("Failed to grab devices on: %x", ecore_x_window_root_first_get());
1204          ecore_x_pointer_ungrab();
1205          return EINA_FALSE;
1206       }
1207
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);
1211
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;
1218
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));
1222
1223    return EINA_TRUE;
1224 }
1225
1226 void screen_reader_gestures_shutdown(void)
1227 {
1228    Ecore_Event_Handler *hdlr;
1229    EINA_LIST_FREE(handlers, hdlr)
1230    {
1231       ecore_event_handler_del(hdlr);
1232    }
1233
1234    ecore_x_input_touch_devices_ungrab();
1235    ecore_x_pointer_ungrab();
1236    ecore_x_shutdown();
1237    ecore_shutdown();
1238    free(_e_mod_config);
1239    free(cov);
1240 }
1241
1242 void screen_reader_gestures_tracker_register(GestureCB cb, void *data)
1243 {
1244    _global_cb = cb;
1245    _global_data = data;
1246 }