Git init
authorKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 16:10:16 +0000 (01:10 +0900)
committerKibum Kim <kb0929.kim@samsung.com>
Fri, 6 Jan 2012 16:10:16 +0000 (01:10 +0900)
20 files changed:
COPYING [new file with mode: 0755]
ChangeLog [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
autogen.sh [new file with mode: 0755]
configure.ac [new file with mode: 0644]
debian/changelog [new file with mode: 0755]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/xserver-xorg-input-gesture.install [new file with mode: 0644]
debian/xsfbs/repack.sh [new file with mode: 0644]
debian/xsfbs/xsfbs.mk [new file with mode: 0644]
debian/xsfbs/xsfbs.sh [new file with mode: 0644]
man/Makefile.am [new file with mode: 0644]
man/gesture.man [new file with mode: 0644]
packaging/xorg-x11-drv-input-gesture.spec [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/gesture.c [new file with mode: 0755]
src/gesture.h [new file with mode: 0755]
xorg-gesture.pc.in [new file with mode: 0644]

diff --git a/COPYING b/COPYING
new file mode 100755 (executable)
index 0000000..8f6ba4b
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,21 @@
+Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is fur-
+nished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
+NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..50ddc5b
--- /dev/null
@@ -0,0 +1,40 @@
+#  Copyright 2007 Peter Hutterer
+#  Copyright 2009 Przemysław Firszt
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, and/or sell copies of the Software, and to permit persons to whom
+#  the Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice (including the next
+#  paragraph) shall be included in all copies or substantial portions of the
+#  Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+AUTOMAKE_OPTIONS = foreign
+
+# Ensure headers are installed below $(prefix) for distcheck
+DISTCHECK_CONFIGURE_FLAGS = --with-sdkdir='$${includedir}/xorg'
+
+SUBDIRS = src man
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = xorg-gesture.pc
+
+EXTRA_DIST = ChangeLog
+
+MAINTAINERCLEANFILES=ChangeLog
+
+.PHONY: ChangeLog
+
+ChangeLog:
+       $(CHANGELOG_CMD)
+
+dist-hook: ChangeLog
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..0aad669
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+ORIGDIR=`pwd`
+cd $srcdir
+
+autoreconf -v --install || exit 1
+cd $ORIGDIR || exit $?
+
+#$srcdir/configure --enable-maintainer-mode "$@"
+#$srcdir/configure --prefix=/usr --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..2aff572
--- /dev/null
@@ -0,0 +1,77 @@
+#  Copyright 2007 Peter Hutterer
+#  Copyright 2009 Przemysław Firszt
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, and/or sell copies of the Software, and to permit persons to whom
+#  the Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice (including the next
+#  paragraph) shall be included in all copies or substantial portions of the
+#  Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Process this file with autoconf to produce a configure script
+
+AC_PREREQ(2.57)
+AC_INIT([xf86-input-gesture],
+        0.0.1,
+        [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg],
+        xf86-input-gesture)
+
+AC_CONFIG_SRCDIR([Makefile.am])
+AC_CONFIG_AUX_DIR(.)
+AM_INIT_AUTOMAKE([dist-bzip2])
+
+AM_MAINTAINER_MODE
+
+# Require xorg-macros: XORG_DEFAULT_OPTIONS
+m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.3 or later before running autoconf/autogen])])
+XORG_MACROS_VERSION(1.3)
+AM_CONFIG_HEADER([config.h])
+
+# Checks for programs.
+AC_DISABLE_STATIC
+AC_PROG_LIBTOOL
+AC_PROG_CC
+XORG_DEFAULT_OPTIONS
+
+AH_TOP([#include "xorg-server.h"])
+
+AC_ARG_WITH(xorg-module-dir,
+            AC_HELP_STRING([--with-xorg-module-dir=DIR],
+                           [Default xorg module directory [[default=$libdir/xorg/modules]]]),
+            [moduledir="$withval"],
+            [moduledir="$libdir/xorg/modules"])
+inputdir=${moduledir}/input
+AC_SUBST(inputdir)
+
+# Checks for pkg-config packages. We need to be able to override sdkdir
+# to satisfy silly distcheck requirements.
+PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
+XORG_CFLAGS="$CWARNFLAGS $XORG_CFLAGS"
+AC_ARG_WITH([sdkdir], [],
+    [sdkdir="$withval"],
+    [sdkdir=`$PKG_CONFIG --variable=sdkdir xorg-server`])
+AC_SUBST([sdkdir])
+
+# Checks for libraries.
+
+# Checks for header files.
+AC_HEADER_STDC
+
+DRIVER_NAME=gesture
+AC_SUBST([DRIVER_NAME])
+
+AC_OUTPUT([Makefile
+           src/Makefile
+           man/Makefile
+           xorg-gesture.pc])
diff --git a/debian/changelog b/debian/changelog
new file mode 100755 (executable)
index 0000000..f45efac
--- /dev/null
@@ -0,0 +1,37 @@
+xserver-xorg-input-gesture (0.1.0-4) unstable; urgency=low
+
+  * Exception handling routine added. This commit is to fix Xorg BS problem at booting time.
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-gesture
+  * Tag: xserver-xorg-input-gesture_0.1.0-4
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 28 Nov 2011 15:20:14 +0900
+
+xserver-xorg-input-gesture (0.1.0-3) unstable; urgency=low
+
+  * Define ErrorStatus and check up error status at important check points
+    Fix GestureEventsFlush() not to modify timestamp of each event
+    Remove unnecessary modification and remove unused code
+    Remove unused macro from gesture.h
+    Remove whitespace and fix indentation
+    Replace GestureEventsFree() with GestureEventsDrop()
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-gesture
+  * Tag: xserver-xorg-input-gesture_0.1.0-3
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Mon, 21 Nov 2011 22:51:22 +0900
+
+xserver-xorg-input-gesture (0.1.0-2) unstable; urgency=low
+
+  * add null check
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-gesture
+  * Tag: xserver-xorg-input-gesture_0.1.0-2
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Tue, 08 Nov 2011 12:44:49 +0900
+
+xserver-xorg-input-gesture (0.1.0-1) unstable; urgency=low
+
+  * Initial version
+  * Git: 165.213.180.234:slp/pkgs/xorg/driver/xserver-xorg-input-gesture
+  * Tag: xserver-xorg-input-gesture_0.1.0-1
+
+ -- Sung-Jin Park <sj76.park@samsung.com>  Wed, 19 Oct 2011 17:13:15 +0900
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..aeced7a
--- /dev/null
@@ -0,0 +1,21 @@
+Source: xserver-xorg-input-gesture
+Section: x11
+Priority: optional
+Maintainer: Sung-Jin Park <sj76.park@samsung.com>, Sangjin Lee <lsj119.@samsung.com>
+Uploaders: Sung-Jin Park <sj76.park@samsung.com>
+Build-Depends: debhelper (>= 5.0.0), pkg-config, quilt, xserver-xorg-dev (>= 1.9.3-19slp2), x11proto-core-dev, dpkg-dev (>= 1.14.17), automake, libtool, xutils-dev (>= 1:7.3~1), libpixman-1-dev, x11proto-gesture-dev (>= 0.1.0-1)
+#Build-Depends: debhelper (>= 5.0.0), pkg-config, quilt, xserver-xorg-dev (>= 1.6.99.900), x11proto-core-dev, x11proto-randr-dev, x11proto-input-dev, x11proto-kb-dev, libxkbfile-dev, dpkg-dev (>= 1.14.17), automake, libtool, xutils-dev (>= 1:7.3~1)
+Standards-Version: 3.8.3
+
+Package: xserver-xorg-input-gesture
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${xserver}
+Provides: ${xinpdriver:Provides}
+Description: X.Org X server -- Xserver gesture driver
+ This package provides the driver for recognizing gesture(s) using button
+ and motion events inside X server.
+
+Package: xserver-xorg-input-gesture-dbg
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}, ${xserver}, xserver-xorg-input-gesture (=${Source-Version})
+Description: Debug package of xserver-xorg-input-gesture
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..dd236a7
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/make -f
+# debian/rules for the Debian xserver-xorg-input-gesture package.
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>
+# Copyright © 2005 Daniel Stone <daniel@fooishbar.org>
+# Copyright © 2005 David Nusinow <dnusinow@debian.org>
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+include debian/xsfbs/xsfbs.mk
+
+CFLAGS = -Wall -g
+LDFLAGS +=  -Wl,--hash-style=both -Wl,--as-needed
+ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+else
+       CFLAGS += -O2
+endif
+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+       NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+       MAKEFLAGS += -j$(NUMJOBS)
+endif
+
+DEB_HOST_ARCH      ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_HOST_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+       confflags += --build=$(DEB_HOST_GNU_TYPE)
+else
+       confflags += --build=$(DEB_HOST_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+#      confflags += --build=$(DEB_BUILD_GNU_TYPE) --host=$(DEB_HOST_GNU_TYPE)
+endif
+
+# kbd_drv.a isn't phenomenally useful; kbd_drv.so more so
+confflags += --disable-static
+
+#configure: $(STAMP_DIR)/patch
+configure:
+       autoreconf -vfi
+       #./autogen.sh
+
+obj-$(DEB_BUILD_GNU_TYPE)/config.status: configure
+       mkdir -p obj-$(DEB_BUILD_GNU_TYPE)
+       cd obj-$(DEB_BUILD_GNU_TYPE) && \
+       ../configure --prefix=/usr --mandir=\$${prefix}/share/man \
+                    --infodir=\$${prefix}/share/info $(confflags) \
+                    CFLAGS="$(CFLAGS)" \
+                    LDFLAGS="$(LDFLAGS)" 
+
+build: build-stamp
+build-stamp: obj-$(DEB_BUILD_GNU_TYPE)/config.status
+       dh_testdir
+       cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE)
+       >$@
+
+clean: xsfclean
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp
+
+       rm -f config.cache config.log config.status
+       rm -f */config.cache */config.log */config.status
+       rm -f conftest* */conftest*
+       rm -rf autom4te.cache */autom4te.cache
+       rm -rf obj-*
+       rm -f $$(find -name Makefile.in)
+       rm -f compile config.guess config.sub configure depcomp install-sh
+       rm -f ltmain.sh missing INSTALL aclocal.m4 ylwrap mkinstalldirs config.h.in
+
+       dh_clean
+
+install: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+
+       cd obj-$(DEB_BUILD_GNU_TYPE) && $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install
+
+# Build architecture-dependent files here.
+binary-arch: build install serverabi
+       dh_testdir
+       dh_testroot
+
+       dh_installdocs
+       dh_installchangelogs ChangeLog
+       dh_install --sourcedir=debian/tmp --list-missing  --exclude=usr/share/man/man4
+       dh_installman
+       dh_link
+       dh_strip --dbg-package=xserver-xorg-input-gesture-dbg
+       dh_compress
+       dh_fixperms
+       dh_installdeb
+#      dh_shlibdeps -- --warnings=6
+       dh_shlibdeps --
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+# Build architecture-independent files here.
+binary-indep: build install
+# Nothing to do
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/xserver-xorg-input-gesture.install b/debian/xserver-xorg-input-gesture.install
new file mode 100644 (file)
index 0000000..1002d70
--- /dev/null
@@ -0,0 +1,2 @@
+usr/lib/xorg/modules/input/*.so
+usr/lib/xorg/modules/input/*.la
diff --git a/debian/xsfbs/repack.sh b/debian/xsfbs/repack.sh
new file mode 100644 (file)
index 0000000..5935cc9
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -e
+
+if ! [ -d debian/prune ]; then
+       exit 0
+fi
+
+if [ "x$1" != x--upstream-version ]; then
+       exit 1
+fi
+
+version="$2"
+filename="$3"
+
+if [ -z "$version" ] || ! [ -f "$filename" ]; then
+       exit 1
+fi
+
+dir="$(pwd)"
+tempdir="$(mktemp -d)"
+
+cd "$tempdir"
+tar xf "$dir/$filename"
+cat "$dir"/debian/prune/* | while read file; do rm -f */$file; done
+
+tar czf "$dir/$filename" *
+cd "$dir"
+rm -rf "$tempdir"
+echo "Done pruning upstream tarball"
+
+exit 0
diff --git a/debian/xsfbs/xsfbs.mk b/debian/xsfbs/xsfbs.mk
new file mode 100644 (file)
index 0000000..f0f8953
--- /dev/null
@@ -0,0 +1,293 @@
+#!/usr/bin/make -f
+
+# Debian X Strike Force Build System (XSFBS): Make portion
+
+# Copyright 1996 Stephen Early
+# Copyright 1997 Mark Eichin
+# Copyright 1998-2005, 2007 Branden Robinson
+# Copyright 2005 David Nusinow
+#
+# Licensed under the GNU General Public License, version 2.  See the file
+# /usr/share/common-licenses/GPL or <http://www.gnu.org/copyleft/gpl.txt>.
+
+# Originally by Stephen Early <sde1000@debian.org>
+# Modified by Mark W. Eichin <eichin@kitten.gen.ma.us>
+# Modified by Adam Heath <doogie@debian.org>
+# Modified by Branden Robinson <branden@debian.org>
+# Modified by Fabio Massimo Di Nitto <fabbione@fabbione.net>
+# Modified by David Nusinow <dnusinow@debian.org>
+# Acknowledgements to Manoj Srivastava.
+
+# Pass $(DH_OPTIONS) into the environment for debhelper's benefit.
+export DH_OPTIONS
+
+# force quilt to not use ~/.quiltrc and to use debian/patches
+QUILT = QUILT_PATCHES=debian/patches quilt --quiltrc /dev/null
+
+# Set up parameters for the upstream build environment.
+
+# Determine (source) package name from Debian changelog.
+SOURCE_NAME:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Source:' | awk '{print $$2}')
+
+# Determine package version from Debian changelog.
+SOURCE_VERSION:=$(shell dpkg-parsechangelog -ldebian/changelog \
+                        | grep '^Version:' | awk '{print $$2}')
+
+# Determine upstream version number.
+UPSTREAM_VERSION:=$(shell echo $(SOURCE_VERSION) | sed 's/-.*//')
+
+# Determine the source version without the epoch for make-orig-tar-gz
+NO_EPOCH_VER:=$(shell echo $(UPSTREAM_VERSION) | sed 's/^.://')
+
+# Figure out who's building this package.
+BUILDER:=$(shell echo $${DEBEMAIL:-$${EMAIL:-$$(echo $$LOGNAME@$$(cat /etc/mailname 2>/dev/null))}})
+
+# Find out if this is an official build; an official build has nothing but
+# digits, dots, and/or the codename of a release in the Debian part of the
+# version number.  Anything else indicates an unofficial build.
+OFFICIAL_BUILD:=$(shell VERSION=$(SOURCE_VERSION); if ! expr "$$(echo $${VERSION\#\#*-} | sed 's/\(woody\|sarge\|etch\|lenny\)//g')" : ".*[^0-9.].*" >/dev/null 2>&1; then echo yes; fi)
+
+# Set up parameters for the Debian build environment.
+
+# Determine our architecture.
+BUILD_ARCH:=$(shell dpkg-architecture -qDEB_BUILD_ARCH)
+# Work around some old-time dpkg braindamage.
+BUILD_ARCH:=$(subst i486,i386,$(BUILD_ARCH))
+# The DEB_HOST_ARCH variable may be set per the Debian cross-compilation policy.
+ifdef DEB_HOST_ARCH
+ ARCH:=$(DEB_HOST_ARCH)
+else
+ # dpkg-cross sets the ARCH environment variable; if set, use it.
+ ifdef ARCH
+  ARCH:=$(ARCH)
+ else
+  ARCH:=$(BUILD_ARCH)
+ endif
+endif
+
+# $(STAMP_DIR) houses stamp files for complex targets.
+STAMP_DIR:=stampdir
+
+# $(DEBTREEDIR) is where all install rules are told (via $(DESTDIR)) to place
+# their files.
+DEBTREEDIR:=$(CURDIR)/debian/tmp
+
+# All "important" targets have four lines:
+#   1) A target name that is invoked by a package-building tool or the user.
+#      This consists of a dependency on a "$(STAMP_DIR)/"-prefixed counterpart.
+#   2) A line delcaring 1) as a phony target (".PHONY:").
+#   3) A "$(STAMP_DIR)/"-prefixed target which does the actual work, and may
+#   depend on other targets.
+#   4) A line declaring 3) as a member of the $(stampdir_targets) variable; the
+#   "$(STAMP_DIR)/" prefix is omitted.
+#
+# This indirection is needed so that the "stamp" files that signify when a rule
+# is done can be located in a separate "stampdir".  Recall that make has no way
+# to know when a goal has been met for a phony target (like "build" or
+# "install").
+#
+# At the end of each "$(STAMP_DIR)/" target, be sure to run the command ">$@"
+# so that the target will not be run again.  Removing the file will make Make
+# run the target over.
+
+# All phony targets should be declared as dependencies of .PHONY, even if they
+# do not have "($STAMP_DIR)/"-prefixed counterparts.
+
+# Define a harmless default rule to keep things from going nuts by accident.
+.PHONY: default
+default:
+
+# Set up the $(STAMP_DIR) directory.
+.PHONY: stampdir
+stampdir_targets+=stampdir
+stampdir: $(STAMP_DIR)/stampdir
+$(STAMP_DIR)/stampdir:
+       mkdir $(STAMP_DIR)
+       >$@
+
+# Set up the package build directory as quilt expects to find it.
+.PHONY: prepare
+stampdir_targets+=prepare
+prepare: $(STAMP_DIR)/prepare
+$(STAMP_DIR)/prepare: $(STAMP_DIR)/log $(STAMP_DIR)/genscripts
+       >$@
+
+.PHONY: log
+stampdir_targets+=log
+log: $(STAMP_DIR)/log
+$(STAMP_DIR)/log: $(STAMP_DIR)/stampdir
+       mkdir -p $(STAMP_DIR)/log
+
+# Apply all patches to the upstream source.
+.PHONY: patch
+stampdir_targets+=patch
+patch: $(STAMP_DIR)/patch
+$(STAMP_DIR)/patch: $(STAMP_DIR)/prepare
+       if ! [ `which quilt` ]; then \
+               echo "Couldn't find quilt. Please install it or add it to the build-depends for this package."; \
+               exit 1; \
+       fi; \
+       if $(QUILT) next >/dev/null 2>&1; then \
+         echo -n "Applying patches..."; \
+         if $(QUILT) push -a -v >$(STAMP_DIR)/log/patch 2>&1; then \
+           cat $(STAMP_DIR)/log/patch; \
+           echo "successful."; \
+         else \
+           cat $(STAMP_DIR)/log/patch; \
+           echo "failed! (check $(STAMP_DIR)/log/patch for details)"; \
+           exit 1; \
+         fi; \
+       else \
+         echo "No patches to apply"; \
+       fi; \
+       >$@
+
+# Revert all patches to the upstream source.
+.PHONY: unpatch
+unpatch: $(STAMP_DIR)/log
+       rm -f $(STAMP_DIR)/patch
+       @echo -n "Unapplying patches..."; \
+       if $(QUILT) applied >/dev/null 2>/dev/null; then \
+         if $(QUILT) pop -a -v >$(STAMP_DIR)/log/unpatch 2>&1; then \
+           cat $(STAMP_DIR)/log/unpatch; \
+           echo "successful."; \
+         else \
+           cat $(STAMP_DIR)/log/unpatch; \
+           echo "failed! (check $(STAMP_DIR)/log/unpatch for details)"; \
+           exit 1; \
+         fi; \
+       else \
+         echo "nothing to do."; \
+       fi
+
+# Clean the generated maintainer scripts.
+.PHONY: cleanscripts
+cleanscripts:
+       rm -f $(STAMP_DIR)/genscripts
+       rm -f debian/*.config \
+             debian/*.postinst \
+             debian/*.postrm \
+             debian/*.preinst \
+             debian/*.prerm
+
+# Clean the package build tree.
+.PHONY: xsfclean
+xsfclean: cleanscripts unpatch
+       dh_testdir
+       rm -rf .pc
+       rm -rf $(STAMP_DIR) $(SOURCE_DIR)
+       rm -rf imports
+       dh_clean debian/shlibs.local \
+                debian/po/pothead
+
+# Generate the debconf templates POT file header.
+debian/po/pothead: debian/po/pothead.in
+       sed -e 's/SOURCE_VERSION/$(SOURCE_VERSION)/' \
+         -e 's/DATE/$(shell date "+%F %X%z"/)' <$< >$@
+
+# Update POT and PO files.
+.PHONY: updatepo
+updatepo: debian/po/pothead
+       debian/scripts/debconf-updatepo --pot-header=pothead --verbose
+
+# Remove files from the upstream source tree that we don't need, or which have
+# licensing problems.  It must be run before creating the .orig.tar.gz.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: prune-upstream-tree
+prune-upstream-tree:
+       # Ensure we're in the correct directory.
+       dh_testdir
+       grep -rvh '^#' debian/prune/ | xargs --no-run-if-empty rm -rf
+
+# Verify that there are no offsets or fuzz in the patches we apply.
+#
+# Note: This rule is for Debian package maintainers' convenience, and is not
+# needed for conventional build scenarios.
+.PHONY: patch-audit
+patch-audit: prepare unpatch
+       @echo -n "Auditing patches..."; \
+       >$(STAMP_DIR)/log/patch; \
+       FUZZY=; \
+       while [ -n "$$($(QUILT) next)" ]; do \
+         RESULT=$$($(QUILT) push -v | tee -a $(STAMP_DIR)/log/patch | grep ^Hunk | sed 's/^Hunk.*\(succeeded\|FAILED\).*/\1/');\
+         case "$$RESULT" in \
+           succeeded) \
+             echo "fuzzy patch: $$($(QUILT) top)" \
+               | tee -a $(STAMP_DIR)/log/$$($(QUILT) top); \
+             FUZZY=yes; \
+             ;; \
+           FAILED) \
+             echo "broken patch: $$($(QUILT) next)" \
+               | tee -a $(STAMP_DIR)/log/$$($(QUILT) next); \
+             exit 1; \
+             ;; \
+         esac; \
+       done; \
+       if [ -n "$$FUZZY" ]; then \
+         echo "there were fuzzy patches; please fix."; \
+         exit 1; \
+       else \
+         echo "done."; \
+       fi
+
+# Generate the maintainer scripts.
+.PHONY: genscripts
+stampdir_targets+=genscripts
+genscripts: $(STAMP_DIR)/genscripts
+$(STAMP_DIR)/genscripts: $(STAMP_DIR)/stampdir
+       for FILE in debian/*.config.in \
+                   debian/*.postinst.in \
+                   debian/*.postrm.in \
+                   debian/*.preinst.in \
+                   debian/*.prerm.in; do \
+         if [ -e "$$FILE" ]; then \
+           MAINTSCRIPT=$$(echo $$FILE | sed 's/.in$$//'); \
+           sed -n '1,/^#INCLUDE_SHELL_LIB#$$/p' <$$FILE \
+             | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >$$MAINTSCRIPT.tmp; \
+           cat debian/xsfbs/xsfbs.sh >>$$MAINTSCRIPT.tmp; \
+           sed -n '/^#INCLUDE_SHELL_LIB#$$/,$$p' <$$FILE \
+             | sed -e '/^#INCLUDE_SHELL_LIB#$$/d' >>$$MAINTSCRIPT.tmp; \
+           sed -e 's/@SOURCE_VERSION@/$(SOURCE_VERSION)/' \
+               -e 's/@OFFICIAL_BUILD@/$(OFFICIAL_BUILD)/' \
+               -e 's/@DEFAULT_DCRESOLUTIONS@/$(DEFAULT_DCRESOLUTIONS)/' \
+             <$$MAINTSCRIPT.tmp >$$MAINTSCRIPT; \
+           rm $$MAINTSCRIPT.tmp; \
+         fi; \
+       done
+       # Validate syntax of generated shell scripts.
+       #sh debian/scripts/validate-posix-sh debian/*.config \
+       #                                    debian/*.postinst \
+       #                                    debian/*.postrm \
+       #                                    debian/*.preinst \
+       #                                    debian/*.prerm
+       >$@
+
+# Generate the shlibs.local file.
+debian/shlibs.local:
+       cat debian/*.shlibs >$@
+
+SERVERMINVERS = $(shell cat /usr/share/xserver-xorg/serverminver 2>/dev/null)
+VIDEOABI = $(shell cat /usr/share/xserver-xorg/videoabiver 2>/dev/null)
+INPUTABI = $(shell cat /usr/share/xserver-xorg/inputabiver 2>/dev/null)
+SERVER_DEPENDS = xserver-xorg-core (>= $(SERVERMINVERS))
+VIDDRIVER_PROVIDES = xserver-xorg-video-$(VIDEOABI)
+INPDRIVER_PROVIDES = xserver-xorg-input-$(INPUTABI)
+ifeq ($(PACKAGE),)
+PACKAGE=$(shell awk '/^Package:/ { print $$2; exit }' < debian/control)
+endif
+
+.PHONY: serverabi
+serverabi: install
+ifeq ($(SERVERMINVERS),)
+       @echo error: xserver-xorg-dev needs to be installed
+       @exit 1
+else
+       echo "xserver:Depends=$(SERVER_DEPENDS)" >> debian/$(PACKAGE).substvars
+       echo "xviddriver:Provides=$(VIDDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+       echo "xinpdriver:Provides=$(INPDRIVER_PROVIDES)" >> debian/$(PACKAGE).substvars
+endif
+
+# vim:set noet ai sts=8 sw=8 tw=0:
diff --git a/debian/xsfbs/xsfbs.sh b/debian/xsfbs/xsfbs.sh
new file mode 100644 (file)
index 0000000..781826f
--- /dev/null
@@ -0,0 +1,853 @@
+# $Id$
+
+# This is the X Strike Force shell library for X Window System package
+# maintainer scripts.  It serves to define shell functions commonly used by
+# such packages, and performs some error checking necessary for proper operation
+# of those functions.  By itself, it does not "do" much; the maintainer scripts
+# invoke the functions defined here to accomplish package installation and
+# removal tasks.
+
+# If you are reading this within a Debian package maintainer script (e.g.,
+# /var/lib/dpkg)info/PACKAGE.{config,preinst,postinst,prerm,postrm}), you can
+# skip past this library by scanning forward in this file to the string
+# "GOBSTOPPER".
+
+SOURCE_VERSION=@SOURCE_VERSION@
+OFFICIAL_BUILD=@OFFICIAL_BUILD@
+
+# Use special abnormal exit codes so that problems with this library are more
+# easily tracked down.
+SHELL_LIB_INTERNAL_ERROR=86
+SHELL_LIB_THROWN_ERROR=74
+SHELL_LIB_USAGE_ERROR=99
+
+# old -> new variable names
+if [ -z "$DEBUG_XORG_PACKAGE" ] && [ -n "$DEBUG_XFREE86_PACKAGE" ]; then
+  DEBUG_XORG_PACKAGE="$DEBUG_XFREE86_PACKAGE"
+fi
+if [ -z "$DEBUG_XORG_DEBCONF" ] && [ -n "$DEBUG_XFREE86_DEBCONF" ]; then
+  DEBUG_XORG_DEBCONF="$DEBUG_XFREE86_DEBCONF"
+fi
+
+# initial sanity checks
+if [ -z "$THIS_PACKAGE" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_PACKAGE shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of this package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+if [ -z "$THIS_SCRIPT" ]; then
+  cat >&2 <<EOF
+Error: package maintainer script attempted to use shell library without
+definining \$THIS_SCRIPT shell variable.  Please report the package name,
+version, and the text of this error message to the Debian Bug Tracking System.
+Visit <http://www.debian.org/Bugs/Reporting> on the World Wide Web for
+instructions, read the file /usr/share/doc/debian/bug-reporting.txt from the
+"doc-debian" package, or install the "reportbug" package and use the command of
+the same name to file a report against version $SOURCE_VERSION of the
+"$THIS_PACKAGE" package.
+EOF
+  exit $SHELL_LIB_USAGE_ERROR
+fi
+
+if [ "$1" = "reconfigure" ] || [ -n "$DEBCONF_RECONFIGURE" ]; then
+  RECONFIGURE="true"
+else
+  RECONFIGURE=
+fi
+
+if ([ "$1" = "install" ] || [ "$1" = "configure" ]) && [ -z "$2" ]; then
+  FIRSTINST="yes"
+fi
+
+if [ -z "$RECONFIGURE" ] && [ -z "$FIRSTINST" ]; then
+  UPGRADE="yes"
+fi
+
+trap "message;\
+      message \"Received signal.  Aborting $THIS_PACKAGE package $THIS_SCRIPT script.\";\
+      message;\
+      exit 1" HUP INT QUIT TERM
+
+reject_nondigits () {
+  # syntax: reject_nondigits [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters other than decimal digits and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain anything but digits?
+    if ! expr "$1" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+      # can't use die(), because it wraps message() which wraps this function
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_nondigits() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+reject_whitespace () {
+  # syntax: reject_whitespace [ operand ]
+  #
+  # scan operand (typically a shell variable whose value cannot be trusted) for
+  # whitespace characters and barf if any are found
+  if [ -n "$1" ]; then
+    # does the operand contain any whitespace?
+    if expr "$1" : "[[:space:]]" > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_whitespace() encountered" \
+           "possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+  fi
+}
+
+reject_unlikely_path_chars () {
+  # syntax: reject_unlikely_path_chars [ operand ... ]
+  #
+  # scan operands (typically shell variables whose values cannot be trusted) for
+  # characters unlikely to be seen in a path and which the shell might
+  # interpret and barf if any are found
+  while [ -n "$1" ]; do
+    # does the operand contain any funny characters?
+    if expr "$1" : '.*[!$&()*;<>?|].*' > /dev/null 2>&1; then
+      # can't use die(), because I want to avoid forward references
+      echo "$THIS_PACKAGE $THIS_SCRIPT error: reject_unlikely_path_chars()" \
+           "encountered possibly malicious garbage \"$1\"" >&2
+      exit $SHELL_LIB_THROWN_ERROR
+    fi
+    shift
+  done
+}
+
+# Query the terminal to establish a default number of columns to use for
+# displaying messages to the user.  This is used only as a fallback in the
+# event the COLUMNS variable is not set.  ($COLUMNS can react to SIGWINCH while
+# the script is running, and this cannot, only being calculated once.)
+DEFCOLUMNS=$(stty size 2> /dev/null | awk '{print $2}') || true
+if ! expr "$DEFCOLUMNS" : "[[:digit:]]\+$" > /dev/null 2>&1; then
+  DEFCOLUMNS=80
+fi
+
+message () {
+  # pretty-print messages of arbitrary length
+  reject_nondigits "$COLUMNS"
+  echo "$*" | fmt -t -w ${COLUMNS:-$DEFCOLUMNS} >&2
+}
+
+observe () {
+  # syntax: observe message ...
+  #
+  # issue observational message suitable for logging someday when support for
+  # it exists in dpkg
+  if [ -n "$DEBUG_XORG_PACKAGE" ]; then
+    message "$THIS_PACKAGE $THIS_SCRIPT note: $*"
+  fi
+}
+
+warn () {
+  # syntax: warn message ...
+  #
+  # issue warning message suitable for logging someday when support for
+  # it exists in dpkg; also send to standard error
+  message "$THIS_PACKAGE $THIS_SCRIPT warning: $*"
+}
+
+die () {
+  # syntax: die message ...
+  #
+  # exit script with error message
+  message "$THIS_PACKAGE $THIS_SCRIPT error: $*"
+  exit $SHELL_LIB_THROWN_ERROR
+}
+
+internal_error () {
+  # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message
+  message "internal error: $*"
+  if [ -n "$OFFICIAL_BUILD" ]; then
+    message "Please report a bug in the $THIS_SCRIPT script of the" \
+            "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+            "Tracking System.  Include all messages above that mention the" \
+            "$THIS_PACKAGE package.  Visit " \
+            "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+            "instructions, read the file" \
+            "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+            "package, or install the reportbug package and use the command of" \
+            "the same name to file a report."
+  fi
+  exit $SHELL_LIB_INTERNAL_ERROR
+}
+
+usage_error () {
+  message "usage error: $*"
+  message "Please report a bug in the $THIS_SCRIPT script of the" \
+          "$THIS_PACKAGE package, version $SOURCE_VERSION to the Debian Bug" \
+          "Tracking System.  Include all messages above that mention the" \
+          "$THIS_PACKAGE package.  Visit " \
+          "<http://www.debian.org/Bugs/Reporting> on the World Wide Web for" \
+          "instructions, read the file" \
+          "/usr/share/doc/debian/bug-reporting.txt from the doc-debian" \
+          "package, or install the reportbug package and use the command of" \
+          "the same name to file a report."
+  exit $SHELL_LIB_USAGE_ERROR
+}
+
+
+maplink () {
+  # returns what symlink should point to; i.e., what the "sane" answer is
+  # Keep this in sync with the debian/*.links files.
+  # This is only needed for symlinks to directories.
+  #
+  # XXX: Most of these look wrong in the X11R7 world and need to be fixed.
+  # If we've stopped using this function, fixing it might enable us to re-enable
+  # it again and catch more errors.
+  case "$1" in
+    /etc/X11/xkb/compiled) echo /var/lib/xkb ;;
+    /etc/X11/xkb/xkbcomp) echo /usr/X11R6/bin/xkbcomp ;;
+    /usr/X11R6/lib/X11/app-defaults) echo /etc/X11/app-defaults ;;
+    /usr/X11R6/lib/X11/fs) echo /etc/X11/fs ;;
+    /usr/X11R6/lib/X11/lbxproxy) echo /etc/X11/lbxproxy ;;
+    /usr/X11R6/lib/X11/proxymngr) echo /etc/X11/proxymngr ;;
+    /usr/X11R6/lib/X11/rstart) echo /etc/X11/rstart ;;
+    /usr/X11R6/lib/X11/twm) echo /etc/X11/twm ;;
+    /usr/X11R6/lib/X11/xdm) echo /etc/X11/xdm ;;
+    /usr/X11R6/lib/X11/xinit) echo /etc/X11/xinit ;;
+    /usr/X11R6/lib/X11/xkb) echo /etc/X11/xkb ;;
+    /usr/X11R6/lib/X11/xserver) echo /etc/X11/xserver ;;
+    /usr/X11R6/lib/X11/xsm) echo /etc/X11/xsm ;;
+    /usr/bin/X11) echo ../X11R6/bin ;;
+    /usr/bin/rstartd) echo ../X11R6/bin/rstartd ;;
+    /usr/include/X11) echo ../X11R6/include/X11 ;;
+    /usr/lib/X11) echo ../X11R6/lib/X11 ;;
+    *) internal_error "maplink() called with unknown path \"$1\"" ;;
+  esac
+}
+
+analyze_path () {
+  # given a supplied set of pathnames, break each one up by directory and do an
+  # ls -dl on each component, cumulatively; i.e.
+  # analyze_path /usr/X11R6/bin -> ls -dl /usr /usr/X11R6 /usr/X11R6/bin
+  # Thanks to Randolph Chung for this clever hack.
+
+  local f g
+
+  while [ -n "$1" ]; do
+    reject_whitespace "$1"
+    g=
+    message "Analyzing $1:"
+    for f in $(echo "$1" | tr / \  ); do
+      if [ -e /$g$f ]; then
+        ls -dl /$g$f /$g$f.dpkg-* 2> /dev/null || true
+        g=$g$f/
+      else
+        message "/$g$f: nonexistent; directory contents of /$g:"
+        ls -l /$g
+        break
+      fi
+    done
+    shift
+  done
+}
+
+find_culprits () {
+  local f p dpkg_info_dir possible_culprits smoking_guns bad_packages package \
+    msg
+
+  reject_whitespace "$1"
+  message "Searching for overlapping packages..."
+  dpkg_info_dir=/var/lib/dpkg/info
+  if [ -d $dpkg_info_dir ]; then
+    if [ "$(echo $dpkg_info_dir/*.list)" != "$dpkg_info_dir/*.list" ]; then
+      possible_culprits=$(ls -1 $dpkg_info_dir/*.list | egrep -v \
+        "(xbase-clients|x11-common|xfs|xlibs)")
+      if [ -n "$possible_culprits" ]; then
+        smoking_guns=$(grep -l "$1" $possible_culprits || true)
+        if [ -n "$smoking_guns" ]; then
+          bad_packages=$(printf "\\n")
+          for f in $smoking_guns; do
+            # too bad you can't nest parameter expansion voodoo
+            p=${f%*.list}      # strip off the trailing ".list"
+            package=${p##*/}   # strip off the directories
+            bad_packages=$(printf "%s\n%s" "$bad_packages" "$package")
+          done
+          msg=$(cat <<EOF
+The following packages appear to have file overlaps with the X.Org packages;
+these packages are either very old, or in violation of Debian Policy.  Try
+upgrading each of these packages to the latest available version if possible:
+for example, with the command "apt-get install".  If no newer version of a
+package is available, you will have to remove it; for example, with the command
+"apt-get remove".  If even the latest available version of the package has
+this file overlap, please file a bug against that package with the Debian Bug
+Tracking System.  You may want to refer the package maintainer to section 12.8
+of the Debian Policy manual.
+EOF
+)
+          message "$msg"
+          message "The overlapping packages are: $bad_packages"
+        else
+          message "no overlaps found."
+        fi
+      fi
+    else
+      message "cannot search; no matches for $dpkg_info_dir/*.list."
+    fi
+  else
+    message "cannot search; $dpkg_info_dir does not exist."
+  fi
+}
+
+check_symlink () {
+  # syntax: check_symlink symlink
+  #
+  # See if specified symlink points where it is supposed to.  Return 0 if it
+  # does, and 1 if it does not.
+  #
+  # Primarily used by check_symlinks_and_warn() and check_symlinks_and_bomb().
+
+  local symlink
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "check_symlink() called with wrong number of arguments;" \
+                "expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  symlink="$1"
+
+  if [ "$(maplink "$symlink")" = "$(readlink "$symlink")" ]; then
+    return 0
+  else
+    return 1
+  fi
+}
+
+check_symlinks_and_warn () {
+  # syntax: check_symlinks_and_warn symlink ...
+  #
+  # For each argument, check for symlink sanity, and warn if it isn't sane.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install".
+
+  local errmsg symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_warn() called with wrong number of" \
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        observe "$symlink symbolic link points to wrong location" \
+                "$(readlink "$symlink"); removing"
+        rm "$symlink"
+      fi
+    elif [ -e "$symlink" ]; then
+      errmsg="$symlink exists and is not a symbolic link; this package cannot"
+      errmsg="$errmsg be installed until this"
+      if [ -f "$symlink" ]; then
+        errmsg="$errmsg file"
+      elif [ -d "$symlink" ]; then
+        errmsg="$errmsg directory"
+      else
+        errmsg="$errmsg thing"
+      fi
+      errmsg="$errmsg is removed"
+      die "$errmsg"
+    fi
+    shift
+  done
+}
+
+check_symlinks_and_bomb () {
+  # syntax: check_symlinks_and_bomb symlink ...
+  #
+  # For each argument, check for symlink sanity, and bomb if it isn't sane.
+  #
+  # Call this function from a postinst script.
+
+  local problem symlink
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "check_symlinks_and_bomb() called with wrong number of"
+                "arguments; expected at least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  while [ -n "$1" ]; do
+    problem=
+    symlink="$1"
+    if [ -L "$symlink" ]; then
+      if ! check_symlink "$symlink"; then
+        problem=yes
+        warn "$symlink symbolic link points to wrong location" \
+             "$(readlink "$symlink")"
+      fi
+    elif [ -e "$symlink" ]; then
+      problem=yes
+      warn "$symlink is not a symbolic link"
+    else
+      problem=yes
+      warn "$symlink symbolic link does not exist"
+    fi
+    if [ -n "$problem" ]; then
+      analyze_path "$symlink" "$(readlink "$symlink")"
+      find_culprits "$symlink"
+      die "bad symbolic links on system"
+    fi
+    shift
+  done
+}
+
+font_update () {
+  # run $UPDATECMDS in $FONTDIRS
+
+  local dir cmd shortcmd x_font_dir_prefix
+
+  x_font_dir_prefix="/usr/share/fonts/X11"
+
+  if [ -z "$UPDATECMDS" ]; then
+    usage_error "font_update() called but \$UPDATECMDS not set"
+  fi
+  if [ -z "$FONTDIRS" ]; then
+    usage_error "font_update() called but \$FONTDIRS not set"
+  fi
+
+  reject_unlikely_path_chars "$UPDATECMDS"
+  reject_unlikely_path_chars "$FONTDIRS"
+
+  for dir in $FONTDIRS; do
+    if [ -d "$x_font_dir_prefix/$dir" ]; then
+      for cmd in $UPDATECMDS; do
+        if which "$cmd" > /dev/null 2>&1; then
+          shortcmd=${cmd##*/}
+          observe "running $shortcmd in $dir font directory"
+         cmd_opts=
+          if [ "$shortcmd" = "update-fonts-alias" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-dir" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          if [ "$shortcmd" = "update-fonts-scale" ]; then
+            cmd_opts=--x11r7-layout
+          fi
+          $cmd $cmd_opts $dir || warn "$cmd $cmd_opts $dir" \
+                              "failed; font directory data may not" \
+                              "be up to date"
+        else
+          warn "$cmd not found; not updating corresponding $dir font" \
+               "directory data"
+        fi
+      done
+    else
+      warn "$dir is not a directory; not updating font directory data"
+    fi
+  done
+}
+
+remove_conffile_prepare () {
+  # syntax: remove_conffile_prepare filename official_md5sum ...
+  #
+  # Check a conffile "filename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 2 ]; then
+    usage_error "remove_conffile_prepare() called with wrong number of" \
+                "arguments; expected at least 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+  shift
+
+  # does the conffile even exist?
+  if [ -e "$conffile" ]; then
+    # calculate its checksum
+    current_checksum=$(md5sum < "$conffile" | sed 's/[[:space:]].*//')
+    # compare it to each supplied checksum
+    while [ -n "$1" ]; do
+      if [ "$current_checksum" = "$1" ]; then
+        # we found a match; move the confffile and stop looking
+        observe "preparing obsolete conffile $conffile for removal"
+        mv "$conffile" "$conffile.$THIS_PACKAGE-tmp"
+        break
+      fi
+      shift
+    done
+  fi
+}
+
+remove_conffile_lookup () {
+  # syntax: remove_conffile_lookup package filename
+  #
+  # Lookup the md5sum of a conffile in dpkg's database, and prepare for removal
+  # if it matches the actual file's md5sum.
+  #
+  # Call this function when you would call remove_conffile_prepare but only
+  # want to check against dpkg's status database instead of known checksums.
+
+  local package conffile old_md5sum
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "remove_conffile_lookup() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  package="$1"
+  conffile="$2"
+
+  if ! [ -e "$conffile" ]; then
+    return
+  fi
+  old_md5sum="$(dpkg-query -W -f='${Conffiles}' "$package" | \
+    awk '{ if (match($0, "^ '"$conffile"' ")) print $2}')"
+  if [ -n "$old_md5sum" ]; then
+    remove_conffile_prepare "$conffile" "$old_md5sum"
+  fi
+}
+
+remove_conffile_commit () {
+  # syntax: remove_conffile_commit filename
+  #
+  # Complete the removal of a conffile "filename" that has become obsolete.
+  #
+  # Call this function from a postinst script after having used
+  # remove_conffile_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_commit() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, remove it
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "committing removal of obsolete conffile $conffile"
+    rm "$conffile.$THIS_PACKAGE-tmp"
+  fi
+}
+
+remove_conffile_rollback () {
+  # syntax: remove_conffile_rollback filename
+  #
+  # Roll back the removal of a conffile "filename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" is  after having used remove_conffile_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "remove_conffile_rollback() called with wrong number of" \
+                "arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  # if the temporary file created by remove_conffile_prepare() exists, move it
+  # back
+  if [ -e "$conffile.$THIS_PACKAGE-tmp" ]; then
+    observe "rolling back removal of obsolete conffile $conffile"
+    mv "$conffile.$THIS_PACKAGE-tmp" "$conffile"
+  fi
+}
+
+replace_conffile_with_symlink_prepare () {
+  # syntax: replace_conffile_with_symlink_prepare oldfilename newfilename \
+  # official_md5sum ...
+  #
+  # Check a conffile "oldfilename" against a list of canonical MD5 checksums.
+  # If the file's current MD5 checksum matches one of the "official_md5sum"
+  # operands provided, then prepare the conffile for removal from the system.
+  # We defer actual deletion until the package is configured so that we can
+  # roll this operation back if package installation fails. Otherwise copy it
+  # to newfilename and let dpkg handle it through conffiles mechanism.
+  #
+  # Call this function from a preinst script in the event $1 is "upgrade" or
+  # "install" and verify $2 to ensure the package is being upgraded from a
+  # version (or installed over a version removed-but-not-purged) prior to the
+  # one in which the conffile was obsoleted.
+
+  local conffile current_checksum
+
+  # validate arguments
+  if [ $# -lt 3 ]; then
+    usage_error "replace_conffile_with_symlink_prepare() called with wrong" \
+                " number of arguments; expected at least 3, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  shift
+  newconffile="$1"
+  shift
+
+  remove_conffile_prepare "$_oldconffile" "$@"
+  # If $oldconffile still exists, then md5sums didn't match.
+  # Copy it to new one.
+  if [ -f "$oldconffile" ]; then
+    cp "$oldconffile" "$newconffile"
+  fi
+
+}
+
+replace_conffile_with_symlink_commit () {
+  # syntax: replace_conffile_with_symlink_commit oldfilename
+  #
+  # Complete the removal of a conffile "oldfilename" that has been
+  # replaced by a symlink.
+  #
+  # Call this function from a postinst script after having used
+  # replace_conffile_with_symlink_prepare() in the preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 1 ]; then
+    usage_error "replace_conffile_with_symlink_commit() called with wrong" \
+                "number of arguments; expected 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  conffile="$1"
+
+  remove_conffile_commit "$conffile"
+}
+
+replace_conffile_with_symlink_rollback () {
+  # syntax: replace_conffile_with_symlink_rollback oldfilename newfilename
+  #
+  # Roll back the replacing of a conffile "oldfilename" with symlink to
+  # "newfilename".
+  #
+  # Call this function from a postrm script in the event $1 is "abort-upgrade"
+  # or "abort-install" and verify $2 to ensure the package failed to upgrade
+  # from a version (or install over a version removed-but-not-purged) prior
+  # to the one in which the conffile was obsoleted.
+  # You should have  used replace_conffile_with_symlink_prepare() in the
+  # preinst.
+
+  local conffile
+
+  # validate arguments
+  if [ $# -ne 2 ]; then
+    usage_error "replace_conffile_with_symlink_rollback() called with wrong" \
+                "number of arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  oldconffile="$1"
+  newconffile="$2"
+
+  remove_conffile_rollback "$_oldconffile"
+  if [ -f "$newconffile" ]; then
+    rm "$newconffile"
+  fi
+}
+
+run () {
+  # syntax: run command [ argument ... ]
+  #
+  # Run specified command with optional arguments and report its exit status.
+  # Useful for commands whose exit status may be nonzero, but still acceptable,
+  # or commands whose failure is not fatal to us.
+  #
+  # NOTE: Do *not* use this function with db_get or db_metaget commands; in
+  # those cases the return value of the debconf command *must* be checked
+  # before the string returned by debconf is used for anything.
+
+  local retval
+
+  # validate arguments
+  if [ $# -lt 1 ]; then
+    usage_error "run() called with wrong number of arguments; expected at" \
+                "least 1, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  "$@" || retval=$?
+
+  if [ ${retval:-0} -ne 0 ]; then
+    observe "command \"$*\" exited with status $retval"
+  fi
+}
+
+make_symlink_sane () {
+  # syntax: make_symlink_sane symlink target
+  #
+  # Ensure that the symbolic link symlink exists, and points to target.
+  #
+  # If symlink does not exist, create it and point it at target.
+  #
+  # If symlink exists but is not a symbolic link, back it up.
+  #
+  # If symlink exists, is a symbolic link, but points to the wrong location, fix
+  # it.
+  #
+  # If symlink exists, is a symbolic link, and already points to target, do
+  # nothing.
+  #
+  # This function wouldn't be needed if ln had an -I, --idempotent option.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "make_symlink_sane() called with wrong number of arguments;" \
+      "expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local symlink target
+
+  symlink="$1"
+  target="$2"
+
+  if [ -L "$symlink" ] && [ "$(readlink "$symlink")" = "$target" ]; then
+      observe "link from $symlink to $target already exists"
+  else
+    observe "creating symbolic link from $symlink to $target"
+    mkdir -p "${target%/*}" "${symlink%/*}"
+    ln -s -b -S ".dpkg-old" "$target" "$symlink"
+  fi
+}
+
+migrate_dir_to_symlink () {
+  # syntax: migrate_dir_to_symlink old_location new_location
+  #
+  # Per Debian Policy section 6.5.4, "A directory will never be replaced by a
+  # symbolic link to a directory or vice versa; instead, the existing state
+  # (symlink or not) will be left alone and dpkg will follow the symlink if
+  # there is one."
+  #
+  # We have to do it ourselves.
+  #
+  # This function moves the contents of old_location, a directory, into
+  # new_location, a directory, then makes old_location a symbolic link to
+  # new_location.
+  #
+  # old_location need not exist, but if it does, it must be a directory (or a
+  # symlink to a directory).  If it is not, it is backed up.  If new_location
+  # exists already and is not a directory, it is backed up.
+  #
+  # This function should be called from a package's preinst so that other
+  # packages unpacked after this one --- but before this package's postinst runs
+  # --- are unpacked into new_location even if their payloads contain
+  # old_location filespecs.
+
+  # Validate arguments.
+  if [ $# -ne 2 ]; then
+    usage_error "migrate_dir_to_symlink() called with wrong number of"
+                "arguments; expected 2, got $#"
+    exit $SHELL_LIB_USAGE_ERROR
+  fi
+
+  # We could just use the positional parameters as-is, but that makes things
+  # harder to follow.
+  local new old
+
+  old="$1"
+  new="$2"
+
+  # Is old location a symlink?
+  if [ -L "$old" ]; then
+    # Does it already point to new location?
+    if [ "$(readlink "$old")" = "$new" ]; then
+      # Nothing to do; migration has already been done.
+      observe "migration of $old to $new already done"
+      return 0
+    else
+      # Back it up.
+      warn "backing up symbolic link $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+    fi
+  fi
+
+  # Does old location exist, but is not a directory?
+  if [ -e "$old" ] && ! [ -d "$old" ]; then
+      # Back it up.
+      warn "backing up non-directory $old as $old.dpkg-old"
+      mv -b "$old" "$old.dpkg-old"
+  fi
+
+  observe "migrating $old to $new"
+
+  # Is new location a symlink?
+  if [ -L "$new" ]; then
+    # Does it point the wrong way, i.e., back to where we're migrating from?
+    if [ "$(readlink "$new")" = "$old" ]; then
+      # Get rid of it.
+      observe "removing symbolic link $new which points to $old"
+      rm "$new"
+    else
+      # Back it up.
+      warn "backing up symbolic link $new as $new.dpkg-old"
+      mv -b "$new" "$new.dpkg-old"
+    fi
+  fi
+
+  # Does new location exist, but is not a directory?
+  if [ -e "$new" ] && ! [ -d "$new" ]; then
+    warn "backing up non-directory $new as $new.dpkg-old"
+    mv -b "$new" "$new.dpkg-old"
+  fi
+
+  # Create new directory if it does not yet exist.
+  if ! [ -e "$new" ]; then
+    observe "creating $new"
+    mkdir -p "$new"
+  fi
+
+  # Copy files in old location to new location.  Back up any filenames that
+  # already exist in the new location with the extension ".dpkg-old".
+  observe "copying files from $old to $new"
+  if ! (cd "$old" && cp -a -b -S ".dpkg-old" . "$new"); then
+    die "error(s) encountered while copying files from $old to $new"
+  fi
+
+  # Remove files at old location.
+  observe "removing $old"
+  rm -r "$old"
+
+  # Create symlink from old location to new location.
+  make_symlink_sane "$old" "$new"
+}
+
+# vim:set ai et sw=2 ts=2 tw=80:
+
+# GOBSTOPPER: The X Strike Force shell library ends here.
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644 (file)
index 0000000..276f2f0
--- /dev/null
@@ -0,0 +1,57 @@
+# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# 
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.
+# 
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+# 
+# Except as contained in this notice, the name of the copyright holders shall
+# not be used in advertising or otherwise to promote the sale, use or
+# other dealings in this Software without prior written authorization
+# from the copyright holders.
+# 
+
+drivermandir = $(DRIVER_MAN_DIR)
+
+driverman_PRE = @DRIVER_NAME@.man
+
+driverman_DATA = $(driverman_PRE:man=@DRIVER_MAN_SUFFIX@)
+
+EXTRA_DIST = @DRIVER_NAME@.man
+
+CLEANFILES = $(driverman_DATA)
+
+SED = sed
+
+# Strings to replace in man pages
+XORGRELSTRING = @PACKAGE_STRING@
+  XORGMANNAME = X Version 11
+
+MAN_SUBSTS = \
+       -e 's|__vendorversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+       -e 's|__xorgversion__|"$(XORGRELSTRING)" "$(XORGMANNAME)"|' \
+       -e 's|__xservername__|Xorg|g' \
+       -e 's|__xconfigfile__|xorg.conf|g' \
+       -e 's|__projectroot__|$(prefix)|g' \
+       -e 's|__appmansuffix__|$(APP_MAN_SUFFIX)|g' \
+       -e 's|__drivermansuffix__|$(DRIVER_MAN_SUFFIX)|g' \
+       -e 's|__adminmansuffix__|$(ADMIN_MAN_SUFFIX)|g' \
+       -e 's|__miscmansuffix__|$(MISC_MAN_SUFFIX)|g' \
+       -e 's|__filemansuffix__|$(FILE_MAN_SUFFIX)|g'
+
+SUFFIXES = .$(DRIVER_MAN_SUFFIX) .man
+
+.man.$(DRIVER_MAN_SUFFIX):
+       sed $(MAN_SUBSTS) < $< > $@
diff --git a/man/gesture.man b/man/gesture.man
new file mode 100644 (file)
index 0000000..f3e0eeb
--- /dev/null
@@ -0,0 +1,29 @@
+.ds q \N'34'
+.TH GESUTRE __drivermansuffix__ __vendorversion__
+.SH NAME
+gesture \- Example X.Org input driver
+.SH SYNOPSIS
+.nf
+.B "Section \*qInputDevice\*q"
+.BI "  Identifier \*q" devname \*q
+.B  "  Driver \*qgesture\*q"
+.BI "  Option \*qDevice\*q   \*q" devpath \*q
+\ \ ...
+.B EndSection
+.fi
+.SH DESCRIPTION
+.B gesture 
+is an example __xservername__ input driver It reads from /dev/ugesture and
+moves the pointer along the X axis by a gesture number of pixels.
+.PP
+.SH EMPTY MANPAGE
+This is an example driver, hence the man page is not particularly useful.
+For a better structure of the man page, including which sections to use in a
+new man page see the 
+.B evdev(4)
+man page.
+
+
+.SH "SEE ALSO"
+__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__),
+README.mouse.
diff --git a/packaging/xorg-x11-drv-input-gesture.spec b/packaging/xorg-x11-drv-input-gesture.spec
new file mode 100644 (file)
index 0000000..81cdee0
--- /dev/null
@@ -0,0 +1,48 @@
+Name:       xorg-x11-drv-input-gesture
+Summary:    X.Org X server -- Xserver gesture driver
+Version:    0.1.0
+Release:    4
+Group:      System/X Hardware Support
+License:    MIT
+Source0:    %{name}-%{version}.tar.gz
+Requires:   xorg-x11-server
+BuildRequires:  pkgconfig(xorg-server)
+BuildRequires:  pkgconfig(gestureproto)
+BuildRequires:  pkgconfig(xproto)
+BuildRequires:  pkgconfig(inputproto)
+%description
+ This package provides the driver for recognizing gesture(s) using button
+and motion events inside X server.
+
+
+%package devel
+Summary:    Development files for xorg gesture driver
+Group:      Development/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description devel
+xorg-x11-drv-input-gesture development files
+
+
+%prep
+%setup -q 
+
+%build
+
+autoreconf -vfi
+./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS"
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+
+%remove_docs
+
+%files
+%{_libdir}/xorg/modules/input/gesture_drv.so
+
+%files devel
+%{_libdir}/pkgconfig/xorg-gesture.pc
+
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..902f7ad
--- /dev/null
@@ -0,0 +1,37 @@
+#  Copyright 2005 Adam Jackson.
+#
+#  Permission is hereby granted, free of charge, to any person obtaining a
+#  copy of this software and associated documentation files (the "Software"),
+#  to deal in the Software without restriction, including without limitation
+#  on the rights to use, copy, modify, merge, publish, distribute, sub
+#  license, and/or sell copies of the Software, and to permit persons to whom
+#  the Software is furnished to do so, subject to the following conditions:
+#
+#  The above copyright notice and this permission notice (including the next
+#  paragraph) shall be included in all copies or substantial portions of the
+#  Software.
+#
+#  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+#  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+#  FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+#  ADAM JACKSON BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+#  IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+# this is obnoxious:
+# -module lets us name the module exactly how we want
+# -avoid-version prevents gratuitous .0.0.0 version numbers on the end
+# _ladir passes a dummy rpath to libtool so the thing will actually link
+# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
+AM_CFLAGS = $(XORG_CFLAGS)
+
+@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
+@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
+@DRIVER_NAME@_drv_ladir = @inputdir@
+
+INCLUDES=-I$(top_srcdir)/include/
+
+@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+                               @DRIVER_NAME@.h 
+
diff --git a/src/gesture.c b/src/gesture.c
new file mode 100755 (executable)
index 0000000..cf1c32d
--- /dev/null
@@ -0,0 +1,2560 @@
+/**************************************************************************
+
+xserver-xorg-input-gesture
+
+Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+
+Contact: Sung-Jin Park <sj76.park@samsung.com>
+         Sangjin LEE <lsj119@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <linux/input.h>
+#include <linux/types.h>
+
+#include <xf86_OSproc.h>
+
+#include <unistd.h>
+
+#include <xf86.h>
+#include <xf86Xinput.h>
+#include <exevents.h>
+#include <xorgVersion.h>
+#include <xkbsrv.h>
+
+#ifdef HAVE_PROPERTIES
+#include <X11/Xatom.h>
+#include <xserver-properties.h>
+/* 1.6 has properties, but no labels */
+#ifdef AXIS_LABEL_PROP
+#define HAVE_LABELS
+#else
+#undef HAVE_LABELS
+#endif
+
+#endif
+
+#define __DEBUG__
+//#define __DETAIL_DEBUG__
+//#define __DEBUG_EVENT_HANDLER__
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <xorg-server.h>
+#include <xorgVersion.h>
+#include <xf86Module.h>
+#include <X11/Xatom.h>
+#include "gesture.h"
+#include <xorg/mi.h>
+
+//Basic functions
+static InputInfoPtr GesturePreInit(InputDriverPtr  drv, IDevPtr dev, int flags);
+static void GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
+static pointer GesturePlug(pointer module, pointer options, int *errmaj, int  *errmin);
+static void GestureUnplug(pointer p);
+static int GestureControl(DeviceIntPtr    device,int what);
+static int GestureInit(DeviceIntPtr device);
+static void GestureFini(DeviceIntPtr device);
+static void GestureReadInput(InputInfoPtr pInfo);
+
+//other initializers
+ErrorStatus GestureRegionsInit(void);
+
+//event queue handling functions
+ErrorStatus GestureInitEQ(void);
+ErrorStatus GestureFiniEQ(void);
+ErrorStatus GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+ErrorStatus GestureEventsFlush(void);
+void GestureEventsDrop(void);
+
+//utility functions
+ErrorStatus GestureRegionsReinit(void);
+void GestureSetDisable(InputInfoPtr pInfo, int enable);
+WindowPtr GestureGetEventsWindow(void);
+
+//Enqueued event handlers and enabler/disabler
+static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
+static ErrorStatus GestureDisableEventHandler(void);
+static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
+static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
+void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+
+//Gesture recognizer helper
+static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
+static WindowPtr GestureWindowOnXY(int x, int y);
+Bool GestureHasFingerEventMask(int eventType, int num_finger);
+
+//Gesture recognizer and handlers
+void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
+void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
+void GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
+void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
+void GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
+void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
+void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction);
+void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy);
+void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy);
+void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds);
+void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds);
+void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds);
+void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device);
+ErrorStatus GestureFlushOrDrop(void);
+
+#ifdef HAVE_PROPERTIES
+//function related property handling
+static void GestureInitProperty(DeviceIntPtr dev);
+static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly);
+#endif
+
+static Atom prop_gesture_recognizer_onoff = None;
+
+GestureDevicePtr g_pGesture = NULL;
+_X_EXPORT InputDriverRec GESTURE = {
+    1,
+    "gesture",
+    NULL,
+    GesturePreInit,
+    GestureUnInit,
+    NULL,
+    0
+};
+
+static XF86ModuleVersionInfo GestureVersionRec =
+{
+    "gesture",
+    MODULEVENDORSTRING,
+    MODINFOSTRING1,
+    MODINFOSTRING2,
+    XORG_VERSION_CURRENT,
+    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
+    PACKAGE_VERSION_PATCHLEVEL,
+    ABI_CLASS_XINPUT,
+    ABI_XINPUT_VERSION,
+    MOD_CLASS_XINPUT,
+    {0, 0, 0, 0}
+};
+
+_X_EXPORT XF86ModuleData gestureModuleData =
+{
+    &GestureVersionRec,
+    &GesturePlug,
+    &GestureUnplug
+};
+
+static Bool
+PointInBorderSize(WindowPtr pWin, int x, int y)
+{
+    BoxRec box;
+    if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
+       return TRUE;
+
+    return FALSE;
+}
+
+static WindowPtr
+GestureWindowOnXY(int x, int y)
+{
+    WindowPtr pWin;
+    BoxRec box;
+    SpritePtr pSprite;
+    DeviceIntPtr pDev = g_pGesture->master_pointer;
+
+    pSprite = pDev->spriteInfo->sprite;
+    pSprite->spriteTraceGood = 1;      /* root window still there */
+    pWin = RootWindow(pDev)->firstChild;
+
+    while (pWin)
+    {
+       if ((pWin->mapped) &&
+           (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+           (x < pWin->drawable.x + (int)pWin->drawable.width +
+            wBorderWidth(pWin)) &&
+           (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+           (y < pWin->drawable.y + (int)pWin->drawable.height +
+            wBorderWidth (pWin))
+           /* When a window is shaped, a further check
+            * is made to see if the point is inside
+            * borderSize
+            */
+           && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+           && (!wInputShape(pWin) ||
+               RegionContainsPoint(wInputShape(pWin),
+                                   x - pWin->drawable.x,
+                                   y - pWin->drawable.y, &box))
+#ifdef ROOTLESS
+    /* In rootless mode windows may be offscreen, even when
+     * they're in X's stack. (E.g. if the native window system
+     * implements some form of virtual desktop system).
+     */
+               && !pWin->rootlessUnhittable
+#endif
+           )
+       {
+           if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
+           {
+               pSprite->spriteTraceSize += 10;
+               pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+                                   pSprite->spriteTraceSize*sizeof(WindowPtr));
+           }
+           pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+           pWin = pWin->firstChild;
+       }
+       else
+           pWin = pWin->nextSib;
+    }
+    return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
+}
+
+Bool
+GestureHasFingerEventMask(int eventType, int num_finger)
+{
+       Bool ret = FALSE;
+       Mask eventmask = (1L << eventType);
+
+       if( (g_pGesture->grabMask & eventmask) &&
+               (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
+#endif//__DETAIL_DEBUG__
+               return TRUE;
+       }
+
+       if( g_pGesture->eventMask & eventmask )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
+#endif//__DETAIL_DEBUG__
+               return TRUE;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
+#endif//__DETAIL_DEBUG__
+
+       return ret;
+}
+
+void
+GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyFlickEvent fev;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
+               num_of_fingers, distance, duration, direction);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= FlickFilterMask;
+       memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
+       fev.type = GestureNotifyFlick;
+       fev.kind = GestureDone;
+       fev.num_finger = num_of_fingers;
+       fev.distance = distance;
+       fev.duration = duration;
+       fev.direction = direction;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               fev.window = target_win;
+       }
+       else
+       {
+               fev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
+}
+
+void
+GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyTapEvent tev;
+
+       //skip non-tap events and single finger tap
+       if( !tap_repeat || num_finger <= 1 )
+               return;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
+               num_finger, tap_repeat, cx, cy);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= TapFilterMask;
+       memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
+       tev.type = GestureNotifyTap;
+       tev.kind = GestureDone;
+       tev.num_finger = num_finger;
+       tev.tap_repeat = tap_repeat;
+       tev.interval = 0;
+       tev.cx = cx;
+       tev.cy = cy;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               tev.window = target_win;
+       }
+       else
+       {
+               tev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", tev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
+}
+
+void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyPinchRotationEvent prev;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f, distance=%d\n",
+                               num_of_fingers, zoom, angle, distance, cx, cy);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= PinchRotationFilterMask;
+       memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent));
+       prev.type = GestureNotifyPinchRotation;
+       prev.kind = GestureDone;
+       prev.num_finger = num_of_fingers;
+       prev.zoom = XDoubleToFixed(zoom);
+       prev.angle = XDoubleToFixed(angle);
+       prev.distance = distance;
+       prev.cx = cx;
+       prev.cy = cy;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               prev.window = target_win;
+       }
+       else
+       {
+               prev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", prev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev);
+}
+
+void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyHoldEvent hev;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
+                               num_fingers, cx, cy, holdtime, kinds);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= HoldFilterMask;
+       memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
+       hev.type = GestureNotifyHold;
+       hev.kind = kinds;
+       hev.num_finger = num_fingers;
+       hev.holdtime = holdtime;
+       hev.cx = cx;
+       hev.cy = cy;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               hev.window = target_win;
+       }
+       else
+       {
+               hev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
+}
+
+void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyTapNHoldEvent thev;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_TapNHold] num_fingers=%d, cx=%d, cy=%d, interval=%d, holdtime=%d, kinds=%d\n",
+                               num_fingers, cx, cy, interval, holdtime, kinds);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= TapNHoldFilterMask;
+       memset(&thev, 0, sizeof(xGestureNotifyTapNHoldEvent));
+       thev.type = GestureNotifyTapNHold;
+       thev.kind = kinds;
+       thev.num_finger = num_fingers;
+       thev.holdtime = holdtime;
+       thev.cx = cx;
+       thev.cy = cy;
+       thev.interval = interval;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               thev.window = target_win;
+       }
+       else
+       {
+               thev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_TapNHold] thev.window=0x%x, g_pGesture->grabMask=0x%x\n", thev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyTapNHold, GestureTapNHoldMask, (xGestureCommonEvent *)&thev);
+}
+
+void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds)
+{
+       Window target_win;
+       WindowPtr target_pWin;
+       xGestureNotifyPanEvent pev;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Pan] num_fingers=%d, dx=%d, dy=%d, direction=%d, distance=%d, duration=%d, kinds=%d\n",
+                               num_fingers, dx, dy, direction, distance, duration, kinds);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->recognized_gesture |= PanFilterMask;
+       memset(&pev, 0, sizeof(xGestureNotifyPanEvent));
+       pev.type = GestureNotifyPan;
+       pev.kind = kinds;
+       pev.num_finger = num_fingers;
+       pev.direction = direction;
+       pev.distance = distance;
+       pev.duration = duration;
+       pev.dx = dx;
+       pev.dy = dy;
+
+       target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window;
+       target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin;
+
+       if( g_pGesture->grabMask && (target_win != None) )
+       {
+               pev.window = target_win;
+       }
+       else
+       {
+               pev.window = g_pGesture->gestureWin;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureHandleGesture_Pan] pev.window=0x%x, g_pGesture->grabMask=0x%x\n", pev.window, g_pGesture->grabMask);
+#endif//__DETAIL_DEBUG__
+
+       GestureSendEvent(target_pWin, GestureNotifyPan, GesturePanMask, (xGestureCommonEvent *)&pev);
+}
+
+void
+GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
+{
+
+       g_pGesture->recognized_gesture &= ~PinchRotationFilterMask;
+       g_pGesture->filter_mask |= PinchRotationFilterMask;
+       return;
+}
+
+void
+GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
+{
+       static int num_pressed = 0;
+       static int mbits = 0;
+       static int base_area_size = 0;
+       static Time base_time = 0;
+       static int base_x, base_y;
+       Time current_time;
+       Time duration;
+       int distx, disty;
+       int distance, direction;
+       int area_size;
+       int flicked = 0;
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       g_pGesture->fingers[idx].flags |= PressFlagFlick;
+
+                       if( g_pGesture->num_pressed < 2 )
+                               return;
+
+                       if( !base_area_size || g_pGesture->num_pressed > num_pressed )
+                       {
+                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               base_x = g_pGesture->area.extents.x1;
+                               base_y = g_pGesture->area.extents.y1;
+                               base_time = GetTimeInMillis();
+                       }
+                       num_pressed = g_pGesture->num_pressed;
+
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupFlick][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, base_area_size);
+#endif//__DETAIL_DEBUG__
+                       break;
+
+               case ET_Motion:
+                       if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
+                               break;
+
+#ifdef __DETAIL_DEBUG__
+                       if( num_pressed > g_pGesture->num_pressed )
+                       {
+                               ErrorF("[GroupFlick][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+                               //goto cleanup_flick;
+                       }
+#endif//__DETAIL_DEBUG__
+
+                       if( num_pressed < 2 )
+                               return;
+
+                       mbits |= (1 << idx);
+                       if( mbits == (pow(2, num_pressed)-1) )
+                       {
+                               area_size = AREA_SIZE(&g_pGesture->area.extents);
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[M][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, area_size);
+#endif//__DETAIL_DEBUG__
+                               if( ABS(base_area_size - area_size) >= FLICK_AREA_THRESHOLD )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       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);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_flick;
+                               }
+
+                               current_time = GetTimeInMillis();
+                               if( (current_time - base_time) >= FLICK_AREA_TIMEOUT )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       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);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_flick;
+                               }
+                               mbits = 0;
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       if( g_pGesture->num_pressed )
+                               break;
+
+                       duration = GetTimeInMillis() - base_time;
+                       distx = g_pGesture->area.extents.x1 - base_x;
+                       disty = g_pGesture->area.extents.y1 - base_y;
+
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupFlick] duration=%d, distx=%d, disty=%d\n", duration, distx, disty);
+#endif//__DETAIL_DEBUG__
+
+                       if( duration <= 0 || duration >= FLICK_AREA_TIMEOUT )
+                               goto cleanup_flick;
+
+                       if( ABS(distx) >= FLICK_MOVE_THRESHOLD )
+                       {
+                               direction = (distx > 0) ? FLICK_EASTWARD : FLICK_WESTWARD;
+                               distance = ABS(distx);
+                               flicked++;
+                       }
+                       else if( ABS(disty) >= FLICK_MOVE_THRESHOLD )
+                       {
+                               direction = (disty > 0) ? FLICK_SOUTHWARD : FLICK_NORTHWARD;
+                               distance = ABS(disty);
+                               flicked++;
+                       }
+
+                       if( !flicked )
+                               goto cleanup_flick;
+
+                       if( GestureHasFingerEventMask(GestureNotifyFlick, num_pressed) )
+                               GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
+                       goto cleanup_flick_recognized;
+                       break;
+       }
+
+       return;
+
+cleanup_flick:
+
+       g_pGesture->recognized_gesture &= ~FlickFilterMask;
+
+cleanup_flick_recognized:
+
+       g_pGesture->filter_mask |= FlickFilterMask;
+       num_pressed = 0;
+       base_area_size = 0;
+       base_time = 0;
+       mbits = 0;
+       return;
+}
+
+void
+GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+{
+       static int num_pressed = 0;
+       static int mbits = 0;
+       static int base_area_size = 0;
+       static Time base_time = 0;
+       static pixman_box16_t base_box_ext;
+       static int base_cx;
+       static int base_cy;
+       static int prev_cx;
+       static int prev_cy;
+       static int cx = 0;
+       static int cy = 0;
+       int dx, dy;
+       static Time prev_time = 0;
+       Time current_time = 0;
+       int distance = 0;
+       int direction = 0;
+       int area_size;
+       static int time_checked = 0;
+       static int state = GestureEnd;
+
+       static OsTimerPtr pan_event_timer = NULL;
+       static int event_type = GestureNotifyPan;
+
+       if( timer_expired )
+       {
+               if( !time_checked )
+               {
+                       current_time = GetTimeInMillis();
+                       if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
+                       {
+                               if( (!cx && !cy) || INBOX(&base_box_ext, cx, cy) )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupPan][Timer] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_pan;
+                               }
+                               time_checked = 1;
+                       }
+               }
+               return;
+       }
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       g_pGesture->fingers[idx].flags |= PressFlagPan;
+
+                       if( g_pGesture->num_pressed < 2 )
+                               return;
+
+                       if( !base_area_size || g_pGesture->num_pressed > num_pressed )
+                       {
+                               if( state != GestureEnd )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupPan][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_pan;
+                               }
+                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               prev_cx = base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               prev_cy = base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                               prev_time = base_time = GetTimeInMillis();
+                               base_box_ext.x1 = base_cx-PAN_MOVE_THRESHOLD;
+                               base_box_ext.y1 = base_cy-PAN_MOVE_THRESHOLD;
+                               base_box_ext.x2 = base_cx+PAN_MOVE_THRESHOLD;
+                               base_box_ext.y2 = base_cy+PAN_MOVE_THRESHOLD;
+                               event_type = GestureNotifyPan;
+                               pan_event_timer = TimerSet(pan_event_timer, 0, PAN_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                       }
+                       num_pressed = g_pGesture->num_pressed;
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+                       break;
+
+               case ET_Motion:
+                       if( !(g_pGesture->fingers[idx].flags & PressFlagPan ) )
+                               break;
+
+                       if( num_pressed != g_pGesture->num_pressed )
+                       {
+                               if( state != GestureEnd )
+                               {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupPan][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_pan;
+                               }
+                       }
+
+                       if( num_pressed < 2 )
+                               return;
+
+                       mbits |= (1 << idx);
+                       if( mbits == (pow(2, num_pressed)-1) )
+                       {
+                               area_size = AREA_SIZE(&g_pGesture->area.extents);
+#ifdef __DETAIL_DEBUG__
+                               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));
+#endif//__DETAIL_DEBUG__
+
+                               if( (state != GestureUpdate) && (ABS(base_area_size - area_size) >= PAN_AREA_THRESHOLD) )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       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);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_pan;
+                               }
+
+                               cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupPan][M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx));
+                               ErrorF("[GroupPan][M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy));
+#endif//__DETAIL_DEBUG__
+
+                               if( !time_checked )
+                               {
+                                       current_time = GetTimeInMillis();
+                                       if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
+                                       {
+                                               if( INBOX(&base_box_ext, cx, cy) )
+                                               {
+#ifdef __DETAIL_DEBUG__
+                                                       ErrorF("[GroupPan][M] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
+#endif//__DETAIL_DEBUG__
+                                                       goto cleanup_pan;
+                                               }
+                                               time_checked = 1;
+                                       }
+                               }
+
+                               if( time_checked )
+                               {
+                                       if( state <= GestureBegin )
+                                       {
+                                               base_box_ext.x1 = prev_cx-PAN_MOVE_THRESHOLD;
+                                               base_box_ext.y1 = prev_cy-PAN_MOVE_THRESHOLD;
+                                               base_box_ext.x2 = prev_cx+PAN_MOVE_THRESHOLD;
+                                               base_box_ext.y2 = prev_cy+PAN_MOVE_THRESHOLD;
+
+                                               if( !INBOX(&base_box_ext, cx, cy) )
+                                               {
+                                                       current_time = GetTimeInMillis();
+#ifdef __DETAIL_DEBUG__
+                                                       ErrorF("[GroupPan] PAN Begin !dx=%d, dy=%d, state=%d\n", prev_cx, prev_cy, state);
+#endif//__DETAIL_DEBUG__
+                                                       if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
+                                                       {
+                                                               GestureHandleGesture_Pan(num_pressed, prev_cx, prev_cy, direction, distance, current_time-prev_time, GestureBegin);
+                                                               state = GestureUpdate;
+                                                       }
+                                                       else
+                                                               goto cleanup_pan;
+                                               }
+                                       }
+                                       else
+                                       {
+                                               dx = cx-prev_cx;
+                                               dy = cy-prev_cy;
+                                               //if( ABS(dx) >= PAN_UPDATE_MOVE_THRESHOLD || ABS(dy) >= PAN_UPDATE_MOVE_THRESHOLD )
+                                               {
+#ifdef __DETAIL_DEBUG__
+                                                       ErrorF("[GroupPan] PAN Update !dx=%d, dy=%d, state=%d\n", dx, dy, state);
+#endif//__DETAIL_DEBUG__
+
+                                                       GestureHandleGesture_Pan(num_pressed, dx, dy, direction, distance, current_time-prev_time, GestureUpdate);
+                                               }
+                                       }
+                                       prev_cx = cx;
+                                       prev_cy = cy;
+                                       prev_time = current_time;
+                               }
+                               mbits = 0;
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       if( state != GestureEnd && num_pressed >= 2)
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupPan][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_pan;
+                       }
+
+                       if( g_pGesture->num_pressed )
+                               break;
+
+                       goto cleanup_pan;
+                       break;
+       }
+
+       return;
+
+cleanup_pan:
+
+       if( state == GestureBegin || state == GestureUpdate )
+       {
+               state = GestureEnd;
+               if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
+               {
+                       GestureHandleGesture_Pan(num_pressed, (short int)(cx-prev_cx), (short int)(cy-prev_cy), direction, distance, GetTimeInMillis()-prev_time, GestureEnd);
+               }
+       }
+       else
+       {
+               g_pGesture->recognized_gesture &= ~PanFilterMask;
+       }
+
+       g_pGesture->filter_mask |= PanFilterMask;
+       num_pressed = 0;
+       base_area_size = 0;
+       base_time = 0;
+       mbits = 0;
+       time_checked = 0;
+       state = GestureEnd;
+       cx = cy = 0;
+       prev_time = 0;
+       base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
+       TimerCancel(pan_event_timer);
+       return;
+}
+
+void
+GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+{
+       static int num_pressed = 0;
+       static int base_area_size = 0;
+
+       static Time base_time = 0;
+       Time current_time;
+
+       int cx, cy;
+       int area_size;
+
+       static int state = 0;
+       static int mbits = 0;
+       static int base_cx;
+       static int base_cy;
+       static pixman_box16_t base_box_ext;
+
+       static int tap_repeat = 0;
+       static int prev_tap_repeat = 0;
+       static int prev_num_pressed = 0;
+
+       static OsTimerPtr tap_event_timer = NULL;
+       static int event_type = GestureNotifyTap;
+
+       if( timer_expired )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[GroupTap][Timer] state=%d\n", state);
+#endif//__DETAIL_DEBUG__
+
+               switch( state )
+               {
+                       case 1://first tap initiation check
+                               if( num_pressed )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
+#endif//__DETAIL_DEBUG__
+                                       state = 0;
+                                       goto cleanup_tap;
+                               }
+                               break;
+
+                       case 2:
+                               if( tap_repeat <= 1 )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupTap][Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       state = 0;
+                                       goto cleanup_tap;
+                               }
+
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTap][Timer][state=2]  tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed);
+#endif//__DETAIL_DEBUG__
+                               if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
+                                       GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
+                               goto cleanup_tap;
+                               break;
+               }
+
+               return;
+       }
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       g_pGesture->fingers[idx].flags |= PressFlagTap;
+
+                       if( g_pGesture->num_pressed < 2 )
+                               return;
+
+                       if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
+                       {
+                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                               base_time = GetTimeInMillis();
+                               base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
+                               base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
+                               base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
+                               base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
+                               state = 1;
+                               TimerCancel(tap_event_timer);
+                               tap_event_timer = TimerSet(tap_event_timer, 0, SGL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                       }
+
+                       num_pressed = g_pGesture->num_pressed;
+
+                       current_time = GetTimeInMillis();
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+                       break;
+
+               case ET_Motion:
+                       if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) )
+                               break;
+
+                       if( num_pressed < 2 )
+                               return;
+
+                       if( num_pressed != g_pGesture->num_pressed )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTap][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               //goto cleanup_tap;
+                       }
+
+                       mbits |= (1 << idx);
+                       if( mbits == (pow(2, num_pressed)-1) )
+                       {
+                               area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+#ifdef __DETAIL_DEBUG__
+                               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));
+                               ErrorF("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
+                               ErrorF("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
+#endif//__DETAIL_DEBUG__
+
+                               if( ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       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));
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tap;
+                               }
+
+                               if( !INBOX(&base_box_ext, cx, cy) )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tap;
+                               }
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       if( g_pGesture->num_pressed )
+                               break;
+
+                       if( !tap_repeat )
+                       {
+                               prev_num_pressed = num_pressed;
+                       }
+
+                       prev_tap_repeat = tap_repeat;
+                       tap_repeat++;
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+
+                       if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
+                                       num_pressed, prev_num_pressed, num_pressed);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_tap;
+                       }
+
+                       if( tap_repeat < MAX_TAP_REPEATS )
+                       {
+                               state = 2;
+                               TimerCancel(tap_event_timer);
+                               tap_event_timer = TimerSet(tap_event_timer, 0, DBL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                               num_pressed = 0;
+                               break;
+                       }
+
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupTap][R] %d finger %s\n", num_pressed, (tap_repeat==2) ? "DBL_TAP" : "TRIPLE_TAP");
+#endif//__DETAIL_DEBUG__
+
+                       if( GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
+                               GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
+
+                       if( tap_repeat >= MAX_TAP_REPEATS )
+                       {
+                               goto cleanup_tap;
+                       }
+
+                       prev_num_pressed = num_pressed;
+                       num_pressed = 0;
+                       break;
+       }
+
+       return;
+
+cleanup_tap:
+
+       if( 0 == state )
+               g_pGesture->recognized_gesture &= ~TapFilterMask;
+       g_pGesture->filter_mask |= TapFilterMask;
+
+       if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
+#endif//__DETAIL_DEBUG__
+
+               if( ERROR_INVALPTR == GestureFlushOrDrop() )
+               {
+                       GestureControl(g_pGesture->this_device, DEVICE_OFF);
+               }
+       }
+
+       num_pressed = 0;
+       tap_repeat = 0;
+       prev_num_pressed = 0;
+       mbits = 0;
+       base_time = 0;
+       state = 0;
+       TimerCancel(tap_event_timer);
+       return;
+}
+
+void
+GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+{
+       static int num_pressed = 0;
+       static int base_area_size = 0;
+       static Time base_time = 0;
+       static int base_cx;
+       static int base_cy;
+       int cx, cy;
+       static pixman_box16_t base_box_ext;
+       int area_size;
+       static int mbits = 0;
+
+       static int tap_repeat = 0;
+       static int prev_num_pressed = 0;
+
+       static OsTimerPtr tapnhold_event_timer = NULL;
+       static int event_type = GestureNotifyTapNHold;
+       static int state = GestureEnd;
+
+       Time interval = 0;
+       Time holdtime = 0;
+
+       if( timer_expired )
+       {
+               if( (state == GestureEnd) && num_pressed )
+               {
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupTapNHold][Timer][state=%d] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", GestureEnd, tap_repeat, num_pressed, tap_repeat);
+#endif//__DETAIL_DEBUG__
+                       state = 0;
+                       goto cleanup_tapnhold;
+               }
+
+               if( state == GestureDone )
+               {
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupTapNHold][Timer][state=%d] Interval between Tap and Hold is too long !\n");
+#endif//__DETAIL_DEBUG__
+                       goto cleanup_tapnhold;
+               }
+
+#ifdef __DETAIL_DEBUG__
+               switch( state )
+               {
+                       case GestureBegin:
+                               ErrorF("[GroupTapNHold][Timer] TapNHold Begin !\n");
+                               break;
+
+                       case GestureUpdate:
+                               ErrorF("[GroupTapNHold][Timer] TapNHold Update !\n");
+                               break;
+               }
+#endif//__DETAIL_DEBUG__
+
+               if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
+               {
+                       GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
+                       tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+               }
+               else
+               {
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupTapNHold][Timer] %d finger TapNHold event was not grabbed/selected !\n", prev_num_pressed);
+#endif//__DETAIL_DEBUG__
+                       goto cleanup_tapnhold;
+               }
+
+               if( state <= GestureBegin )
+                       state++;
+               return;
+       }
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       g_pGesture->fingers[idx].flags |= PressFlagTapNHold;
+
+                       if( g_pGesture->num_pressed < 2 )
+                               return;
+
+                       //if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
+                       if( !base_area_size || g_pGesture->num_pressed > num_pressed )
+                       {
+
+                               if( state == GestureUpdate )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupTapNHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tapnhold;
+                               }
+
+                               if( state == GestureDone )
+                                       state = GestureBegin;
+
+                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                               base_time = GetTimeInMillis();
+                               base_box_ext.x1 = base_cx-TAPNHOLD_MOVE_THRESHOLD;
+                               base_box_ext.y1 = base_cy-TAPNHOLD_MOVE_THRESHOLD;
+                               base_box_ext.x2 = base_cx+TAPNHOLD_MOVE_THRESHOLD;
+                               base_box_ext.y2 = base_cy+TAPNHOLD_MOVE_THRESHOLD;
+                               if( state == GestureEnd )
+                                       tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                               else
+                               {
+                                       TimerCancel(tapnhold_event_timer);
+                                       tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                               }
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][P] Create Timer !(state=%d)\n", state);
+#endif//__DETAIL_DEBUG__
+                       }
+
+                       num_pressed = g_pGesture->num_pressed;
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+                       break;
+
+               case ET_Motion:
+                       if( !(g_pGesture->fingers[idx].flags & PressFlagTapNHold ) )
+                               break;
+
+                       if( num_pressed < 2 )
+                               return;
+
+                       if( num_pressed != g_pGesture->num_pressed )
+                       {
+                               if( state != GestureEnd )
+                               {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tapnhold;
+                               }
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               //goto cleanup_tapnhold;
+                       }
+
+                       mbits |= (1 << idx);
+                       if( mbits == (pow(2, num_pressed)-1) )
+                       {
+                               area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+#ifdef __DETAIL_DEBUG__
+                               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));
+                               ErrorF("[GroupTapNHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
+                               ErrorF("[GroupTapNHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
+#endif//__DETAIL_DEBUG__
+
+                               if( ABS(base_area_size-area_size) >= TAPNHOLD_AREA_THRESHOLD )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       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));
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tapnhold;
+                               }
+
+                               if( !INBOX(&base_box_ext, cx, cy) )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupTapNHold][M] current center coordinates is not in base coordinates box !\n");
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_tapnhold;
+                               }
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       if( state != GestureEnd && num_pressed >= 2)
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_tapnhold;
+                       }
+
+                       if( g_pGesture->num_pressed )
+                               break;
+
+                       if( !tap_repeat )
+                       {
+                               prev_num_pressed = num_pressed;
+                       }
+
+                       tap_repeat++;
+
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GroupTapNHold][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
+#endif//__DETAIL_DEBUG__
+
+                       if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTapNHold, num_pressed) )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
+                                       num_pressed, prev_num_pressed, num_pressed);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_tapnhold;
+                       }
+
+                       if( tap_repeat > 1 )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupTapNHold][R] Tap events(tap_repeat=%d) were put twice or more !(ignored)\n", tap_repeat);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_tapnhold;
+                       }
+
+                       prev_num_pressed = num_pressed;
+                       num_pressed = 0;
+                       state = GestureDone;
+
+                       TimerCancel(tapnhold_event_timer);
+                       tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_INTV_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+                       break;
+       }
+
+       return;
+
+cleanup_tapnhold:
+
+       if( state == GestureUpdate )
+       {
+               state = GestureEnd;
+               if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
+               {
+                       GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
+               }
+       }
+       else
+       {
+               g_pGesture->recognized_gesture &= ~TapNHoldFilterMask;
+       }
+
+       g_pGesture->filter_mask |= TapNHoldFilterMask;
+       if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[GroupTapNHold][cleanup] GestureFlushOrDrop() !\n");
+#endif//__DETAIL_DEBUG__
+
+               if( ERROR_INVALPTR == GestureFlushOrDrop() )
+               {
+                       GestureControl(g_pGesture->this_device, DEVICE_OFF);
+               }
+       }
+
+       TimerCancel(tapnhold_event_timer);
+       num_pressed = 0;
+       tap_repeat = 0;
+       prev_num_pressed = 0;
+       mbits = 0;
+       base_time = 0;
+       state = 0;
+
+       return;
+}
+
+void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+{
+       static int num_pressed = 0;
+       static int base_area_size = 0;
+       static Time base_time = 0;
+       static int base_cx;
+       static int base_cy;
+       int cx, cy;
+       static pixman_box16_t base_box_ext;
+       int area_size;
+       static int state = GestureEnd;
+
+       static OsTimerPtr hold_event_timer = NULL;
+       static int event_type = GestureNotifyHold;
+
+       if( timer_expired )
+       {
+               if( state <= GestureBegin )
+                       state++;
+
+#ifdef __DETAIL_DEBUG__
+               switch( state )
+               {
+                       case GestureBegin:
+                               ErrorF("[GroupHold] HOLD Begin !\n");
+                               break;
+
+                       case GestureUpdate:
+                               ErrorF("[GroupHold] HOLD Update !\n");
+                               break;
+               }
+#endif//__DETAIL_DEBUG__
+
+               if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
+               {
+                       GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
+                       hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+               }
+               return;
+       }
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       g_pGesture->fingers[idx].flags |= PressFlagHold;
+
+                       if( g_pGesture->num_pressed < 2 )
+                               return;
+
+                       if( !base_area_size || g_pGesture->num_pressed > num_pressed )
+                       {
+                               if( state != GestureEnd )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[GroupHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_hold;
+                               }
+
+                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                               base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                               base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                               base_time = GetTimeInMillis();
+                               base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
+                               base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
+                               base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
+                               base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
+                               event_type = GestureNotifyHold;
+                               hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
+                       }
+                       num_pressed = g_pGesture->num_pressed;
+
+#ifdef __DETAIL_DEBUG__
+                       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);
+#endif//__DETAIL_DEBUG__
+                       break;
+
+               case ET_Motion:
+                       if( !(g_pGesture->fingers[idx].flags & PressFlagHold ) )
+                               break;
+
+                       if( num_pressed < 2 )
+                               return;
+
+                       if( num_pressed != g_pGesture->num_pressed )
+                       {
+                               if( state != GestureEnd )
+                               {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       goto cleanup_hold;
+                               }
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               //goto cleanup_hold;
+                       }
+
+                       area_size = AREA_SIZE(&g_pGesture->area.extents);
+                       cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                       cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+#ifdef __DETAIL_DEBUG__
+                       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));
+                       ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
+                       ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
+#endif//__DETAIL_DEBUG__
+
+                       if( ABS(base_area_size-area_size) >= HOLD_AREA_THRESHOLD )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               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));
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_hold;
+                       }
+
+                       if( !INBOX(&base_box_ext, cx, cy) )
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupHold][M] current center coordinates is not in base coordinates box !\n");
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_hold;
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       if( state != GestureEnd && num_pressed >= 2)
+                       {
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[GroupHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                               goto cleanup_hold;
+                       }
+
+                       //ErrorF("[GroupHold][R] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+                       if( g_pGesture->num_pressed )
+                               break;
+
+                       goto cleanup_hold;
+                       break;
+       }
+
+       return;
+
+cleanup_hold:
+
+       if( state == GestureBegin || state == GestureUpdate )
+       {
+               state = GestureEnd;
+               if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
+               {
+                       GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
+               }
+       }
+       else
+       {
+               g_pGesture->recognized_gesture &= ~HoldFilterMask;
+       }
+
+       g_pGesture->filter_mask |= HoldFilterMask;
+       num_pressed = 0;
+       base_area_size = 0;
+       base_time = 0;
+       base_cx = base_cy = 0;
+       state = GestureEnd;
+       base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
+       TimerCancel(hold_event_timer);
+       return;
+}
+
+WindowPtr
+GestureGetEventsWindow(void)
+{
+       Mask mask;
+       WindowPtr pWin;
+
+       //check grabbed event(s)
+       if( !GestureHasGrabbedEvents(&g_pGesture->grabMask, &g_pGesture->GrabEvents) )
+               g_pGesture->grabMask = 0;
+
+       pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
+
+       if( pWin )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
+#endif//__DETAIL_DEBUG__
+               g_pGesture->gestureWin = pWin->drawable.id;
+       }
+       else
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
+#endif//__DETAIL_DEBUG__
+               return NULL;
+       }
+
+       //check selected event(s)
+       if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) )
+               g_pGesture->eventMask = 0;
+
+       if( !g_pGesture->grabMask && !g_pGesture->eventMask )
+       {
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureGetEventsWindow] No events were grabbed/selected for window(0x%x) !\n", pWin->drawable.id);
+#endif//__DETAIL_DEBUG__
+               return NULL;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->grabMask=0x%x, g_pGesture->eventMask=0x%x\n",
+                       g_pGesture->grabMask, g_pGesture->eventMask);
+#endif//__DETAIL_DEBUG__
+
+       mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->filter_mask = mask;
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
+#endif//__DETAIL_DEBUG__
+
+       return pWin;
+}
+
+static CARD32
+GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+       int event_type = *(int *)arg;
+
+       switch( event_type )
+       {
+               case GestureNotifyHold:
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
+#endif//__DETAIL_DEBUG__
+                       GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
+                       break;
+
+               case GestureNotifyPan:
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GestureEventTimerHandler] GestureNotifyPan (event_type = %d)\n", event_type);
+#endif//__DETAIL_DEBUG__
+                       GestureRecognize_GroupPan(event_type, NULL, NULL, 0, 1);
+                       break;
+
+               case GestureNotifyTap:
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
+#endif//__DETAIL_DEBUG__
+                       GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
+                       break;
+
+               case GestureNotifyTapNHold:
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GestureEventTimerHandler] GestureNotifyTapNHold (event_type = %d)\n", event_type);
+#endif//__DETAIL_DEBUG__
+                       GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1);
+                       break;
+
+               default:
+#ifdef __DETAIL_DEBUG__
+                       ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
+#endif//__DETAIL_DEBUG__
+                       if(timer)
+                               ErrorF("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer);
+       }
+
+       return 0;
+}
+
+static CARD32
+GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+       g_pGesture->recognized_gesture = 0;
+
+       if( ERROR_INVALPTR == GestureFlushOrDrop() )
+       {
+               GestureControl(g_pGesture->this_device, DEVICE_OFF);
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][Single] expired !\n");
+#endif//__DETAIL_DEBUG__
+
+       return 0;
+}
+
+void
+GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
+{
+       int i;
+       int idx = device->id - g_pGesture->first_fingerid;
+       static OsTimerPtr single_finger_timer = NULL;
+
+       if( PROPAGATE_EVENTS == g_pGesture->ehtype )
+               return;
+
+       if( device->id < g_pGesture->first_fingerid )//filtering device id : 2
+               return;
+
+       switch( type )
+       {
+               case ET_ButtonPress:
+                       if( idx == 0 )
+                               g_pGesture->event_sum[0] = BTN_PRESSED;
+                       g_pGesture->fingers[idx].ptime = ev->any.time;
+                       g_pGesture->fingers[idx].px = ev->device_event.root_x;
+                       g_pGesture->fingers[idx].py = ev->device_event.root_y;
+
+                       g_pGesture->num_pressed++;
+                       if( g_pGesture->num_pressed == 1 )
+                       {
+                               single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
+                       }
+                       else
+                       {
+                               TimerCancel(single_finger_timer);
+                       }
+
+                       if( g_pGesture->num_pressed > g_pGesture->num_mt_devices )
+                               g_pGesture->num_pressed = g_pGesture->num_mt_devices;
+
+                       if( !g_pGesture->pTempWin || g_pGesture->num_pressed != g_pGesture->inc_num_pressed )
+                       {
+                               g_pGesture->pTempWin = GestureGetEventsWindow();
+
+                               if( NULL == g_pGesture->pTempWin )
+                               {
+#ifdef __DETAIL_DEBUG__
+                                       ErrorF("[X11][GestureRecognize][g_pGesture->num_pressed=%d] No grabbed events and no event masks !\n", g_pGesture->num_pressed);
+#endif//__DETAIL_DEBUG__
+                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+                                       goto flush_or_drop;
+                               }
+                       }
+
+                       g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
+
+                       g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
+                       g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
+                       g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
+                       g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
+
+                       if( g_pGesture->inc_num_pressed == 1 )
+                       {
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
+#endif//__DETAIL_DEBUG__
+                       }
+                       else
+                       {
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
+                               {
+                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
+                               }
+#ifdef __DETAIL_DEBUG__
+                               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));
+#endif//__DETAIL_DEBUG__
+                       }
+                       break;
+
+               case ET_Motion:
+                       if( !g_pGesture->fingers[idx].ptime )
+                               return;
+
+                       g_pGesture->fingers[idx].mx = ev->device_event.root_x;
+                       g_pGesture->fingers[idx].my = ev->device_event.root_y;
+
+                       if( idx == 0 && g_pGesture->event_sum[0] )
+                       {
+                               g_pGesture->event_sum[0] += BTN_MOVING;
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[X11][GestureRecognize] moving !\n");
+#endif//__DETAIL_DEBUG__
+                               if( g_pGesture->event_sum[0] >= 7 )
+                               {
+                               if( (g_pGesture->event_sum[0] >= 7) && (g_pGesture->inc_num_pressed < 2) )
+                                {
+ #ifdef __DETAIL_DEBUG__
+                                       ErrorF("[X11][GestureRecognize] moving limit!\n");
+ #endif//__DETAIL_DEBUG__
+                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+                                           goto flush_or_drop;
+                                }
+                               }
+                       }
+
+                       g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
+                       g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
+                       g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
+                       g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
+
+                       if( g_pGesture->inc_num_pressed == 1 )
+                       {
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
+#endif//__DETAIL_DEBUG__
+                       }
+                       else
+                       {
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
+                               {
+                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
+                               }
+#ifdef __DETAIL_DEBUG__
+                               ErrorF("[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
+#endif//__DETAIL_DEBUG__
+                       }
+                       break;
+
+               case ET_ButtonRelease:
+                       g_pGesture->fingers[idx].rtime = ev->any.time;
+                       g_pGesture->fingers[idx].rx = ev->device_event.root_x;
+                       g_pGesture->fingers[idx].ry = ev->device_event.root_y;
+
+                       g_pGesture->num_pressed--;
+                       if( g_pGesture->num_pressed <= 0 )
+                       {
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureRecognize] All fingers were released !\n");
+#endif//__DETAIL_DEBUG__
+                               if( g_pGesture->inc_num_pressed == 1 )
+                                       goto flush_or_drop;
+                       }
+                       break;
+       }
+
+       if( g_pGesture->filter_mask != GESTURE_FILTER_MASK_ALL )
+       {
+               if( !(g_pGesture->filter_mask & FlickFilterMask) )
+               {
+                       GestureRecognize_GroupFlick(type, ev, device, idx);
+               }
+               if( !(g_pGesture->filter_mask & PanFilterMask) )
+               {
+                       GestureRecognize_GroupPan(type, ev, device, idx, 0);
+               }
+               if( !(g_pGesture->filter_mask & PinchRotationFilterMask) )
+               {
+                       GestureRecognize_GroupPinchRotation(type, ev, device, idx);
+               }
+               if( !(g_pGesture->filter_mask & TapFilterMask) )
+               {
+                       GestureRecognize_GroupTap(type, ev, device, idx, 0);
+               }
+               if( !(g_pGesture->filter_mask & TapNHoldFilterMask) )
+               {
+                       GestureRecognize_GroupTapNHold(type, ev, device, idx, 0);
+               }
+               if( !(g_pGesture->filter_mask & HoldFilterMask) )
+               {
+                       GestureRecognize_GroupHold(type, ev, device, idx, 0);
+               }
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureRecognize][N] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
+       ErrorF("[X11][GestureRecognize][N] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
+       ErrorF("[X11][GestureRecognize][N] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
+#endif//__DETAIL_DEBUG__
+
+       if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
+       {
+               if( !g_pGesture->recognized_gesture )
+                       goto flush_or_drop;
+               else if( !g_pGesture->num_pressed )
+                       goto flush_or_drop;
+       }
+
+       if( g_pGesture->recognized_gesture )
+       {
+               if( g_pGesture->ehtype == KEEP_EVENTS )
+                       GestureEventsDrop();
+               g_pGesture->ehtype = IGNORE_EVENTS;
+       }
+
+       return;
+
+flush_or_drop:
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[GestureRecognize] GestureFlushOrDrop() !\n");
+#endif//__DETAIL_DEBUG__
+       if( ERROR_INVALPTR == GestureFlushOrDrop() )
+       {
+               GestureControl(g_pGesture->this_device, DEVICE_OFF);
+       }
+}
+
+
+ErrorStatus GestureFlushOrDrop(void)
+{
+       ErrorStatus err;
+
+       if( g_pGesture->recognized_gesture )
+       {
+               GestureEventsDrop();
+       }
+       else
+       {
+               g_pGesture->ehtype = PROPAGATE_EVENTS;
+
+               err = GestureEventsFlush();
+               if( ERROR_NONE != err )
+                       return err;
+
+#ifdef __DETAIL_DEBUG__
+               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
+               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
+               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
+#endif//__DETAIL_DEBUG__
+       }
+
+       err = GestureRegionsReinit();
+       if( ERROR_NONE != err )
+               return err;
+
+       g_pGesture->pTempWin = NULL;
+       g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
+       g_pGesture->event_sum[0] = 0;
+
+       return ERROR_NONE;
+}
+
+void
+GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+       int i;
+
+#ifdef __DEBUG_EVENT_HANDLER__
+       ErrorF("\n[X11][GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
+                       ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
+#endif//__DEBUG_EVENT_HANDLER__
+
+       if( MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync )
+       {
+               g_pGesture->ehtype = KEEP_EVENTS;
+               g_pGesture->filter_mask = 0;
+               g_pGesture->recognized_gesture = 0;
+               g_pGesture->num_pressed = 0;
+
+               for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
+                       g_pGesture->fingers[i].ptime = 0;
+       }
+       else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
+       {
+               g_pGesture->ehtype = PROPAGATE_EVENTS;
+       }
+}
+
+void
+GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+#ifdef __DEBUG_EVENT_HANDLER__
+       ErrorF("[X11][GestureHandleButtonPEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
+#endif//__DEBUG_EVENT_HANDLER__
+
+       switch( g_pGesture->ehtype )
+       {
+               case KEEP_EVENTS:
+                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
+                       {
+                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                               return;
+                       }
+
+                       if( g_pGesture->num_mt_devices )
+                               GestureRecognize(ET_ButtonPress, ev, device);
+                       else
+                               device->public.processInputProc(ev, device);
+                       break;
+
+               case PROPAGATE_EVENTS:
+                       device->public.processInputProc(ev, device);
+                       break;
+
+               case IGNORE_EVENTS:
+                       GestureRecognize(ET_ButtonPress, ev, device);
+                       break;
+
+               default:
+                       break;
+       }
+}
+
+void
+GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+#ifdef __DEBUG_EVENT_HANDLER__
+       ErrorF("[X11][GestureHandleMotionEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
+#endif//__DEBUG_EVENT_HANDLER__
+
+       switch( g_pGesture->ehtype )
+       {
+               case KEEP_EVENTS:
+                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
+                       {
+                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                               return;
+                       }
+
+                       if( g_pGesture->num_mt_devices )
+                               GestureRecognize(ET_Motion, ev, device);
+                       else
+                               device->public.processInputProc(ev, device);
+                       break;
+
+               case PROPAGATE_EVENTS:
+                       device->public.processInputProc(ev, device);
+                       break;
+
+               case IGNORE_EVENTS:
+                       GestureRecognize(ET_Motion, ev, device);
+                       break;
+
+               default:
+                       break;
+       }
+
+}
+
+void
+GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+#ifdef __DEBUG_EVENT_HANDLER__
+       ErrorF("[X11][GestureHandleButtonREvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
+#endif//__DEBUG_EVENT_HANDLER__
+
+       switch( g_pGesture->ehtype )
+       {
+               case KEEP_EVENTS:
+                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
+                       {
+                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                               return;
+                       }
+
+                       if( g_pGesture->num_mt_devices )
+                               GestureRecognize(ET_ButtonRelease, ev, device);
+                       else
+                               device->public.processInputProc(ev, device);
+                       break;
+
+               case PROPAGATE_EVENTS:
+                       device->public.processInputProc(ev, device);
+                       break;
+
+               case IGNORE_EVENTS:
+                       GestureRecognize(ET_ButtonRelease, ev, device);
+                       break;
+
+               default:
+                       break;
+       }
+}
+
+static ErrorStatus
+GestureEnableEventHandler(InputInfoPtr pInfo)
+ {
+       Bool res;
+       GestureDevicePtr pGesture = pInfo->private;
+
+       res = GestureInstallResourceStateHooks();
+
+       if( !res )
+       {
+               ErrorF("[X11][GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
+               return ERROR_ABNORMAL;
+       }
+
+       res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
+
+       if( !res )
+       {
+               ErrorF("[X11][GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
+               goto failed;
+       }
+
+       pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 500, GestureTimerHandler, pInfo);
+
+       if( !pGesture->device_setting_timer )
+       {
+               ErrorF("[X11][GestureEnableEventHandler] Failed to allocate memory for timer !\n");
+               goto failed;
+       }
+
+       if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
+       {
+               goto failed;
+       }
+
+       mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
+       mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
+       mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
+       if( pGesture->is_active )
+               mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
+
+       return ERROR_NONE;
+
+failed:
+       GestureUninstallResourceStateHooks();
+       GestureUnsetMaxNumberOfFingers();
+
+       return ERROR_ABNORMAL;
+}
+
+static ErrorStatus
+GestureDisableEventHandler(void)
+{
+       ErrorStatus err = ERROR_NONE;
+
+       mieqSetHandler(ET_ButtonPress, NULL);
+       mieqSetHandler(ET_ButtonRelease, NULL);
+       mieqSetHandler(ET_Motion, NULL);
+       mieqSetHandler(ET_MTSync, NULL);
+
+       err = GestureFiniEQ();
+
+       if( ERROR_INVALPTR == err )
+       {
+               ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
+       }
+
+       GestureUninstallResourceStateHooks();
+       GestureUnsetMaxNumberOfFingers();
+
+       return err;
+}
+
+static CARD32
+GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+       InputInfoPtr pInfo = (InputInfoPtr)arg;
+       GestureDevicePtr pGesture = pInfo->private;
+
+       int idx = 0;
+       DeviceIntPtr dev;
+       for( dev = inputInfo.pointer ; dev; dev = dev->next )
+       {
+               if(IsMaster(dev) && IsPointerDevice(dev))
+               {
+                       pGesture->master_pointer = dev;
+                       ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
+                       continue;
+               }
+
+               if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
+               {
+                       pGesture->xtest_pointer = dev;
+                       ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
+                       continue;
+               }
+
+               if(IsPointerDevice(dev))
+               {
+                       if( idx >= MAX_MT_DEVICES )
+                       {
+                               ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
+                                       MAX_MT_DEVICES);
+                               continue;
+                       }
+                       pGesture->mt_devices[idx] = dev;
+                       ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
+                       idx++;
+               }
+       }
+
+       if( !pGesture->master_pointer || !pGesture->xtest_pointer )
+       {
+               ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
+               pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
+               pGesture->num_mt_devices = 0;
+
+               return 0;
+       }
+
+       pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
+       pGesture->first_fingerid = pGesture->mt_devices[0]->id;
+       pGesture->num_mt_devices = idx;
+
+       if( !pGesture->num_mt_devices )
+       {
+               ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
+               pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
+               pGesture->num_mt_devices = 0;
+
+               return 0;
+       }
+
+       memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
+       pGesture->pRootWin = RootWindow(pGesture->master_pointer);
+       g_pGesture->grabMask = g_pGesture->eventMask = 0;
+       g_pGesture->pTempWin = NULL;
+       g_pGesture->inc_num_pressed = 0;
+
+       return 0;
+}
+
+BOOL
+IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
+{
+       if (IsMaster(dev))
+               return FALSE;
+
+       if (master)
+               return (dev->xtest_master_id == master->id);
+
+       return (dev->xtest_master_id != 0);
+}
+
+void
+GestureSetDisable(InputInfoPtr pInfo, int enable)
+{
+       if( !enable )
+       {
+               g_pGesture->ehtype = PROPAGATE_EVENTS;
+               mieqSetHandler(ET_MTSync, NULL);
+               g_pGesture->is_active = 0;
+               ErrorF("[X11][GestureSetDisable] Disabled !\n");
+       }
+       else
+       {
+               g_pGesture->ehtype = KEEP_EVENTS;
+               mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
+               g_pGesture->is_active = 1;
+               ErrorF("[X11][GestureSetDisable] Enabled !\n");
+       }
+}
+
+ErrorStatus
+GestureRegionsInit(void)
+{
+       int i;
+
+       if( !g_pGesture )
+               return ERROR_INVALPTR;
+
+       pixman_region_init(&g_pGesture->area);
+
+       for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
+       {
+               pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
+       }
+
+       return ERROR_NONE;
+}
+
+ErrorStatus
+GestureRegionsReinit(void)
+{
+       if( !g_pGesture )
+       {
+               ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
+               return ERROR_INVALPTR;
+       }
+
+       pixman_region_init(&g_pGesture->area);
+
+       return ERROR_NONE;
+}
+
+ErrorStatus
+GestureInitEQ(void)
+{
+       int i;
+       IEventPtr tmpEQ;
+
+       tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
+
+       if( !tmpEQ )
+       {
+               ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
+               return ERROR_ALLOCFAIL;
+       }
+
+       for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
+       {
+               tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
+               if( !tmpEQ[i].event )
+               {
+                       ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
+                       return ERROR_ALLOCFAIL;
+               }
+       }
+
+       g_pGesture->EQ = tmpEQ;
+       g_pGesture->headEQ = g_pGesture->tailEQ = 0;
+
+       return ERROR_NONE;
+}
+
+ErrorStatus
+GestureFiniEQ(void)
+{
+       int i;
+
+       if( !g_pGesture || !g_pGesture->EQ )
+               return ERROR_INVALPTR;
+
+       for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
+       {
+               if( g_pGesture->EQ[i].event )
+               {
+                       free(g_pGesture->EQ[i].event);
+                       g_pGesture->EQ[i].event = NULL;
+               }
+       }
+
+       free(g_pGesture->EQ);
+       g_pGesture->EQ = NULL;
+
+       return ERROR_NONE;
+}
+
+ErrorStatus
+GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+       int tail;
+
+       if( !g_pGesture || !g_pGesture->EQ )
+       {
+               ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
+               return ERROR_INVALPTR;
+       }
+
+       tail = g_pGesture->tailEQ;
+
+       if( tail >= GESTURE_EQ_SIZE )
+       {
+               ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
+               return ERROR_EQFULL;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       switch( ev->any.type )
+       {
+               case ET_ButtonPress:
+                       ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
+                       break;
+
+               case ET_ButtonRelease:
+                       ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
+                       break;
+
+               case ET_Motion:
+                       ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
+                       break;
+       }
+#endif//__DETAIL_DEBUG__
+
+       g_pGesture->EQ[tail].device = device;
+       g_pGesture->EQ[tail].screen_num = screen_num;
+       memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
+       g_pGesture->tailEQ++;
+
+       return ERROR_NONE;
+}
+
+ErrorStatus
+GestureEventsFlush(void)
+{
+       int i;
+       DeviceIntPtr device;
+
+       if( !g_pGesture->EQ )
+       {
+               ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
+               return ERROR_INVALPTR;
+       }
+
+#ifdef __DETAIL_DEBUG__
+       ErrorF("[X11][GestureEventsFlush]\n");
+#endif//__DETAIL_DEBUG__
+
+       for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
+       {
+               device = g_pGesture->EQ[i].device;
+               device->public.processInputProc(g_pGesture->EQ[i].event, device);
+       }
+
+       for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
+               g_pGesture->event_sum[i] = 0;
+
+       g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
+
+       return ERROR_NONE;
+}
+
+void
+GestureEventsDrop(void)
+{
+       g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
+}
+
+#ifdef HAVE_PROPERTIES
+static void
+GestureInitProperty(DeviceIntPtr dev)
+{
+       int rc;
+
+       prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
+       rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
+
+       if (rc != Success)
+               return;
+
+       XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
+}
+
+static int
+GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+                 BOOL checkonly)
+{
+       InputInfoPtr pInfo  = dev->public.devicePrivate;
+
+       if( prop_gesture_recognizer_onoff == atom )
+       {
+               int data;
+               if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
+                       return BadMatch;
+
+               if( !checkonly )
+               {
+                       data = *((int *)val->data);
+                       GestureSetDisable(pInfo, data);
+               }
+       }
+
+       return Success;
+}
+#endif//HAVE_PROPERTIES
+
+static int
+GestureInit(DeviceIntPtr device)
+{
+       InputInfoPtr pInfo;
+       pInfo = device->public.devicePrivate;
+
+#ifdef HAVE_PROPERTIES
+       GestureInitProperty(device);
+       XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
+#endif
+
+       return Success;
+}
+
+static void
+GestureFini(DeviceIntPtr device)
+{
+       XIRegisterPropertyHandler(device, NULL, NULL, NULL);
+}
+
+static pointer
+GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
+{
+       xf86AddInputDriver(&GESTURE, module, 0);
+       return module;
+}
+
+static void
+GestureUnplug(pointer p)
+{
+}
+
+static InputInfoPtr
+GesturePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+{
+    InputInfoPtr        pInfo;
+    GestureDevicePtr    pGesture;
+
+    if (!(pInfo = xf86AllocateInput(drv, 0)))
+        return NULL;
+
+    pGesture = calloc(1, sizeof(GestureDeviceRec));
+    if (!pGesture) {
+        pInfo->private = NULL;
+        xf86DeleteInput(pInfo, 0);
+        return NULL;
+    }
+
+    g_pGesture = pGesture;
+    pInfo->private = pGesture;
+    pInfo->name = xstrdup(dev->identifier);
+    pInfo->flags = 0;
+    pInfo->type_name = XI_MOUSE; /* see XI.h */
+    pInfo->conf_idev = dev;
+    pInfo->read_input = GestureReadInput; /* new data avl */
+    pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
+    pInfo->device_control = GestureControl; /* enable/disable dev */
+    /* process driver specific options */
+    pGesture->device = xf86SetStrOption(dev->commonOptions, "Device", "/dev/null");
+    pGesture->is_active = xf86SetIntOption(dev->commonOptions, "Activate", 0);
+    pGesture->gestureWin = None;
+
+    xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
+
+    /* process generic options */
+    xf86CollectInputOptions(pInfo, NULL, NULL);
+    xf86ProcessCommonOptions(pInfo, pInfo->options);
+
+    pInfo->fd = -1;
+    pInfo->flags |= XI86_POINTER_CAPABLE;
+    pInfo->flags |= XI86_OPEN_ON_INIT;
+    pInfo->flags |= XI86_CONFIGURED;
+    return pInfo;
+}
+
+static void
+GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+{
+       GestureDevicePtr pGesture = pInfo->private;
+
+       g_pGesture = pGesture = NULL;
+       pInfo->private = NULL;
+
+       xf86DeleteInput(pInfo, 0);
+}
+
+static int
+GestureControl(DeviceIntPtr device, int what)
+{
+    InputInfoPtr  pInfo = device->public.devicePrivate;
+    GestureDevicePtr pGesture = pInfo->private;
+
+    switch(what)
+    {
+        case DEVICE_INIT:
+            GestureInit(device);
+            break;
+
+        /* Switch device on.  Establish socket, start event delivery.  */
+        case DEVICE_ON:
+            xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
+
+            if (device->public.on)
+                    break;
+
+            device->public.on = TRUE;
+            pGesture->this_device = device;
+            pGesture->num_mt_devices = 0;
+            if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
+               goto device_off;
+            break;
+
+       case DEVICE_OFF:
+device_off:
+            GestureDisableEventHandler();
+            GestureFini(device);
+            pGesture->this_device = NULL;
+             xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
+
+            if (!device->public.on)
+                break;
+
+            pInfo->fd = -1;
+            device->public.on = FALSE;
+            break;
+
+      case DEVICE_CLOSE:
+            /* free what we have to free */
+            break;
+    }
+    return Success;
+}
+
+static void
+GestureReadInput(InputInfoPtr pInfo)
+{
+}
+
diff --git a/src/gesture.h b/src/gesture.h
new file mode 100755 (executable)
index 0000000..e9e17ff
--- /dev/null
@@ -0,0 +1,378 @@
+/**************************************************************************
+
+xserver-xorg-input-gesture
+
+Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+
+Contact: Sung-Jin Park <sj76.park@samsung.com>
+         Sangjin LEE <lsj119@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _GESTURE_H_
+#define _GESTURE_H_
+
+#include <xorg/events.h>
+#include <xorg/gestureext.h>
+#include <X11/extensions/gestureconst.h>
+#include <pixman.h>
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+#define HAVE_PROPERTIES 1
+#endif
+
+#define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
+#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
+#define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK)
+#define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET))
+
+#define MAX_MT_DEVICES         3
+#define GESTURE_EQ_SIZE        256
+
+#define GESTURE_RECOGNIZER_ONOFF       "GESTURE_RECOGNIZER_ONOFF"
+
+#define FINGER_WIDTH           10
+#define FINGER_HEIGHT          10
+#define FINGER_WIDTH_2T        20
+#define FINGER_HEIGHT_2T       20
+#define AREA_CENTER_X(extents) ((extents)->x1 + (((extents)->x2-(extents)->x1)/2))
+#define AREA_CENTER_Y(extents) ((extents)->y1 + (((extents)->y2-(extents)->y1)/2))
+#define AREA_SIZE(extents)             (ABS((extents)->x2-(extents)->x1)*ABS((extents)->y2-(extents)->y1))
+#define INBOX(r,x,y)                           ( ((r)->x2 >  x) && ((r)->x1 <= x) && ((r)->y2 >  y) && ((r)->y1 <= y) )
+
+//tap
+#define TAP_THRESHOLD                  100//in pixel
+#define SINGLE_TAP_TIMEOUT             100//in msec
+#define DOUBLE_TAP_TIMEOUT     250//in msec
+
+//pinch rotation
+#define ZOOM_THRESHOLD                 0.05f
+#define ANGLE_THRESHOLD                0.1f
+
+typedef int XFixed;
+typedef double XDouble;
+#define XDoubleToFixed(f)    ((XFixed) ((f) * 65536))
+#define XFixedToDouble(f)    (((XDouble) (f)) / 65536)
+
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+#define ABS(x) (((x) < 0) ? -(x) : (x))
+
+enum
+{
+       FLICK_NORTHWARD = 0,
+       FLICK_NORTHEASTWARD,
+       FLICK_EASTWARD,
+       FLICK_SOUTHEASTWARD,
+       FLICK_SOUTHWARD,
+       FLICK_SOUTHWESTWARD,
+       FLICK_WESTWARD,
+       FLICK_NORTHWESTWARD
+};
+
+#define PAN_AREA_THRESHOLD                     10000//=100pixel * 100pixel
+#define PAN_MOVE_THRESHOLD                     5//pixel
+#define PAN_UPDATE_MOVE_THRESHOLD      3//pixel
+#define PAN_TIME_THRESHOLD                     300//ms
+
+#define HOLD_AREA_THRESHOLD                    2500//=50pixel * 50pixel
+#define HOLD_MOVE_THRESHOLD                    10//pixel
+#define HOLD_TIME_THRESHOLD                    500//ms
+
+#define TAP_AREA_THRESHOLD                     10000//= 100pixel * 100pixel
+#define TAP_MOVE_THRESHOLD                     70//pixel
+#define SGL_TAP_TIME_THRESHOLD         200//ms
+#define DBL_TAP_TIME_THRESHOLD         200//ms
+#define MAX_TAP_REPEATS                                3
+
+#define TAPNHOLD_AREA_THRESHOLD                        4900//= 70pixel * 70pixel
+#define TAPNHOLD_MOVE_THRESHOLD                        50//pixel
+#define TAPNHOLD_TAP_TIME_THRESHOLD            200//ms
+#define TAPNHOLD_INTV_TIME_THRESHOLD           200//ms
+#define TAPNHOLD_HOLD_TIME_THRESHOLD   500//ms
+
+#define FLICK_AREA_THRESHOLD                   22500//=150pixel * 150pixel
+#define FLICK_AREA_TIMEOUT                             700//ms
+#define FLICK_MOVE_THRESHOLD                   100//pixel
+#define FLICK_MOVE_TIMEOUT                             1000//ms
+
+typedef enum _MTSyncType
+{
+       MTOUCH_FRAME_SYNC_END,
+       MTOUCH_FRAME_SYNC_BEGIN
+} MTSyncType;
+
+typedef enum _EventHandleType
+{
+       KEEP_EVENTS,
+       PROPAGATE_EVENTS,
+       IGNORE_EVENTS
+} EventHandleType;
+
+typedef enum _ErrorStatus
+{
+       ERROR_NONE,
+       ERROR_ABNORMAL,
+       ERROR_INVALPTR,
+       ERROR_EQFULL,
+       ERROR_ALLOCFAIL
+} ErrorStatus;
+
+enum EventType
+{
+    ET_KeyPress = 2,
+    ET_KeyRelease,
+    ET_ButtonPress,
+    ET_ButtonRelease,
+    ET_Motion,
+    /*
+    ...
+    */
+    ET_MTSync = 0x7E,
+    ET_Internal = 0xFF /* First byte */
+};
+
+struct _DeviceEvent
+{
+    unsigned char header; /**< Always ET_Internal */
+    enum EventType type;  /**< One of EventType */
+    int length;           /**< Length in bytes */
+    Time time;            /**< Time in ms */
+    int deviceid;         /**< Device to post this event for */
+    int sourceid;         /**< The physical source device */
+    union {
+        uint32_t button;  /**< Button number */
+        uint32_t key;     /**< Key code */
+    } detail;
+    int16_t root_x;       /**< Pos relative to root window in integral data */
+    float root_x_frac;    /**< Pos relative to root window in frac part */
+    int16_t root_y;       /**< Pos relative to root window in integral part */
+    float root_y_frac;    /**< Pos relative to root window in frac part */
+    uint8_t    buttons[(MAX_BUTTONS + 7)/8]; /**< Button mask */
+    struct {
+        uint8_t  mask[(MAX_VALUATORS + 7)/8]; /**< Valuator mask */
+        uint8_t  mode[(MAX_VALUATORS + 7)/8]; /**< Valuator mode (Abs or Rel)*/
+        int32_t  data[MAX_VALUATORS];         /**< Valuator data */
+        int32_t  data_frac[MAX_VALUATORS];    /**< Fractional part for data */
+    } valuators;
+    struct {
+        uint32_t base;    /**< XKB base modifiers */
+        uint32_t latched; /**< XKB latched modifiers */
+        uint32_t locked;  /**< XKB locked modifiers */
+        uint32_t effective;/**< XKB effective modifiers */
+    } mods;
+    struct {
+        uint8_t base;    /**< XKB base group */
+        uint8_t latched; /**< XKB latched group */
+        uint8_t locked;  /**< XKB locked group */
+        uint8_t effective;/**< XKB effective group */
+    } group;
+    Window      root; /**< Root window of the event */
+    int corestate;    /**< Core key/button state BEFORE the event */
+    int key_repeat;   /**< Internally-generated key repeat event */
+};
+
+typedef struct _AnyEvent AnyEvent;
+struct _AnyEvent
+{
+    unsigned char header; /**< Always ET_Internal */
+    enum EventType type;  /**< One of EventType */
+    int length;           /**< Length in bytes */
+    Time time;            /**< Time in ms */
+    int deviceid;
+    MTSyncType sync;
+    int x;
+    int y;
+};
+
+union _InternalEvent {
+       struct {
+           unsigned char header; /**< Always ET_Internal */
+           enum EventType type;  /**< One of ET_* */
+           int length;           /**< Length in bytes */
+           Time time;            /**< Time in ms. */
+       } any;
+       AnyEvent any_event;
+       DeviceEvent device_event;
+};
+
+#define wUseDefault(w,field,def)       ((w)->optional ? (w)->optional->field : def)
+#define wBoundingShape(w)      wUseDefault(w, boundingShape, NULL)
+#define wInputShape(w)          wUseDefault(w, inputShape, NULL)
+#define wBorderWidth(w)                ((int) (w)->borderWidth)
+
+/* used as NULL-terminated list */
+typedef struct _DevCursorNode {
+    CursorPtr                   cursor;
+    DeviceIntPtr                dev;
+    struct _DevCursorNode*      next;
+} DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
+
+typedef struct _WindowOpt {
+    VisualID           visual;            /* default: same as parent */
+    CursorPtr          cursor;            /* default: window.cursorNone */
+    Colormap           colormap;          /* default: same as parent */
+    Mask               dontPropagateMask; /* default: window.dontPropagate */
+    Mask               otherEventMasks;   /* default: 0 */
+    struct _OtherClients *otherClients;           /* default: NULL */
+    struct _GrabRec    *passiveGrabs;     /* default: NULL */
+    PropertyPtr                userProps;         /* default: NULL */
+    unsigned long      backingBitPlanes;  /* default: ~0L */
+    unsigned long      backingPixel;      /* default: 0 */
+    RegionPtr          boundingShape;     /* default: NULL */
+    RegionPtr          clipShape;         /* default: NULL */
+    RegionPtr          inputShape;        /* default: NULL */
+    struct _OtherInputMasks *inputMasks;   /* default: NULL */
+    DevCursorList       deviceCursors;     /* default: NULL */
+} WindowOptRec, *WindowOptPtr;
+
+typedef struct _Window {
+    DrawableRec                drawable;
+    PrivateRec         *devPrivates;
+    WindowPtr          parent;         /* ancestor chain */
+    WindowPtr          nextSib;        /* next lower sibling */
+    WindowPtr          prevSib;        /* next higher sibling */
+    WindowPtr          firstChild;     /* top-most child */
+    WindowPtr          lastChild;      /* bottom-most child */
+    RegionRec          clipList;       /* clipping rectangle for output */
+    RegionRec          borderClip;     /* NotClippedByChildren + border */
+    union _Validate    *valdata;
+    RegionRec          winSize;
+    RegionRec          borderSize;
+    DDXPointRec                origin;         /* position relative to parent */
+    unsigned short     borderWidth;
+    unsigned short     deliverableEvents; /* all masks from all clients */
+    Mask               eventMask;      /* mask from the creating client */
+    PixUnion           background;
+    PixUnion           border;
+    pointer            backStorage;    /* null when BS disabled */
+    WindowOptPtr       optional;
+    unsigned           backgroundState:2; /* None, Relative, Pixel, Pixmap */
+    unsigned           borderIsPixel:1;
+    unsigned           cursorIsNone:1; /* else real cursor (might inherit) */
+    unsigned           backingStore:2;
+    unsigned           saveUnder:1;
+    unsigned           DIXsaveUnder:1;
+    unsigned           bitGravity:4;
+    unsigned           winGravity:4;
+    unsigned           overrideRedirect:1;
+    unsigned           visibility:2;
+    unsigned           mapped:1;
+    unsigned           realized:1;     /* ancestors are all mapped */
+    unsigned           viewable:1;     /* realized && InputOutput */
+    unsigned           dontPropagate:3;/* index into DontPropagateMasks */
+    unsigned           forcedBS:1;     /* system-supplied backingStore */
+    unsigned           redirectDraw:2; /* COMPOSITE rendering redirect */
+    unsigned           forcedBG:1;     /* must have an opaque background */
+#ifdef ROOTLESS
+    unsigned           rootlessUnhittable:1;   /* doesn't hit-test */
+#endif
+} WindowRec;
+
+typedef struct _IEvent {
+       InternalEvent *event;
+       int screen_num;
+       DeviceIntPtr device;
+} IEventRec, *IEventPtr;
+
+enum
+{
+       BTN_RELEASED,
+       BTN_PRESSED,
+       BTN_MOVING
+};
+
+#define PressFlagFlick                 0x01//(1 << 0)
+#define PressFlagPan                           0x02//(1 << 1)
+#define PressFlagPinchRotation 0x04//(1 << 2)
+#define PressFlagTap                           0x08//(1 << 3)
+#define PressFlagTapNHold              0x10//(1 << 4)
+#define PressFlagHold                  0x20//(1 << 5)
+
+#define FlickFilterMask                        0x01//(1 << 0)
+#define PanFilterMask                  0x02//(1 << 1)
+#define PinchRotationFilterMask        0x04//(1 << 2)
+#define TapFilterMask                  0x08//(1 << 3)
+#define TapNHoldFilterMask             0x10//(1 << 4)
+#define HoldFilterMask                 0x20//(1 << 5)
+
+#define GESTURE_FILTER_MASK_ALL        0x3f//(FlickFilterMask | PanFilterMask | PinchRotationFilterMask | TapFilterMask |TapNHoldFilterMask | HoldFilterMask)
+
+typedef struct _tagTouchStatus
+{
+       int status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING
+       uint32_t flags;
+
+       int px;         //press x
+       int py;         //press y
+       int mx;         //motion x
+       int my;         //motion y
+       int rx;         //release x
+       int ry;         //release y
+       Time ptime;     //press time
+       Time mtime;     //motion time
+       Time rtime;     //current/previous release time
+} TouchStatus;
+
+typedef struct _GestureDeviceRec
+{
+       char *device;
+       int version;        /* Driver version */
+       OsTimerPtr device_setting_timer;
+
+       int is_active;
+
+       WindowPtr pRootWin;
+       Window gestureWin;
+       int num_mt_devices;
+
+       Mask grabMask;
+       Mask eventMask;
+       GestureGrabEventPtr GrabEvents;
+
+       EventHandleType ehtype;
+       IEventPtr       EQ;
+       int headEQ;
+       int tailEQ;
+
+       pixman_region16_t area;
+       pixman_region16_t finger_rects[MAX_MT_DEVICES];
+
+       WindowPtr pTempWin;
+       int inc_num_pressed;
+
+       int first_fingerid;
+       int num_pressed;
+       TouchStatus fingers[MAX_MT_DEVICES];
+
+       int event_sum[MAX_MT_DEVICES];
+       uint32_t recognized_gesture;
+       uint32_t filter_mask;
+
+       DeviceIntPtr this_device;
+       DeviceIntPtr mt_devices[MAX_MT_DEVICES];
+       DeviceIntPtr master_pointer;
+       DeviceIntPtr xtest_pointer;
+} GestureDeviceRec, *GestureDevicePtr ;
+
+#endif//_GESTURE_H_
diff --git a/xorg-gesture.pc.in b/xorg-gesture.pc.in
new file mode 100644 (file)
index 0000000..320b0be
--- /dev/null
@@ -0,0 +1,6 @@
+sdkdir=@sdkdir@
+
+Name: xorg-evdev
+Description: X.Org gesture input driver.
+Version: @PACKAGE_VERSION@
+Cflags: -I${sdkdir}