From f04c89548b4b16d26281056d60bfcad599d09c21 Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Tue, 8 Sep 2015 21:32:58 +0900 Subject: [PATCH] tizen 2.3.1 release --- ChangeLog => .gitignore | 0 Makefile.am | 40 - debian/changelog | 61 - debian/compat | 1 - debian/control | 21 - debian/rules | 105 - debian/xserver-xorg-input-gesture.install | 1 - debian/xsfbs/repack.sh | 32 - debian/xsfbs/xsfbs.mk | 293 - debian/xsfbs/xsfbs.sh | 853 --- man/Makefile.am | 57 - mobile/AUTHORS | 2 + COPYING => mobile/COPYING | 0 mobile/ChangeLog | 0 mobile/LICENSE.MIT | 20 + mobile/Makefile.am | 41 + mobile/NOTICE | 3 + autogen.sh => mobile/autogen.sh | 0 configure.ac => mobile/configure.ac | 38 +- mobile/man/Makefile.am | 53 + {man => mobile/man}/gesture.man | 0 mobile/src/Makefile.am | 37 + mobile/src/gesture.c | 6487 +++++++++++++++++++++++ mobile/src/gesture.h | 709 +++ xorg-gesture.pc.in => mobile/xorg-gesture.pc.in | 0 packaging/xorg-x11-drv-gesture.spec | 32 +- src/Makefile.am | 37 - src/gesture.c | 2883 ---------- wearable/AUTHORS | 2 + wearable/COPYING | 21 + wearable/ChangeLog | 0 wearable/LICENSE.MIT | 20 + wearable/Makefile.am | 41 + wearable/NOTICE | 3 + wearable/autogen.sh | 13 + wearable/configure.ac | 75 + wearable/man/Makefile.am | 53 + wearable/man/gesture.man | 29 + wearable/src/Makefile.am | 37 + wearable/src/gesture.c | 3795 +++++++++++++ {src => wearable/src}/gesture.h | 205 +- wearable/xorg-gesture.pc.in | 6 + 42 files changed, 11652 insertions(+), 4454 deletions(-) rename ChangeLog => .gitignore (100%) delete mode 100644 Makefile.am delete mode 100755 debian/changelog delete mode 100644 debian/compat delete mode 100644 debian/control delete mode 100755 debian/rules delete mode 100644 debian/xserver-xorg-input-gesture.install delete mode 100644 debian/xsfbs/repack.sh delete mode 100644 debian/xsfbs/xsfbs.mk delete mode 100644 debian/xsfbs/xsfbs.sh delete mode 100644 man/Makefile.am create mode 100644 mobile/AUTHORS rename COPYING => mobile/COPYING (100%) create mode 100644 mobile/ChangeLog create mode 100644 mobile/LICENSE.MIT create mode 100644 mobile/Makefile.am create mode 100644 mobile/NOTICE rename autogen.sh => mobile/autogen.sh (100%) rename configure.ac => mobile/configure.ac (52%) create mode 100644 mobile/man/Makefile.am rename {man => mobile/man}/gesture.man (100%) create mode 100644 mobile/src/Makefile.am create mode 100644 mobile/src/gesture.c create mode 100644 mobile/src/gesture.h rename xorg-gesture.pc.in => mobile/xorg-gesture.pc.in (100%) delete mode 100644 src/Makefile.am delete mode 100755 src/gesture.c create mode 100644 wearable/AUTHORS create mode 100755 wearable/COPYING create mode 100644 wearable/ChangeLog create mode 100644 wearable/LICENSE.MIT create mode 100644 wearable/Makefile.am create mode 100644 wearable/NOTICE create mode 100755 wearable/autogen.sh create mode 100644 wearable/configure.ac create mode 100644 wearable/man/Makefile.am create mode 100644 wearable/man/gesture.man create mode 100644 wearable/src/Makefile.am create mode 100644 wearable/src/gesture.c rename {src => wearable/src}/gesture.h (69%) mode change 100755 => 100644 create mode 100644 wearable/xorg-gesture.pc.in diff --git a/ChangeLog b/.gitignore similarity index 100% rename from ChangeLog rename to .gitignore diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index 50ddc5b..0000000 --- a/Makefile.am +++ /dev/null @@ -1,40 +0,0 @@ -# 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/debian/changelog b/debian/changelog deleted file mode 100755 index c6c0520..0000000 --- a/debian/changelog +++ /dev/null @@ -1,61 +0,0 @@ -xserver-xorg-input-gesture (0.1.0-7) unstable; urgency=low - - * do not install libtool files - * Git: slp/pkgs/xorg/driver/xserver-xorg-input-gesture - * Tag: xserver-xorg-input-gesture_0.1.0-7 - - -- SooChan Lim Fri, 18 May 2012 09:27:37 +0900 - -xserver-xorg-input-gesture (0.1.0-6) unstable; urgency=low - - * Fix a bug : gesture driver doesn't work properly when id of multitouch devices is not consecutive - * Git: slp/pkgs/xorg/driver/xserver-xorg-input-gesture - * Tag: xserver-xorg-input-gesture_0.1.0-6 - - -- Sung-Jin Park Mon, 02 Jan 2012 20:43:41 +0900 - -xserver-xorg-input-gesture (0.1.0-5) unstable; urgency=low - - * Implement multi-finger pinchrotation - * Git: slp/pkgs/xorg/driver/xserver-xorg-input-gesture - * Tag: xserver-xorg-input-gesture_0.1.0-5 - - -- Sung-Jin Park Tue, 20 Dec 2011 13:15:05 +0900 - -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 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 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 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 Wed, 19 Oct 2011 17:13:15 +0900 - diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff8..0000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index 19f809e..0000000 --- a/debian/control +++ /dev/null @@ -1,21 +0,0 @@ -Source: xserver-xorg-input-gesture -Section: x11 -Priority: optional -Maintainer: Sung-Jin Park , Sangjin Lee -Uploaders: Sung-Jin Park , SooChan Lim -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 deleted file mode 100755 index dd236a7..0000000 --- a/debian/rules +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/make -f -# debian/rules for the Debian xserver-xorg-input-gesture package. -# Copyright © 2004 Scott James Remnant -# Copyright © 2005 Daniel Stone -# Copyright © 2005 David Nusinow - -# 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 deleted file mode 100644 index 4ac2576..0000000 --- a/debian/xserver-xorg-input-gesture.install +++ /dev/null @@ -1 +0,0 @@ -usr/lib/xorg/modules/input/*.so diff --git a/debian/xsfbs/repack.sh b/debian/xsfbs/repack.sh deleted file mode 100644 index 5935cc9..0000000 --- a/debian/xsfbs/repack.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/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 deleted file mode 100644 index f0f8953..0000000 --- a/debian/xsfbs/xsfbs.mk +++ /dev/null @@ -1,293 +0,0 @@ -#!/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 . - -# Originally by Stephen Early -# Modified by Mark W. Eichin -# Modified by Adam Heath -# Modified by Branden Robinson -# Modified by Fabio Massimo Di Nitto -# Modified by David Nusinow -# 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 deleted file mode 100644 index 781826f..0000000 --- a/debian/xsfbs/xsfbs.sh +++ /dev/null @@ -1,853 +0,0 @@ -# $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 < 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 < 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 " \ - " 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 " \ - " 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 < /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 deleted file mode 100644 index 276f2f0..0000000 --- a/man/Makefile.am +++ /dev/null @@ -1,57 +0,0 @@ -# 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/mobile/AUTHORS b/mobile/AUTHORS new file mode 100644 index 0000000..e903784 --- /dev/null +++ b/mobile/AUTHORS @@ -0,0 +1,2 @@ +Sung-Jin Park +Sangjin Lee diff --git a/COPYING b/mobile/COPYING similarity index 100% rename from COPYING rename to mobile/COPYING diff --git a/mobile/ChangeLog b/mobile/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/mobile/LICENSE.MIT b/mobile/LICENSE.MIT new file mode 100644 index 0000000..1c81bdc --- /dev/null +++ b/mobile/LICENSE.MIT @@ -0,0 +1,20 @@ +Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. Red +Hat makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied +warranty. + +THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/mobile/Makefile.am b/mobile/Makefile.am new file mode 100644 index 0000000..8e655ec --- /dev/null +++ b/mobile/Makefile.am @@ -0,0 +1,41 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS 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/mobile/NOTICE b/mobile/NOTICE new file mode 100644 index 0000000..c10a9c5 --- /dev/null +++ b/mobile/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under MIT License. +Please, see the LICENSE.MIT file for MIT License terms and conditions. diff --git a/autogen.sh b/mobile/autogen.sh similarity index 100% rename from autogen.sh rename to mobile/autogen.sh diff --git a/configure.ac b/mobile/configure.ac similarity index 52% rename from configure.ac rename to mobile/configure.ac index 8f20226..16c2d38 100644 --- a/configure.ac +++ b/mobile/configure.ac @@ -1,25 +1,23 @@ -# Copyright 2007 Peter Hutterer -# Copyright 2009 Przemysław Firszt +# 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 -# 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: +# 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. # -# The above copyright notice and this permission notice (including the next -# paragraph) shall be included in all copies or substantial portions of the -# Software. +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS 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([xserver-xorg-input-gesture], @@ -56,7 +54,7 @@ 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) +PKG_CHECK_MODULES(XORG, xorg-server xproto xdbg $REQUIRED_MODULES) XORG_CFLAGS="$CWARNFLAGS $XORG_CFLAGS" AC_ARG_WITH([sdkdir], [], [sdkdir="$withval"], diff --git a/mobile/man/Makefile.am b/mobile/man/Makefile.am new file mode 100644 index 0000000..b91dae4 --- /dev/null +++ b/mobile/man/Makefile.am @@ -0,0 +1,53 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +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/mobile/man/gesture.man similarity index 100% rename from man/gesture.man rename to mobile/man/gesture.man diff --git a/mobile/src/Makefile.am b/mobile/src/Makefile.am new file mode 100644 index 0000000..695f833 --- /dev/null +++ b/mobile/src/Makefile.am @@ -0,0 +1,37 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS 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/mobile/src/gesture.c b/mobile/src/gesture.c new file mode 100644 index 0000000..c85ffed --- /dev/null +++ b/mobile/src/gesture.c @@ -0,0 +1,6487 @@ +/************************************************************************** + +xserver-xorg-input-gesture + +Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + +Contact: Sung-Jin Park + Sangjin LEE + +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 +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_PROPERTIES +#include +#include +/* 1.6 has properties, but no labels */ +#ifdef AXIS_LABEL_PROP +#define HAVE_LABELS +#else +#undef HAVE_LABELS +#endif + +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gesture.h" +#include +#include + +#define MGEST XDBG_M('G','E','S','T') + +static const void(*PalmRecognize)(int, InternalEvent*, DeviceIntPtr); + +#define _GESTUREPALMRECOGNIZE_(function, type, ev, device) \ + if(function) \ + { \ + XDBG_WARNING(MGEST, "[_GESTUREPALMRECOGNIZE_] Enable GesturePalmRecognize. type=%d\n", type); \ + function(type, ev, device); \ + } \ + else \ + { \ + XDBG_WARNING(MGEST, "[_GESTUREPALMRECOGNIZE_] Disable GesturePalmRecognize \n"); \ + } \ + +static void printk(const char* fmt, ...) __attribute__((format(printf, 1, 0))); +extern char *strcasestr(const char *s, const char *find); +extern ScreenPtr miPointerCurrentScreen(void); +extern EventQueuePtr mieqGetEventQueuePtr(); + +static Bool GestureIsEventInMIEQ(int finger_index, enum EventType type); +static int GestureGetFingerIndexFromDevice(DeviceIntPtr device); +static int GestureGetDeviceIdFromFingerIndex(int finger_index); +static Bool GestureIsPalmEventInMIEQ(void); +static Bool GestureIsPalmEvent(InternalEvent *event); +static int GestureGetMTToolValuator(InternalEvent *ev, DeviceIntPtr device); +static void GestureRegisterTouchInfo(InternalEvent *ev, DeviceIntPtr device); +static void GestureSetToolData(InternalEvent *ev, double val_tool); +static void GestureCleanupTouch(int screen_num, InternalEvent *ev, DeviceIntPtr device); +static void GestureChangeEventToFirstFingerEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device); + +//Basic functions +static int GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, 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 GestureEnable(int enable, Bool prop, DeviceIntPtr dev); +static inline void GestureEnableDisable(); +void GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent); +void GestureCbEventsSelected(Window win, Mask *pEventMask); +WindowPtr GestureGetEventsWindow(void); +static Bool GestureHasFingersEvents(int eventType); + +//Enqueued event handlers and enabler/disabler +static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo); +static ErrorStatus GestureDisableEventHandler(void); +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); +void GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device); +void GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device); + +static void GestureRegisterDeviceInfo(DeviceIntPtr device); + +//Gesture recognizer helper +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21 +static Bool PointInBorderSize(WindowPtr pWin, int x, int y); +#endif +static WindowPtr GestureWindowOnXY(int x, int y); +Bool GestureHasFingerEventMask(int eventType, int num_finger); +#ifdef _F_SUPPORT_BEZEL_FLICK_ +static int get_distance(int x1, int y1, int x2, int y2); +#endif +static double get_angle(int x1, int y1, int x2, int y2); + +//Gesture recognizer and handlers +void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); +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); +#ifdef _F_SUPPORT_BEZEL_FLICK_ +int GestureBezelAngleRecognize(int type, int distance, double angle); +#endif +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, int kinds); +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); +static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device); +void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device); +ErrorStatus GestureFlushOrDrop(void); + +static int GesturePalmGetHorizIndexWithX(int x, int type); +static int GesturePalmGetVertiIndexWithY(int y, int type); +static void GesturePalmRecognize_FlickHorizen(int type, int idx); +static void GesturePalmRecognize_FlickVertical(int type,int idx); +static int GesturePalmGetScreenInfo(); +static int GesturePalmGetAbsAxisInfo(DeviceIntPtr dev); +static void GesturePalmDataUpdate(int idx, int type, InternalEvent *ev, DeviceIntPtr device); +static void GesturePalmUpdateAreaInfo(int type, int idx); +void GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device); + +void GestureGenerateTouchCancelEvent(void); + +static void GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata); + +//#define __PALM_GESTURE_LOG__ +//#define __PALM_DETAIL_LOG__ +//#define __DETAIL_DEBUG__ +//#define __BEZEL_DEBUG__ +//#define __DEBUG_EVENT_HANDLER__ + +#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; +static Atom prop_gesture_palm_rejection_mode = None; + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT +static Atom prop_anr_in_input_event = None; +static Atom prop_anr_event_window = None; +static Window prop_anr_event_window_xid = None; +#endif + +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 +}; + +extern CallbackListPtr DPMSCallback; + +static void +printk(const char* fmt, ...) +{ + static FILE* fp = NULL; + static char init = 0; + va_list argptr; + + if(!init && !fp) + { + fp = fopen("/dev/kmsg", "wt"); + init = 1; + } + + if(!fp) return; + + va_start(argptr, fmt); + vfprintf(fp, fmt, argptr); + fflush(fp); + va_end(argptr); +} + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT +static WindowPtr +_GestureFindANRWindow(DeviceIntPtr device) +{ + WindowPtr root=NULL; + WindowPtr anr_window=NULL; + Window anr_xid=0; + PropertyPtr pProp; + int rc=0; + + root = RootWindow(device); + + if( prop_anr_event_window == None ) + prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE); + + rc = dixLookupProperty (&pProp, root, prop_anr_event_window, serverClient, DixReadAccess); + if (rc == Success && pProp->data){ + anr_xid = *(int*)pProp->data; + } + + if( anr_xid != 0 ) + { + rc = dixLookupWindow(&anr_window, anr_xid, serverClient, DixSetPropAccess); + if( rc == BadWindow ) + { + XDBG_ERROR(MGEST, "Can't find ANR window !!\n"); + anr_window = NULL; + } + prop_anr_event_window_xid = anr_xid; + } + + XDBG_DEBUG(MGEST, "ANR Window is %#x. Ptr is %#x\n", anr_xid, anr_window); + return anr_window; +} +#endif + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21 +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; +} +#endif + +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)); + if (!pSprite->spriteTrace) { + return NULL; + } + + } + 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__ + XDBG_DEBUG(MGEST, "TRUE !! Has grabMask\n"); +#endif//__DETAIL_DEBUG__ + return TRUE; + } + + if( g_pGesture->eventMask & eventmask ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "TRUE !! Has eventMask\n"); +#endif//__DETAIL_DEBUG__ + return TRUE; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger); +#endif//__DETAIL_DEBUG__ + + return ret; +} + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +static int +get_distance(int _x1, int _y1, int _x2, int _y2) +{ + int xx, yy; + xx = ABS(_x2 - _x1); + yy = ABS(_y2 - _y1); + + if(xx && yy) + { + return (int)sqrt(pow(xx, 2) + pow(yy, 2)); + } + else if(xx) + { + return yy; + } + else if(yy) + { + return xx; + } + else + { + return 0; + } +} +#endif//_F_SUPPORT_BEZEL_FLICK_ + +static double +get_angle(int _x1, int _y1, int _x2, int _y2) +{ + double a, xx, yy; + xx = fabs(_x2 - _x1); + yy = fabs(_y2 - _y1); + + if (((int) xx) && ((int) yy)) + { + a = atan(yy / xx); + if (_x1 < _x2) + { + if (_y1 < _y2) + { + return (RAD_360DEG - a); + } + else + { + return (a); + } + } + else + { + if (_y1 < _y2) + { + return (RAD_180DEG + a); + } + else + { + return (RAD_180DEG - a); + } + } + } + + if (((int) xx)) + { /* Horizontal line */ + if (_x2 < _x1) + { + return (RAD_180DEG); + } + else + { + return (0.0); + } + } + + /* Vertical line */ + if (_y2 < _y1) + { + return (RAD_90DEG); + } + else + { + return (RAD_270DEG); + } +} + +void +GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction) +{ + Window target_win; + WindowPtr target_pWin; + xGestureNotifyFlickEvent fev; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "num_fingers=%d, distance=%d, duration=%d, direction=%d\n", + num_of_fingers, distance, duration, direction); +#endif//__DETAIL_DEBUG__ + + if(num_of_fingers == 0) + { + if(direction == FLICK_EASTWARD || direction == FLICK_WESTWARD) + g_pGesture->recognized_palm |= PalmFlickHorizFilterMask; + if(direction == FLICK_NORTHWARD || direction == FLICK_SOUTHWARD) + g_pGesture->recognized_palm |= PalmFlickVertiFilterMask; + } +#ifdef _F_SUPPORT_BEZEL_FLICK_ + else if(num_of_fingers == 1) + { + g_pGesture->bezel_recognized_mask |= BezelFlickFilterMask; + } +#endif + else + 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; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + fev.window = target_win; + } + else + { + fev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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__ + XDBG_DEBUG(MGEST, "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; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + tev.window = target_win; + } + else + { + tev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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, int kinds) +{ + Window target_win; + WindowPtr target_pWin; + xGestureNotifyPinchRotationEvent prev; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n", + num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy); +#endif//__DETAIL_DEBUG__ + + g_pGesture->recognized_gesture |= PinchRotationFilterMask; + memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent)); + prev.type = GestureNotifyPinchRotation; + prev.kind = kinds; + prev.num_finger = num_of_fingers; + prev.zoom = XDoubleToFixed(zoom); + prev.angle = XDoubleToFixed(angle); + prev.distance = distance; + prev.cx = cx; + prev.cy = cy; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + prev.window = target_win; + } + else + { + prev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "prev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)prev.window, (unsigned int)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__ + XDBG_DEBUG(MGEST, "num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n", + num_fingers, cx, cy, holdtime, kinds); +#endif//__DETAIL_DEBUG__ + + if(num_fingers == 0) + g_pGesture->hold_detected = TRUE; + else + 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; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + hev.window = target_win; + } + else + { + hev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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__ + XDBG_DEBUG(MGEST, "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; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + thev.window = target_win; + } + else + { + thev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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__ + XDBG_DEBUG(MGEST, "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; + + if(g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if( g_pGesture->grabMask && (target_win != None) ) + { + pev.window = target_win; + } + else + { + pev.window = g_pGesture->gestureWin; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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); +} + +static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + int idx = -1; + pixman_region16_t tarea1; + static int num_pressed = 0; + unsigned int hold_area_size; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + + if(!g_pGesture->hold_detector_activate) + { +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "g_pGesture->hold_detector_activate=0\n"); +#endif//__HOLD_DETECTOR_DEBUG__ + return; + } + + if(!g_pGesture->has_hold_grabmask) + { + Mask eventmask = (1L << GestureNotifyHold); + + if( (g_pGesture->grabMask & eventmask) && + (g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[0].window != None) ) + { + g_pGesture->has_hold_grabmask = 1; + + //Initialize a set of variables + num_pressed = 0; + memset(&g_pGesture->cts, 0, sizeof(g_pGesture->cts)); + pixman_region_init(&g_pGesture->chold_area); +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "[%d] Initialize...\n", __LINE__); +#endif//__HOLD_DETECTOR_DEBUG__ + } + else + { + //reset local hold_grab_mask variable + g_pGesture->has_hold_grabmask = 0; + + g_pGesture->hold_detector_activate = 0; +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "has_hold_grabmask=0 and g_pGesture->hold_detector_activate=0\n"); +#endif//__HOLD_DETECTOR_DEBUG__ + return; + } + } + + if( IGNORE_EVENTS == g_pGesture->ehtype || + device->id < g_pGesture->first_fingerid ) + { +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "Return (IGNORE_EVENTS or device->id:%d < first_fingerid:%d)\n", device->id, g_pGesture->first_fingerid); +#endif//__HOLD_DETECTOR_DEBUG__ + return; + } + + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if( device->id == g_pGesture->mt_devices[i]->id ) + { + idx = i; + break; + } + } + if( (idx < 0) || ((MAX_MT_DEVICES-1) < idx )) return; + + switch( type ) + { + case ET_ButtonPress: + g_pGesture->cts[idx].status = BTN_PRESSED; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + + num_pressed++; + if(num_pressed < 3) break; + + if( num_pressed > g_pGesture->num_mt_devices ) + num_pressed = g_pGesture->num_mt_devices; + + pixman_region_init(&tarea1); + pixman_region_init(&g_pGesture->chold_area); + pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1); + + tarea1.extents.x1 = g_pGesture->cts[0].cx; + tarea1.extents.x2 = g_pGesture->cts[0].cx+1; + tarea1.extents.y1 = g_pGesture->cts[0].cy; + tarea1.extents.y2 = g_pGesture->cts[0].cy+1; + + pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1); + + for( i = 1 ; i < num_pressed ; i++ ) + { + pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1); + + tarea1.extents.x1 = g_pGesture->cts[i].cx; + tarea1.extents.x2 = g_pGesture->cts[i].cx + 1; + tarea1.extents.y1 = g_pGesture->cts[i].cy; + tarea1.extents.y2 = g_pGesture->cts[i].cy + 1; + + pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1); + } + break; + + case ET_Motion: + if(BTN_RELEASED == g_pGesture->cts[idx].status) + return; + + g_pGesture->cts[idx].status = BTN_MOVING; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + + if(num_pressed < 3) break; + + pixman_region_init(&tarea1); + pixman_region_init(&g_pGesture->chold_area); + pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1); + + tarea1.extents.x1 = g_pGesture->cts[0].cx; + tarea1.extents.x2 = g_pGesture->cts[0].cx+1; + tarea1.extents.y1 = g_pGesture->cts[0].cy; + tarea1.extents.y2 = g_pGesture->cts[0].cy+1; + + pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1); + + for( i = 1 ; i < num_pressed ; i++ ) + { + pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1); + + tarea1.extents.x1 = g_pGesture->cts[i].cx; + tarea1.extents.x2 = g_pGesture->cts[i].cx + 1; + tarea1.extents.y1 = g_pGesture->cts[i].cy; + tarea1.extents.y2 = g_pGesture->cts[i].cy + 1; + + pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1); + } + break; + + case ET_ButtonRelease: + g_pGesture->cts[idx].status = BTN_RELEASED; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + + num_pressed--; + if(num_pressed <3) + { + pixman_region_init(&g_pGesture->chold_area); + } + break; + } + + if(num_pressed >= 3) + { + hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents); + +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "hold_area_size=%d, pPalmMisc->half_scrn_area_size=%d\n", hold_area_size, pPalmMisc->half_scrn_area_size); +#endif//__HOLD_DETECTOR_DEBUG__ + + if(pPalmMisc->half_scrn_area_size <= hold_area_size) + { + GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureBegin); + GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureEnd); + + g_pGesture->hold_detector_activate = 0; + g_pGesture->has_hold_grabmask = 0; + } + } +} + +void +GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired) +{ + static int cx, cy; + + static int num_pressed = 0; + static int state = GestureEnd; + static int event_type = GestureNotifyPinchRotation; + static OsTimerPtr pinchrotation_event_timer = NULL; + + static pixman_region16_t base_area; + static pixman_region16_t cur_area; + + static double base_distance = 0.0f; + static double base_angle = 0.0f; + + static double prev_distance = 0.0f; + static double prev_angle = 0.0f; + + static double cur_distance = 0.0f; + static double cur_angle = 0.0f; + + double diff_distance = 0.0f; + double diff_angle = 0.0f; + + static int has_event_mask = 0; + + static Time base_time = 0; + Time current_time; + + if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_pinchrotation; + + if( timer_expired ) + { + if( state == GestureEnd ) + { + current_time = GetTimeInMillis(); + if( (current_time - base_time) >= g_pGesture->pinchrotation_time_threshold ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[Timer] You must move farther than dist threshold(=%.2f) or angle threshold(=%2f) within time threshold(=%d) !\n", g_pGesture->pinchrotation_dist_threshold, g_pGesture->pinchrotation_angle_threshold, g_pGesture->pinchrotation_time_threshold); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + } + + return; + } + + switch( type ) + { + case ET_ButtonPress: + g_pGesture->fingers[idx].flags |= PressFlagPinchRotation; + + if( g_pGesture->num_pressed < 2 ) + return; + + if( g_pGesture->num_pressed < num_pressed && state != GestureEnd ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[P][cleanup] num_finger changed !(state: %d) num_pressed=%d, g_pGesture->num_pressed=%d\n", state, num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + goto cleanup_pinchrotation; + } + + if( base_distance == 0.0f && g_pGesture->num_pressed == 2 ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + + base_time = GetTimeInMillis(); + pixman_region_init(&base_area); + pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); + + prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents); + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px, + g_pGesture->fingers[0].py, g_pGesture->fingers[1].py); +#endif//__DETAIL_DEBUG__ + + prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle)); +#endif//__DETAIL_DEBUG__ + event_type = GestureNotifyPinchRotation; + pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, g_pGesture->pinchrotation_time_threshold, GestureEventTimerHandler, (int *)&event_type); + } + num_pressed = g_pGesture->num_pressed; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents)); + XDBG_DEBUG(MGEST, "[P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle)); +#endif//__DETAIL_DEBUG__ + break; + + case ET_Motion: + if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) ) + break; + + if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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_pinchrotation; + } + + if( num_pressed < 2 ) + return; + + if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my ) + { + pixman_region_init(&cur_area); + pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); + + cur_distance = AREA_DIAG_LEN(&cur_area.extents); + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx, + g_pGesture->fingers[0].my, g_pGesture->fingers[1].my); +#endif//__DETAIL_DEBUG__ + + cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle)); +#endif//__DETAIL_DEBUG__ + + diff_distance = prev_distance - cur_distance; + diff_angle = prev_angle - cur_angle; + + cx = AREA_CENTER_X(&cur_area.extents); + cy = AREA_CENTER_Y(&cur_area.extents); + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M][state=%d] cx=%d, cy=%d\n", state, cx, cy); +#endif//__DETAIL_DEBUG__ + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance); + XDBG_DEBUG(MGEST, "[M][num_pressed=%d] prev_angle=%.2f(deg=%.2f), cur_angle=%.2f(deg=%.2f), diff=%.2f(deg=%.2f)\n", num_pressed, prev_angle, rad2degree(prev_angle), cur_angle, rad2degree(cur_angle), diff_angle, rad2degree(diff_angle)); +#endif//__DETAIL_DEBUG__ + + switch( state ) + { + case GestureEnd: + if( (ABS(diff_distance) >= g_pGesture->pinchrotation_dist_threshold) || (ABS(diff_angle) >= g_pGesture->pinchrotation_angle_threshold) ) + { +#ifdef __DETAIL_DEBUG__ + if( ABS(diff_distance) >= g_pGesture->pinchrotation_dist_threshold ) + XDBG_DEBUG(MGEST, "[M] zoom changed !\n"); + + if( ABS(diff_angle) >= g_pGesture->pinchrotation_angle_threshold ) + XDBG_DEBUG(MGEST, "[M] angle changed !\n"); +#endif//__DETAIL_DEBUG__ + + TimerCancel(pinchrotation_event_timer); + state = GestureBegin; + goto gesture_begin_handle; + } + break; + + case GestureBegin: +gesture_begin_handle: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) ) + { + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureBegin); + prev_distance = cur_distance; + prev_angle = cur_angle; + state = GestureUpdate; + has_event_mask = 1; + } + else + { + has_event_mask = 0; + goto cleanup_pinchrotation; + } + break; + + case GestureUpdate: + //if( ABS(diff_distance) < g_pGesture->pinchrotation_dist_threshold && ABS(diff_angle) < g_pGesture->pinchrotation_angle_threshold ) + // break; + +#ifdef __DETAIL_DEBUG__ + if( ABS(diff_distance) >= g_pGesture->pinchrotation_dist_threshold ) + XDBG_DEBUG(MGEST, "[M] zoom changed !\n"); + + if( ABS(diff_angle) >= g_pGesture->pinchrotation_angle_threshold ) + XDBG_DEBUG(MGEST, "[M] angle changed !\n"); +#endif//__DETAIL_DEBUG__ + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureUpdate); + prev_distance = cur_distance; + prev_angle = cur_angle; + break; + + case GestureDone: + default: + break; + } + } + break; + + case ET_ButtonRelease: + if( state != GestureEnd && num_pressed >= 2) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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_pinchrotation; + } + + if( g_pGesture->num_pressed ) + break; + + goto cleanup_pinchrotation; + break; + } + + return; + +cleanup_pinchrotation: + g_pGesture->filter_mask |= PinchRotationFilterMask; + if( has_event_mask && (state == GestureBegin || state == GestureUpdate) ) + { + state = GestureEnd; +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state); +#endif//__DETAIL_DEBUG__ + GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureEnd); + } + else if(g_pGesture->num_pressed > 1) + { + if(!(g_pGesture->filter_mask & PanFilterMask)) + { + pixman_region_init(&base_area); + pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); + + prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents); + prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py); + + g_pGesture->filter_mask &= ~PinchRotationFilterMask; + + return; + } + g_pGesture->recognized_gesture &= ~PinchRotationFilterMask; + } + + if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[cleanup] GestureFlushOrDrop() !\n"); +#endif//__DETAIL_DEBUG__ + + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + + prev_distance = base_distance = 0.0f; + prev_angle = base_angle = 0.0f; + has_event_mask = num_pressed = 0; + state = GestureEnd; + cx = cy = 0; + TimerCancel(pinchrotation_event_timer); + 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; + + if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_flick; + + 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__ + XDBG_DEBUG(MGEST, "[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 ) + { + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "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(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_pan; + + 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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx)); + XDBG_DEBUG(MGEST, "[M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy)); +#endif//__DETAIL_DEBUG__ + + if( state <= GestureBegin ) + { + if( !INBOX(&base_box_ext, cx, cy) ) + { + TimerCancel(pan_event_timer); + pan_event_timer = NULL; + + 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__ + XDBG_DEBUG(MGEST, "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; + mbits = 0; + } + break; + + case ET_ButtonRelease: + if( state != GestureEnd && num_pressed >= 2) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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: + g_pGesture->filter_mask |= PanFilterMask; + 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 if(g_pGesture->num_pressed > 1) + { + if(!(g_pGesture->filter_mask & PinchRotationFilterMask)) + { + 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; + g_pGesture->filter_mask &= ~PanFilterMask; + return; + } + g_pGesture->recognized_gesture &= ~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; + if( pan_event_timer ) + { + TimerCancel(pan_event_timer); + pan_event_timer = NULL; + } + 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; + + int cx, cy; + int area_size; + + static int state = GestureEnd; + 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_num_pressed = 0; + + static OsTimerPtr tap_event_timer = NULL; + static int event_type = GestureNotifyTap; + + if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_tap; + + if( timer_expired ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[Timer] state=%d\n", state); +#endif//__DETAIL_DEBUG__ + + switch( state ) + { + case GestureBegin://first tap initiation check + if( num_pressed ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", num_pressed, tap_repeat); +#endif//__DETAIL_DEBUG__ + state = GestureEnd; + goto cleanup_tap; + } + break; + + case GestureUpdate: + if( tap_repeat <= 1 ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed); +#endif//__DETAIL_DEBUG__ + state = GestureEnd; + goto cleanup_tap; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[Timer][state=2] tap_repeat=%d, num_pressed=%d\n", tap_repeat, num_pressed); +#endif//__DETAIL_DEBUG__ + if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) ) + { + if(prev_num_pressed == 2 && tap_repeat == 2) + { + g_pGesture->zoom_enabled = (g_pGesture->zoom_enabled + 1)%2; + if(g_pGesture->zoom_enabled == 1) + { + g_pGesture->recognized_gesture |= TapFilterMask; + } + } + 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 = GestureBegin; + TimerCancel(tap_event_timer); + tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->singletap_threshold, GestureEventTimerHandler, (int *)&event_type); + } + + num_pressed = g_pGesture->num_pressed; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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, GetTimeInMillis()); +#endif//__DETAIL_DEBUG__ + break; + + case ET_Motion: + if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) ) + break; + + if( num_pressed < 2 ) + return; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M][num_pressed=%d] g_pGesture->num_pressed: %d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + + if( num_pressed != g_pGesture->num_pressed ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + //goto cleanup_tap; + break; + } + + 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__ + XDBG_DEBUG(MGEST, "[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)); + XDBG_DEBUG(MGEST, "[M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx)); + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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; + } + + tap_repeat++; + g_pGesture->tap_repeated = tap_repeat; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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(GestureNotifyTap, num_pressed) ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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 = GestureUpdate; + TimerCancel(tap_event_timer); + tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->doubletap_threshold, GestureEventTimerHandler, (int *)&event_type); + num_pressed = 0; + break; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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); + + goto cleanup_tap; + } + + return; + +cleanup_tap: + + if( GestureEnd == state ) + g_pGesture->recognized_gesture &= ~TapFilterMask; + g_pGesture->filter_mask |= TapFilterMask; + + if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[cleanup] GestureFlushOrDrop() !\n"); +#endif//__DETAIL_DEBUG__ + + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + + num_pressed = 0; + tap_repeat = 0; + g_pGesture->tap_repeated = 0; + prev_num_pressed = 0; + mbits = 0; + base_time = 0; + state = GestureEnd; + 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(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_tapnhold; + + if( timer_expired ) + { + if( (state == GestureEnd) && num_pressed ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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: + XDBG_DEBUG(MGEST, "[Timer] TapNHold Begin !\n"); + break; + + case GestureUpdate: + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[P] Create Timer !(state=%d)\n", state); +#endif//__DETAIL_DEBUG__ + } + + num_pressed = g_pGesture->num_pressed; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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)); + XDBG_DEBUG(MGEST, "[M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx)); + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + goto cleanup_hold; + + if( timer_expired ) + { + if( state <= GestureBegin ) + state++; + +#ifdef __DETAIL_DEBUG__ + switch( state ) + { + case GestureBegin: + XDBG_DEBUG(MGEST, "HOLD Begin !\n"); + break; + + case GestureUpdate: + XDBG_DEBUG(MGEST, "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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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)); + XDBG_DEBUG(MGEST, "[M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx)); + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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__ + XDBG_DEBUG(MGEST, "[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; + } + + //XDBG_DEBUG(MGEST, "[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; +} + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +int +GestureBezelAngleRecognize(int type, int distance, double angle) +{ + if (distance < g_pGesture->bezel.flick_distance) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "distance(%d) < flick_distance(%d)\n", distance, g_pGesture->bezel.flick_distance); +#endif//__BEZEL_DEBUG__ + return 0; + } + switch(type) + { + case BEZEL_TOP_LEFT: + break; + case BEZEL_TOP_RIGHT: + break; + case BEZEL_BOTTOM_LEFT: + if( (g_pGesture->bezel.min_rad< angle) && (angle < g_pGesture->bezel.max_rad) ) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "bottom_left bezel success....\n"); +#endif//__BEZEL_DEBUG__ + return 1; + } + else + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "bottom_left bezel failed....\n"); +#endif//__BEZEL_DEBUG__ + return 0; + } + case BEZEL_BOTTOM_RIGHT: + if( (g_pGesture->bezel.min_180_rad< angle) && (angle < g_pGesture->bezel.max_180_rad)) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "bottom_right bezel success...\n"); +#endif//__BEZEL_DEBUG__ + return 1; + } + else + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "bottom_right bezel failed....\n"); +#endif//__BEZEL_DEBUG__ + return 0; + } + default: + return 0; + } + return 0; +} +#endif + +static inline void +GestureEnableDisable() +{ + if((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None)) + { + GestureEnable(1, FALSE, g_pGesture->this_device); + } + else + { + GestureEnable(0, FALSE, g_pGesture->this_device); + } +} + +void +GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent) +{ + g_pGesture->grabMask = *pGrabMask; + g_pGesture->GrabEvents = (GestureGrabEventPtr)pGrabEvent; + GestureEnableDisable(); +} + +void +GestureCbEventsSelected(Window win, Mask *pEventMask) +{ + g_pGesture->lastSelectedWin = win; + g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0; + GestureEnableDisable(); +} + +WindowPtr +GestureGetEventsWindow(void) +{ + Mask mask; + WindowPtr pWin; + + pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py); + + if( pWin ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "pWin->drawable.id=0x%x\n", pWin->drawable.id); +#endif//__DETAIL_DEBUG__ + g_pGesture->gestureWin = pWin->drawable.id; + } + else + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureWindowOnXY returns NULL !\n"); +#endif//__DETAIL_DEBUG__ + return NULL; + } + if(g_pGesture->gestureWin == g_pGesture->lastSelectedWin) + { + g_pGesture->eventMask = g_pGesture->lastSelectedMask; + goto nonempty_eventmask; + } + + //check selected event(s) + if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) ) + { + g_pGesture->eventMask = 0; + } + else + { + g_pGesture->lastSelectedWin = g_pGesture->gestureWin; + g_pGesture->lastSelectedMask = g_pGesture->eventMask; + } + + if( !g_pGesture->eventMask && !g_pGesture->grabMask) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id); +#endif//__DETAIL_DEBUG__ + return NULL; + } + +nonempty_eventmask: + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask); +#endif//__DETAIL_DEBUG__ + + mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask)); + +#ifdef __DETAIL_DEBUG__ +#ifdef _F_SUPPORT_BEZEL_FLICK_ + XDBG_DEBUG(MGEST, "g_pGesture->filter_mask=0x%x, mask=0x%x, palm_filter_mask=0x%x bezel_filter_mask=0x%x\n", g_pGesture->filter_mask, mask, g_pGesture->palm_filter_mask, g_pGesture->bezel_filter_mask); +#else + XDBG_DEBUG(MGEST, "g_pGesture->filter_mask=0x%x, mask=0x%x, palm_filter_mask=0x%x\n", g_pGesture->filter_mask, mask, g_pGesture->palm_filter_mask); +#endif +#endif//__DETAIL_DEBUG__ + g_pGesture->palm_filter_mask = 0; + if(mask & FlickFilterMask) + { + g_pGesture->palm_filter_mask |= PalmFlickHorizFilterMask; + g_pGesture->palm_filter_mask |= PalmFlickVertiFilterMask; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + g_pGesture->bezel_filter_mask |= BezelFlickFilterMask; +#endif + } + if(!(mask & FlickFilterMask)) + { +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[1].window)) + { + g_pGesture->bezel_filter_mask |= BezelFlickFilterMask; + } + else +#endif + if(!(g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[0].window)) + { + g_pGesture->palm_filter_mask |= PalmFlickHorizFilterMask; + g_pGesture->palm_filter_mask |= PalmFlickVertiFilterMask; + } + } + if(!g_pGesture->palm.palmflag) + { + if(!GestureHasFingersEvents(HoldFilterMask)) + mask |= HoldFilterMask; + if(!GestureHasFingersEvents(FlickFilterMask)) + mask |= FlickFilterMask; + g_pGesture->filter_mask = mask; + } +#ifdef __DETAIL_DEBUG__ +#ifdef _F_SUPPORT_BEZEL_FLICK_ + XDBG_DEBUG(MGEST, "g_pGesture->filter_mask=0x%x, palm_filter_mask: 0x%x, bezel_filter_mask=0x%x\n", g_pGesture->filter_mask, g_pGesture->palm_filter_mask, g_pGesture->bezel_filter_mask); +#else + XDBG_DEBUG(MGEST, "g_pGesture->filter_mask=0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->palm_filter_mask); +#endif +#endif//__DETAIL_DEBUG__ + + return pWin; +} + +static Bool +GestureHasFingersEvents(int eventType) +{ + int i=0; + Mask eventmask = (1L << eventType); + for(i=2; igrabMask & eventmask) && + (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[i].window != None) ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "TRUE !! Has grabMask\n"); +#endif//__DETAIL_DEBUG__ + return TRUE; + } + } + return FALSE; +} + +static CARD32 +GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + int event_type = *(int *)arg; + + switch( event_type ) + { + case GestureNotifyHold: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureNotifyHold (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1); + break; + + case GestureNotifyPan: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureNotifyPan (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupPan(event_type, NULL, NULL, 0, 1); + break; + + case GestureNotifyTap: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureNotifyTap (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1); + break; + + case GestureNotifyTapNHold: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureNotifyTapNHold (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1); + break; + + case GestureNotifyPinchRotation: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureNotifyPinchRotation (event_type = %d)\n", event_type); +#endif//__DETAIL_DEBUG__ + GestureRecognize_GroupPinchRotation(event_type, NULL, NULL, 0, 1); + break; + + default: +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "unknown event_type (=%d)\n", event_type); +#endif//__DETAIL_DEBUG__ + if(timer) + XDBG_INFO(MGEST, "timer=%x\n", (unsigned int)timer); + } + + return 0; +} + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +static CARD32 +GestureBezelSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + BezelFlickStatusPtr pBezel = &g_pGesture->bezel; + + if( pBezel->is_active != BEZEL_NONE ) + { + pBezel->is_active = BEZEL_END; +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "end\n"); +#endif//__BEZEL_DEBUG__ + } + return 0; +} +#endif + +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__ + XDBG_DEBUG(MGEST, "expired !\n"); +#endif//__DETAIL_DEBUG__ + + return 0; +} + +static CARD32 +GesturePalmSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + PalmStatusPtr pPalm = &g_pGesture->palm; + if(pPalm->palmflag || (pPalm->biggest_tmajor >= PALM_FLICK_FINGER_MIN_TOUCH_MAJOR)) + { + pPalm->single_timer_expired = 0; + return 0; + } + + pPalm->single_timer_expired = 1; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "palm expired !\n"); +#endif//__DETAIL_DEBUG__ + + return 0; +} + +static int +GesturePalmGetHorizIndexWithX(int x, int type) +{ + int i; + int ret_idx = -1; + static int pressed_idx = -1; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + + for(i = 0 ; i < PALM_HORIZ_ARRAY_COUNT ; i++) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "pPalmMisc->horiz_coord[%d]=%d, x=%d\n", i, pPalmMisc->horiz_coord[i], x); +#endif//__PALM_DETAIL_LOG__ + if(x <= pPalmMisc->horiz_coord[i]) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "index=%d\n", i); +#endif//__PALM_DETAIL_LOG__ + ret_idx = i; + goto index_check; + } + } +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "Error ! Failed to get horiz coordinate index !\n"); +#endif//__PALM_DETAIL_LOG__ + return ret_idx; + +index_check: + + if(type == ET_ButtonPress) + { + pressed_idx = ret_idx; + } + else if(type == ET_ButtonRelease) + { + if((pressed_idx <= 1) && (ret_idx >= (PALM_HORIZ_ARRAY_COUNT-2))) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Valid !\n"); +#else + ; +#endif//__PALM_DETAIL_LOG__ + } + else if((pressed_idx >= (PALM_HORIZ_ARRAY_COUNT-2)) && (ret_idx <= 1)) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Valid !\n"); +#else + ; +#endif//__PALM_DETAIL_LOG__ + } + else + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Invalid !(pressed_idx=%d, released_idx=%d\n", pressed_idx, ret_idx); +#endif//__PALM_DETAIL_LOG__ + ret_idx = -1; + } + } + + return ret_idx; +} + +static int +GesturePalmGetVertiIndexWithY(int y, int type) +{ + int i; + int ret_idx = -1; + static int pressed_idx = -1; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + + for(i = 0 ; i < PALM_VERTI_ARRAY_COUNT ; i++) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "pPalmMisc->verti_coord[%d]=%d, x=%d\n", i, pPalmMisc->verti_coord[i], y); +#endif//__PALM_DETAIL_LOG__ + if(y <= pPalmMisc->verti_coord[i]) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "index=%d\n", i); +#endif//__PALM_DETAIL_LOG__ + ret_idx = i; + goto index_check; + } + } +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "Error ! Failed to get verti coordinate index !\n"); +#endif//__PALM_DETAIL_LOG__ + return ret_idx; + +index_check: + + if(type == ET_ButtonPress) + { + if((ret_idx <= 1) || (ret_idx >=(PALM_VERTI_ARRAY_COUNT-2))) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[P] Valid !\n"); +#endif//__PALM_DETAIL_LOG__ + pressed_idx = ret_idx; + } + else + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[P] Invalid !(pressed_idx(=%d) must be between 0 and 1 or between 3 and 4\n", pressed_idx); +#endif//__PALM_DETAIL_LOG__ + ret_idx = -1; + } + + } + else if(type == ET_ButtonRelease) + { + if((pressed_idx <= 1) && (ret_idx >= (PALM_VERTI_ARRAY_COUNT-2))) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Valid !\n"); +#else + ; +#endif//__PALM_DETAIL_LOG__ + } + else if((pressed_idx >= (PALM_VERTI_ARRAY_COUNT-2)) && (ret_idx <= 1)) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Valid !\n"); +#else + ; +#endif//__PALM_DETAIL_LOG__ + } + else + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[R] Invalid !(pressed_idx=%d, released_idx=%d\n", pressed_idx, ret_idx); +#endif//__PALM_DETAIL_LOG__ + ret_idx = -1; + } + } + + return ret_idx; +} + +static void +GesturePalmRecognize_FlickHorizen(int type, int idx) +{ + static int curTouched = 0; + static int num_pressed = 0; + static int base_width_size = 0; + static Time base_time = 0; + static int base_x; + static pixman_box16_t base_box_ext; +#ifdef __PALM_GESTURE_LOG__ + int i; +#endif + + int line_idx; + static int prev_line_idx; + static int horiz_line[PALM_HORIZ_ARRAY_COUNT]; + + Time duration; + int distx=0, disty=0; + int distance, direction; + + int width_size; + static int is_flicking = 1; + //static int is_surface = 0; + static int pass_count = 0; + static int base_cx=0, base_cy=0; + static int release_flag = 0; + + PalmStatusPtr pPalm = &g_pGesture->palm; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d palmflag: %d\n", num_pressed, pPalm->cur_touched, pPalm->palmflag); + XDBG_DEBUG(MGEST, "idx: %d, cx: %d, cy: %d, type: %d, touch_status: %d\n", idx, pPalm->cx, pPalm->cy, type, pPalm->pti[idx].touch_status); +#endif + + if( idx < 0 ) + goto flick_failed; + + if(g_pGesture->enqueue_fulled == 1) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n"); +#endif + goto flick_failed; + } + + if(pPalm->single_timer_expired) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "No flick single finger...expired\n"); +#endif + goto flick_failed; + } + + if(g_pGesture->recognized_gesture || g_pGesture->hold_detected || + (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickHorizFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask) +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "zoom_enabled: %d\n", g_pGesture->zoom_enabled); + XDBG_DEBUG(MGEST, "type(%d) recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", type, g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "type(%d) recognized_gesture= 0x%x, filter_mask= 0x%x\n", type, g_pGesture->recognized_gesture, g_pGesture->filter_mask); +#endif + goto flick_failed; + } + switch( type ) + { + case ET_ButtonPress: + if(!is_flicking) + break; + if(!base_width_size || pPalm->cur_touched > curTouched) + { + if(!base_time) + { + base_time = GetTimeInMillis(); + base_x = AREA_CENTER_X(&pPalm->area.extents); + line_idx = GesturePalmGetHorizIndexWithX(base_x, type); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] cx: %d, cy: %d, x1: %d, x2: %d, y1: %d, y2: %d, line_idx: %d\n", pPalm->cx, pPalm->cy, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2, line_idx); +#endif + if(line_idx < 0) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x, line_idx); +#endif + goto flick_failed; + } + + horiz_line[line_idx]++; + pass_count++; + prev_line_idx = line_idx; + release_flag = 0; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] Base_width=%d, base_x=%d, line_idx=%d\n", base_width_size, base_x, line_idx); +#endif + } + + base_width_size = AREA_WIDTH(&pPalm->area.extents); + if(base_width_size > PALM_FLICK_HORIZ_MAX_BASE_WIDTH) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] No flickBase_width=%d > %d: MAX_WIDTH\n", base_width_size, PALM_FLICK_HORIZ_MAX_BASE_WIDTH); +#endif + goto flick_failed; + } +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] Base_width=%d, cur_touched=%d\n", base_width_size, pPalm->cur_touched); +#endif + if(pPalm->max_touched == 1) + { + base_cx = AREA_CENTER_X(&pPalm->area.extents); + base_cy = AREA_CENTER_Y(&pPalm->area.extents); + 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; + } + } + curTouched = pPalm->cur_touched; + num_pressed++; + break; + + case ET_Motion: + if(!num_pressed || !is_flicking) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] num_pressed: %d, is_flicking: %d\n", num_pressed, is_flicking); +#endif + break; + } + + distx = AREA_CENTER_X(&pPalm->area.extents); + disty = AREA_CENTER_Y(&pPalm->area.extents); + line_idx = GesturePalmGetHorizIndexWithX(distx, type); +#ifdef __PALM_GESTURE_LOG__ + for(i=0; imax_touched == 1) + { + if(ABS(disty - base_cy) > PALM_FLICK_HORIZ_MAX_MOVE_Y) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick ! (move too long toward y coordination %d(%d - %d) > %d\n", ABS(disty - base_cy), disty, base_cy, PALM_FLICK_HORIZ_MAX_MOVE_Y); +#endif + goto flick_failed; + } + } + + if(prev_line_idx != line_idx) + { + horiz_line[line_idx]++; + if(horiz_line[line_idx] > 2) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick ! horiz_line[%d]: %d > 2\n", line_idx, horiz_line[line_idx]); +#endif + goto flick_failed; + } + pass_count++; + } + if(pass_count > 6) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n"); +#endif + goto flick_failed; + } +#if 0 + if((prev_line_idx != line_idx) && horiz_line[line_idx] && !release_flag) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n"); +#endif + goto flick_failed; + } +#endif + prev_line_idx = line_idx; + + width_size = AREA_WIDTH(&pPalm->area.extents); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] Base_width=%d, Current_width=%d, diff=%d\n", base_width_size, width_size, ABS(width_size - base_width_size)); +#endif + duration = GetTimeInMillis() - base_time; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] duration =%d !\n", duration); +#endif + if(((!pPalm->palmflag) && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR-20) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR-20)) && + (duration >= PALM_FLICK_INITIAL_TIMEOUT)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(initial flick timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + if( (duration >= PALM_FLICK_INITIAL_TIMEOUT) && (INBOX(&base_box_ext, distx, disty)) ) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(move too short !in duration: %d)\n", duration); +#endif + goto flick_failed; + } + if( (duration >= PALM_FLICK_FALSE_TIMEOUT) && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(press touch major(%.f) width major (%.f) < (%.f) is little in duration(%d))\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR, duration); +#endif + goto flick_failed; + } + + if(duration >= PALM_FLICK_DETECT_TIMEOUT) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(flick detection timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + break; + + case ET_ButtonRelease: + release_flag = 1; + if(--num_pressed < 0) + num_pressed = 0; + base_width_size = AREA_WIDTH(&pPalm->area.extents); + if(num_pressed) + break; + + if((!pPalm->palmflag) && (pPalm->biggest_tmajor < 100) && (pPalm->bigger_wmajor < 100)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick (No palm comming and all finger release))\n"); +#endif + goto flick_failed; + } + + if(!is_flicking) + goto cleanup_flick; + + duration = GetTimeInMillis() - base_time; + distx = AREA_CENTER_X(&pPalm->area.extents); + line_idx = GesturePalmGetHorizIndexWithX(distx, type); + + if(line_idx < 0) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick (distx: %d, line_idx: %d))\n", distx, line_idx); +#endif + goto flick_failed; + } +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] duration=%d, distx=%d\n", duration, distx); +#endif + if(duration >= PALM_FLICK_DETECT_TIMEOUT) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(flick detection timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + if(pass_count < PALM_HORIZ_ARRAY_COUNT - 1) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(flick distance is short!\n"); +#endif + goto flick_failed; + } + if((pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(touch major(%.f) width major(%.f) < %d) is small...)\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR); +#endif + goto flick_failed; + } + + direction = (line_idx <= 1) ? FLICK_EASTWARD : FLICK_WESTWARD; + distance = ABS(distx - base_x); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] Palm Flick !!!, direction=%d, distance=%d\n", direction, distance); +#endif + if( GestureHasFingerEventMask(GestureNotifyFlick, 0) ) + GestureHandleGesture_Flick(0, distance, duration, direction); + goto cleanup_flick; + break; + } + + return; + +flick_failed: + is_flicking = 0; + g_pGesture->recognized_palm &= ~PalmFlickHorizFilterMask; + g_pGesture->palm_filter_mask |= PalmFlickHorizFilterMask; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[Failed] recognized_palm= 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); +#endif + goto cleanup_flick; + return; + +cleanup_flick: + num_pressed = 0; + is_flicking = 1; + base_width_size = 0; + //is_surface = 0; + base_time = 0; + curTouched = 0; + pass_count = 0; + prev_line_idx = 0; + release_flag = 0; + base_cx = base_cy = 0; + base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0; + memset(&horiz_line, 0L, PALM_HORIZ_ARRAY_COUNT * sizeof(int)); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[cleanup_flick] base_width_size=%d, curTouched=%d\n", base_width_size, curTouched); +#endif + return; +} + +static void +GesturePalmRecognize_FlickVertical(int type,int idx) +{ + static int curTouched = 0; + static int num_pressed = 0; + static int base_height_size = 0; + static Time base_time = 0; + static int base_y; + static int base_cx, base_cy; + static int pass_count = 0; + static int release_flag = 0; + static pixman_box16_t base_box_ext; + + int line_idx; + static int prev_line_idx; + static int verti_line[PALM_VERTI_ARRAY_COUNT]; + + Time duration; + int disty; + int distx; + int distance, direction; + + int height_size; + static int is_flicking = 1; + static int false_base_height_size = 0; + + PalmStatusPtr pPalm = &g_pGesture->palm; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d, palm_flag: %d, single_timer_expired: %d\n", num_pressed, pPalm->cur_touched, pPalm->palmflag, pPalm->single_timer_expired); +#endif + + if( idx < 0 ) + goto flick_failed; + + if(g_pGesture->enqueue_fulled == 1) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "EQ Event is full.... No palm recognize drop..\n"); +#endif + goto flick_failed; + } + + if(g_pGesture->recognized_gesture || g_pGesture->hold_detected || + (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickVertiFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask) +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "zoom_enabled: %d\n", g_pGesture->zoom_enabled); + XDBG_DEBUG(MGEST, "type(%d) recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", type, g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "type(%d) recognized_gesture= 0x%x, filter_mask= 0x%x\n", type, g_pGesture->recognized_gesture, g_pGesture->filter_mask); +#endif + goto flick_failed; + } + + if(pPalm->single_timer_expired) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "No flick single finger...expired\n"); +#endif + goto flick_failed; + } + + switch( type ) + { + case ET_ButtonPress: + if(!is_flicking) + break; + if(!base_height_size || pPalm->cur_touched > curTouched) + { + if(!base_time) + { + base_time = GetTimeInMillis(); + base_y = AREA_CENTER_Y(&pPalm->area.extents); + line_idx = GesturePalmGetVertiIndexWithY(base_y, type); + +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx); +#endif + if(line_idx < 0) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] No Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx); +#endif + goto flick_failed; + } + + verti_line[line_idx] = 1; + pass_count++; + prev_line_idx = line_idx; + release_flag = 0; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx); +#endif + } + + base_height_size = AREA_HEIGHT(&pPalm->area.extents); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] Base_height=%d, cur_touched=%d\n", base_height_size, pPalm->cur_touched); +#endif + if(base_height_size > PALM_FLICK_VERTI_MAX_BASE_WIDTH) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[P] No flickBase_width=%d > MAX_WIDTH\n", base_height_size, PALM_FLICK_VERTI_MAX_BASE_WIDTH); +#endif + goto flick_failed; + } + false_base_height_size = 0; + if(pPalm->max_touched == 1) + { + base_cx = AREA_CENTER_X(&pPalm->area.extents); + base_cy = AREA_CENTER_Y(&pPalm->area.extents); + 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; + } + } + + curTouched = pPalm->cur_touched; + num_pressed++; + break; + + case ET_Motion: + if(!num_pressed|| !is_flicking) + break; + + distx = AREA_CENTER_X(&pPalm->area.extents); + disty = AREA_CENTER_Y(&pPalm->area.extents); + line_idx = GesturePalmGetVertiIndexWithY(disty, type); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] line_idx: %d\n", line_idx); +#endif + + if(line_idx < 0) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No line_idx: %d\n", line_idx); +#endif + goto flick_failed; + } + if((prev_line_idx != line_idx) && verti_line[line_idx] && !release_flag) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n"); +#endif + goto flick_failed; + } +#if 0 + if(pPalm->max_touched == 1) + { + if(ABS(AREA_CENTER_X(&pPalm->area.extents) - base_cx) > PALM_FLICK_VERTI_MAX_MOVE_X) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick ! (move too long toward x coordination %d(%d - %d) > PALM_FLICK_VERTI_MAX_MOVE_X\n", ABS(AREA_CENTER_X(&pPalm->area.extents) - base_cx), AREA_CENTER_X(&pPalm->area.extents) , base_cx, PALM_FLICK_VERTI_MAX_MOVE_X); +#endif + goto flick_failed; + } + } +#endif + verti_line[line_idx] = 1; + if(prev_line_idx != line_idx) + pass_count++; + prev_line_idx = line_idx; + + height_size = AREA_HEIGHT(&pPalm->area.extents); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] Base_height=%d, Current_height=%d, diff=%d\n", base_height_size, height_size, ABS(height_size - base_height_size)); +#endif + + duration = GetTimeInMillis() - base_time; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] duration =%d !\n", duration); +#endif + + if(!pPalm->palmflag && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR-20) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR-20) + && (duration >= PALM_FLICK_INITIAL_TIMEOUT)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(initial flick timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + if( (duration >= PALM_FLICK_INITIAL_TIMEOUT) && (INBOX(&base_box_ext, distx, disty)) ) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(move too short !in duration: %d)\n", duration); +#endif + goto flick_failed; + } + + if(duration >= PALM_FLICK_DETECT_TIMEOUT) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[M] No flick !(flick detection timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + break; + + case ET_ButtonRelease: + release_flag = 1; + + if(--num_pressed < 0) + num_pressed = 0; + if(num_pressed) + break; + + if(!pPalm->palmflag && (pPalm->biggest_tmajor < 100) && (pPalm->bigger_wmajor < 100)) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick (No palm comming and all finger release))\n"); +#endif + goto flick_failed; + } + + if(!is_flicking) + goto cleanup_flick; + + duration = GetTimeInMillis() - base_time; + disty = AREA_CENTER_Y(&pPalm->area.extents); + line_idx = GesturePalmGetVertiIndexWithY(disty, type); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] line_idx: %d\n", line_idx); +#endif + + if(line_idx < 0) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No line_idx: %d\n", line_idx); +#endif + goto flick_failed; + } +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] duration=%d, disty=%d\n", duration, disty); +#endif + + if(duration >= PALM_FLICK_DETECT_TIMEOUT) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(flick detection timeout : duration=%d)\n", duration); +#endif + goto flick_failed; + } + if(pass_count < PALM_VERTI_ARRAY_COUNT -1) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(flick distance is short!)\n"); +#endif + goto flick_failed; + } + if(pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR && pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR) + { +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] No flick !(flick touch major(%.f) width major(%.f) < %d) is small!)\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR); +#endif + goto flick_failed; + } + direction = (line_idx <= 1) ? FLICK_SOUTHWARD : FLICK_NORTHWARD; + distance = ABS(disty - base_y); + +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[R] Palm Flick !!!, direction=%d, distance=%d\n", direction, distance); +#endif + + if( GestureHasFingerEventMask(GestureNotifyFlick, 0) ) + GestureHandleGesture_Flick(0, distance, duration, direction); + goto cleanup_flick; + break; + } + + return; + +flick_failed: + is_flicking = 0; + g_pGesture->recognized_palm &= ~PalmFlickVertiFilterMask; + g_pGesture->palm_filter_mask |= PalmFlickVertiFilterMask; +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[Fail] recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); +#endif + goto cleanup_flick; + return; + +cleanup_flick: + num_pressed = 0; + is_flicking = 1; + base_height_size = 0; + base_time = 0; + curTouched = 0; + pass_count = 0; + false_base_height_size = 0; + prev_line_idx = 0; + release_flag = 0; + base_cx = base_cy = 0; + base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0; + memset(&verti_line, 0L, PALM_VERTI_ARRAY_COUNT * sizeof(int)); +#ifdef __PALM_GESTURE_LOG__ + XDBG_DEBUG(MGEST, "[cleanup_flick] base_height_size=%d, curTouched=%d\n", base_height_size, curTouched); +#endif + + return; +} + + +static int +GesturePalmGetScreenInfo() +{ + int i; + pixman_region16_t tarea; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + ScreenPtr pScreen = miPointerCurrentScreen(); + + if(!pScreen) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "Failed to get screen information !\n"); +#endif + pPalmMisc->scrn_width = pPalmMisc->scrn_height = 0; + return 0; + } + + pPalmMisc->scrn_width = pScreen->width; + pPalmMisc->scrn_height = pScreen->height; + pixman_region_init(&tarea); + pixman_region_init_rect(&tarea, 0, 0, pPalmMisc->scrn_width, pPalmMisc->scrn_height); + pPalmMisc->half_scrn_area_size = AREA_SIZE(&tarea.extents); + pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 2.4f); +#ifdef __HOLD_DETECTOR_DEBUG__ + XDBG_DEBUG(MGEST, "pPalmMisc->half_scrn_area_size = %d\n", pPalmMisc->half_scrn_area_size); +#endif//__HOLD_DETECTOR_DEBUG__ + + for(i = 0 ; i < PALM_HORIZ_ARRAY_COUNT ; i++) + { + pPalmMisc->horiz_coord[i] = pPalmMisc->scrn_width * ((i+1)/(double)PALM_HORIZ_ARRAY_COUNT); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "pPalmMisc->horiz_coord[%d]=%d, pPalmMisc->scrn_width=%d\n", i, pPalmMisc->horiz_coord[i], pPalmMisc->scrn_width); +#endif + } + for(i = 0 ; i < PALM_VERTI_ARRAY_COUNT ; i++) + { + pPalmMisc->verti_coord[i] = pPalmMisc->scrn_height * ((i+1)/(double)PALM_VERTI_ARRAY_COUNT); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "pPalmMisc->verti_coord[%d]=%d, pPalmMisc->scrn_height=%d\n", i, pPalmMisc->verti_coord[i], pPalmMisc->scrn_height); +#endif + } + + return 1; +} + +static int +GesturePalmGetAbsAxisInfo(DeviceIntPtr dev) +{ + int i, found = 0; + int numAxes; + PalmStatusPtr pPalm; + + Atom atom_wmajor; + Atom atom_tmajor; + Atom atom_tminor; + Atom atom_tangle; + Atom atom_tpalm; + Atom atom_mt_px; + Atom atom_mt_py; + + Atom atom_px; + Atom atom_py; + Atom atom_mt_slot; + Atom atom_tracking_id; + Atom atom_distance; + Atom atom_mt_tool; + + g_pGesture->wmajor_idx = -1; + g_pGesture->tmajor_idx = -1; + g_pGesture->tminor_idx = -1; + g_pGesture->tangle_idx = -1; + g_pGesture->tpalm_idx = -1; + g_pGesture->mt_px_idx = -1; + g_pGesture->mt_py_idx = -1; + g_pGesture->mt_tool_idx = -1; + + memset(&g_pGesture->palm, 0, sizeof(PalmStatus)); + + if (!dev || !dev->valuator) + goto out; + + numAxes = dev->valuator->numAxes; + atom_mt_px = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X); + atom_mt_py = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y); + atom_wmajor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR); + atom_tmajor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR); + atom_tminor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR); + atom_tangle = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_ANGLE); + atom_tpalm = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PALM); + + atom_px = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X); + atom_py = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y); + atom_mt_slot = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_SLOT); + atom_tracking_id = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TRACKING_ID); + atom_distance = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_DISTANCE); + atom_mt_tool = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE); + + if (!numAxes || !atom_mt_px || !atom_mt_py || !atom_tmajor || !atom_tminor || !atom_tangle || !atom_tpalm) + { + XDBG_WARNING(MGEST, "one or more axes is/are not supported!\n"); + goto out; + } + if (!atom_mt_tool) + { + XDBG_WARNING(MGEST, "multitouch various type was not supported\n"); + } + + for( i = 0 ; i < numAxes ; i++ ) + { + AxisInfoPtr axes = &dev->valuator->axes[i]; + + if (!axes || (axes->mode != Absolute)) + continue; + + if ( axes->label == atom_mt_px ) + { + g_pGesture->mt_px_idx = i; + found += 1; + } + else if ( axes->label == atom_mt_py ) + { + g_pGesture->mt_py_idx = i; + found += 2; + } + else if ( axes->label == atom_wmajor ) + { + g_pGesture->wmajor_idx = i; + found += 3; + } + else if ( axes->label == atom_tmajor ) + { + g_pGesture->tmajor_idx = i; + found += 4; + } + else if ( axes->label == atom_tminor ) + { + g_pGesture->tminor_idx = i; + found += 5; + } + else if ( axes->label == atom_tangle ) + { + g_pGesture->tangle_idx = i; + found += 6; + } + else if ( axes->label == atom_tpalm ) + { + g_pGesture->tpalm_idx = i; + found += 7; + } + else if ( atom_mt_tool && axes->label == atom_mt_tool ) + { + g_pGesture->mt_tool_idx = i; + found += 8; + } + } + + if (found != 36) + { + XDBG_WARNING(MGEST, "Various multitouch devices are not supported !\n"); + if (found != 28) + { + XDBG_WARNING(MGEST, "Axes for palm recognization are not supported !\n"); + goto out; + } + } + + pPalm = &g_pGesture->palm; + pixman_region_init(&pPalm->area); + + for( i = 0 ; i < MAX_MT_DEVICES ; i++ ) + { + pixman_region_init_rect (&pPalm->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T); + } + + g_pGesture->palm_misc.enabled = 1; + XDBG_INFO(MGEST, "Axes for palm recognization are supported !\n"); + return 1; + +out: + g_pGesture->palm_misc.enabled = 0; + XDBG_INFO(MGEST, "Palm recognization is not supported !\n"); + return 0; +} + +static void +GesturePalmDataUpdate(int idx, int type, InternalEvent *ev, DeviceIntPtr device) +{ + int wmajor_idx = g_pGesture->wmajor_idx; + int tmajor_idx = g_pGesture->tmajor_idx; + int tminor_idx = g_pGesture->tminor_idx; + int tangle_idx = g_pGesture->tangle_idx; + int tpalm_idx = g_pGesture->tpalm_idx; + int px_idx = g_pGesture->mt_px_idx; + int py_idx= g_pGesture->mt_py_idx; + + double width_major = 0.0f; + double touch_major = 0.0f; + double touch_minor = 0.0f; + double touch_angle = 0.0f; + double touch_palm = 0.0f; + double max_width = -1.0f; + + int i; + int count; + double meanX = 0.0f; + double meanY = 0.0f; + double tmpXp = 0.0f; + double tmpYp = 0.0f; + + PalmStatusPtr pPalm = &g_pGesture->palm; + DeviceEvent *de = &ev->device_event; + pPalm->cx = 0; + pPalm->cy = 0; + + if (!de) + { + XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n"); + return; + } + + if ((wmajor_idx < 0) || (tmajor_idx < 0) || (tminor_idx < 0) || (tangle_idx < 0) || (tpalm_idx < 0) || (px_idx < 0) || (py_idx < 0)) + { + XDBG_WARNING(MGEST, "One or more of axes are not supported !\n"); + return; + } + + width_major = de->valuators.data[wmajor_idx]; + touch_major = de->valuators.data[tmajor_idx]; + touch_minor = de->valuators.data[tminor_idx]; + touch_angle = de->valuators.data[tangle_idx]; + touch_palm = de->valuators.data[tpalm_idx]; + if( !(g_pGesture->palm.palmflag) && pPalm->max_palm >= PALM_FLICK_MIN_PALM) + { + g_pGesture->palm.palmflag = 1; + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + } + +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[idx:%d, devid:%d, type:%d] width_major=%.f, touch_major=%.f, touch_minor=%.f, touch_palm=%.f \n", idx, de->deviceid, type, width_major, touch_major, touch_minor, touch_palm); + XDBG_DEBUG(MGEST, "[%d]: touch_status: %d, x: %d, y: %d (cur_touched: %d);\n", idx, pPalm->pti[idx].touch_status, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->cur_touched); +#endif + + switch(type) + { + case ET_ButtonPress: + if (!pPalm->pti[idx].touch_status) + { + pPalm->cur_touched++; + pPalm->pti[idx].touch_status = 1; + } + + pPalm->pti[idx].x = de->root_x; + pPalm->pti[idx].y = de->root_y; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[idx:%d(devid:%d)][PRESS] x=%d, y=%d, wmajor=%.f, tmajor=%.f, tminor=%.f, tangle=%.f, tpalm=%.f\n", idx, device->id, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->pti[idx].wmajor, pPalm->pti[idx].tmajor, pPalm->pti[idx].tminor, pPalm->pti[idx].tangle, pPalm->pti[idx].tpalm); +#endif + break; + + case ET_ButtonRelease: + if (pPalm->pti[idx].touch_status) + { + --pPalm->cur_touched; + if (pPalm->cur_touched < 0) + pPalm->cur_touched = 0; + } + + pPalm->pti[idx].touch_status = 2; + + pPalm->pti[idx].x = de->root_x; + pPalm->pti[idx].y = de->root_y; + + pPalm->pti[idx].tangle = 0.0f; + pPalm->pti[idx].wmajor = 0.0f; + pPalm->pti[idx].tmajor = 0.0f; + pPalm->pti[idx].tminor = 0.0f; + pPalm->pti[idx].tpalm = 0.0f; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[idx:%d(devid:%d)][RELEASE] x=%d, y=%d, wmajor=%.f, tmajor=%.f, tminor=%.f, tangle=%.f, tpalm=%.f\n", idx, device->id, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->pti[idx].wmajor, pPalm->pti[idx].tmajor, pPalm->pti[idx].tminor, pPalm->pti[idx].tangle, pPalm->pti[idx].tpalm); +#endif + break; + + case ET_Motion: + pPalm->pti[idx].x = de->root_x; + pPalm->pti[idx].y = de->root_y; + + pPalm->pti[idx].tmajor = touch_major; + pPalm->pti[idx].tangle = touch_angle; + pPalm->pti[idx].wmajor = width_major; + pPalm->pti[idx].tminor = touch_minor; + pPalm->pti[idx].tpalm = touch_palm; + + if (!pPalm->pti[idx].touch_status || (pPalm->pti[idx].tmajor == 0)) + return; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[idx:%d(devid:%d)][MOVE] x=%d, y=%d, wmajor=%.f, tmajor=%.f, tminor=%.f, tangle=%.f, tpalm=%.f\n", idx, device->id, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->pti[idx].wmajor, pPalm->pti[idx].tmajor, pPalm->pti[idx].tminor, pPalm->pti[idx].tangle, pPalm->pti[idx].tpalm); +#endif + break; + } + + pPalm->sum_size = 0.0f; + pPalm->max_wmajor = -1.0f; + pPalm->max_tmajor = -1.0f; + pPalm->max_tminor = -1.0f; + pPalm->max_size_idx = -1; + pPalm->max_palm = -1.0f; + max_width = -1.0f; + + for( count = 0, i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if (!pPalm->pti[i].touch_status) + continue; + if(pPalm->pti[i].touch_status == 2) + pPalm->pti[i].touch_status =0; + count++; + meanX += pPalm->pti[i].x; + meanY += pPalm->pti[i].y; + pPalm->sum_size += pPalm->pti[i].wmajor; + if(max_width < pPalm->pti[i].wmajor) + { + pPalm->max_size_idx = i; + } + if (pPalm->max_wmajor < pPalm->pti[i].wmajor) + { + pPalm->max_wmajor = pPalm->pti[i].wmajor; + } + if(pPalm->max_tmajor < pPalm->pti[i].tmajor) + pPalm->max_tmajor = pPalm->pti[i].tmajor; + if(pPalm->max_tminor < pPalm->pti[i].tminor) + pPalm->max_tminor = pPalm->pti[i].tminor; + if(pPalm->max_palm < pPalm->pti[i].tpalm) + { + pPalm->max_palm = (int)pPalm->pti[i].tpalm; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "max_palm=%d pPalm->pti[%d].tpalm: %.f\n", pPalm->max_palm, i, pPalm->pti[i].tpalm); +#endif + } + } + + if (pPalm->max_size_idx < 0) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "Failed to get sum_size !\n"); +#endif + //meanX = 0; + //meanY = 0; + pPalm->dispersionX = 0.0f; + pPalm->deviationX = 0.0f; + pPalm->dispersionY= 0.0f; + pPalm->deviationY = 0.0f; + pPalm->max_eccen = 0.0f; + pPalm->max_angle = 0.0f; + } + else + { + meanX /= count; + meanY /= count; + pPalm->cx = meanX; + pPalm->cy = meanY; + + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if (!pPalm->pti[i].touch_status) + continue; + + tmpXp += (pPalm->pti[i].x - meanX)*(pPalm->pti[i].x - meanX); + tmpYp += (pPalm->pti[i].y - meanY)*(pPalm->pti[i].y - meanY); + } + + pPalm->dispersionX = tmpXp / count; + pPalm->deviationX = sqrt(pPalm->dispersionX); + pPalm->dispersionY = tmpYp / count; + pPalm->deviationY = sqrt(pPalm->dispersionY); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "meanX=%.f, meanY=%.f, count=%d, tmpXp=%.f, tmpYp=%.f\n", meanX, meanY, count, tmpXp, tmpYp); +#endif + + pPalm->max_eccen = pPalm->max_tmajor/ pPalm->max_tminor; + pPalm->max_angle = pPalm->pti[pPalm->max_size_idx].tangle; + } + if(pPalm->palmflag) + { + TimerCancel(pPalm->palm_single_finger_timer); + pPalm->single_timer_expired = 0; + } + if(pPalm->biggest_tmajor < pPalm->max_tmajor) + pPalm->biggest_tmajor = pPalm->max_tmajor; + if(pPalm->biggest_wmajor < pPalm->max_wmajor) + pPalm->biggest_wmajor = pPalm->max_wmajor; + if(pPalm->bigger_wmajor < pPalm->max_wmajor) + pPalm->bigger_wmajor = pPalm->max_wmajor; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[maxidx:%d] cur_touched=%d, palmflag=%d, sum_size=%.f, max_wmajor=%.f, max_eccen=%.1f, max_angle=%.f\n", pPalm->max_size_idx, pPalm->cur_touched, pPalm->palmflag, pPalm->sum_size, pPalm->max_wmajor, pPalm->max_eccen, pPalm->max_angle); + XDBG_DEBUG(MGEST, "sum_size=%.f, max_tmajor=%.f, dispersionX=%.f, deviationX=%.f, dispersionY=%.f, deviationY=%.f\n", pPalm->sum_size, pPalm->max_tmajor, pPalm->dispersionX, pPalm->deviationX, pPalm->dispersionY, pPalm->deviationY); + XDBG_DEBUG(MGEST, "max_palm=%d\n", pPalm->max_palm); +#endif +} + +static void +GesturePalmUpdateAreaInfo(int type, int idx) +{ + int i; + PalmStatusPtr pPalm = &g_pGesture->palm; + + switch(type) + { + case ET_ButtonPress: + pPalm->finger_rects[idx].extents.x1 = pPalm->pti[idx].x - FINGER_WIDTH; + pPalm->finger_rects[idx].extents.x2 = pPalm->pti[idx].x + FINGER_WIDTH; + pPalm->finger_rects[idx].extents.y1 = pPalm->pti[idx].y - FINGER_HEIGHT; + pPalm->finger_rects[idx].extents.y2 = pPalm->pti[idx].y + FINGER_HEIGHT; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[P] [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->finger_rects[idx].extents.x1, pPalm->finger_rects[idx].extents.x2, pPalm->finger_rects[idx].extents.y1, pPalm->finger_rects[idx].extents.y2); + XDBG_DEBUG(MGEST, "[P] area [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif// __PALM_DETAIL_LOG__ + + if(pPalm->cur_touched == 1) + { + pixman_region_union(&pPalm->area, &pPalm->finger_rects[idx], &pPalm->finger_rects[idx]); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[P] cur:1 [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + } + else + { + pixman_region_union(&pPalm->area, &pPalm->finger_rects[idx], &pPalm->finger_rects[idx]); + for(i = 0 ; i < g_pGesture->num_mt_devices ; i++) + { + if(!pPalm->pti[i].touch_status) + continue; + + pixman_region_union(&pPalm->area, &pPalm->area, &pPalm->finger_rects[i]); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[P] cur:else [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", i, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + } + } + break; + + case ET_ButtonRelease: + break; + + case ET_Motion: + if (!pPalm->pti[idx].touch_status || (pPalm->pti[idx].tmajor == 0)) + return; + pPalm->finger_rects[idx].extents.x1 = pPalm->pti[idx].x - FINGER_WIDTH; + pPalm->finger_rects[idx].extents.x2 = pPalm->pti[idx].x + FINGER_WIDTH; + pPalm->finger_rects[idx].extents.y1 = pPalm->pti[idx].y - FINGER_HEIGHT; + pPalm->finger_rects[idx].extents.y2 = pPalm->pti[idx].y + FINGER_HEIGHT; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[M] [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->finger_rects[idx].extents.x1, pPalm->finger_rects[idx].extents.x2, pPalm->finger_rects[idx].extents.y1, pPalm->finger_rects[idx].extents.y2); + XDBG_DEBUG(MGEST, "[M] area [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + if(pPalm->cur_touched == 1) + { + pixman_region_union(&pPalm->area, &pPalm->finger_rects[idx], &pPalm->finger_rects[idx]); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[M] cur:1 [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + } + else + { + pixman_region_union(&pPalm->area, &pPalm->finger_rects[idx], &pPalm->finger_rects[idx]); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[M] cur:else:first [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", idx, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + + for(i = 0 ; i < g_pGesture->num_mt_devices ; i++) + { + if(!pPalm->pti[i].touch_status) + continue; + pixman_region_union(&pPalm->area, &pPalm->area, &pPalm->finger_rects[i]); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[M] cur:else [%d]: x1: %d, x2: %d, y1: %d, y2: %d\n", i, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2); +#endif//__PALM_DETAIL_LOG__ + } + } + break; + } +} + +void +GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + int idx = -1; + PalmStatusPtr pPalm = &g_pGesture->palm; + static int calc_touched = 0; + static int event_sum_palm_first_finger = 0, event_sum_palm_second_finger=0; + + if( device->id < g_pGesture->first_fingerid ) + return; + + idx = GestureGetFingerIndexFromDevice(device); + if( idx < 0 ) + return; + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[g_pGesture->num_pressed=%d]\n", g_pGesture->num_pressed); +#endif//__DETAIL_DEBUG__ + if(!g_pGesture->pTempPalmWin) + { + g_pGesture->pTempPalmWin = GestureGetEventsWindow(); + if(!g_pGesture->pTempPalmWin || g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "No events are grabbed/selected !\n"); +#endif//__PALM_DETAIL_LOG__ + g_pGesture->no_palm_events = TRUE; + if (g_pGesture->palm_rejection_mode == 0) + { + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + goto flush_or_drop; + } + else + { + g_pGesture->palm_filter_mask = 0; + } + } + } + GesturePalmDataUpdate(idx, type, ev, device); + GesturePalmUpdateAreaInfo(type, idx); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "[idx: %d: %d](%d, %d)max_tmajor: %lf, palmflag: %d, max_wmajor: %lf\n", idx, type, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->max_tmajor, pPalm->palmflag, pPalm->max_wmajor); + XDBG_DEBUG(MGEST, "bigger_wmajor: %lf, biggest_tmajor: %lf, biggest_wmajor: %lf\n", pPalm->bigger_wmajor, pPalm->biggest_tmajor, pPalm->biggest_wmajor); + XDBG_DEBUG(MGEST, "area: %d, deviationX: %lf, deviationY: %lf, dispersionX: %lf, dispersion: %lf\n", pPalm->area, pPalm->deviationX, pPalm->deviationY, pPalm->dispersionX, pPalm->dispersionY); +#endif + switch(type) + { + case ET_ButtonPress: + if( idx == 0 ) + event_sum_palm_first_finger = BTN_PRESSED; + else if( idx == 1) + event_sum_palm_second_finger = BTN_PRESSED; + pPalm->max_touched++; + + if( g_pGesture->num_pressed == 1 ) + { + pPalm->palm_single_finger_timer = TimerSet(pPalm->palm_single_finger_timer, 0, 50, GesturePalmSingleFingerTimerHandler, NULL); + } + else if(g_pGesture->num_pressed > 1) + { + TimerCancel(pPalm->palm_single_finger_timer); + } + break; + case ET_Motion: + if(pPalm->cur_touched == 0 || pPalm->pti[idx].touch_status != 1) + { + return; + } + if((pPalm->cur_touched == 1 && idx == 0 && event_sum_palm_first_finger == BTN_PRESSED) || + (pPalm->cur_touched == 2 && idx == 1 && event_sum_palm_second_finger == BTN_PRESSED)) + { + if(idx == 0) + { + event_sum_palm_first_finger = BTN_MOVING; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "First move detected!\n"); +#endif//__PALM_DETAIL_LOG__ + } + else // idx == 1 + { + event_sum_palm_second_finger = BTN_MOVING; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "Second finger First move detected!\n"); +#endif//__PALM_DETAIL_LOG__ + } + if (pPalm->palmflag < 1 && pPalm->biggest_tmajor < g_pGesture->palm_min_touch_major && pPalm->biggest_wmajor < g_pGesture->palm_min_width_major) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "No palm coming.\n"); +#endif//__PALM_DETAIL_LOG__ + Bool exist; + exist = GestureIsPalmEventInMIEQ(); +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "palm event exist: %d\n", exist); +#endif//__PALM_DETAIL_LOG__ + + if (exist) + { + pPalm->palmflag = 1; + g_pGesture->palm_detected = TRUE; + } + else + { + /* + * The following is the bezel condition for palm + * -- palm touch area can be smaller than that of non-bezel regions, so the threshold value is reduced. + */ + if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask) && + (pPalm->cx >= g_pGesture->screen_width - g_pGesture->palm_bezel || pPalm->cx < g_pGesture->palm_bezel) && + (pPalm->biggest_tmajor >= g_pGesture->palm_min_touch_major_bezel || pPalm->biggest_wmajor >= g_pGesture->palm_min_width_major_bezel)) + { + g_pGesture->palm_detected = TRUE; + break; + } + if(!(g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask) && + (pPalm->cy >= g_pGesture->screen_height - g_pGesture->palm_bezel || pPalm->cy < g_pGesture->palm_bezel) && + (pPalm->biggest_tmajor >= g_pGesture->palm_min_touch_major_bezel || pPalm->biggest_wmajor >= g_pGesture->palm_min_width_major_bezel)) + { + g_pGesture->palm_detected = TRUE; + break; + } + + if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->no_palm_events == TRUE) + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + g_pGesture->recognized_palm = 0; + if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)) + { + GesturePalmRecognize_FlickHorizen(type, -1); + } + if(!(g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask)) + { + GesturePalmRecognize_FlickVertical(type, -1); + } + if (g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL) + goto flush_or_drop; + } + } + else + { + g_pGesture->palm_detected = TRUE; + } + } + calc_touched++; + if(calc_touched == pPalm->cur_touched) + { + calc_touched = 0; + } + break; + case ET_ButtonRelease: + if( idx == 0 ) + event_sum_palm_first_finger = BTN_RELEASED; + else if( idx == 1) + event_sum_palm_second_finger = BTN_RELEASED; + if(calc_touched) + { + calc_touched--; + } + break; + } + if( g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE && g_pGesture->no_palm_events == TRUE) + { + g_pGesture->recognized_palm = 0; + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + goto flush_or_drop; + } + + if( GestureHasFingerEventMask(GestureNotifyFlick, 0) ) + { + if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)) + { + GesturePalmRecognize_FlickHorizen(type, idx); + } + if(!(g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask)) + { + GesturePalmRecognize_FlickVertical(type, idx); + } + } + + if(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL) + { + pixman_region_init(&pPalm->area); + + for( i = 0 ; i < MAX_MT_DEVICES ; i++ ) + { + pixman_region_init_rect (&pPalm->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T); + } + pPalm->palmflag = 0; + } + + switch(type) + { + case ET_ButtonPress: + break; + + case ET_ButtonRelease: + if(( g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL ) && ( pPalm->cur_touched == 0)) + goto flush_or_drop; + break; + + case ET_Motion: + break; + } +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "recognized_palm: 0x%x, palm_filter_mask: 0x%x, ehtype: %d\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask, g_pGesture->ehtype); +#endif//__PALM_DETAIL_LOG__ + if( g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL ) + { + if( !g_pGesture->recognized_palm ) + goto flush_or_drop; + } + + if( g_pGesture->recognized_palm ) + { + if( g_pGesture->ehtype == KEEP_EVENTS ) + GestureEventsDrop(); + g_pGesture->ehtype = IGNORE_EVENTS; + } + + return; + +flush_or_drop: + calc_touched = 0; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "GestureFlushOrDrop() !\n"); +#endif//__PALM_DETAIL_LOG__ + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + +} + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +void +GestureBezelRecognize(int type, InternalEvent *ev, DeviceIntPtr device) +{ + static OsTimerPtr bezel_finger_timer = NULL; + + BezelFlickStatusPtr pBezel = &g_pGesture->bezel; + int direction = 0; + int distance; + double angle; + static Time base_time = 0; + int idx = -1; + int i; + static int px=-1, py=-1; + static int mx=-1, my=-1; + static int rx=-1, ry=-1; + static int event_count=0; + + if(g_pGesture->enqueue_fulled == 1) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n"); +#endif//__BEZEL_DEBUG__ + goto bezel_failed; + } + + if( (PROPAGATE_EVENTS == g_pGesture->ehtype) || (device->id != g_pGesture->first_fingerid) ) + return; + + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if( device->id == g_pGesture->mt_devices[i]->id ) + { + idx = i; + break; + } + } +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[type: %d][g_pGesture->num_pressed=%d, x,y(%d, %d) ]\n", type, g_pGesture->num_pressed, ev->device_event.root_x, ev->device_event.root_x); + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, bezel_filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->bezel_filter_mask, g_pGesture->palm_filter_mask); +#endif//__BEZEL_DEBUG__ + + if (idx < 0) + return; + if(g_pGesture->recognized_gesture || g_pGesture->recognized_palm) + goto bezel_failed; + if(g_pGesture->num_pressed > 1) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "Not single finger g_pGesture->num_pressed: %d\n", g_pGesture->num_pressed); +#endif//__BEZEL_DEBUG__ + goto bezel_failed; + } + if(pBezel->is_active == BEZEL_END) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "Bezel state is END pBezel->is_active: %d\n", pBezel->is_active); + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, bezel_filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->bezel_filter_mask, g_pGesture->palm_filter_mask); +#endif//__BEZEL_DEBUG__ + goto bezel_failed; + } + + switch(type) + { + case ET_ButtonPress: + base_time = GetTimeInMillis(); + px = ev->device_event.root_x; + py = ev->device_event.root_y; +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] pBezel->is_active: %d, g_pGesture->num_pressed: %d, idx: %d\n", pBezel->is_active, g_pGesture->num_pressed, idx); + XDBG_DEBUG(MGEST, "[P] g_pGesture->fingers[%d].p: (%d, %d)\n", idx, px,py); +#endif//__BEZEL_DEBUG__ + if( (pBezel->is_active == BEZEL_ON) && ((g_pGesture->num_pressed == 1) && (idx == 0)) ) + { + if( ( px < pBezel->top_left.width) && ( py < pBezel->top_left.height) ) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] top_left\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_START; + pBezel->bezelStatus = BEZEL_TOP_LEFT; + } + else if( (px > (720 - pBezel->top_right.width)) && ( py < pBezel->top_right.height) ) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] top_right\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_START; + pBezel->bezelStatus = BEZEL_TOP_RIGHT; + } + else if( (px < pBezel->bottom_left.width) && ( py > (1280 - pBezel->bottom_left.height)) ) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] bottom_left\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_START; + pBezel->bezelStatus = BEZEL_BOTTOM_LEFT; + } + else if( (px > (720 - pBezel->bottom_right.width)) && ( py > (1280 - pBezel->bottom_right.height)) ) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] bottom_right\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_START; + pBezel->bezelStatus = BEZEL_BOTTOM_RIGHT; + } + else + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[P] None\n"); +#endif//__BEZEL_DEBUG__ + pBezel->bezelStatus = NO_BEZEL; + goto bezel_failed; + } + } + if(pBezel->is_active == BEZEL_START) + { + bezel_finger_timer = TimerSet(bezel_finger_timer, 0, 500, GestureBezelSingleFingerTimerHandler, NULL); + } + else + { + TimerCancel(bezel_finger_timer); + } + break; + case ET_Motion: + if(px <0 || py < 0) + return; + mx = ev->device_event.root_x; + my = ev->device_event.root_y; + event_count++; + if( (g_pGesture->bezel.bezel_angle_moving_check) && (event_count >= 10)) + { + angle = get_angle(px, py, mx, my); + event_count = 0; + if(!GestureBezelAngleRecognize(pBezel->bezelStatus, pBezel->flick_distance, angle)) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[M] moving limit!\n"); +#endif//__BEZEL_DEBUG__ + TimerCancel(bezel_finger_timer); + goto bezel_failed; + } + } + break; + case ET_ButtonRelease: + rx = ev->device_event.root_x; + ry = ev->device_event.root_y; + if( (g_pGesture->num_pressed == 0) && (g_pGesture->inc_num_pressed == 1) && (pBezel->is_active == BEZEL_START) ) + { + angle = get_angle(px, py, rx, ry); + distance = get_distance(px, py, rx, ry); + Time duration = GetTimeInMillis() - base_time; +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[R] bezelStatus: %d, distance: %d, angle: %lf\n", pBezel->bezelStatus, distance, angle); +#endif//__BEZEL_DEBUG__ + int res = GestureBezelAngleRecognize(pBezel->bezelStatus, distance, angle); + if(res) + { +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[R] Bezel Success\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_DONE; + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + TimerCancel(bezel_finger_timer); + + if( (0.0 < angle) && (angle < RAD_90DEG)) + direction = FLICK_NORTHEASTWARD; + else if(angle < RAD_180DEG) + direction = FLICK_NORTHWESTWARD; + + if( GestureHasFingerEventMask(GestureNotifyFlick, 1) ) + GestureHandleGesture_Flick(1, distance, duration, direction); + goto bezel_cleanup; + } +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[R] Bezel failed\n"); +#endif//__BEZEL_DEBUG__ + goto bezel_failed; + } + break; + } + return; +bezel_failed: +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[F] Bezel failed\n"); +#endif//__BEZEL_DEBUG__ + pBezel->is_active = BEZEL_END; + g_pGesture->bezel_filter_mask |= BezelFlickFilterMask; + goto bezel_cleanup; + return; +bezel_cleanup: +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[F] Bezel cleanup\n"); +#endif//__BEZEL_DEBUG__ + TimerCancel(bezel_finger_timer); + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + bezel_finger_timer = NULL; + base_time = 0; + px=py=mx=my=rx=ry=-1; + event_count = 0; +} +#endif + +static EventQueuePtr +GestureGetMIEQ(void) +{ + if (*checkForInput[0] == *checkForInput[1]) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "mieq is empty !\n"); +#endif//__DETAIL_DEBUG__ + return NULL; + } + + EventQueuePtr mieqEQPtr = NULL; + mieqEQPtr = mieqGetEventQueuePtr(); + + if (!mieqEQPtr) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "mieqEQPtr is NULL !\n"); +#endif//__DETAIL_DEBUG__ + + return NULL; + } + + int num = mieqNumEnqueued(mieqEQPtr); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, " num of event in mieq = %d\n", num); +#endif//__DETAIL_DEBUG__ + if (num <= 0) + return NULL; + + return mieqEQPtr; +} + +static Bool +GestureIsEventInMIEQ(int finger_index, enum EventType type) +{ + EventQueuePtr mieqEQPtr = NULL; + mieqEQPtr = GestureGetMIEQ(); + if (!mieqEQPtr) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "failed to get mieq\n"); +#endif//__DETAIL_DEBUG__ + return FALSE; + } + + int deviceid = GestureGetDeviceIdFromFingerIndex(finger_index); + if (deviceid < 0) + { + XDBG_ERROR(MGEST, "Failed to get deviceid from finger index !\n"); + return FALSE; + } + + EventRec *e = NULL; + static InternalEvent event; + HWEventQueueType head, tail; + head = mieqEQPtr->head; + tail = mieqEQPtr->tail; + + while (head != tail) + { + e = &mieqEQPtr->events[head]; + if (e) + { + event = *e->events; + + if (e->pDev && (deviceid == e->pDev->id) && (event.any.type == type)) + { + return TRUE; + } + } + + head = (head + 1) % mieqEQPtr->nevents; + } + + return FALSE; +} + +static Bool +GestureIsPalmEventInMIEQ(void) +{ + EventQueuePtr mieqEQPtr = NULL; + mieqEQPtr = GestureGetMIEQ(); + if (!mieqEQPtr) + { +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "failed to get mieq\n"); +#endif//__PALM_DETAIL_LOG__ + return FALSE; + } + + EventRec *e = NULL; + static InternalEvent event; + HWEventQueueType head, tail; + head = mieqEQPtr->head; + tail = mieqEQPtr->tail; + + while (head != tail) + { + e = &mieqEQPtr->events[head]; + if (e) + { + event = *e->events; + + if (GestureIsPalmEvent(&event)) + { + return TRUE; + } + } + + head = (head + 1) % mieqEQPtr->nevents; + } + + return FALSE; +} + +static Bool +GestureIsPalmEvent(InternalEvent *event) +{ + int wmajor_idx = g_pGesture->wmajor_idx; + int tmajor_idx = g_pGesture->tmajor_idx; + int tpalm_idx = g_pGesture->tpalm_idx; + + double width_major = 0.0f; + double touch_major = 0.0f; + double touch_palm = 0.0f; + + if (event->any.type != ET_ButtonPress && event->any.type != ET_Motion && event->any.type != ET_ButtonRelease) + return FALSE; + + DeviceEvent *de = &event->device_event; + + if (!de) + { + XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n"); + return FALSE; + } + + if ((wmajor_idx < 0) || (tmajor_idx < 0) || (tpalm_idx < 0)) + { + XDBG_WARNING(MGEST, "One or more of axes are not supported !\n"); + return FALSE; + } + + width_major = de->valuators.data[wmajor_idx]; + touch_major = de->valuators.data[tmajor_idx]; + touch_palm = de->valuators.data[tpalm_idx]; +#ifdef __PALM_DETAIL_LOG__ + XDBG_DEBUG(MGEST, "width_major: %.f, touch_major: %.f, touch_palm: %.f\n", width_major, touch_major, touch_palm); +#endif//__PALM_DETAIL_LOG__ + + if (touch_palm >= 1 || touch_major >= g_pGesture->palm_min_touch_major || width_major >= g_pGesture->palm_min_width_major) + return TRUE; + return FALSE; +} + +static int +GestureGetFingerIndexFromDevice(DeviceIntPtr device) +{ + int i; + + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if( device->id == g_pGesture->mt_devices[i]->id ) + { + return i; + } + } + + return -1; +} + +static int +GestureGetDeviceIdFromFingerIndex(int finger_index) +{ + if (g_pGesture->num_mt_devices <= finger_index) + return -1; + + return g_pGesture->mt_devices[finger_index]->id; +} + + +void +GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + static OsTimerPtr single_finger_timer = NULL; + int idx = -1; + + if( PROPAGATE_EVENTS == g_pGesture->ehtype || + device->id < g_pGesture->first_fingerid ) + return; + + idx = GestureGetFingerIndexFromDevice(device); + + if( idx < 0 ) + return; +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[type: %d][g_pGesture->num_pressed=%d, x,y(%d, %d) ]\n", type, g_pGesture->num_pressed, ev->device_event.root_x, ev->device_event.root_x); + XDBG_DEBUG(MGEST, "[inc_num_pressed: %d]\n", g_pGesture->inc_num_pressed); +#ifdef _F_SUPPORT_BEZEL_FLICK_ + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, bezel_filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->bezel_filter_mask, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "[recognized_gesture: 0x%x, bezel_recognize_mask: 0x%x, recognized_palm: 0x%x\n", g_pGesture->recognized_gesture, g_pGesture->bezel_recognized_mask, g_pGesture->recognized_palm); +#else + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "[recognized_gesture: 0x%x, recognized_palm: 0x%x\n", g_pGesture->recognized_gesture, g_pGesture->recognized_palm); +#endif +#endif//__DETAIL_DEBUG__ + + + 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; + + if( g_pGesture->num_pressed == 1 ) + { + single_finger_timer = TimerSet(single_finger_timer, 0, g_pGesture->tap_repeated ? 80 : g_pGesture->singlefinger_threshold, 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 || g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "[g_pGesture->num_pressed=%d] No events were selected !\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; + + 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__ + XDBG_DEBUG(MGEST, "[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_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( (g_pGesture->inc_num_pressed < 2) && (idx == 0)) + { + g_pGesture->event_sum[0] += BTN_MOVING; +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "no seconds finger comming\n"); +#endif//__DETAIL_DEBUG__ + if(!g_pGesture->tap_repeated) + { + if(g_pGesture->event_sum[0] >= 3) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "single finger!\n"); +#endif//__DETAIL_DEBUG__ + Bool exist; + exist = GestureIsEventInMIEQ(1, ET_ButtonPress); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "two finger touch in queue, exist: %d\n", exist); +#endif//__DETAIL_DEBUG__ + if (exist) + g_pGesture->event_sum[0] -= BTN_MOVING; + else + { + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + goto flush_or_drop; + } + } + } + else + { + if(ABS(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > FINGER_WIDTH + || ABS(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > FINGER_HEIGHT) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "tap repeat Moving Limit Exceeded.\n"); +#endif//__DETAIL_DEBUG__ + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + goto flush_or_drop; + } + else if(g_pGesture->event_sum[0] >= 15) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "tap repeat Moving Limit Exceeded.\n"); +#endif//__DETAIL_DEBUG__ + Bool exist; + exist = GestureIsEventInMIEQ(1, ET_ButtonPress); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "two finger touch in queue, exist: %d\n", exist); +#endif//__DETAIL_DEBUG__ + if (exist) + g_pGesture->event_sum[0] -= BTN_MOVING; + else + { + 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; + + 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__ + XDBG_DEBUG(MGEST, "[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; + + if( g_pGesture->num_pressed <= 0 ) + { +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "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, 0); + } + 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__ +#ifdef _F_SUPPORT_BEZEL_FLICK_ + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, bezel_filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->bezel_filter_mask, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "[recognized_gesture: 0x%x, bezel_recognize_mask: 0x%x, recognized_palm: 0x%x\n", g_pGesture->recognized_gesture, g_pGesture->bezel_recognized_mask, g_pGesture->recognized_palm); +#else + XDBG_DEBUG(MGEST, "[filter_mask: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->filter_mask, g_pGesture->palm_filter_mask); + XDBG_DEBUG(MGEST, "[recognized_gesture: 0x%x, recognized_palm: 0x%x\n", g_pGesture->recognized_gesture, g_pGesture->recognized_palm); +#endif +#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: + TimerCancel(single_finger_timer); +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "GestureFlushOrDrop() !\n"); +#endif//__DETAIL_DEBUG__ + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } +} + + +ErrorStatus GestureFlushOrDrop(void) +{ + ErrorStatus err = ERROR_NONE; + PalmStatusPtr pPalm = &g_pGesture->palm; + int i; +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "recognized_gesture: 0x%x, filter_mask: 0x%x\n", g_pGesture->recognized_gesture, g_pGesture->filter_mask); + XDBG_DEBUG(MGEST, "recognized_palm: 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask); +#ifdef _F_SUPPORT_BEZEL_FLICK_ + XDBG_DEBUG(MGEST, "bezel_recognized_mask: 0x%x, bezel_filter_mask: 0x%x\n", g_pGesture->bezel_recognized_mask, g_pGesture->bezel_filter_mask); +#endif +#endif//__DETAIL_DEBUG__ + + if(g_pGesture->recognized_gesture || g_pGesture->recognized_palm +#ifdef _F_SUPPORT_BEZEL_FLICK_ + || g_pGesture->bezel_recognized_mask) +#else + ) +#endif + { + g_pGesture->ehtype = IGNORE_EVENTS; + GestureEventsDrop(); + if(g_pGesture->recognized_palm) + err = GestureRegionsReinit(); + //memset(pPalm->pti, 0, sizeof(pPalm->pti[MAX_MT_DEVICES])); + for(i=0; ipti[i].touch_status = 0; + pPalm->pti[i].tangle = 0.0f; + pPalm->pti[i].wmajor = 0.0f; + pPalm->pti[i].tmajor = 0.0f; + pPalm->pti[i].tminor = 0.0f; + pPalm->pti[i].tpalm = 0.0f; + } + if( ERROR_NONE != err ) + return err; + } + else if((g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL) && (g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL) +#ifdef _F_SUPPORT_BEZEL_FLICK_ + && (g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) +#else + ) +#endif + { + g_pGesture->ehtype = PROPAGATE_EVENTS; + if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE) + { + GestureEventsDrop(); + } + else + { + err = GestureEventsFlush(); + if( ERROR_NONE != err ) + return err; + } + err = GestureRegionsReinit(); + for(i=0; ipti[i].touch_status = 0; + pPalm->pti[i].tangle = 0.0f; + pPalm->pti[i].wmajor = 0.0f; + pPalm->pti[i].tmajor = 0.0f; + pPalm->pti[i].tminor = 0.0f; + pPalm->pti[i].tpalm = 0.0f; + } + if( ERROR_NONE != err ) + return err; + + g_pGesture->pTempWin = NULL; + g_pGesture->inc_num_pressed = 0; + g_pGesture->event_sum[0] = 0; + } + + return ERROR_NONE; +} + +void +GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + PalmStatusPtr pPalm = &g_pGesture->palm; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + BezelFlickStatusPtr pBezel = &g_pGesture->bezel; +#endif +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "(%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 ) + { +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "SYNC_BEGIN\n"); +#endif//__DEBUG_EVENT_HANDLER + g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_BEGIN; + + if(g_pGesture->is_active) + { + g_pGesture->ehtype = KEEP_EVENTS; + g_pGesture->filter_mask = 0; + g_pGesture->recognized_gesture = 0; + g_pGesture->num_pressed = 0; + g_pGesture->palm_filter_mask = 0; + g_pGesture->recognized_palm= 0; + g_pGesture->hold_detector_activate = 1; + g_pGesture->has_hold_grabmask = 0; + pPalm->palmflag = 0; + pPalm->single_timer_expired = 0; + pPalm->biggest_tmajor = 0; + pPalm->biggest_wmajor = 0; + pPalm->bigger_wmajor = 0; + g_pGesture->enqueue_fulled = 0; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + pBezel->is_active = BEZEL_ON; + g_pGesture->bezel_filter_mask = 0; + g_pGesture->bezel_recognized_mask = 0; +#endif + for( i=0 ; i < g_pGesture->num_mt_devices ; i++ ) + g_pGesture->fingers[i].ptime = 0; + } + g_pGesture->stylusInfo.stylus_id = 0; + g_pGesture->stylusInfo.pen_detected = FALSE; + g_pGesture->no_palm_events = FALSE; + g_pGesture->stylusInfo.fake_events = FALSE; + g_pGesture->palm_detected = FALSE; + memset(&g_pGesture->last_touches, 0, sizeof(g_pGesture->last_touches)); + } + else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync ) + { +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "SYNC_END\n"); +#endif//__DEBUG_EVENT_HANDLER + g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END; + g_pGesture->touch_cancel_status = FALSE; + + if(g_pGesture->is_active) + { + g_pGesture->ehtype = PROPAGATE_EVENTS; + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + pPalm->cur_touched = 0; + pPalm->palmflag = 0; + pPalm->max_palm = 0; + g_pGesture->pTempPalmWin = NULL; + if(pPalm->palm_single_finger_timer) + TimerCancel(pPalm->palm_single_finger_timer); + g_pGesture->pTempWin = NULL; + g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0; + g_pGesture->event_sum[0] = 0; + pPalm->max_touched = 0; + g_pGesture->hold_detected = FALSE; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + pBezel->is_active = BEZEL_END; + g_pGesture->bezel_filter_mask = BezelFlickFilterMask; +#endif + } + for(i=0; istylusInfo.t_status[i].status = BTN_RELEASED; + } + } +} + +static int +GestureGetMTToolValuator(InternalEvent *ev, DeviceIntPtr device) +{ + int mt_tool_idx = g_pGesture->mt_tool_idx; + double mt_tool = 0.0f; + + DeviceEvent *de = &ev->device_event; + + if (!de) + { + XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n"); + return -1; + } + + if (0 > mt_tool_idx) + { + XDBG_WARNING(MGEST, "One or more of axes are not supported !\n"); + return -1; + } + + if (ev->any.type == ET_ButtonPress || ev->any.type == ET_ButtonRelease) + { + if (device->id == g_pGesture->master_pointer->id && g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid) + de->valuators.data[mt_tool_idx] = 1; + + if (g_pGesture->stylusInfo.stylus_id == device->id) + de->valuators.data[mt_tool_idx] = 1; + } + + mt_tool = de->valuators.data[mt_tool_idx]; + + return (int)mt_tool; +} + +static void +GestureRegisterTouchInfo(InternalEvent *ev, DeviceIntPtr device) +{ + int idx; + + idx = GestureGetFingerIndexFromDevice(device); + if (idx < 0) + { + if (device->id != g_pGesture->master_pointer->id) + XDBG_WARNING(MGEST, "Failed to get correct idx(%d) device->id: %d, master_pointer: %d\n", idx, device->id, g_pGesture->master_pointer->id); + return; + } + switch(ev->any.type) + { + case ET_ButtonPress: + g_pGesture->stylusInfo.t_status[idx].status = BTN_PRESSED; + break; + case ET_Motion: + if (g_pGesture->stylusInfo.t_status[idx].status == BTN_PRESSED) + g_pGesture->stylusInfo.t_status[idx].status = BTN_MOVING; + break; + case ET_ButtonRelease: + g_pGesture->stylusInfo.t_status[idx].status = BTN_RELEASED; + break; + default: + XDBG_WARNING(MGEST, "unhandled event type(%d)\n", ev->any.type); + break; + } + g_pGesture->stylusInfo.t_status[idx].cx = ev->device_event.root_x; + g_pGesture->stylusInfo.t_status[idx].cy = ev->device_event.root_y; +} + +static void +GestureSetToolData(InternalEvent *ev, double val_tool) +{ + int mt_tool_idx = g_pGesture->mt_tool_idx; + double mt_tool = 0.0f; + + DeviceEvent *de = &ev->device_event; + + if (!de) + { + XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n"); + return; + } + + if (0 > mt_tool_idx) + { + XDBG_WARNING(MGEST, "One or more of axes are not supported !\n"); + return; + } + de->valuators.data[mt_tool_idx] = val_tool; +} + +static void +GestureCleanupTouch(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + ErrorStatus err; + int i; + if (g_pGesture->stylusInfo.stylus_id == 0 && g_pGesture->stylusInfo.pen_detected == FALSE) + g_pGesture->stylusInfo.stylus_id = device->id; + + if (g_pGesture->ehtype == KEEP_EVENTS) + { + GestureEventsDrop(); + g_pGesture->ehtype = PROPAGATE_EVENTS; + } + else if (g_pGesture->stylusInfo.pen_detected == FALSE && g_pGesture->ehtype == PROPAGATE_EVENTS) + { + g_pGesture->stylusInfo.pen_detected = TRUE; + g_pGesture->stylusInfo.fake_events = TRUE; + for(i=0; istylusInfo.t_status[i].status == BTN_PRESSED || g_pGesture->stylusInfo.t_status[i].status == BTN_MOVING) + { + InternalEvent release_ev; + memcpy(&release_ev, ev, sizeof(InternalEvent)); + release_ev.any.time = ev->any.time; + release_ev.any.type = ET_ButtonRelease; + + release_ev.device_event.detail.button = 1; + release_ev.device_event.type = ET_ButtonRelease; + release_ev.device_event.root_x = g_pGesture->stylusInfo.t_status[i].cx; + release_ev.device_event.root_y = g_pGesture->stylusInfo.t_status[i].cy; + release_ev.device_event.deviceid = g_pGesture->mt_devices[i]->id; + g_pGesture->stylusInfo.t_status[i].status = BTN_RELEASED; + GestureSetToolData(&release_ev, (double)0); + + GestureHandleButtonReleaseEvent(screen_num, &release_ev, g_pGesture->mt_devices[i]); + if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid) + { + InternalEvent release_mev; + memcpy(&release_mev, ev, sizeof(InternalEvent)); + release_mev.any.time = ev->any.time; + release_mev.any.type = ET_ButtonRelease; + + release_mev.device_event.detail.button = 1; + release_mev.device_event.type = ET_ButtonRelease; + release_mev.device_event.root_x = g_pGesture->stylusInfo.t_status[i].cx; + release_mev.device_event.root_y = g_pGesture->stylusInfo.t_status[i].cy; + release_mev.device_event.deviceid = g_pGesture->master_pointer->id; + GestureSetToolData(&release_mev, (double)0); + + GestureHandleButtonReleaseEvent(screen_num, &release_mev, g_pGesture->master_pointer); + } + } + } + g_pGesture->stylusInfo.fake_events = FALSE; + } + g_pGesture->stylusInfo.pen_detected = TRUE; + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + g_pGesture->recognized_gesture = 0; + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; + g_pGesture->recognized_palm = 0; +} + +static void +GestureChangeEventToFirstFingerEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + InternalEvent master_ev; + ev->device_event.deviceid = g_pGesture->first_fingerid; + + switch(ev->any.type) + { + case ET_ButtonPress: + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed++; + break; + case ET_ButtonRelease: + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed--; + break; + default: + break; + } + memcpy(&master_ev, ev, sizeof(InternalEvent)); + g_pGesture->mt_devices[0]->public.processInputProc(ev, g_pGesture->mt_devices[0]); + + master_ev.device_event.deviceid = g_pGesture->master_pointer->id; + g_pGesture->master_pointer->public.processInputProc(&master_ev, g_pGesture->master_pointer); +} + +void +GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n", + g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif//__DEBUG_EVENT_HANDLER__ + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + XDBG_DEBUG(MGEST, "Ignore Button Press event after touch cancel generated. \n"); + return; + } + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_PRESSED; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->stylus_able) + { + int isStylus = GestureGetMTToolValuator(ev, device); + +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id); +#endif//__DEBUG_EVENT_HANDLER__ + + if (g_pGesture->stylusInfo.pen_detected == FALSE) + { + if (!isStylus) + { + GestureRegisterTouchInfo(ev, device); + } + else + { + GestureCleanupTouch(screen_num, ev, device); + } + } + if (g_pGesture->stylusInfo.pen_detected == TRUE) + { + if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id )) + { + if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id)) + { + return; + } + } + else if (device->id != g_pGesture->first_fingerid) + { + GestureChangeEventToFirstFingerEvent(screen_num, ev, device); + return; + } + } + } + + 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 ) + { + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed++; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_ButtonPress, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_ButtonPress, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonPress, ev, device) + else + g_pGesture->ehtype = PROPAGATE_EVENTS; + } + } + else + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_ButtonPress, ev, device); + break; + + case PROPAGATE_EVENTS: + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed++; + if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE) + { + device->public.processInputProc(ev, device); + } + else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE)) + { + device->public.processInputProc(ev, device); + } + GestureHoldDetector(ET_ButtonPress, ev, device); + break; + + case IGNORE_EVENTS: + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed++; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_ButtonPress, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_ButtonPress, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonPress, ev, device); + } + break; + + default: + break; + } +} + +void +GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n", + g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif//__DEBUG_EVENT_HANDLER__ + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + XDBG_DEBUG(MGEST, "Ignore Button Press event after touch cancel generated. \n"); + return; + } + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_MOVING; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->stylus_able) + { + int isStylus = GestureGetMTToolValuator(ev, device); + +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id); +#endif//__DEBUG_EVENT_HANDLER__ + + if (g_pGesture->stylusInfo.pen_detected == FALSE) + { + if (!isStylus) + { + GestureRegisterTouchInfo(ev, device); + } + else + { + GestureCleanupTouch(screen_num, ev, device); + } + } + if (g_pGesture->stylusInfo.pen_detected == TRUE) + { + if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id )) + { + if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id)) + { + return; + } + } + else if (device->id != g_pGesture->first_fingerid) + { + GestureChangeEventToFirstFingerEvent(screen_num, ev, device); + return; + } + } + } + + 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 ) + { +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_Motion, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_Motion, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_Motion, ev, device) + else + g_pGesture->ehtype = PROPAGATE_EVENTS; + } + } + else + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_Motion, ev, device); + break; + + case PROPAGATE_EVENTS: + if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE) + { + device->public.processInputProc(ev, device); + } + else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE)) + { + device->public.processInputProc(ev, device); + } + GestureHoldDetector(ET_Motion, ev, device); + break; + + case IGNORE_EVENTS: +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_Motion, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_Motion, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_Motion, ev, device); + } + break; + + default: + break; + } + +} + +void +GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n", + g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif//__DEBUG_EVENT_HANDLER__ + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + XDBG_DEBUG(MGEST, "Ignore Button Press event after touch cancel generated. \n"); + return; + } + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_RELEASED; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->stylus_able) + { + int isStylus = GestureGetMTToolValuator(ev, device); + +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id); +#endif//__DEBUG_EVENT_HANDLER__ + + if (g_pGesture->stylusInfo.pen_detected == FALSE) + { + if (!isStylus) + { + GestureRegisterTouchInfo(ev, device); + } + else + { + GestureCleanupTouch(screen_num, ev, device); + } + } + if (g_pGesture->stylusInfo.pen_detected == TRUE) + { + if (g_pGesture->stylusInfo.fake_events == TRUE) + { + goto deliver_event; + } + if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id )) + { + if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id)) + { + return; + } + } + else if (device->id != g_pGesture->first_fingerid) + { + GestureChangeEventToFirstFingerEvent(screen_num, ev, device); + return; + } + } + } +deliver_event: + 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 ) + { + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed--; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_ButtonRelease, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_ButtonRelease, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonRelease, ev, device) + else + g_pGesture->num_mt_devices = PROPAGATE_EVENTS; + } + } + else + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_ButtonRelease, ev, device); + break; + + case PROPAGATE_EVENTS: +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT + if( IsMaster(device) && ev->any.type == ET_ButtonRelease ) + { + if( g_pGesture->anr_window == NULL ) + { + g_pGesture->anr_window = _GestureFindANRWindow(device); + } + Time current_time; + + // Send event to the e17 process. + current_time = GetTimeInMillis(); + if( g_pGesture->anr_window != NULL ) + { + // Check anr_window validation. + if( dixLookupWindow(&g_pGesture->anr_window, prop_anr_event_window_xid, serverClient, DixSetPropAccess) != BadWindow ) + { + if( serverClient->devPrivates != NULL ) + dixChangeWindowProperty (serverClient, g_pGesture->anr_window, prop_anr_in_input_event, + XA_CARDINAL, 32, PropModeReplace, 1, ¤t_time, TRUE); + } + else + { + prop_anr_event_window_xid = 0; + g_pGesture->anr_window = NULL; + } + XDBG_DEBUG(MGEST, "Release TOUCH!! devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis()); + } + } +#endif + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed--; + if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE) + { + device->public.processInputProc(ev, device); + } + else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE)) + { + device->public.processInputProc(ev, device); + } + GestureHoldDetector(ET_ButtonRelease, ev, device); + break; + + case IGNORE_EVENTS: + if(!(device->id < g_pGesture->first_fingerid)) + g_pGesture->num_pressed--; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + GestureBezelRecognize(ET_ButtonRelease, ev, device); +#endif + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + GestureRecognize(ET_ButtonRelease, ev, device); + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if (PalmRecognize) + _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonRelease, ev, device); + } + break; + + default: + break; + } +} + +void +GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_HANDLER__ + XDBG_DEBUG(MGEST, "devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis()); +#endif//__DEBUG_EVENT_HANDLER__ + static int find_dev_false_count = 0; + + if(DPMSPowerLevel == DPMSModeOff) + { + XDBG_INFO(MGEST, "LCD status : Off\n"); + + { + int i; + for(i = 0 ; i < NUM_PASSKEYS ; i++) + { + if(0 == g_pGesture->pass_keycodes[i]) + break; + + if(g_pGesture->pass_keycodes[i] == ev->device_event.detail.key) + { + XDBG_SECURE(MGEST, "Pass KeyPress (devid:%d, keycode:%d) during LCD Off!\n", device->id, ev->device_event.detail.key); + goto handle_keypress; + } + } + + XDBG_SECURE(MGEST, "Ignore KeyPress (devid:%d, keycode:%d) during LCD Off!\n", device->id, ev->device_event.detail.key); + return; + } + } + +handle_keypress: + if (g_pGesture->touchkey_id <= 0 && find_dev_false_count < 10) + { + DeviceIntPtr dev; + find_dev_false_count++; + + for( dev = inputInfo.keyboard ; dev; dev = dev->next ) + { + if(strcasestr(dev->name, "touchkey")) + { + g_pGesture->touchkey_id = dev->id; + find_dev_false_count = 0; + break; + } + } + } + + if((g_pGesture->mtsync_status != MTOUCH_FRAME_SYNC_END) && (device->id == g_pGesture->touchkey_id)) + { + if(ev->device_event.detail.key == 177) + XDBG_INFO(MGEST, "Ignore TouchKey KEY_MENU (devid:%d)\n", device->id); + else if (ev->device_event.detail.key == 166) + XDBG_INFO(MGEST, "Ignore TouchKey KEY_BACK (devid:%d)\n", device->id); + else + XDBG_SECURE(MGEST, "Ignore TouchKey KeyPress (devid:%d, keycode:%d)\n", device->id, ev->device_event.detail.key); + return; + } + + device->public.processInputProc(ev, device); +} + +void +GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + if (g_pGesture->pass_keycodes[3] == ev->device_event.detail.key) + { + XDBG_SECURE(MGEST, "TIME = %d, keycode = %d\n", ev->any.time, ev->device_event.detail.key); + } + device->public.processInputProc(ev, device); +} + +static ErrorStatus +GestureEnableEventHandler(InputInfoPtr pInfo) + { + Bool res; + GestureDevicePtr pGesture = pInfo->private; + + res = GestureInstallResourceStateHooks(); + + if( !res ) + { + XDBG_ERROR(MGEST, "Failed on GestureInstallResourceStateHooks() !\n"); + return ERROR_ABNORMAL; + } + + res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES); + + if( !res ) + { + XDBG_ERROR(MGEST, "Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES); + goto failed; + } + + res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected); + + if( !res ) + { + XDBG_ERROR(MGEST, "Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n"); + goto failed; + } + + return ERROR_NONE; + +failed: + GestureUninstallResourceStateHooks(); + GestureUnsetMaxNumberOfFingers(); + + return ERROR_ABNORMAL; +} + +static ErrorStatus +GestureDisableEventHandler(void) +{ + ErrorStatus err = ERROR_NONE; + + mieqSetHandler(ET_KeyPress, NULL); + mieqSetHandler(ET_KeyRelease, NULL); + mieqSetHandler(ET_ButtonPress, NULL); + mieqSetHandler(ET_ButtonRelease, NULL); + mieqSetHandler(ET_Motion, NULL); + mieqSetHandler(ET_MTSync, NULL); + + err = GestureFiniEQ(); + + if( ERROR_INVALPTR == err ) + { + XDBG_ERROR(MGEST, "EQ is invalid or was freed already !\n"); + } + + GestureRegisterCallbacks(NULL, NULL); + GestureUninstallResourceStateHooks(); + + return err; +} + +static void +GestureRegisterDeviceInfo(DeviceIntPtr device) +{ + InputInfoPtr pInfo = device->public.devicePrivate; + GestureDevicePtr pGesture = pInfo->private; + DeviceIntPtr dev; + ScreenPtr pScreen = miPointerCurrentScreen(); + int width = 0, height = 0; + int idx = 0; + int i; + + XDBG_INFO(MGEST, "Get devices information\n"); + + for (i=0; imt_devices[i] = NULL; + } + + for( dev = inputInfo.pointer ; dev; dev = dev->next ) + { + if(IsMaster(dev) && IsPointerDevice(dev)) + { + pGesture->master_pointer = dev; + XDBG_INFO(MGEST, "[id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name); + continue; + } + + if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev)) + { + pGesture->xtest_pointer = dev; + XDBG_INFO(MGEST, "[id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name); + continue; + } + + if(IsPointerDevice(dev)) + { + if( idx >= MAX_MT_DEVICES ) + { + XDBG_WARNING(MGEST, "Number of mt device is over MAX_MT_DEVICES(%d) !\n", + MAX_MT_DEVICES); + continue; + } + if (strcasestr(dev->name, "Touchscreen")) + { + pGesture->mt_devices[idx] = dev; + XDBG_INFO(MGEST, "[id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name); + ErrorF("[id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name); + GesturePalmGetAbsAxisInfo(dev); + idx++; + } + } + } + + if( !pGesture->master_pointer || !pGesture->xtest_pointer ) + { + XDBG_ERROR(MGEST, "Failed to get info of master pointer or XTest pointer !\n"); + pGesture->num_mt_devices = 0; + + return; + } + + pGesture->num_mt_devices = idx; + + if( !pGesture->num_mt_devices ) + { + XDBG_ERROR(MGEST, "Failed to mt device information !\n"); + pGesture->num_mt_devices = 0; + pGesture->first_fingerid = -1; + return; + } + + pGesture->first_fingerid = pGesture->mt_devices[0]->id; + memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices); + + pGesture->pRootWin = RootWindow(pGesture->master_pointer); + + if(g_pGesture->palm_misc.enabled) + GesturePalmGetScreenInfo(); + + g_pGesture->pTempWin = NULL; + g_pGesture->pTempPalmWin = NULL; + g_pGesture->inc_num_pressed = 0; + + if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() ) + { + goto failed; + } + + if (pScreen) + { + pGesture->screen_width = pScreen->width; + pGesture->screen_height = pScreen->height; + XDBG_ERROR(MGEST, "screen_width = %d, screen_height = %d\n", pGesture->screen_width, pGesture->screen_height); + } + else + { + XDBG_ERROR(MGEST, "Fail to get current screen size\n"); + } + + mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent); + mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent); + mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent); + mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent); + mieqSetHandler(ET_Motion, GestureHandleMotionEvent); + mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent); + + return; + +failed: + + GestureUninstallResourceStateHooks(); + GestureUnsetMaxNumberOfFingers(); +} + +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 +GestureGenerateTouchCancelEvent(void) +{ + int i; + Bool canceled_touch_index[MAX_MT_DEVICES] = {FALSE, }; + + if (g_pGesture->mtsync_status == MTOUCH_FRAME_SYNC_END) + { + XDBG_DEBUG(MGEST, "no Touch(%d)\n", g_pGesture->mtsync_status); + return; + } + + for (i=0; imt_devices[i]->button->buttonsDown)) continue; + InternalEvent cancel_event; + + cancel_event.touch_cancel_event.header = ET_Internal; + cancel_event.touch_cancel_event.type = ET_TouchCancel; + cancel_event.touch_cancel_event.length = sizeof(TouchCancelEvent); + cancel_event.touch_cancel_event.time = CurrentTime; + cancel_event.touch_cancel_event.deviceid = g_pGesture->mt_devices[i]->id; + + cancel_event.touch_cancel_event.sourceid = g_pGesture->mt_devices[i]->id; + cancel_event.touch_cancel_event.resource = 0; + cancel_event.touch_cancel_event.flags = 0; + + g_pGesture->mt_devices[i]->public.processInputProc(&cancel_event, g_pGesture->mt_devices[i]); + canceled_touch_index[i] = TRUE; + g_pGesture->touch_cancel_status = TRUE; + } + + for (i=0; imt_devices[i]->id; + release_event.device_event.sourceid = g_pGesture->mt_devices[i]->button->sourceid; + release_event.device_event.detail.button = 1; + release_event.device_event.root_x = g_pGesture->last_touches[i].cx; + release_event.device_event.root_y = g_pGesture->last_touches[i].cy; + if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid) + { + memcpy(&release_event_master, &release_event, sizeof(InternalEvent)); + release_event_master.device_event.deviceid = g_pGesture->master_pointer->id; + } + + g_pGesture->mt_devices[i]->public.processInputProc(&release_event, g_pGesture->mt_devices[i]); + if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid) + { + g_pGesture->master_pointer->public.processInputProc(&release_event_master, g_pGesture->master_pointer); + } + } +} + +static void +GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata) +{ + int dpmsLevel = *(int *)calldata; + + if ((DPMSModeOff == dpmsLevel) && (MTOUCH_FRAME_SYNC_END != g_pGesture->mtsync_status)) { + XDBG_DEBUG(MGEST, "TouchCancel dpmslevel: %d\n", dpmsLevel); + GestureGenerateTouchCancelEvent(); + } +} + +void +GestureEnable(int enable, Bool prop, DeviceIntPtr dev) +{ + if((!enable) && (g_pGesture->is_active)) + { + g_pGesture->is_active = 0; + XDBG_INFO(MGEST, "Disabled !\n"); + } + else if((enable) && (!g_pGesture->is_active)) + { + g_pGesture->is_active = 1; + XDBG_INFO(MGEST, "Enabled !\n"); + } + + if(!prop) + XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE); +} + +ErrorStatus +GestureRegionsInit(void) +{ + int i; + PalmStatusPtr pPalm = &g_pGesture->palm; + + if( !g_pGesture ) + return ERROR_INVALPTR; + + pixman_region_init(&g_pGesture->area); + pixman_region_init(&pPalm->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); + pixman_region_init_rect (&pPalm->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T); + } + + return ERROR_NONE; +} + +ErrorStatus +GestureRegionsReinit(void) +{ + PalmStatusPtr pPalm = &g_pGesture->palm; + int i; + if( !g_pGesture ) + { + XDBG_ERROR(MGEST, "Invalid pointer access !\n"); + return ERROR_INVALPTR; + } + + pixman_region_init(&g_pGesture->area); + pixman_region_init(&pPalm->area); + + for( i = 0 ; i < MAX_MT_DEVICES ; i++ ) + { + pixman_region_init_rect (&pPalm->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T); + } + + return ERROR_NONE; +} + +ErrorStatus +GestureInitEQ(void) +{ + int i; + IEventPtr tmpEQ; + + tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec)); + + if( !tmpEQ ) + { + XDBG_ERROR(MGEST, "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 ) + { + XDBG_ERROR(MGEST, "Failed to allocation memory for each event buffer in EQ !\n"); + i--; + while(i >= 0 && tmpEQ[i].event) + { + free(tmpEQ[i].event); + tmpEQ[i].event = NULL; + } + free (tmpEQ); + tmpEQ = NULL; + 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 ) + { + XDBG_ERROR(MGEST, "Invalid pointer access !\n"); + return ERROR_INVALPTR; + } + + tail = g_pGesture->tailEQ; + + if( tail >= GESTURE_EQ_SIZE ) + { + XDBG_WARNING(MGEST, "Gesture EQ is full !\n"); + printk("[X11][GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n"); + g_pGesture->enqueue_fulled = 1; + if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)) + { + if( !(g_pGesture->filter_mask & FlickFilterMask) ) + { + GestureRecognize_GroupFlick(ev->any.type, ev, device, 0); + } + if( !(g_pGesture->filter_mask & PanFilterMask) ) + { + GestureRecognize_GroupPan(ev->any.type, ev, device, 0, 0); + } + if( !(g_pGesture->filter_mask & PinchRotationFilterMask) ) + { + GestureRecognize_GroupPinchRotation(ev->any.type, ev, device, 0, 0); + } + if( !(g_pGesture->filter_mask & TapFilterMask) ) + { + GestureRecognize_GroupTap(ev->any.type, ev, device, 0, 0); + } + if( !(g_pGesture->filter_mask & TapNHoldFilterMask) ) + { + GestureRecognize_GroupTapNHold(ev->any.type, ev, device, 0, 0); + } + if( !(g_pGesture->filter_mask & HoldFilterMask) ) + { + GestureRecognize_GroupHold(ev->any.type, ev, device, 0, 0); + } + } + if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)) + { + if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)) + { + GesturePalmRecognize_FlickHorizen(ev->any.type, 0); + } + if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)) + { + GesturePalmRecognize_FlickVertical(ev->any.type, 0); + } + } +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(!(g_pGesture->bezel_filter_mask == BezelFlickFilterMask)) + { + GestureBezelRecognize(ev->any.type, ev, device); + } +#endif + g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL; + g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + g_pGesture->bezel_filter_mask = BezelFlickFilterMask; + g_pGesture->bezel_recognized_mask = 0; +#endif + g_pGesture->recognized_gesture = 0; + g_pGesture->recognized_palm = 0; + if( ERROR_INVALPTR == GestureFlushOrDrop() ) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + return ERROR_EQFULL; + } + +#ifdef __DETAIL_DEBUG__ + switch( ev->any.type ) + { + case ET_ButtonPress: + XDBG_DEBUG(MGEST, "ET_ButtonPress (id:%d)\n", device->id); + break; + + case ET_ButtonRelease: + XDBG_DEBUG(MGEST, "ET_ButtonRelease (id:%d)\n", device->id); + break; + + case ET_Motion: + XDBG_DEBUG(MGEST, "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, j; + DeviceIntPtr device; + + if( !g_pGesture->EQ ) + { + XDBG_ERROR(MGEST, "Invalid pointer access !\n"); + return ERROR_INVALPTR; + } + +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "\n"); +#endif//__DETAIL_DEBUG__ + + for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++) + { + device = g_pGesture->EQ[i].device; +#ifdef __DETAIL_DEBUG__ + if(g_pGesture->EQ[i].event->any.type != ET_Motion) + XDBG_DEBUG(MGEST, "[%d] type: %d\n", device->id, g_pGesture->EQ[i].event->any.type); +#endif//__DETAIL_DEBUG__ + + for(j = 0 ; j < MAX_MT_DEVICES+1 ; j++) + { + if(g_pGesture->palm.qti[j].devid == device->id) + { +#ifdef __DETAIL_DEBUG__ + if(g_pGesture->EQ[i].event->any.type != ET_Motion) + XDBG_DEBUG(MGEST, "[%d] type: %d(pressed: %d) time: %d\n", device->id, g_pGesture->EQ[i].event->any.type, g_pGesture->palm.qti[j].pressed, GetTimeInMillis()); +#endif//__DETAIL_DEBUG__ + if( (g_pGesture->palm.qti[j].pressed == 0) && (g_pGesture->EQ[i].event->any.type == ET_ButtonRelease) ) + { + XDBG_WARNING(MGEST, "Enqueued event..ButtonRelease with no ButtonPress !(devid: %d)\n", device->id); + g_pGesture->EQ[i].event->any.type = ET_ButtonPress; + device->public.processInputProc(g_pGesture->EQ[i].event, device); + g_pGesture->EQ[i].event->any.type = ET_ButtonRelease; + g_pGesture->palm.qti[j].pressed = 0; + } + else if(g_pGesture->EQ[i].event->any.type == ET_ButtonPress) + { + g_pGesture->palm.qti[j].pressed = 1; + } + else if( (g_pGesture->palm.qti[j].pressed == 1) && (g_pGesture->EQ[i].event->any.type == ET_ButtonRelease)) + { + g_pGesture->palm.qti[j].pressed = 0; + } + break; + } + else if(g_pGesture->palm.qti[j].devid == 0) + { + g_pGesture->palm.qti[j].devid = device->id; + j--; + } + } +#ifdef __DETAIL_DEBUG__ + if(g_pGesture->EQ[i].event->any.type != ET_Motion) + XDBG_DEBUG(MGEST, "!!! [%d] type: %d\n", device->id, g_pGesture->EQ[i].event->any.type); +#endif + device->public.processInputProc(g_pGesture->EQ[i].event, device); + } + memset(g_pGesture->palm.qti, 0, sizeof(g_pGesture->palm.qti[MAX_MT_DEVICES+1])); + + 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) +{ +#ifdef __DETAIL_DEBUG__ + XDBG_DEBUG(MGEST, "\n"); +#endif//__DETAIL_DEBUG__ + + g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ +} + +#ifdef HAVE_PROPERTIES +static void +GestureInitProperty(DeviceIntPtr dev) +{ + int rc; + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT + prop_anr_in_input_event = MakeAtom(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT, strlen(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT), TRUE); + prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE); +#endif + + 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); + + prop_gesture_palm_rejection_mode = MakeAtom(GESTURE_PALM_REJECTION_MODE, strlen(GESTURE_PALM_REJECTION_MODE), TRUE); + rc = XIChangeDeviceProperty(dev, prop_gesture_palm_rejection_mode, XA_INTEGER, 8, PropModeReplace, 1, &g_pGesture->palm_rejection_mode, FALSE); + + if (rc != Success) + return; + + XISetDevicePropertyDeletable(dev, prop_gesture_palm_rejection_mode, FALSE); +} + +static int +GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, + BOOL checkonly) +{ + 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); + GestureEnable(data, TRUE, dev); + } + } + else if( prop_gesture_palm_rejection_mode == atom) + { + int data; + if( val->format != 8 || val->type != XA_INTEGER || val->size != 1 ) + return BadMatch; + + if( !checkonly ) + { + int ret; + data = *((BOOL*)val->data); + int fd, fd_result; + char buf[128]; + + g_pGesture->palm_rejection_mode = (int)data; + + fd = open("/sys/class/sec/tsp/cmd", O_WRONLY); + if (fd < 0) + { + XDBG_ERROR(MGEST, "failed to open tsp node(%d)\n", fd); + return Success; + } + + sprintf(buf, "stylus_enable,%d", !!(g_pGesture->palm_rejection_mode)); + XDBG_DEBUG(MGEST, "stylus_changed: %d!\n", !!(g_pGesture->palm_rejection_mode)); + + ret = write(fd, buf, strlen(buf)); + if (ret <= 0) + { + XDBG_WARNING(MGEST, "failed to stylus_changed: %d\n", !!(g_pGesture->palm_rejection_mode)); + } + + close(fd); + + fd_result = open("/sys/class/sec/tsp/cmd_result", O_RDONLY); + if (fd_result < 0) + { + XDBG_ERROR(MGEST, "failed to open tsp node(%d)\n", fd_result); + return Success; + } + + memset(buf, 0L, sizeof(buf)); + + ret = read(fd_result, buf, sizeof(buf)); + if (ret <= 0) + { + XDBG_WARNING(MGEST, "failed to read cmd_result\n"); + } + else + { + ErrorF("stylus mode result: %s\n", buf); + } + close(fd_result); + } + } + + return Success; +} +#endif//HAVE_PROPERTIES + +static int +GestureInit(DeviceIntPtr device) +{ +#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 int +GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) +{ + int rc = BadAlloc; + GestureDevicePtr pGesture; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + BezelFlickStatusPtr pBezel; +#endif + + pGesture = calloc(1, sizeof(GestureDeviceRec)); + + if (!pGesture) { + pInfo->private = NULL; + //xf86DeleteInput(pInfo, 0); + goto error; + } + + g_pGesture = pGesture; + pInfo->private = pGesture; + pInfo->flags = 0; + 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(pInfo->options, "Device", "/dev/null"); + pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0); + pGesture->stylus_able = xf86SetIntOption(pInfo->options, "Stylus", 0); + pGesture->support_palm = xf86SetIntOption(pInfo->options, "SupportPalm", 0); + + if (pGesture->support_palm) + { + PalmRecognize = GesturePalmRecognize; + XDBG_DEBUG(MGEST, "Palm Support !!\n"); + } + else + { + PalmRecognize = NULL; + XDBG_DEBUG(MGEST, "No Palm Support !!\n"); + } + + { + int i; + char tmp[10]; + + memset(&pGesture->pass_keycodes, 0, sizeof(pGesture->pass_keycodes)); + + for(i = 0 ; i < NUM_PASSKEYS ; i++) + { + snprintf(tmp, sizeof(tmp), "PassKey%d", i+1); + pGesture->pass_keycodes[i] = xf86SetIntOption(pInfo->options, tmp, 0); + XDBG_SECURE(MGEST, "pass_keycode[%d]=%d\n", i, pGesture->pass_keycodes[i]); + } + } + + pGesture->gestureWin = None; + +#ifdef _F_SUPPORT_BEZEL_FLICK_ + pBezel = &pGesture->bezel; + pBezel->is_active = xf86SetIntOption(pInfo->options, "Bezel_Activate", 0); + pBezel->top_left.width = xf86SetIntOption(pInfo->options, "Bezel_Top_Left_Width", 0); + pBezel->top_left.height = xf86SetIntOption(pInfo->options, "Bezel_Top_Left_Height", 0); + pBezel->top_right.width = xf86SetIntOption(pInfo->options, "Bezel_Top_Right_Width", 0); + pBezel->top_right.height = xf86SetIntOption(pInfo->options, "Bezel_Top_Right_Height", 0); + pBezel->bottom_left.width = xf86SetIntOption(pInfo->options, "Bezel_Bottom_Left_Width", 0); + pBezel->bottom_left.height = xf86SetIntOption(pInfo->options, "Bezel_Bottom_Left_Height", 0); + pBezel->bottom_right.width = xf86SetIntOption(pInfo->options, "Bezel_Bottom_Right_Width", 0); + pBezel->bottom_right.height = xf86SetIntOption(pInfo->options, "Bezel_Bottom_Right_Height", 0); + pBezel->flick_distance = xf86SetIntOption(pInfo->options, "Bezel_Flick_Distance", 0); + pBezel->bezel_angle_ratio = xf86SetIntOption(pInfo->options, "Bezel_Flick_Angle_Ratio", 0); + pBezel->bezel_angle_moving_check = xf86SetIntOption(pInfo->options, "Bezel_Flick_Angle_Moving_Check", 0); +#ifdef __BEZEL_DEBUG__ + XDBG_DEBUG(MGEST, "[BEZEL] top_left.width: %d, top_left.height: %d\n", pBezel->top_left.width, pBezel->top_left.height); + XDBG_DEBUG(MGEST, "[BEZEL] top_right.width: %d, top_right.height: %d\n", pBezel->top_right.width, pBezel->top_right.height); + XDBG_DEBUG(MGEST, "[BEZEL] bottom_left.width: %d, bottom_left.height: %d\n", pBezel->bottom_left.width, pBezel->bottom_left.height); + XDBG_DEBUG(MGEST, "[BEZEL] bottom_right.width: %d, bottom_right.height: %d\n", pBezel->bottom_right.width, pBezel->bottom_right.height); + XDBG_DEBUG(MGEST, "[BEZEL] flick_distance: %d, bezel_angle_ratio: %d, bezel_angle_moving_check: %d\n", pBezel->flick_distance, pBezel->bezel_angle_ratio, pBezel->bezel_angle_moving_check); +#endif//__BEZEL_DEBUG__ +#endif + + pGesture->pinchrotation_time_threshold = xf86SetIntOption(pInfo->options, "PinchRotationTimeThresHold", PINCHROTATION_TIME_THRESHOLD); + pGesture->pinchrotation_dist_threshold = xf86SetRealOption(pInfo->options, "PinchRotationDistThresHold", PINCHROTATION_DIST_THRESHOLD); + pGesture->pinchrotation_angle_threshold = xf86SetRealOption(pInfo->options, "PinchRotationAngleThresHold", PINCHROTATION_ANGLE_THRESHOLD); + pGesture->singlefinger_threshold = xf86SetIntOption(pInfo->options, "SingleFingerThresHold", SGL_FINGER_TIME_THRESHOLD); + pGesture->singletap_threshold = xf86SetIntOption(pInfo->options, "SingleTapThresHold", SGL_TAP_TIME_THRESHOLD); + pGesture->doubletap_threshold = xf86SetIntOption(pInfo->options, "DoubleTapThresHold", DBL_TAP_TIME_THRESHOLD); + + pGesture->palm_min_touch_major = xf86SetIntOption(pInfo->options, "PalmMinTouchMajor", PALM_MIN_TOUCH_MAJOR); + pGesture->palm_min_width_major = xf86SetIntOption(pInfo->options, "PalmMinWidthMajor", PALM_MIN_WIDTH_MAJOR); + pGesture->palm_min_touch_major_bezel = xf86SetIntOption(pInfo->options, "PalmMinTouchMajorBezel", PALM_MIN_TOUCH_MAJOR_BEZEL); + pGesture->palm_min_width_major_bezel = xf86SetIntOption(pInfo->options, "PalmMinWidthMajorBezel", PALM_MIN_WIDTH_MAJOR_BEZEL); + pGesture->palm_bezel = xf86SetIntOption(pInfo->options, "PalmBezel", PALM_BEZEL); + + if (pGesture->is_active) + pGesture->ehtype = KEEP_EVENTS; + else + pGesture->ehtype = PROPAGATE_EVENTS; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + if(pBezel->bezel_angle_ratio > 0) + { + pBezel->min_rad = (RAD_90DEG / pBezel->bezel_angle_ratio); + pBezel->max_rad = ((RAD_90DEG / pBezel->bezel_angle_ratio) * (pBezel->bezel_angle_ratio-1)); + pBezel->min_180_rad = (RAD_90DEG + pBezel->min_rad); + pBezel->max_180_rad = (RAD_90DEG + pBezel->max_rad); + } + else + { + pBezel->min_rad = MIN_RAD; + pBezel->max_rad = MAX_RAD; + pBezel->min_180_rad = RAD_180DEG_MIN; + pBezel->max_180_rad = RAD_180DEG_MAX; + } +#endif + pGesture->lastSelectedWin = None; + pGesture->touchkey_id = 0; + pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END; + g_pGesture->grabMask = g_pGesture->eventMask = 0; + + xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device); + + /* process generic options */ + xf86CollectInputOptions(pInfo, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + pInfo->fd = -1; + + g_pGesture->tap_repeated = 0; + + g_pGesture->palm.palmflag = 0; + g_pGesture->palm.palm_single_finger_timer = NULL; + g_pGesture->enqueue_fulled = 0; + g_pGesture->zoom_enabled = 0; + memset(g_pGesture->palm.qti, 0, sizeof(g_pGesture->palm.qti[MAX_MT_DEVICES+1])); + + g_pGesture->palm_rejection_mode = 0; + g_pGesture->palm_detected = FALSE; + + memset(g_pGesture->stylusInfo.t_status, 0, sizeof(g_pGesture->stylusInfo.t_status[MAX_MT_DEVICES])); + g_pGesture->stylusInfo.stylus_id = 0; + g_pGesture->stylusInfo.pen_detected = FALSE; + + g_pGesture->touch_cancel_status = FALSE; + + return Success; + +error: + if (pInfo->fd >= 0) + close(pInfo->fd); + return rc; +} + +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; + if (!AddCallback(&DPMSCallback, GestureDPMSCallback, NULL)) + ErrorF("[Gesture]Failed to Add DPMS CallBack\n"); + break; + + case DEVICE_OFF: +device_off: + GestureDisableEventHandler(); + DeleteCallback(&DPMSCallback, GestureDPMSCallback, NULL); + 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; + case DEVICE_READY: + GestureRegisterDeviceInfo(device); + break; + } + return Success; +} + +static void +GestureReadInput(InputInfoPtr pInfo) +{ +} + diff --git a/mobile/src/gesture.h b/mobile/src/gesture.h new file mode 100644 index 0000000..23bc008 --- /dev/null +++ b/mobile/src/gesture.h @@ -0,0 +1,709 @@ +/************************************************************************** + +xserver-xorg-input-gesture + +Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + +Contact: Sung-Jin Park + Sangjin LEE + +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 +#include +#include +#include + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 +#define HAVE_PROPERTIES 1 +#endif + +#ifndef ABS_CNT +#define ABS_CNT (ABS_MAX+1) +#endif + +/** + * If there's touch event in pointed window and there's no reponse, we just assume that client looks like deadlock. + * In this case, we will make a popup window and terminate application. + * To support this feature, we use SUPPORT_ANR_WITH_INPUT_EVENT flag. + */ +#define SUPPORT_ANR_WITH_INPUT_EVENT + +#define NUM_PASSKEYS 20 + +#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 10 +#define GESTURE_EQ_SIZE 256 + +#define GESTURE_RECOGNIZER_ONOFF "GESTURE_RECOGNIZER_ONOFF" +#define GESTURE_PALM_REJECTION_MODE "GESTURE_PALM_REJECTION_MODE" +#define CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT "_CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT_" +#define ANR_EVENT_WINDOW "_ANR_EVENT_WINDOW_" + +#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) ) +#define AREA_HEIGHT(extents) (((extents)->y2)-((extents)->y1)) +#define AREA_WIDTH(extents) (((extents)->x2)-((extents)->x1)) +#define AREA_DIAG_LEN(extents) sqrt((AREA_WIDTH(extents)*AREA_WIDTH(extents))+(AREA_HEIGHT(extents)*AREA_HEIGHT(extents))) + +//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 +}; + +/* Gesture query devices infomation and register handlers + * if a device_control function is called using DEVICE_READY */ +#define DEVICE_READY 11 + +#define SCREEN_WIDTH 720 +#define SCREEN_HEIGHT 1280 + +#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 PINCHROTATION_TIME_THRESHOLD 500//ms +#define PINCHROTATION_INIT_DIST_THRESHOLD 25.0f +#define PINCHROTATION_INIT_ANGLE_THRESHOLD 0.2f +#define PINCHROTATION_DIST_THRESHOLD 25.0f +#define PINCHROTATION_ANGLE_THRESHOLD 0.2f + +#define HOLD_AREA_THRESHOLD 2500//=50pixel * 50pixel +#define HOLD_MOVE_THRESHOLD 10//pixel +#define HOLD_TIME_THRESHOLD 500//ms + +#define TAP_AREA_THRESHOLD 30000//= 300pixel * 100pixel +#define TAP_MOVE_THRESHOLD 300//pixel +#define SGL_FINGER_TIME_THRESHOLD 50//ms +#define SGL_TAP_TIME_THRESHOLD 200//ms +#define DBL_TAP_TIME_THRESHOLD 400//ms +#define MAX_TAP_REPEATS 2 + +#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 + +#define RAD_90DEG M_PI_2 +#define RAD_180DEG M_PI +#define RAD_270DEG (M_PI_2 * 3) +#define RAD_360DEG (M_PI * 2) +#define MIN_RAD (RAD_90DEG / 4) +#define MAX_RAD ((RAD_90DEG / 4) * 3) +#define RAD_180DEG_MIN (RAD_90DEG + MIN_RAD) +#define RAD_180DEG_MAX (RAD_90DEG + MAX_RAD) + +#define rad2degree(r) ((r) * 180/M_PI) + +#define AXIS_LABEL_PROP_ABS_X "Abs X" +#define AXIS_LABEL_PROP_ABS_Y "Abs Y" +#define AXIS_LABEL_PROP_ABS_Z "Abs Z" +#define AXIS_LABEL_PROP_ABS_RX "Abs Rotary X" +#define AXIS_LABEL_PROP_ABS_RY "Abs Rotary Y" +#define AXIS_LABEL_PROP_ABS_RZ "Abs Rotary Z" +#define AXIS_LABEL_PROP_ABS_THROTTLE "Abs Throttle" +#define AXIS_LABEL_PROP_ABS_RUDDER "Abs Rudder" +#define AXIS_LABEL_PROP_ABS_WHEEL "Abs Wheel" +#define AXIS_LABEL_PROP_ABS_GAS "Abs Gas" +#define AXIS_LABEL_PROP_ABS_BRAKE "Abs Brake" +#define AXIS_LABEL_PROP_ABS_HAT0X "Abs Hat 0 X" +#define AXIS_LABEL_PROP_ABS_HAT0Y "Abs Hat 0 Y" +#define AXIS_LABEL_PROP_ABS_HAT1X "Abs Hat 1 X" +#define AXIS_LABEL_PROP_ABS_HAT1Y "Abs Hat 1 Y" +#define AXIS_LABEL_PROP_ABS_HAT2X "Abs Hat 2 X" +#define AXIS_LABEL_PROP_ABS_HAT2Y "Abs Hat 2 Y" +#define AXIS_LABEL_PROP_ABS_HAT3X "Abs Hat 3 X" +#define AXIS_LABEL_PROP_ABS_HAT3Y "Abs Hat 3 Y" +#define AXIS_LABEL_PROP_ABS_PRESSURE "Abs Pressure" +#define AXIS_LABEL_PROP_ABS_DISTANCE "Abs Distance" +#define AXIS_LABEL_PROP_ABS_TILT_X "Abs Tilt X" +#define AXIS_LABEL_PROP_ABS_TILT_Y "Abs Tilt Y" +#define AXIS_LABEL_PROP_ABS_TOOL_WIDTH "Abs Tool Width" +#define AXIS_LABEL_PROP_ABS_VOLUME "Abs Volume" +#define AXIS_LABEL_PROP_ABS_MT_SLOT "Abs MT Slot" +#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major" +#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor" +#define AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR "Abs MT Width Major" +#define AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR "Abs MT Width Minor" +#define AXIS_LABEL_PROP_ABS_MT_ORIENTATION "Abs MT Orientation" +#define AXIS_LABEL_PROP_ABS_MT_POSITION_X "Abs MT Position X" +#define AXIS_LABEL_PROP_ABS_MT_POSITION_Y "Abs MT Position Y" +#define AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE "Abs MT Tool Type" +#define AXIS_LABEL_PROP_ABS_MT_BLOB_ID "Abs MT Blob ID" +#define AXIS_LABEL_PROP_ABS_MT_TRACKING_ID "Abs MT Tracking ID" +#define AXIS_LABEL_PROP_ABS_MT_PRESSURE "Abs MT Pressure" +#define AXIS_LABEL_PROP_ABS_MT_DISTANCE "Abs MT Distance" +#define AXIS_LABEL_PROP_ABS_MT_ANGLE "Abs MT Angle/MT Component" +#define AXIS_LABEL_PROP_ABS_MT_PALM "Abs MT Palm/MT Sumsize" +#define AXIS_LABEL_PROP_ABS_MISC "Abs Misc" + + +typedef enum _MTSyncType +{ + MTOUCH_FRAME_SYNC_END, + MTOUCH_FRAME_SYNC_BEGIN +} MTSyncType; + +typedef enum _EventHandleType +{ + PROPAGATE_EVENTS, + KEEP_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_TouchCancel = 31, + 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 (also used in pointer emulating + touch events) */ + uint32_t key; /**< Key code */ + } detail; + uint32_t touchid; /**< Touch ID (client_id) */ + 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)*/ + double data[MAX_VALUATORS]; /**< Valuator 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 */ + uint32_t flags; /**< Flags to be copied into the generated 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; +}; + +typedef struct _TouchCancelEvent TouchCancelEvent; +struct _TouchCancelEvent { + unsigned char header; /**< Always ET_Internal */ + enum EventType type; /**< ET_TouchOwnership */ + int length; /**< Length in bytes */ + Time time; /**< Time in ms */ + int deviceid; /**< Device to post this event for */ + int sourceid; /**< The physical source device */ + uint32_t resource; /**< Provoking grab or event selection */ + uint32_t flags; /**< Flags to be copied into the generated event */ +}; + + + +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; + TouchCancelEvent touch_cancel_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 +}; + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +enum +{ + BEZEL_NONE, + BEZEL_ON, + BEZEL_START, + BEZEL_DONE, + BEZEL_END +}; + +enum +{ + NO_BEZEL, + BEZEL_TOP_LEFT, + BEZEL_TOP_RIGHT, + BEZEL_BOTTOM_LEFT, + BEZEL_BOTTOM_RIGHT +}; +#endif + +#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) + +#define PalmFlickHorizFilterMask 0x01//(1 << 0) +#define PalmFlickVertiFilterMask 0x02//(1 << 1) + +#define GESTURE_PALM_FILTER_MASK_ALL 0x03//(PalmFlickHorizFilterMask | PalmFlickVertiFilterMask) + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +#define BezelFlickFilterMask 0x01//(1 << 0) +#endif + +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 _tagCurrentTouchStatus +{ + int status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING + + int cx; //current x + int cy; //current y +} CurTouchStatus; + +//palm global +#define PALM_MIN_TOUCH_MAJOR 30 +#define PALM_MIN_WIDTH_MAJOR 40 +#define PALM_MIN_TOUCH_MAJOR_BEZEL 16 +#define PALM_MIN_WIDTH_MAJOR_BEZEL 24 +#define PALM_BEZEL 33 + +//palm flick +#define PALM_FLICK_INITIAL_TIMEOUT 300//ms +#define PALM_FLICK_FALSE_TIMEOUT 900//ms +#define PALM_FLICK_DETECT_TIMEOUT 2000//ms +#define PALM_HORIZ_ARRAY_COUNT 4 +#define PALM_VERTI_ARRAY_COUNT 7 +#define PALM_FLICK_MIN_PALM 1 +#define PALM_FLICK_MIN_BASE_WIDTH 30 +#define PALM_FLICK_HORIZ_MAX_BASE_WIDTH 400 +#define PALM_FLICK_VERTI_MAX_BASE_WIDTH 300 +#define PALM_FALSE_FLICK_BASE_WIDTH 8 +#define PALM_FLICK_TOUCH_MAJOR 80 +#define PALM_FLICK_FINGER_MIN_TOUCH_MAJOR 15 +#define PALM_FLICK_HORIZ_MAX_MOVE_Y 400 +#define PALM_FLICK_VERTI_MAX_MOVE_X 300 + +//palm tap +#define PALM_MIN_MAJOR 200 +#define PALM_SGL_TAP_TIMEOUT 200//ms +#define PALM_DBL_TAP_TIMEOUT 300//ms +#define PALM_TAP_MIN_DEVIATION 100 +#define PALM_TAP_FALSE_DEVIATION 20 +#define PALM_TAP_FALSE_SIZE 3 + +//palm hold +#define PALM_HOLD_TIME_THRESHOLD 150 + +typedef struct _tagPalmTouchInfo +{ + int touch_status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING + + int x; + int y; + double wmajor;//Value of valuator ABS_MT_WIDTH_MAJOR + double tmajor;//Value of valuator ABS_MT_TOUCH_MAJOR + double tminor;//Value of valuator ABS_MT_TOUCH_MINOR + double tangle;//Value of valuator ABS_MT_ANGLE + double tpalm;//Value of valuator ABS_MT_PALM +} PalmTouchInfo, *PalmTouchInfoPtr; + +typedef struct _tagQueuedTouchInfo +{ + int devid; + int pressed; +}QueuedTouchInfo; + +typedef struct _tagPalmStatus +{ + int palmflag; + double sum_size; + double max_eccen; + double max_angle; + double max_wmajor; + double max_tmajor; + double max_tminor; + double biggest_tmajor; + double biggest_wmajor; + double bigger_wmajor; + int max_size_idx; + int max_touched; + int cur_touched; + double dispersionX; + double deviationX; + double dispersionY; + double deviationY; + int cx; + int cy; + int max_palm; + int single_timer_expired; + + OsTimerPtr palm_single_finger_timer; + PalmTouchInfo pti[MAX_MT_DEVICES]; + QueuedTouchInfo qti[MAX_MT_DEVICES+1]; + pixman_region16_t area; + pixman_region16_t finger_rects[MAX_MT_DEVICES]; +} PalmStatus, *PalmStatusPtr; + +typedef struct _tagPalmDrvStatus +{ + int enabled; + int scrn_width; + int scrn_height; + unsigned int half_scrn_area_size; + int horiz_coord[PALM_HORIZ_ARRAY_COUNT]; + int verti_coord[PALM_VERTI_ARRAY_COUNT]; +} PalmMiscInfo, *PalmMiscInfoPtr; + +typedef struct _tagStylusStatus +{ + CurTouchStatus t_status[MAX_MT_DEVICES]; + int stylus_id; + Bool pen_detected; + Bool fake_events; +} StylusInfo, *StylusInfoPtr; + +#ifdef _F_SUPPORT_BEZEL_FLICK_ +typedef struct _tagBezelStatus +{ + int width; + int height; +}BezelStatus, *BezelStatusPtr; +typedef struct _tagBezelFlickStatus +{ + int is_active; + BezelStatus top_left; + BezelStatus top_right; + BezelStatus bottom_left; + BezelStatus bottom_right; + int flick_distance; + int bezel_angle_ratio; + double min_rad; + double max_rad; + double min_180_rad; + double max_180_rad; + int bezel_angle_moving_check; + int bezelStatus; +}BezelFlickStatus, *BezelFlickStatusPtr; +#endif + +typedef struct _GestureDeviceRec +{ + char *device; + int version; /* Driver version */ + OsTimerPtr device_setting_timer; + + int is_active; + + int screen_width; + int screen_height; + + int pinchrotation_time_threshold; + double pinchrotation_dist_threshold; + double pinchrotation_angle_threshold; + + int singlefinger_threshold; + int singletap_threshold; + int doubletap_threshold; + + int palm_min_touch_major; + int palm_min_width_major; + int palm_min_touch_major_bezel; + int palm_min_width_major_bezel; + int palm_bezel; + + int touchkey_id; + MTSyncType mtsync_status; + StylusInfo stylusInfo; + int palm_rejection_mode; + Bool palm_detected; + Bool no_palm_events; + + int pass_keycodes[NUM_PASSKEYS]; + + WindowPtr pRootWin; + Window gestureWin; + int num_mt_devices; + + Mask grabMask; + Mask eventMask; + GestureGrabEventPtr GrabEvents; + Mask lastSelectedMask; + Window lastSelectedWin; + + EventHandleType ehtype; + IEventPtr EQ; + int headEQ; + int tailEQ; + + int hold_detector_activate; + int has_hold_grabmask; + pixman_region16_t chold_area; + CurTouchStatus cts[MAX_MT_DEVICES]; + CurTouchStatus last_touches[MAX_MT_DEVICES]; + Bool touch_cancel_status; + Bool hold_detected; + + PalmStatus palm; + PalmMiscInfo palm_misc; + int wmajor_idx; + int tmajor_idx; + int tminor_idx; + int tangle_idx; + int tpalm_idx; + int mt_px_idx; + int mt_py_idx; + int mt_tool_idx; + + pixman_region16_t area; + pixman_region16_t finger_rects[MAX_MT_DEVICES]; + + WindowPtr pTempWin; + WindowPtr pTempPalmWin; + int inc_num_pressed; + + int first_fingerid; + int num_pressed; + int zoom_enabled; + int enqueue_fulled; + int tap_repeated; + TouchStatus fingers[MAX_MT_DEVICES]; + + int event_sum[MAX_MT_DEVICES]; + uint32_t recognized_gesture; + uint32_t filter_mask; + uint32_t palm_filter_mask; + uint32_t recognized_palm; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + uint32_t bezel_filter_mask; + uint32_t bezel_recognized_mask; +#endif + + DeviceIntPtr this_device; + DeviceIntPtr mt_devices[MAX_MT_DEVICES]; + DeviceIntPtr master_pointer; + DeviceIntPtr xtest_pointer; +#ifdef _F_SUPPORT_BEZEL_FLICK_ + BezelFlickStatus bezel; +#endif + WindowPtr anr_window; + + int stylus_able; + int support_palm; +} GestureDeviceRec, *GestureDevicePtr ; + +#endif//_GESTURE_H_ diff --git a/xorg-gesture.pc.in b/mobile/xorg-gesture.pc.in similarity index 100% rename from xorg-gesture.pc.in rename to mobile/xorg-gesture.pc.in diff --git a/packaging/xorg-x11-drv-gesture.spec b/packaging/xorg-x11-drv-gesture.spec index 5d11fd2..aac856c 100644 --- a/packaging/xorg-x11-drv-gesture.spec +++ b/packaging/xorg-x11-drv-gesture.spec @@ -1,8 +1,9 @@ #sbs-git:slp/pkgs/xorg/driver/xserver-xorg-input-gesture xorg-x11-drv-gesture 0.1.0 fb1092a8ea453d658b38d5c28e67a58462d7c931 Name: xorg-x11-drv-gesture Summary: X.Org X server -- Xserver gesture driver -Version: 0.1.0 -Release: 4 +Version: 0.1.60 +Release: 1 +VCS: adaptation/xorg/driver/xserver-xorg-input-gesture#xorg-x11-drv-gesture-0.1.2-8-6-g7c67de9af10190753599a01144e865bf0a341604 Group: System/X Hardware Support License: MIT Source0: %{name}-%{version}.tar.gz @@ -12,6 +13,10 @@ BuildRequires: pkgconfig(xproto) BuildRequires: pkgconfig(inputproto) BuildRequires: pkgconfig(resourceproto) BuildRequires: pkgconfig(xorg-macros) +BuildRequires: pkgconfig(dlog) +%if "%{?tizen_profile_name}" == "mobile" +BuildRequires: pkgconfig(xdbg) +%endif %description This package provides the driver for recognizing gesture(s) using button @@ -26,27 +31,40 @@ Requires: %{name} = %{version}-%{release} %description devel xorg-x11-drv-gesture development files - %prep %setup -q %build -autoreconf -vfi -./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" -#./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info CFLAGS="$CFLAGS -D__DETAIL_DEBUG__ -D__DEBUG_EVENT_HANDLER__ " LDFLAGS="$LDFLAGS" +%if "%{?tizen_profile_name}" == "wearable" +cd wearable +%else +cd mobile +%endif + +#%autogen -ivf +%reconfigure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" make %{?jobs:-j%jobs} %install + +%if "%{?tizen_profile_name}" == "wearable" +cd wearable +%else +cd mobile +%endif + rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp -af COPYING %{buildroot}/usr/share/license/%{name} %make_install %remove_docs %files %{_libdir}/xorg/modules/input/gesture_drv.so +/usr/share/license/%{name} %files devel %{_libdir}/pkgconfig/xorg-gesture.pc - diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 902f7ad..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# 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 deleted file mode 100755 index fa3928a..0000000 --- a/src/gesture.c +++ /dev/null @@ -1,2883 +0,0 @@ -/************************************************************************** - -xserver-xorg-input-gesture - -Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved - -Contact: Sung-Jin Park - Sangjin LEE - -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 -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef HAVE_PROPERTIES -#include -#include -/* 1.6 has properties, but no labels */ -#ifdef AXIS_LABEL_PROP -#define HAVE_LABELS -#else -#undef HAVE_LABELS -#endif - -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gesture.h" -#include - -//Basic functions -static InputInfoPtr GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, 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); -static double get_angle(int x1, int y1, int x2, int y2); - -//Gesture recognizer and handlers -void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); -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, int kinds); -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; -} - -static double -get_angle(int x1, int y1, int x2, int y2) -{ - double a, xx, yy; - xx = fabs(x2 - x1); - yy = fabs(y2 - y1); - - if (((int) xx) && ((int) yy)) - { - a = atan(yy / xx); - if (x1 < x2) - { - if (y1 < y2) - { - return (RAD_360DEG - a); - } - else - { - return (a); - } - } - else - { - if (y1 < y2) - { - return (RAD_180DEG + a); - } - else - { - return (RAD_180DEG - a); - } - } - } - - if (((int) xx)) - { /* Horizontal line */ - if (x2 < x1) - { - return (RAD_180DEG); - } - else - { - return (0.0); - } - } - - /* Vertical line */ - if (y2 < y1) - { - return (RAD_90DEG); - } - else - { - return (RAD_270DEG); - } -} - -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, int kinds) -{ - Window target_win; - WindowPtr target_pWin; - xGestureNotifyPinchRotationEvent prev; - -#ifdef __DETAIL_DEBUG__ - ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n", - num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy); -#endif//__DETAIL_DEBUG__ - - g_pGesture->recognized_gesture |= PinchRotationFilterMask; - memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent)); - prev.type = GestureNotifyPinchRotation; - prev.kind = kinds; - 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", (unsigned int)prev.window, (unsigned int)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, int timer_expired) -{ - static int cx, cy; - - static int num_pressed = 0; - static int state = GestureEnd; - static int event_type = GestureNotifyPinchRotation; - static OsTimerPtr pinchrotation_event_timer = NULL; - - static pixman_region16_t base_area; - static pixman_region16_t cur_area; - - static double base_distance = 0.0f; - static double base_angle = 0.0f; - - static double prev_distance = 0.0f; - static double prev_angle = 0.0f; - - static double cur_distance = 0.0f; - static double cur_angle = 0.0f; - - double diff_distance = 0.0f; - double diff_angle = 0.0f; - - static int has_event_mask = 0; - - static Time base_time = 0; - Time current_time; - - if( timer_expired ) - { - if( state == GestureEnd ) - { - current_time = GetTimeInMillis(); - if( (current_time - base_time) >= PINCHROTATION_TIME_THRESHOLD ) - { -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][Timer] You must move farther than dist threshold(=%.2f) or angle threshold(=%2f) within time threshold(=%d) !\n", PINCHROTATION_DIST_THRESHOLD, PINCHROTATION_ANGLE_THRESHOLD, PINCHROTATION_TIME_THRESHOLD); -#endif//__DETAIL_DEBUG__ - goto cleanup_pinchrotation; - } - } - - return; - } - - switch( type ) - { - case ET_ButtonPress: - g_pGesture->fingers[idx].flags |= PressFlagPinchRotation; - - if( g_pGesture->num_pressed < 2 ) - return; - - if( g_pGesture->num_pressed < num_pressed && state != GestureEnd ) - { -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][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_pinchrotation; - } - - if( base_distance == 0.0f && g_pGesture->num_pressed == 2 ) - { -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); -#endif//__DETAIL_DEBUG__ - - base_time = GetTimeInMillis(); - pixman_region_init(&base_area); - pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); - - prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents); - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px, - g_pGesture->fingers[0].py, g_pGesture->fingers[1].py); -#endif//__DETAIL_DEBUG__ - - prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py); -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle)); -#endif//__DETAIL_DEBUG__ - event_type = GestureNotifyPinchRotation; - pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, PINCHROTATION_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type); - } - num_pressed = g_pGesture->num_pressed; - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents)); - ErrorF("[GroupPinchRotation][P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle)); -#endif//__DETAIL_DEBUG__ - break; - - case ET_Motion: - if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) ) - break; - - if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) ) - { -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][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_pinchrotation; - } - - if( num_pressed < 2 ) - return; - - if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my ) - { - pixman_region_init(&cur_area); - pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]); - - cur_distance = AREA_DIAG_LEN(&cur_area.extents); - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx, - g_pGesture->fingers[0].my, g_pGesture->fingers[1].my); -#endif//__DETAIL_DEBUG__ - - cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my); -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle)); -#endif//__DETAIL_DEBUG__ - - diff_distance = prev_distance - cur_distance; - diff_angle = prev_angle - cur_angle; - - cx = AREA_CENTER_X(&cur_area.extents); - cy = AREA_CENTER_Y(&cur_area.extents); - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][M][state=%d] cx=%d, cy=%d\n", state, cx, cy); -#endif//__DETAIL_DEBUG__ - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance); - ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_angle=%.2f(deg=%.2f), cur_angle=%.2f(deg=%.2f), diff=%.2f(deg=%.2f)\n", num_pressed, prev_angle, rad2degree(prev_angle), cur_angle, rad2degree(cur_angle), diff_angle, rad2degree(diff_angle)); -#endif//__DETAIL_DEBUG__ - - switch( state ) - { - case GestureEnd: - if( (ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD) || (ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD) ) - { -#ifdef __DETAIL_DEBUG__ - if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD ) - ErrorF("[GroupPinchRotation][M] zoom changed !\n"); - - if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD ) - ErrorF("[GroupPinchRotation][M] angle changed !\n"); -#endif//__DETAIL_DEBUG__ - - TimerCancel(pinchrotation_event_timer); - state = GestureBegin; - goto gesture_begin_handle; - } - break; - - case GestureBegin: -gesture_begin_handle: -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation] PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state); -#endif//__DETAIL_DEBUG__ - if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) ) - { - GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureBegin); - prev_distance = cur_distance; - prev_angle = cur_angle; - state = GestureUpdate; - has_event_mask = 1; - } - else - { - has_event_mask = 0; - goto cleanup_pinchrotation; - } - break; - - case GestureUpdate: - //if( ABS(diff_distance) < PINCHROTATION_DIST_THRESHOLD && ABS(diff_angle) < PINCHROTATION_ANGLE_THRESHOLD ) - // break; - -#ifdef __DETAIL_DEBUG__ - if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD ) - ErrorF("[GroupPinchRotation][M] zoom changed !\n"); - - if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD ) - ErrorF("[GroupPinchRotation][M] angle changed !\n"); -#endif//__DETAIL_DEBUG__ - -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation] PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state); -#endif//__DETAIL_DEBUG__ - GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureUpdate); - prev_distance = cur_distance; - prev_angle = cur_angle; - break; - - case GestureDone: - default: - break; - } - } - break; - - case ET_ButtonRelease: - if( state != GestureEnd && num_pressed >= 2) - { -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][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_pinchrotation; - } - - if( g_pGesture->num_pressed ) - break; - - goto cleanup_pinchrotation; - break; - } - - return; - -cleanup_pinchrotation: - - if( has_event_mask && (state == GestureBegin || state == GestureUpdate) ) - { - state = GestureEnd; -#ifdef __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation] PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state); -#endif//__DETAIL_DEBUG__ - GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureEnd); - } - else - { - g_pGesture->recognized_gesture &= ~PinchRotationFilterMask; - } - - g_pGesture->filter_mask |= PinchRotationFilterMask; - - if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL ) - { -#if 1//def __DETAIL_DEBUG__ - ErrorF("[GroupPinchRotation][cleanup] GestureFlushOrDrop() !\n"); -#endif//__DETAIL_DEBUG__ - - if( ERROR_INVALPTR == GestureFlushOrDrop() ) - { - GestureControl(g_pGesture->this_device, DEVICE_OFF); - } - } - - prev_distance = base_distance = 0.0f; - prev_angle = base_angle = 0.0f; - has_event_mask = num_pressed = 0; - state = GestureEnd; - cx = cy = 0; - TimerCancel(pinchrotation_event_timer); - 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; - - case GestureNotifyPinchRotation: -#ifdef __DETAIL_DEBUG__ - ErrorF("[GestureEventTimerHandler] GestureNotifyPinchRotation (event_type = %d)\n", event_type); -#endif//__DETAIL_DEBUG__ - GestureRecognize_GroupPinchRotation(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; - static OsTimerPtr single_finger_timer = NULL; - int idx = -1; - - if( PROPAGATE_EVENTS == g_pGesture->ehtype || - device->id < g_pGesture->first_fingerid ) - return; - - for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) - { - if( device->id == g_pGesture->mt_devices[i]->id ) - { - idx = i; - break; - } - } - - if( idx < 0 ) - 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, 0); - } - 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, InputInfoPtr pInfo, int flags) -{ - int rc = BadAlloc; - GestureDevicePtr pGesture; - - pGesture = calloc(1, sizeof(GestureDeviceRec)); - - if (!pGesture) { - pInfo->private = NULL; - //xf86DeleteInput(pInfo, 0); - goto error; - } - - g_pGesture = pGesture; - pInfo->private = pGesture; - pInfo->flags = 0; - 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(pInfo->options, "Device", "/dev/null"); - pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0); - pGesture->gestureWin = None; - - xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device); - - /* process generic options */ - xf86CollectInputOptions(pInfo, NULL); - xf86ProcessCommonOptions(pInfo, pInfo->options); - - pInfo->fd = -1; - return Success; - -error: - if (pInfo->fd >= 0) - close(pInfo->fd); - return rc; -} - -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/wearable/AUTHORS b/wearable/AUTHORS new file mode 100644 index 0000000..e903784 --- /dev/null +++ b/wearable/AUTHORS @@ -0,0 +1,2 @@ +Sung-Jin Park +Sangjin Lee diff --git a/wearable/COPYING b/wearable/COPYING new file mode 100755 index 0000000..8f6ba4b --- /dev/null +++ b/wearable/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/wearable/ChangeLog b/wearable/ChangeLog new file mode 100644 index 0000000..e69de29 diff --git a/wearable/LICENSE.MIT b/wearable/LICENSE.MIT new file mode 100644 index 0000000..1c81bdc --- /dev/null +++ b/wearable/LICENSE.MIT @@ -0,0 +1,20 @@ +Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat +not be used in advertising or publicity pertaining to distribution +of the software without specific, written prior permission. Red +Hat makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied +warranty. + +THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN +NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS +OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, +NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/wearable/Makefile.am b/wearable/Makefile.am new file mode 100644 index 0000000..8e655ec --- /dev/null +++ b/wearable/Makefile.am @@ -0,0 +1,41 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS 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/wearable/NOTICE b/wearable/NOTICE new file mode 100644 index 0000000..c10a9c5 --- /dev/null +++ b/wearable/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under MIT License. +Please, see the LICENSE.MIT file for MIT License terms and conditions. diff --git a/wearable/autogen.sh b/wearable/autogen.sh new file mode 100755 index 0000000..0aad669 --- /dev/null +++ b/wearable/autogen.sh @@ -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/wearable/configure.ac b/wearable/configure.ac new file mode 100644 index 0000000..109646d --- /dev/null +++ b/wearable/configure.ac @@ -0,0 +1,75 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +AC_PREREQ(2.57) +AC_INIT([xserver-xorg-input-gesture], + 0.1.0, + [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], + xserver-xorg-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 dlog $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/wearable/man/Makefile.am b/wearable/man/Makefile.am new file mode 100644 index 0000000..b91dae4 --- /dev/null +++ b/wearable/man/Makefile.am @@ -0,0 +1,53 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS SOFTWARE. +# + +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/wearable/man/gesture.man b/wearable/man/gesture.man new file mode 100644 index 0000000..f3e0eeb --- /dev/null +++ b/wearable/man/gesture.man @@ -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/wearable/src/Makefile.am b/wearable/src/Makefile.am new file mode 100644 index 0000000..695f833 --- /dev/null +++ b/wearable/src/Makefile.am @@ -0,0 +1,37 @@ +# Copyright (c) 2011 Samsung Electronics Co., Ltd 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, and that the name of Red Hat not be used in +# advertising or publicity pertaining to distribution of the software without +# specific, written prior permission. Red Hat makes no +# representations about the suitability of this software for any purpose. It +# is provided "as is" without express or implied warranty. +# +# RED HAT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +# EVENT SHALL RED HAT BE LIABLE FOR ANY SPECIAL, INDIRECT OR +# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +# DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER +# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +# PERFORMANCE OF THIS 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/wearable/src/gesture.c b/wearable/src/gesture.c new file mode 100644 index 0000000..6c6b01e --- /dev/null +++ b/wearable/src/gesture.c @@ -0,0 +1,3795 @@ +/************************************************************************** + +xserver-xorg-input-gesture + +Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + +Contact: Sung-Jin Park + Sangjin LEE + +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 +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_PROPERTIES +#include +#include +/* 1.6 has properties, but no labels */ +#ifdef AXIS_LABEL_PROP +#define HAVE_LABELS +#else +#undef HAVE_LABELS +#endif + +#endif + +//#define __DETAIL_DEBUG__ +//#define __DEBUG_EVENT_HANDLER__ +//#define __PalmFlick_DEBUG__ +//#define __HOLD_DETECTOR_DEBUG__ + +#ifdef __PalmFlick_DEBUG__ +#define PalmFlickDebugPrint ErrorF +#else +#define PalmFlickDebugPrint(...) +#endif + +#ifdef __HOLD_DETECTOR_DEBUG__ +#define HoldDetectorDebugPrint ErrorF +#else +#define HoldDetectorDebugPrint(...) +#endif + + +#ifdef __DETAIL_DEBUG__ +#define DetailDebugPrint ErrorF +#else +#define DetailDebugPrint(...) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gesture.h" +#include + +#define LOG_TAG "GESTURE" +#include "dlog.h" + + + +char *strcasestr(const char *s, const char *find); +extern ScreenPtr miPointerCurrentScreen(void); +static void printk(const char* fmt, ...) __attribute__((format(printf, 1, 0))); + +//Basic functions +static int GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, 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 GestureEnable(int enable, Bool prop, DeviceIntPtr dev); +void GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent); +void GestureCbEventsSelected(Window win, Mask *pEventMask); +WindowPtr GestureGetEventsWindow(void); +static int GestureGetFingerIndexFromDevice(DeviceIntPtr device); + +//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); +void GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device); +void GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device); + +void GestureEmulateHWKey(DeviceIntPtr dev, int keycode); + +//Gesture recognizer helper +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21 +static Bool PointInBorderSize(WindowPtr pWin, int x, int y); +#endif +static WindowPtr GestureWindowOnXY(int x, int y); +Bool GestureHasFingerEventMask(int eventType, int num_finger); + +//Gesture recognizer and handlers +void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device); +void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); +void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction); +void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired); +void GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx); +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_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds); +ErrorStatus GestureFlushOrDrop(void); + +static int GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device); +static int GesturePalmGetAbsAxisInfo(DeviceIntPtr dev); +static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device); +static int GesturePalmGetScreenInfo(); +static int GesturePalmGetHorizIndexWithX(int current_x, int idx, int type); + +void GestureGenerateTouchCancelEvent(void); + +static void GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata); + +#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; + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT +static Atom prop_anr_in_input_event = None; +static Atom prop_anr_event_window = None; +static Window prop_anr_event_window_xid = None; +#endif + + +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 +}; + +extern CallbackListPtr DPMSCallback; + +static void +printk(const char* fmt, ...) +{ + static FILE* fp = NULL; + static char init = 0; + va_list argptr; + + if (!init && !fp) + { + fp = fopen("/dev/kmsg", "wt"); + init = 1; + } + + if (!fp) return; + + va_start(argptr, fmt); + vfprintf(fp, fmt, argptr); + fflush(fp); + va_end(argptr); +} + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT +static WindowPtr +_GestureFindANRWindow(DeviceIntPtr device) +{ + WindowPtr root=NULL; + WindowPtr anr_window=NULL; + Window anr_xid=0; + PropertyPtr pProp; + int rc=0; + + root = RootWindow(device); + + if( prop_anr_event_window == None ) + prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE); + + rc = dixLookupProperty (&pProp, root, prop_anr_event_window, serverClient, DixReadAccess); + if (rc == Success && pProp->data){ + anr_xid = *(int*)pProp->data; + } + + if( anr_xid != 0 ) + { + rc = dixLookupWindow(&anr_window, anr_xid, serverClient, DixSetPropAccess); + if( rc == BadWindow ) + { + ErrorF("Can't find ANR window !!\n"); + anr_window = NULL; + } + prop_anr_event_window_xid = anr_xid; + } + + ErrorF("ANR Window is %#x. Ptr is %#x\n", anr_xid, anr_window); + return anr_window; +} +#endif + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21 +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; +} +#endif + +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)); + if (!pSprite->spriteTrace) { + return NULL; + } + } + 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)) + { + DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has grabMask\n"); + return TRUE; + } + + if (g_pGesture->eventMask & eventmask) + { + DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has eventMask\n"); + return TRUE; + } + + DetailDebugPrint("[GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger); + + return ret; +} + +static CARD32 +GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + int event_type = *(int *)arg; + + switch (event_type) + { + case GestureNotifyHold: + DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type); + GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1); + break; + case GestureNotifyTap: + DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type); + GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1); + break; + default: + DetailDebugPrint("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type); + if (timer) + { + DetailDebugPrint("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer); + } + } + + return 0; +} + +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; + } + + DetailDebugPrint("[GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n", num_finger, tap_repeat, cx, cy); + + g_pGesture->recognized_gesture |= WTapFilterMask; + 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; + } + + DetailDebugPrint("[GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)tev.window, (unsigned int)g_pGesture->grabMask); + + GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev); + LOGI("GroupTap Event done. 2 fingers %d tap!", tap_repeat); +} + +void +GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction) +{ + if (num_of_fingers == 0) + { + Window target_win; + WindowPtr target_pWin; + xGestureNotifyFlickEvent fev; + + DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction); + + g_pGesture->recognized_gesture |= WPalmFlickFilterMask; + + 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; + + if (g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if (g_pGesture->grabMask && (target_win != None)) + { + fev.window = target_win; + } + else + { + fev.window = g_pGesture->gestureWin; + } + + DetailDebugPrint("[GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask); + + GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev); + } + else + { + DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction); + + switch (direction) + { + case FLICK_NORTHWARD: + DetailDebugPrint("[GestureHandleGesture_Flick] Flick Down \n"); + GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down); + break; + + case FLICK_SOUTHWARD: + DetailDebugPrint("[GestureHandleGesture_Flick] Flick Up \n"); + GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up); + break; + case FLICK_WESTWARD: + if (g_pGesture->power_pressed == 2) + { + DetailDebugPrint("[GestureHandleGesture_Flick] Flick Right & power_pressed\n"); + GestureEmulateHWKey(g_pGesture->hwkey_dev, 122); + } + break; + default: + break; + } + g_pGesture->recognized_gesture |= WFlickFilterMask; + } +} + +void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds) +{ + Window target_win; + WindowPtr target_pWin; + xGestureNotifyHoldEvent hev; + + DetailDebugPrint("[GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n", num_fingers, cx, cy, holdtime, kinds); + + if (num_fingers == 0) + { + g_pGesture->hold_detected = TRUE; + LOGI("[PalmHold] PalmHold success !\n"); + } + else + { + g_pGesture->recognized_gesture |= WHoldFilterMask; + } + + 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; + + if (g_pGesture->GrabEvents) + { + target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window; + target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin; + } + else + { + target_win = None; + target_pWin = None; + } + + if (g_pGesture->grabMask && (target_win != None)) + { + hev.window = target_win; + } + else + { + hev.window = g_pGesture->gestureWin; + } + + DetailDebugPrint("[GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask); + + GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev); + LOGI("[GroupHold] GestureHold success !\n"); +} + + +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; + + 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_num_pressed = 0; + + static OsTimerPtr tap_event_timer = NULL; + static int event_type = GestureNotifyTap; + + if (timer_expired) + { + DetailDebugPrint("[GroupTap][Timer] state=%d, num_pressed=%d, tap_repeat=%d\n", state, num_pressed, tap_repeat); + + switch (state) + { + case 1://first tap initiation check + if (num_pressed) + { + DetailDebugPrint("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", num_pressed, tap_repeat); + DetailDebugPrint("[GroupTap][F] 1\n"); + + state = 0; + goto cleanup_tap; + } + break; + + case 2: + if (tap_repeat <= 1) + { + state = 0; + DetailDebugPrint("[GroupTap][Timer][state=2] 2 finger %d tap\n", tap_repeat); + LOGI("[GroupTap][F] Second tap doesn't come up in 400ms after first tap.\n"); + goto cleanup_tap; + } + + if (GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed)) + { + DetailDebugPrint("[GroupTap] Success 1!! 2 finger %d tap\n", tap_repeat); + 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) + { + DetailDebugPrint("[GroupTap][P] num_pressed=%d, base_px=%d, base_py=%d. return \n", g_pGesture->num_pressed, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + return; + } + + if ((!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_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, g_pGesture->singletap_threshold, GestureEventTimerHandler, (int *)&event_type); + } + num_pressed = g_pGesture->num_pressed; + + DetailDebugPrint("[GroupTap][P] num_pressed=%d, area_size=%d, base_mx=%d, base_my=%d\n", num_pressed, base_area_size, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + break; + + case ET_Motion: + if (!(g_pGesture->fingers[idx].flags & PressFlagTap)) + { + break; + } + + if (num_pressed < 2) + { + DetailDebugPrint("[GroupTap][M] num_pressed=%d, return \n", num_pressed); + return; + } + + if (num_pressed != g_pGesture->num_pressed) + { + DetailDebugPrint("[GroupTap][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); + } + + 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); + + DetailDebugPrint("[GroupTap][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size)); + DetailDebugPrint("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, g_pGesture->fingers[idx].mx, ABS(cx-base_cx)); + DetailDebugPrint("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, g_pGesture->fingers[idx].my, ABS(cy-base_cy)); + + if (ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD) + { + DetailDebugPrint("[GroupTap][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size)); + DetailDebugPrint("[GroupTap][F] 3\n"); + LOGI("[GroupTap][F] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size)); + + goto cleanup_tap; + } + + if (!INBOX(&base_box_ext, cx, cy)) + { + DetailDebugPrint("[GroupTap][M] current center coordinates is not in base coordinates box !\n"); + DetailDebugPrint("[GroupTap][F] 4\n"); + LOGI("[GroupTap][F] current center coordinates is not in base coordinates box !\n"); + + goto cleanup_tap; + } + } + break; + + case ET_ButtonRelease: + if (g_pGesture->num_pressed) + { + DetailDebugPrint("[GroupTap][R] Second finger doesn't come up. g_pGesture->num_pressed=%d\n", g_pGesture->num_pressed); + break; + } + + if (!tap_repeat) + { + prev_num_pressed = num_pressed; + } + + tap_repeat++; + g_pGesture->num_tap_repeated = tap_repeat; + + DetailDebugPrint("[GroupTap][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed); + DetailDebugPrint("[GroupTap][R] base_rx=%d, base_ry=%d,\n", g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry); + + if ((num_pressed != prev_num_pressed) || (!GestureHasFingerEventMask(GestureNotifyTap, num_pressed))) + { + DetailDebugPrint("[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); + DetailDebugPrint("[GroupTap][F] 5\n"); + LOGI("[GroupTap][F] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n", + num_pressed, prev_num_pressed, num_pressed); + goto cleanup_tap; + } + + if (tap_repeat == 1) + { + DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat); + TimerCancel(tap_event_timer); + tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->doubletap_threshold, GestureEventTimerHandler, (int *)&event_type); + state = 2; + prev_num_pressed = num_pressed; + num_pressed = 0; + break; + } + + else if (tap_repeat == 2) + { + DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat); + TimerCancel(tap_event_timer); + tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->tripletap_threshold, GestureEventTimerHandler, (int *)&event_type); + state = 2; + base_area_size = num_pressed = 0; + break; + } + + DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat); + + if (tap_repeat == MAX_TAP_REPEATS) + { + if (GestureHasFingerEventMask(GestureNotifyTap, num_pressed)) + { + DetailDebugPrint("[GroupTap] Sucess 2!\n"); + GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy); + } + goto cleanup_tap; + } + + if (tap_repeat >= MAX_TAP_REPEATS) + { + LOGI("[GroupTap][F] More than 3 taps. Ignore. \n"); + goto cleanup_tap; + } + + prev_num_pressed = num_pressed; + num_pressed = 0; + break; + } + + return; + +cleanup_tap: + + DetailDebugPrint("[GroupTap][cleanup_tap]\n"); + + if (0 == state) + { + g_pGesture->recognized_gesture &= ~WTapFilterMask; + } + + g_pGesture->filter_mask |= WTapFilterMask; + + if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL) + { + DetailDebugPrint("[GroupTap][cleanup] GestureFlushOrDrop() !\n"); + + if (ERROR_INVALPTR == GestureFlushOrDrop()) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + + num_pressed = 0; + g_pGesture->num_tap_repeated = tap_repeat = 0; + prev_num_pressed = 0; + mbits = 0; + state = 0; + TimerCancel(tap_event_timer); + return; +} + +void +GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction) +{ + static int num_pressed = 0; + static Time base_time = 0; + Time duration; + int distance; + static int diff_base_coord = 0; + static int diff_base_minor_coord = 0; + static int diff_current_coord = 0; + static int false_diff_count = 0; + static int false_minor_diff_count = 0; + static float angle = 0.0f; + static int angle_base_x = 0, angle_base_y = 0; + static int motion_count = 0; + + if (g_pGesture->num_pressed > 1) + { + DetailDebugPrint("[GroupFlick][F] 1\n"); + goto cleanup_flick; + } + + if ((start_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= start_point)) + { + DetailDebugPrint("[GroupFlick][F] 2\n"); + goto cleanup_flick; + } + + switch (type) + { + case ET_ButtonPress: + g_pGesture->fingers[idx].flags = PressFlagFlick; + base_time = GetTimeInMillis(); + num_pressed = g_pGesture->num_pressed; + switch (start_point) + { + case FLICK_POINT_UP: + if (g_pGesture->fingers[idx].py > g_pGesture->flick_press_area) + { + DetailDebugPrint("[GroupFlick][FlickDown][P] press coord is out of bound. (%d, %d)\n", + g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + DetailDebugPrint("[GroupFlick][F] 3\n"); + //LOGI("[BackKey][F] press coord is out of bound (40 pixel from upper vezel). press y=%d\n", g_pGesture->fingers[idx].py); + goto cleanup_flick; + } + + angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py; + angle_base_x = g_pGesture->fingers[idx].px; + DetailDebugPrint("[GroupFlick][FlickDown][P] px=%d, py=%d\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + break; + + case FLICK_POINT_DOWN: + if (g_pGesture->fingers[idx].py < g_pGesture->screen_height - g_pGesture->flick_press_area) + { + DetailDebugPrint("[GroupFlick][FlickUp][P] press coord is out of bound. (%d, %d)\n", + g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + DetailDebugPrint("[GroupFlick][F] 4\n"); + goto cleanup_flick; + } + angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py; + angle_base_x = g_pGesture->fingers[idx].px; + break; + + case FLICK_POINT_LEFT: + if (g_pGesture->fingers[idx].px > g_pGesture->flick_press_area) + { + DetailDebugPrint("[GroupFlick][FlickLeft][P] press coord is out of bound. (%d, %d)\n", + g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + DetailDebugPrint("[GroupFlick][F] 5\n"); + goto cleanup_flick; + } + angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py; + angle_base_x = g_pGesture->fingers[idx].px; + break; + + default: + DetailDebugPrint("[GroupFlick][F] 6\n"); + goto cleanup_flick; + break; + } + + break; + + case ET_Motion: + + motion_count++; + + if (motion_count > 15) + { + DetailDebugPrint("[GroupFlick][F] 6-1 motion_count=%d\n", motion_count); + LOGI("[BackKey][F] More than 15 motion.\n"); + goto cleanup_flick; + } + + if (!(g_pGesture->fingers[idx].flags & PressFlagFlick)) + { + break; + } + + switch (start_point) + { + case FLICK_POINT_UP: + diff_base_coord = diff_current_coord; + diff_current_coord = g_pGesture->fingers[idx].my; + + if ((diff_current_coord - diff_base_coord) < 0) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff\n"); + false_diff_count++; + } + + if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff_count: %d > %d\n", + false_diff_count, FLICK_FALSE_Y_DIFF_COUNT); + DetailDebugPrint("[GroupFlick][F] 7\n"); + LOGI("[BackKey][F] Direction is wrong for 7 times.\n"); + goto cleanup_flick; + } + + if ((g_pGesture->fingers[idx].my < g_pGesture->flick_press_area) && + (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) >(int)( g_pGesture->screen_width/2))) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] move x: %d - %d, y coord: %d\n", + g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].my); + DetailDebugPrint("[GroupFlick][F] 8\n"); + LOGI("[BackKey][F] From press point, moving x axis is more than half screen size.\n"); + goto cleanup_flick; + } + + if ((g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > g_pGesture->flick_minimum_height) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] %d - %d < %d(min_size), angle_base_coord (%d, %d)\n", + g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height, angle_base_x, angle_base_y); + + if (abs(g_pGesture->fingers[idx].mx - angle_base_x) == 0) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] abs(%d - %d) = 0\n", + g_pGesture->fingers[idx].mx, angle_base_x); + angle = 1.0f; + } + else + { + DetailDebugPrint("[GroupFlick][FlickDown][M] angle_base_x: %d, angle_base_y: %d\n", + angle_base_x, angle_base_y); + int y_diff = abs(g_pGesture->fingers[idx].my - angle_base_y); + int x_diff = abs(g_pGesture->fingers[idx].mx - angle_base_x); + angle = (float)y_diff / (float)x_diff; + } + + if (angle < 0.23f) + { + DetailDebugPrint("[GroupFlick][FlickDown][M][F] %d / %d = %f (angle)\n", + abs(g_pGesture->fingers[idx].my - angle_base_y), abs(g_pGesture->fingers[idx].mx - angle_base_x), angle); + DetailDebugPrint("[GroupFlick][F] 9\n"); + LOGI("[BackKey][F] angle is improper. %d < 0.23\n", angle); + goto cleanup_flick; + } + + distance = g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py; + duration = GetTimeInMillis() - base_time; + + GestureHandleGesture_Flick(num_pressed, distance, duration, direction); + DetailDebugPrint("[GroupFlick][FlickDown][M] FlickDown Done!!\n"); + goto cleanup_flick_recognized; + } + else + { + if ((g_pGesture->fingers[idx].mx - diff_base_minor_coord) < 0) + { + false_minor_diff_count++; + } + + if (false_minor_diff_count> FLICK_FALSE_X_DIFF_COUNT) + { + DetailDebugPrint("[GroupFlick][FlickDown][M] false_minor_diff_count: %d > %d\n", + false_minor_diff_count, FLICK_FALSE_X_DIFF_COUNT); + DetailDebugPrint("[GroupFlick][F] 10\n"); + goto cleanup_flick; + } + } + + if (g_pGesture->fingers[idx].my < g_pGesture->flick_press_area) + { + angle_base_x = g_pGesture->fingers[idx].px; + angle_base_y = g_pGesture->fingers[idx].py; + } + DetailDebugPrint("[GroupFlick][FlickDown][M] mx=%d, my=%d, diff_x=%d, diff_y=%d\n", + g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my, abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py)); + + break; + + case FLICK_POINT_DOWN: + diff_base_coord = diff_current_coord; + diff_current_coord = g_pGesture->fingers[idx].my; + + if ((diff_base_coord - diff_current_coord) < 0) + { + false_diff_count++; + } + + if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT) + { + DetailDebugPrint("[GroupFlick][FlickUp][M] false_diff_count: %d > %d\n", + false_diff_count, FLICK_FALSE_Y_DIFF_COUNT); + DetailDebugPrint("[GroupFlick][F] 11\n"); + goto cleanup_flick; + } + + if ((g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my) > g_pGesture->flick_minimum_height) + { + DetailDebugPrint("[GroupFlick][FlickUp][R] %d - %d < %d(min_size)\n", + g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height); + if (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) == 0) + { + DetailDebugPrint("[GroupFlick][FlickUp][R] abs(%d - %d) = 0\n", + g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px); + angle = 1.0f; + } + else + { + int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py); + int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px); + angle = (float)y_diff / (float)x_diff; + } + + if (angle <0.5f) + { + DetailDebugPrint("[GroupFlick][FlickUp][R] %d / %d = %f (angle)\n", + abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), angle); + DetailDebugPrint("[GroupFlick][F] 12\n"); + goto cleanup_flick; + } + + distance = g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my; + duration = GetTimeInMillis() - base_time; + + GestureHandleGesture_Flick(num_pressed, distance, duration, direction); + goto cleanup_flick_recognized; + } + break; + + case FLICK_POINT_LEFT: + diff_base_coord = diff_current_coord; + diff_current_coord = g_pGesture->fingers[idx].mx; + + if ((diff_current_coord - diff_base_coord) < 0) + { + false_diff_count++; + } + + if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT) + { + DetailDebugPrint("[GroupFlick][FlickLeft][M] false_diff_count: %d > %d\n", + false_diff_count, FLICK_FALSE_Y_DIFF_COUNT); + DetailDebugPrint("[GroupFlick][F] 13\n"); + goto cleanup_flick; + } + + if ((g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > g_pGesture->flick_minimum_height) + { + DetailDebugPrint("[GroupFlick][FlickLeft][M] %d - %d < %d(min_size)\n", + g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->flick_minimum_height); + + if (abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) == 0) + { + DetailDebugPrint("[GroupFlick][FlickLeft][M] abs(%d - %d) = 0\n", + g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py); + angle = 1.0f; + } + else + { + int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py); + int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px); + angle = (float)x_diff / (float)y_diff; + } + + if ( angle < 0.5f) + { + DetailDebugPrint("[GroupFlick][FlickLeft][M] %d / %d = %f (angle)\n", + abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), angle); + DetailDebugPrint("[GroupFlick][F] 14\n"); + goto cleanup_flick; + } + + distance = g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px; + duration = GetTimeInMillis() - base_time; + + GestureHandleGesture_Flick(num_pressed, distance, duration, direction); + goto cleanup_flick_recognized; + } + + break; + default: + DetailDebugPrint("[GroupFlick][F] 15\n"); + goto cleanup_flick; + break; + } + break; + + case ET_ButtonRelease: + DetailDebugPrint("[GroupFlick][R][F] 16\n"); + goto cleanup_flick; + break; + } + + return; + +cleanup_flick: + DetailDebugPrint("[GroupFlick] cleanup_flick \n"); + g_pGesture->recognized_gesture &= ~WFlickFilterMask; + motion_count = 0; + +cleanup_flick_recognized: + DetailDebugPrint("[GroupFlick] Flick recognized !\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + num_pressed = 0; + base_time = 0; + false_diff_count = 0; + diff_base_coord = 0; + diff_current_coord = 0; + angle = 0.0f; + angle_base_x = angle_base_y = 0; + motion_count = 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++; + } + + switch (state) + { + case GestureBegin: + DetailDebugPrint("[GroupHold] HOLD Begin !\n"); + break; + + case GestureUpdate: + DetailDebugPrint("[GroupHold] HOLD Update !\n"); + break; + } + + if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed)) + { + DetailDebugPrint("[GroupHold] Success 1! \n"); + GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state); + + // one more time + hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->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) + { + DetailDebugPrint("[GroupHold][P] No num_finger changed ! num_pressed=%d\n", num_pressed); + DetailDebugPrint("[GroupHold][F] 0\n"); + return; + } + + if (!base_area_size || g_pGesture->num_pressed > num_pressed) + { + if (state != GestureEnd) + { + DetailDebugPrint("[GroupHold][P][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); + DetailDebugPrint("[GroupHold][F] 1\n"); + + 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-g_pGesture->hold_move_threshold; + base_box_ext.y1 = base_cy-g_pGesture->hold_move_threshold; + base_box_ext.x2 = base_cx+g_pGesture->hold_move_threshold; + base_box_ext.y2 = base_cy+g_pGesture->hold_move_threshold; + + event_type = GestureNotifyHold; + + hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type); + } + num_pressed = g_pGesture->num_pressed; + + DetailDebugPrint("[GroupHold][P] num_pressed=%d area_size=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy); + + break; + + case ET_Motion: + if (!(g_pGesture->fingers[idx].flags & PressFlagHold)) + { + DetailDebugPrint("[GroupHold][M] No PressFlagHold\n"); + break; + } + + if (num_pressed < 2) + { + DetailDebugPrint("[GroupHold][M] No num_finger changed ! num_pressed=%d\n", num_pressed); + DetailDebugPrint("[GroupHold][F] 2\n"); + return; + } + + if (num_pressed != g_pGesture->num_pressed) + { + if (state != GestureEnd) + { + DetailDebugPrint("[GroupHold][M][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); + DetailDebugPrint("[GroupHold][F] 3\n"); + goto cleanup_hold; + } + + DetailDebugPrint("[GroupHold][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); + } + + area_size = AREA_SIZE(&g_pGesture->area.extents); + cx = AREA_CENTER_X(&g_pGesture->area.extents); + cy = AREA_CENTER_Y(&g_pGesture->area.extents); + + DetailDebugPrint("[GroupHold][M] num_pressed=%d area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size)); + DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx)); + DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy)); + + if (area_size > 0 && base_area_size > 0) + { + if (((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size) >= g_pGesture->hold_area_threshold) + { + DetailDebugPrint("[GroupHold][M] No diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%lf)!\n", area_size, base_area_size, ((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size)); + DetailDebugPrint("[GroupHold][F] 4\n"); + goto cleanup_hold; + } + } + + if (!INBOX(&base_box_ext, cx, cy)) + { + DetailDebugPrint("[GroupHold][M] No current center coordinates is not in base coordinates box !\n"); + DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx)); + DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy)); + DetailDebugPrint("[GroupHold][F] 5\n"); + goto cleanup_hold; + } + break; + + case ET_ButtonRelease: + if (state != GestureEnd && num_pressed >= 2) + { + DetailDebugPrint("[GroupHold][R] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed); + DetailDebugPrint("[GroupHold][F] 6\n"); + goto cleanup_hold; + } + + if (g_pGesture->num_pressed) + { + DetailDebugPrint("[GroupHold][R] num_pressed=%d\n", num_pressed); + DetailDebugPrint("[GroupHold][F] 7\n"); + break; + } + + goto cleanup_hold; + break; + } + + return; + +cleanup_hold: + + DetailDebugPrint("[GroupHold][cleanup_hold] enter!\n"); + + if (state == GestureBegin || state == GestureUpdate) + { + state = GestureEnd; + if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed)) + { + DetailDebugPrint("[GroupHold] Success 2!\n"); + GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state); + } + } + else + { + g_pGesture->recognized_gesture &= ~WHoldFilterMask; + } + + g_pGesture->filter_mask |= WHoldFilterMask; + 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; +} + +int +GestureGetMaxTmajor(InternalEvent *ev, int max_tmajor) +{ + int mt_tmajor_idx = g_pGesture->tmajor_idx; + int mt_tmajor = 0; + + DeviceEvent *de = &ev->device_event; + + if (!de) + { + DetailDebugPrint("[GestureGetMaxTmajor] de is NULL !\n"); + return -1; + } + + if (mt_tmajor_idx < 0) + { + DetailDebugPrint("[GestureGetMaxTmajor] One or more of axes are not supported !\n"); + return -1; + } + + mt_tmajor = de->valuators.data[mt_tmajor_idx]; + + DetailDebugPrint("[GestureGetMaxTmajor]mt_tmajor_idx=%d, mt_tmajor=%d, max_tmajor=%d\n", mt_tmajor_idx, mt_tmajor, max_tmajor); + + return ((mt_tmajor > max_tmajor) ? mt_tmajor : max_tmajor); + +} + +void +GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx) +{ + // static int num_pressed = 0; + static int base_time = 0, current_time = 0; + static int base_x[MAX_MT_DEVICES] = {0}, base_y[MAX_MT_DEVICES] = {0}; + static int update_x[MAX_MT_DEVICES] = {0}, update_y[MAX_MT_DEVICES] = {0}; + + + static int current_x[MAX_MT_DEVICES] = {0}, current_y[MAX_MT_DEVICES] = {0}; + static Bool press_status[MAX_MT_DEVICES] = {FALSE, FALSE}; + static Bool release_status[MAX_MT_DEVICES] = {FALSE, FALSE}; + + static int line_idx[MAX_MT_DEVICES] = {0}, prev_line_idx[MAX_MT_DEVICES] = {0}, press_idx[MAX_MT_DEVICES] = {0}; + static Bool is_line_invalid[MAX_MT_DEVICES] = {TRUE, TRUE}; + + static int max_tmajor[MAX_MT_DEVICES] = {0}; + static int total_max_tmajor = 0; + static Bool is_tmajor_invalid[MAX_MT_DEVICES] = {TRUE, TRUE}; + + static int mt_sync_count[MAX_MT_DEVICES] = {0}; + + static Bool is_palm = FALSE; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + + static Bool is_retry = FALSE; + + int distance, direction, duration; + + if (g_pGesture->recognized_gesture && !(g_pGesture->recognized_gesture & WPalmFlickFilterMask)) + { + PalmFlickDebugPrint("[PalmFlick] recognize other gesture already( g_pGesture->recognized_gesture: %d)\n", g_pGesture->recognized_gesture); + PalmFlickDebugPrint("[PalmFlick][F] 1\n"); + goto flick_failed; + } + + // only first finger recognize + if (!(idx == 0 || idx == 1)) + { + PalmFlickDebugPrint("[PalmFlick] idx=%d, least two fingers come on\n", idx); + return; + } + + switch (type) + { + case ET_ButtonPress: + + if (!is_palm) + { + if (idx == 0) + { + base_time = GetTimeInMillis(); + } + + // press (x,y), touch major + update_x[idx] = base_x[idx] = g_pGesture->fingers[idx].px; + update_y[idx] = base_y[idx] = g_pGesture->fingers[idx].py; + max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx]; + press_status[idx] = TRUE; + is_tmajor_invalid[idx] = FALSE; + is_line_invalid[idx] = FALSE; + + total_max_tmajor = (total_max_tmajor > max_tmajor[idx]) ? total_max_tmajor : max_tmajor[idx]; + + // press region + press_idx[idx] = prev_line_idx[idx] = line_idx[idx] = GesturePalmGetHorizIndexWithX(base_x[idx], idx, type); + + PalmFlickDebugPrint("[PalmFlick][P] idx: %d, num_pressed: %d\n", idx, g_pGesture->num_pressed); + PalmFlickDebugPrint("[PalmFlick][P] base_time: %d, base_x: %d, base_y: %d, line_idx: %d, touch_major=%d\n", + base_time, base_x[idx], base_y[idx], line_idx[idx], max_tmajor[idx]); + + // invalid region + if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT) + { + PalmFlickDebugPrint("[PalmFlick][P][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 2\n"); + goto flick_failed; + } + + // check press point when there are two fingers + if (idx == 1) + { + if (press_idx[0] != press_idx[1]) + { + PalmFlickDebugPrint("[PalmFlick] Press line_idx is the different between two fingers. 1st finger_line_idx=%d, 2nd finger_line_idx=%d\n", + press_idx[0], press_idx[1]); + PalmFlickDebugPrint("[PalmFlick][F] 2-1\n"); + goto flick_failed; + } + } + } + else + { + update_x[idx] = g_pGesture->fingers[idx].px; + update_y[idx] = g_pGesture->fingers[idx].py; + + PalmFlickDebugPrint("[PalmFlick][P] Already palm flick success. base_x=%d, base_y=%d, update_x=%d, update_y=%d\n", + base_x[idx], base_y[idx], update_x[idx], update_y[idx]); + } + + break; + + case ET_Motion: + + if (total_max_tmajor > g_pGesture->palm_flick_max_tmajor_threshold) + { + mt_sync_count[idx]++; + is_palm = TRUE; + DetailDebugPrint("[PalmFlick][M] Sufficient touch enough ! max_tmajor=%d\n", total_max_tmajor); + break; + } + + // motion information (touch major, x, y) + current_x[idx] = g_pGesture->fingers[idx].mx; + current_y[idx] = g_pGesture->fingers[idx].my; + max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx]; + mt_sync_count[idx]++; + + //int temp_total_max_tmajor = (idx == 0 ? max_tmajor[0] : max_tmajor[0] + max_tmajor[1]); + int temp_total_max_tmajor = max_tmajor[idx]; + total_max_tmajor = (total_max_tmajor > temp_total_max_tmajor ? total_max_tmajor : temp_total_max_tmajor); + + PalmFlickDebugPrint("[PalmFlick][M] idx=%d, total_max_tmajor=%d, max_tmajor[0]=%d, max_tmajor[1]=%d, current current=(%d, %d)\n", + idx, total_max_tmajor, max_tmajor[0], max_tmajor[1], current_x[idx], current_y[idx]); + + // exception vezel end line motion + if (current_x[idx] < 5 || current_x[idx] > 355) + { + if (total_max_tmajor >= g_pGesture->palm_flick_max_tmajor_threshold) + { + PalmFlickDebugPrint("[PalmFlick][M][Vezel] Sufficient touch major was came(%d)\n", total_max_tmajor); + is_palm = TRUE; + } + else + { + mt_sync_count[idx]--; + PalmFlickDebugPrint("[PalmFlick][M] Except vezel end line condition. x=%d, sync_count=%d \n", + current_x[idx], mt_sync_count[idx]); + } + break; + } + + // get current position + line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type); + + PalmFlickDebugPrint("[PalmFlick][M] line_idx: %d, prev_line_idx: %d, sync_count: %d\n", + line_idx[idx], prev_line_idx[idx], mt_sync_count[idx]); + + //error check + if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT) + { + PalmFlickDebugPrint("[PalmFlick][M][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 3\n"); + goto flick_failed; + } + + // screen capture motion validation + if (line_idx[idx] != prev_line_idx[idx]) + { + if (base_x[idx] <= pPalmMisc->horiz_coord[0]) + { + if (line_idx[idx] < prev_line_idx[idx]) + { + PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[0]: %d\n", + line_idx[idx], prev_line_idx[idx], pPalmMisc->horiz_coord[0]); + + is_line_invalid[idx] = TRUE; + + if (is_line_invalid[0] && is_line_invalid[1]) + { + PalmFlickDebugPrint("[PalmFlick][F] 4\n"); + goto flick_failed; + } + } + } + else if (base_x[idx] >= pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1]) + { + if (line_idx[idx] > prev_line_idx[idx]) + { + PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[%d]: %d\n", + line_idx[idx], prev_line_idx[idx], PALM_HORIZ_ARRAY_COUNT-1, pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1]); + + is_line_invalid[idx] = TRUE; + + if (is_line_invalid[0] && is_line_invalid[1]) + { + PalmFlickDebugPrint("[PalmFlick][F] 5\n"); + goto flick_failed; + } + } + } + prev_line_idx[idx] = line_idx[idx]; + } + + if (is_palm == FALSE) + { + switch (mt_sync_count[idx]) + { + case 1: + if (total_max_tmajor <= g_pGesture->palm_flick_min_tmajor_threshold) + { + PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n", + mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_min_tmajor_threshold, line_idx[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 6\n"); + is_tmajor_invalid[idx] = TRUE; + //goto flick_failed; + } + break; + case 2: + if (total_max_tmajor <= (g_pGesture->palm_flick_max_tmajor_threshold - 10)) + { + PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n", + mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold-10, line_idx[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 7\n"); + is_tmajor_invalid[idx] = TRUE; + //goto flick_failed; + } + break; + case 3: + if (total_max_tmajor < g_pGesture->palm_flick_max_tmajor_threshold) + { + PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n", + mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold, line_idx[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 8\n"); + is_tmajor_invalid[idx] = TRUE; + //goto flick_failed; + } + break; + default: + PalmFlickDebugPrint("[PalmFlick][M] See more next motion...\n"); + break; + } + } + + if (is_tmajor_invalid[0] && is_tmajor_invalid[1]) + { + PalmFlickDebugPrint("[PalmFlick][M][F] max_tmajor=%d\n", total_max_tmajor); + goto flick_failed; + } + + current_time = GetTimeInMillis(); + + if (current_time - base_time > g_pGesture->palm_flick_time_threshold) + { + PalmFlickDebugPrint("[PalmFlick][M][F] Release event were not came too long time (%d - %d > %d)\n", current_time, base_time, g_pGesture->palm_flick_time_threshold); + PalmFlickDebugPrint("[PalmFlick][F] 10\n"); + goto flick_failed; + } + + break; + + case ET_ButtonRelease: + current_x[idx] = g_pGesture->fingers[idx].mx; + current_y[idx] = g_pGesture->fingers[idx].my; + release_status[idx] = TRUE; + + if ((update_x[idx] == current_x[idx]) && (update_y[idx] == current_y[idx])) + { + PalmFlickDebugPrint("[PalmFlick][R][F] Press point and release point are the same. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n", + update_x[idx], update_y[idx], current_x[idx], current_y[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 10-1\n"); + break; + //goto flick_failed; + } + + if (!is_palm) + { + is_tmajor_invalid[idx] = TRUE; + + if (is_tmajor_invalid[0] && is_tmajor_invalid[1]) + { + PalmFlickDebugPrint("[PalmFlick][R][F] Insufficient touch major was came(%d)\n", total_max_tmajor); + PalmFlickDebugPrint("[PalmFlick][F] 11\n"); + goto flick_failed; + } + } + + line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type); + + if (is_palm && line_idx[idx] == 1) + { + PalmFlickDebugPrint("[PalmFlick][R] Enough major, but release. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n", + base_x[idx], base_y[idx], current_x[idx], current_y[idx]); + is_retry = TRUE; + mt_sync_count[idx] = 0; + break; + } + + if (line_idx[idx] < 0 || line_idx[idx] > PALM_HORIZ_ARRAY_COUNT - 1) + { + is_line_invalid[idx] = TRUE; + + if (is_line_invalid[0] && is_line_invalid[1]) + { + PalmFlickDebugPrint("[PalmFlick][R][F] No line_idx is invalid.. base_x: %d, current_x: %d\n", base_x[idx], current_x[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 12\n"); + goto flick_failed; + } + } + + current_time = GetTimeInMillis(); + + if (current_time - base_time > g_pGesture->palm_flick_time_threshold) + { + PalmFlickDebugPrint("[PalmFlick][R][F] Release event were came to have long delay (%d - %d > %d)\n", + current_time, base_time, g_pGesture->palm_flick_time_threshold); + PalmFlickDebugPrint("[PalmFlick][F] 13\n"); + goto flick_failed; + } + + direction = (line_idx[idx] <= 1) ? FLICK_EASTWARD : FLICK_WESTWARD; + distance = ABS(current_x[idx] - base_x[idx]); + duration = current_time - base_time; + + if (!is_retry) + { + if (GestureHasFingerEventMask(GestureNotifyFlick, 0)) + { + PalmFlickDebugPrint("[PalmFlick][R] Palm Flick1 !!!, direction=%d, distance=%d\n", direction, distance); + is_palm = FALSE; + GestureHandleGesture_Flick(0, distance, duration, direction); + } + } + else + { + if (mt_sync_count[idx] < 25) + { + PalmFlickDebugPrint("[PalmFlick][R][F] No enough motion=%d\n", mt_sync_count[idx]); + PalmFlickDebugPrint("[PalmFlick][F] 14\n"); + goto flick_failed; + } + else + { + if (GestureHasFingerEventMask(GestureNotifyFlick, 0)) + { + PalmFlickDebugPrint("[PalmFlick][R] Palm Flick2 !!!, direction=%d, distance=%d\n", direction, distance); + is_palm = FALSE; + GestureHandleGesture_Flick(0, distance, duration, direction); + } + } + } + + g_pGesture->recognized_gesture |= WPalmFlickFilterMask; + + goto cleanup_flick; + break; + } + + return; + +flick_failed: + + DetailDebugPrint("[PalmFlick][R] flick failed\n"); + + g_pGesture->recognized_gesture &= ~WPalmFlickFilterMask; + g_pGesture->filter_mask |= WPalmFlickFilterMask; + goto cleanup_flick; + +cleanup_flick: + + DetailDebugPrint("[PalmFlick][R] cleanup_flick\n"); + + for (int i = 0; i < MAX_MT_DEVICES; i++) + { + base_x[i] = 0; + base_y[i] = 0; + update_x[i] = 0; + update_y[i] = 0; + current_x[i] = 0; + current_y[i] = 0; + line_idx[i] = 0; + press_idx[i] = 0; + prev_line_idx[i] = 0; + max_tmajor[i] = 0; + mt_sync_count[i] = 0; + press_status[i] = FALSE; + release_status[i] = FALSE; + is_tmajor_invalid[i] = TRUE; + is_line_invalid[i] = TRUE; + } + + total_max_tmajor = 0; + is_palm = FALSE; + is_retry = FALSE; + + return; +} + +static int +GesturePalmGetHorizIndexWithX(int current_x, int idx, int type) +{ + int i; + int ret_idx = -1; + static int pressed_idx[MAX_MT_DEVICES] = {-1, -1}; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + + for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++) + { + if (current_x <= pPalmMisc->horiz_coord[i]) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX] index=%d, pPalmMisc->horiz_coord[%d]=%d\n", i, i, pPalmMisc->horiz_coord[i]); + + ret_idx = i; + goto index_check; + } + } + + DetailDebugPrint("[GesturePalmGetHorizIndexWithX]Error ! Failed to get horiz coordinate index !\n"); + return ret_idx; + +index_check: + + if (type == ET_ButtonPress) + { + pressed_idx[idx] = ret_idx; + + // first press is center + if (pressed_idx[idx] == PALM_HORIZ_ARRAY_COUNT -2) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] Invalid press area x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]); + ret_idx = -1; + } + + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] pressed_idx=%d\n", pressed_idx[idx]); + } + + else if (type == ET_Motion) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][M] moving x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]); + } + + else if (type == ET_ButtonRelease) + { + if ((pressed_idx[idx] == 0) && (ret_idx == (PALM_HORIZ_ARRAY_COUNT - 1))) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the left to the right ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx); + } + else if ((pressed_idx[idx] == (PALM_HORIZ_ARRAY_COUNT - 1)) && (ret_idx == 0)) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the right to the left ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx); + } + else if ((pressed_idx[idx] == ret_idx) && ret_idx != 1) + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Relased the same region ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx); + return 1; + } + else + { + DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Invalid ! pressed_idx=%d, released_idx=%d\n", pressed_idx[idx], ret_idx); + ret_idx = -1; + } + + pressed_idx[idx] = -1; + } + + return ret_idx; +} + +static int +GesturePalmGetAbsAxisInfo(DeviceIntPtr dev) +{ + int i, found = 0; + int numAxes; + + Atom atom_tpalm; + Atom atom_mt_slot; + Atom atom_tracking_id; + Atom atom_tmajor; + Atom atom_tminor; + + g_pGesture->tpalm_idx = -1; + g_pGesture->tmajor_idx = -1; + g_pGesture->tminor_idx = -1; + + if (!dev || !dev->valuator) + goto out; + + numAxes = dev->valuator->numAxes; + + atom_tpalm = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PALM); + atom_mt_slot = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_SLOT); + atom_tracking_id = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TRACKING_ID); + atom_tmajor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR); + atom_tminor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR); + + if (!numAxes || !atom_tpalm || !atom_tmajor || !atom_tminor) + { + ErrorF("one or more axes is/are not supported!\n"); + goto out; + } + + for (i = 0; i < numAxes; i++) + { + AxisInfoPtr axes = &dev->valuator->axes[i]; + + if (!axes || (axes->mode != Absolute)) + continue; + + if (axes->label == atom_tpalm) + { + g_pGesture->tpalm_idx = i; + found += 1; + } + else if (axes->label == atom_tmajor) + { + g_pGesture->tmajor_idx = i; + found += 2; + } + else if (axes->label == atom_tminor) + { + g_pGesture->tminor_idx = i; + found += 4; + } + } + + if (found != 7) + { + ErrorF("Axes for palm recognization are not supported !\n"); + goto out; + } + + g_pGesture->palm_misc.enabled = 1; + ErrorF("Axes for palm recognization are supported !\n"); + return 1; + +out: + g_pGesture->palm_misc.enabled = 0; + ErrorF("Palm recognization is not supported !\n"); + return 0; +} + +static int +GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device) +{ + int mt_palm_idx = g_pGesture->tpalm_idx; + int mt_palm = 0; + + DeviceEvent *de = &ev->device_event; + + if (!de) + { + ErrorF("[GestureGetPalmValuator] de is NULL !\n"); + return -1; + } + + if (mt_palm_idx < 0) + { + ErrorF("[GestureGetPalmValuator] One or more of axes are not supported !\n"); + return -1; + } + + mt_palm = de->valuators.data[mt_palm_idx]; + + HoldDetectorDebugPrint("[GestureGetPalmValuator] mt_palm:%d\n", mt_palm); + + return mt_palm; +} + +static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + int idx = -1; + pixman_region16_t tarea1; + static int num_pressed = 0; + unsigned int hold_area_size; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + int palm_flag = 0; + + if (!g_pGesture->has_hold_grabmask) + { + HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->has_hold_grabmask=%d\n", g_pGesture->has_hold_grabmask); + + Mask eventmask = (1L << GestureNotifyHold); + + if ((g_pGesture->grabMask & eventmask) && + (g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[0].window != None)) + { + g_pGesture->has_hold_grabmask = 1; + + //Initialize a set of variables + num_pressed = 0; + memset(&g_pGesture->cts, 0, sizeof(g_pGesture->cts)); + pixman_region_init(&g_pGesture->chold_area); + + HoldDetectorDebugPrint("[GestureHoldDetector] Initialize...\n"); + } + else + { + //reset local hold_grab_mask variable + g_pGesture->has_hold_grabmask = 0; + + g_pGesture->hold_detector_activate = 0; + HoldDetectorDebugPrint("[GestureHoldDetector] has_hold_grabmask=0 and g_pGesture->hold_detector_activate=0\n"); + return; + } + } + + if (IGNORE_EVENTS == g_pGesture->ehtype || + device->id < g_pGesture->first_fingerid) + { + HoldDetectorDebugPrint("[GestureHoldDetector] Return (IGNORE_EVENTS or device->id:%d < first_fingerid:%d)\n", device->id, g_pGesture->first_fingerid); + return; + } + + palm_flag = GestureGetPalmValuator(ev, device); + + if (palm_flag) + { + GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureBegin); + GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureEnd); + + g_pGesture->hold_detector_activate = 0; + g_pGesture->has_hold_grabmask = 0; + HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d enable\n", palm_flag); + return; + } + else + { + HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d disable\n", palm_flag); + return; + } + + HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->num_mt_devices:%d\n", g_pGesture->num_mt_devices); + + for (i = 0; i < g_pGesture->num_mt_devices; i++) + { + if ( device->id == g_pGesture->mt_devices[i]->id) + { + idx = i; + HoldDetectorDebugPrint("[GestureHoldDetector] idx:%d\n", idx); + break; + } + } + if ((idx < 0) || ((MAX_MT_DEVICES-1) < idx)) return; + + switch (type) + { + case ET_ButtonPress: + g_pGesture->cts[idx].status = BTN_PRESSED; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + num_pressed++; + HoldDetectorDebugPrint("[GestureHoldDetector][P] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed); + + if (num_pressed < 2) + { + HoldDetectorDebugPrint("[GestureHoldDetector][P] num_pressed:%d\n", num_pressed); + break; + } + + if (num_pressed > g_pGesture->num_mt_devices) + num_pressed = g_pGesture->num_mt_devices; + + pixman_region_init(&tarea1); + pixman_region_init(&g_pGesture->chold_area); + pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1); + + tarea1.extents.x1 = g_pGesture->cts[0].cx; + tarea1.extents.x2 = g_pGesture->cts[0].cx+1; + tarea1.extents.y1 = g_pGesture->cts[0].cy; + tarea1.extents.y2 = g_pGesture->cts[0].cy+1; + + pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1); + + for (i = 1; i < num_pressed; i++) + { + pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1); + + tarea1.extents.x1 = g_pGesture->cts[i].cx; + tarea1.extents.x2 = g_pGesture->cts[i].cx + 1; + tarea1.extents.y1 = g_pGesture->cts[i].cy; + tarea1.extents.y2 = g_pGesture->cts[i].cy + 1; + + pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1); + } + break; + + case ET_Motion: + if (BTN_RELEASED == g_pGesture->cts[idx].status) + return; + + g_pGesture->cts[idx].status = BTN_MOVING; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + + HoldDetectorDebugPrint("[GestureHoldDetector][M] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed); + + if (num_pressed < 2) + { + HoldDetectorDebugPrint("[GestureHoldDetector][M] num_pressed:%d\n", num_pressed); + break; + } + + pixman_region_init(&tarea1); + pixman_region_init(&g_pGesture->chold_area); + pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1); + + tarea1.extents.x1 = g_pGesture->cts[0].cx; + tarea1.extents.x2 = g_pGesture->cts[0].cx+1; + tarea1.extents.y1 = g_pGesture->cts[0].cy; + tarea1.extents.y2 = g_pGesture->cts[0].cy+1; + + pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1); + + for (i = 1; i < num_pressed; i++) + { + pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1); + + tarea1.extents.x1 = g_pGesture->cts[i].cx; + tarea1.extents.x2 = g_pGesture->cts[i].cx + 1; + tarea1.extents.y1 = g_pGesture->cts[i].cy; + tarea1.extents.y2 = g_pGesture->cts[i].cy + 1; + + pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1); + } + break; + + case ET_ButtonRelease: + g_pGesture->cts[idx].status = BTN_RELEASED; + g_pGesture->cts[idx].cx = ev->device_event.root_x; + g_pGesture->cts[idx].cy = ev->device_event.root_y; + + HoldDetectorDebugPrint("[GestureHoldDetector][R] cx:%d, cy:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy); + + num_pressed--; + if (num_pressed <3) + { + pixman_region_init(&g_pGesture->chold_area); + } + break; + } + + if (num_pressed >= 2) + { + hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents); + + HoldDetectorDebugPrint("[GestureHoldDetector] hold_area_size=%d, pPalmMisc->half_scrn_area_size=%d\n", hold_area_size, pPalmMisc->half_scrn_area_size); + + if (pPalmMisc->half_scrn_area_size <= hold_area_size) + { + GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureBegin); + GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureEnd); + + g_pGesture->hold_detector_activate = 0; + g_pGesture->has_hold_grabmask = 0; + } + } + else + { + hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents); + HoldDetectorDebugPrint("[GestureHoldDetector] num_pressed is under 2, hold_area_size=%d\n", hold_area_size); + } +} + + +static int +GesturePalmGetScreenInfo() +{ + int i; + pixman_region16_t tarea; + PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc; + ScreenPtr pScreen = miPointerCurrentScreen(); + + if (!pScreen) + { + DetailDebugPrint("[X11][GesturePalmGetScreenInfo]Failed to get screen information !\n"); + + pPalmMisc->scrn_width = pPalmMisc->scrn_height = 0; + return 0; + } + + pPalmMisc->scrn_width = pScreen->width; + pPalmMisc->scrn_height = pScreen->height; + pixman_region_init(&tarea); + pixman_region_init_rect(&tarea, 0, 0, pPalmMisc->scrn_width, pPalmMisc->scrn_height); + + DetailDebugPrint("[X11][GesturePalmGetScreenInfo] x2:%d, x2:%d, y2:%d, y1:%d \n", tarea.extents.x2, tarea.extents.x1, tarea.extents.y2, tarea.extents.y1); + pPalmMisc->half_scrn_area_size = AREA_SIZE(&tarea.extents); + pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 4); + + DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->half_scrn_area_size = %d\n", pPalmMisc->half_scrn_area_size); + + for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++) + { + pPalmMisc->horiz_coord[i] = pPalmMisc->scrn_width * ((i+1)/(double)PALM_HORIZ_ARRAY_COUNT); + DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->horiz_coord[%d]=%d, pPalmMisc->scrn_width=%d\n", i, pPalmMisc->horiz_coord[i], pPalmMisc->scrn_width); + } + for (i = 0; i < PALM_VERTI_ARRAY_COUNT; i++) + { + pPalmMisc->verti_coord[i] = pPalmMisc->scrn_height * ((i+1)/(double)PALM_VERTI_ARRAY_COUNT); + DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->verti_coord[%d]=%d, pPalmMisc->scrn_height=%d\n", i, pPalmMisc->verti_coord[i], pPalmMisc->scrn_height); + } + + return 1; +} + + +static inline void +GestureEnableDisable() +{ + GestureEnable(1, FALSE, g_pGesture->this_device); +#if 0 + if ((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None)) + { + GestureEnable(1, FALSE, g_pGesture->this_device); + } + else + { + GestureEnable(0, FALSE, g_pGesture->this_device); + } +#endif +} + +void +GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent) +{ + g_pGesture->grabMask = *pGrabMask; + g_pGesture->GrabEvents = (GestureGrabEventPtr)pGrabEvent; + GestureEnableDisable(); +} + +void +GestureCbEventsSelected(Window win, Mask *pEventMask) +{ + g_pGesture->lastSelectedWin = win; + g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0; + GestureEnableDisable(); +} + +WindowPtr +GestureGetEventsWindow(void) +{ + Mask mask; + WindowPtr pWin; + + pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py); + + if (pWin) + { + DetailDebugPrint("[GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id); + g_pGesture->gestureWin = pWin->drawable.id; + } + else + { + DetailDebugPrint("[GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n"); + return NULL; + } + + if (g_pGesture->gestureWin == g_pGesture->lastSelectedWin) + { + g_pGesture->eventMask = g_pGesture->lastSelectedMask; + goto nonempty_eventmask; + } + + //check selected event(s) + if (!GestureHasSelectedEvents(pWin, &g_pGesture->eventMask)) + { + g_pGesture->eventMask = 0; + } + else + { + g_pGesture->lastSelectedWin = g_pGesture->gestureWin; + g_pGesture->lastSelectedMask = g_pGesture->eventMask; + } + + if (!g_pGesture->eventMask && !g_pGesture->grabMask) + { + DetailDebugPrint("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id); + return NULL; + } + +nonempty_eventmask: + + DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask); + + mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask)); + + DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask); + + g_pGesture->filter_mask = mask; + + DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask); + + return pWin; +} + +static CARD32 +GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + g_pGesture->filter_mask |= WTapFilterMask; + g_pGesture->filter_mask |= WHoldFilterMask; + //LOGI("[GroupTap][GroupHold] 50ms after 1st finger.\n"); + + DetailDebugPrint("[GestureSingleFingerTimerHandler] TapFilterMask, HoldFilterMask \n"); + + if ((g_pGesture->event_sum[0] == BTN_PRESSED) && ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) && (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point))) + { + DetailDebugPrint("[GestureSingleFingerTimerHandler] press_point: %d\n", g_pGesture->flick_pressed_point); + DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + } + + if (g_pGesture->flick_pressed_point == FLICK_POINT_DOWN && abs(g_pGesture->fingers[0].py - g_pGesture->fingers[0].my) < 3) + { + DetailDebugPrint("[GestureSingleFingerTimerHandler] py: %d, my: %d\n", g_pGesture->fingers[0].py, g_pGesture->fingers[0].my); + DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + } + + DetailDebugPrint("[GestureSingleFingerTimerHandler] expired !\n"); + + if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL) + { + if ( ERROR_INVALPTR == GestureFlushOrDrop()) + { + DetailDebugPrint("[GestureSingleFingerTimerHandler] AllFilterMask, Flush!\n"); + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + + return 0; +} + +static int +GestureGetFingerIndexFromDevice(DeviceIntPtr device) +{ + int i; + + for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ ) + { + if( device->id == g_pGesture->mt_devices[i]->id ) + { + return i; + } + } + + return -1; +} + +void +GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device) +{ + int i; + static OsTimerPtr single_finger_timer = NULL; + int idx = -1; + + if (PROPAGATE_EVENTS == g_pGesture->ehtype || device->id < g_pGesture->first_fingerid) + { + return; + } + + idx = GestureGetFingerIndexFromDevice(device); + + if (idx < 0) + return; + + switch (type) + { + case ET_ButtonPress: + if (idx == 0) + { + g_pGesture->event_sum[0] = BTN_PRESSED; + } + + g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]); + + 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->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; + + g_pGesture->num_pressed++; + g_pGesture->inc_num_pressed = g_pGesture->num_pressed; + + if (g_pGesture->inc_num_pressed == 1) + { + pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]); + } + 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]); + } + } + + DetailDebugPrint("[GestureRecognize][P] num_pressed=%d, area_size=%d, px=%d, py=%d\n", + g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py); + + if (g_pGesture->num_pressed == 1) + { + single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL); + + if (g_pGesture->fingers[idx].py <= g_pGesture->flick_press_area) + { + if ((!g_pGesture->activate_flick_down) + || (g_pGesture->fingers[idx].px <= (g_pGesture->flick_press_area_left_right)) + || (g_pGesture->fingers[idx].px >= (g_pGesture->screen_width - g_pGesture->flick_press_area_left_right))) + { + DetailDebugPrint("[GestureRecognize][P] px=%d, flick_press_area_left_right=%d\n", + g_pGesture->fingers[idx].px, g_pGesture->flick_press_area_left_right); + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + LOGI("[BackKey][F] Press touch within 40 pixel area from left or right vezel\n"); + } + else + { + DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_UP\n"); + g_pGesture->flick_pressed_point = FLICK_POINT_UP; + } + } + else + { + LOGI("[BackKey][F] Press touch outside 40 pixel area from upper vezel. \n"); + } + + if (g_pGesture->fingers[idx].py >= (g_pGesture->screen_height - g_pGesture->flick_press_area)) + { + if (!g_pGesture->activate_flick_up) + { + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + } + else + { + DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_DOWN\n"); + g_pGesture->flick_pressed_point = FLICK_POINT_DOWN; + } + } + else if ( g_pGesture->fingers[idx].px <= g_pGesture->flick_press_area_left) + { + if (!g_pGesture->activate_flick_right) + { + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + } + else + { + DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_LEFT\n"); + g_pGesture->flick_pressed_point = FLICK_POINT_LEFT; + } + } + + DetailDebugPrint("[GestureRecognize][P] flick_press_point: %d\n", g_pGesture->flick_pressed_point); + + if ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point)) + { + DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_NONE\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + } + else + { + g_pGesture->flick_direction = (g_pGesture->flick_pressed_point - 1) * 2; + if ((g_pGesture->flick_direction == FLICK_WESTWARD) && (g_pGesture->power_pressed != 2)) + { + DetailDebugPrint("[GestureRecognize][P] Flick WesWard is disable when power is not pressed\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + } + if ((g_pGesture->flick_direction < FLICK_NORTHWARD) || (FLICK_NORTHWESTWARD < g_pGesture->flick_direction)) + { + DetailDebugPrint("[GestureRecognize][P] Invalid flick direction\n"); + g_pGesture->filter_mask |= WFlickFilterMask; + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + } + + DetailDebugPrint("[GestureRecognize][P] flick_direction: %d\n", g_pGesture->flick_direction); + } + } + else + { + DetailDebugPrint("[GestureRecognize][P] Two more fingers come on!\n"); + TimerCancel(single_finger_timer); + single_finger_timer = NULL; + } + break; + + case ET_Motion: + + if (!g_pGesture->fingers[idx].ptime) + { + DetailDebugPrint("[GestureRecognize][M] Start motion. idx=%d\n", idx); + g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]); + return; + } + + g_pGesture->fingers[idx].mx = ev->device_event.root_x; + g_pGesture->fingers[idx].my = ev->device_event.root_y; + g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]); + + if (idx == 0) + { + g_pGesture->event_sum[0] += BTN_MOVING; + } + + 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]); + } + 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]); + } + } + + DetailDebugPrint("[GestureRecognize][M] num_pressed=%d, area_size=%d, mx=%d, my=%d\n", + g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my); + + 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->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]); + + g_pGesture->num_pressed--; + + if (g_pGesture->num_pressed == 0) + { + DetailDebugPrint("[GestureRecognize] All fingers were released !\n"); + } + else if (g_pGesture->num_pressed < 0) + { + DetailDebugPrint("[GestureRecognize] All fingers were released. But, num_pressed is under 0 !\n"); + } + + DetailDebugPrint("[GestureRecognize][R] num_pressed=%d, rx=%d, ry=%d\n", + g_pGesture->num_pressed, g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry); + + break; + } + + if (!(g_pGesture->filter_mask & WFlickFilterMask)) + { + DetailDebugPrint("[GestureRecognize] GestureRecognize_groupFlick !\n"); + GestureRecognize_GroupFlick(type, ev, device, idx, g_pGesture->flick_pressed_point, g_pGesture->flick_direction); + } + if (!(g_pGesture->filter_mask & WTapFilterMask)) + { + DetailDebugPrint("[GestureRecognize] GestureRecognize_groupTap !\n"); + GestureRecognize_GroupTap(type, ev, device, idx, 0); + } + if (!(g_pGesture->filter_mask & WHoldFilterMask)) + { + DetailDebugPrint("[GestureRecognize] GestureRecognize_groupHold !\n"); + GestureRecognize_GroupHold(type, ev, device, idx, 0); + } +/* + if (!(g_pGesture->filter_mask & WPalmFlickFilterMask)) + { + DetailDebugPrint("[GestureRecognize] GestureRecognize_palmFlick !\n"); + GestureRecognize_PalmFlick(type, ev, device, idx); + } +*/ + DetailDebugPrint("[GestureRecognize][N] g_pGesture->filter_mask = 0x%x, g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x, g_pGesture->recognized_gesture=0x%x\n", + g_pGesture->filter_mask, GESTURE_WATCH_FILTER_MASK_ALL, g_pGesture->recognized_gesture); + + if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL) + { + if (!g_pGesture->recognized_gesture) + { + DetailDebugPrint("[GestureRecognize][F] 1 !\n"); + goto flush_or_drop; + } + else if (!g_pGesture->num_pressed) + { + DetailDebugPrint("[GestureRecognize][F] 2 !\n"); + goto flush_or_drop; + } + } + + if (g_pGesture->recognized_gesture) + { + if (g_pGesture->ehtype == KEEP_EVENTS) + { + DetailDebugPrint("[GestureRecognize] Keep Event !\n"); + GestureEventsDrop(); + } + g_pGesture->ehtype = IGNORE_EVENTS; + } + return; + +flush_or_drop: + + DetailDebugPrint("[GestureRecognize] GestureFlushOrDrop() !\n"); + + if (ERROR_INVALPTR == GestureFlushOrDrop()) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } +} + +ErrorStatus GestureFlushOrDrop(void) +{ + ErrorStatus err; + + if (g_pGesture->recognized_gesture) + { + g_pGesture->ehtype = IGNORE_EVENTS; + GestureEventsDrop(); + DetailDebugPrint("[GestureFlushOrDrop][Drop] IGNORE_EVENTS\n"); + } + else + { + g_pGesture->ehtype = PROPAGATE_EVENTS; + + err = GestureEventsFlush(); + + if (ERROR_NONE != err) + { + return err; + } + + DetailDebugPrint("[GestureFlushOrDrop][Flush] PROPAGATE_EVENTS\n"); + DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask); + DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x\n", GESTURE_WATCH_FILTER_MASK_ALL); + DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture); + } + + 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; + int idx; + +#ifdef __DEBUG_EVENT_HANDLER__ + DetailDebugPrint("[GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n", + ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis()); +#endif + + if (!g_pGesture->is_active) + { + g_pGesture->ehtype = PROPAGATE_EVENTS; + DetailDebugPrint("[GestureHandleMTSyncEvent] PROPAGATE_EVENT\n"); + return; + } + + switch(ev->any_event.sync) + { + case ROTARY_FRAME_SYNC_BEGIN: + if (g_pGesture->mt_devices[0] && (g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH)) + { + int zero = 0; + xf86PostButtonEvent(g_pGesture->mt_devices[0], 0, Button1, 0, 0, 2, &zero, &zero); + } + g_pGesture->mtsync_flag |= MTSYNC_FLAG_ROTARY; + DetailDebugPrint("[GestureHandleMTSyncEvent] Rotary input starts. Now touch events are dropped!\n"); + break; + case ROTARY_FRAME_SYNC_END: + g_pGesture->mtsync_flag &= ~MTSYNC_FLAG_ROTARY; + DetailDebugPrint("[GestureHandleMTSyncEvent] Rotary input is finished. Now touch events are not dropped!\n"); + break; + case MTOUCH_FRAME_SYNC_BEGIN: + g_pGesture->mtsync_flag |= MTSYNC_FLAG_TOUCH; + DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_BEGIN\n"); + g_pGesture->ehtype = KEEP_EVENTS; + g_pGesture->filter_mask = 0; + g_pGesture->recognized_gesture = 0; + g_pGesture->hold_detector_activate = 1; + g_pGesture->num_pressed = 0; + g_pGesture->has_hold_grabmask = 0; + g_pGesture->mtsync_total_count = 0; + memset(&g_pGesture->last_touches, 0, sizeof(g_pGesture->last_touches)); + for (i=0; i < g_pGesture->num_mt_devices; i++) + { + g_pGesture->fingers[i].ptime = 0; + g_pGesture->max_mt_tmajor[i] = 0; + } + break; + case MTOUCH_FRAME_SYNC_END: + g_pGesture->mtsync_flag &= ~MTSYNC_FLAG_TOUCH; + DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_END\n"); + g_pGesture->ehtype = PROPAGATE_EVENTS; + g_pGesture->flick_pressed_point = FLICK_POINT_NONE; + g_pGesture->pTempWin = NULL; + g_pGesture->num_pressed = 0; + g_pGesture->hold_detected = FALSE; + break; + case MTOUCH_FRAME_SYNC_UPDATE: + g_pGesture->mtsync_flag |= MTSYNC_FLAG_TOUCH; + g_pGesture->mtsync_total_count++; + + DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_Update. mt_total_sync=%d\n", g_pGesture->mtsync_total_count); + + if ((g_pGesture->inc_num_pressed < 2) && (g_pGesture->filter_mask != GESTURE_WATCH_FILTER_MASK_ALL)) + { + if (g_pGesture->num_tap_repeated == 1 || g_pGesture->num_tap_repeated == 2) + { + if (g_pGesture->mtsync_total_count >= 6) + { + DetailDebugPrint("[GestureHandleMTSyncEvent] Moving Limit first tap repeated. tap_repeated: %d, mtsync_total_count: %d\n", + g_pGesture->num_tap_repeated, g_pGesture->mtsync_total_count); + g_pGesture->filter_mask |= WTapFilterMask; + g_pGesture->filter_mask |= WHoldFilterMask; + LOGI("[GroupTap][GroupHold] Motions are more than 6 between 1st finger and 2nd finger.\n"); + } + } + + if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL) + { + DetailDebugPrint("[GestureHandleMTSyncEvent] Gesture filter mask all. GestureFlushOrDrop() !\n"); + + if (ERROR_INVALPTR == GestureFlushOrDrop()) + { + GestureControl(g_pGesture->this_device, DEVICE_OFF); + } + } + } + break; + default: + ErrorF("[GestureHandleMTSyncEvent] Unknown MTSync Event received.\n"); + break; + } +} + +void GestureEmulateHWKey(DeviceIntPtr dev, int keycode) +{ + if (dev) + { + DetailDebugPrint("[GestureEmulateHWKey] keycode=%d\n", keycode); + xf86PostKeyboardEvent(dev, keycode, 1); + xf86PostKeyboardEvent(dev, keycode, 0); + } +} + +void +GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_HANDLER__ + DetailDebugPrint("[GestureHandleButtonPressEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif//__DEBUG_EVENT_HANDLER__ + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n"); + return; + } + + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_PRESSED; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->ehtype != KEEP_EVENTS) + { + if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY) + { + DetailDebugPrint("[GestureHandleButtonPressEvent] Rotary input is coming. Dropping touch events.\n"); + return; + } + else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH) + { + DetailDebugPrint("[GestureHandleButtonPressEvent] Other input is coming. Dropping touch events.\n"); + return; + } + } + + switch (g_pGesture->ehtype) + { + case KEEP_EVENTS: + DetailDebugPrint("[GestureHandleButtonPressEvent] KEEP_EVENT\n"); + + 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); + } + + GestureHoldDetector(ET_ButtonPress, ev, device); + break; + + case PROPAGATE_EVENTS: + DetailDebugPrint("[GestureHandleButtonPressEvent] PROPAGATE_EVENT\n"); + + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_ButtonPress, ev, device); + break; + + case IGNORE_EVENTS: + DetailDebugPrint("[GestureHandleButtonPressEvent] IGNORE_EVENTS\n"); + + GestureRecognize(ET_ButtonPress, ev, device); + break; + + default: + break; + } +} + +void +GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ +#ifdef __DEBUG_EVENT_MOTION_HANDLER__ + DetailDebugPrint("[GestureHandleMotionEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n"); + return; + } + + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_MOVING; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->ehtype != KEEP_EVENTS) + { + if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY) + { + DetailDebugPrint("[GestureHandleMotionEvent] Rotary input is coming. Dropping touch events.\n"); + return; + } + else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH) + { + DetailDebugPrint("[GestureHandleMotionEvent] Other input is coming. Dropping touch events.\n"); + return; + } + } + + 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); + } + + GestureHoldDetector(ET_Motion, ev, device); + break; + + case PROPAGATE_EVENTS: + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_Motion, 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__ + DetailDebugPrint("[GestureHandleButtonReleaseEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y); +#endif + int idx=0; + if (g_pGesture->touch_cancel_status == TRUE) + { + DetailDebugPrint("[GestureHandleButtonPressEvent] Ignore Button Press event after touch cancel generated. \n"); + return; + } + + idx = GestureGetFingerIndexFromDevice(device); + if (0 <= idx) + { + g_pGesture->last_touches[idx].status = BTN_RELEASED; + g_pGesture->last_touches[idx].cx = ev->device_event.root_x; + g_pGesture->last_touches[idx].cy = ev->device_event.root_y; + } + + if (g_pGesture->ehtype != KEEP_EVENTS) + { + if(!(g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH)) + { + if(g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY) + { + DetailDebugPrint("[GestureHandleButtonReleaseEvent] Rotary input is coming. Dropping touch events.\n"); + return; + } + else if (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH) + { + DetailDebugPrint("[GestureHandleButtonReleaseEvent] Other input is coming. Dropping touch events.\n"); + return; + } + } + } + + switch (g_pGesture->ehtype) + { + case KEEP_EVENTS: + DetailDebugPrint("[GestureHandleButtonReleaseEvent] KEEP_EVENT\n"); + + 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); + } + + GestureHoldDetector(ET_ButtonRelease, ev, device); + break; + + case PROPAGATE_EVENTS: + DetailDebugPrint("[GestureHandleButtonReleaseEvent] PROPAGATE_EVENTS\n"); +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT + if( IsMaster(device) && ev->any.type == ET_ButtonRelease ) + { + if( g_pGesture->anr_window == NULL ) + { + g_pGesture->anr_window = _GestureFindANRWindow(device); + } + Time current_time; + + // Send event to the e17 process. + current_time = GetTimeInMillis(); + if( g_pGesture->anr_window != NULL ) + { + // Check anr_window validation. + if( dixLookupWindow(&g_pGesture->anr_window, prop_anr_event_window_xid, serverClient, DixSetPropAccess) != BadWindow ) + { + if( serverClient->devPrivates != NULL ) + dixChangeWindowProperty (serverClient, g_pGesture->anr_window, prop_anr_in_input_event, + XA_CARDINAL, 32, PropModeReplace, 1, ¤t_time, TRUE); + } + else + { + prop_anr_event_window_xid = 0; + g_pGesture->anr_window = NULL; + } + DetailDebugPrint("[GestureHandleButtonReleaseEvent] Release TOUCH!! devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis()); + } + } +#endif + device->public.processInputProc(ev, device); + GestureHoldDetector(ET_ButtonRelease, ev, device); +#if 0 + GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down); + GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up); +#endif + break; + + case IGNORE_EVENTS: + DetailDebugPrint("[GestureHandleButtonReleaseEvent] IGNORE_EVENTS\n"); + GestureRecognize(ET_ButtonRelease, ev, device); + break; + + default: + break; + } +} + +void +GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0)) + { + g_pGesture->power_pressed = 2; + g_pGesture->power_device = device; + + DetailDebugPrint("[GestureHandleKeyPressEvent] power key pressed devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id); + DetailDebugPrint("[GestureHandleKeyPressEvent] power_pressed: %d\n", g_pGesture->power_pressed); + } + device->public.processInputProc(ev, device); +} + +void +GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device) +{ + if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0)) + { + g_pGesture->power_pressed = 1; + g_pGesture->power_device = device; + + DetailDebugPrint("[GestureHandleKeyReleaseEvent] power key released devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id); + DetailDebugPrint("[GestureHandleKeyReleaseEvent] power_pressed: %d\n", g_pGesture->power_pressed); + } + device->public.processInputProc(ev, device); +} + +static void +GestureHandleClientState (CallbackListPtr *list, pointer closure, pointer calldata) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata; + ClientPtr client = clientinfo->client; + + if (client->clientState != ClientStateGone) + { + return; + } + + if (!g_pGesture->factory_cmdname) + { + return; + } + + if (strncmp(client->clientIds->cmdname, g_pGesture->factory_cmdname, strlen(g_pGesture->factory_cmdname))) + { + return; + } + + if (g_pGesture->is_active == 0) + { + int prop_val = 1; + int rc = XIChangeDeviceProperty(g_pGesture->this_device, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &prop_val, FALSE); + + ErrorF("[GestureHandleClientState] %s is exited unintentionally\n", g_pGesture->factory_cmdname); + + if (rc != Success) + { + ErrorF("[GestureHandleClientState] Failed to Gesture Enable\n"); + return; + } + } +} + +static ErrorStatus +GestureEnableEventHandler(InputInfoPtr pInfo) +{ + Bool res; + GestureDevicePtr pGesture = pInfo->private; + + res = GestureInstallResourceStateHooks(); + + if (!res) + { + ErrorF("[GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n"); + return ERROR_ABNORMAL; + } + + res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES); + + if (!res) + { + ErrorF("[GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES); + goto failed; + } + + res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected); + + if (!res) + { + ErrorF("[GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n"); + goto failed; + } + + pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo); + + if (!pGesture->device_setting_timer) + { + ErrorF("[GestureEnableEventHandler] Failed to set time for detecting devices !\n"); + goto failed; + } + + 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_KeyPress, NULL); + mieqSetHandler(ET_KeyRelease, NULL); + mieqSetHandler(ET_MTSync, NULL); + + err = GestureFiniEQ(); + + if (ERROR_INVALPTR == err) + { + ErrorF("[GestureDisableEventHandler] EQ is invalid or was freed already !\n"); + } + + GestureRegisterCallbacks(NULL, NULL); + GestureUninstallResourceStateHooks(); + + return err; +} + +static CARD32 +GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg) +{ + InputInfoPtr pInfo = (InputInfoPtr)arg; + GestureDevicePtr pGesture; + int idx; + DeviceIntPtr dev; + + if (!pInfo) + { + ErrorF("[GestureTimerHandler][%s] pInfo is NULL !\n"); + goto failed; + } + + pGesture = pInfo->private; + + idx = 0; + for (dev = inputInfo.pointer; dev; dev = dev->next) + { + if (IsMaster(dev) && IsPointerDevice(dev)) + { + pGesture->master_pointer = dev; + ErrorF("[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("[GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name); + continue; + } + + if (IsPointerDevice(dev)) + { + if (idx >= MAX_MT_DEVICES) + { + ErrorF("[GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n", MAX_MT_DEVICES); + continue; + } + pGesture->mt_devices[idx] = dev; + ErrorF("[GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name); + GesturePalmGetAbsAxisInfo(dev); + idx++; + } + } + + for (dev = inputInfo.keyboard ; dev; dev = dev->next) + { + if (g_pGesture->hwkey_name && !strncmp(dev->name, g_pGesture->hwkey_name, strlen(dev->name))) + { + g_pGesture->hwkey_id = dev->id; + g_pGesture->hwkey_dev = dev; + + ErrorF("[GestureTimerHandler] hwkey_name has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name); + break; + } + else if (!strncmp(dev->name, "tizen_rotary", strlen(dev->name))) + { + g_pGesture->rotary_id = dev->id; + g_pGesture->rotary_dev = dev; + + ErrorF("[GestureTimerHandler] rotary_name has been found. rotary_id=%d (rotary_dev->name:%s)\n", g_pGesture->rotary_id, g_pGesture->rotary_dev->name); + break; + } + else if (!strcasestr(dev->name, "keyboard") && strcasestr(dev->name, "key") && !IsXTestDevice(dev, NULL) && !IsMaster(dev)) + { + g_pGesture->hwkey_id = dev->id; + g_pGesture->hwkey_dev = dev; + + ErrorF("[GestureTimerHandler] hwkey has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name); + break; + } + } + + if (!g_pGesture->hwkey_id) + { + g_pGesture->hwkey_id = inputInfo.keyboard->id; + g_pGesture->hwkey_dev = inputInfo.keyboard; + + ErrorF("[GestureTimerHandler] No hwkey has been found. Back key will go through VCK. hwkey_id=%d (hwkey_dev->name:%s)\n", + g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name); + } + + if (!pGesture->master_pointer || !pGesture->xtest_pointer) + { + ErrorF("[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; + } + + TimerCancel(pGesture->device_setting_timer); + pGesture->device_setting_timer = NULL; + pGesture->num_mt_devices = idx; + + if (!pGesture->num_mt_devices) + { + ErrorF("[GestureTimerHandler] Failed to mt device information !\n"); + TimerCancel(pGesture->device_setting_timer); + pGesture->device_setting_timer = NULL; + pGesture->num_mt_devices = 0; + pGesture->first_fingerid = -1; + return 0; + } + + pGesture->first_fingerid = pGesture->mt_devices[0]->id; + memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices); + pGesture->pRootWin = RootWindow(pGesture->master_pointer); + + if (g_pGesture->palm_misc.enabled) + { + GesturePalmGetScreenInfo(); + } + + g_pGesture->pTempWin = NULL; + g_pGesture->inc_num_pressed = 0; + + if (ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ()) + { + goto failed; + } + + mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent); + mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent); + mieqSetHandler(ET_Motion, GestureHandleMotionEvent); + mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent); + mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent); + + //if ( pGesture->is_active) + mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent); + + return 0; + +failed: + GestureUninstallResourceStateHooks(); + GestureUnsetMaxNumberOfFingers(); + + 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 +GestureGenerateTouchCancelEvent(void) +{ + int i; + Bool canceled_touch_index[MAX_MT_DEVICES] = {FALSE, }; + + if (g_pGesture->mtsync_flag & MTSYNC_FLAG_TOUCH) + { + ErrorF("no Touch(%d)\n", g_pGesture->mtsync_flag); + return; + } + + for (i=0; imt_devices[i]->button->buttonsDown)) continue; + InternalEvent cancel_event; + + cancel_event.touch_cancel_event.header = ET_Internal; + cancel_event.touch_cancel_event.type = ET_TouchCancel; + cancel_event.touch_cancel_event.length = sizeof(TouchCancelEvent); + cancel_event.touch_cancel_event.time = CurrentTime; + cancel_event.touch_cancel_event.deviceid = g_pGesture->mt_devices[i]?g_pGesture->mt_devices[i]->id:0; + + cancel_event.touch_cancel_event.sourceid = g_pGesture->mt_devices[i]?g_pGesture->mt_devices[i]->id:0; + cancel_event.touch_cancel_event.resource = 0; + cancel_event.touch_cancel_event.flags = 0; + + g_pGesture->mt_devices[i]->public.processInputProc(&cancel_event, g_pGesture->mt_devices[i]); + canceled_touch_index[i] = TRUE; + g_pGesture->touch_cancel_status = TRUE; + } + + for (i=0; imt_devices[i]->id; + release_event.device_event.sourceid = g_pGesture->mt_devices[i]->button->sourceid; + release_event.device_event.detail.button = 1; + release_event.device_event.root_x = g_pGesture->last_touches[i].cx; + release_event.device_event.root_y = g_pGesture->last_touches[i].cy; + if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid) + { + memcpy(&release_event_master, &release_event, sizeof(InternalEvent)); + release_event_master.device_event.deviceid = g_pGesture->master_pointer->id; + } + + g_pGesture->mt_devices[i]->public.processInputProc(&release_event, g_pGesture->mt_devices[i]); + if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid) + { + g_pGesture->master_pointer->public.processInputProc(&release_event_master, g_pGesture->master_pointer); + } + g_pGesture->touch_cancel_status = TRUE; + } +} + +static void +GestureDPMSCallback(CallbackListPtr *pcbl, void *unused, void *calldata) +{ + int dpmsLevel = *(int *)calldata; + + if ((DPMSModeOff == dpmsLevel) && (MTSYNC_FLAG_TOUCH & g_pGesture->mtsync_flag)) { + ErrorF("TouchCancel dpmslevel: %d, g_pGesture->mtsync_flag: %d\n", dpmsLevel, g_pGesture->mtsync_flag); + GestureGenerateTouchCancelEvent(); + } +} + +void +GestureEnable(int enable, Bool prop, DeviceIntPtr dev) +{ + if ((!enable) && (g_pGesture->is_active)) + { + g_pGesture->ehtype = PROPAGATE_EVENTS; + mieqSetHandler(ET_MTSync, NULL); + g_pGesture->is_active = 0; + ErrorF("[GestureEnable] Disabled !\n"); + int res = AddCallback (&ClientStateCallback, GestureHandleClientState, NULL); + + if (!res) + { + ErrorF("[GestureEnable] Failed to add callback for client state\n"); + return; + } + } + + else if ((enable) && (!g_pGesture->is_active)) + { + g_pGesture->ehtype = KEEP_EVENTS; + mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent); + g_pGesture->is_active = 1; + ErrorF("[GestureEnable] Enabled !\n"); + + DeleteCallback (&ClientStateCallback, GestureHandleClientState, NULL); + } + + if (!prop) + { + XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE); + } +} + +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("[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("[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("[GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n"); + i--; + while(i >= 0 && tmpEQ[i].event) + { + free(tmpEQ[i].event); + tmpEQ[i].event = NULL; + } + free (tmpEQ); + tmpEQ = NULL; + 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("[GestureEnqueueEvent] Invalid pointer access !\n"); + return ERROR_INVALPTR; + } + + tail = g_pGesture->tailEQ; + + if (tail >= GESTURE_EQ_SIZE) + { + ErrorF("[GestureEnqueueEvent] Gesture EQ is full !\n"); + printk("[GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n"); + GestureEventsFlush(); + return ERROR_EQFULL; + } + + if((g_pGesture->mtsync_flag & MTSYNC_FLAG_ROTARY) || (g_pGesture->mtsync_flag & ~MTSYNC_FLAG_TOUCH)) + { + DetailDebugPrint("[GestureEnqueueEvent] Rotary or other input are coming. Do not push events to queue.\n"); + return ERROR_NONE; + } + + switch (ev->any.type) + { + case ET_ButtonPress: + DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id); + break; + + case ET_ButtonRelease: + DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id); + break; + + case ET_Motion: + DetailDebugPrint("[GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id); + break; + } + + 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("[GestureEventsFlush] Invalid pointer access !\n"); + return ERROR_INVALPTR; + } + + DetailDebugPrint("[GestureEventsFlush]\n"); + + 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) +{ + DetailDebugPrint("[GestureEventsDrop]\n"); + g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ +} + +#ifdef HAVE_PROPERTIES +static void +GestureInitProperty(DeviceIntPtr dev) +{ + int rc; + +#ifdef SUPPORT_ANR_WITH_INPUT_EVENT + prop_anr_in_input_event = MakeAtom(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT, strlen(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT), TRUE); + prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE); +#endif + + 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) +{ + 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); + GestureEnable(data, TRUE, dev); + } + } + return Success; +} +#endif//HAVE_PROPERTIES + +static int +GestureInit(DeviceIntPtr device) +{ +#ifdef HAVE_PROPERTIES + GestureInitProperty(device); + XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL); +#endif + //GestureEnable(1, FALSE, g_pGesture->this_device); + 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 int +GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) +{ + int rc = BadAlloc; + GestureDevicePtr pGesture; + + pGesture = calloc(1, sizeof(GestureDeviceRec)); + + if (!pGesture) + { + pInfo->private = NULL; + //xf86DeleteInput(pInfo, 0); + goto error; + } + + g_pGesture = pGesture; + + pInfo->private = pGesture; + pInfo->flags = 0; + 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(pInfo->options, "Device", "/dev/null"); + pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0); + pGesture->gestureWin = None; + pGesture->lastSelectedWin = None; + pGesture->power_pressed = 1; + pGesture->hwkey_id = 0; + pGesture->hwkey_dev = NULL; + pGesture->num_tap_repeated = 0; + pGesture->mtsync_total_count = 0; + pGesture->hwkey_name = xf86SetStrOption(pInfo->options, "BackHWKeyName", NULL); + pGesture->screen_width = xf86SetIntOption(pInfo->options,"ScreenWidth", 0); + pGesture->screen_height = xf86SetIntOption(pInfo->options,"ScreenHeight", 0); + pGesture->hwkeycode_flick_down = xf86SetIntOption(pInfo->options, "FlickDownKeycode", 0); + pGesture->hwkeycode_flick_up = xf86SetIntOption(pInfo->options, "FlickUpKeycode", 0); + pGesture->flick_press_area = xf86SetIntOption(pInfo->options, "FlickPressArea", 0); + pGesture->flick_press_area_left = xf86SetIntOption(pInfo->options, "FlickPressArea_LEFT", 0); + pGesture->flick_press_area_left_right = xf86SetIntOption(pInfo->options, "FlickPressArea_LEFT_RIGHT", 0); + pGesture->flick_minimum_height = xf86SetIntOption(pInfo->options, "FlickMinimumHeight", 0); + pGesture->shutdown_keycode = xf86SetIntOption(pInfo->options, "ShutdownKeycode", 0); + pGesture->singletap_threshold= xf86SetIntOption(pInfo->options, "SingleTapThresHold", 0); + pGesture->doubletap_threshold= xf86SetIntOption(pInfo->options, "DoubleTapThresHold", 0); + pGesture->tripletap_threshold= xf86SetIntOption(pInfo->options, "TripleTapThresHold", 0); + pGesture->hold_area_threshold = xf86SetRealOption(pInfo->options, "HoldAreaThresHold", 0); + pGesture->hold_move_threshold = xf86SetIntOption(pInfo->options, "HoldMoveThresHold", 0); + pGesture->hold_time_threshold = xf86SetIntOption(pInfo->options, "HoldTimeThresHold", 0); + pGesture->palm_flick_time_threshold = xf86SetIntOption(pInfo->options, "PalmFlickTimeThresHold", 0); + pGesture->palm_flick_max_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMaxTouchMajorThresHold", 0); + pGesture->palm_flick_min_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMinTouchMajorThresHold", 0); + pGesture->activate_flick_down = xf86SetIntOption(pInfo->options, "ActivateFlickDown", 0); + pGesture->activate_flick_up = xf86SetIntOption(pInfo->options, "ActivateFlickUp", 0); + pGesture->activate_flick_right = xf86SetIntOption(pInfo->options, "ActivateFlickRight", 0); + pGesture->factory_cmdname = xf86SetStrOption(pInfo->options, "FactoryCmdName", NULL); + + ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__); + ErrorF("[X11][%s] screen_width=%d, screen_height=%d\n", __FUNCTION__, + pGesture->screen_width, pGesture->screen_height); + ErrorF("[X11][%s] FlickDownKeycode=%d, FlickUpKeycode=%d\n", __FUNCTION__, + pGesture->hwkeycode_flick_down, pGesture->hwkeycode_flick_up); + ErrorF("[X11][%s] flick_press_area=%d, flick_press_area_left: %d, flick_press_area_left_right: %d, flick_minimum_height=%d\n", __FUNCTION__, + pGesture->flick_press_area, pGesture->flick_press_area_left, pGesture->flick_press_area_left_right, pGesture->flick_minimum_height); + ErrorF("[X11][%s] ShutdownKeycode=%d\n", __FUNCTION__, pGesture->shutdown_keycode); + ErrorF("[X11][%s] singletap_threshold=%d, doubletap_threshold=%d\n", __FUNCTION__, pGesture->singletap_threshold, pGesture->doubletap_threshold); + ErrorF("[X11][%s] hold_area_threshold: %f, hold_move_threshold: %d, hold_time_threshold: %d\n", __FUNCTION__, + pGesture->hold_area_threshold, pGesture->hold_move_threshold, pGesture->hold_time_threshold); + ErrorF("[X11][%s] palm_flick_time_threshold: %d, palm_flick_max_tmajor_threshold: %d, palm_flick_min_tmajor_threshold: %d\n", __FUNCTION__, + pGesture->palm_flick_time_threshold, pGesture->palm_flick_max_tmajor_threshold, pGesture->palm_flick_min_tmajor_threshold); + ErrorF("[X11][%s] activate_flick_down=%d, activate_flick_up=%d, activate_flick_right=%d\n", __FUNCTION__, + pGesture->activate_flick_down, pGesture->activate_flick_up, pGesture->activate_flick_right); + ErrorF("[X11][%s] factory cmd name: %s\n", __FUNCTION__, pGesture->factory_cmdname); + ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__); + + if (pGesture->hwkey_name) + { + ErrorF("[X11][%s] hwkey_name=%s\n", __FUNCTION__, pGesture->hwkey_name); + } + + pGesture->mtsync_flag = 0x00; + g_pGesture->grabMask = g_pGesture->eventMask = 0; + + xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device); + + /* process generic options */ + xf86CollectInputOptions(pInfo, NULL); + xf86ProcessCommonOptions(pInfo, pInfo->options); + + pInfo->fd = -1; + + g_pGesture->touch_cancel_status = FALSE; + + return Success; + +error: + if (pInfo->fd >= 0) + close(pInfo->fd); + return rc; +} + +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; + if (!AddCallback(&DPMSCallback, GestureDPMSCallback, NULL)) + ErrorF("[Gesture]Failed to Add DPMS CallBack\n"); + break; + + case DEVICE_OFF: +device_off: + GestureDisableEventHandler(); + DeleteCallback(&DPMSCallback, GestureDPMSCallback, NULL); + 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/wearable/src/gesture.h old mode 100755 new mode 100644 similarity index 69% rename from src/gesture.h rename to wearable/src/gesture.h index 8f7bed0..e5c59ae --- a/src/gesture.h +++ b/wearable/src/gesture.h @@ -41,12 +41,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define HAVE_PROPERTIES 1 #endif +/** + * If there's touch event in pointed window and there's no reponse, we just assume that client looks like deadlock. + * In this case, we will make a popup window and terminate application. + * To support this feature, we use SUPPORT_ANR_WITH_INPUT_EVENT flag. + */ +#define SUPPORT_ANR_WITH_INPUT_EVENT + +#define GESTURE_RECOGNIZER_ONOFF "GESTURE_RECOGNIZER_ONOFF" +#define GESTURE_PALM_REJECTION_MODE "GESTURE_PALM_REJECTION_MODE" +#define CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT "_CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT_" +#define ANR_EVENT_WINDOW "_ANR_EVENT_WINDOW_" + + #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 MAX_MT_DEVICES 2 #define GESTURE_EQ_SIZE 256 #define GESTURE_RECOGNIZER_ONOFF "GESTURE_RECOGNIZER_ONOFF" @@ -68,9 +81,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #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 +//palm +#define PALM_HORIZ_ARRAY_COUNT 3 +#define PALM_VERTI_ARRAY_COUNT 4 typedef int XFixed; typedef double XDouble; @@ -93,54 +106,51 @@ enum 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 PINCHROTATION_TIME_THRESHOLD 500//ms -#define PINCHROTATION_INIT_DIST_THRESHOLD 25.0f -#define PINCHROTATION_INIT_ANGLE_THRESHOLD 0.2f -#define PINCHROTATION_DIST_THRESHOLD 25.0f -#define PINCHROTATION_ANGLE_THRESHOLD 0.2f - -#define HOLD_AREA_THRESHOLD 2500//=50pixel * 50pixel -#define HOLD_MOVE_THRESHOLD 10//pixel -#define HOLD_TIME_THRESHOLD 500//ms +enum +{ + FLICK_POINT_NONE = 0, + FLICK_POINT_UP, + FLICK_POINT_RIGHT, + FLICK_POINT_DOWN, + FLICK_POINT_LEFT, + FLICK_POINT_MAX +}; #define TAP_AREA_THRESHOLD 10000//= 100pixel * 100pixel -#define TAP_MOVE_THRESHOLD 70//pixel -#define SGL_TAP_TIME_THRESHOLD 200//ms +#define TAP_MOVE_THRESHOLD 35//pixel +#define SGL_TAP_TIME_THRESHOLD 300//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 MAX_TAP_REPEATS 3 #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 +#define FLICK_FALSE_Y_DIFF_COUNT 7 +#define FLICK_FALSE_X_DIFF_COUNT 5 + +#define PALM_FLICK_DETECT_TIMEOUT 1000//ms +#define PALM_FLICK_MAX_TOUCH_MAJOR 130 -#define RAD_90DEG M_PI_2 -#define RAD_180DEG M_PI -#define RAD_270DEG (M_PI_2 * 3) -#define RAD_360DEG (M_PI * 2) -#define rad2degree(r) ((r) * 180/M_PI) +#define AXIS_LABEL_PROP_ABS_MT_TRACKING_ID "Abs MT Tracking ID" +#define AXIS_LABEL_PROP_ABS_MT_SLOT "Abs MT Slot" +#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major" +#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor" +#define AXIS_LABEL_PROP_ABS_MT_PALM "Abs MT Palm/MT Sumsize" typedef enum _MTSyncType { MTOUCH_FRAME_SYNC_END, - MTOUCH_FRAME_SYNC_BEGIN + MTOUCH_FRAME_SYNC_BEGIN, + MTOUCH_FRAME_SYNC_UPDATE, + ROTARY_FRAME_SYNC_END, + ROTARY_FRAME_SYNC_BEGIN } MTSyncType; typedef enum _EventHandleType { - KEEP_EVENTS, PROPAGATE_EVENTS, + KEEP_EVENTS, IGNORE_EVENTS } EventHandleType; @@ -163,12 +173,12 @@ enum EventType /* ... */ + ET_TouchCancel = 31, ET_MTSync = 0x7E, ET_Internal = 0xFF /* First byte */ }; -struct _DeviceEvent -{ +struct _DeviceEvent { unsigned char header; /**< Always ET_Internal */ enum EventType type; /**< One of EventType */ int length; /**< Length in bytes */ @@ -176,19 +186,20 @@ struct _DeviceEvent int deviceid; /**< Device to post this event for */ int sourceid; /**< The physical source device */ union { - uint32_t button; /**< Button number */ + uint32_t button; /**< Button number (also used in pointer emulating + touch events) */ uint32_t key; /**< Key code */ } detail; + uint32_t touchid; /**< Touch ID (client_id) */ 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 */ + 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 */ + uint8_t mask[(MAX_VALUATORS + 7) / 8];/**< Valuator mask */ + uint8_t mode[(MAX_VALUATORS + 7) / 8];/**< Valuator mode (Abs or Rel)*/ + double data[MAX_VALUATORS]; /**< Valuator data */ } valuators; struct { uint32_t base; /**< XKB base modifiers */ @@ -202,9 +213,10 @@ struct _DeviceEvent uint8_t locked; /**< XKB locked group */ uint8_t effective;/**< XKB effective group */ } group; - Window root; /**< Root window of the event */ + Window root; /**< Root window of the event */ int corestate; /**< Core key/button state BEFORE the event */ int key_repeat; /**< Internally-generated key repeat event */ + uint32_t flags; /**< Flags to be copied into the generated event */ }; typedef struct _AnyEvent AnyEvent; @@ -220,6 +232,20 @@ struct _AnyEvent int y; }; +typedef struct _TouchCancelEvent TouchCancelEvent; +struct _TouchCancelEvent { + unsigned char header; /**< Always ET_Internal */ + enum EventType type; /**< ET_TouchOwnership */ + int length; /**< Length in bytes */ + Time time; /**< Time in ms */ + int deviceid; /**< Device to post this event for */ + int sourceid; /**< The physical source device */ + uint32_t resource; /**< Provoking grab or event selection */ + uint32_t flags; /**< Flags to be copied into the generated event */ +}; + + + union _InternalEvent { struct { unsigned char header; /**< Always ET_Internal */ @@ -229,6 +255,7 @@ union _InternalEvent { } any; AnyEvent any_event; DeviceEvent device_event; + TouchCancelEvent touch_cancel_event; }; #define wUseDefault(w,field,def) ((w)->optional ? (w)->optional->field : def) @@ -333,6 +360,18 @@ enum #define GESTURE_FILTER_MASK_ALL 0x3f//(FlickFilterMask | PanFilterMask | PinchRotationFilterMask | TapFilterMask |TapNHoldFilterMask | HoldFilterMask) +#define WFlickFilterMask 0x01//(1 << 0) +#define WTapFilterMask 0x02//(1 << 1) +#define WHoldFilterMask 0x04//(1 << 2) +#define WPalmFlickFilterMask 0x08//(1 << 3) + +#define GESTURE_WATCH_FILTER_MASK_ALL 0x07//(WFlickFilterMask | WTapFilterMask | WHoldFilterMask ) + +#define MTSYNC_FLAG_TOUCH 0x01//(1 << 0) +#define MTSYNC_FLAG_ROTARY 0x02//(1 << 1) + +#define PALM_HOLD_TIME_THRESHOLD 150 + typedef struct _tagTouchStatus { int status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING @@ -349,6 +388,24 @@ typedef struct _tagTouchStatus Time rtime; //current/previous release time } TouchStatus; +typedef struct _tagCurrentTouchStatus +{ + int status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING + int cx; //current x + int cy; //current y +} CurTouchStatus; + +typedef struct _tagPalmDrvStatus +{ + int enabled; + int scrn_width; + int scrn_height; + unsigned int half_scrn_area_size; + int horiz_coord[PALM_HORIZ_ARRAY_COUNT]; + int verti_coord[PALM_VERTI_ARRAY_COUNT]; +} PalmMiscInfo, *PalmMiscInfoPtr; + + typedef struct _GestureDeviceRec { char *device; @@ -356,6 +413,49 @@ typedef struct _GestureDeviceRec OsTimerPtr device_setting_timer; int is_active; + int power_pressed; + int flick_pressed_point; + int flick_direction; + + int hwkeycode_flick_down; + int hwkeycode_flick_up; + int shutdown_keycode; + int flick_press_area; + int flick_press_area_left; + int flick_press_area_left_right; + int flick_minimum_height; + int activate_flick_down;//up to down + int activate_flick_up;//down to up + int activate_flick_right;//left to right + int screen_width; + int screen_height; + + int singletap_threshold; + int doubletap_threshold; + int tripletap_threshold; + + int num_tap_repeated; + + double hold_area_threshold; + int hold_move_threshold; + int hold_time_threshold; + + int palm_flick_time_threshold; + int palm_flick_max_tmajor_threshold; + int palm_flick_min_tmajor_threshold; + char *factory_cmdname; + + int max_mt_tmajor[MAX_MT_DEVICES]; + + int hwkey_id; + char *hwkey_name; + DeviceIntPtr hwkey_dev; + int rotary_id; + DeviceIntPtr rotary_dev; + unsigned char mtsync_flag; + int mtsync_total_count; + + DeviceIntPtr power_device; WindowPtr pRootWin; Window gestureWin; @@ -364,12 +464,29 @@ typedef struct _GestureDeviceRec Mask grabMask; Mask eventMask; GestureGrabEventPtr GrabEvents; + Mask lastSelectedMask; + Window lastSelectedWin; EventHandleType ehtype; IEventPtr EQ; int headEQ; int tailEQ; + int hold_detector_activate; + int has_hold_grabmask; + pixman_region16_t chold_area; + CurTouchStatus cts[MAX_MT_DEVICES]; + CurTouchStatus last_touches[MAX_MT_DEVICES]; + Bool touch_cancel_status; + Bool hold_detected; + + PalmMiscInfo palm_misc; + int tmajor_idx; + int tminor_idx; + int tpalm_idx; + int mt_px_idx; + int mt_py_idx; + pixman_region16_t area; pixman_region16_t finger_rects[MAX_MT_DEVICES]; @@ -388,6 +505,8 @@ typedef struct _GestureDeviceRec DeviceIntPtr mt_devices[MAX_MT_DEVICES]; DeviceIntPtr master_pointer; DeviceIntPtr xtest_pointer; + + WindowPtr anr_window; } GestureDeviceRec, *GestureDevicePtr ; #endif//_GESTURE_H_ diff --git a/wearable/xorg-gesture.pc.in b/wearable/xorg-gesture.pc.in new file mode 100644 index 0000000..320b0be --- /dev/null +++ b/wearable/xorg-gesture.pc.in @@ -0,0 +1,6 @@ +sdkdir=@sdkdir@ + +Name: xorg-evdev +Description: X.Org gesture input driver. +Version: @PACKAGE_VERSION@ +Cflags: -I${sdkdir} -- 2.7.4