tizen 2.3.1 release
[adaptation/xorg/driver/xserver-xorg-input-gesture.git] / wearable / src / gesture.c
1 /**************************************************************************
2
3 xserver-xorg-input-gesture
4
5 Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
6
7 Contact: Sung-Jin Park <sj76.park@samsung.com>
8          Sangjin LEE <lsj119@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <linux/input.h>
37 #include <linux/types.h>
38
39 #include <xf86_OSproc.h>
40
41 #include <unistd.h>
42
43 #include <xf86.h>
44 #include <xf86Xinput.h>
45 #include <exevents.h>
46 #include <xorgVersion.h>
47 #include <xkbsrv.h>
48
49 #ifdef HAVE_PROPERTIES
50 #include <X11/Xatom.h>
51 #include <xserver-properties.h>
52 /* 1.6 has properties, but no labels */
53 #ifdef AXIS_LABEL_PROP
54 #define HAVE_LABELS
55 #else
56 #undef HAVE_LABELS
57 #endif
58
59 #endif
60
61 //#define __DETAIL_DEBUG__
62 //#define __DEBUG_EVENT_HANDLER__
63 //#define __PalmFlick_DEBUG__
64 //#define __HOLD_DETECTOR_DEBUG__
65
66 #ifdef __PalmFlick_DEBUG__
67 #define PalmFlickDebugPrint ErrorF
68 #else
69 #define PalmFlickDebugPrint(...)
70 #endif
71
72 #ifdef __HOLD_DETECTOR_DEBUG__
73 #define HoldDetectorDebugPrint ErrorF
74 #else
75 #define HoldDetectorDebugPrint(...)
76 #endif
77
78
79 #ifdef __DETAIL_DEBUG__
80 #define DetailDebugPrint ErrorF
81 #else
82 #define DetailDebugPrint(...)
83 #endif
84
85 #include <stdio.h>
86 #include <sys/stat.h>
87 #include <sys/syscall.h>
88 #include <unistd.h>
89 #include <errno.h>
90 #include <sys/types.h>
91 #include <fcntl.h>
92 #include <xorg-server.h>
93 #include <xorgVersion.h>
94 #include <xf86Module.h>
95 #include <X11/Xatom.h>
96 #include "gesture.h"
97 #include <xorg/mi.h>
98
99 #define LOG_TAG "GESTURE"
100 #include "dlog.h"
101
102
103
104 char *strcasestr(const char *s, const char *find);
105 extern ScreenPtr miPointerCurrentScreen(void);
106 static void printk(const char* fmt, ...) __attribute__((format(printf, 1, 0)));
107
108 //Basic functions
109 static int GesturePreInit(InputDriverPtr  drv, InputInfoPtr pInfo, int flags);
110 static void GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
111 static pointer GesturePlug(pointer module, pointer options, int *errmaj, int  *errmin);
112 static void GestureUnplug(pointer p);
113 static int GestureControl(DeviceIntPtr    device,int what);
114 static int GestureInit(DeviceIntPtr device);
115 static void GestureFini(DeviceIntPtr device);
116 static void GestureReadInput(InputInfoPtr pInfo);
117
118 //other initializers
119 ErrorStatus GestureRegionsInit(void);
120
121 //event queue handling functions
122 ErrorStatus GestureInitEQ(void);
123 ErrorStatus GestureFiniEQ(void);
124 ErrorStatus GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
125 ErrorStatus GestureEventsFlush(void);
126 void GestureEventsDrop(void);
127
128 //utility functions
129 ErrorStatus GestureRegionsReinit(void);
130 void GestureEnable(int enable, Bool prop, DeviceIntPtr dev);
131 void GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent);
132 void GestureCbEventsSelected(Window win, Mask *pEventMask);
133 WindowPtr GestureGetEventsWindow(void);
134 static int GestureGetFingerIndexFromDevice(DeviceIntPtr device);
135
136 //Enqueued event handlers and enabler/disabler
137 static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
138 static ErrorStatus GestureDisableEventHandler(void);
139 static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
140 static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
141 void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
142 void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
143 void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
144 void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
145 void GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
146 void GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
147
148 void GestureEmulateHWKey(DeviceIntPtr dev, int keycode);
149
150 //Gesture recognizer helper
151 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
152 static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
153 #endif
154 static WindowPtr GestureWindowOnXY(int x, int y);
155 Bool GestureHasFingerEventMask(int eventType, int num_finger);
156
157 //Gesture recognizer and handlers
158 void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device);
159 void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
160 void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction);
161 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
162 void GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
163 void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction);
164 void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy);
165 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds);
166 ErrorStatus GestureFlushOrDrop(void);
167
168 static int GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device);
169 static int GesturePalmGetAbsAxisInfo(DeviceIntPtr dev);
170 static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device);
171 static int GesturePalmGetScreenInfo();
172 static int GesturePalmGetHorizIndexWithX(int current_x, int idx, int type);
173
174 void GestureGenerateTouchCancelEvent(void);
175
176 static void GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata);
177
178 #ifdef HAVE_PROPERTIES
179 //function related property handling
180 static void GestureInitProperty(DeviceIntPtr dev);
181 static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly);
182 #endif
183
184 static Atom prop_gesture_recognizer_onoff = None;
185
186 #ifdef SUPPORT_ANR_WITH_INPUT_EVENT
187 static Atom prop_anr_in_input_event = None;
188 static Atom prop_anr_event_window = None;
189 static Window prop_anr_event_window_xid = None;
190 #endif
191
192
193 GestureDevicePtr g_pGesture = NULL;
194 _X_EXPORT InputDriverRec GESTURE = {
195     1,
196     "gesture",
197     NULL,
198     GesturePreInit,
199     GestureUnInit,
200     NULL,
201     0
202 };
203
204 static XF86ModuleVersionInfo GestureVersionRec =
205 {
206     "gesture",
207     MODULEVENDORSTRING,
208     MODINFOSTRING1,
209     MODINFOSTRING2,
210     XORG_VERSION_CURRENT,
211     PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
212     PACKAGE_VERSION_PATCHLEVEL,
213     ABI_CLASS_XINPUT,
214     ABI_XINPUT_VERSION,
215     MOD_CLASS_XINPUT,
216     {0, 0, 0, 0}
217 };
218
219 _X_EXPORT XF86ModuleData gestureModuleData =
220 {
221     &GestureVersionRec,
222     &GesturePlug,
223     &GestureUnplug
224 };
225
226 extern CallbackListPtr DPMSCallback;
227
228 static void
229 printk(const char* fmt, ...)
230 {
231     static FILE* fp = NULL;
232     static char init = 0;
233     va_list argptr;
234
235     if (!init && !fp)
236     {
237         fp = fopen("/dev/kmsg", "wt");
238         init = 1;
239     }
240
241     if (!fp) return;
242
243     va_start(argptr, fmt);
244     vfprintf(fp, fmt, argptr);
245     fflush(fp);
246     va_end(argptr);
247 }
248
249 #ifdef SUPPORT_ANR_WITH_INPUT_EVENT
250 static WindowPtr
251 _GestureFindANRWindow(DeviceIntPtr device)
252 {
253     WindowPtr root=NULL;
254     WindowPtr anr_window=NULL;
255     Window anr_xid=0;
256     PropertyPtr pProp;
257     int rc=0;
258
259     root = RootWindow(device);
260
261     if( prop_anr_event_window == None )
262         prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
263
264     rc = dixLookupProperty (&pProp, root, prop_anr_event_window, serverClient, DixReadAccess);
265     if (rc == Success && pProp->data){
266         anr_xid = *(int*)pProp->data;
267     }
268
269     if( anr_xid != 0 )
270     {
271         rc = dixLookupWindow(&anr_window, anr_xid, serverClient, DixSetPropAccess);
272         if( rc == BadWindow )
273         {
274             ErrorF("Can't find ANR window !!\n");
275             anr_window = NULL;
276         }
277         prop_anr_event_window_xid = anr_xid;
278     }
279
280     ErrorF("ANR Window is %#x. Ptr is %#x\n", anr_xid, anr_window);
281     return anr_window;
282 }
283 #endif
284
285 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
286 static Bool
287 PointInBorderSize(WindowPtr pWin, int x, int y)
288 {
289     BoxRec box;
290     if (pixman_region_contains_point (&pWin->borderSize, x, y, &box))
291     {
292         return TRUE;
293     }
294     return FALSE;
295 }
296 #endif
297
298 static WindowPtr
299 GestureWindowOnXY(int x, int y)
300 {
301     WindowPtr pWin;
302     BoxRec box;
303     SpritePtr pSprite;
304     DeviceIntPtr pDev = g_pGesture->master_pointer;
305
306     pSprite = pDev->spriteInfo->sprite;
307     pSprite->spriteTraceGood = 1;       /* root window still there */
308     pWin = RootWindow(pDev)->firstChild;
309
310     while (pWin)
311     {
312         if ((pWin->mapped) &&
313                 (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
314                 (x < pWin->drawable.x + (int)pWin->drawable.width +
315                  wBorderWidth(pWin)) &&
316                 (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
317                 (y < pWin->drawable.y + (int)pWin->drawable.height +
318                  wBorderWidth (pWin))
319                 /* When a window is shaped, a further check
320                  * is made to see if the point is inside
321                  * borderSize
322                  */
323                 && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
324                 && (!wInputShape(pWin) ||
325                     RegionContainsPoint(wInputShape(pWin),
326                         x - pWin->drawable.x,
327                         y - pWin->drawable.y, &box))
328 #ifdef ROOTLESS
329                 /* In rootless mode windows may be offscreen, even when
330                  * they're in X's stack. (E.g. if the native window system
331                  * implements some form of virtual desktop system).
332                  */
333                     && !pWin->rootlessUnhittable
334 #endif
335                     )
336                     {
337                         if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
338                         {
339                             pSprite->spriteTraceSize += 10;
340                             pSprite->spriteTrace = realloc(pSprite->spriteTrace,
341                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
342                             if (!pSprite->spriteTrace) {
343                                 return NULL;
344                             }
345                         }
346                         pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
347                         pWin = pWin->firstChild;
348                     }
349         else
350             pWin = pWin->nextSib;
351     }
352     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
353 }
354
355     Bool
356 GestureHasFingerEventMask(int eventType, int num_finger)
357 {
358     Bool ret = FALSE;
359     Mask eventmask = (1L << eventType);
360
361     if ((g_pGesture->grabMask & eventmask) &&
362             (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None))
363     {
364         DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has grabMask\n");
365         return TRUE;
366     }
367
368     if (g_pGesture->eventMask & eventmask)
369     {
370         DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has eventMask\n");
371         return TRUE;
372     }
373
374     DetailDebugPrint("[GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
375
376     return ret;
377 }
378
379 static CARD32
380 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
381 {
382     int event_type = *(int *)arg;
383
384     switch (event_type)
385     {
386         case GestureNotifyHold:
387             DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
388             GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
389             break;
390         case GestureNotifyTap:
391             DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
392             GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
393             break;
394         default:
395             DetailDebugPrint("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
396             if (timer)
397             {
398                 DetailDebugPrint("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer);
399             }
400     }
401
402     return 0;
403 }
404
405 void
406 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
407 {
408     Window target_win;
409     WindowPtr target_pWin;
410     xGestureNotifyTapEvent tev;
411
412     //skip non-tap events and single finger tap
413     if (!tap_repeat || num_finger <= 1)
414     {
415         return;
416     }
417
418     DetailDebugPrint("[GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n", num_finger, tap_repeat, cx, cy);
419
420     g_pGesture->recognized_gesture |= WTapFilterMask;
421     memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
422     tev.type = GestureNotifyTap;
423     tev.kind = GestureDone;
424     tev.num_finger = num_finger;
425     tev.tap_repeat = tap_repeat;
426     tev.interval = 0;
427     tev.cx = cx;
428     tev.cy = cy;
429
430     target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
431     target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
432
433     if (g_pGesture->grabMask && (target_win != None))
434     {
435         tev.window = target_win;
436     }
437     else
438     {
439         tev.window = g_pGesture->gestureWin;
440     }
441
442     DetailDebugPrint("[GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)tev.window, (unsigned int)g_pGesture->grabMask);
443
444     GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
445     LOGI("GroupTap Event done. 2 fingers %d tap!", tap_repeat);
446 }
447
448 void
449 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
450 {
451     if (num_of_fingers == 0)
452     {
453         Window target_win;
454         WindowPtr target_pWin;
455         xGestureNotifyFlickEvent fev;
456
457         DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction);
458
459         g_pGesture->recognized_gesture |= WPalmFlickFilterMask;
460
461         memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
462         fev.type = GestureNotifyFlick;
463         fev.kind = GestureDone;
464         fev.num_finger = num_of_fingers;
465         fev.distance = distance;
466         fev.duration = duration;
467         fev.direction = direction;
468
469         if (g_pGesture->GrabEvents)
470         {
471             target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
472             target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
473         }
474         else
475         {
476             target_win = None;
477             target_pWin = None;
478         }
479
480         if (g_pGesture->grabMask && (target_win != None))
481         {
482             fev.window = target_win;
483         }
484         else
485         {
486             fev.window = g_pGesture->gestureWin;
487         }
488
489         DetailDebugPrint("[GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
490
491         GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
492     }
493     else
494     {
495         DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction);
496
497         switch (direction)
498         {
499             case FLICK_NORTHWARD:
500                 DetailDebugPrint("[GestureHandleGesture_Flick] Flick Down \n");
501                 GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
502                 break;
503
504             case FLICK_SOUTHWARD:
505                 DetailDebugPrint("[GestureHandleGesture_Flick] Flick Up \n");
506                 GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
507                 break;
508             case FLICK_WESTWARD:
509                 if (g_pGesture->power_pressed == 2)
510                 {
511                     DetailDebugPrint("[GestureHandleGesture_Flick] Flick Right & power_pressed\n");
512                     GestureEmulateHWKey(g_pGesture->hwkey_dev, 122);
513                 }
514                 break;
515             default:
516                 break;
517         }
518         g_pGesture->recognized_gesture |= WFlickFilterMask;
519     }
520 }
521
522 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
523 {
524     Window target_win;
525     WindowPtr target_pWin;
526     xGestureNotifyHoldEvent hev;
527
528     DetailDebugPrint("[GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n", num_fingers, cx, cy, holdtime, kinds);
529
530     if (num_fingers == 0)
531     {
532         g_pGesture->hold_detected = TRUE;
533         LOGI("[PalmHold] PalmHold success !\n");
534     }
535     else
536     {
537         g_pGesture->recognized_gesture |= WHoldFilterMask;
538     }
539
540     memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
541     hev.type = GestureNotifyHold;
542     hev.kind = kinds;
543     hev.num_finger = num_fingers;
544     hev.holdtime = holdtime;
545     hev.cx = cx;
546     hev.cy = cy;
547
548     if (g_pGesture->GrabEvents)
549     {
550         target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
551         target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
552     }
553     else
554     {
555         target_win = None;
556         target_pWin = None;
557     }
558
559     if (g_pGesture->grabMask && (target_win != None))
560     {
561         hev.window = target_win;
562     }
563     else
564     {
565         hev.window = g_pGesture->gestureWin;
566     }
567
568     DetailDebugPrint("[GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
569
570     GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
571     LOGI("[GroupHold] GestureHold success !\n");
572 }
573
574
575 void
576 GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
577 {
578     static int num_pressed = 0;
579     static int base_area_size = 0;
580
581     int cx, cy;
582     int area_size;
583
584     static int state = 0;
585     static int mbits = 0;
586     static int base_cx;
587     static int base_cy;
588     static pixman_box16_t base_box_ext;
589
590     static int tap_repeat = 0;
591     static int prev_num_pressed = 0;
592
593     static OsTimerPtr tap_event_timer = NULL;
594     static int event_type = GestureNotifyTap;
595
596     if (timer_expired)
597     {
598         DetailDebugPrint("[GroupTap][Timer] state=%d, num_pressed=%d, tap_repeat=%d\n", state, num_pressed, tap_repeat);
599
600         switch (state)
601         {
602             case 1://first tap initiation check
603                 if (num_pressed)
604                 {
605                     DetailDebugPrint("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", num_pressed, tap_repeat);
606                     DetailDebugPrint("[GroupTap][F] 1\n");
607
608                     state = 0;
609                     goto cleanup_tap;
610                 }
611                 break;
612
613             case 2:
614                 if (tap_repeat <= 1)
615                 {
616                     state = 0;
617                     DetailDebugPrint("[GroupTap][Timer][state=2] 2 finger %d tap\n", tap_repeat);
618                     LOGI("[GroupTap][F] Second tap doesn't come up in 400ms after first tap.\n");
619                     goto cleanup_tap;
620                 }
621
622                 if (GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed))
623                 {
624                     DetailDebugPrint("[GroupTap] Success 1!! 2 finger %d tap\n", tap_repeat);
625                     GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
626                     goto cleanup_tap;
627                 }
628                 break;
629         }
630         return;
631     }
632
633     switch (type)
634     {
635         case ET_ButtonPress:
636             g_pGesture->fingers[idx].flags |= PressFlagTap;
637
638             if (g_pGesture->num_pressed < 2)
639             {
640                 DetailDebugPrint("[GroupTap][P] num_pressed=%d, base_px=%d, base_py=%d. return \n", g_pGesture->num_pressed, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
641                 return;
642             }
643
644             if ((!base_area_size || g_pGesture->num_pressed > num_pressed))
645             {
646                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
647                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
648                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
649                 base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
650                 base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
651                 base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
652                 base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
653                 state = 1;
654                 TimerCancel(tap_event_timer);
655                 tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->singletap_threshold, GestureEventTimerHandler, (int *)&event_type);
656             }
657             num_pressed = g_pGesture->num_pressed;
658
659             DetailDebugPrint("[GroupTap][P] num_pressed=%d, area_size=%d, base_mx=%d, base_my=%d\n", num_pressed, base_area_size, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
660             break;
661
662         case ET_Motion:
663             if (!(g_pGesture->fingers[idx].flags & PressFlagTap))
664             {
665                 break;
666             }
667
668             if (num_pressed < 2)
669             {
670                 DetailDebugPrint("[GroupTap][M] num_pressed=%d, return \n", num_pressed);
671                 return;
672             }
673
674             if (num_pressed != g_pGesture->num_pressed)
675             {
676                 DetailDebugPrint("[GroupTap][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
677             }
678
679             mbits |= (1 << idx);
680             if (mbits == (pow(2, num_pressed)-1))
681             {
682                 area_size = AREA_SIZE(&g_pGesture->area.extents);
683                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
684                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
685
686                 DetailDebugPrint("[GroupTap][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
687                 DetailDebugPrint("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, g_pGesture->fingers[idx].mx, ABS(cx-base_cx));
688                 DetailDebugPrint("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, g_pGesture->fingers[idx].my, ABS(cy-base_cy));
689
690                 if (ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD)
691                 {
692                     DetailDebugPrint("[GroupTap][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size));
693                     DetailDebugPrint("[GroupTap][F] 3\n");
694                     LOGI("[GroupTap][F] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size));
695
696                     goto cleanup_tap;
697                 }
698
699                 if (!INBOX(&base_box_ext, cx, cy))
700                 {
701                     DetailDebugPrint("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
702                     DetailDebugPrint("[GroupTap][F] 4\n");
703                     LOGI("[GroupTap][F] current center coordinates is not in base coordinates box !\n");
704
705                     goto cleanup_tap;
706                 }
707             }
708             break;
709
710         case ET_ButtonRelease:
711             if (g_pGesture->num_pressed)
712             {
713                 DetailDebugPrint("[GroupTap][R] Second finger doesn't come up. g_pGesture->num_pressed=%d\n", g_pGesture->num_pressed);
714                 break;
715             }
716
717             if (!tap_repeat)
718             {
719                 prev_num_pressed = num_pressed;
720             }
721
722             tap_repeat++;
723             g_pGesture->num_tap_repeated = tap_repeat;
724
725             DetailDebugPrint("[GroupTap][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
726             DetailDebugPrint("[GroupTap][R] base_rx=%d, base_ry=%d,\n", g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry);
727
728             if ((num_pressed != prev_num_pressed) || (!GestureHasFingerEventMask(GestureNotifyTap, num_pressed)))
729             {
730                 DetailDebugPrint("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
731                         num_pressed, prev_num_pressed, num_pressed);
732                 DetailDebugPrint("[GroupTap][F] 5\n");
733                 LOGI("[GroupTap][F] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
734                         num_pressed, prev_num_pressed, num_pressed);
735                 goto cleanup_tap;
736             }
737
738             if (tap_repeat == 1)
739             {
740                 DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
741                 TimerCancel(tap_event_timer);
742                 tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->doubletap_threshold, GestureEventTimerHandler, (int *)&event_type);
743                 state = 2;
744                 prev_num_pressed = num_pressed;
745                 num_pressed = 0;
746                 break;
747             }
748
749             else if (tap_repeat == 2)
750             {
751                 DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
752                 TimerCancel(tap_event_timer);
753                 tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->tripletap_threshold, GestureEventTimerHandler, (int *)&event_type);
754                 state = 2;
755                 base_area_size = num_pressed = 0;
756                 break;
757             }
758
759             DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
760
761             if (tap_repeat == MAX_TAP_REPEATS)
762             {
763                 if (GestureHasFingerEventMask(GestureNotifyTap, num_pressed))
764                 {
765                     DetailDebugPrint("[GroupTap] Sucess 2!\n");
766                     GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
767                 }
768                 goto cleanup_tap;
769             }
770
771             if (tap_repeat >= MAX_TAP_REPEATS)
772             {
773                 LOGI("[GroupTap][F] More than 3 taps. Ignore. \n");
774                 goto cleanup_tap;
775             }
776
777             prev_num_pressed = num_pressed;
778             num_pressed = 0;
779             break;
780     }
781
782     return;
783
784 cleanup_tap:
785
786     DetailDebugPrint("[GroupTap][cleanup_tap]\n");
787
788     if (0 == state)
789     {
790         g_pGesture->recognized_gesture &= ~WTapFilterMask;
791     }
792
793     g_pGesture->filter_mask |= WTapFilterMask;
794
795     if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
796     {
797         DetailDebugPrint("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
798
799         if (ERROR_INVALPTR == GestureFlushOrDrop())
800         {
801             GestureControl(g_pGesture->this_device, DEVICE_OFF);
802         }
803     }
804
805     num_pressed = 0;
806     g_pGesture->num_tap_repeated = tap_repeat = 0;
807     prev_num_pressed = 0;
808     mbits = 0;
809     state = 0;
810     TimerCancel(tap_event_timer);
811     return;
812 }
813
814 void
815 GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction)
816 {
817     static int num_pressed = 0;
818     static Time base_time = 0;
819     Time duration;
820     int distance;
821     static int diff_base_coord = 0;
822     static int diff_base_minor_coord = 0;
823     static int diff_current_coord = 0;
824     static int false_diff_count = 0;
825     static int false_minor_diff_count = 0;
826     static float angle = 0.0f;
827     static int angle_base_x = 0, angle_base_y = 0;
828     static int motion_count = 0;
829
830     if (g_pGesture->num_pressed > 1)
831     {
832         DetailDebugPrint("[GroupFlick][F] 1\n");
833         goto cleanup_flick;
834     }
835
836     if ((start_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= start_point))
837     {
838         DetailDebugPrint("[GroupFlick][F] 2\n");
839         goto cleanup_flick;
840     }
841
842     switch (type)
843     {
844         case ET_ButtonPress:
845             g_pGesture->fingers[idx].flags = PressFlagFlick;
846             base_time = GetTimeInMillis();
847             num_pressed = g_pGesture->num_pressed;
848             switch (start_point)
849             {
850                 case FLICK_POINT_UP:
851                     if (g_pGesture->fingers[idx].py > g_pGesture->flick_press_area)
852                     {
853                         DetailDebugPrint("[GroupFlick][FlickDown][P] press coord is out of bound. (%d, %d)\n",
854                                 g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
855                         DetailDebugPrint("[GroupFlick][F] 3\n");
856                         //LOGI("[BackKey][F] press coord is out of bound (40 pixel from upper vezel). press y=%d\n", g_pGesture->fingers[idx].py);
857                         goto cleanup_flick;
858                     }
859
860                     angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
861                     angle_base_x = g_pGesture->fingers[idx].px;
862                     DetailDebugPrint("[GroupFlick][FlickDown][P] px=%d, py=%d\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
863                     break;
864
865                 case FLICK_POINT_DOWN:
866                     if (g_pGesture->fingers[idx].py < g_pGesture->screen_height - g_pGesture->flick_press_area)
867                     {
868                         DetailDebugPrint("[GroupFlick][FlickUp][P] press coord is out of bound. (%d, %d)\n",
869                                 g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
870                         DetailDebugPrint("[GroupFlick][F] 4\n");
871                         goto cleanup_flick;
872                     }
873                     angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
874                     angle_base_x = g_pGesture->fingers[idx].px;
875                     break;
876
877                 case FLICK_POINT_LEFT:
878                     if (g_pGesture->fingers[idx].px > g_pGesture->flick_press_area)
879                     {
880                         DetailDebugPrint("[GroupFlick][FlickLeft][P] press coord is out of bound. (%d, %d)\n",
881                                 g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
882                         DetailDebugPrint("[GroupFlick][F] 5\n");
883                         goto cleanup_flick;
884                     }
885                     angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
886                     angle_base_x = g_pGesture->fingers[idx].px;
887                     break;
888
889                 default:
890                     DetailDebugPrint("[GroupFlick][F] 6\n");
891                     goto cleanup_flick;
892                     break;
893             }
894
895             break;
896
897         case ET_Motion:
898
899             motion_count++;
900
901             if (motion_count > 15)
902             {
903                 DetailDebugPrint("[GroupFlick][F] 6-1 motion_count=%d\n", motion_count);
904                 LOGI("[BackKey][F] More than 15 motion.\n");
905                 goto cleanup_flick;
906             }
907
908             if (!(g_pGesture->fingers[idx].flags & PressFlagFlick))
909             {
910                 break;
911             }
912
913             switch (start_point)
914             {
915                 case FLICK_POINT_UP:
916                     diff_base_coord = diff_current_coord;
917                     diff_current_coord = g_pGesture->fingers[idx].my;
918
919                     if ((diff_current_coord - diff_base_coord) < 0)
920                     {
921                         DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff\n");
922                         false_diff_count++;
923                     }
924
925                     if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
926                     {
927                         DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff_count: %d > %d\n",
928                                 false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
929                         DetailDebugPrint("[GroupFlick][F] 7\n");
930                         LOGI("[BackKey][F] Direction is wrong for 7 times.\n");
931                         goto cleanup_flick;
932                     }
933
934                     if ((g_pGesture->fingers[idx].my < g_pGesture->flick_press_area) &&
935                             (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) >(int)( g_pGesture->screen_width/2)))
936                     {
937                         DetailDebugPrint("[GroupFlick][FlickDown][M] move x: %d - %d, y coord: %d\n",
938                                 g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].my);
939                         DetailDebugPrint("[GroupFlick][F] 8\n");
940                         LOGI("[BackKey][F] From press point, moving x axis is more than half screen size.\n");
941                         goto cleanup_flick;
942                     }
943
944                     if ((g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > g_pGesture->flick_minimum_height)
945                     {
946                         DetailDebugPrint("[GroupFlick][FlickDown][M] %d - %d < %d(min_size), angle_base_coord (%d, %d)\n",
947                                 g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height, angle_base_x, angle_base_y);
948
949                         if (abs(g_pGesture->fingers[idx].mx - angle_base_x) == 0)
950                         {
951                             DetailDebugPrint("[GroupFlick][FlickDown][M] abs(%d - %d) = 0\n",
952                                     g_pGesture->fingers[idx].mx, angle_base_x);
953                             angle = 1.0f;
954                         }
955                         else
956                         {
957                             DetailDebugPrint("[GroupFlick][FlickDown][M] angle_base_x: %d, angle_base_y: %d\n",
958                                     angle_base_x, angle_base_y);
959                             int y_diff = abs(g_pGesture->fingers[idx].my - angle_base_y);
960                             int x_diff = abs(g_pGesture->fingers[idx].mx - angle_base_x);
961                             angle = (float)y_diff / (float)x_diff;
962                         }
963
964                         if (angle < 0.23f)
965                         {
966                             DetailDebugPrint("[GroupFlick][FlickDown][M][F] %d / %d = %f (angle)\n",
967                                     abs(g_pGesture->fingers[idx].my - angle_base_y), abs(g_pGesture->fingers[idx].mx - angle_base_x), angle);
968                             DetailDebugPrint("[GroupFlick][F] 9\n");
969                             LOGI("[BackKey][F] angle is improper. %d < 0.23\n", angle);
970                             goto cleanup_flick;
971                         }
972
973                         distance = g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py;
974                         duration = GetTimeInMillis() - base_time;
975
976                         GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
977                         DetailDebugPrint("[GroupFlick][FlickDown][M] FlickDown Done!!\n");
978                         goto cleanup_flick_recognized;
979                     }
980                     else
981                     {
982                         if ((g_pGesture->fingers[idx].mx - diff_base_minor_coord) < 0)
983                         {
984                             false_minor_diff_count++;
985                         }
986
987                         if (false_minor_diff_count> FLICK_FALSE_X_DIFF_COUNT)
988                         {
989                             DetailDebugPrint("[GroupFlick][FlickDown][M] false_minor_diff_count: %d > %d\n",
990                                     false_minor_diff_count, FLICK_FALSE_X_DIFF_COUNT);
991                             DetailDebugPrint("[GroupFlick][F] 10\n");
992                             goto cleanup_flick;
993                         }
994                     }
995
996                     if (g_pGesture->fingers[idx].my < g_pGesture->flick_press_area)
997                     {
998                         angle_base_x = g_pGesture->fingers[idx].px;
999                         angle_base_y = g_pGesture->fingers[idx].py;
1000                     }
1001                     DetailDebugPrint("[GroupFlick][FlickDown][M] mx=%d, my=%d, diff_x=%d, diff_y=%d\n",
1002                             g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my, abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py));
1003
1004                     break;
1005
1006                 case FLICK_POINT_DOWN:
1007                     diff_base_coord = diff_current_coord;
1008                     diff_current_coord = g_pGesture->fingers[idx].my;
1009
1010                     if ((diff_base_coord - diff_current_coord) < 0)
1011                     {
1012                         false_diff_count++;
1013                     }
1014
1015                     if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
1016                     {
1017                         DetailDebugPrint("[GroupFlick][FlickUp][M] false_diff_count: %d > %d\n",
1018                                 false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
1019                         DetailDebugPrint("[GroupFlick][F] 11\n");
1020                         goto cleanup_flick;
1021                     }
1022
1023                     if ((g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my) > g_pGesture->flick_minimum_height)
1024                     {
1025                         DetailDebugPrint("[GroupFlick][FlickUp][R] %d - %d < %d(min_size)\n",
1026                                 g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height);
1027                         if (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) == 0)
1028                         {
1029                             DetailDebugPrint("[GroupFlick][FlickUp][R] abs(%d - %d) = 0\n",
1030                                     g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px);
1031                             angle = 1.0f;
1032                         }
1033                         else
1034                         {
1035                             int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
1036                             int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
1037                             angle = (float)y_diff / (float)x_diff;
1038                         }
1039
1040                         if (angle <0.5f)
1041                         {
1042                             DetailDebugPrint("[GroupFlick][FlickUp][R] %d / %d = %f (angle)\n",
1043                                     abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), angle);
1044                             DetailDebugPrint("[GroupFlick][F] 12\n");
1045                             goto cleanup_flick;
1046                         }
1047
1048                         distance = g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my;
1049                         duration = GetTimeInMillis() - base_time;
1050
1051                         GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
1052                         goto cleanup_flick_recognized;
1053                     }
1054                     break;
1055
1056                 case FLICK_POINT_LEFT:
1057                     diff_base_coord = diff_current_coord;
1058                     diff_current_coord = g_pGesture->fingers[idx].mx;
1059
1060                     if ((diff_current_coord - diff_base_coord) < 0)
1061                     {
1062                         false_diff_count++;
1063                     }
1064
1065                     if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
1066                     {
1067                         DetailDebugPrint("[GroupFlick][FlickLeft][M] false_diff_count: %d > %d\n",
1068                                 false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
1069                         DetailDebugPrint("[GroupFlick][F] 13\n");
1070                         goto cleanup_flick;
1071                     }
1072
1073                     if ((g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > g_pGesture->flick_minimum_height)
1074                     {
1075                         DetailDebugPrint("[GroupFlick][FlickLeft][M] %d - %d < %d(min_size)\n",
1076                                 g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->flick_minimum_height);
1077
1078                         if (abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) == 0)
1079                         {
1080                             DetailDebugPrint("[GroupFlick][FlickLeft][M] abs(%d - %d) = 0\n",
1081                                     g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py);
1082                             angle = 1.0f;
1083                         }
1084                         else
1085                         {
1086                             int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
1087                             int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
1088                             angle = (float)x_diff / (float)y_diff;
1089                         }
1090
1091                         if ( angle < 0.5f)
1092                         {
1093                             DetailDebugPrint("[GroupFlick][FlickLeft][M] %d / %d = %f (angle)\n",
1094                                     abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), angle);
1095                             DetailDebugPrint("[GroupFlick][F] 14\n");
1096                             goto cleanup_flick;
1097                         }
1098
1099                         distance = g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px;
1100                         duration = GetTimeInMillis() - base_time;
1101
1102                         GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
1103                         goto cleanup_flick_recognized;
1104                     }
1105
1106                     break;
1107                 default:
1108                     DetailDebugPrint("[GroupFlick][F] 15\n");
1109                     goto cleanup_flick;
1110                     break;
1111             }
1112             break;
1113
1114         case ET_ButtonRelease:
1115             DetailDebugPrint("[GroupFlick][R][F] 16\n");
1116             goto cleanup_flick;
1117             break;
1118     }
1119
1120     return;
1121
1122 cleanup_flick:
1123     DetailDebugPrint("[GroupFlick] cleanup_flick \n");
1124     g_pGesture->recognized_gesture &= ~WFlickFilterMask;
1125     motion_count = 0;
1126
1127 cleanup_flick_recognized:
1128     DetailDebugPrint("[GroupFlick] Flick recognized !\n");
1129     g_pGesture->filter_mask |= WFlickFilterMask;
1130     num_pressed = 0;
1131     base_time = 0;
1132     false_diff_count = 0;
1133     diff_base_coord = 0;
1134     diff_current_coord = 0;
1135     angle = 0.0f;
1136     angle_base_x = angle_base_y = 0;
1137     motion_count = 0;
1138     return;
1139 }
1140
1141 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1142 {
1143     static int num_pressed = 0;
1144     static int base_area_size = 0;
1145     static Time base_time = 0;
1146     static int base_cx;
1147     static int base_cy;
1148     int cx, cy;
1149     static pixman_box16_t base_box_ext;
1150     int area_size;
1151     static int state = GestureEnd;
1152
1153     static OsTimerPtr hold_event_timer = NULL;
1154     static int event_type = GestureNotifyHold;
1155
1156     if (timer_expired)
1157     {
1158         if (state <= GestureBegin)
1159         {
1160             state++;
1161         }
1162
1163         switch (state)
1164         {
1165             case GestureBegin:
1166                 DetailDebugPrint("[GroupHold] HOLD Begin !\n");
1167                 break;
1168
1169             case GestureUpdate:
1170                 DetailDebugPrint("[GroupHold] HOLD Update !\n");
1171                 break;
1172         }
1173
1174         if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed))
1175         {
1176             DetailDebugPrint("[GroupHold] Success 1! \n");
1177             GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1178
1179             // one more time
1180             hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
1181         }
1182         return;
1183     }
1184
1185     switch (type)
1186     {
1187         case ET_ButtonPress:
1188             g_pGesture->fingers[idx].flags |= PressFlagHold;
1189
1190             if (g_pGesture->num_pressed < 2)
1191             {
1192                 DetailDebugPrint("[GroupHold][P] No num_finger changed ! num_pressed=%d\n", num_pressed);
1193                 DetailDebugPrint("[GroupHold][F] 0\n");
1194                 return;
1195             }
1196
1197             if (!base_area_size || g_pGesture->num_pressed > num_pressed)
1198             {
1199                 if (state != GestureEnd)
1200                 {
1201                     DetailDebugPrint("[GroupHold][P][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1202                     DetailDebugPrint("[GroupHold][F] 1\n");
1203
1204                     goto cleanup_hold;
1205                 }
1206
1207                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1208                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1209                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1210                 base_time = GetTimeInMillis();
1211
1212                 base_box_ext.x1 = base_cx-g_pGesture->hold_move_threshold;
1213                 base_box_ext.y1 = base_cy-g_pGesture->hold_move_threshold;
1214                 base_box_ext.x2 = base_cx+g_pGesture->hold_move_threshold;
1215                 base_box_ext.y2 = base_cy+g_pGesture->hold_move_threshold;
1216
1217                 event_type = GestureNotifyHold;
1218
1219                 hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
1220             }
1221             num_pressed = g_pGesture->num_pressed;
1222
1223             DetailDebugPrint("[GroupHold][P] num_pressed=%d area_size=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
1224
1225             break;
1226
1227         case ET_Motion:
1228             if (!(g_pGesture->fingers[idx].flags & PressFlagHold))
1229             {
1230                 DetailDebugPrint("[GroupHold][M] No PressFlagHold\n");
1231                 break;
1232             }
1233
1234             if (num_pressed < 2)
1235             {
1236                 DetailDebugPrint("[GroupHold][M] No num_finger changed ! num_pressed=%d\n", num_pressed);
1237                 DetailDebugPrint("[GroupHold][F] 2\n");
1238                 return;
1239             }
1240
1241             if (num_pressed != g_pGesture->num_pressed)
1242             {
1243                 if (state != GestureEnd)
1244                 {
1245                     DetailDebugPrint("[GroupHold][M][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1246                     DetailDebugPrint("[GroupHold][F] 3\n");
1247                     goto cleanup_hold;
1248                 }
1249
1250                 DetailDebugPrint("[GroupHold][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1251             }
1252
1253             area_size = AREA_SIZE(&g_pGesture->area.extents);
1254             cx = AREA_CENTER_X(&g_pGesture->area.extents);
1255             cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1256
1257             DetailDebugPrint("[GroupHold][M] num_pressed=%d area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
1258             DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1259             DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1260
1261             if (area_size > 0 && base_area_size > 0)
1262             {
1263                 if (((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size) >= g_pGesture->hold_area_threshold)
1264                 {
1265                     DetailDebugPrint("[GroupHold][M] No diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%lf)!\n", area_size, base_area_size, ((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size));
1266                     DetailDebugPrint("[GroupHold][F] 4\n");
1267                     goto cleanup_hold;
1268                 }
1269             }
1270
1271             if (!INBOX(&base_box_ext, cx, cy))
1272             {
1273                 DetailDebugPrint("[GroupHold][M] No current center coordinates is not in base coordinates box !\n");
1274                 DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1275                 DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1276                 DetailDebugPrint("[GroupHold][F] 5\n");
1277                 goto cleanup_hold;
1278             }
1279             break;
1280
1281         case ET_ButtonRelease:
1282             if (state != GestureEnd && num_pressed >= 2)
1283             {
1284                 DetailDebugPrint("[GroupHold][R] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1285                 DetailDebugPrint("[GroupHold][F] 6\n");
1286                 goto cleanup_hold;
1287             }
1288
1289             if (g_pGesture->num_pressed)
1290             {
1291                 DetailDebugPrint("[GroupHold][R] num_pressed=%d\n", num_pressed);
1292                 DetailDebugPrint("[GroupHold][F] 7\n");
1293                 break;
1294             }
1295
1296             goto cleanup_hold;
1297             break;
1298     }
1299
1300     return;
1301
1302 cleanup_hold:
1303
1304     DetailDebugPrint("[GroupHold][cleanup_hold] enter!\n");
1305
1306     if (state == GestureBegin || state == GestureUpdate)
1307     {
1308         state = GestureEnd;
1309         if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed))
1310         {
1311             DetailDebugPrint("[GroupHold] Success 2!\n");
1312             GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1313         }
1314     }
1315     else
1316     {
1317         g_pGesture->recognized_gesture &= ~WHoldFilterMask;
1318     }
1319
1320     g_pGesture->filter_mask |= WHoldFilterMask;
1321     num_pressed = 0;
1322     base_area_size = 0;
1323     base_time = 0;
1324     base_cx = base_cy = 0;
1325     state = GestureEnd;
1326     base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1327     TimerCancel(hold_event_timer);
1328     return;
1329 }
1330
1331 int
1332 GestureGetMaxTmajor(InternalEvent *ev, int max_tmajor)
1333 {
1334     int mt_tmajor_idx = g_pGesture->tmajor_idx;
1335     int mt_tmajor = 0;
1336
1337     DeviceEvent *de = &ev->device_event;
1338
1339     if (!de)
1340     {
1341         DetailDebugPrint("[GestureGetMaxTmajor] de is NULL !\n");
1342         return -1;
1343     }
1344
1345     if (mt_tmajor_idx < 0)
1346     {
1347         DetailDebugPrint("[GestureGetMaxTmajor] One or more of axes are not supported !\n");
1348         return -1;
1349     }
1350
1351     mt_tmajor = de->valuators.data[mt_tmajor_idx];
1352
1353     DetailDebugPrint("[GestureGetMaxTmajor]mt_tmajor_idx=%d, mt_tmajor=%d, max_tmajor=%d\n", mt_tmajor_idx, mt_tmajor, max_tmajor);
1354
1355     return ((mt_tmajor > max_tmajor) ? mt_tmajor : max_tmajor);
1356
1357 }
1358
1359 void
1360 GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
1361 {
1362     //  static int num_pressed = 0;
1363     static int base_time = 0, current_time = 0;
1364     static int base_x[MAX_MT_DEVICES] = {0}, base_y[MAX_MT_DEVICES] = {0};
1365     static int update_x[MAX_MT_DEVICES] = {0}, update_y[MAX_MT_DEVICES] = {0};
1366
1367
1368     static int current_x[MAX_MT_DEVICES] = {0}, current_y[MAX_MT_DEVICES] = {0};
1369     static Bool press_status[MAX_MT_DEVICES] = {FALSE, FALSE};
1370     static Bool release_status[MAX_MT_DEVICES] = {FALSE, FALSE};
1371
1372     static int line_idx[MAX_MT_DEVICES] = {0}, prev_line_idx[MAX_MT_DEVICES] = {0}, press_idx[MAX_MT_DEVICES] = {0};
1373     static Bool is_line_invalid[MAX_MT_DEVICES] = {TRUE, TRUE};
1374
1375     static int max_tmajor[MAX_MT_DEVICES] = {0};
1376     static int total_max_tmajor = 0;
1377     static Bool is_tmajor_invalid[MAX_MT_DEVICES] = {TRUE, TRUE};
1378
1379     static int mt_sync_count[MAX_MT_DEVICES] = {0};
1380
1381     static Bool is_palm = FALSE;
1382     PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
1383
1384     static Bool is_retry = FALSE;
1385
1386     int distance, direction, duration;
1387
1388     if (g_pGesture->recognized_gesture && !(g_pGesture->recognized_gesture & WPalmFlickFilterMask))
1389     {
1390         PalmFlickDebugPrint("[PalmFlick] recognize other gesture already( g_pGesture->recognized_gesture: %d)\n", g_pGesture->recognized_gesture);
1391         PalmFlickDebugPrint("[PalmFlick][F] 1\n");
1392         goto flick_failed;
1393     }
1394
1395     // only first finger recognize
1396     if (!(idx == 0 || idx == 1))
1397     {
1398         PalmFlickDebugPrint("[PalmFlick] idx=%d, least two fingers come on\n", idx);
1399         return;
1400     }
1401
1402     switch (type)
1403     {
1404         case ET_ButtonPress:
1405
1406             if (!is_palm)
1407             {
1408                 if (idx == 0)
1409                 {
1410                     base_time = GetTimeInMillis();
1411                 }
1412
1413                 // press (x,y), touch major
1414                 update_x[idx] = base_x[idx] = g_pGesture->fingers[idx].px;
1415                 update_y[idx] = base_y[idx] = g_pGesture->fingers[idx].py;
1416                 max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx];
1417                 press_status[idx] = TRUE;
1418                 is_tmajor_invalid[idx] = FALSE;
1419                 is_line_invalid[idx] = FALSE;
1420
1421                 total_max_tmajor = (total_max_tmajor > max_tmajor[idx]) ? total_max_tmajor : max_tmajor[idx];
1422
1423                 // press region
1424                 press_idx[idx] = prev_line_idx[idx] = line_idx[idx] = GesturePalmGetHorizIndexWithX(base_x[idx], idx, type);
1425
1426                 PalmFlickDebugPrint("[PalmFlick][P] idx: %d, num_pressed: %d\n", idx, g_pGesture->num_pressed);
1427                 PalmFlickDebugPrint("[PalmFlick][P] base_time: %d, base_x: %d, base_y: %d, line_idx: %d, touch_major=%d\n",
1428                         base_time, base_x[idx], base_y[idx], line_idx[idx], max_tmajor[idx]);
1429
1430                 // invalid region
1431                 if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT)
1432                 {
1433                     PalmFlickDebugPrint("[PalmFlick][P][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]);
1434                     PalmFlickDebugPrint("[PalmFlick][F] 2\n");
1435                     goto flick_failed;
1436                 }
1437
1438                 // check press point when there are two fingers
1439                 if (idx == 1)
1440                 {
1441                     if (press_idx[0] != press_idx[1])
1442                     {
1443                         PalmFlickDebugPrint("[PalmFlick] Press line_idx is the different between two fingers. 1st finger_line_idx=%d, 2nd finger_line_idx=%d\n",
1444                                 press_idx[0], press_idx[1]);
1445                         PalmFlickDebugPrint("[PalmFlick][F] 2-1\n");
1446                         goto flick_failed;
1447                     }
1448                 }
1449             }
1450             else
1451             {
1452                 update_x[idx] = g_pGesture->fingers[idx].px;
1453                 update_y[idx] = g_pGesture->fingers[idx].py;
1454
1455                 PalmFlickDebugPrint("[PalmFlick][P] Already palm flick success. base_x=%d, base_y=%d, update_x=%d, update_y=%d\n",
1456                         base_x[idx], base_y[idx], update_x[idx], update_y[idx]);
1457             }
1458
1459             break;
1460
1461         case ET_Motion:
1462
1463             if (total_max_tmajor > g_pGesture->palm_flick_max_tmajor_threshold)
1464             {
1465                 mt_sync_count[idx]++;
1466                 is_palm = TRUE;
1467                 DetailDebugPrint("[PalmFlick][M] Sufficient touch enough ! max_tmajor=%d\n", total_max_tmajor);
1468                 break;
1469             }
1470
1471             // motion information (touch major, x, y)
1472             current_x[idx] = g_pGesture->fingers[idx].mx;
1473             current_y[idx] = g_pGesture->fingers[idx].my;
1474             max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx];
1475             mt_sync_count[idx]++;
1476
1477             //int temp_total_max_tmajor = (idx == 0 ? max_tmajor[0] : max_tmajor[0] + max_tmajor[1]);
1478             int temp_total_max_tmajor = max_tmajor[idx];
1479             total_max_tmajor = (total_max_tmajor > temp_total_max_tmajor ? total_max_tmajor : temp_total_max_tmajor);
1480
1481             PalmFlickDebugPrint("[PalmFlick][M] idx=%d, total_max_tmajor=%d, max_tmajor[0]=%d, max_tmajor[1]=%d, current current=(%d, %d)\n",
1482                     idx, total_max_tmajor, max_tmajor[0], max_tmajor[1], current_x[idx], current_y[idx]);
1483
1484             // exception vezel end line motion
1485             if (current_x[idx] < 5 || current_x[idx] > 355)
1486             {
1487                 if (total_max_tmajor >= g_pGesture->palm_flick_max_tmajor_threshold)
1488                 {
1489                     PalmFlickDebugPrint("[PalmFlick][M][Vezel] Sufficient touch major was came(%d)\n", total_max_tmajor);
1490                     is_palm = TRUE;
1491                 }
1492                 else
1493                 {
1494                     mt_sync_count[idx]--;
1495                     PalmFlickDebugPrint("[PalmFlick][M] Except vezel end line condition. x=%d, sync_count=%d \n",
1496                             current_x[idx], mt_sync_count[idx]);
1497                 }
1498                 break;
1499             }
1500
1501             // get current position
1502             line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type);
1503
1504             PalmFlickDebugPrint("[PalmFlick][M] line_idx: %d, prev_line_idx: %d, sync_count: %d\n",
1505                     line_idx[idx], prev_line_idx[idx], mt_sync_count[idx]);
1506
1507             //error check
1508             if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT)
1509             {
1510                 PalmFlickDebugPrint("[PalmFlick][M][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]);
1511                 PalmFlickDebugPrint("[PalmFlick][F] 3\n");
1512                 goto flick_failed;
1513             }
1514
1515             // screen capture motion validation
1516             if (line_idx[idx] != prev_line_idx[idx])
1517             {
1518                 if (base_x[idx] <= pPalmMisc->horiz_coord[0])
1519                 {
1520                     if (line_idx[idx] < prev_line_idx[idx])
1521                     {
1522                         PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[0]: %d\n",
1523                                 line_idx[idx], prev_line_idx[idx], pPalmMisc->horiz_coord[0]);
1524
1525                         is_line_invalid[idx] = TRUE;
1526
1527                         if (is_line_invalid[0] && is_line_invalid[1])
1528                         {
1529                             PalmFlickDebugPrint("[PalmFlick][F] 4\n");
1530                             goto flick_failed;
1531                         }
1532                     }
1533                 }
1534                 else if (base_x[idx] >= pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1])
1535                 {
1536                     if (line_idx[idx] > prev_line_idx[idx])
1537                     {
1538                         PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[%d]: %d\n",
1539                                 line_idx[idx], prev_line_idx[idx], PALM_HORIZ_ARRAY_COUNT-1, pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1]);
1540
1541                         is_line_invalid[idx] = TRUE;
1542
1543                         if (is_line_invalid[0] && is_line_invalid[1])
1544                         {
1545                             PalmFlickDebugPrint("[PalmFlick][F] 5\n");
1546                             goto flick_failed;
1547                         }
1548                     }
1549                 }
1550                 prev_line_idx[idx] = line_idx[idx];
1551             }
1552
1553             if (is_palm == FALSE)
1554             {
1555                 switch (mt_sync_count[idx])
1556                 {
1557                     case 1:
1558                         if (total_max_tmajor <= g_pGesture->palm_flick_min_tmajor_threshold)
1559                         {
1560                             PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
1561                                     mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_min_tmajor_threshold, line_idx[idx]);
1562                             PalmFlickDebugPrint("[PalmFlick][F] 6\n");
1563                             is_tmajor_invalid[idx] = TRUE;
1564                             //goto flick_failed;
1565                         }
1566                         break;
1567                     case 2:
1568                         if (total_max_tmajor <= (g_pGesture->palm_flick_max_tmajor_threshold - 10))
1569                         {
1570                             PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
1571                                     mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold-10, line_idx[idx]);
1572                             PalmFlickDebugPrint("[PalmFlick][F] 7\n");
1573                             is_tmajor_invalid[idx] = TRUE;
1574                             //goto flick_failed;
1575                         }
1576                         break;
1577                     case 3:
1578                         if (total_max_tmajor < g_pGesture->palm_flick_max_tmajor_threshold)
1579                         {
1580                             PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
1581                                     mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold, line_idx[idx]);
1582                             PalmFlickDebugPrint("[PalmFlick][F] 8\n");
1583                             is_tmajor_invalid[idx] = TRUE;
1584                             //goto flick_failed;
1585                         }
1586                         break;
1587                     default:
1588                         PalmFlickDebugPrint("[PalmFlick][M] See more next motion...\n");
1589                         break;
1590                 }
1591             }
1592
1593             if (is_tmajor_invalid[0] && is_tmajor_invalid[1])
1594             {
1595                 PalmFlickDebugPrint("[PalmFlick][M][F] max_tmajor=%d\n", total_max_tmajor);
1596                 goto flick_failed;
1597             }
1598
1599             current_time = GetTimeInMillis();
1600
1601             if (current_time - base_time > g_pGesture->palm_flick_time_threshold)
1602             {
1603                 PalmFlickDebugPrint("[PalmFlick][M][F] Release event were not came too long time (%d - %d > %d)\n", current_time, base_time, g_pGesture->palm_flick_time_threshold);
1604                 PalmFlickDebugPrint("[PalmFlick][F] 10\n");
1605                 goto flick_failed;
1606             }
1607
1608             break;
1609
1610         case ET_ButtonRelease:
1611             current_x[idx] = g_pGesture->fingers[idx].mx;
1612             current_y[idx] = g_pGesture->fingers[idx].my;
1613             release_status[idx] = TRUE;
1614
1615             if ((update_x[idx] == current_x[idx]) && (update_y[idx] == current_y[idx]))
1616             {
1617                 PalmFlickDebugPrint("[PalmFlick][R][F] Press point and release point are the same. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n",
1618                         update_x[idx], update_y[idx], current_x[idx], current_y[idx]);
1619                 PalmFlickDebugPrint("[PalmFlick][F] 10-1\n");
1620                 break;
1621                 //goto flick_failed;
1622             }
1623
1624             if (!is_palm)
1625             {
1626                 is_tmajor_invalid[idx] = TRUE;
1627
1628                 if (is_tmajor_invalid[0] && is_tmajor_invalid[1])
1629                 {
1630                     PalmFlickDebugPrint("[PalmFlick][R][F] Insufficient touch major was came(%d)\n", total_max_tmajor);
1631                     PalmFlickDebugPrint("[PalmFlick][F] 11\n");
1632                     goto flick_failed;
1633                 }
1634             }
1635
1636             line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type);
1637
1638             if (is_palm && line_idx[idx] == 1)
1639             {
1640                 PalmFlickDebugPrint("[PalmFlick][R] Enough major, but release. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n",
1641                         base_x[idx], base_y[idx], current_x[idx], current_y[idx]);
1642                 is_retry = TRUE;
1643                 mt_sync_count[idx] = 0;
1644                 break;
1645             }
1646
1647             if (line_idx[idx] < 0 || line_idx[idx] > PALM_HORIZ_ARRAY_COUNT - 1)
1648             {
1649                 is_line_invalid[idx] = TRUE;
1650
1651                 if (is_line_invalid[0] && is_line_invalid[1])
1652                 {
1653                     PalmFlickDebugPrint("[PalmFlick][R][F] No line_idx is invalid.. base_x: %d, current_x: %d\n", base_x[idx], current_x[idx]);
1654                     PalmFlickDebugPrint("[PalmFlick][F] 12\n");
1655                     goto flick_failed;
1656                 }
1657             }
1658
1659             current_time = GetTimeInMillis();
1660
1661             if (current_time - base_time > g_pGesture->palm_flick_time_threshold)
1662             {
1663                 PalmFlickDebugPrint("[PalmFlick][R][F] Release event were came to have long delay (%d - %d > %d)\n",
1664                         current_time, base_time, g_pGesture->palm_flick_time_threshold);
1665                 PalmFlickDebugPrint("[PalmFlick][F] 13\n");
1666                 goto flick_failed;
1667             }
1668
1669             direction = (line_idx[idx] <= 1) ? FLICK_EASTWARD : FLICK_WESTWARD;
1670             distance = ABS(current_x[idx] - base_x[idx]);
1671             duration = current_time - base_time;
1672
1673             if (!is_retry)
1674             {
1675                 if (GestureHasFingerEventMask(GestureNotifyFlick, 0))
1676                 {
1677                     PalmFlickDebugPrint("[PalmFlick][R] Palm Flick1 !!!, direction=%d, distance=%d\n", direction, distance);
1678                     is_palm = FALSE;
1679                     GestureHandleGesture_Flick(0, distance, duration, direction);
1680                 }
1681             }
1682             else
1683             {
1684                 if (mt_sync_count[idx] < 25)
1685                 {
1686                     PalmFlickDebugPrint("[PalmFlick][R][F] No enough motion=%d\n", mt_sync_count[idx]);
1687                     PalmFlickDebugPrint("[PalmFlick][F] 14\n");
1688                     goto flick_failed;
1689                 }
1690                 else
1691                 {
1692                     if (GestureHasFingerEventMask(GestureNotifyFlick, 0))
1693                     {
1694                         PalmFlickDebugPrint("[PalmFlick][R] Palm Flick2 !!!, direction=%d, distance=%d\n", direction, distance);
1695                         is_palm = FALSE;
1696                         GestureHandleGesture_Flick(0, distance, duration, direction);
1697                     }
1698                 }
1699             }
1700
1701             g_pGesture->recognized_gesture |= WPalmFlickFilterMask;
1702
1703             goto cleanup_flick;
1704             break;
1705     }
1706
1707     return;
1708
1709 flick_failed:
1710
1711     DetailDebugPrint("[PalmFlick][R] flick failed\n");
1712
1713     g_pGesture->recognized_gesture &= ~WPalmFlickFilterMask;
1714     g_pGesture->filter_mask |= WPalmFlickFilterMask;
1715     goto cleanup_flick;
1716
1717 cleanup_flick:
1718
1719     DetailDebugPrint("[PalmFlick][R] cleanup_flick\n");
1720
1721     for (int i = 0; i < MAX_MT_DEVICES; i++)
1722     {
1723         base_x[i] = 0;
1724         base_y[i] = 0;
1725         update_x[i] = 0;
1726         update_y[i] = 0;
1727         current_x[i] = 0;
1728         current_y[i] = 0;
1729         line_idx[i] = 0;
1730         press_idx[i] = 0;
1731         prev_line_idx[i] = 0;
1732         max_tmajor[i] = 0;
1733         mt_sync_count[i] = 0;
1734         press_status[i] = FALSE;
1735         release_status[i] = FALSE;
1736         is_tmajor_invalid[i] = TRUE;
1737         is_line_invalid[i] = TRUE;
1738     }
1739
1740     total_max_tmajor = 0;
1741     is_palm = FALSE;
1742     is_retry = FALSE;
1743
1744     return;
1745 }
1746
1747 static int
1748 GesturePalmGetHorizIndexWithX(int current_x, int idx, int type)
1749 {
1750     int i;
1751     int ret_idx = -1;
1752     static int pressed_idx[MAX_MT_DEVICES] = {-1, -1};
1753     PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
1754
1755     for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++)
1756     {
1757         if (current_x <= pPalmMisc->horiz_coord[i])
1758         {
1759             DetailDebugPrint("[GesturePalmGetHorizIndexWithX] index=%d, pPalmMisc->horiz_coord[%d]=%d\n", i, i, pPalmMisc->horiz_coord[i]);
1760
1761             ret_idx = i;
1762             goto index_check;
1763         }
1764     }
1765
1766     DetailDebugPrint("[GesturePalmGetHorizIndexWithX]Error ! Failed to get horiz coordinate index !\n");
1767     return ret_idx;
1768
1769 index_check:
1770
1771     if (type == ET_ButtonPress)
1772     {
1773         pressed_idx[idx] = ret_idx;
1774
1775         // first press is center
1776         if (pressed_idx[idx] == PALM_HORIZ_ARRAY_COUNT -2)
1777         {
1778             DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] Invalid press area x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]);
1779             ret_idx = -1;
1780         }
1781
1782         DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] pressed_idx=%d\n", pressed_idx[idx]);
1783     }
1784
1785     else if (type == ET_Motion)
1786     {
1787         DetailDebugPrint("[GesturePalmGetHorizIndexWithX][M] moving x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]);
1788     }
1789
1790     else if (type == ET_ButtonRelease)
1791     {
1792         if ((pressed_idx[idx] == 0) && (ret_idx == (PALM_HORIZ_ARRAY_COUNT - 1)))
1793         {
1794             DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the left to the right ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
1795         }
1796         else if ((pressed_idx[idx] == (PALM_HORIZ_ARRAY_COUNT - 1)) && (ret_idx == 0))
1797         {
1798             DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the right to the left ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
1799         }
1800         else if ((pressed_idx[idx] == ret_idx) && ret_idx != 1)
1801         {
1802             DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Relased the same region ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
1803             return 1;
1804         }
1805         else
1806         {
1807             DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Invalid ! pressed_idx=%d, released_idx=%d\n", pressed_idx[idx], ret_idx);
1808             ret_idx = -1;
1809         }
1810
1811         pressed_idx[idx] = -1;
1812     }
1813
1814     return ret_idx;
1815 }
1816
1817 static int
1818 GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
1819 {
1820     int i, found = 0;
1821     int numAxes;
1822
1823     Atom atom_tpalm;
1824     Atom atom_mt_slot;
1825     Atom atom_tracking_id;
1826     Atom atom_tmajor;
1827     Atom atom_tminor;
1828
1829     g_pGesture->tpalm_idx = -1;
1830     g_pGesture->tmajor_idx = -1;
1831     g_pGesture->tminor_idx = -1;
1832
1833     if (!dev || !dev->valuator)
1834         goto out;
1835
1836     numAxes = dev->valuator->numAxes;
1837
1838     atom_tpalm = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PALM);
1839     atom_mt_slot = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_SLOT);
1840     atom_tracking_id = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TRACKING_ID);
1841     atom_tmajor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR);
1842     atom_tminor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR);
1843
1844     if (!numAxes || !atom_tpalm || !atom_tmajor || !atom_tminor)
1845     {
1846         ErrorF("one or more axes is/are not supported!\n");
1847         goto out;
1848     }
1849
1850     for (i = 0; i < numAxes; i++)
1851     {
1852         AxisInfoPtr axes = &dev->valuator->axes[i];
1853
1854         if (!axes || (axes->mode != Absolute))
1855             continue;
1856
1857         if (axes->label == atom_tpalm)
1858         {
1859             g_pGesture->tpalm_idx = i;
1860             found += 1;
1861         }
1862         else if (axes->label == atom_tmajor)
1863         {
1864             g_pGesture->tmajor_idx = i;
1865             found += 2;
1866         }
1867         else if (axes->label == atom_tminor)
1868         {
1869             g_pGesture->tminor_idx = i;
1870             found += 4;
1871         }
1872     }
1873
1874     if (found != 7)
1875     {
1876         ErrorF("Axes for palm recognization are not supported !\n");
1877         goto out;
1878     }
1879
1880     g_pGesture->palm_misc.enabled = 1;
1881     ErrorF("Axes for palm recognization are supported !\n");
1882     return 1;
1883
1884 out:
1885     g_pGesture->palm_misc.enabled = 0;
1886     ErrorF("Palm recognization is not supported !\n");
1887     return 0;
1888 }
1889
1890 static int
1891 GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device)
1892 {
1893     int mt_palm_idx = g_pGesture->tpalm_idx;
1894     int mt_palm = 0;
1895
1896     DeviceEvent *de = &ev->device_event;
1897
1898     if (!de)
1899     {
1900         ErrorF("[GestureGetPalmValuator] de is NULL !\n");
1901         return -1;
1902     }
1903
1904     if (mt_palm_idx < 0)
1905     {
1906         ErrorF("[GestureGetPalmValuator] One or more of axes are not supported !\n");
1907         return -1;
1908     }
1909
1910     mt_palm = de->valuators.data[mt_palm_idx];
1911
1912     HoldDetectorDebugPrint("[GestureGetPalmValuator] mt_palm:%d\n", mt_palm);
1913
1914     return mt_palm;
1915 }
1916
1917 static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device)
1918 {
1919     int i;
1920     int idx = -1;
1921     pixman_region16_t tarea1;
1922     static int num_pressed = 0;
1923     unsigned int hold_area_size;
1924     PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
1925     int palm_flag = 0;
1926
1927     if (!g_pGesture->has_hold_grabmask)
1928     {
1929         HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->has_hold_grabmask=%d\n", g_pGesture->has_hold_grabmask);
1930
1931         Mask eventmask = (1L << GestureNotifyHold);
1932
1933         if ((g_pGesture->grabMask & eventmask) &&
1934                 (g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[0].window != None))
1935         {
1936             g_pGesture->has_hold_grabmask = 1;
1937
1938             //Initialize a set of variables
1939             num_pressed = 0;
1940             memset(&g_pGesture->cts, 0, sizeof(g_pGesture->cts));
1941             pixman_region_init(&g_pGesture->chold_area);
1942
1943             HoldDetectorDebugPrint("[GestureHoldDetector] Initialize...\n");
1944         }
1945         else
1946         {
1947             //reset local hold_grab_mask variable
1948             g_pGesture->has_hold_grabmask = 0;
1949
1950             g_pGesture->hold_detector_activate = 0;
1951             HoldDetectorDebugPrint("[GestureHoldDetector] has_hold_grabmask=0 and g_pGesture->hold_detector_activate=0\n");
1952             return;
1953         }
1954     }
1955
1956     if (IGNORE_EVENTS == g_pGesture->ehtype ||
1957             device->id < g_pGesture->first_fingerid)
1958     {
1959         HoldDetectorDebugPrint("[GestureHoldDetector] Return (IGNORE_EVENTS or device->id:%d < first_fingerid:%d)\n", device->id, g_pGesture->first_fingerid);
1960         return;
1961     }
1962
1963     palm_flag = GestureGetPalmValuator(ev, device);
1964
1965     if (palm_flag)
1966     {
1967         GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureBegin);
1968         GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureEnd);
1969
1970         g_pGesture->hold_detector_activate = 0;
1971         g_pGesture->has_hold_grabmask = 0;
1972         HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d enable\n", palm_flag);
1973         return;
1974     }
1975     else
1976     {
1977         HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d disable\n", palm_flag);
1978         return;
1979     }
1980
1981     HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->num_mt_devices:%d\n", g_pGesture->num_mt_devices);
1982
1983     for (i = 0; i < g_pGesture->num_mt_devices; i++)
1984     {
1985         if ( device->id == g_pGesture->mt_devices[i]->id)
1986         {
1987             idx = i;
1988             HoldDetectorDebugPrint("[GestureHoldDetector] idx:%d\n", idx);
1989             break;
1990         }
1991     }
1992     if ((idx < 0) || ((MAX_MT_DEVICES-1) < idx)) return;
1993
1994     switch (type)
1995     {
1996         case ET_ButtonPress:
1997             g_pGesture->cts[idx].status = BTN_PRESSED;
1998             g_pGesture->cts[idx].cx = ev->device_event.root_x;
1999             g_pGesture->cts[idx].cy = ev->device_event.root_y;
2000             num_pressed++;
2001             HoldDetectorDebugPrint("[GestureHoldDetector][P] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed);
2002
2003             if (num_pressed < 2)
2004             {
2005                 HoldDetectorDebugPrint("[GestureHoldDetector][P] num_pressed:%d\n", num_pressed);
2006                 break;
2007             }
2008
2009             if (num_pressed > g_pGesture->num_mt_devices)
2010                 num_pressed = g_pGesture->num_mt_devices;
2011
2012             pixman_region_init(&tarea1);
2013             pixman_region_init(&g_pGesture->chold_area);
2014             pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1);
2015
2016             tarea1.extents.x1 = g_pGesture->cts[0].cx;
2017             tarea1.extents.x2 = g_pGesture->cts[0].cx+1;
2018             tarea1.extents.y1 = g_pGesture->cts[0].cy;
2019             tarea1.extents.y2 = g_pGesture->cts[0].cy+1;
2020
2021             pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1);
2022
2023             for (i = 1; i < num_pressed; i++)
2024             {
2025                 pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1);
2026
2027                 tarea1.extents.x1 = g_pGesture->cts[i].cx;
2028                 tarea1.extents.x2 = g_pGesture->cts[i].cx + 1;
2029                 tarea1.extents.y1 = g_pGesture->cts[i].cy;
2030                 tarea1.extents.y2 = g_pGesture->cts[i].cy + 1;
2031
2032                 pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1);
2033             }
2034             break;
2035
2036         case ET_Motion:
2037             if (BTN_RELEASED == g_pGesture->cts[idx].status)
2038                 return;
2039
2040             g_pGesture->cts[idx].status = BTN_MOVING;
2041             g_pGesture->cts[idx].cx = ev->device_event.root_x;
2042             g_pGesture->cts[idx].cy = ev->device_event.root_y;
2043
2044             HoldDetectorDebugPrint("[GestureHoldDetector][M] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed);
2045
2046             if (num_pressed < 2)
2047             {
2048                 HoldDetectorDebugPrint("[GestureHoldDetector][M] num_pressed:%d\n", num_pressed);
2049                 break;
2050             }
2051
2052             pixman_region_init(&tarea1);
2053             pixman_region_init(&g_pGesture->chold_area);
2054             pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1);
2055
2056             tarea1.extents.x1 = g_pGesture->cts[0].cx;
2057             tarea1.extents.x2 = g_pGesture->cts[0].cx+1;
2058             tarea1.extents.y1 = g_pGesture->cts[0].cy;
2059             tarea1.extents.y2 = g_pGesture->cts[0].cy+1;
2060
2061             pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1);
2062
2063             for (i = 1; i < num_pressed; i++)
2064             {
2065                 pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1);
2066
2067                 tarea1.extents.x1 = g_pGesture->cts[i].cx;
2068                 tarea1.extents.x2 = g_pGesture->cts[i].cx + 1;
2069                 tarea1.extents.y1 = g_pGesture->cts[i].cy;
2070                 tarea1.extents.y2 = g_pGesture->cts[i].cy + 1;
2071
2072                 pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1);
2073             }
2074             break;
2075
2076         case ET_ButtonRelease:
2077             g_pGesture->cts[idx].status = BTN_RELEASED;
2078             g_pGesture->cts[idx].cx = ev->device_event.root_x;
2079             g_pGesture->cts[idx].cy = ev->device_event.root_y;
2080
2081             HoldDetectorDebugPrint("[GestureHoldDetector][R] cx:%d, cy:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy);
2082
2083             num_pressed--;
2084             if (num_pressed <3)
2085             {
2086                 pixman_region_init(&g_pGesture->chold_area);
2087             }
2088             break;
2089     }
2090
2091     if (num_pressed >= 2)
2092     {
2093         hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents);
2094
2095         HoldDetectorDebugPrint("[GestureHoldDetector] hold_area_size=%d, pPalmMisc->half_scrn_area_size=%d\n", hold_area_size, pPalmMisc->half_scrn_area_size);
2096
2097         if (pPalmMisc->half_scrn_area_size <= hold_area_size)
2098         {
2099             GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureBegin);
2100             GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureEnd);
2101
2102             g_pGesture->hold_detector_activate = 0;
2103             g_pGesture->has_hold_grabmask = 0;
2104         }
2105     }
2106     else
2107     {
2108         hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents);
2109         HoldDetectorDebugPrint("[GestureHoldDetector] num_pressed is under 2, hold_area_size=%d\n", hold_area_size);
2110     }
2111 }
2112
2113
2114 static int
2115 GesturePalmGetScreenInfo()
2116 {
2117     int i;
2118     pixman_region16_t tarea;
2119     PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
2120     ScreenPtr pScreen = miPointerCurrentScreen();
2121
2122     if (!pScreen)
2123     {
2124         DetailDebugPrint("[X11][GesturePalmGetScreenInfo]Failed to get screen information !\n");
2125
2126         pPalmMisc->scrn_width = pPalmMisc->scrn_height = 0;
2127         return 0;
2128     }
2129
2130     pPalmMisc->scrn_width = pScreen->width;
2131     pPalmMisc->scrn_height = pScreen->height;
2132     pixman_region_init(&tarea);
2133     pixman_region_init_rect(&tarea, 0, 0, pPalmMisc->scrn_width, pPalmMisc->scrn_height);
2134
2135     DetailDebugPrint("[X11][GesturePalmGetScreenInfo] x2:%d, x2:%d, y2:%d, y1:%d \n", tarea.extents.x2, tarea.extents.x1, tarea.extents.y2, tarea.extents.y1);
2136     pPalmMisc->half_scrn_area_size = AREA_SIZE(&tarea.extents);
2137     pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 4);
2138
2139     DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->half_scrn_area_size = %d\n", pPalmMisc->half_scrn_area_size);
2140
2141     for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++)
2142     {
2143         pPalmMisc->horiz_coord[i] = pPalmMisc->scrn_width * ((i+1)/(double)PALM_HORIZ_ARRAY_COUNT);
2144         DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->horiz_coord[%d]=%d, pPalmMisc->scrn_width=%d\n", i, pPalmMisc->horiz_coord[i], pPalmMisc->scrn_width);
2145     }
2146     for (i = 0; i < PALM_VERTI_ARRAY_COUNT; i++)
2147     {
2148         pPalmMisc->verti_coord[i] = pPalmMisc->scrn_height * ((i+1)/(double)PALM_VERTI_ARRAY_COUNT);
2149         DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->verti_coord[%d]=%d, pPalmMisc->scrn_height=%d\n", i, pPalmMisc->verti_coord[i], pPalmMisc->scrn_height);
2150     }
2151
2152     return 1;
2153 }
2154
2155
2156 static inline void
2157 GestureEnableDisable()
2158 {
2159     GestureEnable(1, FALSE, g_pGesture->this_device);
2160 #if 0
2161     if ((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None))
2162     {
2163         GestureEnable(1, FALSE, g_pGesture->this_device);
2164     }
2165     else
2166     {
2167         GestureEnable(0, FALSE, g_pGesture->this_device);
2168     }
2169 #endif
2170 }
2171
2172 void
2173 GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent)
2174 {
2175     g_pGesture->grabMask = *pGrabMask;
2176     g_pGesture->GrabEvents = (GestureGrabEventPtr)pGrabEvent;
2177     GestureEnableDisable();
2178 }
2179
2180 void
2181 GestureCbEventsSelected(Window win, Mask *pEventMask)
2182 {
2183     g_pGesture->lastSelectedWin = win;
2184     g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0;
2185     GestureEnableDisable();
2186 }
2187
2188 WindowPtr
2189 GestureGetEventsWindow(void)
2190 {
2191     Mask mask;
2192     WindowPtr pWin;
2193
2194     pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
2195
2196     if (pWin)
2197     {
2198         DetailDebugPrint("[GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
2199         g_pGesture->gestureWin = pWin->drawable.id;
2200     }
2201     else
2202     {
2203         DetailDebugPrint("[GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
2204         return NULL;
2205     }
2206
2207     if (g_pGesture->gestureWin == g_pGesture->lastSelectedWin)
2208     {
2209         g_pGesture->eventMask = g_pGesture->lastSelectedMask;
2210         goto nonempty_eventmask;
2211     }
2212
2213     //check selected event(s)
2214     if (!GestureHasSelectedEvents(pWin, &g_pGesture->eventMask))
2215     {
2216         g_pGesture->eventMask = 0;
2217     }
2218     else
2219     {
2220         g_pGesture->lastSelectedWin = g_pGesture->gestureWin;
2221         g_pGesture->lastSelectedMask = g_pGesture->eventMask;
2222     }
2223
2224     if (!g_pGesture->eventMask && !g_pGesture->grabMask)
2225     {
2226         DetailDebugPrint("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id);
2227         return NULL;
2228     }
2229
2230 nonempty_eventmask:
2231
2232     DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask);
2233
2234     mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
2235
2236     DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
2237
2238     g_pGesture->filter_mask = mask;
2239
2240     DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
2241
2242     return pWin;
2243 }
2244
2245 static CARD32
2246 GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2247 {
2248     g_pGesture->filter_mask |= WTapFilterMask;
2249     g_pGesture->filter_mask |= WHoldFilterMask;
2250     //LOGI("[GroupTap][GroupHold] 50ms after 1st finger.\n");
2251
2252     DetailDebugPrint("[GestureSingleFingerTimerHandler] TapFilterMask, HoldFilterMask \n");
2253
2254     if ((g_pGesture->event_sum[0] == BTN_PRESSED) && ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) && (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point)))
2255     {
2256         DetailDebugPrint("[GestureSingleFingerTimerHandler] press_point: %d\n", g_pGesture->flick_pressed_point);
2257         DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n");
2258         g_pGesture->filter_mask |= WFlickFilterMask;
2259     }
2260
2261     if (g_pGesture->flick_pressed_point == FLICK_POINT_DOWN && abs(g_pGesture->fingers[0].py - g_pGesture->fingers[0].my) < 3)
2262     {
2263         DetailDebugPrint("[GestureSingleFingerTimerHandler] py: %d, my: %d\n", g_pGesture->fingers[0].py, g_pGesture->fingers[0].my);
2264         DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n");
2265         g_pGesture->filter_mask |= WFlickFilterMask;
2266     }
2267
2268     DetailDebugPrint("[GestureSingleFingerTimerHandler] expired !\n");
2269
2270     if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
2271     {
2272         if ( ERROR_INVALPTR == GestureFlushOrDrop())
2273         {
2274             DetailDebugPrint("[GestureSingleFingerTimerHandler] AllFilterMask, Flush!\n");
2275             GestureControl(g_pGesture->this_device, DEVICE_OFF);
2276         }
2277     }
2278
2279     return 0;
2280 }
2281
2282 static int
2283 GestureGetFingerIndexFromDevice(DeviceIntPtr device)
2284 {
2285     int i;
2286
2287     for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
2288     {
2289         if( device->id == g_pGesture->mt_devices[i]->id )
2290         {
2291             return i;
2292         }
2293     }
2294
2295     return -1;
2296 }
2297
2298 void
2299 GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
2300 {
2301     int i;
2302     static OsTimerPtr single_finger_timer = NULL;
2303     int idx = -1;
2304
2305     if (PROPAGATE_EVENTS == g_pGesture->ehtype || device->id < g_pGesture->first_fingerid)
2306     {
2307         return;
2308     }
2309
2310     idx = GestureGetFingerIndexFromDevice(device);
2311
2312     if (idx < 0)
2313         return;
2314
2315     switch (type)
2316     {
2317         case ET_ButtonPress:
2318             if (idx == 0)
2319             {
2320                 g_pGesture->event_sum[0] = BTN_PRESSED;
2321             }
2322
2323             g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
2324
2325             g_pGesture->fingers[idx].ptime = ev->any.time;
2326             g_pGesture->fingers[idx].px = ev->device_event.root_x;
2327             g_pGesture->fingers[idx].py = ev->device_event.root_y;
2328
2329             g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2330             g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2331             g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2332             g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2333
2334             g_pGesture->num_pressed++;
2335             g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
2336
2337             if (g_pGesture->inc_num_pressed == 1)
2338             {
2339                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2340             }
2341             else
2342             {
2343                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2344
2345                 for (i = 1; i < g_pGesture->inc_num_pressed; i++)
2346                 {
2347                     pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2348                 }
2349             }
2350
2351             DetailDebugPrint("[GestureRecognize][P] num_pressed=%d, area_size=%d, px=%d, py=%d\n",
2352                     g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
2353
2354             if (g_pGesture->num_pressed == 1)
2355             {
2356                 single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
2357
2358                 if (g_pGesture->fingers[idx].py <= g_pGesture->flick_press_area)
2359                 {
2360                     if ((!g_pGesture->activate_flick_down)
2361                             || (g_pGesture->fingers[idx].px <= (g_pGesture->flick_press_area_left_right))
2362                             || (g_pGesture->fingers[idx].px >= (g_pGesture->screen_width - g_pGesture->flick_press_area_left_right)))
2363                     {
2364                         DetailDebugPrint("[GestureRecognize][P] px=%d, flick_press_area_left_right=%d\n",
2365                             g_pGesture->fingers[idx].px, g_pGesture->flick_press_area_left_right);
2366                         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2367                         LOGI("[BackKey][F] Press touch within 40 pixel area from left or right vezel\n");
2368                     }
2369                     else
2370                     {
2371                         DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_UP\n");
2372                         g_pGesture->flick_pressed_point = FLICK_POINT_UP;
2373                     }
2374                 }
2375                 else
2376                 {
2377                     LOGI("[BackKey][F] Press touch outside 40 pixel area from upper vezel. \n");
2378                 }
2379
2380                 if (g_pGesture->fingers[idx].py >= (g_pGesture->screen_height - g_pGesture->flick_press_area))
2381                 {
2382                     if (!g_pGesture->activate_flick_up)
2383                     {
2384                         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2385                     }
2386                     else
2387                     {
2388                         DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_DOWN\n");
2389                         g_pGesture->flick_pressed_point = FLICK_POINT_DOWN;
2390                     }
2391                 }
2392                 else if ( g_pGesture->fingers[idx].px <= g_pGesture->flick_press_area_left)
2393                 {
2394                     if (!g_pGesture->activate_flick_right)
2395                     {
2396                         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2397                     }
2398                     else
2399                     {
2400                         DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_LEFT\n");
2401                         g_pGesture->flick_pressed_point = FLICK_POINT_LEFT;
2402                     }
2403                 }
2404
2405                 DetailDebugPrint("[GestureRecognize][P] flick_press_point: %d\n", g_pGesture->flick_pressed_point);
2406
2407                 if ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point))
2408                 {
2409                     DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_NONE\n");
2410                     g_pGesture->filter_mask |= WFlickFilterMask;
2411                     g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2412                 }
2413                 else
2414                 {
2415                     g_pGesture->flick_direction = (g_pGesture->flick_pressed_point - 1) * 2;
2416                     if ((g_pGesture->flick_direction == FLICK_WESTWARD) && (g_pGesture->power_pressed != 2))
2417                     {
2418                         DetailDebugPrint("[GestureRecognize][P] Flick WesWard is disable when power is not pressed\n");
2419                         g_pGesture->filter_mask |= WFlickFilterMask;
2420                         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2421                     }
2422                     if ((g_pGesture->flick_direction < FLICK_NORTHWARD) || (FLICK_NORTHWESTWARD < g_pGesture->flick_direction))
2423                     {
2424                         DetailDebugPrint("[GestureRecognize][P] Invalid flick direction\n");
2425                         g_pGesture->filter_mask |= WFlickFilterMask;
2426                         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2427                     }
2428
2429                     DetailDebugPrint("[GestureRecognize][P] flick_direction: %d\n", g_pGesture->flick_direction);
2430                 }
2431             }
2432             else
2433             {
2434                 DetailDebugPrint("[GestureRecognize][P] Two more fingers come on!\n");
2435                 TimerCancel(single_finger_timer);
2436                 single_finger_timer = NULL;
2437             }
2438             break;
2439
2440         case ET_Motion:
2441
2442             if (!g_pGesture->fingers[idx].ptime)
2443             {
2444                 DetailDebugPrint("[GestureRecognize][M] Start motion. idx=%d\n", idx);
2445                 g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
2446                 return;
2447             }
2448
2449             g_pGesture->fingers[idx].mx = ev->device_event.root_x;
2450             g_pGesture->fingers[idx].my = ev->device_event.root_y;
2451             g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
2452
2453             if (idx == 0)
2454             {
2455                 g_pGesture->event_sum[0] += BTN_MOVING;
2456             }
2457
2458             g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2459             g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2460             g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2461             g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2462
2463             if (g_pGesture->inc_num_pressed == 1)
2464             {
2465                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2466             }
2467             else
2468             {
2469                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2470
2471                 for (i = 1; i < g_pGesture->inc_num_pressed; i++)
2472                 {
2473                     pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2474                 }
2475             }
2476
2477             DetailDebugPrint("[GestureRecognize][M] num_pressed=%d, area_size=%d, mx=%d, my=%d\n",
2478                     g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my);
2479
2480             break;
2481
2482         case ET_ButtonRelease:
2483             g_pGesture->fingers[idx].rtime = ev->any.time;
2484             g_pGesture->fingers[idx].rx = ev->device_event.root_x;
2485             g_pGesture->fingers[idx].ry = ev->device_event.root_y;
2486             g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
2487
2488             g_pGesture->num_pressed--;
2489
2490             if (g_pGesture->num_pressed == 0)
2491             {
2492                 DetailDebugPrint("[GestureRecognize] All fingers were released !\n");
2493             }
2494             else if (g_pGesture->num_pressed < 0)
2495             {
2496                 DetailDebugPrint("[GestureRecognize] All fingers were released. But, num_pressed is under 0 !\n");
2497             }
2498
2499             DetailDebugPrint("[GestureRecognize][R] num_pressed=%d, rx=%d, ry=%d\n",
2500                     g_pGesture->num_pressed, g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry);
2501
2502             break;
2503     }
2504
2505     if (!(g_pGesture->filter_mask & WFlickFilterMask))
2506     {
2507         DetailDebugPrint("[GestureRecognize] GestureRecognize_groupFlick !\n");
2508         GestureRecognize_GroupFlick(type, ev, device, idx, g_pGesture->flick_pressed_point, g_pGesture->flick_direction);
2509     }
2510     if (!(g_pGesture->filter_mask & WTapFilterMask))
2511     {
2512         DetailDebugPrint("[GestureRecognize] GestureRecognize_groupTap !\n");
2513         GestureRecognize_GroupTap(type, ev, device, idx, 0);
2514     }
2515     if (!(g_pGesture->filter_mask & WHoldFilterMask))
2516     {
2517         DetailDebugPrint("[GestureRecognize] GestureRecognize_groupHold !\n");
2518         GestureRecognize_GroupHold(type, ev, device, idx, 0);
2519     }
2520 /*
2521     if (!(g_pGesture->filter_mask & WPalmFlickFilterMask))
2522     {
2523         DetailDebugPrint("[GestureRecognize] GestureRecognize_palmFlick !\n");
2524         GestureRecognize_PalmFlick(type, ev, device, idx);
2525     }
2526 */
2527     DetailDebugPrint("[GestureRecognize][N] g_pGesture->filter_mask = 0x%x, g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x, g_pGesture->recognized_gesture=0x%x\n",
2528             g_pGesture->filter_mask, GESTURE_WATCH_FILTER_MASK_ALL, g_pGesture->recognized_gesture);
2529
2530     if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
2531     {
2532         if (!g_pGesture->recognized_gesture)
2533         {
2534             DetailDebugPrint("[GestureRecognize][F] 1 !\n");
2535             goto flush_or_drop;
2536         }
2537         else if (!g_pGesture->num_pressed)
2538         {
2539             DetailDebugPrint("[GestureRecognize][F] 2 !\n");
2540             goto flush_or_drop;
2541         }
2542     }
2543
2544     if (g_pGesture->recognized_gesture)
2545     {
2546         if (g_pGesture->ehtype == KEEP_EVENTS)
2547         {
2548             DetailDebugPrint("[GestureRecognize] Keep Event !\n");
2549             GestureEventsDrop();
2550         }
2551         g_pGesture->ehtype = IGNORE_EVENTS;
2552     }
2553     return;
2554
2555 flush_or_drop:
2556
2557     DetailDebugPrint("[GestureRecognize] GestureFlushOrDrop() !\n");
2558
2559     if (ERROR_INVALPTR == GestureFlushOrDrop())
2560     {
2561         GestureControl(g_pGesture->this_device, DEVICE_OFF);
2562     }
2563 }
2564
2565 ErrorStatus GestureFlushOrDrop(void)
2566 {
2567     ErrorStatus err;
2568
2569     if (g_pGesture->recognized_gesture)
2570     {
2571         g_pGesture->ehtype = IGNORE_EVENTS;
2572         GestureEventsDrop();
2573         DetailDebugPrint("[GestureFlushOrDrop][Drop] IGNORE_EVENTS\n");
2574     }
2575     else
2576     {
2577         g_pGesture->ehtype = PROPAGATE_EVENTS;
2578
2579         err = GestureEventsFlush();
2580
2581         if (ERROR_NONE != err)
2582         {
2583             return err;
2584         }
2585
2586         DetailDebugPrint("[GestureFlushOrDrop][Flush] PROPAGATE_EVENTS\n");
2587         DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
2588         DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x\n", GESTURE_WATCH_FILTER_MASK_ALL);
2589         DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
2590     }
2591
2592     err = GestureRegionsReinit();
2593
2594     if (ERROR_NONE != err)
2595     {
2596         return err;
2597     }
2598
2599     g_pGesture->pTempWin = NULL;
2600     g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
2601     g_pGesture->event_sum[0] = 0;
2602
2603     return ERROR_NONE;
2604 }
2605
2606 void
2607 GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2608 {
2609     int i;
2610     int idx;
2611
2612 #ifdef __DEBUG_EVENT_HANDLER__
2613     DetailDebugPrint("[GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
2614             ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
2615 #endif
2616
2617     if (!g_pGesture->is_active)
2618     {
2619         g_pGesture->ehtype = PROPAGATE_EVENTS;
2620         DetailDebugPrint("[GestureHandleMTSyncEvent] PROPAGATE_EVENT\n");
2621         return;
2622     }
2623
2624     switch(ev->any_event.sync)
2625     {
2626     case ROTARY_FRAME_SYNC_BEGIN:
2627         if (g_pGesture->mt_devices[0] && (g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH))
2628         {
2629             int zero = 0;
2630             xf86PostButtonEvent(g_pGesture->mt_devices[0], 0, Button1, 0, 0, 2, &zero, &zero);
2631         }
2632         g_pGesture->mtsync_flag |= MTSYNC_FLAG_ROTARY;
2633         DetailDebugPrint("[GestureHandleMTSyncEvent] Rotary input starts. Now touch events are dropped!\n");
2634         break;
2635     case ROTARY_FRAME_SYNC_END:
2636         g_pGesture->mtsync_flag &= ~MTSYNC_FLAG_ROTARY;
2637         DetailDebugPrint("[GestureHandleMTSyncEvent] Rotary input is finished. Now touch events are not dropped!\n");
2638         break;
2639     case MTOUCH_FRAME_SYNC_BEGIN:
2640         g_pGesture->mtsync_flag |= MTSYNC_FLAG_TOUCH;
2641         DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_BEGIN\n");
2642         g_pGesture->ehtype = KEEP_EVENTS;
2643         g_pGesture->filter_mask = 0;
2644         g_pGesture->recognized_gesture = 0;
2645         g_pGesture->hold_detector_activate = 1;
2646         g_pGesture->num_pressed = 0;
2647         g_pGesture->has_hold_grabmask = 0;
2648         g_pGesture->mtsync_total_count = 0;
2649         memset(&g_pGesture->last_touches, 0, sizeof(g_pGesture->last_touches));
2650         for (i=0; i < g_pGesture->num_mt_devices; i++)
2651         {
2652             g_pGesture->fingers[i].ptime = 0;
2653             g_pGesture->max_mt_tmajor[i] = 0;
2654         }
2655         break;
2656     case MTOUCH_FRAME_SYNC_END:
2657         g_pGesture->mtsync_flag &= ~MTSYNC_FLAG_TOUCH;
2658         DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_END\n");
2659         g_pGesture->ehtype = PROPAGATE_EVENTS;
2660         g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
2661         g_pGesture->pTempWin = NULL;
2662         g_pGesture->num_pressed = 0;
2663         g_pGesture->hold_detected = FALSE;
2664         break;
2665     case MTOUCH_FRAME_SYNC_UPDATE:
2666         g_pGesture->mtsync_flag |= MTSYNC_FLAG_TOUCH;
2667         g_pGesture->mtsync_total_count++;
2668
2669         DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_Update. mt_total_sync=%d\n", g_pGesture->mtsync_total_count);
2670
2671         if ((g_pGesture->inc_num_pressed < 2) && (g_pGesture->filter_mask != GESTURE_WATCH_FILTER_MASK_ALL))
2672         {
2673             if (g_pGesture->num_tap_repeated == 1 || g_pGesture->num_tap_repeated == 2)
2674             {
2675                 if (g_pGesture->mtsync_total_count >= 6)
2676                 {
2677                     DetailDebugPrint("[GestureHandleMTSyncEvent] Moving Limit first tap repeated. tap_repeated: %d, mtsync_total_count: %d\n",
2678                             g_pGesture->num_tap_repeated, g_pGesture->mtsync_total_count);
2679                     g_pGesture->filter_mask |= WTapFilterMask;
2680                     g_pGesture->filter_mask |= WHoldFilterMask;
2681                                         LOGI("[GroupTap][GroupHold] Motions are more than 6 between 1st finger and 2nd finger.\n");
2682                 }
2683             }
2684
2685             if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
2686             {
2687                 DetailDebugPrint("[GestureHandleMTSyncEvent] Gesture filter mask all. GestureFlushOrDrop() !\n");
2688
2689                 if (ERROR_INVALPTR == GestureFlushOrDrop())
2690                 {
2691                     GestureControl(g_pGesture->this_device, DEVICE_OFF);
2692                 }
2693             }
2694         }
2695         break;
2696     default:
2697         ErrorF("[GestureHandleMTSyncEvent] Unknown MTSync Event received.\n");
2698         break;
2699     }
2700 }
2701
2702 void GestureEmulateHWKey(DeviceIntPtr dev, int keycode)
2703 {
2704     if (dev)
2705     {
2706         DetailDebugPrint("[GestureEmulateHWKey] keycode=%d\n", keycode);
2707         xf86PostKeyboardEvent(dev, keycode, 1);
2708         xf86PostKeyboardEvent(dev, keycode, 0);
2709     }
2710 }
2711
2712 void
2713 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2714 {
2715 #ifdef __DEBUG_EVENT_HANDLER__
2716     DetailDebugPrint("[GestureHandleButtonPressEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
2717 #endif//__DEBUG_EVENT_HANDLER__
2718     int idx=0;
2719     if (g_pGesture->touch_cancel_status == TRUE)
2720     {
2721         DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n");
2722         return;
2723     }
2724
2725     idx = GestureGetFingerIndexFromDevice(device);
2726     if (0 <= idx)
2727     {
2728         g_pGesture->last_touches[idx].status = BTN_PRESSED;
2729         g_pGesture->last_touches[idx].cx = ev->device_event.root_x;
2730         g_pGesture->last_touches[idx].cy = ev->device_event.root_y;
2731     }
2732
2733     if (g_pGesture->ehtype != KEEP_EVENTS)
2734     {
2735         if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY)
2736         {
2737             DetailDebugPrint("[GestureHandleButtonPressEvent] Rotary input is coming. Dropping touch events.\n");
2738             return;
2739         }
2740         else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH)
2741         {
2742             DetailDebugPrint("[GestureHandleButtonPressEvent] Other input is coming. Dropping touch events.\n");
2743             return;
2744         }
2745     }
2746
2747     switch (g_pGesture->ehtype)
2748     {
2749         case KEEP_EVENTS:
2750             DetailDebugPrint("[GestureHandleButtonPressEvent] KEEP_EVENT\n");
2751
2752             if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev, device))
2753             {
2754                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2755                 return;
2756             }
2757
2758             if (g_pGesture->num_mt_devices)
2759             {
2760                 GestureRecognize(ET_ButtonPress, ev, device);
2761             }
2762             else
2763             {
2764                 device->public.processInputProc(ev, device);
2765             }
2766
2767             GestureHoldDetector(ET_ButtonPress, ev, device);
2768             break;
2769
2770         case PROPAGATE_EVENTS:
2771             DetailDebugPrint("[GestureHandleButtonPressEvent] PROPAGATE_EVENT\n");
2772
2773             device->public.processInputProc(ev, device);
2774             GestureHoldDetector(ET_ButtonPress, ev, device);
2775             break;
2776
2777         case IGNORE_EVENTS:
2778             DetailDebugPrint("[GestureHandleButtonPressEvent] IGNORE_EVENTS\n");
2779
2780             GestureRecognize(ET_ButtonPress, ev, device);
2781             break;
2782
2783         default:
2784             break;
2785     }
2786 }
2787
2788 void
2789 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2790 {
2791 #ifdef __DEBUG_EVENT_MOTION_HANDLER__
2792     DetailDebugPrint("[GestureHandleMotionEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
2793 #endif
2794     int idx=0;
2795     if (g_pGesture->touch_cancel_status == TRUE)
2796     {
2797         DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n");
2798         return;
2799     }
2800
2801     idx = GestureGetFingerIndexFromDevice(device);
2802     if (0 <= idx)
2803     {
2804         g_pGesture->last_touches[idx].status = BTN_MOVING;
2805         g_pGesture->last_touches[idx].cx = ev->device_event.root_x;
2806         g_pGesture->last_touches[idx].cy = ev->device_event.root_y;
2807     }
2808
2809     if (g_pGesture->ehtype != KEEP_EVENTS)
2810     {
2811         if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY)
2812         {
2813             DetailDebugPrint("[GestureHandleMotionEvent] Rotary input is coming. Dropping touch events.\n");
2814             return;
2815         }
2816         else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH)
2817         {
2818             DetailDebugPrint("[GestureHandleMotionEvent] Other input is coming. Dropping touch events.\n");
2819             return;
2820         }
2821     }
2822
2823     switch (g_pGesture->ehtype)
2824     {
2825         case KEEP_EVENTS:
2826             if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev, device))
2827             {
2828                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2829                 return;
2830             }
2831
2832             if (g_pGesture->num_mt_devices)
2833             {
2834                 GestureRecognize(ET_Motion, ev, device);
2835             }
2836             else
2837             {
2838                 device->public.processInputProc(ev, device);
2839             }
2840
2841             GestureHoldDetector(ET_Motion, ev, device);
2842             break;
2843
2844         case PROPAGATE_EVENTS:
2845             device->public.processInputProc(ev, device);
2846             GestureHoldDetector(ET_Motion, ev, device);
2847             break;
2848
2849         case IGNORE_EVENTS:
2850             GestureRecognize(ET_Motion, ev, device);
2851             break;
2852
2853         default:
2854             break;
2855     }
2856
2857 }
2858
2859 void
2860 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2861 {
2862 #ifdef __DEBUG_EVENT_HANDLER__
2863     DetailDebugPrint("[GestureHandleButtonReleaseEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
2864 #endif
2865     int idx=0;
2866     if (g_pGesture->touch_cancel_status == TRUE)
2867     {
2868         DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n");
2869         return;
2870     }
2871
2872     idx = GestureGetFingerIndexFromDevice(device);
2873     if (0 <= idx)
2874     {
2875         g_pGesture->last_touches[idx].status = BTN_RELEASED;
2876         g_pGesture->last_touches[idx].cx = ev->device_event.root_x;
2877         g_pGesture->last_touches[idx].cy = ev->device_event.root_y;
2878     }
2879
2880     if (g_pGesture->ehtype != KEEP_EVENTS)
2881     {
2882         if(!(g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH))
2883         {
2884             if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY)
2885             {
2886                 DetailDebugPrint("[GestureHandleButtonReleaseEvent] Rotary input is coming. Dropping touch events.\n");
2887                 return;
2888             }
2889             else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH)
2890             {
2891                 DetailDebugPrint("[GestureHandleButtonReleaseEvent] Other input is coming. Dropping touch events.\n");
2892                 return;
2893             }
2894         }
2895     }
2896
2897     switch (g_pGesture->ehtype)
2898     {
2899         case KEEP_EVENTS:
2900             DetailDebugPrint("[GestureHandleButtonReleaseEvent] KEEP_EVENT\n");
2901
2902             if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device))
2903             {
2904                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2905                 return;
2906             }
2907
2908             if (g_pGesture->num_mt_devices)
2909             {
2910                 GestureRecognize(ET_ButtonRelease, ev, device);
2911             }
2912             else
2913             {
2914                 device->public.processInputProc(ev, device);
2915             }
2916
2917             GestureHoldDetector(ET_ButtonRelease, ev, device);
2918             break;
2919
2920         case PROPAGATE_EVENTS:
2921             DetailDebugPrint("[GestureHandleButtonReleaseEvent] PROPAGATE_EVENTS\n");
2922 #ifdef SUPPORT_ANR_WITH_INPUT_EVENT
2923                      if( IsMaster(device) && ev->any.type == ET_ButtonRelease )
2924                      {
2925                          if( g_pGesture->anr_window == NULL )
2926                          {
2927                              g_pGesture->anr_window = _GestureFindANRWindow(device);
2928                          }
2929                          Time current_time;
2930
2931                          // Send event to the e17 process.
2932                          current_time = GetTimeInMillis();
2933                          if( g_pGesture->anr_window != NULL )
2934                          {
2935                              // Check anr_window validation.
2936                              if( dixLookupWindow(&g_pGesture->anr_window, prop_anr_event_window_xid, serverClient, DixSetPropAccess) != BadWindow )
2937                              {
2938                                  if( serverClient->devPrivates != NULL )
2939                                      dixChangeWindowProperty (serverClient, g_pGesture->anr_window, prop_anr_in_input_event,
2940                                                                                XA_CARDINAL, 32, PropModeReplace, 1, &current_time, TRUE);
2941                              }
2942                              else
2943                              {
2944                                  prop_anr_event_window_xid = 0;
2945                                  g_pGesture->anr_window = NULL;
2946                              }
2947                              DetailDebugPrint("[GestureHandleButtonReleaseEvent] Release TOUCH!! devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis());
2948                          }
2949                      }
2950 #endif
2951             device->public.processInputProc(ev, device);
2952             GestureHoldDetector(ET_ButtonRelease, ev, device);
2953 #if 0
2954             GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
2955             GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
2956 #endif
2957             break;
2958
2959         case IGNORE_EVENTS:
2960             DetailDebugPrint("[GestureHandleButtonReleaseEvent] IGNORE_EVENTS\n");
2961             GestureRecognize(ET_ButtonRelease, ev, device);
2962             break;
2963
2964         default:
2965             break;
2966     }
2967 }
2968
2969 void
2970 GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2971 {
2972     if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0))
2973     {
2974         g_pGesture->power_pressed = 2;
2975         g_pGesture->power_device = device;
2976
2977         DetailDebugPrint("[GestureHandleKeyPressEvent] power key pressed devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
2978         DetailDebugPrint("[GestureHandleKeyPressEvent] power_pressed: %d\n", g_pGesture->power_pressed);
2979     }
2980     device->public.processInputProc(ev, device);
2981 }
2982
2983 void
2984 GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2985 {
2986     if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0))
2987     {
2988         g_pGesture->power_pressed = 1;
2989         g_pGesture->power_device = device;
2990
2991         DetailDebugPrint("[GestureHandleKeyReleaseEvent] power key released devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
2992         DetailDebugPrint("[GestureHandleKeyReleaseEvent] power_pressed: %d\n", g_pGesture->power_pressed);
2993     }
2994     device->public.processInputProc(ev, device);
2995 }
2996
2997 static void
2998 GestureHandleClientState (CallbackListPtr *list, pointer closure, pointer calldata)
2999 {
3000     NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata;
3001     ClientPtr client = clientinfo->client;
3002
3003     if (client->clientState != ClientStateGone)
3004     {
3005         return;
3006     }
3007
3008     if (!g_pGesture->factory_cmdname)
3009     {
3010         return;
3011     }
3012
3013     if (strncmp(client->clientIds->cmdname, g_pGesture->factory_cmdname, strlen(g_pGesture->factory_cmdname)))
3014     {
3015         return;
3016     }
3017
3018     if (g_pGesture->is_active == 0)
3019     {
3020         int prop_val = 1;
3021         int rc = XIChangeDeviceProperty(g_pGesture->this_device, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &prop_val, FALSE);
3022
3023         ErrorF("[GestureHandleClientState] %s is exited unintentionally\n", g_pGesture->factory_cmdname);
3024
3025         if (rc != Success)
3026         {
3027             ErrorF("[GestureHandleClientState] Failed to Gesture Enable\n");
3028             return;
3029         }
3030     }
3031 }
3032
3033 static ErrorStatus
3034 GestureEnableEventHandler(InputInfoPtr pInfo)
3035 {
3036     Bool res;
3037     GestureDevicePtr pGesture = pInfo->private;
3038
3039     res = GestureInstallResourceStateHooks();
3040
3041     if (!res)
3042     {
3043         ErrorF("[GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
3044         return ERROR_ABNORMAL;
3045     }
3046
3047     res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
3048
3049     if (!res)
3050     {
3051         ErrorF("[GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
3052         goto failed;
3053     }
3054
3055     res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected);
3056
3057     if (!res)
3058     {
3059         ErrorF("[GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n");
3060         goto failed;
3061     }
3062
3063     pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
3064
3065     if (!pGesture->device_setting_timer)
3066     {
3067         ErrorF("[GestureEnableEventHandler] Failed to set time for detecting devices !\n");
3068         goto failed;
3069     }
3070
3071     return ERROR_NONE;
3072
3073 failed:
3074     GestureUninstallResourceStateHooks();
3075     GestureUnsetMaxNumberOfFingers();
3076
3077     return ERROR_ABNORMAL;
3078 }
3079
3080 static ErrorStatus
3081 GestureDisableEventHandler(void)
3082 {
3083     ErrorStatus err = ERROR_NONE;
3084
3085     mieqSetHandler(ET_ButtonPress, NULL);
3086     mieqSetHandler(ET_ButtonRelease, NULL);
3087     mieqSetHandler(ET_Motion, NULL);
3088     mieqSetHandler(ET_KeyPress, NULL);
3089     mieqSetHandler(ET_KeyRelease, NULL);
3090     mieqSetHandler(ET_MTSync, NULL);
3091
3092     err = GestureFiniEQ();
3093
3094     if (ERROR_INVALPTR == err)
3095     {
3096         ErrorF("[GestureDisableEventHandler] EQ is invalid or was freed already !\n");
3097     }
3098
3099     GestureRegisterCallbacks(NULL, NULL);
3100     GestureUninstallResourceStateHooks();
3101
3102     return err;
3103 }
3104
3105 static CARD32
3106 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
3107 {
3108     InputInfoPtr pInfo = (InputInfoPtr)arg;
3109     GestureDevicePtr pGesture;
3110     int idx;
3111     DeviceIntPtr dev;
3112
3113     if (!pInfo)
3114     {
3115         ErrorF("[GestureTimerHandler][%s] pInfo is NULL !\n");
3116         goto failed;
3117     }
3118
3119     pGesture = pInfo->private;
3120
3121     idx = 0;
3122     for (dev = inputInfo.pointer; dev; dev = dev->next)
3123     {
3124         if (IsMaster(dev) && IsPointerDevice(dev))
3125         {
3126             pGesture->master_pointer = dev;
3127             ErrorF("[GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
3128             continue;
3129         }
3130
3131         if (IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
3132         {
3133             pGesture->xtest_pointer = dev;
3134             ErrorF("[GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
3135             continue;
3136         }
3137
3138         if (IsPointerDevice(dev))
3139         {
3140             if (idx >= MAX_MT_DEVICES)
3141             {
3142                 ErrorF("[GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n", MAX_MT_DEVICES);
3143                 continue;
3144             }
3145             pGesture->mt_devices[idx] = dev;
3146             ErrorF("[GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
3147             GesturePalmGetAbsAxisInfo(dev);
3148             idx++;
3149         }
3150     }
3151
3152     for (dev = inputInfo.keyboard ; dev; dev = dev->next)
3153     {
3154         if (g_pGesture->hwkey_name && !strncmp(dev->name, g_pGesture->hwkey_name, strlen(dev->name)))
3155         {
3156             g_pGesture->hwkey_id = dev->id;
3157             g_pGesture->hwkey_dev = dev;
3158
3159             ErrorF("[GestureTimerHandler] hwkey_name has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
3160             break;
3161         }
3162         else if (!strncmp(dev->name, "tizen_rotary", strlen(dev->name)))
3163         {
3164             g_pGesture->rotary_id = dev->id;
3165             g_pGesture->rotary_dev = dev;
3166
3167             ErrorF("[GestureTimerHandler] rotary_name has been found. rotary_id=%d (rotary_dev->name:%s)\n", g_pGesture->rotary_id, g_pGesture->rotary_dev->name);
3168             break;
3169         }
3170         else if (!strcasestr(dev->name, "keyboard") && strcasestr(dev->name, "key") && !IsXTestDevice(dev, NULL) && !IsMaster(dev))
3171         {
3172             g_pGesture->hwkey_id = dev->id;
3173             g_pGesture->hwkey_dev = dev;
3174
3175             ErrorF("[GestureTimerHandler] hwkey has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
3176             break;
3177         }
3178     }
3179
3180     if (!g_pGesture->hwkey_id)
3181     {
3182         g_pGesture->hwkey_id = inputInfo.keyboard->id;
3183         g_pGesture->hwkey_dev = inputInfo.keyboard;
3184
3185         ErrorF("[GestureTimerHandler] No hwkey has been found. Back key will go through VCK. hwkey_id=%d (hwkey_dev->name:%s)\n",
3186                 g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
3187     }
3188
3189     if (!pGesture->master_pointer || !pGesture->xtest_pointer)
3190     {
3191         ErrorF("[GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
3192         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
3193         pGesture->num_mt_devices = 0;
3194
3195         return 0;
3196     }
3197
3198     TimerCancel(pGesture->device_setting_timer);
3199     pGesture->device_setting_timer = NULL;
3200     pGesture->num_mt_devices = idx;
3201
3202     if (!pGesture->num_mt_devices)
3203     {
3204         ErrorF("[GestureTimerHandler] Failed to mt device information !\n");
3205         TimerCancel(pGesture->device_setting_timer);
3206         pGesture->device_setting_timer = NULL;
3207         pGesture->num_mt_devices = 0;
3208         pGesture->first_fingerid = -1;
3209         return 0;
3210     }
3211
3212     pGesture->first_fingerid = pGesture->mt_devices[0]->id;
3213     memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
3214     pGesture->pRootWin = RootWindow(pGesture->master_pointer);
3215
3216     if (g_pGesture->palm_misc.enabled)
3217     {
3218         GesturePalmGetScreenInfo();
3219     }
3220
3221     g_pGesture->pTempWin = NULL;
3222     g_pGesture->inc_num_pressed = 0;
3223
3224     if (ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ())
3225     {
3226         goto failed;
3227     }
3228
3229     mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
3230     mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
3231     mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
3232     mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent);
3233     mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent);
3234
3235     //if ( pGesture->is_active)
3236     mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
3237
3238     return 0;
3239
3240 failed:
3241     GestureUninstallResourceStateHooks();
3242     GestureUnsetMaxNumberOfFingers();
3243
3244     return 0;
3245 }
3246
3247 BOOL
3248 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
3249 {
3250     if (IsMaster(dev))
3251     {
3252         return FALSE;
3253     }
3254
3255     if (master)
3256     {
3257         return (dev->xtest_master_id == master->id);
3258     }
3259
3260     return (dev->xtest_master_id != 0);
3261 }
3262
3263 void
3264 GestureGenerateTouchCancelEvent(void)
3265 {
3266     int i;
3267     Bool canceled_touch_index[MAX_MT_DEVICES] = {FALSE, };
3268
3269     if (g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH)
3270     {
3271         ErrorF("no Touch(%d)\n", g_pGesture->mtsync_flag);
3272         return;
3273     }
3274
3275     for (i=0; i<MAX_MT_DEVICES; i++)
3276     {
3277         if (!(g_pGesture->mt_devices[i]->button->buttonsDown)) continue;
3278         InternalEvent cancel_event;
3279
3280         cancel_event.touch_cancel_event.header = ET_Internal;
3281         cancel_event.touch_cancel_event.type = ET_TouchCancel;
3282         cancel_event.touch_cancel_event.length = sizeof(TouchCancelEvent);
3283         cancel_event.touch_cancel_event.time = CurrentTime;
3284         cancel_event.touch_cancel_event.deviceid = g_pGesture->mt_devices[i]?g_pGesture->mt_devices[i]->id:0;
3285
3286         cancel_event.touch_cancel_event.sourceid = g_pGesture->mt_devices[i]?g_pGesture->mt_devices[i]->id:0;
3287         cancel_event.touch_cancel_event.resource = 0;
3288         cancel_event.touch_cancel_event.flags = 0;
3289
3290         g_pGesture->mt_devices[i]->public.processInputProc(&cancel_event, g_pGesture->mt_devices[i]);
3291         canceled_touch_index[i] = TRUE;
3292         g_pGesture->touch_cancel_status = TRUE;
3293     }
3294
3295     for (i=0; i<MAX_MT_DEVICES; i++)
3296     {
3297         if (canceled_touch_index[i] == FALSE) continue;
3298         InternalEvent release_event;
3299         InternalEvent release_event_master;
3300
3301         memset(&release_event, 0, sizeof(InternalEvent));
3302
3303         release_event.device_event.header = ET_Internal;
3304         release_event.device_event.type = ET_ButtonRelease;
3305         release_event.device_event.length = sizeof(DeviceEvent);
3306         release_event.device_event.time = CurrentTime;
3307         release_event.device_event.deviceid = g_pGesture->mt_devices[i]->id;
3308         release_event.device_event.sourceid = g_pGesture->mt_devices[i]->button->sourceid;
3309         release_event.device_event.detail.button = 1;
3310         release_event.device_event.root_x = g_pGesture->last_touches[i].cx;
3311         release_event.device_event.root_y = g_pGesture->last_touches[i].cy;
3312         if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid)
3313         {
3314             memcpy(&release_event_master, &release_event, sizeof(InternalEvent));
3315             release_event_master.device_event.deviceid = g_pGesture->master_pointer->id;
3316         }
3317
3318         g_pGesture->mt_devices[i]->public.processInputProc(&release_event, g_pGesture->mt_devices[i]);
3319         if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid)
3320         {
3321             g_pGesture->master_pointer->public.processInputProc(&release_event_master, g_pGesture->master_pointer);
3322         }
3323         g_pGesture->touch_cancel_status = TRUE;
3324     }
3325 }
3326
3327 static void
3328 GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata)
3329 {
3330     int dpmsLevel = *(int *)calldata;
3331
3332     if ((DPMSModeOff == dpmsLevel) && (MTSYNC_FLAG_TOUCH & g_pGesture->mtsync_flag)) {
3333         ErrorF("TouchCancel dpmslevel: %d, g_pGesture->mtsync_flag: %d\n", dpmsLevel, g_pGesture->mtsync_flag);
3334         GestureGenerateTouchCancelEvent();
3335     }
3336 }
3337
3338 void
3339 GestureEnable(int enable, Bool prop, DeviceIntPtr dev)
3340 {
3341     if ((!enable) && (g_pGesture->is_active))
3342     {
3343         g_pGesture->ehtype = PROPAGATE_EVENTS;
3344         mieqSetHandler(ET_MTSync, NULL);
3345         g_pGesture->is_active = 0;
3346         ErrorF("[GestureEnable] Disabled !\n");
3347         int res = AddCallback (&ClientStateCallback, GestureHandleClientState, NULL);
3348
3349         if (!res)
3350         {
3351             ErrorF("[GestureEnable] Failed to add callback for client state\n");
3352             return;
3353         }
3354     }
3355
3356     else if ((enable) && (!g_pGesture->is_active))
3357     {
3358         g_pGesture->ehtype = KEEP_EVENTS;
3359         mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
3360         g_pGesture->is_active = 1;
3361         ErrorF("[GestureEnable] Enabled !\n");
3362
3363         DeleteCallback (&ClientStateCallback, GestureHandleClientState, NULL);
3364     }
3365
3366     if (!prop)
3367     {
3368         XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
3369     }
3370 }
3371
3372 ErrorStatus
3373 GestureRegionsInit(void)
3374 {
3375     int i;
3376
3377     if (!g_pGesture)
3378     {
3379         return ERROR_INVALPTR;
3380     }
3381
3382     pixman_region_init(&g_pGesture->area);
3383
3384     for (i = 0; i < MAX_MT_DEVICES; i++)
3385     {
3386         pixman_region_init_rect(&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
3387     }
3388
3389     return ERROR_NONE;
3390 }
3391
3392 ErrorStatus
3393 GestureRegionsReinit(void)
3394 {
3395     if (!g_pGesture)
3396     {
3397         ErrorF("[GestureRegionsReinit] Invalid pointer access !\n");
3398         return ERROR_INVALPTR;
3399     }
3400
3401     pixman_region_init(&g_pGesture->area);
3402
3403     return ERROR_NONE;
3404 }
3405
3406 ErrorStatus
3407 GestureInitEQ(void)
3408 {
3409     int i;
3410     IEventPtr tmpEQ;
3411
3412     tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
3413
3414     if (!tmpEQ)
3415     {
3416         ErrorF("[GestureInitEQ] Failed to allocate memory for EQ !\n");
3417         return ERROR_ALLOCFAIL;
3418     }
3419
3420     for (i = 0; i < GESTURE_EQ_SIZE; i++)
3421     {
3422         tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
3423         if (!tmpEQ[i].event)
3424         {
3425             ErrorF("[GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
3426             i--;
3427             while(i >= 0 && tmpEQ[i].event)
3428             {
3429                 free(tmpEQ[i].event);
3430                 tmpEQ[i].event = NULL;
3431             }
3432             free (tmpEQ);
3433             tmpEQ = NULL;
3434             return ERROR_ALLOCFAIL;
3435         }
3436     }
3437
3438     g_pGesture->EQ = tmpEQ;
3439     g_pGesture->headEQ = g_pGesture->tailEQ = 0;
3440
3441     return ERROR_NONE;
3442 }
3443
3444 ErrorStatus
3445 GestureFiniEQ(void)
3446 {
3447     int i;
3448
3449     if (!g_pGesture || !g_pGesture->EQ)
3450     {
3451         return ERROR_INVALPTR;
3452     }
3453
3454     for (i = 0; i < GESTURE_EQ_SIZE; i++)
3455     {
3456         if (g_pGesture->EQ[i].event)
3457         {
3458             free(g_pGesture->EQ[i].event);
3459             g_pGesture->EQ[i].event = NULL;
3460         }
3461     }
3462
3463     free(g_pGesture->EQ);
3464     g_pGesture->EQ = NULL;
3465
3466     return ERROR_NONE;
3467 }
3468
3469 ErrorStatus
3470 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
3471 {
3472     int tail;
3473
3474     if (!g_pGesture || !g_pGesture->EQ)
3475     {
3476         ErrorF("[GestureEnqueueEvent] Invalid pointer access !\n");
3477         return ERROR_INVALPTR;
3478     }
3479
3480     tail = g_pGesture->tailEQ;
3481
3482     if (tail >= GESTURE_EQ_SIZE)
3483     {
3484         ErrorF("[GestureEnqueueEvent] Gesture EQ is full !\n");
3485         printk("[GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
3486         GestureEventsFlush();
3487         return ERROR_EQFULL;
3488     }
3489
3490     if((g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY) || (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH))
3491     {
3492         DetailDebugPrint("[GestureEnqueueEvent] Rotary or other input are coming. Do not push events to queue.\n");
3493         return ERROR_NONE;
3494     }
3495
3496     switch (ev->any.type)
3497     {
3498         case ET_ButtonPress:
3499             DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
3500             break;
3501
3502         case ET_ButtonRelease:
3503             DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
3504             break;
3505
3506         case ET_Motion:
3507             DetailDebugPrint("[GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
3508             break;
3509     }
3510
3511     g_pGesture->EQ[tail].device = device;
3512     g_pGesture->EQ[tail].screen_num = screen_num;
3513     memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
3514     g_pGesture->tailEQ++;
3515
3516     return ERROR_NONE;
3517 }
3518
3519 ErrorStatus
3520 GestureEventsFlush(void)
3521 {
3522     int i;
3523     DeviceIntPtr device;
3524
3525     if (!g_pGesture->EQ)
3526     {
3527         ErrorF("[GestureEventsFlush] Invalid pointer access !\n");
3528         return ERROR_INVALPTR;
3529     }
3530
3531     DetailDebugPrint("[GestureEventsFlush]\n");
3532
3533     for (i = g_pGesture->headEQ; i < g_pGesture->tailEQ; i++)
3534     {
3535         device = g_pGesture->EQ[i].device;
3536         device->public.processInputProc(g_pGesture->EQ[i].event, device);
3537     }
3538
3539     for (i = 0; i < MAX_MT_DEVICES; i++)
3540     {
3541         g_pGesture->event_sum[i] = 0;
3542     }
3543
3544     g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
3545
3546     return ERROR_NONE;
3547 }
3548
3549 void
3550 GestureEventsDrop(void)
3551 {
3552     DetailDebugPrint("[GestureEventsDrop]\n");
3553     g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
3554 }
3555
3556 #ifdef HAVE_PROPERTIES
3557 static void
3558 GestureInitProperty(DeviceIntPtr dev)
3559 {
3560     int rc;
3561
3562 #ifdef SUPPORT_ANR_WITH_INPUT_EVENT
3563     prop_anr_in_input_event = MakeAtom(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT, strlen(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT),  TRUE);
3564     prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
3565 #endif
3566
3567     prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
3568     rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
3569
3570     if (rc != Success)
3571     {
3572         return;
3573     }
3574
3575     XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
3576 }
3577
3578 static int
3579 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
3580         BOOL checkonly)
3581 {
3582     if (prop_gesture_recognizer_onoff == atom)
3583     {
3584         int data;
3585         if (val->format != 32 || val->type != XA_INTEGER || val->size != 1)
3586             return BadMatch;
3587
3588         if (!checkonly)
3589         {
3590             data = *((int *)val->data);
3591             GestureEnable(data, TRUE, dev);
3592         }
3593     }
3594     return Success;
3595 }
3596 #endif//HAVE_PROPERTIES
3597
3598 static int
3599 GestureInit(DeviceIntPtr device)
3600 {
3601 #ifdef HAVE_PROPERTIES
3602     GestureInitProperty(device);
3603     XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
3604 #endif
3605     //GestureEnable(1, FALSE, g_pGesture->this_device);
3606     return Success;
3607 }
3608
3609 static void
3610 GestureFini(DeviceIntPtr device)
3611 {
3612     XIRegisterPropertyHandler(device, NULL, NULL, NULL);
3613 }
3614
3615 static pointer
3616 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
3617 {
3618     xf86AddInputDriver(&GESTURE, module, 0);
3619     return module;
3620 }
3621
3622 static void
3623 GestureUnplug(pointer p)
3624 {
3625 }
3626
3627 static int
3628 GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3629 {
3630     int rc = BadAlloc;
3631     GestureDevicePtr pGesture;
3632
3633     pGesture = calloc(1, sizeof(GestureDeviceRec));
3634
3635     if (!pGesture)
3636     {
3637         pInfo->private = NULL;
3638         //xf86DeleteInput(pInfo, 0);
3639         goto error;
3640     }
3641
3642     g_pGesture = pGesture;
3643
3644     pInfo->private = pGesture;
3645     pInfo->flags = 0;
3646     pInfo->read_input = GestureReadInput; /* new data avl */
3647     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
3648     pInfo->device_control = GestureControl; /* enable/disable dev */
3649
3650     /* process driver specific options */
3651     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
3652     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
3653     pGesture->gestureWin = None;
3654     pGesture->lastSelectedWin = None;
3655     pGesture->power_pressed = 1;
3656     pGesture->hwkey_id = 0;
3657     pGesture->hwkey_dev = NULL;
3658     pGesture->num_tap_repeated = 0;
3659     pGesture->mtsync_total_count = 0;
3660     pGesture->hwkey_name = xf86SetStrOption(pInfo->options, "BackHWKeyName", NULL);
3661     pGesture->screen_width = xf86SetIntOption(pInfo->options,"ScreenWidth", 0);
3662     pGesture->screen_height = xf86SetIntOption(pInfo->options,"ScreenHeight", 0);
3663     pGesture->hwkeycode_flick_down = xf86SetIntOption(pInfo->options, "FlickDownKeycode", 0);
3664     pGesture->hwkeycode_flick_up = xf86SetIntOption(pInfo->options, "FlickUpKeycode", 0);
3665     pGesture->flick_press_area = xf86SetIntOption(pInfo->options, "FlickPressArea", 0);
3666     pGesture->flick_press_area_left = xf86SetIntOption(pInfo->options, "FlickPressArea_LEFT", 0);
3667     pGesture->flick_press_area_left_right = xf86SetIntOption(pInfo->options, "FlickPressArea_LEFT_RIGHT", 0);
3668     pGesture->flick_minimum_height = xf86SetIntOption(pInfo->options, "FlickMinimumHeight", 0);
3669     pGesture->shutdown_keycode = xf86SetIntOption(pInfo->options, "ShutdownKeycode", 0);
3670     pGesture->singletap_threshold= xf86SetIntOption(pInfo->options, "SingleTapThresHold", 0);
3671     pGesture->doubletap_threshold= xf86SetIntOption(pInfo->options, "DoubleTapThresHold", 0);
3672     pGesture->tripletap_threshold= xf86SetIntOption(pInfo->options, "TripleTapThresHold", 0);
3673     pGesture->hold_area_threshold = xf86SetRealOption(pInfo->options, "HoldAreaThresHold", 0);
3674     pGesture->hold_move_threshold = xf86SetIntOption(pInfo->options, "HoldMoveThresHold", 0);
3675     pGesture->hold_time_threshold = xf86SetIntOption(pInfo->options, "HoldTimeThresHold", 0);
3676     pGesture->palm_flick_time_threshold = xf86SetIntOption(pInfo->options, "PalmFlickTimeThresHold", 0);
3677     pGesture->palm_flick_max_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMaxTouchMajorThresHold", 0);
3678     pGesture->palm_flick_min_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMinTouchMajorThresHold", 0);
3679     pGesture->activate_flick_down = xf86SetIntOption(pInfo->options, "ActivateFlickDown", 0);
3680     pGesture->activate_flick_up = xf86SetIntOption(pInfo->options, "ActivateFlickUp", 0);
3681     pGesture->activate_flick_right = xf86SetIntOption(pInfo->options, "ActivateFlickRight", 0);
3682     pGesture->factory_cmdname = xf86SetStrOption(pInfo->options, "FactoryCmdName", NULL);
3683
3684     ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__);
3685     ErrorF("[X11][%s] screen_width=%d, screen_height=%d\n", __FUNCTION__,
3686             pGesture->screen_width, pGesture->screen_height);
3687     ErrorF("[X11][%s] FlickDownKeycode=%d, FlickUpKeycode=%d\n", __FUNCTION__,
3688             pGesture->hwkeycode_flick_down, pGesture->hwkeycode_flick_up);
3689     ErrorF("[X11][%s] flick_press_area=%d, flick_press_area_left: %d, flick_press_area_left_right: %d, flick_minimum_height=%d\n", __FUNCTION__,
3690             pGesture->flick_press_area, pGesture->flick_press_area_left, pGesture->flick_press_area_left_right, pGesture->flick_minimum_height);
3691     ErrorF("[X11][%s] ShutdownKeycode=%d\n", __FUNCTION__, pGesture->shutdown_keycode);
3692     ErrorF("[X11][%s] singletap_threshold=%d, doubletap_threshold=%d\n", __FUNCTION__, pGesture->singletap_threshold, pGesture->doubletap_threshold);
3693     ErrorF("[X11][%s] hold_area_threshold: %f, hold_move_threshold: %d, hold_time_threshold: %d\n", __FUNCTION__,
3694             pGesture->hold_area_threshold, pGesture->hold_move_threshold, pGesture->hold_time_threshold);
3695     ErrorF("[X11][%s] palm_flick_time_threshold: %d, palm_flick_max_tmajor_threshold: %d, palm_flick_min_tmajor_threshold: %d\n", __FUNCTION__,
3696             pGesture->palm_flick_time_threshold, pGesture->palm_flick_max_tmajor_threshold, pGesture->palm_flick_min_tmajor_threshold);
3697     ErrorF("[X11][%s] activate_flick_down=%d, activate_flick_up=%d, activate_flick_right=%d\n", __FUNCTION__,
3698             pGesture->activate_flick_down, pGesture->activate_flick_up, pGesture->activate_flick_right);
3699     ErrorF("[X11][%s] factory cmd name: %s\n", __FUNCTION__, pGesture->factory_cmdname);
3700     ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__);
3701
3702     if (pGesture->hwkey_name)
3703     {
3704         ErrorF("[X11][%s] hwkey_name=%s\n", __FUNCTION__, pGesture->hwkey_name);
3705     }
3706
3707     pGesture->mtsync_flag = 0x00;
3708     g_pGesture->grabMask = g_pGesture->eventMask = 0;
3709
3710     xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
3711
3712     /* process generic options */
3713     xf86CollectInputOptions(pInfo, NULL);
3714     xf86ProcessCommonOptions(pInfo, pInfo->options);
3715
3716     pInfo->fd = -1;
3717
3718     g_pGesture->touch_cancel_status = FALSE;
3719
3720     return Success;
3721
3722 error:
3723     if (pInfo->fd >= 0)
3724         close(pInfo->fd);
3725     return rc;
3726 }
3727
3728 static void
3729 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
3730 {
3731     GestureDevicePtr pGesture = pInfo->private;
3732
3733     g_pGesture = pGesture = NULL;
3734     pInfo->private = NULL;
3735
3736     xf86DeleteInput(pInfo, 0);
3737 }
3738
3739 static int
3740 GestureControl(DeviceIntPtr device, int what)
3741 {
3742     InputInfoPtr  pInfo = device->public.devicePrivate;
3743     GestureDevicePtr pGesture = pInfo->private;
3744
3745     switch (what)
3746     {
3747         case DEVICE_INIT:
3748             GestureInit(device);
3749             break;
3750
3751             /* Switch device on.  Establish socket, start event delivery.  */
3752         case DEVICE_ON:
3753             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
3754
3755             if (device->public.on)
3756                 break;
3757
3758             device->public.on = TRUE;
3759             pGesture->this_device = device;
3760             pGesture->num_mt_devices = 0;
3761             if (ERROR_ABNORMAL == GestureEnableEventHandler(pInfo))
3762                 goto device_off;
3763             if (!AddCallback(&DPMSCallback, GestureDPMSCallback, NULL))
3764                 ErrorF("[Gesture]Failed to Add DPMS CallBack\n");
3765             break;
3766
3767         case DEVICE_OFF:
3768 device_off:
3769             GestureDisableEventHandler();
3770             DeleteCallback(&DPMSCallback, GestureDPMSCallback, NULL);
3771             GestureFini(device);
3772             pGesture->this_device = NULL;
3773             xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
3774
3775             if (!device->public.on)
3776                 break;
3777
3778             pInfo->fd = -1;
3779             device->public.on = FALSE;
3780             break;
3781
3782         case DEVICE_CLOSE:
3783             /* free what we have to free */
3784             break;
3785     }
3786     return Success;
3787 }
3788
3789 static void
3790 GestureReadInput(InputInfoPtr pInfo)
3791 {
3792 }
3793
3794
3795