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