Merge "AArch64 support" into tizen
[platform/adaptation/xf86-input-gesture.git] / 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 #include <stdio.h>
62 #include <sys/stat.h>
63 #include <sys/syscall.h>
64 #include <unistd.h>
65 #include <errno.h>
66 #include <sys/types.h>
67 #include <fcntl.h>
68 #include <xorg-server.h>
69 #include <xorgVersion.h>
70 #include <xf86Module.h>
71 #include <X11/Xatom.h>
72 #include "gesture.h"
73 #include <xorg/mi.h>
74
75 //Basic functions
76 static InputInfoPtr GesturePreInit(InputDriverPtr  drv, InputInfoPtr pInfo, int flags);
77 static void GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
78 static pointer GesturePlug(pointer module, pointer options, int *errmaj, int  *errmin);
79 static void GestureUnplug(pointer p);
80 static int GestureControl(DeviceIntPtr    device,int what);
81 static int GestureInit(DeviceIntPtr device);
82 static void GestureFini(DeviceIntPtr device);
83 static void GestureReadInput(InputInfoPtr pInfo);
84
85 //other initializers
86 ErrorStatus GestureRegionsInit(void);
87
88 //event queue handling functions
89 ErrorStatus GestureInitEQ(void);
90 ErrorStatus GestureFiniEQ(void);
91 ErrorStatus GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
92 ErrorStatus GestureEventsFlush(void);
93 void GestureEventsDrop(void);
94
95 //utility functions
96 ErrorStatus GestureRegionsReinit(void);
97 void GestureEnable(int enable, Bool prop, DeviceIntPtr dev);
98 static inline void GestureEnableDisable();
99 void GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent);
100 void GestureCbEventsSelected(Window win, Mask *pEventMask);
101 WindowPtr GestureGetEventsWindow(void);
102
103 //Enqueued event handlers and enabler/disabler
104 static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
105 static ErrorStatus GestureDisableEventHandler(void);
106 static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
107 static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
108 void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
109 void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
110 void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
111 void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
112
113 //Gesture recognizer helper
114 static WindowPtr GestureWindowOnXY(int x, int y);
115 Bool GestureHasFingerEventMask(int eventType, int num_finger);
116 static double get_angle(int x1, int y1, int x2, int y2);
117
118 //Gesture recognizer and handlers
119 void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
120 void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
121 void GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
122 void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
123 void GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
124 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
125 void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction);
126 void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy);
127 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds);
128 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds);
129 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds);
130 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds);
131 void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device);
132 ErrorStatus GestureFlushOrDrop(void);
133
134 #ifdef HAVE_PROPERTIES
135 //function related property handling
136 static void GestureInitProperty(DeviceIntPtr dev);
137 static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly);
138 #endif
139
140 static Atom prop_gesture_recognizer_onoff = None;
141
142 GestureDevicePtr g_pGesture = NULL;
143 _X_EXPORT InputDriverRec GESTURE = {
144     1,
145     "gesture",
146     NULL,
147     GesturePreInit,
148     GestureUnInit,
149     NULL,
150     0
151 };
152
153 static XF86ModuleVersionInfo GestureVersionRec =
154 {
155     "gesture",
156     MODULEVENDORSTRING,
157     MODINFOSTRING1,
158     MODINFOSTRING2,
159     XORG_VERSION_CURRENT,
160     PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
161     PACKAGE_VERSION_PATCHLEVEL,
162     ABI_CLASS_XINPUT,
163     ABI_XINPUT_VERSION,
164     MOD_CLASS_XINPUT,
165     {0, 0, 0, 0}
166 };
167
168 _X_EXPORT XF86ModuleData gestureModuleData =
169 {
170     &GestureVersionRec,
171     &GesturePlug,
172     &GestureUnplug
173 };
174
175 static void
176 printk(const char* fmt, ...)
177 {
178         static FILE* fp = NULL;
179         static char init = 0;
180         va_list argptr;
181
182         if(!init && !fp)
183         {
184                 fp = fopen("/dev/kmsg", "wt");
185                 init = 1;
186         }
187
188         if(!fp) return;
189
190         va_start(argptr, fmt);
191         vfprintf(fp, fmt, argptr);
192         fflush(fp);
193         va_end(argptr);
194 }
195
196 static WindowPtr
197 GestureWindowOnXY(int x, int y)
198 {
199     WindowPtr pWin;
200     BoxRec box;
201     SpritePtr pSprite;
202     DeviceIntPtr pDev = g_pGesture->master_pointer;
203
204     pSprite = pDev->spriteInfo->sprite;
205     pSprite->spriteTraceGood = 1;       /* root window still there */
206     pWin = RootWindow(pDev)->firstChild;
207
208     while (pWin)
209     {
210         if ((pWin->mapped) &&
211             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
212             (x < pWin->drawable.x + (int)pWin->drawable.width +
213              wBorderWidth(pWin)) &&
214             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
215             (y < pWin->drawable.y + (int)pWin->drawable.height +
216              wBorderWidth (pWin))
217             /* When a window is shaped, a further check
218              * is made to see if the point is inside
219              * borderSize
220              */
221             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
222             && (!wInputShape(pWin) ||
223                 RegionContainsPoint(wInputShape(pWin),
224                                     x - pWin->drawable.x,
225                                     y - pWin->drawable.y, &box))
226 #ifdef ROOTLESS
227     /* In rootless mode windows may be offscreen, even when
228      * they're in X's stack. (E.g. if the native window system
229      * implements some form of virtual desktop system).
230      */
231                 && !pWin->rootlessUnhittable
232 #endif
233             )
234         {
235             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
236             {
237                 pSprite->spriteTraceSize += 10;
238                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
239                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
240             }
241             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
242             pWin = pWin->firstChild;
243         }
244         else
245             pWin = pWin->nextSib;
246     }
247     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
248 }
249
250 Bool
251 GestureHasFingerEventMask(int eventType, int num_finger)
252 {
253         Bool ret = FALSE;
254         Mask eventmask = (1L << eventType);
255
256         if( (g_pGesture->grabMask & eventmask) &&
257                 (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
258         {
259 #ifdef __DETAIL_DEBUG__
260                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
261 #endif//__DETAIL_DEBUG__
262                 return TRUE;
263         }
264
265         if( g_pGesture->eventMask & eventmask )
266         {
267 #ifdef __DETAIL_DEBUG__
268                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
269 #endif//__DETAIL_DEBUG__
270                 return TRUE;
271         }
272
273 #ifdef __DETAIL_DEBUG__
274         ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
275 #endif//__DETAIL_DEBUG__
276
277         return ret;
278 }
279
280 static double
281 get_angle(int x1, int y1, int x2, int y2)
282 {
283    double a, xx, yy;
284    xx = fabs(x2 - x1);
285    yy = fabs(y2 - y1);
286
287    if (((int) xx) && ((int) yy))
288      {
289         a = atan(yy / xx);
290         if (x1 < x2)
291           {
292              if (y1 < y2)
293                {
294                   return (RAD_360DEG - a);
295                }
296              else
297                {
298                   return (a);
299                }
300           }
301         else
302           {
303              if (y1 < y2)
304                {
305                   return (RAD_180DEG + a);
306                }
307              else
308                {
309                   return (RAD_180DEG - a);
310                }
311           }
312      }
313
314    if (((int) xx))
315      {  /* Horizontal line */
316         if (x2 < x1)
317           {
318              return (RAD_180DEG);
319           }
320         else
321           {
322              return (0.0);
323           }
324      }
325
326    /* Vertical line */
327    if (y2 < y1)
328      {
329         return (RAD_90DEG);
330      }
331    else
332      {
333         return (RAD_270DEG);
334      }
335 }
336
337 void
338 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
339 {
340         Window target_win;
341         WindowPtr target_pWin;
342         xGestureNotifyFlickEvent fev;
343
344 #ifdef __DETAIL_DEBUG__
345         ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
346                 num_of_fingers, distance, duration, direction);
347 #endif//__DETAIL_DEBUG__
348
349         g_pGesture->recognized_gesture |= FlickFilterMask;
350         memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
351         fev.type = GestureNotifyFlick;
352         fev.kind = GestureDone;
353         fev.num_finger = num_of_fingers;
354         fev.distance = distance;
355         fev.duration = duration;
356         fev.direction = direction;
357
358         target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
359         target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
360
361         if( g_pGesture->grabMask && (target_win != None) )
362         {
363                 fev.window = target_win;
364         }
365         else
366         {
367                 fev.window = g_pGesture->gestureWin;
368         }
369
370 #ifdef __DETAIL_DEBUG__
371         ErrorF("[X11][GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
372 #endif//__DETAIL_DEBUG__
373
374         GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
375 }
376
377 void
378 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
379 {
380         Window target_win;
381         WindowPtr target_pWin;
382         xGestureNotifyTapEvent tev;
383
384         //skip non-tap events and single finger tap
385         if( !tap_repeat || num_finger <= 1 )
386                 return;
387
388 #ifdef __DETAIL_DEBUG__
389         ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
390                 num_finger, tap_repeat, cx, cy);
391 #endif//__DETAIL_DEBUG__
392
393         g_pGesture->recognized_gesture |= TapFilterMask;
394         memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
395         tev.type = GestureNotifyTap;
396         tev.kind = GestureDone;
397         tev.num_finger = num_finger;
398         tev.tap_repeat = tap_repeat;
399         tev.interval = 0;
400         tev.cx = cx;
401         tev.cy = cy;
402
403         target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
404         target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
405
406         if( g_pGesture->grabMask && (target_win != None) )
407         {
408                 tev.window = target_win;
409         }
410         else
411         {
412                 tev.window = g_pGesture->gestureWin;
413         }
414
415 #ifdef __DETAIL_DEBUG__
416         ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", tev.window, g_pGesture->grabMask);
417 #endif//__DETAIL_DEBUG__
418
419         GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
420 }
421
422 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds)
423 {
424         Window target_win;
425         WindowPtr target_pWin;
426         xGestureNotifyPinchRotationEvent prev;
427
428 #ifdef __DETAIL_DEBUG__
429         ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n",
430                                 num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy);
431 #endif//__DETAIL_DEBUG__
432
433         g_pGesture->recognized_gesture |= PinchRotationFilterMask;
434         memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent));
435         prev.type = GestureNotifyPinchRotation;
436         prev.kind = kinds;
437         prev.num_finger = num_of_fingers;
438         prev.zoom = XDoubleToFixed(zoom);
439         prev.angle = XDoubleToFixed(angle);
440         prev.distance = distance;
441         prev.cx = cx;
442         prev.cy = cy;
443
444         target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window;
445         target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin;
446
447         if( g_pGesture->grabMask && (target_win != None) )
448         {
449                 prev.window = target_win;
450         }
451         else
452         {
453                 prev.window = g_pGesture->gestureWin;
454         }
455
456 #ifdef __DETAIL_DEBUG__
457         ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)prev.window, (unsigned int)g_pGesture->grabMask);
458 #endif//__DETAIL_DEBUG__
459
460         GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev);
461 }
462
463 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
464 {
465         Window target_win;
466         WindowPtr target_pWin;
467         xGestureNotifyHoldEvent hev;
468
469 #ifdef __DETAIL_DEBUG__
470         ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
471                                 num_fingers, cx, cy, holdtime, kinds);
472 #endif//__DETAIL_DEBUG__
473
474         g_pGesture->recognized_gesture |= HoldFilterMask;
475         memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
476         hev.type = GestureNotifyHold;
477         hev.kind = kinds;
478         hev.num_finger = num_fingers;
479         hev.holdtime = holdtime;
480         hev.cx = cx;
481         hev.cy = cy;
482
483         target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
484         target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
485
486         if( g_pGesture->grabMask && (target_win != None) )
487         {
488                 hev.window = target_win;
489         }
490         else
491         {
492                 hev.window = g_pGesture->gestureWin;
493         }
494
495 #ifdef __DETAIL_DEBUG__
496         ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
497 #endif//__DETAIL_DEBUG__
498
499         GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
500 }
501
502 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds)
503 {
504         Window target_win;
505         WindowPtr target_pWin;
506         xGestureNotifyTapNHoldEvent thev;
507
508 #ifdef __DETAIL_DEBUG__
509         ErrorF("[X11][GestureHandleGesture_TapNHold] num_fingers=%d, cx=%d, cy=%d, interval=%d, holdtime=%d, kinds=%d\n",
510                                 num_fingers, cx, cy, interval, holdtime, kinds);
511 #endif//__DETAIL_DEBUG__
512
513         g_pGesture->recognized_gesture |= TapNHoldFilterMask;
514         memset(&thev, 0, sizeof(xGestureNotifyTapNHoldEvent));
515         thev.type = GestureNotifyTapNHold;
516         thev.kind = kinds;
517         thev.num_finger = num_fingers;
518         thev.holdtime = holdtime;
519         thev.cx = cx;
520         thev.cy = cy;
521         thev.interval = interval;
522
523         target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window;
524         target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin;
525
526         if( g_pGesture->grabMask && (target_win != None) )
527         {
528                 thev.window = target_win;
529         }
530         else
531         {
532                 thev.window = g_pGesture->gestureWin;
533         }
534
535 #ifdef __DETAIL_DEBUG__
536         ErrorF("[X11][GestureHandleGesture_TapNHold] thev.window=0x%x, g_pGesture->grabMask=0x%x\n", thev.window, g_pGesture->grabMask);
537 #endif//__DETAIL_DEBUG__
538
539         GestureSendEvent(target_pWin, GestureNotifyTapNHold, GestureTapNHoldMask, (xGestureCommonEvent *)&thev);
540 }
541
542 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds)
543 {
544         Window target_win;
545         WindowPtr target_pWin;
546         xGestureNotifyPanEvent pev;
547
548 #ifdef __DETAIL_DEBUG__
549         ErrorF("[X11][GestureHandleGesture_Pan] num_fingers=%d, dx=%d, dy=%d, direction=%d, distance=%d, duration=%d, kinds=%d\n",
550                                 num_fingers, dx, dy, direction, distance, duration, kinds);
551 #endif//__DETAIL_DEBUG__
552
553         g_pGesture->recognized_gesture |= PanFilterMask;
554         memset(&pev, 0, sizeof(xGestureNotifyPanEvent));
555         pev.type = GestureNotifyPan;
556         pev.kind = kinds;
557         pev.num_finger = num_fingers;
558         pev.direction = direction;
559         pev.distance = distance;
560         pev.duration = duration;
561         pev.dx = dx;
562         pev.dy = dy;
563
564         target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window;
565         target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin;
566
567         if( g_pGesture->grabMask && (target_win != None) )
568         {
569                 pev.window = target_win;
570         }
571         else
572         {
573                 pev.window = g_pGesture->gestureWin;
574         }
575
576 #ifdef __DETAIL_DEBUG__
577         ErrorF("[X11][GestureHandleGesture_Pan] pev.window=0x%x, g_pGesture->grabMask=0x%x\n", pev.window, g_pGesture->grabMask);
578 #endif//__DETAIL_DEBUG__
579
580         GestureSendEvent(target_pWin, GestureNotifyPan, GesturePanMask, (xGestureCommonEvent *)&pev);
581 }
582
583 void
584 GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
585 {
586         static int cx, cy;
587
588         static int num_pressed = 0;
589         static int state = GestureEnd;
590         static int event_type = GestureNotifyPinchRotation;
591         static OsTimerPtr pinchrotation_event_timer = NULL;
592
593         static pixman_region16_t base_area;
594         static pixman_region16_t cur_area;
595
596         static double base_distance = 0.0f;
597         static double base_angle = 0.0f;
598
599         static double prev_distance = 0.0f;
600         static double prev_angle = 0.0f;
601
602         static double cur_distance = 0.0f;
603         static double cur_angle = 0.0f;
604
605         double diff_distance = 0.0f;
606         double diff_angle = 0.0f;
607
608         static int has_event_mask = 0;
609
610         static Time base_time = 0;
611         Time current_time;
612
613         if( timer_expired )
614         {
615                 if( state == GestureEnd )
616                 {
617                         current_time = GetTimeInMillis();
618                         if( (current_time - base_time) >= PINCHROTATION_TIME_THRESHOLD )
619                         {
620 #ifdef __DETAIL_DEBUG__
621                                 ErrorF("[GroupPinchRotation][Timer] You must move farther than dist threshold(=%.2f) or angle threshold(=%2f) within time threshold(=%d) !\n", PINCHROTATION_DIST_THRESHOLD, PINCHROTATION_ANGLE_THRESHOLD, PINCHROTATION_TIME_THRESHOLD);
622 #endif//__DETAIL_DEBUG__
623                                 goto cleanup_pinchrotation;
624                         }
625                 }
626
627                 return;
628         }
629
630         switch( type )
631         {
632                 case ET_ButtonPress:
633                         g_pGesture->fingers[idx].flags |= PressFlagPinchRotation;
634
635                         if( g_pGesture->num_pressed < 2 )
636                                 return;
637
638                         if( g_pGesture->num_pressed < num_pressed && state != GestureEnd )
639                         {
640 #ifdef __DETAIL_DEBUG__
641                                 ErrorF("[GroupPinchRotation][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
642 #endif//__DETAIL_DEBUG__
643                                 goto cleanup_pinchrotation;
644                         }
645
646                         if( base_distance == 0.0f && g_pGesture->num_pressed == 2 )
647                         {
648 #ifdef __DETAIL_DEBUG__
649                                 ErrorF("[GroupPinchRotation][First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
650 #endif//__DETAIL_DEBUG__
651
652                                 base_time = GetTimeInMillis();
653                                 pixman_region_init(&base_area);
654                                 pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
655
656                                 prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents);
657
658 #ifdef __DETAIL_DEBUG__
659                                 ErrorF("[GroupPinchRotation][P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px,
660                                 g_pGesture->fingers[0].py, g_pGesture->fingers[1].py);
661 #endif//__DETAIL_DEBUG__
662
663                                 prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py);
664 #ifdef __DETAIL_DEBUG__
665                                 ErrorF("[GroupPinchRotation][P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle));
666 #endif//__DETAIL_DEBUG__
667                                 event_type = GestureNotifyPinchRotation;
668                                 pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, PINCHROTATION_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
669                         }
670                         num_pressed = g_pGesture->num_pressed;
671
672 #ifdef __DETAIL_DEBUG__
673                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents));
674                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle));
675 #endif//__DETAIL_DEBUG__
676                         break;
677
678                 case ET_Motion:
679                         if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) )
680                                 break;
681
682                         if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) )
683                         {
684 #ifdef __DETAIL_DEBUG__
685                                 ErrorF("[GroupPinchRotation][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
686 #endif//__DETAIL_DEBUG__
687                                 goto cleanup_pinchrotation;
688                         }
689
690                         if( num_pressed < 2 )
691                                 return;
692
693                         if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my )
694                         {
695                                 pixman_region_init(&cur_area);
696                                 pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
697
698                                 cur_distance = AREA_DIAG_LEN(&cur_area.extents);
699
700 #ifdef __DETAIL_DEBUG__
701                                 ErrorF("[GroupPinchRotation][M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx,
702                                 g_pGesture->fingers[0].my, g_pGesture->fingers[1].my);
703 #endif//__DETAIL_DEBUG__
704
705                                 cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my);
706 #ifdef __DETAIL_DEBUG__
707                                 ErrorF("[GroupPinchRotation][M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle));
708 #endif//__DETAIL_DEBUG__
709
710                                 diff_distance = prev_distance - cur_distance;
711                                 diff_angle = prev_angle - cur_angle;
712
713                                 cx = AREA_CENTER_X(&cur_area.extents);
714                                 cy = AREA_CENTER_Y(&cur_area.extents);
715
716 #ifdef __DETAIL_DEBUG__
717                                 ErrorF("[GroupPinchRotation][M][state=%d] cx=%d, cy=%d\n", state, cx, cy);
718 #endif//__DETAIL_DEBUG__
719
720 #ifdef __DETAIL_DEBUG__
721                                 ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance);
722                                 ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_angle=%.2f(deg=%.2f), cur_angle=%.2f(deg=%.2f), diff=%.2f(deg=%.2f)\n", num_pressed, prev_angle, rad2degree(prev_angle), cur_angle, rad2degree(cur_angle), diff_angle, rad2degree(diff_angle));
723 #endif//__DETAIL_DEBUG__
724
725                                 switch( state )
726                                 {
727                                         case GestureEnd:
728                                                 if( (ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD) || (ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD) )
729                                                 {
730 #ifdef __DETAIL_DEBUG__
731                                                         if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
732                                                                 ErrorF("[GroupPinchRotation][M] zoom changed !\n");
733
734                                                         if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
735                                                                 ErrorF("[GroupPinchRotation][M] angle changed !\n");
736 #endif//__DETAIL_DEBUG__
737
738                                                         TimerCancel(pinchrotation_event_timer);
739                                                         state = GestureBegin;
740                                                         goto gesture_begin_handle;
741                                                 }
742                                                 break;
743
744                                         case GestureBegin:
745 gesture_begin_handle:
746 #ifdef __DETAIL_DEBUG__
747                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state);
748 #endif//__DETAIL_DEBUG__
749                                                 if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) )
750                                                 {
751                                                         GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureBegin);
752                                                         prev_distance = cur_distance;
753                                                         prev_angle = cur_angle;
754                                                         state = GestureUpdate;
755                                                         has_event_mask = 1;
756                                                 }
757                                                 else
758                                                 {
759                                                         has_event_mask = 0;
760                                                         goto cleanup_pinchrotation;
761                                                 }
762                                                 break;
763
764                                         case GestureUpdate:
765                                                 //if( ABS(diff_distance) < PINCHROTATION_DIST_THRESHOLD && ABS(diff_angle) < PINCHROTATION_ANGLE_THRESHOLD )
766                                                 //      break;
767
768 #ifdef __DETAIL_DEBUG__
769                                                 if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
770                                                         ErrorF("[GroupPinchRotation][M] zoom changed !\n");
771
772                                                 if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
773                                                         ErrorF("[GroupPinchRotation][M] angle changed !\n");
774 #endif//__DETAIL_DEBUG__
775
776 #ifdef __DETAIL_DEBUG__
777                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
778 #endif//__DETAIL_DEBUG__
779                                                 GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureUpdate);
780                                                 prev_distance = cur_distance;
781                                                 prev_angle = cur_angle;
782                                                 break;
783
784                                         case GestureDone:
785                                         default:
786                                                 break;
787                                 }
788                         }
789                         break;
790
791                 case ET_ButtonRelease:
792                         if( state != GestureEnd && num_pressed >= 2)
793                         {
794 #ifdef __DETAIL_DEBUG__
795                                 ErrorF("[GroupPinchRotation][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
796 #endif//__DETAIL_DEBUG__
797                                 goto cleanup_pinchrotation;
798                         }
799
800                         if( g_pGesture->num_pressed )
801                                 break;
802
803                         goto cleanup_pinchrotation;
804                         break;
805         }
806
807         return;
808
809 cleanup_pinchrotation:
810
811         if(  has_event_mask  && (state == GestureBegin || state == GestureUpdate) )
812         {
813                 state = GestureEnd;
814 #ifdef __DETAIL_DEBUG__
815                 ErrorF("[GroupPinchRotation] PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
816 #endif//__DETAIL_DEBUG__
817                 GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureEnd);
818         }
819         else
820         {
821                 g_pGesture->recognized_gesture &= ~PinchRotationFilterMask;
822         }
823
824         g_pGesture->filter_mask |= PinchRotationFilterMask;
825
826         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
827         {
828 #if 1//def __DETAIL_DEBUG__
829                 ErrorF("[GroupPinchRotation][cleanup] GestureFlushOrDrop() !\n");
830 #endif//__DETAIL_DEBUG__
831
832                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
833                 {
834                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
835                 }
836         }
837
838         prev_distance = base_distance = 0.0f;
839         prev_angle = base_angle = 0.0f;
840         has_event_mask = num_pressed = 0;
841         state = GestureEnd;
842         cx = cy = 0;
843         TimerCancel(pinchrotation_event_timer);
844         return;
845 }
846
847 void
848 GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
849 {
850         static int num_pressed = 0;
851         static int mbits = 0;
852         static int base_area_size = 0;
853         static Time base_time = 0;
854         static int base_x, base_y;
855         Time current_time;
856         Time duration;
857         int distx, disty;
858         int distance, direction;
859         int area_size;
860         int flicked = 0;
861
862         switch( type )
863         {
864                 case ET_ButtonPress:
865                         g_pGesture->fingers[idx].flags |= PressFlagFlick;
866
867                         if( g_pGesture->num_pressed < 2 )
868                                 return;
869
870                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
871                         {
872                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
873                                 base_x = g_pGesture->area.extents.x1;
874                                 base_y = g_pGesture->area.extents.y1;
875                                 base_time = GetTimeInMillis();
876                         }
877                         num_pressed = g_pGesture->num_pressed;
878
879 #ifdef __DETAIL_DEBUG__
880                         ErrorF("[GroupFlick][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, base_area_size);
881 #endif//__DETAIL_DEBUG__
882                         break;
883
884                 case ET_Motion:
885                         if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
886                                 break;
887
888 #ifdef __DETAIL_DEBUG__
889                         if( num_pressed > g_pGesture->num_pressed )
890                         {
891                                 ErrorF("[GroupFlick][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
892                                 //goto cleanup_flick;
893                         }
894 #endif//__DETAIL_DEBUG__
895
896                         if( num_pressed < 2 )
897                                 return;
898
899                         mbits |= (1 << idx);
900                         if( mbits == (pow(2, num_pressed)-1) )
901                         {
902                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
903 #ifdef __DETAIL_DEBUG__
904                                 ErrorF("[M][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, area_size);
905 #endif//__DETAIL_DEBUG__
906                                 if( ABS(base_area_size - area_size) >= FLICK_AREA_THRESHOLD )
907                                 {
908 #ifdef __DETAIL_DEBUG__
909                                         ErrorF("[GroupFlick][M] diff between Area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, FLICK_AREA_THRESHOLD);
910 #endif//__DETAIL_DEBUG__
911                                         goto cleanup_flick;
912                                 }
913
914                                 current_time = GetTimeInMillis();
915                                 if( (current_time - base_time) >= FLICK_AREA_TIMEOUT )
916                                 {
917 #ifdef __DETAIL_DEBUG__
918                                         ErrorF("[GroupFlick][M] diff between current time(=%d) and base time(=%d) is bigger than threashold(=%d) !\n", current_time, base_time, FLICK_AREA_TIMEOUT);
919 #endif//__DETAIL_DEBUG__
920                                         goto cleanup_flick;
921                                 }
922                                 mbits = 0;
923                         }
924                         break;
925
926                 case ET_ButtonRelease:
927                         if( g_pGesture->num_pressed )
928                                 break;
929
930                         duration = GetTimeInMillis() - base_time;
931                         distx = g_pGesture->area.extents.x1 - base_x;
932                         disty = g_pGesture->area.extents.y1 - base_y;
933
934 #ifdef __DETAIL_DEBUG__
935                         ErrorF("[GroupFlick] duration=%d, distx=%d, disty=%d\n", duration, distx, disty);
936 #endif//__DETAIL_DEBUG__
937
938                         if( duration <= 0 || duration >= FLICK_AREA_TIMEOUT )
939                                 goto cleanup_flick;
940
941                         if( ABS(distx) >= FLICK_MOVE_THRESHOLD )
942                         {
943                                 direction = (distx > 0) ? FLICK_EASTWARD : FLICK_WESTWARD;
944                                 distance = ABS(distx);
945                                 flicked++;
946                         }
947                         else if( ABS(disty) >= FLICK_MOVE_THRESHOLD )
948                         {
949                                 direction = (disty > 0) ? FLICK_SOUTHWARD : FLICK_NORTHWARD;
950                                 distance = ABS(disty);
951                                 flicked++;
952                         }
953
954                         if( !flicked )
955                                 goto cleanup_flick;
956
957                         if( GestureHasFingerEventMask(GestureNotifyFlick, num_pressed) )
958                                 GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
959                         goto cleanup_flick_recognized;
960                         break;
961         }
962
963         return;
964
965 cleanup_flick:
966
967         g_pGesture->recognized_gesture &= ~FlickFilterMask;
968
969 cleanup_flick_recognized:
970
971         g_pGesture->filter_mask |= FlickFilterMask;
972         num_pressed = 0;
973         base_area_size = 0;
974         base_time = 0;
975         mbits = 0;
976         return;
977 }
978
979 void
980 GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
981 {
982         static int num_pressed = 0;
983         static int mbits = 0;
984         static int base_area_size = 0;
985         static Time base_time = 0;
986         static pixman_box16_t base_box_ext;
987         static int base_cx;
988         static int base_cy;
989         static int prev_cx;
990         static int prev_cy;
991         static int cx = 0;
992         static int cy = 0;
993         int dx, dy;
994         static Time prev_time = 0;
995         Time current_time = 0;
996         int distance = 0;
997         int direction = 0;
998         int area_size;
999         static int time_checked = 0;
1000         static int state = GestureEnd;
1001
1002         static OsTimerPtr pan_event_timer = NULL;
1003         static int event_type = GestureNotifyPan;
1004
1005         if( timer_expired )
1006         {
1007                 if( !time_checked )
1008                 {
1009                         current_time = GetTimeInMillis();
1010                         if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
1011                         {
1012                                 if( (!cx && !cy) || INBOX(&base_box_ext, cx, cy) )
1013                                 {
1014 #ifdef __DETAIL_DEBUG__
1015                                         ErrorF("[GroupPan][Timer] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
1016 #endif//__DETAIL_DEBUG__
1017                                         goto cleanup_pan;
1018                                 }
1019                                 time_checked = 1;
1020                         }
1021                 }
1022                 return;
1023         }
1024
1025         switch( type )
1026         {
1027                 case ET_ButtonPress:
1028                         g_pGesture->fingers[idx].flags |= PressFlagPan;
1029
1030                         if( g_pGesture->num_pressed < 2 )
1031                                 return;
1032
1033                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1034                         {
1035                                 if( state != GestureEnd )
1036                                 {
1037 #ifdef __DETAIL_DEBUG__
1038                                         ErrorF("[GroupPan][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1039 #endif//__DETAIL_DEBUG__
1040                                         goto cleanup_pan;
1041                                 }
1042                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1043                                 prev_cx = base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1044                                 prev_cy = base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1045                                 prev_time = base_time = GetTimeInMillis();
1046                                 base_box_ext.x1 = base_cx-PAN_MOVE_THRESHOLD;
1047                                 base_box_ext.y1 = base_cy-PAN_MOVE_THRESHOLD;
1048                                 base_box_ext.x2 = base_cx+PAN_MOVE_THRESHOLD;
1049                                 base_box_ext.y2 = base_cy+PAN_MOVE_THRESHOLD;
1050                                 event_type = GestureNotifyPan;
1051                                 pan_event_timer = TimerSet(pan_event_timer, 0, PAN_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1052                         }
1053                         num_pressed = g_pGesture->num_pressed;
1054
1055 #ifdef __DETAIL_DEBUG__
1056                         ErrorF("[GroupPan][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
1057 #endif//__DETAIL_DEBUG__
1058                         break;
1059
1060                 case ET_Motion:
1061                         if( !(g_pGesture->fingers[idx].flags & PressFlagPan ) )
1062                                 break;
1063
1064                         if( num_pressed != g_pGesture->num_pressed )
1065                         {
1066                                 if( state != GestureEnd )
1067                                 {
1068 #ifdef __DETAIL_DEBUG__
1069                                 ErrorF("[GroupPan][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1070 #endif//__DETAIL_DEBUG__
1071                                         goto cleanup_pan;
1072                                 }
1073                         }
1074
1075                         if( num_pressed < 2 )
1076                                 return;
1077
1078                         mbits |= (1 << idx);
1079                         if( mbits == (pow(2, num_pressed)-1) )
1080                         {
1081                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1082 #ifdef __DETAIL_DEBUG__
1083                                 ErrorF("[GroupPan][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));
1084 #endif//__DETAIL_DEBUG__
1085
1086                                 if( (state != GestureUpdate) && (ABS(base_area_size - area_size) >= PAN_AREA_THRESHOLD) )
1087                                 {
1088 #ifdef __DETAIL_DEBUG__
1089                                         ErrorF("[GroupPan][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, PAN_AREA_THRESHOLD);
1090 #endif//__DETAIL_DEBUG__
1091                                         goto cleanup_pan;
1092                                 }
1093
1094                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1095                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1096 #ifdef __DETAIL_DEBUG__
1097                                 ErrorF("[GroupPan][M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx));
1098                                 ErrorF("[GroupPan][M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy));
1099 #endif//__DETAIL_DEBUG__
1100
1101                                 if( state <= GestureBegin )
1102                                 {
1103                                         if( !INBOX(&base_box_ext, cx, cy) )
1104                                         {
1105                                                 TimerCancel(pan_event_timer);
1106                                                 pan_event_timer = NULL;
1107                                                 
1108                                                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1109                                                 {
1110                                                         GestureHandleGesture_Pan(num_pressed, prev_cx, prev_cy, direction, distance, current_time-prev_time, GestureBegin);
1111                                                         state = GestureUpdate;
1112                                                 }
1113                                                 else
1114                                                         goto cleanup_pan;
1115                                         }
1116                                 }
1117                                 else
1118                                 {
1119                                         dx = cx-prev_cx;
1120                                         dy = cy-prev_cy;
1121
1122                                         //if( ABS(dx) >= PAN_UPDATE_MOVE_THRESHOLD || ABS(dy) >= PAN_UPDATE_MOVE_THRESHOLD )
1123                                         {
1124 #ifdef __DETAIL_DEBUG__
1125                                                 ErrorF("[GroupPan] PAN Update !dx=%d, dy=%d, state=%d\n", dx, dy, state);
1126 #endif//__DETAIL_DEBUG__
1127
1128                                                 GestureHandleGesture_Pan(num_pressed, dx, dy, direction, distance, current_time-prev_time, GestureUpdate);
1129                                         }
1130                                 }
1131
1132                                 prev_cx = cx;
1133                                 prev_cy = cy;
1134                                 mbits = 0;
1135                         }
1136                         break;
1137
1138                 case ET_ButtonRelease:
1139                         if( state != GestureEnd && num_pressed >= 2)
1140                         {
1141 #ifdef __DETAIL_DEBUG__
1142                                 ErrorF("[GroupPan][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1143 #endif//__DETAIL_DEBUG__
1144                                 goto cleanup_pan;
1145                         }
1146
1147                         if( g_pGesture->num_pressed )
1148                                 break;
1149
1150                         goto cleanup_pan;
1151                         break;
1152         }
1153
1154         return;
1155
1156 cleanup_pan:
1157
1158         if( state == GestureBegin || state == GestureUpdate )
1159         {
1160                 state = GestureEnd;
1161                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1162                 {
1163                         GestureHandleGesture_Pan(num_pressed, (short int)(cx-prev_cx), (short int)(cy-prev_cy), direction, distance, GetTimeInMillis()-prev_time, GestureEnd);
1164                 }
1165         }
1166         else
1167         {
1168                 g_pGesture->recognized_gesture &= ~PanFilterMask;
1169         }
1170
1171         g_pGesture->filter_mask |= PanFilterMask;
1172         num_pressed = 0;
1173         base_area_size = 0;
1174         base_time = 0;
1175         mbits = 0;
1176         time_checked = 0;
1177         state = GestureEnd;
1178         cx = cy = 0;
1179         prev_time = 0;
1180         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1181         if( pan_event_timer )
1182         {
1183                 TimerCancel(pan_event_timer);
1184                 pan_event_timer = NULL;
1185         }
1186         return;
1187 }
1188
1189 void
1190 GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1191 {
1192         static int num_pressed = 0;
1193         static int base_area_size = 0;
1194
1195         static Time base_time = 0;
1196         Time current_time;
1197
1198         int cx, cy;
1199         int area_size;
1200
1201         static int state = 0;
1202         static int mbits = 0;
1203         static int base_cx;
1204         static int base_cy;
1205         static pixman_box16_t base_box_ext;
1206
1207         static int tap_repeat = 0;
1208         static int prev_tap_repeat = 0;
1209         static int prev_num_pressed = 0;
1210
1211         static OsTimerPtr tap_event_timer = NULL;
1212         static int event_type = GestureNotifyTap;
1213
1214         if( timer_expired )
1215         {
1216 #ifdef __DETAIL_DEBUG__
1217                 ErrorF("[GroupTap][Timer] state=%d\n", state);
1218 #endif//__DETAIL_DEBUG__
1219
1220                 switch( state )
1221                 {
1222                         case 1://first tap initiation check
1223                                 if( num_pressed )
1224                                 {
1225 #ifdef __DETAIL_DEBUG__
1226                                         ErrorF("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
1227 #endif//__DETAIL_DEBUG__
1228                                         state = 0;
1229                                         goto cleanup_tap;
1230                                 }
1231                                 break;
1232
1233                         case 2:
1234                                 if( tap_repeat <= 1 )
1235                                 {
1236 #ifdef __DETAIL_DEBUG__
1237                                         ErrorF("[GroupTap][Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed);
1238 #endif//__DETAIL_DEBUG__
1239                                         state = 0;
1240                                         goto cleanup_tap;
1241                                 }
1242
1243 #ifdef __DETAIL_DEBUG__
1244                                 ErrorF("[GroupTap][Timer][state=2]  tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed);
1245 #endif//__DETAIL_DEBUG__
1246                                 if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
1247                                         GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
1248                                 goto cleanup_tap;
1249                                 break;
1250                 }
1251
1252                 return;
1253         }
1254
1255         switch( type )
1256         {
1257                 case ET_ButtonPress:
1258                         g_pGesture->fingers[idx].flags |= PressFlagTap;
1259
1260                         if( g_pGesture->num_pressed < 2 )
1261                                 return;
1262
1263                         if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
1264                         {
1265                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1266                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1267                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1268                                 base_time = GetTimeInMillis();
1269                                 base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
1270                                 base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
1271                                 base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
1272                                 base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
1273                                 state = 1;
1274                                 TimerCancel(tap_event_timer);
1275                                 tap_event_timer = TimerSet(tap_event_timer, 0, SGL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1276                         }
1277
1278                         num_pressed = g_pGesture->num_pressed;
1279
1280                         current_time = GetTimeInMillis();
1281
1282 #ifdef __DETAIL_DEBUG__
1283                         ErrorF("[GroupTap][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d, base_time=%d, current_time=%d\n", num_pressed, base_area_size, base_cx, base_cy, base_time, current_time);
1284 #endif//__DETAIL_DEBUG__
1285                         break;
1286
1287                 case ET_Motion:
1288                         if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) )
1289                                 break;
1290
1291                         if( num_pressed < 2 )
1292                                 return;
1293
1294                         if( num_pressed != g_pGesture->num_pressed )
1295                         {
1296 #ifdef __DETAIL_DEBUG__
1297                                 ErrorF("[GroupTap][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1298 #endif//__DETAIL_DEBUG__
1299                                 //goto cleanup_tap;
1300                         }
1301
1302                         mbits |= (1 << idx);
1303                         if( mbits == (pow(2, num_pressed)-1) )
1304                         {
1305                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1306                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1307                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1308 #ifdef __DETAIL_DEBUG__
1309                                 ErrorF("[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));
1310                                 ErrorF("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1311                                 ErrorF("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1312 #endif//__DETAIL_DEBUG__
1313
1314                                 if( ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD )
1315                                 {
1316 #ifdef __DETAIL_DEBUG__
1317                                         ErrorF("[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));
1318 #endif//__DETAIL_DEBUG__
1319                                         goto cleanup_tap;
1320                                 }
1321
1322                                 if( !INBOX(&base_box_ext, cx, cy) )
1323                                 {
1324 #ifdef __DETAIL_DEBUG__
1325                                         ErrorF("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
1326 #endif//__DETAIL_DEBUG__
1327                                         goto cleanup_tap;
1328                                 }
1329                         }
1330                         break;
1331
1332                 case ET_ButtonRelease:
1333                         if( g_pGesture->num_pressed )
1334                                 break;
1335
1336                         if( !tap_repeat )
1337                         {
1338                                 prev_num_pressed = num_pressed;
1339                         }
1340
1341                         prev_tap_repeat = tap_repeat;
1342                         tap_repeat++;
1343
1344 #ifdef __DETAIL_DEBUG__
1345                         ErrorF("[GroupTap][R] tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed, prev_num_pressed);
1346 #endif//__DETAIL_DEBUG__
1347
1348                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1349                         {
1350 #ifdef __DETAIL_DEBUG__
1351                                 ErrorF("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1352                                         num_pressed, prev_num_pressed, num_pressed);
1353 #endif//__DETAIL_DEBUG__
1354                                 goto cleanup_tap;
1355                         }
1356
1357                         if( tap_repeat < MAX_TAP_REPEATS )
1358                         {
1359                                 state = 2;
1360                                 TimerCancel(tap_event_timer);
1361                                 tap_event_timer = TimerSet(tap_event_timer, 0, DBL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1362                                 num_pressed = 0;
1363                                 break;
1364                         }
1365
1366 #ifdef __DETAIL_DEBUG__
1367                         ErrorF("[GroupTap][R] %d finger %s\n", num_pressed, (tap_repeat==2) ? "DBL_TAP" : "TRIPLE_TAP");
1368 #endif//__DETAIL_DEBUG__
1369
1370                         if( GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1371                                 GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
1372
1373                         if( tap_repeat >= MAX_TAP_REPEATS )
1374                         {
1375                                 goto cleanup_tap;
1376                         }
1377
1378                         prev_num_pressed = num_pressed;
1379                         num_pressed = 0;
1380                         break;
1381         }
1382
1383         return;
1384
1385 cleanup_tap:
1386
1387         if( 0 == state )
1388                 g_pGesture->recognized_gesture &= ~TapFilterMask;
1389         g_pGesture->filter_mask |= TapFilterMask;
1390
1391         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1392         {
1393 #ifdef __DETAIL_DEBUG__
1394                 ErrorF("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
1395 #endif//__DETAIL_DEBUG__
1396
1397                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1398                 {
1399                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1400                 }
1401         }
1402
1403         num_pressed = 0;
1404         tap_repeat = 0;
1405         prev_num_pressed = 0;
1406         mbits = 0;
1407         base_time = 0;
1408         state = 0;
1409         TimerCancel(tap_event_timer);
1410         return;
1411 }
1412
1413 void
1414 GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1415 {
1416         static int num_pressed = 0;
1417         static int base_area_size = 0;
1418         static Time base_time = 0;
1419         static int base_cx;
1420         static int base_cy;
1421         int cx, cy;
1422         static pixman_box16_t base_box_ext;
1423         int area_size;
1424         static int mbits = 0;
1425
1426         static int tap_repeat = 0;
1427         static int prev_num_pressed = 0;
1428
1429         static OsTimerPtr tapnhold_event_timer = NULL;
1430         static int event_type = GestureNotifyTapNHold;
1431         static int state = GestureEnd;
1432
1433         Time interval = 0;
1434         Time holdtime = 0;
1435
1436         if( timer_expired )
1437         {
1438                 if( (state == GestureEnd) && num_pressed )
1439                 {
1440 #ifdef __DETAIL_DEBUG__
1441                         ErrorF("[GroupTapNHold][Timer][state=%d] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", GestureEnd, tap_repeat, num_pressed, tap_repeat);
1442 #endif//__DETAIL_DEBUG__
1443                         state = 0;
1444                         goto cleanup_tapnhold;
1445                 }
1446
1447                 if( state == GestureDone )
1448                 {
1449 #ifdef __DETAIL_DEBUG__
1450                         ErrorF("[GroupTapNHold][Timer][state=%d] Interval between Tap and Hold is too long !\n");
1451 #endif//__DETAIL_DEBUG__
1452                         goto cleanup_tapnhold;
1453                 }
1454
1455 #ifdef __DETAIL_DEBUG__
1456                 switch( state )
1457                 {
1458                         case GestureBegin:
1459                                 ErrorF("[GroupTapNHold][Timer] TapNHold Begin !\n");
1460                                 break;
1461
1462                         case GestureUpdate:
1463                                 ErrorF("[GroupTapNHold][Timer] TapNHold Update !\n");
1464                                 break;
1465                 }
1466 #endif//__DETAIL_DEBUG__
1467
1468                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1469                 {
1470                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1471                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1472                 }
1473                 else
1474                 {
1475 #ifdef __DETAIL_DEBUG__
1476                         ErrorF("[GroupTapNHold][Timer] %d finger TapNHold event was not grabbed/selected !\n", prev_num_pressed);
1477 #endif//__DETAIL_DEBUG__
1478                         goto cleanup_tapnhold;
1479                 }
1480
1481                 if( state <= GestureBegin )
1482                         state++;
1483                 return;
1484         }
1485
1486         switch( type )
1487         {
1488                 case ET_ButtonPress:
1489                         g_pGesture->fingers[idx].flags |= PressFlagTapNHold;
1490
1491                         if( g_pGesture->num_pressed < 2 )
1492                                 return;
1493
1494                         //if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
1495                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1496                         {
1497
1498                                 if( state == GestureUpdate )
1499                                 {
1500 #ifdef __DETAIL_DEBUG__
1501                                         ErrorF("[GroupTapNHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1502 #endif//__DETAIL_DEBUG__
1503                                         goto cleanup_tapnhold;
1504                                 }
1505
1506                                 if( state == GestureDone )
1507                                         state = GestureBegin;
1508
1509                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1510                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1511                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1512                                 base_time = GetTimeInMillis();
1513                                 base_box_ext.x1 = base_cx-TAPNHOLD_MOVE_THRESHOLD;
1514                                 base_box_ext.y1 = base_cy-TAPNHOLD_MOVE_THRESHOLD;
1515                                 base_box_ext.x2 = base_cx+TAPNHOLD_MOVE_THRESHOLD;
1516                                 base_box_ext.y2 = base_cy+TAPNHOLD_MOVE_THRESHOLD;
1517                                 if( state == GestureEnd )
1518                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1519                                 else
1520                                 {
1521                                         TimerCancel(tapnhold_event_timer);
1522                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1523                                 }
1524 #ifdef __DETAIL_DEBUG__
1525                                 ErrorF("[GroupTapNHold][P] Create Timer !(state=%d)\n", state);
1526 #endif//__DETAIL_DEBUG__
1527                         }
1528
1529                         num_pressed = g_pGesture->num_pressed;
1530
1531 #ifdef __DETAIL_DEBUG__
1532                         ErrorF("[GroupTapNHold][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d, base_time=%d\n", num_pressed, base_area_size, base_cx, base_cy, base_time);
1533 #endif//__DETAIL_DEBUG__
1534                         break;
1535
1536                 case ET_Motion:
1537                         if( !(g_pGesture->fingers[idx].flags & PressFlagTapNHold ) )
1538                                 break;
1539
1540                         if( num_pressed < 2 )
1541                                 return;
1542
1543                         if( num_pressed != g_pGesture->num_pressed )
1544                         {
1545                                 if( state != GestureEnd )
1546                                 {
1547 #ifdef __DETAIL_DEBUG__
1548                                 ErrorF("[GroupTapNHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1549 #endif//__DETAIL_DEBUG__
1550                                         goto cleanup_tapnhold;
1551                                 }
1552 #ifdef __DETAIL_DEBUG__
1553                                 ErrorF("[GroupTapNHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1554 #endif//__DETAIL_DEBUG__
1555                                 //goto cleanup_tapnhold;
1556                         }
1557
1558                         mbits |= (1 << idx);
1559                         if( mbits == (pow(2, num_pressed)-1) )
1560                         {
1561                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1562                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1563                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1564 #ifdef __DETAIL_DEBUG__
1565                                 ErrorF("[GroupTapNHold][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));
1566                                 ErrorF("[GroupTapNHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1567                                 ErrorF("[GroupTapNHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1568 #endif//__DETAIL_DEBUG__
1569
1570                                 if( ABS(base_area_size-area_size) >= TAPNHOLD_AREA_THRESHOLD )
1571                                 {
1572 #ifdef __DETAIL_DEBUG__
1573                                         ErrorF("[GroupTapNHold][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));
1574 #endif//__DETAIL_DEBUG__
1575                                         goto cleanup_tapnhold;
1576                                 }
1577
1578                                 if( !INBOX(&base_box_ext, cx, cy) )
1579                                 {
1580 #ifdef __DETAIL_DEBUG__
1581                                         ErrorF("[GroupTapNHold][M] current center coordinates is not in base coordinates box !\n");
1582 #endif//__DETAIL_DEBUG__
1583                                         goto cleanup_tapnhold;
1584                                 }
1585                         }
1586                         break;
1587
1588                 case ET_ButtonRelease:
1589                         if( state != GestureEnd && num_pressed >= 2)
1590                         {
1591 #ifdef __DETAIL_DEBUG__
1592                                 ErrorF("[GroupTapNHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1593 #endif//__DETAIL_DEBUG__
1594                                 goto cleanup_tapnhold;
1595                         }
1596
1597                         if( g_pGesture->num_pressed )
1598                                 break;
1599
1600                         if( !tap_repeat )
1601                         {
1602                                 prev_num_pressed = num_pressed;
1603                         }
1604
1605                         tap_repeat++;
1606
1607 #ifdef __DETAIL_DEBUG__
1608                         ErrorF("[GroupTapNHold][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
1609 #endif//__DETAIL_DEBUG__
1610
1611                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTapNHold, num_pressed) )
1612                         {
1613 #ifdef __DETAIL_DEBUG__
1614                                 ErrorF("[GroupTapNHold][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1615                                         num_pressed, prev_num_pressed, num_pressed);
1616 #endif//__DETAIL_DEBUG__
1617                                 goto cleanup_tapnhold;
1618                         }
1619
1620                         if( tap_repeat > 1 )
1621                         {
1622 #ifdef __DETAIL_DEBUG__
1623                                 ErrorF("[GroupTapNHold][R] Tap events(tap_repeat=%d) were put twice or more !(ignored)\n", tap_repeat);
1624 #endif//__DETAIL_DEBUG__
1625                                 goto cleanup_tapnhold;
1626                         }
1627
1628                         prev_num_pressed = num_pressed;
1629                         num_pressed = 0;
1630                         state = GestureDone;
1631
1632                         TimerCancel(tapnhold_event_timer);
1633                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_INTV_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1634
1635 #ifdef __DETAIL_DEBUG__
1636                         ErrorF("[GroupTapNHold][R][Last] state=%d, tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", state,  tap_repeat, num_pressed, prev_num_pressed);
1637 #endif//__DETAIL_DEBUG__
1638                         break;
1639         }
1640
1641         return;
1642
1643 cleanup_tapnhold:
1644
1645         if( state == GestureUpdate )
1646         {
1647                 state = GestureEnd;
1648                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1649                 {
1650                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1651                 }
1652         }
1653         else
1654         {
1655                 g_pGesture->recognized_gesture &= ~TapNHoldFilterMask;
1656         }
1657
1658         g_pGesture->filter_mask |= TapNHoldFilterMask;
1659         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1660         {
1661 #ifdef __DETAIL_DEBUG__
1662                 ErrorF("[GroupTapNHold][cleanup] GestureFlushOrDrop() !\n");
1663 #endif//__DETAIL_DEBUG__
1664
1665                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1666                 {
1667                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1668                 }
1669         }
1670
1671         TimerCancel(tapnhold_event_timer);
1672         num_pressed = 0;
1673         tap_repeat = 0;
1674         prev_num_pressed = 0;
1675         mbits = 0;
1676         base_time = 0;
1677         state = 0;
1678
1679         return;
1680 }
1681
1682 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1683 {
1684         static int num_pressed = 0;
1685         static int base_area_size = 0;
1686         static Time base_time = 0;
1687         static int base_cx;
1688         static int base_cy;
1689         int cx, cy;
1690         static pixman_box16_t base_box_ext;
1691         int area_size;
1692         static int state = GestureEnd;
1693
1694         static OsTimerPtr hold_event_timer = NULL;
1695         static int event_type = GestureNotifyHold;
1696
1697         if( timer_expired )
1698         {
1699                 if( state <= GestureBegin )
1700                         state++;
1701
1702 #ifdef __DETAIL_DEBUG__
1703                 switch( state )
1704                 {
1705                         case GestureBegin:
1706                                 ErrorF("[GroupHold] HOLD Begin !\n");
1707                                 break;
1708
1709                         case GestureUpdate:
1710                                 ErrorF("[GroupHold] HOLD Update !\n");
1711                                 break;
1712                 }
1713 #endif//__DETAIL_DEBUG__
1714
1715                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1716                 {
1717                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1718                         hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1719                 }
1720                 return;
1721         }
1722
1723         switch( type )
1724         {
1725                 case ET_ButtonPress:
1726                         g_pGesture->fingers[idx].flags |= PressFlagHold;
1727
1728                         if( g_pGesture->num_pressed < 2 )
1729                                 return;
1730
1731                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1732                         {
1733                                 if( state != GestureEnd )
1734                                 {
1735 #ifdef __DETAIL_DEBUG__
1736                                         ErrorF("[GroupHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1737 #endif//__DETAIL_DEBUG__
1738                                         goto cleanup_hold;
1739                                 }
1740
1741                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1742                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1743                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1744                                 base_time = GetTimeInMillis();
1745                                 base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
1746                                 base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
1747                                 base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
1748                                 base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
1749                                 event_type = GestureNotifyHold;
1750                                 hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1751                         }
1752                         num_pressed = g_pGesture->num_pressed;
1753
1754 #ifdef __DETAIL_DEBUG__
1755                         ErrorF("[GroupHold][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
1756 #endif//__DETAIL_DEBUG__
1757                         break;
1758
1759                 case ET_Motion:
1760                         if( !(g_pGesture->fingers[idx].flags & PressFlagHold ) )
1761                                 break;
1762
1763                         if( num_pressed < 2 )
1764                                 return;
1765
1766                         if( num_pressed != g_pGesture->num_pressed )
1767                         {
1768                                 if( state != GestureEnd )
1769                                 {
1770 #ifdef __DETAIL_DEBUG__
1771                                 ErrorF("[GroupHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1772 #endif//__DETAIL_DEBUG__
1773                                         goto cleanup_hold;
1774                                 }
1775 #ifdef __DETAIL_DEBUG__
1776                                 ErrorF("[GroupHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1777 #endif//__DETAIL_DEBUG__
1778                                 //goto cleanup_hold;
1779                         }
1780
1781                         area_size = AREA_SIZE(&g_pGesture->area.extents);
1782                         cx = AREA_CENTER_X(&g_pGesture->area.extents);
1783                         cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1784 #ifdef __DETAIL_DEBUG__
1785                         ErrorF("[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));
1786                         ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1787                         ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1788 #endif//__DETAIL_DEBUG__
1789
1790                         if( ABS(base_area_size-area_size) >= HOLD_AREA_THRESHOLD )
1791                         {
1792 #ifdef __DETAIL_DEBUG__
1793                                 ErrorF("[GroupHold][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));
1794 #endif//__DETAIL_DEBUG__
1795                                 goto cleanup_hold;
1796                         }
1797
1798                         if( !INBOX(&base_box_ext, cx, cy) )
1799                         {
1800 #ifdef __DETAIL_DEBUG__
1801                                 ErrorF("[GroupHold][M] current center coordinates is not in base coordinates box !\n");
1802 #endif//__DETAIL_DEBUG__
1803                                 goto cleanup_hold;
1804                         }
1805                         break;
1806
1807                 case ET_ButtonRelease:
1808                         if( state != GestureEnd && num_pressed >= 2)
1809                         {
1810 #ifdef __DETAIL_DEBUG__
1811                                 ErrorF("[GroupHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1812 #endif//__DETAIL_DEBUG__
1813                                 goto cleanup_hold;
1814                         }
1815
1816                         //ErrorF("[GroupHold][R] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1817                         if( g_pGesture->num_pressed )
1818                                 break;
1819
1820                         goto cleanup_hold;
1821                         break;
1822         }
1823
1824         return;
1825
1826 cleanup_hold:
1827
1828         if( state == GestureBegin || state == GestureUpdate )
1829         {
1830                 state = GestureEnd;
1831                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1832                 {
1833                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1834                 }
1835         }
1836         else
1837         {
1838                 g_pGesture->recognized_gesture &= ~HoldFilterMask;
1839         }
1840
1841         g_pGesture->filter_mask |= HoldFilterMask;
1842         num_pressed = 0;
1843         base_area_size = 0;
1844         base_time = 0;
1845         base_cx = base_cy = 0;
1846         state = GestureEnd;
1847         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1848         TimerCancel(hold_event_timer);
1849         return;
1850 }
1851
1852 static inline void
1853 GestureEnableDisable()
1854 {
1855         if((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None))
1856         {
1857                 GestureEnable(1, FALSE, g_pGesture->this_device);
1858         }
1859         else
1860         {
1861                 GestureEnable(0, FALSE, g_pGesture->this_device);
1862         }
1863 }
1864
1865 void
1866 GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent)
1867 {
1868         g_pGesture->grabMask = *pGrabMask;
1869         g_pGesture->GrabEvents = pGrabEvent;
1870         GestureEnableDisable();
1871 }
1872
1873 void
1874 GestureCbEventsSelected(Window win, Mask *pEventMask)
1875 {
1876         g_pGesture->lastSelectedWin = win;
1877         g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0;
1878         GestureEnableDisable();
1879 }
1880
1881 WindowPtr
1882 GestureGetEventsWindow(void)
1883 {
1884         Mask mask;
1885         WindowPtr pWin;
1886
1887         pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
1888
1889         if( pWin )
1890         {
1891 #ifdef __DETAIL_DEBUG__
1892                 ErrorF("[X11][GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
1893 #endif//__DETAIL_DEBUG__
1894                 g_pGesture->gestureWin = pWin->drawable.id;
1895         }
1896         else
1897         {
1898 #ifdef __DETAIL_DEBUG__
1899                 ErrorF("[X11][GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
1900 #endif//__DETAIL_DEBUG__
1901                 return NULL;
1902         }
1903
1904         if(g_pGesture->gestureWin == g_pGesture->lastSelectedWin)
1905         {
1906                 g_pGesture->eventMask = g_pGesture->lastSelectedMask;
1907                 goto nonempty_eventmask;
1908         }
1909
1910         //check selected event(s)
1911         if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) )
1912         {
1913                 g_pGesture->eventMask = 0;
1914         }
1915         else
1916         {
1917                 g_pGesture->lastSelectedWin = g_pGesture->gestureWin;
1918                 g_pGesture->lastSelectedMask = g_pGesture->eventMask;
1919         }
1920
1921         if( !g_pGesture->eventMask && !g_pGesture->grabMask)
1922         {
1923 #ifdef __DETAIL_DEBUG__
1924                 ErrorF("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id);
1925 #endif//__DETAIL_DEBUG__
1926                 return NULL;
1927         }
1928
1929 nonempty_eventmask:
1930
1931 #ifdef __DETAIL_DEBUG__
1932         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask);
1933 #endif//__DETAIL_DEBUG__
1934
1935         mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
1936
1937 #ifdef __DETAIL_DEBUG__
1938         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
1939 #endif//__DETAIL_DEBUG__
1940
1941         g_pGesture->filter_mask = mask;
1942
1943 #ifdef __DETAIL_DEBUG__
1944         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
1945 #endif//__DETAIL_DEBUG__
1946
1947         return pWin;
1948 }
1949
1950 static CARD32
1951 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
1952 {
1953         int event_type = *(int *)arg;
1954
1955         switch( event_type )
1956         {
1957                 case GestureNotifyHold:
1958 #ifdef __DETAIL_DEBUG__
1959                         ErrorF("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
1960 #endif//__DETAIL_DEBUG__
1961                         GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
1962                         break;
1963
1964                 case GestureNotifyPan:
1965 #ifdef __DETAIL_DEBUG__
1966                         ErrorF("[GestureEventTimerHandler] GestureNotifyPan (event_type = %d)\n", event_type);
1967 #endif//__DETAIL_DEBUG__
1968                         GestureRecognize_GroupPan(event_type, NULL, NULL, 0, 1);
1969                         break;
1970
1971                 case GestureNotifyTap:
1972 #ifdef __DETAIL_DEBUG__
1973                         ErrorF("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
1974 #endif//__DETAIL_DEBUG__
1975                         GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
1976                         break;
1977
1978                 case GestureNotifyTapNHold:
1979 #ifdef __DETAIL_DEBUG__
1980                         ErrorF("[GestureEventTimerHandler] GestureNotifyTapNHold (event_type = %d)\n", event_type);
1981 #endif//__DETAIL_DEBUG__
1982                         GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1);
1983                         break;
1984
1985                 case GestureNotifyPinchRotation:
1986 #ifdef __DETAIL_DEBUG__
1987                         ErrorF("[GestureEventTimerHandler] GestureNotifyPinchRotation (event_type = %d)\n", event_type);
1988 #endif//__DETAIL_DEBUG__
1989                         GestureRecognize_GroupPinchRotation(event_type, NULL, NULL, 0, 1);
1990                         break;
1991
1992                 default:
1993 #ifdef __DETAIL_DEBUG__
1994                         ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
1995 #endif//__DETAIL_DEBUG__
1996                         if(timer)
1997                                 ErrorF("[GestureEventTimerHandler] timer=%p\n", timer);
1998         }
1999
2000         return 0;
2001 }
2002
2003 static CARD32
2004 GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2005 {
2006         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2007         g_pGesture->recognized_gesture = 0;
2008
2009         if( ERROR_INVALPTR == GestureFlushOrDrop() )
2010         {
2011                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2012         }
2013
2014 #ifdef __DETAIL_DEBUG__
2015         ErrorF("[X11][Single] expired !\n");
2016 #endif//__DETAIL_DEBUG__
2017
2018         return 0;
2019 }
2020
2021 void
2022 GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
2023 {
2024         int i;
2025         static OsTimerPtr single_finger_timer = NULL;
2026         int idx = -1;
2027
2028         if( PROPAGATE_EVENTS == g_pGesture->ehtype ||
2029                 device->id < g_pGesture->first_fingerid )
2030                 return;
2031
2032         for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
2033         {
2034                 if( device->id == g_pGesture->mt_devices[i]->id )
2035                 {
2036                         idx = i;
2037                         break;
2038                 }
2039         }
2040
2041         if( idx < 0 )
2042                 return;
2043
2044         switch( type )
2045         {
2046                 case ET_ButtonPress:
2047                         if( idx == 0 )
2048                                 g_pGesture->event_sum[0] = BTN_PRESSED;
2049                         g_pGesture->fingers[idx].ptime = ev->any.time;
2050                         g_pGesture->fingers[idx].px = ev->device_event.root_x;
2051                         g_pGesture->fingers[idx].py = ev->device_event.root_y;
2052
2053                         g_pGesture->num_pressed++;
2054                         if( g_pGesture->num_pressed == 1 )
2055                         {
2056                                 single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
2057                         }
2058                         else
2059                         {
2060                                 TimerCancel(single_finger_timer);
2061                         }
2062
2063                         if( g_pGesture->num_pressed > g_pGesture->num_mt_devices )
2064                                 g_pGesture->num_pressed = g_pGesture->num_mt_devices;
2065
2066                         if( !g_pGesture->pTempWin || g_pGesture->num_pressed != g_pGesture->inc_num_pressed )
2067                         {
2068                                 g_pGesture->pTempWin = GestureGetEventsWindow();
2069
2070                                 if( NULL == g_pGesture->pTempWin )
2071                                 {
2072 #ifdef __DETAIL_DEBUG__
2073                                         ErrorF("[X11][GestureRecognize][g_pGesture->num_pressed=%d] No events were selected !\n", g_pGesture->num_pressed);
2074 #endif//__DETAIL_DEBUG__
2075                                         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2076                                         goto flush_or_drop;
2077                                 }
2078                         }
2079
2080                         g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
2081
2082                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2083                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2084                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2085                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2086
2087                         if( g_pGesture->inc_num_pressed == 1 )
2088                         {
2089                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2090 #ifdef __DETAIL_DEBUG__
2091                                 ErrorF("[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
2092 #endif//__DETAIL_DEBUG__
2093                         }
2094                         else
2095                         {
2096                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2097                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
2098                                 {
2099                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2100                                 }
2101 #ifdef __DETAIL_DEBUG__
2102                                 ErrorF("[P][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area.extents)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
2103 #endif//__DETAIL_DEBUG__
2104                         }
2105                         break;
2106
2107                 case ET_Motion:
2108                         if( !g_pGesture->fingers[idx].ptime )
2109                                 return;
2110
2111                         g_pGesture->fingers[idx].mx = ev->device_event.root_x;
2112                         g_pGesture->fingers[idx].my = ev->device_event.root_y;
2113
2114                         if( idx == 0 && g_pGesture->event_sum[0] )
2115                         {
2116                                 g_pGesture->event_sum[0] += BTN_MOVING;
2117 #ifdef __DETAIL_DEBUG__
2118                                 ErrorF("[X11][GestureRecognize] moving !\n");
2119 #endif//__DETAIL_DEBUG__
2120                                 if( g_pGesture->event_sum[0] >= 7 )
2121                                 {
2122                                if( (g_pGesture->event_sum[0] >= 7) && (g_pGesture->inc_num_pressed < 2) )
2123                                 {
2124  #ifdef __DETAIL_DEBUG__
2125                                        ErrorF("[X11][GestureRecognize] moving limit!\n");
2126  #endif//__DETAIL_DEBUG__
2127                                        g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2128                                             goto flush_or_drop;
2129                                 }
2130                                 }
2131                         }
2132
2133                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2134                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2135                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2136                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2137
2138                         if( g_pGesture->inc_num_pressed == 1 )
2139                         {
2140                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2141 #ifdef __DETAIL_DEBUG__
2142                                 ErrorF("[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
2143 #endif//__DETAIL_DEBUG__
2144                         }
2145                         else
2146                         {
2147                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2148                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
2149                                 {
2150                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2151                                 }
2152 #ifdef __DETAIL_DEBUG__
2153                                 ErrorF("[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
2154 #endif//__DETAIL_DEBUG__
2155                         }
2156                         break;
2157
2158                 case ET_ButtonRelease:
2159                         g_pGesture->fingers[idx].rtime = ev->any.time;
2160                         g_pGesture->fingers[idx].rx = ev->device_event.root_x;
2161                         g_pGesture->fingers[idx].ry = ev->device_event.root_y;
2162
2163                         g_pGesture->num_pressed--;
2164                         if( g_pGesture->num_pressed <= 0 )
2165                         {
2166 #ifdef __DETAIL_DEBUG__
2167         ErrorF("[X11][GestureRecognize] All fingers were released !\n");
2168 #endif//__DETAIL_DEBUG__
2169                                 if( g_pGesture->inc_num_pressed == 1 )
2170                                         goto flush_or_drop;
2171                         }
2172                         break;
2173         }
2174
2175         if( g_pGesture->filter_mask != GESTURE_FILTER_MASK_ALL )
2176         {
2177                 if( !(g_pGesture->filter_mask & FlickFilterMask) )
2178                 {
2179                         GestureRecognize_GroupFlick(type, ev, device, idx);
2180                 }
2181                 if( !(g_pGesture->filter_mask & PanFilterMask) )
2182                 {
2183                         GestureRecognize_GroupPan(type, ev, device, idx, 0);
2184                 }
2185                 if( !(g_pGesture->filter_mask & PinchRotationFilterMask) )
2186                 {
2187                         GestureRecognize_GroupPinchRotation(type, ev, device, idx, 0);
2188                 }
2189                 if( !(g_pGesture->filter_mask & TapFilterMask) )
2190                 {
2191                         GestureRecognize_GroupTap(type, ev, device, idx, 0);
2192                 }
2193                 if( !(g_pGesture->filter_mask & TapNHoldFilterMask) )
2194                 {
2195                         GestureRecognize_GroupTapNHold(type, ev, device, idx, 0);
2196                 }
2197                 if( !(g_pGesture->filter_mask & HoldFilterMask) )
2198                 {
2199                         GestureRecognize_GroupHold(type, ev, device, idx, 0);
2200                 }
2201         }
2202
2203 #ifdef __DETAIL_DEBUG__
2204         ErrorF("[X11][GestureRecognize][N] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
2205         ErrorF("[X11][GestureRecognize][N] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
2206         ErrorF("[X11][GestureRecognize][N] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
2207 #endif//__DETAIL_DEBUG__
2208
2209         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
2210         {
2211                 if( !g_pGesture->recognized_gesture )
2212                         goto flush_or_drop;
2213                 else if( !g_pGesture->num_pressed )
2214                         goto flush_or_drop;
2215         }
2216
2217         if( g_pGesture->recognized_gesture )
2218         {
2219                 if( g_pGesture->ehtype == KEEP_EVENTS )
2220                         GestureEventsDrop();
2221                 g_pGesture->ehtype = IGNORE_EVENTS;
2222         }
2223
2224         return;
2225
2226 flush_or_drop:
2227
2228 #ifdef __DETAIL_DEBUG__
2229         ErrorF("[GestureRecognize] GestureFlushOrDrop() !\n");
2230 #endif//__DETAIL_DEBUG__
2231         if( ERROR_INVALPTR == GestureFlushOrDrop() )
2232         {
2233                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2234         }
2235 }
2236
2237
2238 ErrorStatus GestureFlushOrDrop(void)
2239 {
2240         ErrorStatus err;
2241
2242         if( g_pGesture->recognized_gesture )
2243         {
2244                 GestureEventsDrop();
2245         }
2246         else
2247         {
2248                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2249
2250                 err = GestureEventsFlush();
2251                 if( ERROR_NONE != err )
2252                         return err;
2253
2254 #ifdef __DETAIL_DEBUG__
2255                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
2256                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
2257                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
2258 #endif//__DETAIL_DEBUG__
2259         }
2260
2261         err = GestureRegionsReinit();
2262         if( ERROR_NONE != err )
2263                 return err;
2264
2265         g_pGesture->pTempWin = NULL;
2266         g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
2267         g_pGesture->event_sum[0] = 0;
2268
2269         return ERROR_NONE;
2270 }
2271
2272 void
2273 GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2274 {
2275         int i;
2276
2277 #ifdef __DEBUG_EVENT_HANDLER__
2278         ErrorF("\n[X11][GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
2279                         ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
2280 #endif//__DEBUG_EVENT_HANDLER__
2281
2282         if( MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync )
2283         {
2284                 g_pGesture->ehtype = KEEP_EVENTS;
2285                 g_pGesture->filter_mask = 0;
2286                 g_pGesture->recognized_gesture = 0;
2287                 g_pGesture->num_pressed = 0;
2288
2289                 for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
2290                         g_pGesture->fingers[i].ptime = 0;
2291         }
2292         else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
2293         {
2294                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2295         }
2296 }
2297
2298 void
2299 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2300 {
2301 #ifdef __DEBUG_EVENT_HANDLER__
2302         ErrorF("[X11][GestureHandleButtonPEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2303 #endif//__DEBUG_EVENT_HANDLER__
2304
2305         switch( g_pGesture->ehtype )
2306         {
2307                 case KEEP_EVENTS:
2308                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2309                         {
2310                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2311                                 return;
2312                         }
2313
2314                         if( g_pGesture->num_mt_devices )
2315                                 GestureRecognize(ET_ButtonPress, ev, device);
2316                         else
2317                                 device->public.processInputProc(ev, device);
2318                         break;
2319
2320                 case PROPAGATE_EVENTS:
2321                         device->public.processInputProc(ev, device);
2322                         break;
2323
2324                 case IGNORE_EVENTS:
2325                         GestureRecognize(ET_ButtonPress, ev, device);
2326                         break;
2327
2328                 default:
2329                         break;
2330         }
2331 }
2332
2333 void
2334 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2335 {
2336 #ifdef __DEBUG_EVENT_HANDLER__
2337         ErrorF("[X11][GestureHandleMotionEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2338 #endif//__DEBUG_EVENT_HANDLER__
2339
2340         switch( g_pGesture->ehtype )
2341         {
2342                 case KEEP_EVENTS:
2343                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2344                         {
2345                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2346                                 return;
2347                         }
2348
2349                         if( g_pGesture->num_mt_devices )
2350                                 GestureRecognize(ET_Motion, ev, device);
2351                         else
2352                                 device->public.processInputProc(ev, device);
2353                         break;
2354
2355                 case PROPAGATE_EVENTS:
2356                         device->public.processInputProc(ev, device);
2357                         break;
2358
2359                 case IGNORE_EVENTS:
2360                         GestureRecognize(ET_Motion, ev, device);
2361                         break;
2362
2363                 default:
2364                         break;
2365         }
2366
2367 }
2368
2369 void
2370 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2371 {
2372 #ifdef __DEBUG_EVENT_HANDLER__
2373         ErrorF("[X11][GestureHandleButtonREvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2374 #endif//__DEBUG_EVENT_HANDLER__
2375
2376         switch( g_pGesture->ehtype )
2377         {
2378                 case KEEP_EVENTS:
2379                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2380                         {
2381                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2382                                 return;
2383                         }
2384
2385                         if( g_pGesture->num_mt_devices )
2386                                 GestureRecognize(ET_ButtonRelease, ev, device);
2387                         else
2388                                 device->public.processInputProc(ev, device);
2389                         break;
2390
2391                 case PROPAGATE_EVENTS:
2392                         device->public.processInputProc(ev, device);
2393                         break;
2394
2395                 case IGNORE_EVENTS:
2396                         GestureRecognize(ET_ButtonRelease, ev, device);
2397                         break;
2398
2399                 default:
2400                         break;
2401         }
2402 }
2403
2404 static ErrorStatus
2405 GestureEnableEventHandler(InputInfoPtr pInfo)
2406  {
2407         Bool res;
2408         GestureDevicePtr pGesture = pInfo->private;
2409
2410         res = GestureInstallResourceStateHooks();
2411
2412         if( !res )
2413         {
2414                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
2415                 return ERROR_ABNORMAL;
2416         }
2417
2418         res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
2419
2420         if( !res )
2421         {
2422                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
2423                 goto failed;
2424         }
2425
2426         res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected);
2427
2428         if( !res )
2429         {
2430                 ErrorF("[X11][GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n");
2431                 goto failed;
2432         }
2433
2434         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
2435
2436         if( !pGesture->device_setting_timer )
2437         {
2438                 ErrorF("[X11][GestureEnableEventHandler] Failed to allocate memory for timer !\n");
2439                 goto failed;
2440         }
2441
2442         return ERROR_NONE;
2443
2444 failed:
2445         GestureUninstallResourceStateHooks();
2446         GestureUnsetMaxNumberOfFingers();
2447
2448         return ERROR_ABNORMAL;
2449 }
2450
2451 static ErrorStatus
2452 GestureDisableEventHandler(void)
2453 {
2454         ErrorStatus err = ERROR_NONE;
2455
2456         mieqSetHandler(ET_ButtonPress, NULL);
2457         mieqSetHandler(ET_ButtonRelease, NULL);
2458         mieqSetHandler(ET_Motion, NULL);
2459         mieqSetHandler(ET_MTSync, NULL);
2460
2461         err = GestureFiniEQ();
2462
2463         if( ERROR_INVALPTR == err )
2464         {
2465                 ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
2466         }
2467
2468         GestureRegisterCallbacks(NULL, NULL);
2469         GestureUninstallResourceStateHooks();
2470
2471         return err;
2472 }
2473
2474 static CARD32
2475 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2476 {
2477         InputInfoPtr pInfo = (InputInfoPtr)arg;
2478         GestureDevicePtr pGesture = pInfo->private;
2479
2480         int idx = 0;
2481         DeviceIntPtr dev;
2482         for( dev = inputInfo.pointer ; dev; dev = dev->next )
2483         {
2484                 if(IsMaster(dev) && IsPointerDevice(dev))
2485                 {
2486                         pGesture->master_pointer = dev;
2487                         ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
2488                         continue;
2489                 }
2490
2491                 if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
2492                 {
2493                         pGesture->xtest_pointer = dev;
2494                         ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
2495                         continue;
2496                 }
2497
2498                 if(IsPointerDevice(dev))
2499                 {
2500                         if( idx >= MAX_MT_DEVICES )
2501                         {
2502                                 ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
2503                                         MAX_MT_DEVICES);
2504                                 continue;
2505                         }
2506                         pGesture->mt_devices[idx] = dev;
2507                         ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
2508                         idx++;
2509                 }
2510         }
2511
2512         if( !pGesture->master_pointer || !pGesture->xtest_pointer )
2513         {
2514                 ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
2515                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2516                 pGesture->num_mt_devices = 0;
2517
2518                 return 0;
2519         }
2520
2521         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2522         pGesture->num_mt_devices = idx;
2523
2524         if( !pGesture->num_mt_devices )
2525         {
2526                 ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
2527                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2528                 pGesture->num_mt_devices = 0;
2529         pGesture->first_fingerid = -1;
2530                 return 0;
2531         }
2532
2533         pGesture->first_fingerid = pGesture->mt_devices[0]->id;
2534         memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
2535         pGesture->pRootWin = RootWindow(pGesture->master_pointer);
2536         g_pGesture->pTempWin = NULL;
2537         g_pGesture->inc_num_pressed = 0;
2538
2539         if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
2540         {
2541                 goto failed;
2542         }
2543
2544         mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
2545         mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
2546         mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
2547
2548         if( pGesture->is_active )
2549                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2550
2551         return 0;
2552
2553 failed:
2554
2555         GestureUninstallResourceStateHooks();
2556         GestureUnsetMaxNumberOfFingers();
2557
2558         return 0;
2559 }
2560
2561 BOOL
2562 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
2563 {
2564         if (IsMaster(dev))
2565                 return FALSE;
2566
2567         if (master)
2568                 return (dev->xtest_master_id == master->id);
2569
2570         return (dev->xtest_master_id != 0);
2571 }
2572
2573 void
2574 GestureEnable(int enable, Bool prop, DeviceIntPtr dev)
2575 {
2576         if((!enable) && (g_pGesture->is_active))
2577         {
2578                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2579                 mieqSetHandler(ET_MTSync, NULL);
2580                 g_pGesture->is_active = 0;
2581                 ErrorF("[X11][GestureEnable] Disabled !\n");
2582         }
2583         else if((enable) && (!g_pGesture->is_active))
2584         {
2585                 g_pGesture->ehtype = KEEP_EVENTS;
2586                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2587                 g_pGesture->is_active = 1;
2588                 ErrorF("[X11][GestureEnable] Enabled !\n");
2589         }
2590
2591         if(!prop)
2592                  XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2593 }
2594
2595 ErrorStatus
2596 GestureRegionsInit(void)
2597 {
2598         int i;
2599
2600         if( !g_pGesture )
2601                 return ERROR_INVALPTR;
2602
2603         pixman_region_init(&g_pGesture->area);
2604
2605         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2606         {
2607                 pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
2608         }
2609
2610         return ERROR_NONE;
2611 }
2612
2613 ErrorStatus
2614 GestureRegionsReinit(void)
2615 {
2616         if( !g_pGesture )
2617         {
2618                 ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
2619                 return ERROR_INVALPTR;
2620         }
2621
2622         pixman_region_init(&g_pGesture->area);
2623
2624         return ERROR_NONE;
2625 }
2626
2627 ErrorStatus
2628 GestureInitEQ(void)
2629 {
2630         int i;
2631         IEventPtr tmpEQ;
2632
2633         tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
2634
2635         if( !tmpEQ )
2636         {
2637                 ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
2638                 return ERROR_ALLOCFAIL;
2639         }
2640
2641         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2642         {
2643                 tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
2644                 if( !tmpEQ[i].event )
2645                 {
2646                         ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
2647                         i--;
2648                         while(i >= 0 && tmpEQ[i].event)
2649                         {
2650                                 free(tmpEQ[i].event);
2651                                 tmpEQ[i].event = NULL;
2652                         }
2653                         free (tmpEQ);
2654                         tmpEQ = NULL;
2655                         return ERROR_ALLOCFAIL;
2656                 }
2657         }
2658
2659         g_pGesture->EQ = tmpEQ;
2660         g_pGesture->headEQ = g_pGesture->tailEQ = 0;
2661
2662         return ERROR_NONE;
2663 }
2664
2665 ErrorStatus
2666 GestureFiniEQ(void)
2667 {
2668         int i;
2669
2670         if( !g_pGesture || !g_pGesture->EQ )
2671                 return ERROR_INVALPTR;
2672
2673         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2674         {
2675                 if( g_pGesture->EQ[i].event )
2676                 {
2677                         free(g_pGesture->EQ[i].event);
2678                         g_pGesture->EQ[i].event = NULL;
2679                 }
2680         }
2681
2682         free(g_pGesture->EQ);
2683         g_pGesture->EQ = NULL;
2684
2685         return ERROR_NONE;
2686 }
2687
2688 ErrorStatus
2689 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2690 {
2691         int tail;
2692
2693         if( !g_pGesture || !g_pGesture->EQ )
2694         {
2695                 ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
2696                 return ERROR_INVALPTR;
2697         }
2698
2699         tail = g_pGesture->tailEQ;
2700
2701         if( tail >= GESTURE_EQ_SIZE )
2702         {
2703                 ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
2704                 printk("[X11][GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
2705                 GestureEventsFlush();
2706                 return ERROR_EQFULL;
2707         }
2708
2709 #ifdef __DETAIL_DEBUG__
2710         switch( ev->any.type )
2711         {
2712                 case ET_ButtonPress:
2713                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
2714                         break;
2715
2716                 case ET_ButtonRelease:
2717                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
2718                         break;
2719
2720                 case ET_Motion:
2721                         ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
2722                         break;
2723         }
2724 #endif//__DETAIL_DEBUG__
2725
2726         g_pGesture->EQ[tail].device = device;
2727         g_pGesture->EQ[tail].screen_num = screen_num;
2728         memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
2729         g_pGesture->tailEQ++;
2730
2731         return ERROR_NONE;
2732 }
2733
2734 ErrorStatus
2735 GestureEventsFlush(void)
2736 {
2737         int i;
2738         DeviceIntPtr device;
2739
2740         if( !g_pGesture->EQ )
2741         {
2742                 ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
2743                 return ERROR_INVALPTR;
2744         }
2745
2746 #ifdef __DETAIL_DEBUG__
2747         ErrorF("[X11][GestureEventsFlush]\n");
2748 #endif//__DETAIL_DEBUG__
2749
2750         for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
2751         {
2752                 device = g_pGesture->EQ[i].device;
2753                 device->public.processInputProc(g_pGesture->EQ[i].event, device);
2754         }
2755
2756         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2757                 g_pGesture->event_sum[i] = 0;
2758
2759         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2760
2761         return ERROR_NONE;
2762 }
2763
2764 void
2765 GestureEventsDrop(void)
2766 {
2767         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2768 }
2769
2770 #ifdef HAVE_PROPERTIES
2771 static void
2772 GestureInitProperty(DeviceIntPtr dev)
2773 {
2774         int rc;
2775
2776         prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
2777         rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2778
2779         if (rc != Success)
2780                 return;
2781
2782         XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
2783 }
2784
2785 static int
2786 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
2787                  BOOL checkonly)
2788 {
2789         InputInfoPtr pInfo  = dev->public.devicePrivate;
2790
2791         if( prop_gesture_recognizer_onoff == atom )
2792         {
2793                 int data;
2794                 if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
2795                         return BadMatch;
2796
2797                 if( !checkonly )
2798                 {
2799                         data = *((int *)val->data);
2800                         GestureEnable(data, TRUE, dev);
2801                 }
2802         }
2803
2804         return Success;
2805 }
2806 #endif//HAVE_PROPERTIES
2807
2808 static int
2809 GestureInit(DeviceIntPtr device)
2810 {
2811         InputInfoPtr pInfo;
2812         pInfo = device->public.devicePrivate;
2813
2814 #ifdef HAVE_PROPERTIES
2815         GestureInitProperty(device);
2816         XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
2817 #endif
2818
2819         return Success;
2820 }
2821
2822 static void
2823 GestureFini(DeviceIntPtr device)
2824 {
2825         XIRegisterPropertyHandler(device, NULL, NULL, NULL);
2826 }
2827
2828 static pointer
2829 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
2830 {
2831         xf86AddInputDriver(&GESTURE, module, 0);
2832         return module;
2833 }
2834
2835 static void
2836 GestureUnplug(pointer p)
2837 {
2838 }
2839
2840 static InputInfoPtr
2841 GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2842 {
2843     int rc = BadAlloc;
2844     GestureDevicePtr    pGesture;
2845
2846     pGesture = calloc(1, sizeof(GestureDeviceRec));
2847
2848     if (!pGesture) {
2849         pInfo->private = NULL;
2850         //xf86DeleteInput(pInfo, 0);
2851         goto error;
2852     }
2853
2854     g_pGesture = pGesture;
2855     pInfo->private = pGesture;
2856     pInfo->flags = 0;
2857     pInfo->read_input = GestureReadInput; /* new data avl */
2858     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
2859     pInfo->device_control = GestureControl; /* enable/disable dev */
2860     /* process driver specific options */
2861     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
2862     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
2863     pGesture->gestureWin = None;
2864     pGesture->lastSelectedWin = None;
2865     g_pGesture->grabMask = g_pGesture->eventMask = 0;
2866
2867     xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
2868
2869     /* process generic options */
2870     xf86CollectInputOptions(pInfo, NULL);
2871     xf86ProcessCommonOptions(pInfo, pInfo->options);
2872
2873     pInfo->fd = -1;
2874
2875     return Success;
2876
2877 error:
2878     if (pInfo->fd >= 0)
2879         close(pInfo->fd);
2880     return rc;
2881 }
2882
2883 static void
2884 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2885 {
2886         GestureDevicePtr pGesture = pInfo->private;
2887
2888         g_pGesture = pGesture = NULL;
2889         pInfo->private = NULL;
2890
2891         xf86DeleteInput(pInfo, 0);
2892 }
2893
2894 static int
2895 GestureControl(DeviceIntPtr device, int what)
2896 {
2897     InputInfoPtr  pInfo = device->public.devicePrivate;
2898     GestureDevicePtr pGesture = pInfo->private;
2899
2900     switch(what)
2901     {
2902         case DEVICE_INIT:
2903              GestureInit(device);
2904             break;
2905
2906         /* Switch device on.  Establish socket, start event delivery.  */
2907         case DEVICE_ON:
2908             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
2909
2910             if (device->public.on)
2911                     break;
2912
2913             device->public.on = TRUE;
2914              pGesture->this_device = device;
2915              pGesture->num_mt_devices = 0;
2916              if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
2917                 goto device_off;
2918             break;
2919
2920        case DEVICE_OFF:
2921 device_off:
2922              GestureDisableEventHandler();
2923              GestureFini(device);
2924              pGesture->this_device = NULL;
2925              xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
2926
2927             if (!device->public.on)
2928                 break;
2929
2930             pInfo->fd = -1;
2931             device->public.on = FALSE;
2932             break;
2933
2934       case DEVICE_CLOSE:
2935             /* free what we have to free */
2936             break;
2937     }
2938     return Success;
2939 }
2940
2941 static void
2942 GestureReadInput(InputInfoPtr pInfo)
2943 {
2944 }
2945