summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Willich <sabotageandi@gmail.com>2011-08-06 22:56:54 +0200
committerAndreas Willich <sabotageandi@gmail.com>2011-08-06 22:56:54 +0200
commit05e2888845ef46a6851eeb8817811e7f2a5172f1 (patch)
tree01f71afdf31b80285ceaec7fe6dbb4f05a430ce5
downloadsabotageandi-05e2888845ef46a6851eeb8817811e7f2a5172f1.tar.gz
sabotageandi-05e2888845ef46a6851eeb8817811e7f2a5172f1.tar.bz2
sabotageandi-05e2888845ef46a6851eeb8817811e7f2a5172f1.zip
ebuild push
-rw-r--r--dev-libs/glib/Manifest31
-rw-r--r--dev-libs/glib/files/glib-1.2.10-automake.patch29
-rw-r--r--dev-libs/glib/files/glib-1.2.10-configure-LANG.patch44
-rw-r--r--dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch41
-rw-r--r--dev-libs/glib/files/glib-1.2.10-m4.patch9
-rw-r--r--dev-libs/glib/files/glib-2.10.3-ia64-atomic-ops.patch39
-rw-r--r--dev-libs/glib/files/glib-2.12.12-fbsd.patch21
-rw-r--r--dev-libs/glib/files/glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch20
-rw-r--r--dev-libs/glib/files/glib-2.24-assert-test-failure.patch19
-rw-r--r--dev-libs/glib/files/glib-2.24-punt-python-check.patch20
-rw-r--r--dev-libs/glib/files/glib-2.25-punt-python-check.patch20
-rw-r--r--dev-libs/glib/files/glib-2.25-skip-tests-with-dbus-keyring.patch22
-rw-r--r--dev-libs/glib/files/glib-2.26.0-disable-locale-sensitive-test.patch50
-rw-r--r--dev-libs/glib/files/glib-2.26.0-disable-volumemonitor-broken-test.patch43
-rw-r--r--dev-libs/glib/files/glib-2.26.1-deprecation-tests.patch43
-rw-r--r--dev-libs/glib/files/glib-2.26.1-gatomic-header.patch11
-rw-r--r--dev-libs/glib/files/glib-2.26.1-gdatetime-test.patch21
-rw-r--r--dev-libs/glib/files/glib-2.26.1-gdbus-flushes.patch64
-rw-r--r--dev-libs/glib/files/glib-2.26.1-gsettings-read.patch25
-rw-r--r--dev-libs/glib/files/glib-2.26.1-gsettings-rules.patch33
-rw-r--r--dev-libs/glib/files/glib-2.26.1-locked-message.patch68
-rw-r--r--dev-libs/glib/files/glib-2.28.2-gio_launch_handler.patch234
-rw-r--r--dev-libs/glib/glib-2.28.5-r1.ebuild176
-rw-r--r--dev-libs/glib/glib-2.28.6-r1.ebuild176
-rw-r--r--dev-libs/glib/glib-2.28.7-r1.ebuild176
-rw-r--r--dev-libs/glib/glib-2.28.8-r1.ebuild203
-rw-r--r--dev-libs/glib/metadata.xml10
-rw-r--r--dev-util/editje/Manifest1
-rw-r--r--dev-util/editje/editje-9999.ebuild14
-rw-r--r--net-wireless/rt3572usb/Manifest7
-rw-r--r--net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-Makefile.patch11
-rw-r--r--net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-config.mk.patch15
-rw-r--r--net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-nodebug.patch11
-rw-r--r--net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rt_linux.h.patch13
-rw-r--r--net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch19
-rw-r--r--net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild74
-rw-r--r--x11-apps/ccv-bin/Manifest3
-rw-r--r--x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild54
-rw-r--r--x11-apps/ginn/Manifest2
-rw-r--r--x11-apps/ginn/ginn-0.2.4.ebuild27
-rw-r--r--x11-base/xorg-server/Manifest25
-rw-r--r--x11-base/xorg-server/files/diff26
-rw-r--r--x11-base/xorg-server/files/xdm-setup.initd-114
-rw-r--r--x11-base/xorg-server/files/xdm.confd-316
-rwxr-xr-xx11-base/xorg-server/files/xdm.initd-3213
-rw-r--r--x11-base/xorg-server/files/xorg-server-1.10.2-xi2.patch4569
-rw-r--r--x11-base/xorg-server/files/xorg-server-1.9-nouveau-default.patch30
-rw-r--r--x11-base/xorg-server/files/xorg-server-disable-acpi.patch31
-rw-r--r--x11-base/xorg-server/files/xorg-server-gestures-extension.patch1488
-rw-r--r--x11-base/xorg-server/files/xorg-server-xf86CoordinatesToWindow.patch97
-rw-r--r--x11-base/xorg-server/files/xorg-server-xi2.patch4568
-rw-r--r--x11-base/xorg-server/files/xorg-sets.conf6
-rw-r--r--x11-base/xorg-server/metadata.xml12
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.0.901-r1.ebuild254
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.0.902-r1.ebuild254
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild254
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.1.901-r1.ebuild241
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.1.ebuild250
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild240
-rw-r--r--x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild249
-rw-r--r--x11-drivers/xf86-input-evdev/Manifest4
-rw-r--r--x11-drivers/xf86-input-evdev/files/xf86-input-evdev-gestures.patch664
-rw-r--r--x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch1678
-rw-r--r--x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0-r1.ebuild33
-rw-r--r--x11-libs/bamf/Manifest2
-rw-r--r--x11-libs/bamf/bamf-0.2.70.ebuild40
-rw-r--r--x11-libs/libXi/Manifest5
-rw-r--r--x11-libs/libXi/files/libXi-xi2.1.patch355
-rw-r--r--x11-libs/libXi/libXi-1.4.2-r1.ebuild42
-rw-r--r--x11-libs/libXi/libXi-1.4.3.ebuild44
-rw-r--r--x11-libs/mtdev/Manifest2
-rw-r--r--x11-libs/mtdev/mtdev-1.1.0.ebuild21
-rw-r--r--x11-libs/utouch-evemu/Manifest2
-rw-r--r--x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild21
-rw-r--r--x11-libs/utouch-frame/Manifest2
-rw-r--r--x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild26
-rw-r--r--x11-libs/utouch-geis/Manifest6
-rw-r--r--x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild26
-rw-r--r--x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild26
-rw-r--r--x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild26
-rw-r--r--x11-libs/utouch-grail/Manifest2
-rw-r--r--x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild28
-rw-r--r--x11-plugins/e_modules-itask/Manifest3
-rw-r--r--x11-plugins/e_modules-itask/e_modules-itask-9999.ebuild16
-rw-r--r--x11-plugins/e_modules-itask/metadata.xml8
-rw-r--r--x11-proto/inputproto/Manifest6
-rw-r--r--x11-proto/inputproto/files/inputproto-2.0.1-xi2.1.patch943
-rw-r--r--x11-proto/inputproto/files/inputproto-2.0.2-xi2.1.patch191
-rw-r--r--x11-proto/inputproto/inputproto-2.0.1-r1.ebuild30
-rw-r--r--x11-proto/inputproto/inputproto-2.0.2-r1.ebuild27
90 files changed, 19015 insertions, 0 deletions
diff --git a/dev-libs/glib/Manifest b/dev-libs/glib/Manifest
new file mode 100644
index 0000000..1cb13bf
--- /dev/null
+++ b/dev-libs/glib/Manifest
@@ -0,0 +1,31 @@
+AUX glib-1.2.10-automake.patch 827 RMD160 3b1485f89a157b60f31f5ae8ffe2333ab842d217 SHA1 cd40e4dc579190a89e09fad9ac7b209f24b231b3 SHA256 db6d22caf4054c09467b50b6d85566eec7479a29169460950e423c083332ef67
+AUX glib-1.2.10-configure-LANG.patch 1464 RMD160 91481ba6b3f7a1d6e22a4ab7003fcee17450f3c1 SHA1 d98cc2f4ac6cc4aae55270ad0e5705af4de9b3ad SHA256 32377819896297caf9628f382c7bba09ee0a049bd977e9ea927314c0c2e669b4
+AUX glib-1.2.10-gcc34-fix.patch 2008 RMD160 7e92b8842a8232cada12453d7f5e5a587a2bf496 SHA1 cb9c6e2f5320590713b3fba61f1d984e569d5d08 SHA256 848620bc200c2a42d726744fe6c36e20a396624e82b0c742b726dd72287e6cdd
+AUX glib-1.2.10-m4.patch 225 RMD160 65218d0099218a1008827c1364b6e51c073d236b SHA1 e9198bde79320d76ad942d42a0292acb5d216a86 SHA256 c470b3ecc3b8fd6a2d52df816a1c4ccb3ad2d6048e37894f415c8ea9c7925b68
+AUX glib-2.10.3-ia64-atomic-ops.patch 1058 RMD160 066e63a99739dc412fbed7f773118323f53ea774 SHA1 13c22e2f75a77e9e0546e495fd28015ddcb8bade SHA256 ad9cad6793626b4e36a59aa6cb839607847aa57ebc37592fd1e273ccd23a53c8
+AUX glib-2.12.12-fbsd.patch 668 RMD160 d8bf399b7e0b417c4622b278282086418c1d3363 SHA1 b7a0f4d67083f2c9b4bbecd84a6d597dd0f0f9ed SHA256 23b0dc406d3d45fe125268b731af67147e83f6e38a63c7892828bdbfe1c31e8d
+AUX glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch 616 RMD160 dd06abe9298d6e3e4d3eda0d5d155f1545dfd1aa SHA1 92164aa1b29f49cf62fc366231f2046b8b3def52 SHA256 e64ad4fbd67f142f5a19b29eab323bf18856309ed064e7a9f838b6c1c38a8adb
+AUX glib-2.24-assert-test-failure.patch 724 RMD160 011da2b341281d14741e715eddd401968464608d SHA1 76149f52677a337569dbab1b5f664c8fc16d44ff SHA256 1e3d290455d6bbc3a4f69d7b8abdeb559a01c8cd30dc311641e1cb0b7f84c6af
+AUX glib-2.24-punt-python-check.patch 541 RMD160 8783f765b97814bc95a6143b75f317dbbdd8ba0c SHA1 dbaf420d3b8acd7691bc677f1fcc6e2fca04ed54 SHA256 0bdcc11d1434f695a5b5f6ec4c54ab7fa5a9f8a5c22d71b94f97378e92aaff84
+AUX glib-2.25-punt-python-check.patch 541 RMD160 93fe958f07c2e03abb3abf95eaa0273b0822d874 SHA1 a9b0b50847f00773254b55238785f65f516ff4ad SHA256 eea2b3a2692b93c98ff06b26b784a264391bc61f8434d101c30cb14802234a3e
+AUX glib-2.25-skip-tests-with-dbus-keyring.patch 933 RMD160 20eb4c83cffca42aca845dc74cc2a67803c5df6c SHA1 f845fa3cc991330aa3dcdfbec8426501261a8c70 SHA256 930cdfe8f3b46c20826057b5771f953172c97fed8b3e509f4fde13094ff1c251
+AUX glib-2.26.0-disable-locale-sensitive-test.patch 1256 RMD160 2754468a420189f6e8d7ea215b53069a21c14dd0 SHA1 f3008b5db6774b6c9d5a04a4bdbed4a9f553a63e SHA256 f0db01f4198ca3688ece382819d320f39d6b722381e28611df59c880f4d18e02
+AUX glib-2.26.0-disable-volumemonitor-broken-test.patch 1181 RMD160 c99e2969a3cab244dc39c81f2dd32bc42677c6e8 SHA1 cc30a7223108fb7fbe1a1c063d9546ffc457b94f SHA256 aa3075f22a9125551fbce6909645fb6b5c5b74282e6fed2ee1d06853b15437d3
+AUX glib-2.26.1-deprecation-tests.patch 1396 RMD160 2cda39fa239d9eeb83d179260cfda8ec54b68cab SHA1 0e1eda5351e47feaf249c98aa6988f0608e80a17 SHA256 9d95d7f361900116821f79e2122df4a794af648c0ff9661a937805a5aced2f7a
+AUX glib-2.26.1-gatomic-header.patch 269 RMD160 668ded743e0004b671e79d1ee5918c42cc78163d SHA1 db7808b0dfc39d8b415dce071b6a1805cad1a850 SHA256 81046ce8bdb7b1c863aba9cb457443e92b792807b304d0ee8e7dfd2b6fb7b122
+AUX glib-2.26.1-gdatetime-test.patch 760 RMD160 05b81043d5bfb0ff54806f4ac96ec135cf7f2898 SHA1 461d462f2d4509d07a70913f1268bd49847608ea SHA256 5f3569050c1fffbb5f312d0a00db9a43ff80446f510ab5d5116220406dfc61e7
+AUX glib-2.26.1-gdbus-flushes.patch 2270 RMD160 1bb9668f0df08ce54c16cf476102ca099754af96 SHA1 191e2034fa5eb2097657a82af92680c50509b1a9 SHA256 1adee16f5013695aaab38b8a9130c3ac2f3b8b802405cfa3c7d2ed4767873a07
+AUX glib-2.26.1-gsettings-read.patch 784 RMD160 1fa2eb0d8cf57e1724f7ec8738d3bf3606a3b40e SHA1 fe040110bdfdd789a60338edea9091e05f33e7ed SHA256 a43f54e7384c4233026257cd2048c5ad4e470949ad59aad57432f0b9e1a3d49f
+AUX glib-2.26.1-gsettings-rules.patch 1414 RMD160 8593654837d8cdd4f01990fdba9ada3c2d7e5c7c SHA1 ec1a9fac96b4e05cd02d2a9ad51a6198af2d8b16 SHA256 9f8d431cd0c7f1ab7559089500baabe275fee85f3b86b0645aeef1b0e913fb74
+AUX glib-2.26.1-locked-message.patch 2582 RMD160 3fa459353d46c0aa4add9beccf0737d684b91bc1 SHA1 4e3c9449ccf6ce9d0beb45abffea1742323ff846 SHA256 606e0c52b51343929b3f1f8b15b83321a7b52d31cf2be1325f11eaff7545f110
+AUX glib-2.28.2-gio_launch_handler.patch 9004 RMD160 2eced57e3144b344ad242700b2097687ea577aa2 SHA1 f88b53b2631e0a1c24858813720d62867627545e SHA256 d5e450c02e703c2f0792d9f4e41099623eac601cb58bc078351b2eea9760cbb8
+DIST glib-2.28.5.tar.bz2 6943896 RMD160 939aea42ea77d173712135ffcbcd10e3d01ecd29 SHA1 6cfc1a4e5ed069f0282b90de7635a5704cf7c04c SHA256 8eb4b56b228c6d0bf5021dd23db5b0084d80cc6d8d89d7863073c2da575ec22a
+DIST glib-2.28.6.tar.bz2 6955725 RMD160 5858c29829352c0c59fe12dbd6dceba81aabe5f6 SHA1 51996339c823cf36ba28c774c4afad933d5f5744 SHA256 557fb7c39d21b9359fbac51fd6b0b883bc97a2561c0166eef993a4078312f578
+DIST glib-2.28.7.tar.bz2 6972304 RMD160 1fbb64463d89478f0e7b4c4c8818ee6644c17751 SHA1 82ea79fc2c73df29da1c6d33e0fa027e6c77ec68 SHA256 0e1b3816a8934371d4ea2313dfbe25d10d16c950f8d02e0a7879ae10d91b1631
+DIST glib-2.28.8.tar.bz2 7017806 RMD160 f087a71445eb40fae5eab45a14cb74d4e239d5e6 SHA1 20cd63705a8805260da0320c65b979233f2e3c18 SHA256 222f3055d6c413417b50901008c654865e5a311c73f0ae918b0a9978d1f9466f
+DIST pkg-config-0.26.tar.gz 396399 RMD160 face3d16ec338b9b1ab41d56d6e4d1a5624b52d0 SHA1 fd71a70b023b9087c8a7bb76a0dc135a61059652 SHA256 94c1936a797c930fb3e4e5a154165b6268caba22b32d24083dd4c492a533c8af
+EBUILD glib-2.28.5-r1.ebuild 5540 RMD160 4c9534e9eaf1c1f57932ba6e0428e06e35e0b3f8 SHA1 958eb504d211e6257ab4377dc53c61a114dfc507 SHA256 e8e124098994e9274dcef09c93503bceb155d6fbd85c3db656071f3d366562c3
+EBUILD glib-2.28.6-r1.ebuild 5540 RMD160 81f16ac3b28fb6338d0356746507b2d050030bf9 SHA1 3eaff45d064d3a360e2dd9f3996a9f0d01f37df0 SHA256 27b8febd86b13d95f06d09719de6afb58ee1187ca21cc650ab8ba9a5d9f10a21
+EBUILD glib-2.28.7-r1.ebuild 5540 RMD160 81f16ac3b28fb6338d0356746507b2d050030bf9 SHA1 3eaff45d064d3a360e2dd9f3996a9f0d01f37df0 SHA256 27b8febd86b13d95f06d09719de6afb58ee1187ca21cc650ab8ba9a5d9f10a21
+EBUILD glib-2.28.8-r1.ebuild 7100 RMD160 435ff1dc2be2d3386206b693eb0d023955d95e24 SHA1 820dc04645471d9b08a196bb95c731e01e454d8b SHA256 04331159cbbfca79f1ef7ec5dabf757e96e093ac8df953dc5449012c2e9b6986
+MISC metadata.xml 348 RMD160 38bf96fa8c2dd45bc6bc756581391eefe35ce09f SHA1 5af15631fbbecac1dbaa98a6bd9eed791864c7c8 SHA256 ef2043aabcb66d98c534d509c23d4442b82fb8052bd2e88bcbfcd155dc26ed29
diff --git a/dev-libs/glib/files/glib-1.2.10-automake.patch b/dev-libs/glib/files/glib-1.2.10-automake.patch
new file mode 100644
index 0000000..c4f8fd3
--- /dev/null
+++ b/dev-libs/glib/files/glib-1.2.10-automake.patch
@@ -0,0 +1,29 @@
+fix errors with newer automake:
+
+gmodule/Makefile.am:44: testgmodule_LDFLAGS must be set with `=' before using `+='
+
+Makefile.am:73: BUILT_SOURCES multiply defined in condition TRUE ...
+Makefile.am:11: ... `BUILT_SOURCES' previously defined here
+
+--- Makefile.am
++++ Makefile.am
+@@ -70,7 +70,7 @@
+
+ CONFIGURE_DEPENDENCIES = acglib.m4
+
+-BUILT_SOURCES = stamp-gc-h #note: not glibconfig.h
++BUILT_SOURCES += stamp-gc-h #note: not glibconfig.h
+ glibconfig.h: stamp-gc-h
+ @:
+ stamp-gc-h: config.status
+--- gmodule/Makefile.am
++++ gmodule/Makefile.am
+@@ -41,7 +41,7 @@
+ libgplugin_b_la_LIBADD = @G_MODULE_LIBS@ $(libglib)
+
+ noinst_PROGRAMS = testgmodule
+-testgmodule_LDFLAGS += @G_MODULE_LDFLAGS@
++testgmodule_LDFLAGS = @G_MODULE_LDFLAGS@
+ testgmodule_LDADD = libgmodule.la $(libglib) @G_MODULE_LIBS@
+
+ .PHONY: files release
diff --git a/dev-libs/glib/files/glib-1.2.10-configure-LANG.patch b/dev-libs/glib/files/glib-1.2.10-configure-LANG.patch
new file mode 100644
index 0000000..b5e9e82
--- /dev/null
+++ b/dev-libs/glib/files/glib-1.2.10-configure-LANG.patch
@@ -0,0 +1,44 @@
+The LANG vars aren't reset early enough so when sed tries to use [a-zA-Z] in
+option parsing, it may break.
+
+http://bugs.gentoo.org/133679
+
+--- configure
++++ configure
+@@ -54,6 +54,19 @@
+ infodir='${prefix}/info'
+ mandir='${prefix}/man'
+
++# NLS nuisances.
++for as_var in \
++ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
++ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
++ LC_TELEPHONE LC_TIME
++do
++ if (set +x; test -z "`(eval $as_var=C; export $as_var) 2>&1`"); then
++ eval $as_var=C; export $as_var
++ else
++ unset $as_var
++ fi
++done
++
+ # Initialize some other variables.
+ subdirs=
+ MFLAGS= MAKEFLAGS=
+@@ -452,16 +463,6 @@
+ esac
+ done
+
+-# NLS nuisances.
+-# Only set these to C if already set. These must not be set unconditionally
+-# because not all systems understand e.g. LANG=C (notably SCO).
+-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+-# Non-C LC_CTYPE values break the ctype check.
+-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+-
+ # confdefs.h avoids OS command line length limits that DEFS can exceed.
+ rm -rf conftest* confdefs.h
+ # AIX cpp loses on an empty file, so make sure it contains at least a newline.
diff --git a/dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch b/dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch
new file mode 100644
index 0000000..1b89648
--- /dev/null
+++ b/dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch
@@ -0,0 +1,41 @@
+--- glib-1.2.10/gstrfuncs.c.orig 2001-02-27 07:00:22.000000000 +0100
++++ glib-1.2.10/gstrfuncs.c 2004-03-01 13:19:49.531603760 +0100
+@@ -867,7 +867,7 @@
+ /* beware of positional parameters
+ */
+ case '$':
+- g_warning (G_GNUC_PRETTY_FUNCTION
++ g_warning ("%s%s", G_GNUC_PRETTY_FUNCTION,
+ "(): unable to handle positional parameters (%%n$)");
+ len += 1024; /* try adding some safety padding */
+ break;
+@@ -1034,7 +1034,7 @@
+ /* n . dddddddddddddddddddddddd E +- eeee */
+ conv_len += 1 + 1 + MAX (24, spec.precision) + 1 + 1 + 4;
+ if (spec.mod_extra_long)
+- g_warning (G_GNUC_PRETTY_FUNCTION
++ g_warning ("%s%s", G_GNUC_PRETTY_FUNCTION,
+ "(): unable to handle long double, collecting double only");
+ #ifdef HAVE_LONG_DOUBLE
+ #error need to implement special handling for long double
+@@ -1077,7 +1077,7 @@
+ conv_done = TRUE;
+ if (spec.mod_long)
+ {
+- g_warning (G_GNUC_PRETTY_FUNCTION
++ g_warning ("%s%s", G_GNUC_PRETTY_FUNCTION,
+ "(): unable to handle wide char strings");
+ len += 1024; /* try adding some safety padding */
+ }
+@@ -1108,9 +1108,8 @@
+ conv_len += format - spec_start;
+ break;
+ default:
+- g_warning (G_GNUC_PRETTY_FUNCTION
+- "(): unable to handle `%c' while parsing format",
+- c);
++ g_warning ("%s(): unable to handle `%c' while parsing format",
++ G_GNUC_PRETTY_FUNCTION, c);
+ break;
+ }
+ conv_done |= conv_len > 0;
diff --git a/dev-libs/glib/files/glib-1.2.10-m4.patch b/dev-libs/glib/files/glib-1.2.10-m4.patch
new file mode 100644
index 0000000..f57ecf7
--- /dev/null
+++ b/dev-libs/glib/files/glib-1.2.10-m4.patch
@@ -0,0 +1,9 @@
+Fix aclocal warning:
+/usr/share/aclocal/glib.m4:8: warning: underquoted definition of AM_PATH_GLIB
+--- glib-1.2.10/glib.m4
++++ glib-1.2.10/glib.m4
+@@ -7,3 +7,3 @@
+ dnl
+-AC_DEFUN(AM_PATH_GLIB,
++AC_DEFUN([AM_PATH_GLIB],
+ [dnl
diff --git a/dev-libs/glib/files/glib-2.10.3-ia64-atomic-ops.patch b/dev-libs/glib/files/glib-2.10.3-ia64-atomic-ops.patch
new file mode 100644
index 0000000..0859e33
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.10.3-ia64-atomic-ops.patch
@@ -0,0 +1,39 @@
+From Debian, this one is needed for gcc < 4.1...
+
+--- glib-2.10.0/glib/gatomic.c 2006-02-24 14:02:51.000000000 +0000
++++ glib-2.10.0/glib/gatomic.c 2006-03-06 18:12:06.000000000 +0000
+@@ -414,14 +414,14 @@
+ g_atomic_int_exchange_and_add (volatile gint *atomic,
+ gint val)
+ {
+- return __sync_fetch_and_add (atomic, val);
++ return __sync_fetch_and_add_si (atomic, val);
+ }
+
+ void
+ g_atomic_int_add (volatile gint *atomic,
+ gint val)
+ {
+- __sync_fetch_and_add (atomic, val);
++ __sync_fetch_and_add_si (atomic, val);
+ }
+
+ gboolean
+@@ -429,7 +429,7 @@
+ gint oldval,
+ gint newval)
+ {
+- return __sync_bool_compare_and_swap (atomic, oldval, newval);
++ return __sync_bool_compare_and_swap_si (atomic, oldval, newval);
+ }
+
+ gboolean
+@@ -437,7 +437,7 @@
+ gpointer oldval,
+ gpointer newval)
+ {
+- return __sync_bool_compare_and_swap ((long *)atomic,
++ return __sync_bool_compare_and_swap_di ((long *)atomic,
+ (long)oldval, (long)newval);
+ }
+
diff --git a/dev-libs/glib/files/glib-2.12.12-fbsd.patch b/dev-libs/glib/files/glib-2.12.12-fbsd.patch
new file mode 100644
index 0000000..bba6329
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.12.12-fbsd.patch
@@ -0,0 +1,21 @@
+diff --exclude-from=/home/dang/.scripts/diffrc -up -ruN glib-2.12.12.orig/gmodule/gmodule-dl.c glib-2.12.12/gmodule/gmodule-dl.c
+--- glib-2.12.12.orig/gmodule/gmodule-dl.c 2007-05-01 19:12:40.000000000 -0400
++++ glib-2.12.12/gmodule/gmodule-dl.c 2007-07-05 20:10:51.000000000 -0400
+@@ -106,6 +106,7 @@ _g_module_open (const gchar *file_name,
+ static gpointer
+ _g_module_self (void)
+ {
++#ifndef __FreeBSD__
+ gpointer handle;
+
+ /* to query symbols from the program itself, special link options
+@@ -117,6 +118,9 @@ _g_module_self (void)
+ g_module_set_error (fetch_dlerror (TRUE));
+
+ return handle;
++#else
++ return RTLD_DEFAULT;
++#endif
+ }
+
+ static void
diff --git a/dev-libs/glib/files/glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch b/dev-libs/glib/files/glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch
new file mode 100644
index 0000000..cabe56f
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch
@@ -0,0 +1,20 @@
+Temporary workaround for gio tests failure when ran without FEATURES=userpriv
+until upstream bug #552912 is fixed
+
+--- gio/tests/live-g-file.c.orig 2008-09-25 05:44:12.848556034 +0300
++++ gio/tests/live-g-file.c 2008-09-25 06:12:34.248726237 +0300
+@@ -769,11 +769,14 @@
+ if (posix_compat)
+ {
+ /* target directory is not accessible (no execute flag) */
++#if 0
++/* Fails when ran as root */
+ do_copy_move (root, item, TEST_DIR_NO_ACCESS,
+ TEST_NO_ACCESS);
+ /* target directory is readonly */
+ do_copy_move (root, item, TEST_DIR_NO_WRITE,
+ TEST_NO_ACCESS);
++#endif
+ }
+ }
+ }
diff --git a/dev-libs/glib/files/glib-2.24-assert-test-failure.patch b/dev-libs/glib/files/glib-2.24-assert-test-failure.patch
new file mode 100644
index 0000000..6d8e74f
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.24-assert-test-failure.patch
@@ -0,0 +1,19 @@
+Tests fail when upgrading glib from 2.22 to 2.24 if sys-devel/gdb is installed
+because gdb is run on .libs/assert-msg-test before LD_LIBRARY_PATH is set. This
+causes gdb to use the system-wide glib instead, and fail on the test.
+
+This patch exports LD_LIBRARY_PATH before running gdb
+
+https://bugzilla.gnome.org/621368
+
+---
+--- tests/run-assert-msg-test.sh
++++ tests/run-assert-msg-test.sh
+@@ -34,6 +34,7 @@ if [ -e ".libs/lt-$msg_test" ]; then
+ msg_test="lt-$msg_test"
+ fi
+ echo_v "Running gdb on assert-msg-test"
++export LD_LIBRARY_PATH="`dirname $PWD`/glib/.libs:$LD_LIBRARY_PATH"
+ OUT=$(gdb --batch --ex run --ex "print (char*) __glib_assert_msg" .libs/$msg_test 2> $error_out) || \
+ fail "failed to run gdb"
+
diff --git a/dev-libs/glib/files/glib-2.24-punt-python-check.patch b/dev-libs/glib/files/glib-2.24-punt-python-check.patch
new file mode 100644
index 0000000..3cbd6dc
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.24-punt-python-check.patch
@@ -0,0 +1,20 @@
+Remove python detection from configure.in, we won't be installing the gdb python
+scripts anymore. They use a redhat-specific gdb module that has not been
+upstreamed yet.
+
+https://bugs.gentoo.org/291328
+https://bugzilla.gnome.org/623552
+---
+--- configure.in
++++ configure.in
+@@ -379,10 +379,6 @@ if test "x$PERL_PATH" = x ; then
+ fi
+ AC_SUBST(PERL_PATH)
+
+-# Need suitable python path for greport
+-AM_PATH_PYTHON(2.4,,PYTHON="/usr/bin/env python2.4")
+-
+-
+ dnl ***********************
+ dnl *** Tests for iconv ***
+ dnl ***********************
diff --git a/dev-libs/glib/files/glib-2.25-punt-python-check.patch b/dev-libs/glib/files/glib-2.25-punt-python-check.patch
new file mode 100644
index 0000000..077ebf4
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.25-punt-python-check.patch
@@ -0,0 +1,20 @@
+Remove python detection from configure.in, we won't be installing the gdb python
+scripts anymore. They use a redhat-specific gdb module that has not been
+upstreamed yet.
+
+https://bugs.gentoo.org/291328
+https://bugzilla.gnome.org/623552
+---
+--- configure.ac
++++ configure.ac
+@@ -379,10 +379,6 @@ if test "x$PERL_PATH" = x ; then
+ fi
+ AC_SUBST(PERL_PATH)
+
+-# Need suitable python path for greport
+-AM_PATH_PYTHON(2.4,,PYTHON="/usr/bin/env python2.4")
+-
+-
+ dnl ***********************
+ dnl *** Tests for iconv ***
+ dnl ***********************
diff --git a/dev-libs/glib/files/glib-2.25-skip-tests-with-dbus-keyring.patch b/dev-libs/glib/files/glib-2.25-skip-tests-with-dbus-keyring.patch
new file mode 100644
index 0000000..baca1ec
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.25-skip-tests-with-dbus-keyring.patch
@@ -0,0 +1,22 @@
+--- gio/tests/gdbus-peer.c.orig 2010-08-28 20:06:11.000000000 +0300
++++ gio/tests/gdbus-peer.c 2010-08-28 20:06:21.000000000 +0300
+@@ -1448,7 +1448,7 @@
+
+ g_test_add_func ("/gdbus/peer-to-peer", test_peer);
+ g_test_add_func ("/gdbus/delayed-message-processing", delayed_message_processing);
+- g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
++ //g_test_add_func ("/gdbus/nonce-tcp", test_nonce_tcp);
+ g_test_add_func ("/gdbus/credentials", test_credentials);
+ g_test_add_func ("/gdbus/overflow", test_overflow);
+
+--- gio/tests/gdbus-non-socket.c.orig 2010-08-28 20:36:52.000000000 +0300
++++ gio/tests/gdbus-non-socket.c 2010-08-28 20:37:02.000000000 +0300
+@@ -336,7 +336,7 @@
+ /* all the tests rely on a shared main loop */
+ loop = g_main_loop_new (NULL, FALSE);
+
+- g_test_add_func ("/gdbus/non-socket", test_non_socket);
++ //g_test_add_func ("/gdbus/non-socket", test_non_socket);
+
+ ret = g_test_run();
+
diff --git a/dev-libs/glib/files/glib-2.26.0-disable-locale-sensitive-test.patch b/dev-libs/glib/files/glib-2.26.0-disable-locale-sensitive-test.patch
new file mode 100644
index 0000000..235d5c7
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.0-disable-locale-sensitive-test.patch
@@ -0,0 +1,50 @@
+From 3a02a86a0a413304843c1cfad359922322486da6 Mon Sep 17 00:00:00 2001
+From: Gilles Dartiguelongue <eva@gentoo.org>
+Date: Wed, 6 Oct 2010 23:21:01 +0200
+Subject: [PATCH 1/2] gsettings: disable locale sensitive test.
+
+---
+ gio/tests/gsettings.c | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/gio/tests/gsettings.c b/gio/tests/gsettings.c
+index fdadf96..4d19618 100644
+--- a/gio/tests/gsettings.c
++++ b/gio/tests/gsettings.c
+@@ -625,14 +625,14 @@ test_l10n (void)
+ g_free (str);
+ str = NULL;
+
+- setlocale (LC_MESSAGES, "de_DE");
++ /*setlocale (LC_MESSAGES, "de_DE");
+ str = g_settings_get_string (settings, "error-message");
+ setlocale (LC_MESSAGES, locale);
+
+ g_assert_cmpstr (str, ==, "Unbenannt");
+ g_object_unref (settings);
+ g_free (str);
+- str = NULL;
++ str = NULL;*/
+
+ g_free (locale);
+ }
+@@ -666,14 +666,14 @@ test_l10n_context (void)
+ g_free (str);
+ str = NULL;
+
+- setlocale (LC_MESSAGES, "de_DE");
++ /*setlocale (LC_MESSAGES, "de_DE");
+ g_settings_get (settings, "backspace", "s", &str);
+ setlocale (LC_MESSAGES, locale);
+
+ g_assert_cmpstr (str, ==, "Löschen");
+ g_object_unref (settings);
+ g_free (str);
+- str = NULL;
++ str = NULL;*/
+
+ g_free (locale);
+ }
+--
+1.7.3
+
diff --git a/dev-libs/glib/files/glib-2.26.0-disable-volumemonitor-broken-test.patch b/dev-libs/glib/files/glib-2.26.0-disable-volumemonitor-broken-test.patch
new file mode 100644
index 0000000..34fad9e
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.0-disable-volumemonitor-broken-test.patch
@@ -0,0 +1,43 @@
+From 8eb4fb83d0933d09bb6ef0ec1511a6b0eb2cee9b Mon Sep 17 00:00:00 2001
+From: Gilles Dartiguelongue <eva@gentoo.org>
+Date: Wed, 6 Oct 2010 23:21:22 +0200
+Subject: [PATCH 2/2] volumemonitor: disable failing test
+
+---
+ gio/tests/volumemonitor.c | 6 +++---
+ 1 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gio/tests/volumemonitor.c b/gio/tests/volumemonitor.c
+index 54123ec..df19b58 100644
+--- a/gio/tests/volumemonitor.c
++++ b/gio/tests/volumemonitor.c
+@@ -112,7 +112,7 @@ test_connected_drives (void)
+ g_list_free (drives);
+ }
+
+-static void
++/*static void
+ test_volumes (void)
+ {
+ GList *volumes, *l;
+@@ -131,7 +131,7 @@ test_volumes (void)
+
+ g_list_foreach (volumes, (GFunc)g_object_unref, NULL);
+ g_list_free (volumes);
+-}
++}*/
+
+ static void
+ test_mounts (void)
+@@ -173,7 +173,7 @@ main (int argc, char *argv[])
+ monitor = g_volume_monitor_get ();
+
+ g_test_add_func ("/volumemonitor/connected_drives", test_connected_drives);
+- g_test_add_func ("/volumemonitor/volumes", test_volumes);
++ //g_test_add_func ("/volumemonitor/volumes", test_volumes);
+ g_test_add_func ("/volumemonitor/mounts", test_mounts);
+
+ ret = g_test_run ();
+--
+1.7.3
+
diff --git a/dev-libs/glib/files/glib-2.26.1-deprecation-tests.patch b/dev-libs/glib/files/glib-2.26.1-deprecation-tests.patch
new file mode 100644
index 0000000..c4085ae
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-deprecation-tests.patch
@@ -0,0 +1,43 @@
+From cae0b1c57f0f8ce73f4f117f8abb61c68e34a0e7 Mon Sep 17 00:00:00 2001
+From: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date: Tue, 30 Nov 2010 02:28:00 +0000
+Subject: Bug635093: Deprecation check in tests/testglib.c
+
+The Relation API in glib/grel.h has been marked as
+deprecated (G_DISABLE_DEPRECATED), so added check for
+that macro in this source file and added label to indicate
+deprecation
+---
+diff --git a/tests/testglib.c b/tests/testglib.c
+index b4e29f0..158808a 100644
+--- a/tests/testglib.c
++++ b/tests/testglib.c
+@@ -1038,6 +1038,7 @@ hash_table_tests (void)
+ g_hash_table_destroy (hash_table);
+ }
+
++#ifndef G_DISABLE_DEPRECATED
+ static void
+ relation_test (void)
+ {
+@@ -1110,6 +1111,7 @@ relation_test (void)
+
+ relation = NULL;
+ }
++#endif
+
+ static void
+ gstring_tests (void)
+@@ -1539,7 +1541,9 @@ main (int argc,
+ g_test_add_func ("/testglib/GTree", binary_tree_test);
+ g_test_add_func ("/testglib/Arrays", test_arrays);
+ g_test_add_func ("/testglib/GHashTable", hash_table_tests);
+- g_test_add_func ("/testglib/Relation", relation_test);
++#ifndef G_DISABLE_DEPRECATED
++ g_test_add_func ("/testglib/Relation (deprecated)", relation_test);
++#endif
+ g_test_add_func ("/testglib/File Paths", test_paths);
+ g_test_add_func ("/testglib/File Functions", test_file_functions);
+ g_test_add_func ("/testglib/Parse Debug Strings", test_g_parse_debug_string);
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.26.1-gatomic-header.patch b/dev-libs/glib/files/glib-2.26.1-gatomic-header.patch
new file mode 100644
index 0000000..f6454d4
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-gatomic-header.patch
@@ -0,0 +1,11 @@
+$OpenBSD: patch-glib_gatomic_c,v 1.1 2010/10/10 10:52:04 kili Exp $
+--- glib/gatomic.c.orig Thu Sep 23 17:26:45 2010
++++ glib/gatomic.c Sun Oct 10 11:50:01 2010
+@@ -28,6 +28,7 @@
+ #endif
+
+ #include "gatomic.h"
++#include "gthread.h"
+ #include "gthreadprivate.h"
+
+ /**
diff --git a/dev-libs/glib/files/glib-2.26.1-gdatetime-test.patch b/dev-libs/glib/files/glib-2.26.1-gdatetime-test.patch
new file mode 100644
index 0000000..054f311
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-gdatetime-test.patch
@@ -0,0 +1,21 @@
+From 3f059a6a123dd62257f224b9af7701078783060e Mon Sep 17 00:00:00 2001
+From: Matthias Clasen <mclasen@redhat.com>
+Date: Sat, 22 Jan 2011 04:41:12 +0000
+Subject: Remove a test that seems to fail depending on time of day
+
+---
+diff --git a/glib/tests/gdatetime.c b/glib/tests/gdatetime.c
+index 01f08de..619bb02 100644
+--- a/glib/tests/gdatetime.c
++++ b/glib/tests/gdatetime.c
+@@ -804,7 +804,7 @@ GDateTime *__dt = g_date_time_new_local (2009, 10, 24, 0, 0, 0);\
+ TEST_PRINTF_TIME (13, 13, 13, "%r", "01:13:13 PM");
+ TEST_PRINTF ("%R", "00:00");
+ TEST_PRINTF_TIME (13, 13, 31, "%R", "13:13");
+- TEST_PRINTF ("%s", t_str);
++ //TEST_PRINTF ("%s", t_str);
+ TEST_PRINTF ("%S", "00");
+ TEST_PRINTF ("%t", " ");
+ TEST_PRINTF ("%W", "42");
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.26.1-gdbus-flushes.patch b/dev-libs/glib/files/glib-2.26.1-gdbus-flushes.patch
new file mode 100644
index 0000000..5ae2d72
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-gdbus-flushes.patch
@@ -0,0 +1,64 @@
+From b2315084cb21a1ef072a48b0238a2e614af78be3 Mon Sep 17 00:00:00 2001
+From: Ted Gould <ted@gould.cx>
+Date: Mon, 13 Dec 2010 18:33:15 +0000
+Subject: Bug 635626 – GDBus message idle can execute while flushes are pending
+
+https://bugzilla.gnome.org/show_bug.cgi?id=635626
+
+Signed-off-by: David Zeuthen <davidz@redhat.com>
+---
+diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
+index dd9d58a..228c28c 100644
+--- a/gio/gdbusprivate.c
++++ b/gio/gdbusprivate.c
+@@ -431,6 +431,7 @@ struct GDBusWorker
+ gint num_writes_pending;
+ guint64 write_num_messages_written;
+ GList *write_pending_flushes;
++ gboolean flush_pending;
+ };
+
+ /* ---------------------------------------------------------------------------------------------------- */
+@@ -1158,6 +1159,12 @@ ostream_flush_cb (GObject *source_object,
+ if (error != NULL)
+ g_error_free (error);
+
++ /* Make sure we tell folks that we don't have additional
++ flushes pending */
++ g_mutex_lock (data->worker->write_lock);
++ data->worker->flush_pending = FALSE;
++ g_mutex_unlock (data->worker->write_lock);
++
+ /* OK, cool, finally kick off the next write */
+ maybe_write_next_message (data->worker);
+
+@@ -1210,6 +1217,10 @@ message_written (GDBusWorker *worker,
+ worker->write_pending_flushes = g_list_delete_link (worker->write_pending_flushes, l);
+ }
+ }
++ if (flushers != NULL)
++ {
++ worker->flush_pending = TRUE;
++ }
+ g_mutex_unlock (worker->write_lock);
+
+ if (flushers != NULL)
+@@ -1344,7 +1355,7 @@ static gboolean
+ write_message_in_idle_cb (gpointer user_data)
+ {
+ GDBusWorker *worker = user_data;
+- if (worker->num_writes_pending == 0)
++ if (worker->num_writes_pending == 0 && !worker->flush_pending)
+ maybe_write_next_message (worker);
+ return FALSE;
+ }
+@@ -1427,6 +1438,7 @@ _g_dbus_worker_new (GIOStream *stream,
+ worker->stream = g_object_ref (stream);
+ worker->capabilities = capabilities;
+ worker->cancellable = g_cancellable_new ();
++ worker->flush_pending = FALSE;
+
+ worker->frozen = initially_frozen;
+ worker->received_messages_while_frozen = g_queue_new ();
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.26.1-gsettings-read.patch b/dev-libs/glib/files/glib-2.26.1-gsettings-read.patch
new file mode 100644
index 0000000..fa5b081
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-gsettings-read.patch
@@ -0,0 +1,25 @@
+From 900a4c853f8dbf0887c66155ba489ff4570e5948 Mon Sep 17 00:00:00 2001
+From: Matthew Barnes <mbarnes@redhat.com>
+Date: Wed, 01 Dec 2010 00:19:12 +0000
+Subject: Bug 636100 - Can't read GSettings:backend property
+
+The PROP_BACKEND case was missing from the switch statement in
+g_settings_get_property().
+---
+diff --git a/gio/gsettings.c b/gio/gsettings.c
+index 94d1f3a..7f775a0 100644
+--- a/gio/gsettings.c
++++ b/gio/gsettings.c
+@@ -417,6 +417,10 @@ g_settings_get_property (GObject *object,
+ g_value_set_string (value, settings->priv->schema_name);
+ break;
+
++ case PROP_BACKEND:
++ g_value_set_object (value, settings->priv->backend);
++ break;
++
+ case PROP_PATH:
+ g_value_set_string (value, settings->priv->path);
+ break;
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.26.1-gsettings-rules.patch b/dev-libs/glib/files/glib-2.26.1-gsettings-rules.patch
new file mode 100644
index 0000000..01ce226
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-gsettings-rules.patch
@@ -0,0 +1,33 @@
+From 393834ac6f32633a31e52441b051dc7d3969a530 Mon Sep 17 00:00:00 2001
+From: Dan Winship <danw@gnome.org>
+Date: Thu, 04 Nov 2010 19:23:22 +0000
+Subject: gsettings.m4: Fix rules to work when there are no schemas
+
+If there are no schemas, don't try to install "" at install time.
+(In particular, automake conditionals don't work properly with
+@-expanded rules, so if you conditionally build a schema, you'll
+still unconditionally get the install rule.)
+
+https://bugzilla.gnome.org/show_bug.cgi?id=633381
+---
+diff --git a/m4macros/gsettings.m4 b/m4macros/gsettings.m4
+index 4e4352f..f0ed838 100644
+--- a/m4macros/gsettings.m4
++++ b/m4macros/gsettings.m4
+@@ -47,9 +47,11 @@ install-data-am: install-gsettings-schemas
+
+ install-gsettings-schemas: $(gsettings_SCHEMAS) $(gsettings__enum_file)
+ @$(NORMAL_INSTALL)
+- test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"
+- $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"
+- test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir)
++ if test -n "$^"; then \
++ test -z "$(gsettingsschemadir)" || $(MKDIR_P) "$(DESTDIR)$(gsettingsschemadir)"; \
++ $(INSTALL_DATA) $^ "$(DESTDIR)$(gsettingsschemadir)"; \
++ test -n "$(GSETTINGS_DISABLE_SCHEMAS_COMPILE)$(DESTDIR)" || $(GLIB_COMPILE_SCHEMAS) $(gsettingsschemadir); \
++ fi
+
+ uninstall-gsettings-schemas:
+ @$(NORMAL_UNINSTALL)
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.26.1-locked-message.patch b/dev-libs/glib/files/glib-2.26.1-locked-message.patch
new file mode 100644
index 0000000..acec46e
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.26.1-locked-message.patch
@@ -0,0 +1,68 @@
+From 62476cd0f7ca7d3becf81243fb7ac1b97cf7db51 Mon Sep 17 00:00:00 2001
+From: Peng Huang <shawn.p.huang@gmail.com>
+Date: Mon, 13 Dec 2010 18:09:38 +0000
+Subject: Bug 632544 – Cannot send a locked message with PRESERVE_SERIAL flag
+
+https://bugzilla.gnome.org/show_bug.cgi?id=632544
+
+Signed-off-by: David Zeuthen <davidz@redhat.com>
+---
+diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
+index da2b9f9..cf12f41 100644
+--- a/gio/gdbusconnection.c
++++ b/gio/gdbusconnection.c
+@@ -1449,7 +1449,8 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
+ if (out_serial != NULL)
+ *out_serial = serial_to_use;
+
+- g_dbus_message_set_serial (message, serial_to_use);
++ if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
++ g_dbus_message_set_serial (message, serial_to_use);
+
+ g_dbus_message_lock (message);
+ _g_dbus_worker_send_message (connection->worker,
+diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c
+index 866e27c..5c2939e 100644
+--- a/gio/tests/gdbus-connection.c
++++ b/gio/tests/gdbus-connection.c
+@@ -880,6 +880,18 @@ test_connection_filter (void)
+
+ m2 = g_dbus_message_copy (m, &error);
+ g_assert_no_error (error);
++ g_dbus_message_set_serial (m2, data.serial);
++ /* lock the message to test PRESERVE_SERIAL flag. */
++ g_dbus_message_lock (m2);
++ g_dbus_connection_send_message (c, m2, G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL, &data.serial, &error);
++ g_object_unref (m2);
++ g_assert_no_error (error);
++
++ while (data.num_handled == 2)
++ g_thread_yield ();
++
++ m2 = g_dbus_message_copy (m, &error);
++ g_assert_no_error (error);
+ r = g_dbus_connection_send_message_with_reply_sync (c,
+ m2,
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE,
+@@ -891,7 +903,7 @@ test_connection_filter (void)
+ g_assert_no_error (error);
+ g_assert (r != NULL);
+ g_object_unref (r);
+- g_assert_cmpint (data.num_handled, ==, 3);
++ g_assert_cmpint (data.num_handled, ==, 4);
+
+ g_dbus_connection_remove_filter (c, filter_id);
+
+@@ -908,8 +920,8 @@ test_connection_filter (void)
+ g_assert_no_error (error);
+ g_assert (r != NULL);
+ g_object_unref (r);
+- g_assert_cmpint (data.num_handled, ==, 3);
+- g_assert_cmpint (data.num_outgoing, ==, 3);
++ g_assert_cmpint (data.num_handled, ==, 4);
++ g_assert_cmpint (data.num_outgoing, ==, 4);
+
+ /* this is safe; testserver will exit once the bus goes away */
+ g_assert (g_spawn_command_line_async (SRCDIR "/gdbus-testserver.py", NULL));
+--
+cgit v0.8.3.1
diff --git a/dev-libs/glib/files/glib-2.28.2-gio_launch_handler.patch b/dev-libs/glib/files/glib-2.28.2-gio_launch_handler.patch
new file mode 100644
index 0000000..2c232b4
--- /dev/null
+++ b/dev-libs/glib/files/glib-2.28.2-gio_launch_handler.patch
@@ -0,0 +1,234 @@
+From 41a32799fa223937e5e980ffb8c268b183c416e2 Mon Sep 17 00:00:00 2001
+From: Mikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>
+Date: Wed, 18 Aug 2010 12:02:10 +0200
+Subject: [PATCH] gio: New extension point "gio-desktop-app-info-launch-handler"
+
+Add an extension point that gets a callback each time a GAppInfo
+is launched. The callback receives the GAppInfo, the list of URIs,
+the launch context, and the pid.
+---
+ gio/gdesktopappinfo.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++-
+ gio/gdesktopappinfo.h | 31 ++++++++++++
+ gio/gio.symbols | 1 +
+ gio/giomodule.c | 3 +
+ 4 files changed, 157 insertions(+), 1 deletions(-)
+
+Index: glib-2.28.2/gio/gdesktopappinfo.c
+===================================================================
+--- glib-2.28.2.orig/gio/gdesktopappinfo.c 2011-03-05 04:49:45.000000000 +1100
++++ glib-2.28.2/gio/gdesktopappinfo.c 2011-03-08 13:31:40.605569315 +1100
+@@ -74,6 +74,12 @@
+ static void mime_info_cache_reload (const char *dir);
+ static gboolean g_desktop_app_info_ensure_saved (GDesktopAppInfo *info,
+ GError **error);
++static void
++g_desktop_app_info_launch_handler_on_launched (GDesktopAppInfoLaunchHandler *launch_handler,
++ GDesktopAppInfo *app_info,
++ GList *uris,
++ GAppLaunchContext *launch_ctx,
++ gint pid);
+
+ /**
+ * GDesktopAppInfo:
+@@ -995,6 +1001,49 @@
+ g_object_unref (msg);
+ }
+
++static void
++g_desktop_app_info_on_launched (GDesktopAppInfo *app_info,
++ GList *uris,
++ GAppLaunchContext *launch_ctx,
++ gint pid)
++{
++ static gsize lookup = 0;
++
++ if (g_once_init_enter (&lookup))
++ {
++ gsize setup_value = 1;
++ GDesktopAppInfoLaunchHandler *lookup_instance;
++ GIOExtensionPoint *ep;
++ GIOExtension *extension;
++ GList *l;
++
++ /* Ensure vfs in modules loaded */
++ _g_io_modules_ensure_loaded ();
++
++ ep = g_io_extension_point_lookup (G_DESKTOP_APP_INFO_LAUNCH_HANDLER_EXTENSION_POINT_NAME);
++
++ lookup_instance = NULL;
++ for (l = g_io_extension_point_get_extensions (ep); l != NULL; l = l->next)
++ {
++ extension = l->data;
++ lookup_instance = g_object_new (g_io_extension_get_type (extension), NULL);
++ if (lookup_instance != NULL)
++ break;
++ }
++
++ if (lookup_instance != NULL)
++ setup_value = (gsize)lookup_instance;
++
++ g_once_init_leave (&lookup, setup_value);
++ }
++
++ if (lookup == 1)
++ return;
++
++ g_desktop_app_info_launch_handler_on_launched (G_DESKTOP_APP_INFO_LAUNCH_HANDLER (lookup),
++ app_info, uris, launch_ctx, pid);
++}
++
+ #define _SPAWN_FLAGS_DEFAULT (G_SPAWN_SEARCH_PATH)
+
+ static gboolean
+@@ -1086,6 +1135,10 @@
+
+ goto out;
+ }
++ else
++ {
++ g_desktop_app_info_on_launched (info, old_uris, launch_context, pid);
++ }
+
+ if (pid_callback != NULL)
+ pid_callback (info, pid, pid_callback_data);
+@@ -3120,6 +3173,72 @@
+ return desktop_entries;
+ }
+
++/* GDesktopAppInfoLaunchHandler interface: */
++
++static void g_desktop_app_info_launch_handler_base_init (gpointer g_class);
++static void g_desktop_app_info_launch_handler_class_init (gpointer g_class,
++ gpointer class_data);
++
++GType
++g_desktop_app_info_launch_handler_get_type (void)
++{
++ static volatile gsize g_define_type_id__volatile = 0;
++
++ if (g_once_init_enter (&g_define_type_id__volatile))
++ {
++ const GTypeInfo desktop_app_info_launch_handler_info =
++ {
++ sizeof (GDesktopAppInfoLaunchHandlerIface), /* class_size */
++ g_desktop_app_info_launch_handler_base_init, /* base_init */
++ NULL, /* base_finalize */
++ g_desktop_app_info_launch_handler_class_init,
++ NULL, /* class_finalize */
++ NULL, /* class_data */
++ 0,
++ 0, /* n_preallocs */
++ NULL
++ };
++
++ GType g_define_type_id =
++ g_type_register_static (G_TYPE_INTERFACE,
++ I_("GDesktopAppInfoLaunchHandler"),
++ &desktop_app_info_launch_handler_info, 0);
++
++ g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
++
++ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
++ }
++
++ return g_define_type_id__volatile;
++}
++
++static void
++g_desktop_app_info_launch_handler_class_init (gpointer g_class,
++ gpointer class_data)
++{
++}
++
++static void
++g_desktop_app_info_launch_handler_base_init (gpointer g_class)
++{
++}
++
++static void
++g_desktop_app_info_launch_handler_on_launched (GDesktopAppInfoLaunchHandler *launch_handler,
++ GDesktopAppInfo *app_info,
++ GList *uris,
++ GAppLaunchContext *launch_ctx,
++ gint pid)
++{
++ GDesktopAppInfoLaunchHandlerIface *iface;
++
++ g_return_if_fail (G_IS_DESKTOP_APP_INFO_LAUNCH_HANDLER (launch_handler));
++
++ iface = G_DESKTOP_APP_INFO_LAUNCH_HANDLER_GET_IFACE (launch_handler);
++
++ (* iface->on_launched) (launch_handler, app_info, uris, launch_ctx, pid);
++}
++
+ /* GDesktopAppInfoLookup interface: */
+
+ typedef GDesktopAppInfoLookupIface GDesktopAppInfoLookupInterface;
+Index: glib-2.28.2/gio/gdesktopappinfo.h
+===================================================================
+--- glib-2.28.2.orig/gio/gdesktopappinfo.h 2011-01-06 08:44:06.000000000 +1100
++++ glib-2.28.2/gio/gdesktopappinfo.h 2011-03-08 13:31:40.605569315 +1100
+@@ -119,6 +119,37 @@
+
+ #endif /* G_DISABLE_DEPRECATED */
+
++
++
++#define G_TYPE_DESKTOP_APP_INFO_LAUNCH_HANDLER (g_desktop_app_info_launch_handler_get_type ())
++#define G_DESKTOP_APP_INFO_LAUNCH_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_DESKTOP_APP_INFO_LAUNCH_HANDLER, GDesktopAppInfoLaunchHandler))
++#define G_IS_DESKTOP_APP_INFO_LAUNCH_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_DESKTOP_APP_INFO_LAUNCH_HANDLER))
++#define G_DESKTOP_APP_INFO_LAUNCH_HANDLER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), G_TYPE_DESKTOP_APP_INFO_LAUNCH_HANDLER, GDesktopAppInfoLaunchHandlerIface))
++
++/**
++ * G_DESKTOP_APP_INFO_LAUNCH_HANDLER_EXTENSION_POINT_NAME:
++ *
++ * Extension point for default handler to launching. See
++ * <link linkend="extending-gio">Extending GIO</link>.
++ */
++#define G_DESKTOP_APP_INFO_LAUNCH_HANDLER_EXTENSION_POINT_NAME "gio-desktop-app-info-launch-handler"
++
++typedef struct _GDesktopAppInfoLaunchHandler GDesktopAppInfoLaunchHandler;
++typedef struct _GDesktopAppInfoLaunchHandlerIface GDesktopAppInfoLaunchHandlerIface;
++
++struct _GDesktopAppInfoLaunchHandlerIface
++{
++ GTypeInterface g_iface;
++
++ void (* on_launched) (GDesktopAppInfoLaunchHandler *launch_handler,
++ GDesktopAppInfo *app_info,
++ GList *uris,
++ GAppLaunchContext *launch_ctx,
++ gint pid);
++};
++
++GType g_desktop_app_info_launch_handler_get_type (void) G_GNUC_CONST;
++
+ G_END_DECLS
+
+ #endif /* __G_DESKTOP_APP_INFO_H__ */
+Index: glib-2.28.2/gio/gio.symbols
+===================================================================
+--- glib-2.28.2.orig/gio/gio.symbols 2011-01-18 07:54:00.000000000 +1100
++++ glib-2.28.2/gio/gio.symbols 2011-03-08 13:31:40.605569315 +1100
+@@ -135,6 +135,7 @@
+ g_desktop_app_info_get_filename
+ g_desktop_app_info_get_is_hidden
+ g_desktop_app_info_get_type G_GNUC_CONST
++g_desktop_app_info_launch_handler_on_launched
+ g_desktop_app_info_launch_uris_as_manager
+ g_desktop_app_info_lookup_get_type G_GNUC_CONST
+ g_desktop_app_info_lookup_get_default_for_uri_scheme
+Index: glib-2.28.2/gio/giomodule.c
+===================================================================
+--- glib-2.28.2.orig/gio/giomodule.c 2011-01-06 08:44:06.000000000 +1100
++++ glib-2.28.2/gio/giomodule.c 2011-03-08 13:31:40.605569315 +1100
+@@ -559,6 +559,9 @@
+ ep = g_io_extension_point_register (G_PROXY_EXTENSION_POINT_NAME);
+ g_io_extension_point_set_required_type (ep, G_TYPE_PROXY);
+
++ ep = g_io_extension_point_register (G_DESKTOP_APP_INFO_LAUNCH_HANDLER_EXTENSION_POINT_NAME);
++ g_io_extension_point_set_required_type (ep, G_TYPE_DESKTOP_APP_INFO_LAUNCH_HANDLER);
++
+ ep = g_io_extension_point_register (G_TLS_BACKEND_EXTENSION_POINT_NAME);
+ g_io_extension_point_set_required_type (ep, G_TYPE_TLS_BACKEND);
+ }
diff --git a/dev-libs/glib/glib-2.28.5-r1.ebuild b/dev-libs/glib/glib-2.28.5-r1.ebuild
new file mode 100644
index 0000000..4533dea
--- /dev/null
+++ b/dev-libs/glib/glib-2.28.5-r1.ebuild
@@ -0,0 +1,176 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-libs/glib/glib-2.28.5.ebuild,v 1.1 2011/04/01 19:33:37 nirbheek Exp $
+
+EAPI="3"
+PYTHON_DEPEND="2"
+
+inherit autotools gnome.org libtool eutils flag-o-matic pax-utils python virtualx
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="http://www.gtk.org/"
+
+LICENSE="LGPL-2"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~sparc-fbsd ~x86-fbsd"
+IUSE="debug doc fam +introspection selinux +static-libs test xattr utouch"
+
+RDEPEND="virtual/libiconv
+ sys-libs/zlib
+ xattr? ( sys-apps/attr )
+ fam? ( virtual/fam )"
+DEPEND="${RDEPEND}
+ >=dev-util/pkgconfig-0.16
+ >=sys-devel/gettext-0.11
+ >=dev-util/gtk-doc-am-1.13
+ doc? (
+ >=dev-libs/libxslt-1.0
+ >=dev-util/gtk-doc-1.13
+ ~app-text/docbook-xml-dtd-4.1.2 )
+ test? ( >=sys-apps/dbus-1.2.14 )"
+PDEPEND="introspection? ( dev-libs/gobject-introspection )
+ !<gnome-base/gvfs-1.6.4-r990" # Earlier versions do not work with glib
+
+# XXX: Consider adding test? ( sys-devel/gdb ); assert-msg-test tries to use it
+
+pkg_setup() {
+ python_set_active_version 2
+}
+
+src_prepare() {
+ if use ia64 ; then
+ # Only apply for < 4.1
+ local major=$(gcc-major-version)
+ local minor=$(gcc-minor-version)
+ if (( major < 4 || ( major == 4 && minor == 0 ) )); then
+ epatch "${FILESDIR}/glib-2.10.3-ia64-atomic-ops.patch"
+ fi
+ fi
+
+ # Don't fail gio tests when ran without userpriv, upstream bug 552912
+ # This is only a temporary workaround, remove as soon as possible
+ epatch "${FILESDIR}/${PN}-2.18.1-workaround-gio-test-failure-without-userpriv.patch"
+
+ # Fix gmodule issues on fbsd; bug #184301
+ epatch "${FILESDIR}"/${PN}-2.12.12-fbsd.patch
+
+ # Don't check for python, hence removing the build-time python dep.
+ # We remove the gdb python scripts in src_install due to bug 291328
+ epatch "${FILESDIR}/${PN}-2.25-punt-python-check.patch"
+
+ # Fix test failure when upgrading from 2.22 to 2.24, upstream bug 621368
+ epatch "${FILESDIR}/${PN}-2.24-assert-test-failure.patch"
+
+ # Do not try to remove files on live filesystem, upstream bug #619274
+ sed 's:^\(.*"/desktop-app-info/delete".*\):/*\1*/:' \
+ -i "${S}"/gio/tests/desktop-app-info.c || die "sed failed"
+
+ # Disable failing tests, upstream bug #???
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-locale-sensitive-test.patch"
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-volumemonitor-broken-test.patch"
+
+ if use utouch; then
+ epatch "${FILESDIR}/${PN}-2.28.2-gio_launch_handler.patch"
+ fi
+
+ if ! use test; then
+ # don't waste time building tests
+ sed 's/^\(SUBDIRS =.*\)tests\(.*\)$/\1\2/' -i Makefile.am Makefile.in \
+ || die "sed failed"
+ fi
+
+ # Needed for the punt-python-check patch, disabling timeout test
+ # Also needed to prevent croscompile failures, see bug #267603
+ eautoreconf
+
+ [[ ${CHOST} == *-freebsd* ]] && elibtoolize
+
+ epunt_cxx
+}
+
+src_configure() {
+ local myconf
+
+ # Building with --disable-debug highly unrecommended. It will build glib in
+ # an unusable form as it disables some commonly used API. Please do not
+ # convert this to the use_enable form, as it results in a broken build.
+ # -- compnerd (3/27/06)
+ # disable-visibility needed for reference debug, bug #274647
+ use debug && myconf="--enable-debug --disable-visibility"
+
+ # Always use internal libpcre, bug #254659
+ econf ${myconf} \
+ $(use_enable xattr) \
+ $(use_enable doc man) \
+ $(use_enable doc gtk-doc) \
+ $(use_enable fam) \
+ $(use_enable selinux) \
+ $(use_enable static-libs static) \
+ --enable-regex \
+ --with-pcre=internal \
+ --with-threads=posix \
+ --disable-dtrace \
+ --disable-systemtap
+}
+
+src_install() {
+ local f
+ emake DESTDIR="${D}" install || die "Installation failed"
+
+ # Do not install charset.alias even if generated, leave it to libiconv
+ rm -f "${ED}/usr/lib/charset.alias"
+
+ # Don't install gdb python macros, bug 291328
+ rm -rf "${ED}/usr/share/gdb/" "${ED}/usr/share/glib-2.0/gdb/"
+
+ dodoc AUTHORS ChangeLog* NEWS* README || die "dodoc failed"
+
+ insinto /usr/share/bash-completion
+ for f in gdbus gsettings; do
+ newins "${ED}/etc/bash_completion.d/${f}-bash-completion.sh" ${f} || die
+ done
+ rm -rf "${ED}/etc"
+}
+
+src_test() {
+ unset DBUS_SESSION_BUS_ADDRESS
+ export XDG_CONFIG_DIRS=/etc/xdg
+ export XDG_DATA_DIRS=/usr/local/share:/usr/share
+ export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+ export XDG_DATA_HOME="${T}"
+ unset GSETTINGS_BACKEND # bug 352451
+
+ # Related test is a bit nitpicking
+ mkdir "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+ chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+
+ # Hardened: gdb needs this, bug #338891
+ if host-is-pax ; then
+ pax-mark -mr "${S}"/tests/.libs/assert-msg-test \
+ || die "Hardened adjustment failed"
+ fi
+
+ # Need X for dbus-launch session X11 initialization
+ Xemake check || die "tests failed"
+}
+
+pkg_preinst() {
+ # Only give the introspection message if:
+ # * The user has it enabled
+ # * Has glib already installed
+ # * Previous version was different from new version
+ if use introspection && has_version "${CATEGORY}/${PN}"; then
+ if ! has_version "=${CATEGORY}/${PF}"; then
+ ewarn "You must rebuild gobject-introspection so that the installed"
+ ewarn "typelibs and girs are regenerated for the new APIs in glib"
+ fi
+ fi
+}
+
+pkg_postinst() {
+ # Inform users about possible breakage when updating glib and not dbus-glib, bug #297483
+ if has_version dev-libs/dbus-glib; then
+ ewarn "If you experience a breakage after updating dev-libs/glib try"
+ ewarn "rebuilding dev-libs/dbus-glib"
+ fi
+}
diff --git a/dev-libs/glib/glib-2.28.6-r1.ebuild b/dev-libs/glib/glib-2.28.6-r1.ebuild
new file mode 100644
index 0000000..653096a
--- /dev/null
+++ b/dev-libs/glib/glib-2.28.6-r1.ebuild
@@ -0,0 +1,176 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-libs/glib/glib-2.28.6.ebuild,v 1.1 2011/04/01 19:33:37 nirbheek Exp $
+
+EAPI="3"
+PYTHON_DEPEND="2"
+
+inherit autotools gnome.org libtool eutils flag-o-matic pax-utils python virtualx
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="http://www.gtk.org/"
+
+LICENSE="LGPL-2"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~sparc-fbsd ~x86-fbsd"
+IUSE="debug doc fam +introspection selinux +static-libs test xattr utouch"
+
+RDEPEND="virtual/libiconv
+ sys-libs/zlib
+ xattr? ( sys-apps/attr )
+ fam? ( virtual/fam )"
+DEPEND="${RDEPEND}
+ >=dev-util/pkgconfig-0.16
+ >=sys-devel/gettext-0.11
+ >=dev-util/gtk-doc-am-1.13
+ doc? (
+ >=dev-libs/libxslt-1.0
+ >=dev-util/gtk-doc-1.13
+ ~app-text/docbook-xml-dtd-4.1.2 )
+ test? ( >=sys-apps/dbus-1.2.14 )"
+PDEPEND="introspection? ( dev-libs/gobject-introspection )
+ !<gnome-base/gvfs-1.6.4-r990" # Earlier versions do not work with glib
+
+# XXX: Consider adding test? ( sys-devel/gdb ); assert-msg-test tries to use it
+
+pkg_setup() {
+ python_set_active_version 2
+}
+
+src_prepare() {
+ if use ia64 ; then
+ # Only apply for < 4.1
+ local major=$(gcc-major-version)
+ local minor=$(gcc-minor-version)
+ if (( major < 4 || ( major == 4 && minor == 0 ) )); then
+ epatch "${FILESDIR}/glib-2.10.3-ia64-atomic-ops.patch"
+ fi
+ fi
+
+ # Don't fail gio tests when ran without userpriv, upstream bug 552912
+ # This is only a temporary workaround, remove as soon as possible
+ epatch "${FILESDIR}/${PN}-2.18.1-workaround-gio-test-failure-without-userpriv.patch"
+
+ # Fix gmodule issues on fbsd; bug #184301
+ epatch "${FILESDIR}"/${PN}-2.12.12-fbsd.patch
+
+ # Don't check for python, hence removing the build-time python dep.
+ # We remove the gdb python scripts in src_install due to bug 291328
+ epatch "${FILESDIR}/${PN}-2.25-punt-python-check.patch"
+
+ # Fix test failure when upgrading from 2.22 to 2.24, upstream bug 621368
+ epatch "${FILESDIR}/${PN}-2.24-assert-test-failure.patch"
+
+ # Do not try to remove files on live filesystem, upstream bug #619274
+ sed 's:^\(.*"/desktop-app-info/delete".*\):/*\1*/:' \
+ -i "${S}"/gio/tests/desktop-app-info.c || die "sed failed"
+
+ # Disable failing tests, upstream bug #???
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-locale-sensitive-test.patch"
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-volumemonitor-broken-test.patch"
+
+ if use utouch; then
+ epatch "${FILESDIR}/${PN}-2.28.2-gio_launch_handler.patch"
+ fi
+
+ if ! use test; then
+ # don't waste time building tests
+ sed 's/^\(SUBDIRS =.*\)tests\(.*\)$/\1\2/' -i Makefile.am Makefile.in \
+ || die "sed failed"
+ fi
+
+ # Needed for the punt-python-check patch, disabling timeout test
+ # Also needed to prevent croscompile failures, see bug #267603
+ eautoreconf
+
+ [[ ${CHOST} == *-freebsd* ]] && elibtoolize
+
+ epunt_cxx
+}
+
+src_configure() {
+ local myconf
+
+ # Building with --disable-debug highly unrecommended. It will build glib in
+ # an unusable form as it disables some commonly used API. Please do not
+ # convert this to the use_enable form, as it results in a broken build.
+ # -- compnerd (3/27/06)
+ # disable-visibility needed for reference debug, bug #274647
+ use debug && myconf="--enable-debug --disable-visibility"
+
+ # Always use internal libpcre, bug #254659
+ econf ${myconf} \
+ $(use_enable xattr) \
+ $(use_enable doc man) \
+ $(use_enable doc gtk-doc) \
+ $(use_enable fam) \
+ $(use_enable selinux) \
+ $(use_enable static-libs static) \
+ --enable-regex \
+ --with-pcre=internal \
+ --with-threads=posix \
+ --disable-dtrace \
+ --disable-systemtap
+}
+
+src_install() {
+ local f
+ emake DESTDIR="${D}" install || die "Installation failed"
+
+ # Do not install charset.alias even if generated, leave it to libiconv
+ rm -f "${ED}/usr/lib/charset.alias"
+
+ # Don't install gdb python macros, bug 291328
+ rm -rf "${ED}/usr/share/gdb/" "${ED}/usr/share/glib-2.0/gdb/"
+
+ dodoc AUTHORS ChangeLog* NEWS* README || die "dodoc failed"
+
+ insinto /usr/share/bash-completion
+ for f in gdbus gsettings; do
+ newins "${ED}/etc/bash_completion.d/${f}-bash-completion.sh" ${f} || die
+ done
+ rm -rf "${ED}/etc"
+}
+
+src_test() {
+ unset DBUS_SESSION_BUS_ADDRESS
+ export XDG_CONFIG_DIRS=/etc/xdg
+ export XDG_DATA_DIRS=/usr/local/share:/usr/share
+ export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+ export XDG_DATA_HOME="${T}"
+ unset GSETTINGS_BACKEND # bug 352451
+
+ # Related test is a bit nitpicking
+ mkdir "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+ chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+
+ # Hardened: gdb needs this, bug #338891
+ if host-is-pax ; then
+ pax-mark -mr "${S}"/tests/.libs/assert-msg-test \
+ || die "Hardened adjustment failed"
+ fi
+
+ # Need X for dbus-launch session X11 initialization
+ Xemake check || die "tests failed"
+}
+
+pkg_preinst() {
+ # Only give the introspection message if:
+ # * The user has it enabled
+ # * Has glib already installed
+ # * Previous version was different from new version
+ if use introspection && has_version "${CATEGORY}/${PN}"; then
+ if ! has_version "=${CATEGORY}/${PF}"; then
+ ewarn "You must rebuild gobject-introspection so that the installed"
+ ewarn "typelibs and girs are regenerated for the new APIs in glib"
+ fi
+ fi
+}
+
+pkg_postinst() {
+ # Inform users about possible breakage when updating glib and not dbus-glib, bug #297483
+ if has_version dev-libs/dbus-glib; then
+ ewarn "If you experience a breakage after updating dev-libs/glib try"
+ ewarn "rebuilding dev-libs/dbus-glib"
+ fi
+}
diff --git a/dev-libs/glib/glib-2.28.7-r1.ebuild b/dev-libs/glib/glib-2.28.7-r1.ebuild
new file mode 100644
index 0000000..653096a
--- /dev/null
+++ b/dev-libs/glib/glib-2.28.7-r1.ebuild
@@ -0,0 +1,176 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-libs/glib/glib-2.28.6.ebuild,v 1.1 2011/04/01 19:33:37 nirbheek Exp $
+
+EAPI="3"
+PYTHON_DEPEND="2"
+
+inherit autotools gnome.org libtool eutils flag-o-matic pax-utils python virtualx
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="http://www.gtk.org/"
+
+LICENSE="LGPL-2"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~sparc-fbsd ~x86-fbsd"
+IUSE="debug doc fam +introspection selinux +static-libs test xattr utouch"
+
+RDEPEND="virtual/libiconv
+ sys-libs/zlib
+ xattr? ( sys-apps/attr )
+ fam? ( virtual/fam )"
+DEPEND="${RDEPEND}
+ >=dev-util/pkgconfig-0.16
+ >=sys-devel/gettext-0.11
+ >=dev-util/gtk-doc-am-1.13
+ doc? (
+ >=dev-libs/libxslt-1.0
+ >=dev-util/gtk-doc-1.13
+ ~app-text/docbook-xml-dtd-4.1.2 )
+ test? ( >=sys-apps/dbus-1.2.14 )"
+PDEPEND="introspection? ( dev-libs/gobject-introspection )
+ !<gnome-base/gvfs-1.6.4-r990" # Earlier versions do not work with glib
+
+# XXX: Consider adding test? ( sys-devel/gdb ); assert-msg-test tries to use it
+
+pkg_setup() {
+ python_set_active_version 2
+}
+
+src_prepare() {
+ if use ia64 ; then
+ # Only apply for < 4.1
+ local major=$(gcc-major-version)
+ local minor=$(gcc-minor-version)
+ if (( major < 4 || ( major == 4 && minor == 0 ) )); then
+ epatch "${FILESDIR}/glib-2.10.3-ia64-atomic-ops.patch"
+ fi
+ fi
+
+ # Don't fail gio tests when ran without userpriv, upstream bug 552912
+ # This is only a temporary workaround, remove as soon as possible
+ epatch "${FILESDIR}/${PN}-2.18.1-workaround-gio-test-failure-without-userpriv.patch"
+
+ # Fix gmodule issues on fbsd; bug #184301
+ epatch "${FILESDIR}"/${PN}-2.12.12-fbsd.patch
+
+ # Don't check for python, hence removing the build-time python dep.
+ # We remove the gdb python scripts in src_install due to bug 291328
+ epatch "${FILESDIR}/${PN}-2.25-punt-python-check.patch"
+
+ # Fix test failure when upgrading from 2.22 to 2.24, upstream bug 621368
+ epatch "${FILESDIR}/${PN}-2.24-assert-test-failure.patch"
+
+ # Do not try to remove files on live filesystem, upstream bug #619274
+ sed 's:^\(.*"/desktop-app-info/delete".*\):/*\1*/:' \
+ -i "${S}"/gio/tests/desktop-app-info.c || die "sed failed"
+
+ # Disable failing tests, upstream bug #???
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-locale-sensitive-test.patch"
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-volumemonitor-broken-test.patch"
+
+ if use utouch; then
+ epatch "${FILESDIR}/${PN}-2.28.2-gio_launch_handler.patch"
+ fi
+
+ if ! use test; then
+ # don't waste time building tests
+ sed 's/^\(SUBDIRS =.*\)tests\(.*\)$/\1\2/' -i Makefile.am Makefile.in \
+ || die "sed failed"
+ fi
+
+ # Needed for the punt-python-check patch, disabling timeout test
+ # Also needed to prevent croscompile failures, see bug #267603
+ eautoreconf
+
+ [[ ${CHOST} == *-freebsd* ]] && elibtoolize
+
+ epunt_cxx
+}
+
+src_configure() {
+ local myconf
+
+ # Building with --disable-debug highly unrecommended. It will build glib in
+ # an unusable form as it disables some commonly used API. Please do not
+ # convert this to the use_enable form, as it results in a broken build.
+ # -- compnerd (3/27/06)
+ # disable-visibility needed for reference debug, bug #274647
+ use debug && myconf="--enable-debug --disable-visibility"
+
+ # Always use internal libpcre, bug #254659
+ econf ${myconf} \
+ $(use_enable xattr) \
+ $(use_enable doc man) \
+ $(use_enable doc gtk-doc) \
+ $(use_enable fam) \
+ $(use_enable selinux) \
+ $(use_enable static-libs static) \
+ --enable-regex \
+ --with-pcre=internal \
+ --with-threads=posix \
+ --disable-dtrace \
+ --disable-systemtap
+}
+
+src_install() {
+ local f
+ emake DESTDIR="${D}" install || die "Installation failed"
+
+ # Do not install charset.alias even if generated, leave it to libiconv
+ rm -f "${ED}/usr/lib/charset.alias"
+
+ # Don't install gdb python macros, bug 291328
+ rm -rf "${ED}/usr/share/gdb/" "${ED}/usr/share/glib-2.0/gdb/"
+
+ dodoc AUTHORS ChangeLog* NEWS* README || die "dodoc failed"
+
+ insinto /usr/share/bash-completion
+ for f in gdbus gsettings; do
+ newins "${ED}/etc/bash_completion.d/${f}-bash-completion.sh" ${f} || die
+ done
+ rm -rf "${ED}/etc"
+}
+
+src_test() {
+ unset DBUS_SESSION_BUS_ADDRESS
+ export XDG_CONFIG_DIRS=/etc/xdg
+ export XDG_DATA_DIRS=/usr/local/share:/usr/share
+ export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+ export XDG_DATA_HOME="${T}"
+ unset GSETTINGS_BACKEND # bug 352451
+
+ # Related test is a bit nitpicking
+ mkdir "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+ chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+
+ # Hardened: gdb needs this, bug #338891
+ if host-is-pax ; then
+ pax-mark -mr "${S}"/tests/.libs/assert-msg-test \
+ || die "Hardened adjustment failed"
+ fi
+
+ # Need X for dbus-launch session X11 initialization
+ Xemake check || die "tests failed"
+}
+
+pkg_preinst() {
+ # Only give the introspection message if:
+ # * The user has it enabled
+ # * Has glib already installed
+ # * Previous version was different from new version
+ if use introspection && has_version "${CATEGORY}/${PN}"; then
+ if ! has_version "=${CATEGORY}/${PF}"; then
+ ewarn "You must rebuild gobject-introspection so that the installed"
+ ewarn "typelibs and girs are regenerated for the new APIs in glib"
+ fi
+ fi
+}
+
+pkg_postinst() {
+ # Inform users about possible breakage when updating glib and not dbus-glib, bug #297483
+ if has_version dev-libs/dbus-glib; then
+ ewarn "If you experience a breakage after updating dev-libs/glib try"
+ ewarn "rebuilding dev-libs/dbus-glib"
+ fi
+}
diff --git a/dev-libs/glib/glib-2.28.8-r1.ebuild b/dev-libs/glib/glib-2.28.8-r1.ebuild
new file mode 100644
index 0000000..dfa7b9d
--- /dev/null
+++ b/dev-libs/glib/glib-2.28.8-r1.ebuild
@@ -0,0 +1,203 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-libs/glib/glib-2.28.8.ebuild,v 1.2 2011/06/08 17:47:44 pacho Exp $
+
+EAPI="3"
+PYTHON_DEPEND="2"
+
+inherit autotools gnome.org libtool eutils flag-o-matic pax-utils python virtualx
+
+DESCRIPTION="The GLib library of C routines"
+HOMEPAGE="http://www.gtk.org/"
+SRC_URI="${SRC_URI}
+ http://pkgconfig.freedesktop.org/releases/pkg-config-0.26.tar.gz" # pkg.m4 for eautoreconf
+
+LICENSE="LGPL-2"
+SLOT="2"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~sparc-fbsd ~x86-fbsd"
+IUSE="debug doc fam +introspection selinux +static-libs test xattr utouch"
+
+RDEPEND="virtual/libiconv
+ sys-libs/zlib
+ xattr? ( sys-apps/attr )
+ fam? ( virtual/fam )"
+DEPEND="${RDEPEND}
+ >=sys-devel/gettext-0.11
+ >=dev-util/gtk-doc-am-1.13
+ doc? (
+ >=dev-libs/libxslt-1.0
+ >=dev-util/gtk-doc-1.13
+ ~app-text/docbook-xml-dtd-4.1.2 )
+ test? ( dev-util/pkgconfig
+ >=sys-apps/dbus-1.2.14 )
+ !<dev-util/gtk-doc-1.15-r2"
+PDEPEND="introspection? ( dev-libs/gobject-introspection )
+ !<gnome-base/gvfs-1.6.4-r990" # Earlier versions do not work with glib
+
+# XXX: Consider adding test? ( sys-devel/gdb ); assert-msg-test tries to use it
+
+pkg_setup() {
+ python_set_active_version 2
+}
+
+src_prepare() {
+ mv -vf "${WORKDIR}"/pkg-config-*/pkg.m4 "${WORKDIR}"/ || die
+
+ if use ia64 ; then
+ # Only apply for < 4.1
+ local major=$(gcc-major-version)
+ local minor=$(gcc-minor-version)
+ if (( major < 4 || ( major == 4 && minor == 0 ) )); then
+ epatch "${FILESDIR}/glib-2.10.3-ia64-atomic-ops.patch"
+ fi
+ fi
+
+ # Don't fail gio tests when ran without userpriv, upstream bug 552912
+ # This is only a temporary workaround, remove as soon as possible
+ epatch "${FILESDIR}/${PN}-2.18.1-workaround-gio-test-failure-without-userpriv.patch"
+
+ # Fix gmodule issues on fbsd; bug #184301
+ epatch "${FILESDIR}"/${PN}-2.12.12-fbsd.patch
+
+ # Don't check for python, hence removing the build-time python dep.
+ # We remove the gdb python scripts in src_install due to bug 291328
+ epatch "${FILESDIR}/${PN}-2.25-punt-python-check.patch"
+
+ # Fix test failure when upgrading from 2.22 to 2.24, upstream bug 621368
+ epatch "${FILESDIR}/${PN}-2.24-assert-test-failure.patch"
+
+ # Do not try to remove files on live filesystem, upstream bug #619274
+ sed 's:^\(.*"/desktop-app-info/delete".*\):/*\1*/:' \
+ -i "${S}"/gio/tests/desktop-app-info.c || die "sed failed"
+
+ # Disable failing tests, upstream bug #???
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-locale-sensitive-test.patch"
+ epatch "${FILESDIR}/${PN}-2.26.0-disable-volumemonitor-broken-test.patch"
+
+ if use utouch; then
+ epatch "${FILESDIR}/${PN}-2.28.2-gio_launch_handler.patch"
+ fi
+
+ # Disable tests requiring dev-util/desktop-file-utils when not installed, bug #286629
+ if ! has_version dev-util/desktop-file-utils ; then
+ ewarn "Some tests will be skipped due dev-util/desktop-file-utils not being present on your system,"
+ ewarn "think on installing it to get these tests run."
+ sed -i -e "/appinfo\/associations/d" gio/tests/appinfo.c || die
+ sed -i -e "/desktop-app-info\/default/d" gio/tests/desktop-app-info.c || die
+ sed -i -e "/desktop-app-info\/fallback/d" gio/tests/desktop-app-info.c || die
+ sed -i -e "/desktop-app-info\/lastused/d" gio/tests/desktop-app-info.c || die
+ fi
+
+ # Disable tests requiring dev-python/dbus-python, bug #349236
+ if ! has_version dev-python/dbus-python ; then
+ ewarn "Some tests will be skipped due dev-python/dbus-python not being present on your system,"
+ ewarn "think on installing it to get these tests run."
+ sed -i -e "/connection\/filter/d" gio/tests/gdbus-connection.c || die
+ sed -i -e "/connection\/large_message/d" gio/tests/gdbus-connection-slow.c || die
+ sed -i -e "/gdbus\/proxy/d" gio/tests/gdbus-proxy.c || die
+ sed -i -e "/gdbus\/bus-watch-name/d" gio/tests/gdbus-names.c || die
+ sed -i -e "/gdbus\/proxy-well-known-name/d" gio/tests/gdbus-proxy-well-known-name.c || die
+ sed -i -e "/gdbus\/introspection-parser/d" gio/tests/gdbus-introspection.c || die
+ sed -i -e "/gdbus\/method-calls-in-thread/d" gio/tests/gdbus-threading.c || die
+ fi
+
+ if ! use test; then
+ # don't waste time building tests
+ sed 's/^\(SUBDIRS =.*\)tests\(.*\)$/\1\2/' -i Makefile.am Makefile.in \
+ || die "sed failed"
+ fi
+
+ # Needed for the punt-python-check patch, disabling timeout test
+ # Also needed to prevent croscompile failures, see bug #267603
+ AT_M4DIR="${WORKDIR}" eautoreconf
+
+ [[ ${CHOST} == *-freebsd* ]] && elibtoolize
+
+ epunt_cxx
+}
+
+src_configure() {
+ local myconf
+
+ # Building with --disable-debug highly unrecommended. It will build glib in
+ # an unusable form as it disables some commonly used API. Please do not
+ # convert this to the use_enable form, as it results in a broken build.
+ # -- compnerd (3/27/06)
+ use debug && myconf="--enable-debug"
+
+ # Always use internal libpcre, bug #254659
+ econf ${myconf} \
+ $(use_enable xattr) \
+ $(use_enable doc man) \
+ $(use_enable doc gtk-doc) \
+ $(use_enable fam) \
+ $(use_enable selinux) \
+ $(use_enable static-libs static) \
+ --enable-regex \
+ --with-pcre=internal \
+ --with-threads=posix \
+ --disable-dtrace \
+ --disable-systemtap
+}
+
+src_install() {
+ local f
+ emake DESTDIR="${D}" install || die "Installation failed"
+
+ # Do not install charset.alias even if generated, leave it to libiconv
+ rm -f "${ED}/usr/lib/charset.alias"
+
+ # Don't install gdb python macros, bug 291328
+ rm -rf "${ED}/usr/share/gdb/" "${ED}/usr/share/glib-2.0/gdb/"
+
+ dodoc AUTHORS ChangeLog* NEWS* README || die "dodoc failed"
+
+ insinto /usr/share/bash-completion
+ for f in gdbus gsettings; do
+ newins "${ED}/etc/bash_completion.d/${f}-bash-completion.sh" ${f} || die
+ done
+ rm -rf "${ED}/etc"
+}
+
+src_test() {
+ unset DBUS_SESSION_BUS_ADDRESS
+ export XDG_CONFIG_DIRS=/etc/xdg
+ export XDG_DATA_DIRS=/usr/local/share:/usr/share
+ export G_DBUS_COOKIE_SHA1_KEYRING_DIR="${T}/temp"
+ export XDG_DATA_HOME="${T}"
+ unset GSETTINGS_BACKEND # bug 352451
+
+ # Related test is a bit nitpicking
+ mkdir "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+ chmod 0700 "$G_DBUS_COOKIE_SHA1_KEYRING_DIR"
+
+ # Hardened: gdb needs this, bug #338891
+ if host-is-pax ; then
+ pax-mark -mr "${S}"/tests/.libs/assert-msg-test \
+ || die "Hardened adjustment failed"
+ fi
+
+ # Need X for dbus-launch session X11 initialization
+ Xemake check || die "tests failed"
+}
+
+pkg_preinst() {
+ # Only give the introspection message if:
+ # * The user has it enabled
+ # * Has glib already installed
+ # * Previous version was different from new version
+ if use introspection && has_version "${CATEGORY}/${PN}"; then
+ if ! has_version "=${CATEGORY}/${PF}"; then
+ ewarn "You must rebuild gobject-introspection so that the installed"
+ ewarn "typelibs and girs are regenerated for the new APIs in glib"
+ fi
+ fi
+}
+
+pkg_postinst() {
+ # Inform users about possible breakage when updating glib and not dbus-glib, bug #297483
+ if has_version dev-libs/dbus-glib; then
+ ewarn "If you experience a breakage after updating dev-libs/glib try"
+ ewarn "rebuilding dev-libs/dbus-glib"
+ fi
+}
diff --git a/dev-libs/glib/metadata.xml b/dev-libs/glib/metadata.xml
new file mode 100644
index 0000000..8b8529b
--- /dev/null
+++ b/dev-libs/glib/metadata.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+ <herd>gnome</herd>
+ <use>
+ <flag name="introspection">Use <pkg>dev-libs/gobject-introspection</pkg>
+ for introspection</flag>
+ <flag name="utouch">Compile with support for utouch</flag>
+ </use>
+</pkgmetadata>
diff --git a/dev-util/editje/Manifest b/dev-util/editje/Manifest
new file mode 100644
index 0000000..0c7776c
--- /dev/null
+++ b/dev-util/editje/Manifest
@@ -0,0 +1 @@
+EBUILD editje-9999.ebuild 339 RMD160 30887fbccd14faaf177e7458b5b5dd16b79a38b7 SHA1 2eddc18bbb7d5006d17eefc4ebd3332667d523a6 SHA256 258188ca2daf31267f83d63a6ac318b5374f004da1d27fff0e6382cadf616460
diff --git a/dev-util/editje/editje-9999.ebuild b/dev-util/editje/editje-9999.ebuild
new file mode 100644
index 0000000..f90b88b
--- /dev/null
+++ b/dev-util/editje/editje-9999.ebuild
@@ -0,0 +1,14 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit enlightenment
+
+DESCRIPTION="edje viewer based on elementary"
+
+DEPEND="dev-libs/eina
+ dev-python/python-elementary
+ dev-python/python-ecore
+ dev-python/python-evas
+ dev-python/python-edje
+ x11-wm/enlightenment"
diff --git a/net-wireless/rt3572usb/Manifest b/net-wireless/rt3572usb/Manifest
new file mode 100644
index 0000000..3fc0e3a
--- /dev/null
+++ b/net-wireless/rt3572usb/Manifest
@@ -0,0 +1,7 @@
+AUX rt3572usb-2.5.0.0-Makefile.patch 397 RMD160 42e13b71b5f93040e0c3a561b51e9bfa85b7412f SHA1 53e52ffee6dfd9592bf78c2a49f244f35960121d SHA256 5640e0a84a0ffecc65d801e41cdf29f88b368a7704d37bb1c77ceabf6eac6a80
+AUX rt3572usb-2.5.0.0-config.mk.patch 429 RMD160 61abdb5e2ee5dd41006b110e1faba703bae3b134 SHA1 fcc4dd7eb3ff2c68f8f6765965c59bf92ade9730 SHA256 7c9dc3d3c366eaad6e0fe1d2823d338a064008b1881859e7e639013550fc86a4
+AUX rt3572usb-2.5.0.0-nodebug.patch 363 RMD160 6bfab715d2242cac1529f199395512cbf05d6160 SHA1 04bbb9cf513d3178e7d3e9e7adf125476d33fa92 SHA256 96629c68efc49fd995e7ebe4aa873c571efa77da585a78c5f34b72c9c259c1f7
+AUX rt3572usb-2.5.0.0-rt_linux.h.patch 976 RMD160 6c975dd83b9104c5825f81504df9a3160ad32b41 SHA1 ee56f759ca42aad9a39a4a1f77e7bda0b80999a5 SHA256 4ab45c5c890c9456efa0d6ef8f1e0b2d48685104fdd409faf4eaefd1af94f3cb
+AUX rt3572usb-2.5.0.0-rtusb_dev_id.c.patch 802 RMD160 2ba778506f384dfdf4fe645d0a4e4bf4e1fc7a4f SHA1 4a109a0bf2d4ca4a7ee96e2c39f386b446a1aea8 SHA256 19476840e2f11e6b110aaf873ebe37f5efe0416acc6f1320bc0c6d936923894a
+DIST 2011_0427_RT3572_Linux_STA_v2.5.0.0.DPO.tar 4341760 RMD160 517d541382743364a2acb01de5e908926acae818 SHA1 c8c961c6f48b38a5b325ceb018d328a44f3f2089 SHA256 fae608567e3ae7cc5db853dc89e0b81d15a408528531f7f700dfbf2468d06982
+EBUILD rt3572usb-2.5.0.0.ebuild 1853 RMD160 b94568dbf4d7d8e241e4e79a80867b3be718adb5 SHA1 c50a76479be735aede86778969a2d32dda1941a8 SHA256 0b37b3fc11646c0cb78010b55dc57e6a79e301ec55b6b5309adc8e39098ca51c
diff --git a/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-Makefile.patch b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-Makefile.patch
new file mode 100644
index 0000000..20e94ab
--- /dev/null
+++ b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-Makefile.patch
@@ -0,0 +1,11 @@
+--- a/Makefile 2011-04-27 04:22:21.000000000 +0200
++++ b/Makefile 2010-02-14 19:18:23.000000000 +0100
+@@ -117,7 +117,7 @@
+
+ ifeq ($(PLATFORM),PC)
+ # Linux 2.6
+-LINUX_SRC = /lib/modules/$(shell uname -r)/build
++LINUX_SRC = /usr/src/linux
+ # Linux 2.4 Change to your local setting
+ #LINUX_SRC = /usr/src/linux-2.4
+ LINUX_SRC_MODULE = /lib/modules/$(shell uname -r)/kernel/drivers/net/wireless/
diff --git a/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-config.mk.patch b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-config.mk.patch
new file mode 100644
index 0000000..251b293
--- /dev/null
+++ b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-config.mk.patch
@@ -0,0 +1,15 @@
+--- a/os/linux/config.mk 2009-12-04 06:00:21.000000000 +0100
++++ b/os/linux/config.mk 2010-02-14 19:32:50.000000000 +0100
+@@ -8,10 +8,10 @@
+ HAS_XLINK=n
+
+ # Support Wpa_Supplicant
+-HAS_WPA_SUPPLICANT=n
++HAS_WPA_SUPPLICANT=y
+
+ # Support Native WpaSupplicant for Network Maganger
+-HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=n
++HAS_NATIVE_WPA_SUPPLICANT_SUPPORT=y
+
+ #Support Net interface block while Tx-Sw queue full
+ HAS_BLOCK_NET_IF=n
diff --git a/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-nodebug.patch b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-nodebug.patch
new file mode 100644
index 0000000..363f001
--- /dev/null
+++ b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-nodebug.patch
@@ -0,0 +1,11 @@
+--- RT3572_LinuxSTA_V2.3.0.0-orig/os/linux/config.mk 2009-08-13 10:54:04.000000000 +0300
++++ RT3572_LinuxSTA_V2.3.0.0/os/linux/config.mk 2009-09-23 22:23:13.000000000 +0300
+@@ -81,7 +81,7 @@
+ # config for STA mode
+
+ ifeq ($(RT28xx_MODE),STA)
+-WFLAGS += -DCONFIG_STA_SUPPORT -DDBG
++WFLAGS += -DCONFIG_STA_SUPPORT
+
+ ifeq ($(HAS_XLINK),y)
+ WFLAGS += -DXLINK_SUPPORT
diff --git a/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rt_linux.h.patch b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rt_linux.h.patch
new file mode 100644
index 0000000..e2729c7
--- /dev/null
+++ b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rt_linux.h.patch
@@ -0,0 +1,13 @@
+--- 2010_0915_RT3572_Linux_STA_v2.4.0.2.orig/include/os/rt_linux.h 2010-09-15 06:59:22.000000000 +0200
++++ 2010_0915_RT3572_Linux_STA_v2.4.0.2/include/os/rt_linux.h 2010-10-27 22:21:54.721136478 +0200
+@@ -1074,8 +1074,8 @@
+ #define RT28XX_PUT_DEVICE usb_put_dev
+ #define RTUSB_ALLOC_URB(iso) usb_alloc_urb(iso, GFP_ATOMIC)
+ #define RTUSB_SUBMIT_URB(pUrb) usb_submit_urb(pUrb, GFP_ATOMIC)
+-#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_buffer_alloc(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
+-#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_buffer_free(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
++#define RTUSB_URB_ALLOC_BUFFER(pUsb_Dev, BufSize, pDma_addr) usb_alloc_coherent(pUsb_Dev, BufSize, GFP_ATOMIC, pDma_addr)
++#define RTUSB_URB_FREE_BUFFER(pUsb_Dev, BufSize, pTransferBuf, Dma_addr) usb_free_coherent(pUsb_Dev, BufSize, pTransferBuf, Dma_addr)
+ #else
+
+ #define RT28XX_PUT_DEVICE
diff --git a/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch
new file mode 100644
index 0000000..929bb7f
--- /dev/null
+++ b/net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch
@@ -0,0 +1,19 @@
+--- a/common/rtusb_dev_id.c 2009-12-22 08:12:39.000000000 +0100
++++ b/common/rtusb_dev_id.c 2010-02-14 18:01:00.000000000 +0100
+@@ -106,6 +106,7 @@
+ {USB_DEVICE(0x7392,0x7717)},
+ {USB_DEVICE(0x1737,0x0070)}, /* Linksys WUSB100 */
+ {USB_DEVICE(0x1737,0x0071)}, /* Linksys WUSB600N */
++ {USB_DEVICE(0x1737,0x0077)}, /* Linksys WUSB54GC */
+ {USB_DEVICE(0x0411,0x00e8)}, /* Buffalo WLI-UC-G300N*/
+ {USB_DEVICE(0x050d,0x815c)}, /* Belkin F5D8053 */
+ {USB_DEVICE(0x100D,0x9031)}, /* Motorola 2770 */
+@@ -121,6 +122,7 @@
+ {USB_DEVICE(0x1690,0x0744)}, /* 3572 */
+ {USB_DEVICE(0x5A57,0x0284)}, /* Zinwell 3572 */
+ {USB_DEVICE(0x167B,0x4001)}, /* 3572 */
++ {USB_DEVICE(0x1737,0x0079)}, /* WUSB600N ver2 */
+ {USB_DEVICE(0x0930,0x0A07)}, /* TOSHIBA */
+ #endif /* RT35xx */
+ { }/* Terminating entry */
+
diff --git a/net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild b/net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild
new file mode 100644
index 0000000..af095af
--- /dev/null
+++ b/net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild
@@ -0,0 +1,74 @@
+## Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+inherit eutils linux-mod
+
+DESCRIPTION="Driver for the RaLink RT3572 USB wireless chipsets"
+HOMEPAGE="http://www.ralinktech.com/support.php?s=2"
+LICENSE="GPL-2"
+
+RESTRICT="bindist fetch mirror"
+
+MY_P="2011_0427_RT3572_Linux_STA"
+MY_SUFFIX="DPO"
+
+SRC_URI="${MY_P}_v${PV}.${MY_SUFFIX}.tar"
+
+KEYWORDS="-* ~amd64 x86"
+IUSE="debug"
+SLOT="0"
+
+DEPEND=""
+RDEPEND="net-wireless/wireless-tools"
+
+S="${WORKDIR}/${MY_P}_v${PV}.DPO"
+MODULE_NAMES="rt3572sta(net:${S}:${S}/os/linux)"
+BUILD_TARGETS=" "
+MODULESD_RT3572STA_ALIASES=('ra? rt3572sta')
+MODULESD_RT3572STA_ADDITIONS=('blacklist rt2800usb')
+
+CONFIG_CHECK="WIRELESS_EXT"
+ERROR_WIRELESS_EXT="${P} requires support for Wireless LAN drivers (non-hamradio) & Wireless Extensions (CONFIG_WIRELESS_EXT)."
+
+
+pkg_nofetch() {
+ elog "Please download the tar.bz2 source named:"
+ elog "RT3572USB version 2.5.0.0 from:"
+ elog "http://www.ralinktech.com/support.php?s=2"
+ elog "Then put the file in ${DISTDIR}/${SRC_URI}"
+}
+
+src_compile() {
+ epatch ${FILESDIR}/${P}-Makefile.patch
+ epatch ${FILESDIR}/${P}-config.mk.patch
+ epatch ${FILESDIR}/${P}-rtusb_dev_id.c.patch
+ use debug || epatch ${FILESDIR}/${P}-nodebug.patch
+
+ linux-mod_src_compile
+}
+
+src_install() {
+ linux-mod_src_install
+
+ dodoc README_STA iwpriv_usage.txt
+ insinto /etc/Wireless/RT2870STA
+ insopts -m 0600
+ doins RT2870STA.dat
+ doins RT2870STACard.dat
+ insinto /$(get_libdir)/firmware
+ insopts -m 0644
+ doins common/rt2870.bin
+}
+
+pkg_postinst() {
+ linux-mod_pkg_postinst
+
+ einfo
+ einfo "Thanks to RaLink for releasing open drivers!"
+ einfo
+ einfo "The staging 'rt2800usb' kernel driver has been auto blacklisted."
+ einfo "If you want to use it again, blacklist this driver ('rt3572sta')"
+ einfo "and allow the 'rt2800usb' one."
+ einfo
+}
diff --git a/x11-apps/ccv-bin/Manifest b/x11-apps/ccv-bin/Manifest
new file mode 100644
index 0000000..52b775c
--- /dev/null
+++ b/x11-apps/ccv-bin/Manifest
@@ -0,0 +1,3 @@
+DIST ccv-1.4-lin-32-bin.tar.gz 4446215 RMD160 fbd5e14fda6dfa74b9212ae4502d38507d29f74d SHA1 b4e87be6bb78769443351172e47055cc42431371 SHA256 4fededd637ed6e07c1c13008d35ea796fdcfa4b660f83a231384bb4584442930
+DIST ccv-1.4.0-lin-64-bin.tar.gz 6546794 RMD160 f8d090ccbefbbc1ee12059d973811bb5062b7d61 SHA1 5dffb631fc3a9548dca6fb1d863c1cf8a312f3cd SHA256 88dc14dfa0cf981468c68d9b9dabddbcad1edf9deac9c886373f262591a2a6fd
+EBUILD ccv-bin-1.4.0.ebuild 979 RMD160 64923bf2f0fdf7d76629eb516ebc90ca48c390e3 SHA1 0d77c0cea43043b1f2a76579503019d5abe6e4ba SHA256 34b4a4e83cf33daf9775d1867582ed7432d80667b76c8f0cf8d6068781162bfb
diff --git a/x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild b/x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild
new file mode 100644
index 0000000..4051a0f
--- /dev/null
+++ b/x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild
@@ -0,0 +1,54 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header:
+
+EAPI=2
+
+inherit eutils
+
+DESCRIPTION=""
+HOMEPAGE="http://http://nuicode.com/projects/ccv"
+SRC_URI="amd64? ( http://nuicode.com/attachments/download/186/ccv-1.4.0-lin-64-bin.tar.gz )
+ x86? ( http://nuicode.com/attachments/download/184/ccv-1.4-lin-32-bin.tar.gz
+ )"
+
+LICENSE="LGPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE=""
+RESTRICT="mirror"
+
+DEPEND=""
+
+RDEPEND=""
+
+#S=${WORKDIR}
+
+src_unpack() {
+ unpack "${A}"
+
+ EXTRACT_DIR=${WORKDIR}
+
+ if use amd64 ; then
+ EXTRACT_DIR=${WORKDIR}/ccv-1.4.0-lin-64-bin
+ fi
+
+ if use x86 ; then
+ EXTRACT_DIR=${WORKDIR}/ccv-1.4.lin-bin
+ fi
+
+ mv ${EXTRACT_DIR}/* ${WORKDIR}
+
+ rmdir ${EXTRACT_DIR}
+}
+
+src_install() {
+ insinto /opt/ccv
+
+ doins -r * || die
+
+ fperms 0755 /opt/ccv/clickToLaunchApp.sh
+ fperms 0755 /opt/ccv/Community_Core_Vision/clickToLaunchApp.sh
+ fperms 0755 /opt/ccv/Community_Core_Vision/Community_Core_Vision
+}
+
diff --git a/x11-apps/ginn/Manifest b/x11-apps/ginn/Manifest
new file mode 100644
index 0000000..49c8d34
--- /dev/null
+++ b/x11-apps/ginn/Manifest
@@ -0,0 +1,2 @@
+DIST ginn-0.2.4.tar.gz 310648 RMD160 f32c016d9edfa19173ce7e3a3a2fc1294b22351b SHA1 68027da2f37ce8c0794931265364321440440324 SHA256 44e64f81ade40fa8b094b69a51ad80fcc1c69407486cecd6b4e27a6aa91c9745
+EBUILD ginn-0.2.4.ebuild 541 RMD160 630e482ebd597d55ca44860f64f953276f1ee446 SHA1 9323198ec29e04753fd443d777da84e43e064958 SHA256 ae60e49e3fa7d746a731030a2441ba816c35772fa5f120ee140beef339ea8f2d
diff --git a/x11-apps/ginn/ginn-0.2.4.ebuild b/x11-apps/ginn/ginn-0.2.4.ebuild
new file mode 100644
index 0000000..44a73ca
--- /dev/null
+++ b/x11-apps/ginn/ginn-0.2.4.ebuild
@@ -0,0 +1,27 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+DESCRIPTION="Gesture Injector: No-GEIS, No-Toolkits"
+SRC_URI="http://launchpad.net/ginn/0.x/${PV}/+download/ginn-${PV}.tar.gz"
+HOMEPAGE="http://launchpad.net/canonical-multitouch/ginn"
+KEYWORDS="~x86 ~amd64"
+SLOT="0"
+LICENSE="LGPL-3"
+IUSE=""
+
+RDEPEND=""
+DEPEND="${RDEPEND}
+ x11-libs/utouch-geis
+ x11-libs/bamf
+ "
+
+src_compile() {
+ econf
+ emake || die
+}
+
+src_install() {
+ emake DESTDIR="${D}" install || die
+
+}
diff --git a/x11-base/xorg-server/Manifest b/x11-base/xorg-server/Manifest
new file mode 100644
index 0000000..78fb8d2
--- /dev/null
+++ b/x11-base/xorg-server/Manifest
@@ -0,0 +1,25 @@
+AUX diff 1314 RMD160 4e6315e4672e82c2bbe7c07edc5c88ede05400ca SHA1 878bf857b98ae5ba6c15bdee92ca20168930f65d SHA256 0489dfe46dab5d9a04a666683dcebef7a9d99cc3b93abd481adfd225c1d3f563
+AUX xdm-setup.initd-1 339 RMD160 dd3f50da114627d2be776b41a0d7d967ebbff477 SHA1 d86813f810aab72b81a72c298c2d230554d8e82e SHA256 018bc6acc70c708d8e3935617b8da2b84a3f5502a4db4c4731c2eaea7d3f04c0
+AUX xdm.confd-3 853 RMD160 363cd18f760650923e16579bf55f661e93dad63b SHA1 0027b98f2aeb5c43219fa4f9b7d81a05101bec6f SHA256 00af0d957ff1b4f31c1aa4701d93a54080408548792deafac5414cbfa13b89ec
+AUX xdm.initd-3 5551 RMD160 7af6e239e3e75ea88a0766ef2f4976a8b5c51c95 SHA1 bd30222c7941d50fc0f62c5008a0e3b97e2d00e0 SHA256 8f1d35638559d12ed14e8cc2e26800e0ee9a10f14c7be912c834c73d12913601
+AUX xorg-server-1.10.2-xi2.patch 151994 RMD160 c3b23f7b01db5e50ae791a18588b781744efbe5f SHA1 84e9f899d7aeb1aa9a950ac170eb4e5fc83a777a SHA256 f711608e6de2dcb5e38db7d44ba0c0b441e37310f3f0faae75c3a61f84a7fdd1
+AUX xorg-server-1.9-nouveau-default.patch 916 RMD160 0ebdf0fb76364b7fd0c520c3a2f7cc2cc1a83446 SHA1 daddde0f4f4276e12b87354d2e6825ed5c74c6eb SHA256 a7ff421dd928e3025194279f9afb7cc033a896b3417abe339741e9c6ed4b54ea
+AUX xorg-server-disable-acpi.patch 663 RMD160 7074ca5276369b746ea7606a0795232aafe07c90 SHA1 d300a37dd2e0a8aa3965948c13f6995e6767841d SHA256 5b3cc7c8bea18fe3ba81851d2846d19ffd8fab9cdf5d8f3a274846847e734200
+AUX xorg-server-gestures-extension.patch 50539 RMD160 750aac5c86c9006fc02e3effc3dbf5d1814d4954 SHA1 7cea9924080d9ed89929af477281eddb0310155a SHA256 6b4ebcd5a5e69f8978b78aa1a7f4726f529484aaf3f469c9e9cb09362b229517
+AUX xorg-server-xf86CoordinatesToWindow.patch 2994 RMD160 7d14d4b1bac8dcf62e3933b56ada5b828ec8ac3f SHA1 26630051a63d1f34ce4a43ec3468cf284f334f53 SHA256 c3c4fd465f7b8347f330edc3d7f4b36a1980bc6ed61ae774091e807d3aa40cd0
+AUX xorg-server-xi2.patch 151923 RMD160 94b61c9f1236ba5c4203e907ea4fa4afce8846ef SHA1 84411cef3919aa7ca3189e1b253240ef5f24be1c SHA256 89a3e0620af22d539dcdfe058ced8f49848a2461a1066e021bc204433b09fe8c
+AUX xorg-sets.conf 199 RMD160 33815115b6e8b8360af4f0778b0e2c5fb1a9aaee SHA1 b5a2fd01a97558fa909c67f510d8a59b55e20f57 SHA256 1201d0337ac69d9715f4454a86dfb8a7bd1ae6f4c2578042fc08f283a997597c
+DIST xorg-server-1.10.0.901.tar.bz2 5343036 RMD160 923af37a2e84f6e4f2d031fb2c72005379f9bf9d SHA1 0cb588134929302f3b062a7f202422d63ceea8b0 SHA256 de18f52c35fc3d3f18c7e905296f9de5ac42dc71e4e01da9ae8e154a78c7771c
+DIST xorg-server-1.10.0.902.tar.bz2 5347404 RMD160 962665666368ff2a749e80aa3dbee2385c40fb4a SHA1 7d44c57735c321fefd2b58f8917f51a95a829886 SHA256 994ab87bb0cc9b56203e01e3294fddd502a96d074139496ea4ffc03c95b41b42
+DIST xorg-server-1.10.1.901.tar.bz2 5333795 RMD160 a20397a1cbdae631ed0235b1a157650859dfa139 SHA1 06003baabf05dbcaf9c5eddfe3d1b74bfa797daf SHA256 b7d775891e7e7fc3001763cf5727995b81bf07b72e12d9d41db282fe625298e6
+DIST xorg-server-1.10.1.tar.bz2 5344169 RMD160 f0333f67f8226c21bfad395bb3ee72e6d10784f6 SHA1 59ada4c9a59f7f1eb4b68c359e9cd58272aa4809 SHA256 143c7c3d7d4428352e1153dffa34fd64af391f72d30b2a03e911e54e36f00b5d
+DIST xorg-server-1.10.2.tar.bz2 5334473 RMD160 3d1ad6b236772ebe0400a69a03b9093bb210fd4b SHA1 fd831b3c6297d1a68830c602d767752d87b9ca54 SHA256 65264f6640568b9db8d738aec1ddd036c3ae21b7ba05b98d006759d11a72792c
+DIST xorg-server-1.10.3.tar.bz2 5338354 RMD160 dfa59ac6d3f3f7fd059e6f92cead352845e08228 SHA1 1699be5c0edeca553cfa3ee6caa228483465136b SHA256 05ec05fbc8ec336127071db38cfb61c618e43b720edbd8d51d171c0cd359e290
+EBUILD xorg-server-1.10.0.901-r1.ebuild 7468 RMD160 1ba24286737bbd786dd9f0374a34e466a27b2d89 SHA1 900417293a95a20ae0ccb5de1dc5b0f82ac1d8d7 SHA256 dfdae8ea718430170aac89a3b0258c5f133bb2c790768d1af98c754d870ea848
+EBUILD xorg-server-1.10.0.902-r1.ebuild 7478 RMD160 44a339ca7f765082db7eddd2d4f56e205b7ef892 SHA1 45dd41487e6781da98ceb8ec900249679390b704 SHA256 489bfe1731cc7fd3f27219cf4dfc54d1f73d093e9a3fa0e1217a04c5cbb4ff49
+EBUILD xorg-server-1.10.1-r1.ebuild 7478 RMD160 44a339ca7f765082db7eddd2d4f56e205b7ef892 SHA1 45dd41487e6781da98ceb8ec900249679390b704 SHA256 489bfe1731cc7fd3f27219cf4dfc54d1f73d093e9a3fa0e1217a04c5cbb4ff49
+EBUILD xorg-server-1.10.1.901-r1.ebuild 7079 RMD160 ac0f9f268114cd762f03de6c4e4722998a54bfc5 SHA1 16a14f1709492655f07fd6f2bee82b495f20ac02 SHA256 b28679893fd1e4adc4d5918f939c6c7e736ed2b4462d5576be165918b3fff356
+EBUILD xorg-server-1.10.1.ebuild 7285 RMD160 be4ef109bc4283fc1eb95fddfb91470c7cca3a16 SHA1 5c1e089c125930a977f78bb9510ec8522e421f05 SHA256 d359e216185b19e56de4338b5ae2b7bd5d5936dac594f035694f3b95a122a287
+EBUILD xorg-server-1.10.2-r1.ebuild 7119 RMD160 018d5084b72ab1d675d88b32e35027c6cf2f4b76 SHA1 d1820c2c41018a396834fa15655d5c39dd01f94a SHA256 ac45ed8ec1a34c7d0f93ad68ca497dd5b026d0cbfc23dff7cc40178175231ad9
+EBUILD xorg-server-1.10.3-r1.ebuild 7211 RMD160 e0419eea946584f04ee647aeaa69df71a98bcad3 SHA1 97cf885bfe8507683c6a941e846cd744ccb54f67 SHA256 91b3ca4c7e710d50a43567bd4f4de17f5aaaac8ec7df470639b3795c2a5cf741
+MISC metadata.xml 493 RMD160 ec65f5d2366b47e4af3b5c3878067dfd60b56fc1 SHA1 b2035802eabc77fccfaf65c495289a0b8057bf86 SHA256 88cefe886a81d725df9c137d15ac51ae6b05a225f52f13b478fa48e10e71fdff
diff --git a/x11-base/xorg-server/files/diff b/x11-base/xorg-server/files/diff
new file mode 100644
index 0000000..54a4c02
--- /dev/null
+++ b/x11-base/xorg-server/files/diff
@@ -0,0 +1,26 @@
+diff --git a/x11-base/xorg-server/files/xorg-server-xi2.patch b/x11-base/xorg-server/files/xorg-server-xi2.patch
+index ed4b7b4..31648c6 100644
+--- a/x11-base/xorg-server/files/xorg-server-xi2.patch
++++ b/x11-base/xorg-server/files/xorg-server-xi2.patch
+@@ -4296,17 +4296,18 @@ Index: b/test/input.c
+ g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
+ g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
+ g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
+-@@ -1216,7 +1375,9 @@
++@@ -1397,6 +1397,11 @@
+ g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
+ g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
+ g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
+--
+++
+ + g_test_add_func("/dix/input/touch-create", touch_create);
+ + g_test_add_func("/dix/input/touch-find-point", touch_find_point);
+ + g_test_add_func("/dix/input/touch-finish", touch_finish);
+++
++ g_test_add_func("/dix/input/valuator-alloc", dix_valuator_alloc);
+
+ return g_test_run();
+- }
+ Index: b/test/xi2/protocol-eventconvert.c
+ ===================================================================
+ --- a/test/xi2/protocol-eventconvert.c 2011-02-28 16:57:00.000000000 +1100
diff --git a/x11-base/xorg-server/files/xdm-setup.initd-1 b/x11-base/xorg-server/files/xdm-setup.initd-1
new file mode 100644
index 0000000..6ed3922
--- /dev/null
+++ b/x11-base/xorg-server/files/xdm-setup.initd-1
@@ -0,0 +1,14 @@
+#!/sbin/runscript
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-apps/xinit/files/xdm-setup.initd-1,v 1.5 2009/09/24 17:07:56 williamh Exp $
+
+depend() {
+ need localmount
+}
+
+start() {
+ if get_bootparam "nox" ; then
+ touch /etc/.noxdm
+ fi
+}
diff --git a/x11-base/xorg-server/files/xdm.confd-3 b/x11-base/xorg-server/files/xdm.confd-3
new file mode 100644
index 0000000..9c560bb
--- /dev/null
+++ b/x11-base/xorg-server/files/xdm.confd-3
@@ -0,0 +1,16 @@
+# We always try and start X on a static VT. The various DMs normally default
+# to using VT7. If you wish to use the xdm init script, then you should ensure
+# that the VT checked is the same VT your DM wants to use. We do this check to
+# ensure that you haven't accidentally configured something to run on the VT
+# in your /etc/inittab file so that you don't get a dead keyboard.
+CHECKVT=7
+
+# What display manager do you use ? [ xdm | gdm | kdm | kdm-4.3 | gpe | entrance ]
+# NOTE: If this is set in /etc/rc.conf, that setting will override this one.
+#
+# KDE-specific note:
+# - If you are using kdeprefix go with "kdm-4.Y", e.g. "kdm-4.3".
+# You can find possible versions by looking at the directories in /usr/kde/.
+# - Else, if you are using KDE 3 enter "kdm-3.5"
+# - Else, if you are using KDE 4 enter "kdm" without a version
+DISPLAYMANAGER="xdm" \ No newline at end of file
diff --git a/x11-base/xorg-server/files/xdm.initd-3 b/x11-base/xorg-server/files/xdm.initd-3
new file mode 100755
index 0000000..993af2f
--- /dev/null
+++ b/x11-base/xorg-server/files/xdm.initd-3
@@ -0,0 +1,213 @@
+#!/sbin/runscript
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License, v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/files/xdm.initd-3,v 1.2 2011/01/22 15:30:07 lxnay Exp $
+
+# This is here to serve as a note to myself, and future developers.
+#
+# Any Display manager (gdm,kdm,xdm) has the following problem: if
+# it is started before any getty, and no vt is specified, it will
+# usually run on vt2. When the getty on vt2 then starts, and the
+# DM is already started, the getty will take control of the keyboard,
+# leaving us with a "dead" keyboard.
+#
+# Resolution: add the following line to /etc/inittab
+#
+# x:a:once:/etc/X11/startDM.sh
+#
+# and have /etc/X11/startDM.sh start the DM in daemon mode if
+# a lock is present (with the info of what DM should be started),
+# else just fall through.
+#
+# How this basically works, is the "a" runlevel is a additional
+# runlevel that you can use to fork processes with init, but the
+# runlevel never gets changed to this runlevel. Along with the "a"
+# runlevel, the "once" key word means that startDM.sh will only be
+# run when we specify it to run, thus eliminating respawning
+# startDM.sh when "xdm" is not added to the default runlevel, as was
+# done previously.
+#
+# This script then just calls "telinit a", and init will run
+# /etc/X11/startDM.sh after the current runlevel completes (this
+# script should only be added to the actual runlevel the user is
+# using).
+#
+# Martin Schlemmer
+# aka Azarah
+# 04 March 2002
+
+depend() {
+ need localmount xdm-setup
+
+ # this should start as early as possible
+ # we can't do 'before *' as that breaks it
+ # (#139824) Start after ypbind and autofs for network authentication
+ # (#145219 #180163) Could use lirc mouse as input device
+ # (#70689 comment #92) Start after consolefont to avoid display corruption
+ # (#291269) Start after quota, since some dm need readable home
+ after bootmisc consolefont modules netmount
+ after readahead-list ypbind autofs openvpn gpm lircmd
+ after quota
+ before alsasound
+
+ # Start before X
+ use consolekit xfs
+}
+
+setup_dm() {
+ local MY_XDM
+
+ MY_XDM=$(echo "${DISPLAYMANAGER}" | tr '[:upper:]' '[:lower:]')
+
+ # Load our root path from profile.env
+ # Needed for kdm
+ PATH=${PATH}:$(. /etc/profile.env; echo "${ROOTPATH}")
+
+ NAME=
+ case "${MY_XDM}" in
+ kdm|kde)
+ EXE="$(which kdm)"
+ PIDFILE=/var/run/kdm.pid
+ ;;
+ kdm-*)
+ EXE="/usr/kde/${MY_XDM#kdm-}/bin/kdm"
+ PIDFILE=/var/run/kdm.pid
+ ;;
+ entrance*)
+ EXE=/usr/sbin/entranced
+ PIDFILE=/var/lib/entranced.pid
+ ;;
+ gdm|gnome)
+ EXE=/usr/bin/gdm
+ [ "${RC_UNAME}" != "Linux" ] && NAME=gdm-binary
+ PIDFILE=/var/run/gdm.pid
+ ;;
+ wdm)
+ EXE=/usr/bin/wdm
+ PIDFILE=
+ ;;
+ gpe)
+ EXE=/usr/bin/gpe-dm
+ PIDFILE=/var/run/gpe-dm.pid
+ ;;
+ lxdm)
+ EXE=/usr/sbin/lxdm-binary
+ PIDFILE=/var/run/lxdm.pid
+ START_STOP_ARGS="--background"
+ ;;
+ *)
+ # first find out if there is such executable
+ EXE="$(which ${MY_XDM} 2>/dev/null)"
+ PIDFILE="/var/run/${MY_XDM}.pid"
+
+ # warn user that he is doing sick things if the exe was not found
+ if [ -z "${EXE}" ]; then
+ echo "ERROR: Your XDM value is invalid."
+ echo " No ${MY_XDM} executable could be found on your system."
+ fi
+ ;;
+ esac
+
+ if ! [ -x "${EXE}" ]; then
+ EXE=/usr/bin/xdm
+ PIDFILE=/var/run/xdm.pid
+ if ! [ -x "/usr/bin/xdm" ]; then
+ echo "ERROR: Please set your DISPLAYMANAGER variable in /etc/conf.d/xdm,"
+ echo " or install x11-apps/xdm package"
+ eend 255
+ fi
+ fi
+}
+
+# Check to see if something is defined on our VT
+vtstatic() {
+ if [ -e /etc/inittab ] ; then
+ grep -Eq "^[^#]+.*\<tty$1\>" /etc/inittab
+ elif [ -e /etc/ttys ] ; then
+ grep -q "^ttyv$(($1 - 1))" /etc/ttys
+ else
+ return 1
+ fi
+}
+
+start() {
+ local EXE NAME PIDFILE
+ setup_dm
+
+ if [ -f /etc/.noxdm ]; then
+ einfo "Skipping ${EXE##*/}, /etc/.noxdm found or \"nox\" bootparam passed."
+ rm /etc/.noxdm
+ return 0
+ fi
+
+ ebegin "Setting up ${EXE##*/}"
+
+ # save the prefered DM
+ save_options "service" "${EXE}"
+ save_options "name" "${NAME}"
+ save_options "pidfile" "${PIDFILE}"
+ save_options "start_stop_args" "${START_STOP_ARGS}"
+
+ if [ -n "${CHECKVT-y}" ] ; then
+ if vtstatic "${CHECKVT:-7}" ; then
+ if [ -x /sbin/telinit ] && [ "${SOFTLEVEL}" != "BOOT" ] && [ "${RC_SOFTLEVEL}" != "BOOT" ]; then
+ ewarn "Something is already defined on VT ${CHECKVT:-7}, will start X later"
+ telinit a >/dev/null 2>&1
+ return 0
+ else
+ eerror "Something is already defined on VT ${CHECKVT:-7}, not starting"
+ return 1
+ fi
+ fi
+ fi
+
+ /etc/X11/startDM.sh
+ eend 0
+}
+
+stop() {
+ local curvt retval
+
+ retval=0
+ if [ -t 0 ]; then
+ if type fgconsole >/dev/null 2>&1; then
+ curvt=$(fgconsole 2>/dev/null)
+ else
+ curvt=$(tty)
+ case "${curvt}" in
+ /dev/ttyv[0-9]*) curvt=${curvt#/dev/ttyv} ;;
+ *) curvt= ;;
+ esac
+ fi
+ fi
+ local myexe myname mypidfile myservice
+ myexe=$(get_options "service")
+ myname=$(get_options "name")
+ mypidfile=$(get_options "pidfile")
+ myservice=${myexe##*/}
+
+ [ -z "${myexe}" ] && return 0
+
+ ebegin "Stopping ${myservice}"
+
+ if start-stop-daemon --quiet --test --stop --exec "${myexe}"; then
+ start-stop-daemon --stop --exec "${myexe}" --retry TERM/5/TERM/5 \
+ ${mypidfile:+--pidfile} ${mypidfile} \
+ ${myname:+--name} ${myname}
+ retval=${?}
+ fi
+
+ # switch back to original vt
+ if [ -n "${curvt}" ]; then
+ if type chvt >/dev/null 2>&1; then
+ chvt "${curvt}"
+ else
+ vidcontrol -s "$((curvt + 1))"
+ fi
+ fi
+
+ eend ${retval} "Error stopping ${myservice}"
+ return ${retval}
+}
+
+# vim: set ts=4 :
diff --git a/x11-base/xorg-server/files/xorg-server-1.10.2-xi2.patch b/x11-base/xorg-server/files/xorg-server-1.10.2-xi2.patch
new file mode 100644
index 0000000..31648c6
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-1.10.2-xi2.patch
@@ -0,0 +1,4569 @@
+
+Index: b/Xi/allowev.c
+===================================================================
+--- a/Xi/allowev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/allowev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -125,5 +125,24 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
++
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (thisdev->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = thisdev->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return Success;
+ }
+Index: b/Xi/exevents.c
+===================================================================
+--- a/Xi/exevents.c 2011-03-09 11:19:12.126789337 +1100
++++ b/Xi/exevents.c 2011-03-09 13:11:48.093384404 +1100
+@@ -44,6 +44,31 @@
+
+ ********************************************************/
+
++/*
++ * Copyright © 2010 Collabora Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Author: Daniel Stone <daniel@fooishbar.org>
++ */
++
+ /********************************************************************
+ *
+ * Routines to register and initialize extension input devices.
+@@ -77,6 +102,9 @@
+ #include "xiquerydevice.h" /* For List*Info */
+ #include "eventconvert.h"
+ #include "eventstr.h"
++#include "xserver-properties.h"
++#include "inpututils.h"
++#include "mi.h"
+
+ #include <X11/extensions/XKBproto.h>
+ #include "xkbsrv.h"
+@@ -127,6 +155,20 @@
+ return FALSE;
+ }
+
++Bool
++IsTouchEvent(InternalEvent* event)
++{
++ switch(event->any.type)
++ {
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ return TRUE;
++ default:
++ return FALSE;
++ }
++}
++
+ /**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+@@ -725,6 +767,46 @@
+ XISendDeviceChangedEvent(slave, device, dce);
+ }
+
++#define DEFAULT 0
++#define DONT_PROCESS 1
++int
++ReleaseButton(DeviceIntPtr device, int button)
++{
++ ButtonClassPtr b = device->button;
++ int i;
++
++ if (IsMaster(device)) {
++ DeviceIntPtr sd;
++
++ /*
++ * Leave the button down if any slave has the
++ * button still down. Note that this depends on the
++ * event being delivered through the slave first
++ */
++ for (sd = inputInfo.devices; sd; sd = sd->next) {
++ if (IsMaster(sd) || sd->u.master != device)
++ continue;
++ if (!sd->button)
++ continue;
++ for (i = 1; i <= sd->button->numButtons; i++)
++ if (sd->button->map[i] == button &&
++ button_is_down(sd, i, BUTTON_PROCESSED))
++ return DONT_PROCESS;
++ }
++ }
++ set_button_up(device, button, BUTTON_PROCESSED);
++ if (device->valuator)
++ device->valuator->motionHintWindow = NullWindow;
++ if (!b->map[button])
++ return DONT_PROCESS;
++ if (b->buttonsDown >= 1 && !--b->buttonsDown)
++ b->motionMask = 0;
++ if (b->map[button] <= 5)
++ b->state &= ~((Button1Mask >> 1) << b->map[button]);
++
++ return DEFAULT;
++}
++
+ /**
+ * Update the device state according to the data in the event.
+ *
+@@ -732,8 +814,6 @@
+ * DEFAULT ... process as normal
+ * DONT_PROCESS ... return immediately from caller
+ */
+-#define DEFAULT 0
+-#define DONT_PROCESS 1
+ int
+ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
+ {
+@@ -857,34 +937,9 @@
+
+ if (!button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+- if (IsMaster(device)) {
+- DeviceIntPtr sd;
+
+- /*
+- * Leave the button down if any slave has the
+- * button still down. Note that this depends on the
+- * event being delivered through the slave first
+- */
+- for (sd = inputInfo.devices; sd; sd = sd->next) {
+- if (IsMaster(sd) || sd->u.master != device)
+- continue;
+- if (!sd->button)
+- continue;
+- for (i = 1; i <= sd->button->numButtons; i++)
+- if (sd->button->map[i] == key &&
+- button_is_down(sd, i, BUTTON_PROCESSED))
+- return DONT_PROCESS;
+- }
+- }
+- set_button_up(device, key, BUTTON_PROCESSED);
+- if (device->valuator)
+- device->valuator->motionHintWindow = NullWindow;
+- if (!b->map[key])
++ if (ReleaseButton(device, key) == DONT_PROCESS)
+ return DONT_PROCESS;
+- if (b->buttonsDown >= 1 && !--b->buttonsDown)
+- b->motionMask = 0;
+- if (b->map[key] <= 5)
+- b->state &= ~((Button1Mask >> 1) << b->map[key]);
+
+ /* Add state and motionMask to the filter for this event */
+ mask = DevicePointerMotionMask | b->state | b->motionMask;
+@@ -926,6 +981,939 @@
+ }
+
+ /**
++ * Add a touch client to the list of clients for the touch point. Return TRUE
++ * if the caller should stop processing touch clients.
++ */
++static Bool
++AddTouchClient(TouchPointInfoPtr ti, int client_id, WindowPtr window,
++ TouchClientType type, DeviceIntPtr dev, DeviceIntPtr sourcedev,
++ GrabPtr grab)
++{
++ TouchClientPtr client;
++
++ ti->active_clients++;
++ if (ti->active_clients > ti->num_clients)
++ {
++ int num_clients = ti->num_clients ? ti->num_clients * 2 : 2;
++
++ TouchClientPtr tmp;
++ tmp = realloc(ti->clients, num_clients * sizeof(TouchClientRec));
++
++ if (tmp)
++ {
++ ti->clients = tmp;
++ ti->num_clients = num_clients;
++ } else {
++ LogMessage(X_ERROR, "failed to reallocate touch clients\n");
++ return TRUE;
++ }
++ }
++
++ client = &ti->clients[ti->active_clients - 1];
++ client->client = clients[client_id];
++ client->window = window;
++ client->type = type;
++ client->device = dev;
++ client->source = sourcedev;
++ client->grab = grab;
++
++ return FALSE;
++}
++
++/**
++ * Ensure a list of clients for a touchpoint, constructing one for TouchBegin
++ * events. Returns TRUE if a touch client exists, FALSE if none.
++ */
++static Bool
++EnsureTouchClients(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
++ InternalEvent *ev)
++{
++ TouchClassPtr t = sourcedev->touch;
++ SpritePtr sprite = &ti->sprite;
++ DeviceIntPtr masterdev = sourcedev->u.master;
++ int i;
++
++ if (ev->any.type != ET_TouchBegin)
++ return (ti->active_clients > 0);
++
++ if (ti->active_clients > 0)
++ LogMessage(X_ERROR, "Getting touch clients for active touch\n");
++
++ /* Create sprite trace for the touchpoint */
++ if (t->mode == XIDirectTouch)
++ {
++ /* Focus immediately under the touchpoint in direct touch mode.
++ * XXX: Do we need to handle crossing screens here? */
++ sprite->spriteTrace[0] =
++ sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
++ XYToWindow(sprite, ev->device_event.root_x, ev->device_event.root_y);
++ }
++ else
++ {
++ WindowPtr *trace;
++ SpritePtr srcsprite;
++
++ /* Find and reuse an existing, physically active touch's sprite and
++ * touch client list if possible, else use the device's pointer sprite
++ * and generate a new list of touch clients. */
++ for (i = 0; i < t->num_touches; i++)
++ if (!t->touches[i].ddx_pending_finish &&
++ t->touches[i].active_clients > 0)
++ break;
++ if (i < t->num_touches) {
++ srcsprite = &t->touches[i].sprite;
++ ti->active_clients = t->touches[i].active_clients;
++
++ if (ti->active_clients > ti->num_clients)
++ {
++ TouchClientPtr tmp;
++
++ tmp = realloc(ti->clients,
++ ti->active_clients * sizeof(TouchClientRec));
++ if (!tmp)
++ {
++ ti->active_clients = 0;
++ ti->owner = -1;
++ return FALSE;
++ }
++ ti->clients = tmp;
++ ti->num_clients = ti->active_clients;
++ }
++ memcpy(ti->clients, t->touches[i].clients,
++ ti->active_clients * sizeof(TouchClientRec));
++ }
++ else if (sourcedev->spriteInfo->sprite)
++ srcsprite = sourcedev->spriteInfo->sprite;
++ else
++ return FALSE;
++
++ if (srcsprite->spriteTraceGood > sprite->spriteTraceSize)
++ {
++ trace = realloc(sprite->spriteTrace,
++ srcsprite->spriteTraceSize * sizeof(*trace));
++ if (!trace)
++ {
++ sprite->spriteTraceGood = 0;
++ ti->active_clients = 0;
++ ti->owner = -1;
++ return FALSE;
++ }
++ sprite->spriteTrace = trace;
++ sprite->spriteTraceSize = srcsprite->spriteTraceGood;
++ }
++ memcpy(sprite->spriteTrace, srcsprite->spriteTrace,
++ srcsprite->spriteTraceGood * sizeof(*trace));
++ sprite->spriteTraceGood = srcsprite->spriteTraceGood;
++
++ if (ti->active_clients)
++ return TRUE;
++ }
++
++ if (sprite->spriteTraceGood <= 0)
++ return FALSE;
++
++ /* Search for touch grab clients from root to child windows. */
++ for (i = 0; i < sprite->spriteTraceGood; i++)
++ {
++ WindowPtr win = sprite->spriteTrace[i];
++ GrabPtr grab;
++ InternalEvent ev;
++
++ ev.any.type = ET_TouchBegin;
++ if ((grab = CheckPassiveGrabsOnWindow(win, sourcedev, &ev, FALSE,
++ FALSE)))
++ {
++ if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB,
++ sourcedev, sourcedev, grab))
++ goto done;
++ continue;
++ }
++ if (masterdev &&
++ (grab = CheckPassiveGrabsOnWindow(win, masterdev, &ev, FALSE,
++ FALSE)))
++ {
++ if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB,
++ masterdev, sourcedev, grab))
++ goto done;
++ continue;
++ }
++ }
++
++ /* Search for one touch select client from child to root windows. */
++ for (i = sprite->spriteTraceGood - 1; i >= 0; i--)
++ {
++ WindowPtr win = sprite->spriteTrace[i];
++ OtherInputMasks *inputMasks = wOtherInputMasks(win);
++
++ /* Is anyone listening for unowned events on this window? */
++ if (inputMasks &&
++ (BitIsOn(inputMasks->xi2mask[XIAllDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputMasks->xi2mask[sourcedev->id],
++ XI_TouchUpdateUnowned) ||
++ (masterdev &&
++ (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputMasks->xi2mask[masterdev->id],
++ XI_TouchUpdateUnowned)))))
++ {
++ InputClientsPtr inputClients = inputMasks->inputClients;
++
++ /* Find the one client listening for unowned events. */
++ for (inputClients = inputMasks->inputClients;
++ inputClients;
++ inputClients = inputClients->next)
++ {
++ if (BitIsOn(inputClients->xi2mask[XIAllDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputClients->xi2mask[sourcedev->id],
++ XI_TouchUpdateUnowned))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource),
++ win, TOUCH_SELECT_UNOWNED, sourcedev,
++ sourcedev, NULL);
++ goto done;
++ }
++ else if (masterdev &&
++ (BitIsOn(inputClients->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputClients->xi2mask[masterdev->id],
++ XI_TouchUpdateUnowned)))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource),
++ win, TOUCH_SELECT_UNOWNED, masterdev,
++ sourcedev, NULL);
++ goto done;
++ }
++ }
++ }
++
++ /* Is anyone listening for only owned events on this window? */
++ if (inputMasks &&
++ (BitIsOn(inputMasks->xi2mask[XIAllDevices], XI_TouchUpdate) ||
++ BitIsOn(inputMasks->xi2mask[sourcedev->id], XI_TouchUpdate) ||
++ (masterdev &&
++ (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputMasks->xi2mask[masterdev->id],
++ XI_TouchUpdate)))))
++ {
++ InputClientsPtr inputClients = inputMasks->inputClients;
++
++ /* Find the one client listening for owned events. */
++ for (inputClients = inputMasks->inputClients;
++ inputClients;
++ inputClients = inputClients->next)
++ {
++ if (BitIsOn(inputClients->xi2mask[XIAllDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputClients->xi2mask[sourcedev->id],
++ XI_TouchUpdate))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource), win,
++ TOUCH_SELECT, sourcedev, sourcedev, NULL);
++ goto done;
++ }
++ else if (masterdev &&
++ (BitIsOn(inputClients->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputClients->xi2mask[masterdev->id],
++ XI_TouchUpdate)))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource), win,
++ TOUCH_SELECT, masterdev, sourcedev, NULL);
++ goto done;
++ }
++ }
++ }
++ }
++
++done:
++ return (ti->active_clients > 0);
++}
++
++/**
++ * Attempts to deliver a touch event to the given client.
++ */
++static Bool
++DeliverOneTouchEvent(TouchClientPtr client, TouchPointInfoPtr ti,
++ InternalEvent *ev)
++{
++ int err;
++ xEvent *xi2;
++ Mask filter;
++ Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
++
++ /* If we fail here, we're going to leave a client hanging. */
++ err = EventToXI2(ev, &xi2);
++ if (err != Success)
++ FatalError("[Xi] %s: XI2 conversion failed in DeliverOneTouchEvent"
++ " (%d)\n", client->device->name, err);
++
++ FixUpEventFromWindow(&ti->sprite, xi2, client->window, child, FALSE);
++ filter = GetEventFilter(client->device, xi2);
++ if (XaceHook(XACE_RECEIVE_ACCESS, client->client, client->window, xi2, 1)
++ != Success)
++ return FALSE;
++ err = TryClientEvents(client->client, client->device, xi2, 1, filter,
++ filter, NullGrab);
++ free(xi2);
++
++ /* Returning the value from TryClientEvents isn't useful, since all our
++ * resource-gone cleanups will update the delivery list anyway. */
++ return TRUE;
++}
++
++/**
++ * Deliver touch ownership event directly to client.
++ */
++int
++DeliverTouchOwnershipEvent(TouchClientPtr client, TouchPointInfoPtr ti)
++{
++ TouchOwnershipEvent event;
++
++ memset(&event, 0, sizeof(TouchOwnershipEvent));
++ event.header = ET_Internal;
++ event.type = ET_TouchOwnership;
++ event.length = sizeof(TouchOwnershipEvent);
++ event.time = GetTimeInMillis();
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++ event.touchid = ti->client_id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++
++ return 1;
++}
++
++/* Add the given event to the history for the touch point. */
++static void
++UpdateTouchHistory(TouchPointInfoPtr ti, InternalEvent *ev)
++{
++ /* Copy begin events off to the side. This prevents the ring buffer
++ overrunning and erasing the begin event. */
++ if (ev->any.type == ET_TouchBegin)
++ memcpy(ti->begin_event, ev, sizeof(InternalEvent));
++ else
++ {
++ memcpy(ti->next_history, ev, sizeof(InternalEvent));
++
++ ti->next_history++;
++ if (ti->next_history == ti->history + ti->history_size)
++ ti->next_history = ti->history;
++
++ /* If the ring overruns, advance the first pointer so we keep as many
++ events as possible. */
++ if (ti->next_history == ti->first_history)
++ {
++ ti->first_history++;
++ if (ti->first_history == ti->history + ti->history_size)
++ ti->first_history = ti->history;
++ }
++ }
++}
++
++/**
++ * Helper to get a static EventList for pointer emulation.
++ */
++static EventList *
++GetEvents(void)
++{
++ static EventList *events = NULL;
++
++ /* Allocate twice the maximum number of events for motion and button
++ * emulation. */
++ if (!events)
++ events = InitEventList(2 * GetMaximumEventsNum());
++
++ return events;
++}
++
++/* Helper function to set up touch pointer emulation. */
++static void
++SetTouchEmulationMask(InternalEvent *ev, ValuatorMask *mask, int x_axis,
++ int y_axis)
++{
++ valuator_mask_zero(mask);
++ if (BitIsOn(ev->device_event.valuators.mask, x_axis))
++ valuator_mask_set(mask, 0,
++ ev->device_event.valuators.data[x_axis]);
++ if (BitIsOn(ev->device_event.valuators.mask, y_axis))
++ valuator_mask_set(mask, 1,
++ ev->device_event.valuators.data[y_axis]);
++}
++
++/* Process touch emulation. */
++static void
++EmulateTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
++{
++ EventList *emulationEvents = GetEvents();
++ ValuatorMask mask;
++ InternalEvent mevent;
++ DeviceIntPtr master = dev->u.master;
++ enum EventType evtype = ev->any.type;
++ int nevents = 0;
++ int x_axis = dev->touch->x_axis;
++ int y_axis = dev->touch->y_axis;
++ int i;
++
++ /* Set the emulation touch for the device. Only one touch may be emulated
++ * at a time. */
++ if (dev->touch->emulate != ti)
++ return;
++
++ /* Emulate a normal event. */
++ SetTouchEmulationMask(ev, &mask, x_axis, y_axis);
++
++ if (evtype == ET_TouchBegin)
++ {
++ nevents = GetPointerEvents(emulationEvents, dev,
++ MotionNotify, 0, POINTER_ABSOLUTE, &mask);
++ nevents += GetPointerEvents(emulationEvents + nevents, dev,
++ ButtonPress, 1, POINTER_ABSOLUTE, &mask);
++ }
++ else if (evtype == ET_TouchMotion)
++ nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0,
++ POINTER_ABSOLUTE, &mask);
++ else if (evtype == ET_TouchEnd)
++ {
++ nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0,
++ POINTER_ABSOLUTE, &mask);
++ nevents += GetPointerEvents(emulationEvents + nevents, dev,
++ ButtonRelease, 1, POINTER_ABSOLUTE, &mask);
++ }
++
++ if (ti->emulate_pointer)
++ {
++ for (i = 0; i < nevents; i++)
++ {
++ InternalEvent *event = (InternalEvent *)((emulationEvents + i)->event);
++
++ event->device_event.flags |= XIPointerEmulated;
++ event->device_event.touchpoint = ev->device_event.touchpoint;
++
++ if (master)
++ {
++ master->u.lastSlave = dev;
++
++ CopyGetMasterEvent(dev, event, &mevent);
++
++ /* If a grab has been activated but no event has been handled
++ * yet, then the grab is a touch grab. Store the pointer
++ * emulation event for now, ready for replay when the touch grab
++ * is relinquished. */
++ if (master->deviceGrab.sync.state == FROZEN_NO_EVENT)
++ {
++ GrabInfoPtr grabinfo = &master->deviceGrab;
++
++ grabinfo->sync.state = FROZEN_WITH_EVENT;
++ if (!grabinfo->sync.event)
++ grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
++ *grabinfo->sync.event = event->device_event;
++ }
++ else
++ master->public.processInputProc(&mevent, master);
++ }
++ }
++ }
++
++ /* If there are touch clients on a pointer emulated touchpoint, send touch
++ * events through traditional device processing as well. */
++ if (master && ti->active_clients > 0 &&
++ (ev->any.type != ET_TouchEnd ||
++ (ti->clients[ti->active_clients - 1].type == TOUCH_SELECT ||
++ ti->clients[ti->active_clients - 1].type == TOUCH_SELECT_UNOWNED)))
++ {
++ ev->device_event.flags |= XIPointerEmulated;
++ master->u.lastSlave = dev;
++ CopyGetMasterEvent(dev, ev, &mevent);
++ master->process_touch = TRUE;
++ master->public.processInputProc(&mevent, master);
++ master->process_touch = FALSE;
++
++ /* If grabbed by an implicit touch grab from FindFirstGrab, release it
++ * now. */
++ if (master->deviceGrab.grab &&
++ master->deviceGrab.grab->type == ET_TouchBegin &&
++ master->deviceGrab.implicitGrab)
++ master->deviceGrab.DeactivateGrab(master);
++ }
++}
++
++#define ImplicitGrabMask (1 << 7)
++/**
++ * Find the first grab of a new touchpoint. Returns TRUE if a grab was found.
++ */
++static Bool
++FindFirstGrab(DeviceIntPtr dev, TouchPointInfoPtr ti)
++{
++ DeviceIntPtr master = dev->u.master;
++ InternalEvent p_event;
++ InternalEvent t_event;
++ GrabRec tempGrab;
++ int i, j;
++
++ p_event.any.type = ET_ButtonPress;
++ t_event.any.type = ET_TouchBegin;
++
++ j = ti->owner >= 0 ? ti->owner : 0;
++
++ for (i = 0; i < ti->sprite.spriteTraceGood; i++)
++ {
++ WindowPtr win = ti->sprite.spriteTrace[i];
++ TouchClientPtr client = &ti->clients[j];
++ GrabPtr grab;
++
++ /* If master pointer is already grabbed, bypass touch grabs above. */
++ if (ti->emulate_pointer && master->deviceGrab.grab)
++ {
++ if (win == master->deviceGrab.grab->window)
++ {
++ if (j >= ti->active_clients - 1)
++ {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ } else
++ ti->owner = j + 1;
++ return TRUE;
++ } else
++ goto next;
++ }
++
++ /* Check for a touch grab on this window. */
++ if (j < ti->active_clients && win == client->window &&
++ client->type == TOUCH_GRAB)
++ {
++ client->device->deviceGrab.ActivateGrab(client->device,
++ client->grab, currentTime,
++ TRUE);
++ ti->owner = j;
++ return TRUE;
++ }
++
++ if (!ti->emulate_pointer)
++ goto next;
++
++ /* Check for a passive pointer grab on this window. */
++ grab = CheckPassiveGrabsOnWindow(win, dev, &p_event, TRUE, FALSE);
++ if (grab)
++ return TRUE;
++ else if (master)
++ {
++ grab = CheckPassiveGrabsOnWindow(win, master, &p_event, TRUE,
++ FALSE);
++ if (grab)
++ return TRUE;
++ }
++
++next:
++ if (j < ti->active_clients && win == client->window)
++ j++;
++ }
++
++ /* Even when there's no grabbing clients, we need to sync events so we can
++ * properly check for touch vs pointer selection in DeliverDeviceEvents.
++ * Create a temporary implicit touch grab here, and deactivate it after
++ * enqueuing emulated pointer events. */
++ if (ti->emulate_pointer)
++ {
++ memset(&tempGrab, 0, sizeof(GrabRec));
++ tempGrab.next = NULL;
++ tempGrab.device = master;
++ tempGrab.resource = 0;
++ tempGrab.window = ti->sprite.spriteTrace[0];
++ tempGrab.ownerEvents = FALSE;
++ tempGrab.eventMask = 0;
++ tempGrab.keyboardMode = GrabModeAsync;
++ tempGrab.pointerMode = GrabModeSync;
++ tempGrab.confineTo = NullWindow;
++ tempGrab.cursor = NullCursor;
++ tempGrab.type = ET_TouchBegin;
++ tempGrab.grabtype = GRABTYPE_XI2;
++ tempGrab.deviceMask = 0;
++
++ master->deviceGrab.ActivateGrab(master, &tempGrab, currentTime,
++ TRUE | ImplicitGrabMask);
++ }
++
++ return FALSE;
++}
++
++void
++ProcessTouchOwnership(DeviceIntPtr dev, TouchPointInfoPtr ti, uint8_t reason,
++ Bool touch_grab)
++{
++ DeviceIntPtr sourcedev = ti->source;
++ DeviceIntPtr masterdev;
++
++ masterdev = dev->u.master;
++
++ if (reason == XITouchOwnerAccept)
++ {
++ TouchClientPtr client;
++ DeviceEvent event;
++ int i;
++
++ init_event(dev, &event, GetTimeInMillis());
++ event.type = ET_TouchEnd;
++ event.detail.touch = ti->client_id;
++ event.touchpoint = ti;
++
++ for (i = ti->owner + 1; i < ti->active_clients; i++)
++ {
++ client = &ti->clients[i];
++
++ if (client->type == TOUCH_GRAB ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ {
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++ }
++ }
++
++ if (!touch_grab)
++ {
++ ti->active_clients = 0;
++ ti->owner = -1;
++ RemoveTouchEventsFromQueue(masterdev, TRUE, FALSE);
++ return;
++ }
++
++ client = &ti->clients[ti->owner];
++ ti->active_clients = ti->owner + 1;
++ ti->accepted = TRUE;
++
++ RemoveTouchEventsFromQueue(masterdev, FALSE, FALSE);
++ RemoveTouchEventsFromQueue(masterdev, TRUE, FALSE);
++ ReleaseButton(masterdev, 1);
++
++ if (ti->emulate_pointer)
++ masterdev->deviceGrab.DeactivateGrab(masterdev);
++
++ ti->emulate_pointer = FALSE;
++
++ if (ti->pending_finish)
++ {
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++ EndTouchPoint(sourcedev, ti);
++ }
++ } else {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++ GrabPtr grab = masterdev->deviceGrab.grab;
++
++ if (touch_grab)
++ {
++ DeviceEvent event;
++
++ tc = &ti->clients[ti->owner];
++
++ init_event(tc->device, &event, GetTimeInMillis());
++ event.type = ET_TouchEnd;
++ event.detail.touch = ti->client_id;
++ event.deviceid = tc->device->id;
++ event.sourceid = tc->source->id;
++ event.touchpoint = ti;
++
++ DeliverOneTouchEvent(tc, ti, (InternalEvent *)&event);
++
++ ti->owner++;
++ }
++
++ if (ti->owner >= ti->active_clients)
++ {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ tc = NULL;
++ } else {
++ tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT && !ti->emulate_pointer)
++ {
++ InternalEvent *ev;
++ Bool ret;
++
++ /* Deliver the saved touch begin event. */
++ ret = DeliverOneTouchEvent(tc, ti, ti->begin_event);
++
++ /* Deliver all the touch motion events in the ring buffer. */
++ ev = ti->first_history;
++ while (ret && ev != ti->next_history)
++ {
++ ret = DeliverOneTouchEvent(tc, ti, ev);
++
++ if (ev->any.type == ET_TouchEnd)
++ {
++ ti->pending_finish = TRUE;
++ break;
++ }
++
++ ev++;
++ if (ev == ti->history + ti->history_size)
++ ev = ti->history;
++ }
++ } else if (tc->type == TOUCH_SELECT_UNOWNED &&
++ !ti->emulate_pointer) {
++ DeliverTouchOwnershipEvent(tc, ti);
++ }
++ }
++
++ if (ti->emulate_pointer)
++ {
++ if (ti->active_clients &&
++ ti->clients[ti->owner].type == TOUCH_SELECT_UNOWNED)
++ RemoveTouchEventsFromQueue(masterdev, TRUE, TRUE);
++
++ syncEvents.replayDev = masterdev;
++ if (touch_grab)
++ syncEvents.replayWin = grab->window->parent;
++ else
++ syncEvents.replayWin = grab->window;
++ masterdev->deviceGrab.DeactivateGrab(masterdev);
++ syncEvents.replayDev = NULL;
++ }
++
++ if (ti->pending_finish &&
++ (!tc || (tc->type == TOUCH_SELECT ||
++ tc->type == TOUCH_SELECT_UNOWNED)) &&
++ (!ti->emulate_pointer || !masterdev->deviceGrab.grab))
++ EndTouchPoint(sourcedev, ti);
++ }
++}
++
++/**
++ * Processes and delivers a TouchBegin, TouchMotion, or a TouchEnd event.
++ *
++ * Due to having rather different delivery semantics (see the Xi 2.1 protocol
++ * spec for more information), this implements its own grab and event-selection
++ * delivery logic.
++ */
++static void
++ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev)
++{
++ DeviceIntPtr masterdev = sourcedev->u.master;
++ TouchClassPtr t = sourcedev->touch;
++ TouchPointInfoPtr ti;
++ TouchClientPtr client;
++ uint32_t touchid;
++ int i;
++
++ /* We handle deliveries to MDs through the SD, rather than copying
++ * the event and processing it twice. */
++ if (IsMaster(sourcedev))
++ return;
++
++ if (!t)
++ return;
++
++ /* If we hit 50% utilization of touches, double the number of touch
++ * frames. */
++ if (t->active_touches > t->num_touches / 2)
++ {
++ void *tmp;
++
++ tmp = realloc(t->touches, (t->num_touches * 2) * sizeof(*t->touches));
++ if (tmp)
++ {
++ t->touches = tmp;
++ memset(t->touches + t->num_touches, 0,
++ t->num_touches * sizeof(*t->touches));
++
++ for (i = t->num_touches; i < t->num_touches * 2; i++)
++ {
++ if (!InitTouchPoint(t, i))
++ {
++ LogMessage(X_ERROR,
++ "%s: failed to initialize new touchpoint %d\n",
++ sourcedev->name, i);
++ break;
++ }
++ }
++ t->num_touches = i;
++
++ LogMessage(X_INFO, "%s: reallocated %d touches\n", sourcedev->name,
++ t->num_touches);
++ } else
++ LogMessage(X_ERROR, "%s: failed to allocate more touches (%d)\n",
++ sourcedev->name, t->num_touches * 2);
++ }
++
++ touchid = ev->device_event.detail.touch;
++ ti = FindTouchPointByClientID(sourcedev, touchid);
++ if (!ti)
++ {
++ DebugF("[Xi] %s: Received event for inactive touchpoint %d\n",
++ sourcedev->name, touchid);
++ return;
++ }
++
++ /* Set the emulation touch for a direct touch device. Only one touch may be
++ * emulated per master device at a time. */
++ if (ev->any.type == ET_TouchBegin && t->mode == XIDirectTouch &&
++ masterdev && !masterdev->emulate_dev)
++ {
++ ti->emulate_pointer = TRUE;
++ sourcedev->touch->emulate = ti;
++ masterdev->emulate_dev = sourcedev;
++ }
++
++ /* Make sure we have a valid list of touch clients for event delivery. */
++ if (!EnsureTouchClients(sourcedev, ti, ev))
++ {
++ /* No touch clients, so only attempt to emulate a pointer. */
++ EmulateTouchEvents(sourcedev, ti, ev);
++
++ if (ti->active && ev->any.type == ET_TouchEnd)
++ EndTouchPoint(sourcedev, ti);
++
++ return;
++ }
++
++ if (ev->any.type == ET_TouchBegin)
++ {
++ if (ti->emulate_pointer)
++ {
++ if (!FindFirstGrab(sourcedev, ti))
++ {
++ if (ti->clients[0].type == TOUCH_SELECT)
++ {
++ ti->owner = 0;
++ EmulateTouchEvents(sourcedev, ti, ev);
++ return;
++ }
++ else if (ti->clients[0].type == TOUCH_SELECT_UNOWNED)
++ {
++ ti->owner = 0;
++ client = &ti->clients[ti->owner];
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++ DeliverOneTouchEvent(client, ti, ev);
++ EmulateTouchEvents(sourcedev, ti, ev);
++ return;
++ }
++ } else if (ti->owner < 0)
++ /* Pointer grab found, check touch grab first when replayed. */
++ ev->device_event.check_grab = TRUE;
++ }
++ else
++ ti->owner = 0;
++ }
++
++ /* Update touch history for non-emulated touches. Emulated touch history is
++ * maintained in syncEvents queue. */
++ if (!ti->emulate_pointer && !ti->accepted)
++ UpdateTouchHistory(ti, ev);
++
++ EmulateTouchEvents(sourcedev, ti, ev);
++
++ if (ti->owner >= 0)
++ client = &ti->clients[ti->owner];
++
++ /* Handle the special case where we are ending an emulated touch during an
++ * active pointer grab. */
++ if (ti == t->emulate && masterdev && masterdev->deviceGrab.grab &&
++ !masterdev->deviceGrab.fromPassiveGrab &&
++ !masterdev->deviceGrab.implicitGrab && ev->any.type == ET_TouchEnd)
++ {
++ InternalEvent mevent;
++
++ ev->device_event.flags |= XIPointerEmulated;
++
++ masterdev->u.lastSlave = sourcedev;
++ CopyGetMasterEvent(sourcedev, ev, &mevent);
++ masterdev->process_touch = TRUE;
++ masterdev->public.processInputProc(&mevent, masterdev);
++ masterdev->process_touch = FALSE;
++ if (client && (client->type == TOUCH_SELECT ||
++ client->type == TOUCH_SELECT_UNOWNED))
++ EndTouchPoint(sourcedev, ti);
++ }
++
++ /* If a touch is owned, deliver to the owning client. */
++ if (ti->owner >= 0 &&
++ (ti != t->emulate || ti->accepted ||
++ ((!client->grab && !sourcedev->deviceGrab.grab &&
++ !masterdev->deviceGrab.grab) ||
++ (client->grab && sourcedev->deviceGrab.grab &&
++ GrabMatchesSecond(sourcedev->deviceGrab.grab, client->grab, FALSE)) ||
++ (client->grab && masterdev && masterdev->deviceGrab.grab &&
++ GrabMatchesSecond(masterdev->deviceGrab.grab, client->grab, FALSE)))))
++ {
++ if (client->type == TOUCH_GRAB)
++ {
++ /* Mutate end event to a pending finish event for further
++ * clients. */
++ if (ev->any.type == ET_TouchEnd && !ti->accepted)
++ {
++ ev->any.type = ET_TouchMotion;
++ ev->device_event.flags |= XITouchPendingEnd;
++ ti->pending_finish = TRUE;
++ }
++
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, ev);
++ if (ev->any.type == ET_TouchBegin)
++ DeliverTouchOwnershipEvent(client, ti);
++ else if (ev->any.type == ET_TouchEnd)
++ EndTouchPoint(sourcedev, ti);
++ }
++ else if (client->type == TOUCH_SELECT ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ {
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ if (ev->any.type != ET_TouchEnd)
++ DeliverOneTouchEvent(client, ti, ev);
++
++ else if (client->type == TOUCH_SELECT_UNOWNED &&
++ ev->any.type == ET_TouchBegin)
++ DeliverTouchOwnershipEvent(client, ti);
++
++ /* An ending emulated touchpoint must release the primary mouse
++ * button. */
++ if (ev->any.type == ET_TouchEnd)
++ {
++ if (ti == sourcedev->touch->emulate)
++ ReleaseButton(masterdev, 1);
++ else
++ DeliverOneTouchEvent(client, ti, ev);
++
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++ }
++
++ /* Deliver to non-owners. */
++ if (ev->any.type == ET_TouchMotion)
++ ev->any.type = ET_TouchMotionUnowned;
++ else if (ev->any.type == ET_TouchEnd)
++ {
++ ev->any.type = ET_TouchMotionUnowned;
++ ev->device_event.flags |= XITouchPendingEnd;
++ ti->pending_finish = TRUE;
++ }
++
++ for (i = ti->owner + 1; i < ti->active_clients; i++)
++ {
++ TouchClientPtr client = &ti->clients[i];
++
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ if (client->type == TOUCH_GRAB ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ DeliverOneTouchEvent(client, ti, ev);
++ }
++}
++
++/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+@@ -954,6 +1942,33 @@
+ {
+ ProcessRawEvent(&ev->raw_event, device);
+ return;
++ } else if ((!syncEvents.playingEvents && !device->process_touch) &&
++ (ev->any.type == ET_TouchBegin ||
++ ev->any.type == ET_TouchMotion ||
++ ev->any.type == ET_TouchMotionUnowned ||
++ ev->any.type == ET_TouchOwnership ||
++ ev->any.type == ET_TouchEnd))
++ {
++ /* The first time through we figure out what to do with the touch.
++ * Further times through (playingEvents or process_touch), we process
++ * the event like any other. */
++ ProcessTouchEvent(ev, device);
++ return;
++ }
++
++ /* Ownership events are smaller than device events, so we must handle them
++ * first or we'll corrupt the heap. */
++ if (ev->any.type == ET_TouchOwnership)
++ {
++ grab = device->deviceGrab.grab;
++
++ if (grab)
++ DeliverGrabbedEvent(ev, device, FALSE);
++ else
++ DeliverDeviceEvents(GetSpriteWindow(device), ev, NullGrab,
++ NullWindow, device);
++
++ return;
+ }
+
+ if (IsPointerDevice(device))
+@@ -1152,6 +2167,50 @@
+ dev->proximity->in_proximity = FALSE;
+ }
+
++void
++InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
++ int maxval, int resolution)
++{
++ TouchAxisInfoPtr ax;
++
++ if (!dev || !dev->touch || minval > maxval)
++ return;
++ if (axnum >= dev->touch->num_axes)
++ return;
++
++ ax = dev->touch->axes + axnum;
++
++ ax->min_value = minval;
++ ax->max_value = maxval;
++ ax->resolution = resolution;
++ ax->label = label;
++
++ if (ax->label == XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X))
++ {
++ dev->touch->x_axis = axnum;
++ if (dev->touch->mode == XIDirectTouch &&
++ (!dev->valuator || dev->valuator->numAxes < 1 ||
++ dev->valuator->axes[0].min_value != minval ||
++ dev->valuator->axes[0].max_value != maxval ||
++ dev->valuator->axes[0].resolution != resolution))
++ LogMessage(X_WARNING, "Touch X valuator does not match pointer X "
++ "valuator, pointer emulation may be "
++ "incorrect\n");
++ }
++ else if (ax->label == XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y))
++ {
++ dev->touch->y_axis = axnum;
++ if (dev->touch->mode == XIDirectTouch &&
++ (!dev->valuator || dev->valuator->numAxes < 2 ||
++ dev->valuator->axes[1].min_value != minval ||
++ dev->valuator->axes[1].max_value != maxval ||
++ dev->valuator->axes[1].resolution != resolution))
++ LogMessage(X_WARNING, "Touch Y valuator does not match pointer Y "
++ "valuator, pointer emulation may be "
++ "incorrect\n");
++ }
++}
++
+ static void
+ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
+ ButtonClassPtr b, ValuatorClassPtr v, int first)
+@@ -1562,6 +2621,38 @@
+ return AddPassiveGrabToList(client, grab);
+ }
+
++/* Touch grab */
++int
++GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
++ GrabParameters *param, GrabMask *mask)
++{
++ WindowPtr pWin;
++ GrabPtr grab;
++ int rc;
++
++ rc = CheckGrabValues(client, param);
++ if (rc != Success)
++ return rc;
++
++ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
++ if (rc != Success)
++ return rc;
++ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixFreezeAccess);
++ if (rc != Success)
++ return rc;
++
++ /* Touch grabs are asynchronous in protocol, but we need to freeze the
++ * pointer device if a touch grab is activated for pointer emulation. */
++ param->other_devices_mode = GrabModeSync;
++
++ grab = CreateGrab(client->index, dev, mod_dev, pWin, GRABTYPE_XI2,
++ mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
++ if (!grab)
++ return BadAlloc;
++
++ return AddPassiveGrabToList(client, grab);
++}
++
+ int
+ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
+ Mask mask, Mask exclusivemasks)
+@@ -1695,10 +2786,65 @@
+ }
+ }
+
++static void
++RemoveTouchClient(DeviceIntPtr dev, TouchPointInfoPtr ti, int index)
++{
++ TouchClientPtr tc = &ti->clients[index];
++ int i;
++
++ if (index == ti->owner) {
++ if (tc->grab && dev->deviceGrab.grab &&
++ GrabMatchesSecond(tc->grab, dev->deviceGrab.grab,
++ FALSE))
++ ProcessTouchOwnership(dev, ti, XITouchOwnerRejectEnd, TRUE);
++ else {
++ ti->owner++;
++ if (ti->owner >= ti->active_clients) {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ }
++ }
++ return;
++ }
++
++ for (i = index; i < ti->active_clients - 1; i++)
++ memcpy(ti->clients + i, ti->clients + i + 1,
++ sizeof(TouchClientRec));
++ ti->active_clients--;
++}
++
++
+ int
+ InputClientGone(WindowPtr pWin, XID id)
+ {
+ InputClientsPtr other, prev;
++ DeviceIntPtr dev;
++
++ for (dev = inputInfo.devices; dev; dev = dev->next) {
++ TouchClassPtr t = dev->touch;
++ int i;
++
++ if (!t)
++ continue;
++
++ for (i = 0; i < t->num_touches; i++) {
++ TouchPointInfoPtr ti = &t->touches[i];
++ int j;
++
++ if (!ti->active || ti->active_clients == 0)
++ continue;
++
++ j = (ti->owner < 0) ? 0 : ti->owner;
++ while (j < ti->active_clients) {
++ TouchClientPtr tc = &ti->clients[j];
++
++ if (clients[CLIENT_ID(id)] == tc->client)
++ RemoveTouchClient(dev, ti, j);
++ else
++ j++;
++ }
++ }
++ }
+
+ if (!wOtherInputMasks(pWin))
+ return Success;
+@@ -1734,6 +2880,54 @@
+ FatalError("client not on device event list");
+ }
+
++/**
++ * Search for window in each touch trace for each device. Remove the window
++ * and all its subwindows from the trace when found. The initial window
++ * order is preserved.
++ */
++void WindowGone(WindowPtr win)
++{
++ DeviceIntPtr dev;
++
++ for (dev = inputInfo.devices; dev; dev = dev->next) {
++ TouchClassPtr t = dev->touch;
++ int i;
++
++ if (!t)
++ continue;
++
++ for (i = 0; i < t->num_touches; i++) {
++ SpritePtr sprite = &t->touches[i].sprite;
++ int j;
++
++ for (j = 0; j < sprite->spriteTraceGood; j++) {
++ if (sprite->spriteTrace[j] == win) {
++ sprite->spriteTraceGood = j;
++ break;
++ }
++ }
++ }
++
++ for (i = 0; i < t->num_touches; i++) {
++ TouchPointInfoPtr ti = &t->touches[i];
++ int j;
++
++ if (!ti->active || ti->active_clients == 0)
++ continue;
++
++ j = (ti->owner < 0) ? 0 : ti->owner;
++ while (j < ti->active_clients) {
++ TouchClientPtr tc = &ti->clients[j];
++
++ if (win == tc->window)
++ RemoveTouchClient(dev, ti, j);
++ else
++ j++;
++ }
++ }
++ }
++}
++
+ int
+ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
+ xEvent * ev, Mask mask, int count)
+Index: b/Xi/extinit.c
+===================================================================
+--- a/Xi/extinit.c 2011-02-28 16:57:00.000000000 +1100
++++ b/Xi/extinit.c 2011-03-09 13:11:48.093384404 +1100
+@@ -258,7 +258,8 @@
+ ProcXIChangeProperty, /* 57 */
+ ProcXIDeleteProperty, /* 58 */
+ ProcXIGetProperty, /* 59 */
+- ProcXIGetSelectedEvents /* 60 */
++ ProcXIGetSelectedEvents, /* 60 */
++ ProcXIAllowTouchEvents, /* 61 */
+ };
+
+ /* For swapped clients */
+@@ -323,7 +324,8 @@
+ SProcXIChangeProperty, /* 57 */
+ SProcXIDeleteProperty, /* 58 */
+ SProcXIGetProperty, /* 59 */
+- SProcXIGetSelectedEvents /* 60 */
++ SProcXIGetSelectedEvents, /* 60 */
++ SProcXIAllowTouchEvents, /* 61 */
+ };
+
+ /*****************************************************************
+@@ -854,6 +856,21 @@
+ swaps(&to->valuators_len, n);
+ }
+
++static void STouchOwnershipEvent(xXITouchOwnershipEvent *from,
++ xXITouchOwnershipEvent *to)
++{
++ char n;
++
++ *to = *from;
++ swaps(&to->sequenceNumber, n);
++ swapl(&to->length, n);
++ swaps(&to->evtype, n);
++ swaps(&to->deviceid, n);
++ swapl(&to->time, n);
++ swaps(&to->sourceid, n);
++ swapl(&to->touchid, n);
++ swapl(&to->flags, n);
++}
+
+ /** Event swapping function for XI2 events. */
+ void
+@@ -881,8 +898,16 @@
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
++ case XI_TouchBegin:
++ case XI_TouchUpdate:
++ case XI_TouchUpdateUnowned:
++ case XI_TouchEnd:
+ SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
+ break;
++ case XI_TouchOwnership:
++ STouchOwnershipEvent((xXITouchOwnershipEvent*)from,
++ (xXITouchOwnershipEvent*)to);
++ break;
+ case XI_RawMotion:
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+Index: b/Xi/xiallowev.c
+===================================================================
+--- a/Xi/xiallowev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiallowev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -35,11 +35,15 @@
+
+ #include "inputstr.h" /* DeviceIntPtr */
+ #include "windowstr.h" /* window structure */
++#include "eventstr.h"
++#include "mi.h"
+ #include <X11/extensions/XI2.h>
+ #include <X11/extensions/XI2proto.h>
+
+ #include "exglobals.h" /* BadDevice */
+ #include "xiallowev.h"
++#include "exevents.h"
++#include "dixgrabs.h"
+
+ int
+ SProcXIAllowEvents(ClientPtr client)
+@@ -98,6 +102,113 @@
+ ret = BadValue;
+ }
+
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (dev->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = dev->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return ret;
+ }
+
++int
++SProcXIAllowTouchEvents(ClientPtr client)
++{
++ char n;
++
++ REQUEST(xXIAllowTouchEventsReq);
++
++ swaps(&stuff->length, n);
++ swaps(&stuff->deviceid, n);
++ swapl(&stuff->touchid, n);
++
++ return ProcXIAllowTouchEvents(client);
++}
++
++int
++ProcXIAllowTouchEvents(ClientPtr client)
++{
++ DeviceIntPtr dev;
++ TouchClassPtr t;
++ TouchPointInfoPtr ti;
++ TouchClientPtr tc;
++ int ret;
++ EventList *events = InitEventList(GetMaximumEventsNum());
++
++ REQUEST(xXIAllowTouchEventsReq);
++ REQUEST_SIZE_MATCH(xXIAllowTouchEventsReq);
++
++ if (!events)
++ return BadAlloc;
++
++ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
++ if (ret != Success)
++ return ret;
++
++ if (!dev->touch)
++ {
++ client->errorValue = stuff->deviceid;
++ return BadDevice;
++ }
++
++ t = dev->touch;
++
++ ti = FindTouchPointByClientID(dev, stuff->touchid);
++ if (!ti)
++ {
++ client->errorValue = stuff->touchid;
++ return BadValue;
++ }
++
++ tc = &ti->clients[ti->owner];
++
++ if (client != tc->client || !tc->grab)
++ return BadAccess;
++
++ if (ti == t->emulate)
++ {
++ DeviceIntPtr master = dev->u.master;
++
++ if (!master || !master->deviceGrab.grab ||
++ !GrabMatchesSecond(master->deviceGrab.grab, tc->grab, FALSE))
++ return BadAccess;
++ }
++
++ if (stuff->mode & XITouchOwnerAccept)
++ {
++ if (stuff->mode & ~XITouchOwnerAccept)
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++ }
++ else if (stuff->mode & XITouchOwnerRejectEnd)
++ {
++ if (stuff->mode & ~XITouchOwnerRejectEnd)
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++ }
++ else
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++
++ ProcessTouchOwnership(dev, ti, stuff->mode, TRUE);
++
++ return Success;
++}
+Index: b/Xi/xiallowev.h
+===================================================================
+--- a/Xi/xiallowev.h 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiallowev.h 2011-03-09 13:11:48.093384404 +1100
+@@ -32,5 +32,7 @@
+
+ int ProcXIAllowEvents(ClientPtr client);
+ int SProcXIAllowEvents(ClientPtr client);
++int ProcXIAllowTouchEvents(ClientPtr client);
++int SProcXIAllowTouchEvents(ClientPtr client);
+
+ #endif /* XIALLOWEV_H */
+Index: b/Xi/xipassivegrab.c
+===================================================================
+--- a/Xi/xipassivegrab.c 2011-03-09 11:19:12.000000000 +1100
++++ b/Xi/xipassivegrab.c 2011-03-09 13:11:48.093384404 +1100
+@@ -105,19 +105,30 @@
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+- stuff->grab_type != XIGrabtypeFocusIn)
++ stuff->grab_type != XIGrabtypeFocusIn &&
++ stuff->grab_type != XIGrabtypeTouchBegin)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
++ stuff->grab_type == XIGrabtypeFocusIn ||
++ stuff->grab_type == XIGrabtypeTouchBegin) &&
++ stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
++ if (stuff->grab_type == XIGrabtypeTouchBegin &&
++ (stuff->grab_mode != GrabModeAsync ||
++ stuff->paired_device_mode != GrabModeAsync))
++ {
++ client->errorValue = GrabModeSync;
++ return BadValue;
++ }
++
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
+ stuff->mask_len * 4) != Success)
+ return BadValue;
+@@ -185,6 +196,9 @@
+ status = GrabWindow(client, dev, stuff->grab_type,
+ &param, &mask);
+ break;
++ case XIGrabtypeTouchBegin:
++ status = GrabTouch(client, dev, mod_dev, &param, &mask);
++ break;
+ }
+
+ if (status != GrabSuccess)
+Index: b/Xi/xiquerydevice.c
+===================================================================
+--- a/Xi/xiquerydevice.c 2011-03-09 11:19:12.000000000 +1100
++++ b/Xi/xiquerydevice.c 2011-03-09 13:11:48.093384404 +1100
+@@ -232,6 +232,12 @@
+ if (dev->valuator)
+ len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
+
++ if (dev->touch)
++ {
++ len += sizeof(xXITouchInfo);
++ len += sizeof(xXITouchValuatorInfo) * dev->touch->num_axes;
++ }
++
+ return len;
+ }
+
+@@ -373,6 +379,73 @@
+ swaps(&info->sourceid, n);
+ }
+
++/**
++ * List multitouch information
++ *
++ * @return The number of bytes written into info.
++ */
++int
++ListTouchInfo(DeviceIntPtr dev, xXITouchInfo *touch)
++{
++ touch->type = XITouchClass;
++ touch->length = sizeof(xXITouchInfo) >> 2;
++ touch->sourceid = dev->id;
++ touch->mode = dev->touch->mode;
++ touch->num_touches = dev->touch->num_touches;
++
++ return touch->length << 2;
++}
++
++static void
++SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo* touch)
++{
++ char n;
++ swaps(&touch->type, n);
++ swaps(&touch->length, n);
++ swaps(&touch->sourceid, n);
++}
++
++/**
++ * List multitouch axis information
++ *
++ * @return The number of bytes written into info.
++ */
++int
++ListTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val,
++ int axisnumber)
++{
++ TouchClassPtr t = dev->touch;
++
++ val->type = XITouchValuatorClass;
++ val->length = sizeof(xXITouchValuatorInfo) >> 2;
++ val->sourceid = dev->id;
++ val->number = axisnumber;
++ val->label = t->axes[axisnumber].label;
++ val->min.integral = t->axes[axisnumber].min_value;
++ val->min.frac = 0;
++ val->max.integral = t->axes[axisnumber].max_value;
++ val->max.frac = 0;
++ val->resolution = t->axes[axisnumber].resolution;
++
++ return val->length << 2;
++}
++
++static void
++SwapTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val)
++{
++ char n;
++ swaps(&val->type, n);
++ swaps(&val->length, n);
++ swaps(&val->sourceid, n);
++ swaps(&val->number, n);
++ swapl(&val->label, n);
++ swapl(&val->min.integral, n);
++ swapl(&val->min.frac, n);
++ swapl(&val->max.integral, n);
++ swapl(&val->max.frac, n);
++ swapl(&val->resolution, n);
++}
++
+ int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
+ {
+ DeviceIntPtr master = dev->u.master;
+@@ -462,6 +535,22 @@
+ total_len += len;
+ }
+
++ if (dev->touch)
++ {
++ (*nclasses)++;
++ len = ListTouchInfo(dev, (xXITouchInfo*)any);
++ any += len;
++ total_len += len;
++
++ for (i = 0; i < dev->touch->num_axes; i++)
++ {
++ (*nclasses)++;
++ len = ListTouchValuatorInfo(dev, (xXITouchValuatorInfo*)any, i);
++ any += len;
++ total_len += len;
++ }
++ }
++
+ return total_len;
+ }
+
+@@ -489,6 +578,12 @@
+ case XIValuatorClass:
+ SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
+ break;
++ case XITouchClass:
++ SwapTouchInfo(dev, (xXITouchInfo*)any);
++ break;
++ case XITouchValuatorClass:
++ SwapTouchValuatorInfo(dev, (xXITouchValuatorInfo*)any);
++ break;
+ }
+
+ any += len * 4;
+Index: b/Xi/xiquerydevice.h
+===================================================================
+--- a/Xi/xiquerydevice.h 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiquerydevice.h 2011-03-09 13:11:48.093384404 +1100
+@@ -44,4 +44,7 @@
+ int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info);
+ int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info,
+ int axisnumber, Bool reportState);
++int ListTouchInfo(DeviceIntPtr dev, xXITouchInfo* info);
++int ListTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val,
++ int axisnumber);
+ #endif /* QUERYDEV_H */
+Index: b/Xi/xiselectev.c
+===================================================================
+--- a/Xi/xiselectev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiselectev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -152,6 +152,60 @@
+ }
+ }
+
++ if (evmask->mask_len >= 1)
++ {
++ unsigned char *bits = (unsigned char*)&evmask[1];
++
++ /* Check validity of touch selections */
++ if (BitIsOn(bits, XI_TouchBegin) ||
++ BitIsOn(bits, XI_TouchUpdate) ||
++ BitIsOn(bits, XI_TouchEnd))
++ {
++ /* All three touch events must be selected at once */
++ if (!BitIsOn(bits, XI_TouchBegin) ||
++ !BitIsOn(bits, XI_TouchUpdate) ||
++ !BitIsOn(bits, XI_TouchEnd))
++ {
++ client->errorValue = XI_TouchBegin;
++ return BadValue;
++ }
++
++ /* Unowned and ownership events must both be selected */
++ if ((BitIsOn(bits, XI_TouchUpdateUnowned) ||
++ BitIsOn(bits, XI_TouchOwnership)) &&
++ (!BitIsOn(bits, XI_TouchUpdateUnowned) ||
++ !BitIsOn(bits, XI_TouchOwnership)))
++ {
++ client->errorValue = XI_TouchBegin;
++ return BadValue;
++ }
++ }
++
++ /* Only one client per window may select for touch events on the
++ * same devices, including master devices.
++ * XXX: This breaks if a device goes from floating to attached. */
++ if (BitIsOn(bits, XI_TouchBegin))
++ {
++ OtherInputMasks *inputMasks = wOtherInputMasks(win);
++ InputClients *iclient = NULL;
++ if (inputMasks)
++ iclient = inputMasks->inputClients;
++ for (; iclient; iclient = iclient->next)
++ {
++ if (CLIENT_ID(iclient->resource) == client->index)
++ continue;
++ if (BitIsOn(iclient->xi2mask[evmask->deviceid],
++ XI_TouchBegin) ||
++ BitIsOn(iclient->xi2mask[XIAllDevices],
++ XI_TouchBegin) ||
++ (dev && (IsMaster(dev) || dev->u.master) &&
++ BitIsOn(iclient->xi2mask[XIAllMasterDevices],
++ XI_TouchBegin)))
++ return BadAccess;
++ }
++ }
++ }
++
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1],
+ evmask->mask_len * 4) != Success)
+ return BadValue;
+Index: b/dix/devices.c
+===================================================================
+--- a/dix/devices.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/devices.c 2011-03-09 13:11:48.103384795 +1100
+@@ -754,6 +754,20 @@
+ free((*v));
+ break;
+ }
++ case XITouchClass:
++ {
++ TouchClassPtr *t = (TouchClassPtr*)class;
++ int i;
++
++ for (i = 0; i < (*t)->num_touches; i++)
++ {
++ free((*t)->touches[i].sprite.spriteTrace);
++ free((*t)->touches[i].clients);
++ }
++
++ free((*t));
++ break;
++ }
+ case FocusClass:
+ {
+ FocusClassPtr *f = (FocusClassPtr*)class;
+@@ -862,6 +876,7 @@
+
+ FreeDeviceClass(KeyClass, (pointer)&classes->key);
+ FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
++ FreeDeviceClass(XITouchClass, (pointer)&classes->touch);
+ FreeDeviceClass(ButtonClass, (pointer)&classes->button);
+ FreeDeviceClass(FocusClass, (pointer)&classes->focus);
+ FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
+@@ -1543,6 +1558,151 @@
+ InitPtrFeedbackClassDeviceStruct(dev, controlProc));
+ }
+
++Bool
++InitTouchPoint(TouchClassPtr t, int index)
++{
++ TouchPointInfoPtr ti;
++
++ if (!index >= t->num_touches)
++ return FALSE;
++ ti = &t->touches[index];
++
++ ti->valuators = calloc(t->num_axes, sizeof(*ti->valuators));
++ if (!ti->valuators)
++ return FALSE;
++ ti->num_valuators = t->num_axes;
++
++ ti->sprite.spriteTrace = calloc(32, sizeof(*ti->sprite.spriteTrace));
++ if (!ti->sprite.spriteTrace)
++ {
++ free(ti->valuators);
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ return FALSE;
++ }
++ ti->sprite.spriteTraceSize = 32;
++ ti->sprite.spriteTrace[0] = screenInfo.screens[0]->root;
++ ti->sprite.hot.pScreen = screenInfo.screens[0];
++ ti->sprite.hotPhys.pScreen = screenInfo.screens[0];
++
++ ti->ddx_id = -1;
++ ti->client_id = -1;
++
++ ti->history_size = GetMotionHistorySize();
++ ti->begin_event = malloc((ti->history_size + 1) * sizeof(InternalEvent));
++ if (!ti->begin_event)
++ {
++ free(ti->sprite.spriteTrace);
++ free(ti->valuators);
++ ti->sprite.spriteTrace = NULL;
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ return FALSE;
++ }
++ ti->history = ti->begin_event + 1;
++ ti->first_history = ti->history;
++ ti->next_history = ti->history;
++
++ return TRUE;
++}
++
++void
++FreeTouchPoint(DeviceIntPtr device, int index)
++{
++ TouchPointInfoPtr ti;
++
++ if (!device->touch || index >= device->touch->num_touches)
++ return;
++ ti = &device->touch->touches[index];
++
++ if (ti->active)
++ EndTouchPoint(device, ti);
++
++ free(ti->valuators);
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ free(ti->sprite.spriteTrace);
++ ti->sprite.spriteTrace = NULL;
++ free(ti->begin_event);
++ ti->begin_event = NULL;
++ free(ti->clients);
++ ti->clients = NULL;
++ ti->num_clients = 0;
++}
++
++/**
++ * Sets up multitouch capabilities on @device.
++ *
++ * @max_touches The maximum number of simultaneous touches, or 0 for unlimited.
++ * @mode The mode of the touch device (XIDirectTouch or XIDependentTouch).
++ * @num_axes The number of touch valuator axes.
++ */
++Bool
++InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
++ unsigned int mode, unsigned int num_axes)
++{
++ TouchClassPtr touch;
++ int i;
++
++ if (device->touch)
++ return FALSE;
++
++ /* Check the mode is valid, and at least X and Y axes. */
++ if (mode != XIDirectTouch && mode != XIDependentTouch)
++ return FALSE;
++ if (num_axes < 2)
++ return FALSE;
++
++ if (num_axes > MAX_VALUATORS)
++ {
++ LogMessage(X_WARNING,
++ "Device '%s' has %d touch axes, only using first %d.\n",
++ device->name, num_axes, MAX_VALUATORS);
++ num_axes = MAX_VALUATORS;
++ }
++
++ touch = calloc(1, sizeof(*touch));
++ if (!touch)
++ return FALSE;
++
++ touch->axes = calloc(num_axes, sizeof(*touch->axes));
++ if (!touch->axes)
++ goto err;
++ touch->num_axes = num_axes;
++
++ touch->max_touches = max_touches;
++ if (max_touches == 0)
++ max_touches = 5; /* arbitrary number plucked out of the air */
++
++ /* Need cushion for clients who may hold on to touches after they physically
++ * end. So double the initial allocation of touches. */
++ touch->touches = calloc(max_touches * 2, sizeof(*touch->touches));
++ if (!touch->touches)
++ goto err;
++ touch->num_touches = max_touches * 2;
++ for (i = 0; i < touch->num_touches; i++)
++ InitTouchPoint(touch, i);
++
++ touch->mode = mode;
++ touch->x_axis = -1;
++ touch->y_axis = -1;
++ touch->next_client_id = 1;
++
++ device->touch = touch;
++
++ return TRUE;
++
++err:
++ for (i = 0; i < touch->num_touches; i++)
++ FreeTouchPoint(device, i);
++
++ free(touch->touches);
++ free(touch->axes);
++ free(touch);
++
++ return FALSE;
++}
++
+ /*
+ * Check if the given buffer contains elements between low (inclusive) and
+ * high (inclusive) only.
+@@ -2375,6 +2535,58 @@
+ }
+ }
+
++static void
++DropTouchSelectionsOnWindow(DeviceIntPtr dev, WindowPtr win)
++{
++ WindowPtr child;
++
++ if (wOtherInputMasks(win) &&
++ BitIsOn(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin))
++ {
++ InputClientsPtr client = wOtherInputMasks(win)->inputClients;
++
++ /* Don't bother deleting client record if there are no other
++ * selections. The client will likely reselect when it gets the
++ * HierarchyChange event. */
++ while (client)
++ {
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchEnd);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchOwnership);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdate);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdateUnowned);
++
++ client = client->next;
++ }
++
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchEnd);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchOwnership);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdate);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdateUnowned);
++ }
++
++ child = win->firstChild;
++ while (child)
++ {
++ DropTouchSelectionsOnWindow(dev, child);
++ child = child->nextSib;
++ }
++}
++
++static void
++DropTouchSelections(DeviceIntPtr dev)
++{
++ int i;
++
++ for (i = 0; i < screenInfo.numScreens; i++)
++ {
++ WindowPtr win = screenInfo.screens[i]->root;
++
++ DropTouchSelectionsOnWindow(dev, win);
++ }
++}
++
+ /**
+ * Attach device 'dev' to device 'master'.
+ * Client is set to the client that issued the request, or NULL if it comes
+@@ -2440,6 +2652,12 @@
+ dev->spriteInfo->spriteOwner = FALSE;
+
+ RecalculateMasterButtons(master);
++
++ /* Only one client may select for touch events from a device on a window
++ * at any time. Reattaching could break this, so drop all touch event
++ * selections for this specific slave device on all windows. */
++ if (dev->touch)
++ DropTouchSelections(dev);
+ }
+
+ /* XXX: in theory, the MD should change back to its old, original
+Index: b/dix/eventconvert.c
+===================================================================
+--- a/dix/eventconvert.c 2011-03-09 11:39:57.000000000 +1100
++++ b/dix/eventconvert.c 2011-03-09 13:11:48.103384795 +1100
+@@ -55,6 +55,7 @@
+ static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
+ static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
+ static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
++static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
+
+ /* Do not use, read comments below */
+ BOOL EventIsKeyRepeat(xEvent *event);
+@@ -139,6 +140,11 @@
+ case ET_RawButtonPress:
+ case ET_RawButtonRelease:
+ case ET_RawMotion:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchOwnership:
+ return BadMatch;
+ default:
+ /* XXX: */
+@@ -184,6 +190,11 @@
+ case ET_RawButtonPress:
+ case ET_RawButtonRelease:
+ case ET_RawMotion:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchOwnership:
+ *count = 0;
+ *xi = NULL;
+ return BadMatch;
+@@ -225,7 +236,13 @@
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
++ case ET_TouchBegin:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchEnd:
+ return eventToDeviceEvent(&ev->device_event, xi);
++ case ET_TouchOwnership:
++ return eventToTouchOwnershipEvent(&ev->touch_ownership_event, xi);
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ *xi = NULL;
+@@ -588,6 +605,7 @@
+ xde->root_x = FP1616(ev->root_x, ev->root_x_frac);
+ xde->root_y = FP1616(ev->root_y, ev->root_y_frac);
+
++ xde->flags = ev->flags;
+ if (ev->key_repeat)
+ xde->flags |= XIKeyRepeat;
+
+@@ -625,6 +643,27 @@
+ }
+
+ static int
++eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi)
++{
++ int len = sizeof(xXITouchOwnershipEvent);
++ xXITouchOwnershipEvent *xtoe;
++
++ *xi = calloc(1, len);
++ xtoe = (xXITouchOwnershipEvent*)*xi;
++ xtoe->type = GenericEvent;
++ xtoe->extension = IReqCode;
++ xtoe->length = bytes_to_int32(len - sizeof(xEvent));
++ xtoe->evtype = GetXI2Type((InternalEvent*)ev);
++ xtoe->deviceid = ev->deviceid;
++ xtoe->time = ev->time;
++ xtoe->sourceid = ev->sourceid;
++ xtoe->touchid = ev->touchid;
++ xtoe->flags = ev->flags;
++
++ return Success;
++}
++
++static int
+ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
+ {
+ xXIRawEvent* raw;
+@@ -739,6 +778,11 @@
+ case ET_RawMotion: xi2type = XI_RawMotion; break;
+ case ET_FocusIn: xi2type = XI_FocusIn; break;
+ case ET_FocusOut: xi2type = XI_FocusOut; break;
++ case ET_TouchBegin: xi2type = XI_TouchBegin; break;
++ case ET_TouchEnd: xi2type = XI_TouchEnd; break;
++ case ET_TouchMotion: xi2type = XI_TouchUpdate; break;
++ case ET_TouchMotionUnowned: xi2type = XI_TouchUpdateUnowned; break;
++ case ET_TouchOwnership: xi2type = XI_TouchOwnership; break;
+ default:
+ break;
+ }
+Index: b/dix/events.c
+===================================================================
+--- a/dix/events.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/events.c 2011-03-09 13:11:48.103384795 +1100
+@@ -1089,7 +1089,7 @@
+ void
+ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
+ {
+- QdEventPtr tail = *syncEvents.pendtail;
++ QdEventPtr tail = syncEvents.pendtail;
+ QdEventPtr qe;
+ SpritePtr pSprite = device->spriteInfo->sprite;
+ int eventlen;
+@@ -1160,8 +1160,10 @@
+ qe->event = (InternalEvent *)(qe + 1);
+ memcpy(qe->event, event, eventlen);
+ if (tail)
+- syncEvents.pendtail = &tail->next;
+- *syncEvents.pendtail = qe;
++ tail->next = qe;
++ else
++ syncEvents.pending = qe;
++ syncEvents.pendtail = qe;
+ }
+
+ /**
+@@ -1176,18 +1178,19 @@
+ static void
+ PlayReleasedEvents(void)
+ {
+- QdEventPtr *prev, qe;
++ QdEventPtr prev, qe = syncEvents.pending;
+ DeviceIntPtr dev;
+ DeviceIntPtr pDev;
+
+- prev = &syncEvents.pending;
+- while ( (qe = *prev) )
++ prev = NULL;
++ while (qe)
+ {
+ if (!qe->device->deviceGrab.sync.frozen)
+ {
+- *prev = qe->next;
++ if (syncEvents.pending == qe)
++ syncEvents.pending = qe->next;
+ pDev = qe->device;
+- if (*syncEvents.pendtail == *prev)
++ if (syncEvents.pendtail == qe)
+ syncEvents.pendtail = prev;
+ if (qe->event->any.type == ET_Motion)
+ CheckVirtualMotion(pDev, qe, NullWindow);
+@@ -1219,6 +1222,7 @@
+
+ }
+ #endif
++
+ (*qe->device->public.processInputProc)(qe->event, qe->device);
+ free(qe);
+ for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
+@@ -1227,10 +1231,14 @@
+ break;
+ /* Playing the event may have unfrozen another device. */
+ /* So to play it safe, restart at the head of the queue */
+- prev = &syncEvents.pending;
++ qe = syncEvents.pending;
++ prev = NULL;
+ }
+ else
+- prev = &qe->next;
++ {
++ prev = qe;
++ qe = qe->next;
++ }
+ }
+ }
+
+@@ -1252,6 +1260,76 @@
+ dev->public.processInputProc = dev->public.realInputProc;
+ }
+
++void
++RemoveTouchEventsFromQueue(DeviceIntPtr dev, Bool touch, Bool ignoreOwned)
++{
++ QdEventPtr qe = syncEvents.pending;
++ QdEventPtr prev_qe = NULL;
++ QdEventPtr first = NULL;
++ Bool end = FALSE;
++
++ while (qe && !end)
++ {
++ QdEventPtr tmp;
++
++ if (qe->device != dev)
++ continue;
++
++ if (ignoreOwned && (qe->event->any.type == ET_TouchOwnership ||
++ qe->event->any.type == ET_TouchEnd))
++ break;
++
++ if (qe->event->any.type == ET_TouchEnd)
++ end = TRUE;
++
++ if ((touch && !IsTouchEvent(qe->event)) ||
++ (!touch && !IsPointerEvent(qe->event)) ||
++ (ignoreOwned && qe->event->any.type == ET_TouchBegin))
++ {
++ if (!first)
++ first = qe;
++ prev_qe = qe;
++ qe = qe->next;
++ continue;
++ }
++
++ tmp = qe;
++ qe = qe->next;
++ if (prev_qe)
++ prev_qe->next = qe;
++ if (syncEvents.pending == tmp)
++ syncEvents.pending = qe;
++
++ free(tmp);
++
++ if (!qe)
++ syncEvents.pendtail = prev_qe;
++ }
++
++ if (qe && !qe->next)
++ syncEvents.pendtail = qe;
++
++ if (dev->deviceGrab.sync.event &&
++ ((touch && IsTouchEvent((InternalEvent *)dev->deviceGrab.sync.event)) ||
++ (!touch &&
++ IsPointerEvent((InternalEvent *)dev->deviceGrab.sync.event))))
++ {
++ free(dev->deviceGrab.sync.event);
++ if (first)
++ {
++ dev->deviceGrab.sync.event = malloc(sizeof(DeviceEvent));
++ memcpy(dev->deviceGrab.sync.event, first->event,
++ sizeof(DeviceEvent));
++ }
++ else
++ dev->deviceGrab.sync.event = NULL;
++ syncEvents.pending = first->next;
++ free(first);
++ if (!syncEvents.pending)
++ syncEvents.pendtail = NULL;
++ }
++}
++
+ /**
+ * Unfreeze devices and replay all events to the respective clients.
+ *
+@@ -1278,6 +1356,14 @@
+ {
+ DeviceEvent* event = replayDev->deviceGrab.sync.event;
+
++ if (event->type == ET_TouchBegin)
++ {
++ ProcessTouchOwnership(replayDev, event->touchpoint,
++ XITouchOwnerAccept, FALSE);
++ if (!replayDev->deviceGrab.sync.event)
++ goto no_sync;
++ }
++
+ syncEvents.replayDev = (DeviceIntPtr)NULL;
+
+ w = XYToWindow(replayDev->spriteInfo->sprite,
+@@ -1291,6 +1377,7 @@
+ NullWindow, replayDev);
+ }
+ }
++no_sync:
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (!dev->deviceGrab.sync.frozen)
+@@ -1510,6 +1597,20 @@
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
+ ReattachToOldMaster(mouse);
+
++ if (mouse->deviceGrab.sync.event &&
++ (mouse->deviceGrab.sync.event->flags & XIPointerEmulated) &&
++ (grab->grabtype != GRABTYPE_XI2 || grab->type != XI_TouchBegin))
++ {
++ InternalEvent event;
++
++ event.any.type = ET_TouchBegin;
++
++ if (CheckPassiveGrabsOnWindow(grab->window, mouse, &event, FALSE, TRUE))
++ syncEvents.playingEvents = TRUE;
++ }
++ else
++ syncEvents.playingEvents = FALSE;
++
+ ComputeFreezes();
+ }
+
+@@ -1757,6 +1858,25 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
++
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (mouse->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = mouse->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return Success;
+ }
+
+@@ -2174,7 +2294,7 @@
+
+ static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
+ {
+- WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
++ WindowPtr w = DeepestSpriteWin(pSprite);
+ Window child = None;
+
+ /* If the search ends up past the root should the child field be
+@@ -2232,7 +2352,8 @@
+ event->evtype == XI_RawMotion ||
+ event->evtype == XI_DeviceChanged ||
+ event->evtype == XI_HierarchyChanged ||
+- event->evtype == XI_PropertyEvent)
++ event->evtype == XI_PropertyEvent ||
++ event->evtype == XI_TouchOwnership)
+ return;
+
+ event->root = RootWindow(pSprite)->drawable.id;
+@@ -2369,12 +2490,119 @@
+ xEvent core;
+ xEvent *xE = NULL;
+ int rc, mask, count = 0;
++ InternalEvent touch_dummy;
++ Bool check_touch = FALSE;
+
+ CHECKEVENT(event);
+
++ /* If we are replaying a pointer emulated button press event, find the first
++ * pointer or touch selecting client. */
++ if (syncEvents.playingEvents && event->any.type == ET_ButtonPress &&
++ (event->device_event.flags & XIPointerEmulated) &&
++ event->device_event.touchpoint &&
++ event->device_event.touchpoint->active_clients > 0)
++ {
++ QdEventPtr qe;
++ DeviceEvent *te;
++ TouchPointInfoPtr ti;
++ TouchClientPtr tc = NULL;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if (qe->device == dev && qe->event->any.type == ET_TouchBegin)
++ break;
++ if (!qe)
++ {
++ LogMessage(X_ERROR, "no touch for emulated button press\n");
++ goto no_touch_event;
++ }
++
++ te = &qe->event->device_event;
++ ti = te->touchpoint;
++
++ if (ti->active_clients > 0)
++ {
++ tc = &ti->clients[ti->active_clients - 1];
++ te->deviceid = tc->device->id;
++ }
++
++ while (pWin)
++ {
++ Bool touch = FALSE;
++ Bool pointer = FALSE;
++
++ if (tc &&
++ EventIsDeliverable(tc->device, (InternalEvent *)te, pWin) &&
++ (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED))
++ {
++ ti->owner = ti->active_clients - 1;
++ if (tc->type == TOUCH_SELECT_UNOWNED)
++ DeliverTouchOwnershipEvent(tc, ti);
++ touch = TRUE;
++ }
++
++ if (EventIsDeliverable(dev, event, pWin))
++ pointer = TRUE;
++
++ if (touch && pointer)
++ break;
++ else if (touch || pointer)
++ {
++ /* Remove unselected events from queue. */
++ RemoveTouchEventsFromQueue(dev, pointer, FALSE);
++
++ if (touch)
++ {
++ /* If only touch events are selected, release mouse
++ * button. */
++ ReleaseButton(dev, 1);
++ ti->emulate_pointer = FALSE;
++ if (IsPointerEvent(event))
++ return 0;
++ } else {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ if (IsTouchEvent(event))
++ return 0;
++ }
++
++ break;
++ }
++
++ pWin = pWin->parent;
++ }
++ }
++ else if (IsPointerEvent(event) && !syncEvents.playingEvents &&
++ (event->device_event.flags & XIPointerEmulated) &&
++ event->device_event.touchpoint &&
++ event->device_event.touchpoint->active_clients > 0)
++ {
++ /* Non-grabbed emulated pointer event, so check for touch selections. */
++ check_touch = TRUE;
++ touch_dummy.any.type = ET_TouchBegin;
++ }
++ else if (IsTouchEvent(event))
++ {
++ TouchPointInfoPtr ti = event->device_event.touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ pWin = tc->window;
++ }
++
++no_touch_event:
+ while (pWin)
+ {
+- if ((mask = EventIsDeliverable(dev, event, pWin)))
++ DeviceIntPtr check_dev = dev;
++
++ if (IsTouchEvent(event))
++ {
++ TouchPointInfoPtr ti = event->device_event.touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ event->device_event.deviceid = tc->device->id;
++ check_dev = tc->device;
++ }
++
++ if ((mask = EventIsDeliverable(check_dev, event, pWin)))
+ {
+ /* XI2 events first */
+ if (mask & XI2_MASK)
+@@ -2383,10 +2611,25 @@
+ rc = EventToXI2(event, &xi2);
+ if (rc == Success)
+ {
++ if (event->any.type == ET_TouchBegin ||
++ event->any.type == ET_TouchMotionUnowned)
++ {
++ OtherInputMasks *masks = wOtherInputMasks(pWin);
++
++ if (BitIsOn(masks->xi2mask[XIAllDevices],
++ XI_TouchOwnership) ||
++ BitIsOn(masks->xi2mask[check_dev->id],
++ XI_TouchOwnership) ||
++ (IsMaster(check_dev) &&
++ BitIsOn(masks->xi2mask[XIAllMasterDevices],
++ XI_TouchOwnership)))
++ goto unwind;
++ }
++
+ /* XXX: XACE */
+- filter = GetEventFilter(dev, xi2);
++ filter = GetEventFilter(check_dev, xi2);
+ FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE);
+- deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
++ deliveries = DeliverEventsToWindow(check_dev, pWin, xi2, 1,
+ filter, grab);
+ free(xi2);
+ if (deliveries > 0)
+@@ -2439,6 +2682,14 @@
+ goto unwind;
+ }
+ }
++ else if (check_touch && EventIsDeliverable(dev, &touch_dummy, pWin))
++ {
++ /* Only touch events wanted on this window. Skip this event and
++ * stop pointer emulation. Future touch events will be sent
++ * instead. */
++ event->device_event.touchpoint->emulate_pointer = FALSE;
++ goto unwind;
++ }
+
+ child = pWin->drawable.id;
+ pWin = pWin->parent;
+@@ -2591,7 +2842,7 @@
+ else
+ pWin = pWin->nextSib;
+ }
+- return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
++ return DeepestSpriteWin(pSprite);
+ }
+
+ /**
+@@ -2629,7 +2880,8 @@
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+- rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
++ rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
++ TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
+ return rc;
+@@ -2666,7 +2918,8 @@
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+- rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
++ rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
++ TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
+ return rc;
+@@ -3353,7 +3606,7 @@
+ CheckPassiveGrabsOnWindow(
+ WindowPtr pWin,
+ DeviceIntPtr device,
+- DeviceEvent *event,
++ InternalEvent *event,
+ BOOL checkCore,
+ BOOL activate)
+ {
+@@ -3370,9 +3623,22 @@
+ return NULL;
+ /* Fill out the grab details, but leave the type for later before
+ * comparing */
++ switch (event->any.type)
++ {
++ case ET_KeyPress:
++ case ET_KeyRelease:
++ tempGrab.detail.exact = event->device_event.detail.key;
++ break;
++ case ET_ButtonPress:
++ case ET_ButtonRelease:
++ tempGrab.detail.exact = event->device_event.detail.button;
++ break;
++ default:
++ tempGrab.detail.exact = 0;
++ break;
++ }
+ tempGrab.window = pWin;
+ tempGrab.device = device;
+- tempGrab.detail.exact = event->detail.key;
+ tempGrab.detail.pMask = NULL;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.next = NULL;
+@@ -3380,6 +3646,9 @@
+ {
+ DeviceIntPtr gdev;
+ XkbSrvInfoPtr xkbi = NULL;
++ int rc, count = 0;
++ xEvent *xE = NULL;
++ xEvent core;
+
+ gdev= grab->modifierDevice;
+ if (grab->grabtype == GRABTYPE_CORE)
+@@ -3405,16 +3674,15 @@
+ tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
+
+ /* Check for XI2 and XI grabs first */
+- tempGrab.type = GetXI2Type((InternalEvent*)event);
++ tempGrab.type = GetXI2Type(event);
+ tempGrab.grabtype = GRABTYPE_XI2;
+ if (GrabMatchesSecond(&tempGrab, grab, FALSE))
+ match = XI2_MATCH;
+
+- tempGrab.detail.exact = event->detail.key;
+ if (!match)
+ {
+ tempGrab.grabtype = GRABTYPE_XI;
+- if ((tempGrab.type = GetXIType((InternalEvent*)event)) &&
++ if ((tempGrab.type = GetXIType(event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, FALSE)))
+ match = XI_MATCH;
+ }
+@@ -3423,125 +3691,143 @@
+ if (!match && checkCore)
+ {
+ tempGrab.grabtype = GRABTYPE_CORE;
+- if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
++ if ((tempGrab.type = GetCoreType(event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, TRUE)))
+ match = CORE_MATCH;
+ }
+
+- if (match && (!grab->confineTo ||
+- (grab->confineTo->realized &&
+- BorderSizeNotEmpty(device, grab->confineTo))))
+- {
+- int rc, count = 0;
+- xEvent *xE = NULL;
+- xEvent core;
++ if (!match || (grab->confineTo &&
++ (!grab->confineTo->realized ||
++ !BorderSizeNotEmpty(device, grab->confineTo))))
++ continue;
+
+- event->corestate &= 0x1f00;
+- event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
+- grabinfo = &device->deviceGrab;
+- /* In some cases a passive core grab may exist, but the client
+- * already has a core grab on some other device. In this case we
+- * must not get the grab, otherwise we may never ungrab the
+- * device.
+- */
+-
+- if (grab->grabtype == GRABTYPE_CORE)
+- {
+- DeviceIntPtr other;
+- BOOL interfering = FALSE;
+-
+- /* A passive grab may have been created for a different device
+- than it is assigned to at this point in time.
+- Update the grab's device and modifier device to reflect the
+- current state.
+- Since XGrabDeviceButton requires to specify the
+- modifierDevice explicitly, we don't override this choice.
+- */
+- if (tempGrab.type < GenericEvent)
+- {
+- grab->device = device;
+- grab->modifierDevice = GetPairedDevice(device);
+- }
++ grabinfo = &device->deviceGrab;
++ /* In some cases a passive core grab may exist, but the client
++ * already has a core grab on some other device. In this case we
++ * must not get the grab, otherwise we may never ungrab the
++ * device.
++ */
++
++ if (grab->grabtype == GRABTYPE_CORE)
++ {
++ DeviceIntPtr other;
++ BOOL interfering = FALSE;
++
++ /* A passive grab may have been created for a different device
++ than it is assigned to at this point in time.
++ Update the grab's device and modifier device to reflect the
++ current state.
++ Since XGrabDeviceButton requires to specify the
++ modifierDevice explicitly, we don't override this choice.
++ */
++ if (tempGrab.type < GenericEvent)
++ {
++ grab->device = device;
++ grab->modifierDevice = GetPairedDevice(device);
++ }
+
+- for (other = inputInfo.devices; other; other = other->next)
++ for (other = inputInfo.devices; other; other = other->next)
++ {
++ GrabPtr othergrab = other->deviceGrab.grab;
++ if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
++ SameClient(grab, rClient(othergrab)) &&
++ ((IsPointerDevice(grab->device) &&
++ IsPointerDevice(othergrab->device)) ||
++ (IsKeyboardDevice(grab->device) &&
++ IsKeyboardDevice(othergrab->device))))
+ {
+- GrabPtr othergrab = other->deviceGrab.grab;
+- if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
+- SameClient(grab, rClient(othergrab)) &&
+- ((IsPointerDevice(grab->device) &&
+- IsPointerDevice(othergrab->device)) ||
+- (IsKeyboardDevice(grab->device) &&
+- IsKeyboardDevice(othergrab->device))))
+- {
+- interfering = TRUE;
+- break;
+- }
++ interfering = TRUE;
++ break;
+ }
+- if (interfering)
+- continue;
+ }
++ if (interfering)
++ continue;
++ }
+
+- if (!activate)
+- return grab;
++ if (!activate)
++ {
++ return grab;
++ }
++ else if (!GetXIType(event) && !GetCoreType(event))
++ {
++ ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither"
++ " XI 1.x nor core\n", event->any.type);
++ return NULL;
++ }
+
+- if (match & CORE_MATCH)
++ /* The only consumers of corestate are Xi 1.x and core events, which
++ * are guaranteed to come from DeviceEvents. */
++ if (match & (XI_MATCH | CORE_MATCH))
++ {
++ event->device_event.corestate &= 0x1f00;
++ event->device_event.corestate |= tempGrab.modifiersDetail.exact &
++ (~0x1f00);
++ }
++
++ if (match & CORE_MATCH)
++ {
++ rc = EventToCore(event, &core);
++ if (rc != Success)
+ {
+- rc = EventToCore((InternalEvent*)event, &core);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: core conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
+- xE = &core;
+- count = 1;
+- } else if (match & XI2_MATCH)
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: core conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
++ }
++ xE = &core;
++ count = 1;
++ } else if (match & XI2_MATCH)
++ {
++ rc = EventToXI2(event, &xE);
++ if (rc != Success)
+ {
+- rc = EventToXI2((InternalEvent*)event, &xE);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
+- count = 1;
+- } else
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
++ }
++ count = 1;
++ } else
++ {
++ rc = EventToXI(event, &xE, &count);
++ if (rc != Success)
+ {
+- rc = EventToXI((InternalEvent*)event, &xE, &count);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: XI conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: XI conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
+ }
++ }
+
+- (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
++ (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
+
+- if (xE)
+- {
+- FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
++ /* Don't send touch events if you activate a touch grab. Touch grabs
++ * are handled separately. */
++ if (xE && grab->type != ET_TouchBegin)
++ {
++ FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
+
+- TryClientEvents(rClient(grab), device, xE, count,
+- GetEventFilter(device, xE),
+- GetEventFilter(device, xE), grab);
+- }
++ TryClientEvents(rClient(grab), device, xE, count,
++ GetEventFilter(device, xE),
++ GetEventFilter(device, xE), grab);
++ }
+
+- if (grabinfo->sync.state == FROZEN_NO_EVENT)
+- {
++ if (grabinfo->sync.state == FROZEN_NO_EVENT)
++ {
++ /* Touch events are enqueued differently due to pointer
++ * emulation. */
++ if (grab->type != ET_TouchBegin)
++ {
+ if (!grabinfo->sync.event)
+- grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
+- *grabinfo->sync.event = *event;
+- grabinfo->sync.state = FROZEN_WITH_EVENT;
++ grabinfo->sync.event = calloc(1, sizeof(DeviceEvent));
++ *grabinfo->sync.event = event->device_event;
+ }
++ grabinfo->sync.state = FROZEN_WITH_EVENT;
++ }
+
+- if (match & (XI_MATCH | XI2_MATCH))
+- free(xE); /* on core match xE == &core */
+- return grab;
+- }
++ if (match & (XI_MATCH | XI2_MATCH))
++ free(xE); /* on core match xE == &core */
++ return grab;
+ }
+ return NULL;
+ #undef CORE_MATCH
+@@ -3580,8 +3866,13 @@
+ {
+ int i;
+ WindowPtr pWin = NULL;
+- FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
++ FocusClassPtr focus = device->focus;
+ BOOL sendCore = (IsMaster(device) && device->coreEvents);
++ DeviceEvent *touch_event = NULL;
++
++ if (IsPointerEvent((InternalEvent *)event) ||
++ IsTouchEvent((InternalEvent *)event))
++ focus = NULL;
+
+ if (event->type != ET_ButtonPress &&
+ event->type != ET_KeyPress)
+@@ -3609,7 +3900,8 @@
+ for (; i < focus->traceGood; i++)
+ {
+ pWin = focus->trace[i];
+- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
++ if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
++ sendCore, TRUE))
+ return TRUE;
+ }
+
+@@ -3619,11 +3911,54 @@
+ return FALSE;
+ }
+
++ if (syncEvents.pending && event->type == ET_ButtonPress &&
++ (event->flags & XIPointerEmulated))
++ {
++ QdEventPtr qe;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if (qe->device == device && qe->event->any.type == ET_TouchBegin)
++ break;
++ if (qe)
++ touch_event = &qe->event->device_event;
++ }
++
+ for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
+ {
+- pWin = device->spriteInfo->sprite->spriteTrace[i];
+- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
+- return TRUE;
++ pWin = device->spriteInfo->sprite->spriteTrace[i];
++
++ if (!pWin->optional)
++ continue;
++
++ /* Touch grabs are checked before pointer grabs. When a touch grab
++ * should be checked first, check_grab is TRUE. */
++ if (touch_event && touch_event->check_grab)
++ {
++ GrabPtr grab;
++
++ grab = CheckPassiveGrabsOnWindow(pWin, device,
++ (InternalEvent *)touch_event,
++ FALSE, FALSE);
++ if (grab)
++ {
++ TouchPointInfoPtr ti = touch_event->touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ device->deviceGrab.ActivateGrab(device, grab, currentTime,
++ TRUE);
++ touch_event->check_grab = FALSE;
++ DeliverTouchOwnershipEvent(tc, ti);
++ return TRUE;
++ }
++ }
++
++ if (touch_event)
++ touch_event->check_grab = TRUE;
++
++ if (pWin->optional &&
++ CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *)event,
++ sendCore, TRUE))
++ return TRUE;
+ }
+
+ return FALSE;
+@@ -3745,6 +4080,17 @@
+ grabinfo = &thisDev->deviceGrab;
+ grab = grabinfo->grab;
+
++ /* Touch grab deliver is handled in ProcessTouchEvent. */
++ if (event->any.type == ET_TouchBegin ||
++ event->any.type == ET_TouchMotionUnowned)
++ {
++ if (BitIsOn(grab->xi2mask[XIAllDevices], XI_TouchOwnership) ||
++ BitIsOn(grab->xi2mask[thisDev->id], XI_TouchOwnership) ||
++ (IsMaster(thisDev) &&
++ BitIsOn(grab->xi2mask[XIAllMasterDevices], XI_TouchOwnership)))
++ return;
++ }
++
+ if (grab->ownerEvents)
+ {
+ WindowPtr focus;
+@@ -3821,6 +4167,9 @@
+ mask = grab->xi2mask[XIAllDevices][evtype/8] |
+ grab->xi2mask[XIAllMasterDevices][evtype/8] |
+ grab->xi2mask[thisDev->id][evtype/8];
++ if (IsTouchEvent(event))
++ mask |=
++ grab->xi2mask[event->device_event.sourceid][evtype/8];
+ /* try XI2 event */
+ FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
+ /* XXX: XACE */
+@@ -4955,7 +5304,7 @@
+ free(syncEvents.pending);
+ syncEvents.pending = next;
+ }
+- syncEvents.pendtail = &syncEvents.pending;
++ syncEvents.pendtail = NULL;
+ syncEvents.playingEvents = FALSE;
+ syncEvents.time.months = 0;
+ syncEvents.time.milliseconds = 0; /* hardly matters */
+Index: b/dix/getevents.c
+===================================================================
+--- a/dix/getevents.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/getevents.c 2011-03-09 13:11:48.103384795 +1100
+@@ -47,6 +47,7 @@
+ #include "eventstr.h"
+ #include "eventconvert.h"
+ #include "inpututils.h"
++#include "windowstr.h"
+
+ #include <X11/extensions/XKBproto.h>
+ #include "xkbsrv.h"
+@@ -160,7 +161,7 @@
+ (1 << (key_code & 7)));
+ }
+
+-static void
++void
+ init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
+ {
+ memset(event, 0, sizeof(DeviceEvent));
+@@ -172,6 +173,18 @@
+ }
+
+ static void
++init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
++{
++ memset(event, 0, sizeof(TouchOwnershipEvent));
++ event->header = ET_Internal;
++ event->type = ET_TouchOwnership;
++ event->length = sizeof(TouchOwnershipEvent);
++ event->time = ms;
++ event->deviceid = dev->id;
++ event->sourceid = dev->id;
++}
++
++static void
+ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
+ {
+ memset(event, 0, sizeof(RawDeviceEvent));
+@@ -210,7 +223,8 @@
+ if (valuator_mask_isset(mask, i))
+ {
+ SetBit(event->valuators.mask, i);
+- if (valuator_get_mode(dev, i) == Absolute)
++ if (!IsTouchEvent((InternalEvent *)event) &&
++ valuator_get_mode(dev, i) == Absolute)
+ SetBit(event->valuators.mode, i);
+ event->valuators.data[i] = valuator_mask_get(mask, i);
+ event->valuators.data_frac[i] =
+@@ -1058,23 +1072,14 @@
+ }
+
+ static void
+-transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
++transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask, int *x, int *y)
+ {
+- struct pixman_f_vector p;
+-
+- /* p' = M * p in homogeneous coordinates */
+- p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
+- dev->last.valuators[0]);
+- p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
+- dev->last.valuators[1]);
+- p.v[2] = 1.0;
++ struct pixman_f_vector p = {.v = {*x, *y, 1}};
+
+ pixman_f_transform_point(&dev->transform, &p);
+
+- if (lround(p.v[0]) != dev->last.valuators[0])
+- valuator_mask_set(mask, 0, lround(p.v[0]));
+- if (lround(p.v[1]) != dev->last.valuators[1])
+- valuator_mask_set(mask, 1, lround(p.v[1]));
++ *x = lround(p.v[0]);
++ *y = lround(p.v[1]);
+ }
+
+ /**
+@@ -1116,7 +1121,10 @@
+ switch (type)
+ {
+ case MotionNotify:
+- if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
++ if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0 ||
++ (pDev->touch && pDev->touch->active_touches > 1 &&
++ (pDev->touch->mode == XIDependentTouch ||
++ pDev->touch->mode == XISemiMultitouch)))
+ return 0;
+ break;
+ case ButtonPress:
+@@ -1165,7 +1173,16 @@
+ }
+ }
+
+- transformAbsolute(pDev, &mask);
++ x = (valuator_mask_isset(&mask, 0) ? valuator_mask_get(&mask, 0) :
++ pDev->last.valuators[0]);
++ y = (valuator_mask_isset(&mask, 1) ? valuator_mask_get(&mask, 1) :
++ pDev->last.valuators[1]);
++ transformAbsolute(pDev, &mask, &x, &y);
++ if (valuator_mask_isset(&mask, 0))
++ valuator_mask_set(&mask, 0, x);
++ if (valuator_mask_isset(&mask, 1))
++ valuator_mask_set(&mask, 1, y);
++
+ moveAbsolute(pDev, &x, &y, &mask);
+ } else {
+ if (flags & POINTER_ACCELERATE) {
+@@ -1286,6 +1303,130 @@
+ return num_events;
+ }
+
++int
++GetTouchOwnershipEvents(EventList *events, DeviceIntPtr pDev,
++ TouchPointInfoPtr ti, uint8_t reason, XID resource,
++ uint32_t flags)
++{
++ TouchClassPtr t = pDev->touch;
++ TouchOwnershipEvent *event;
++ CARD32 ms = GetTimeInMillis();
++
++ if (!pDev->enabled || !t || !ti)
++ return 0;
++
++ if (reason != XITouchOwnerAccept && reason != XITouchOwnerRejectEnd)
++ return 0;
++
++ event = (TouchOwnershipEvent *) events->event;
++ init_touch_ownership(pDev, event, ms);
++
++ event->touchid = ti->client_id;
++ event->resource = resource;
++ event->flags = flags;
++
++ return 1;
++}
++
++/**
++ * Get events for a touch. Generates a TouchBegin event if end is not set and
++ * the touch id is not active. Generates a TouchMotion event if end is not set
++ * and the touch id is active. Generates a TouchEnd event if end is set and the
++ * touch id is active.
++ *
++ * events is not NULL-terminated; the return value is the number of events.
++ * The DDX is responsible for allocating the event structure in the first
++ * place via GetMaximumEventsNum(), and for freeing it.
++ */
++int
++GetTouchEvents(EventList *events, DeviceIntPtr pDev, TouchPointInfoPtr ti,
++ uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
++{
++ ScreenPtr scr = pDev->spriteInfo->sprite->hotPhys.pScreen;
++ TouchClassPtr t = pDev->touch;
++ DeviceEvent *event;
++ CARD32 ms = GetTimeInMillis();
++ ValuatorMask mask;
++ int x, y; /* in screen co-ord space */
++ float x_frac = 0.0, y_frac = 0.0; /* as above */
++ int i;
++
++ if (!pDev->enabled || !t || t->x_axis == -1 || t->y_axis == -1)
++ return 0;
++
++ event = (DeviceEvent *) events->event;
++ init_event(pDev, event, ms);
++
++ switch (type) {
++ case XI_TouchBegin:
++ event->type = ET_TouchBegin;
++ /* If we're starting a touch, we must have x & y co-ordinates. */
++ if (!valuator_mask_isset(mask_in, t->x_axis) ||
++ !valuator_mask_isset(mask_in, t->y_axis))
++ {
++ DebugF("%s: Attempted to start touch without x/y (driver bug)\n",
++ pDev->name);
++ return 0;
++ }
++ break;
++ case XI_TouchUpdate:
++ event->type = ET_TouchMotion;
++ break;
++ case XI_TouchEnd:
++ event->type = ET_TouchEnd;
++ break;
++ default:
++ return 0;
++ }
++
++ event->touchpoint = ti;
++
++ valuator_mask_copy(&mask, mask_in);
++
++ /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y):
++ * these come from the touchpoint in Absolute mode, or the sprite in
++ * Relative. */
++ if (t->mode == XIDirectTouch) {
++ if (valuator_mask_isset(&mask, t->x_axis))
++ x = valuator_mask_get(&mask, t->x_axis);
++ else
++ x = ti->valuators[t->x_axis];
++ x = rescaleValuatorAxis(x, 0.0, &x_frac,
++ (AxisInfoPtr)(t->axes + t->x_axis),
++ NULL, scr->width);
++
++ if (valuator_mask_isset(&mask, t->y_axis))
++ y = valuator_mask_get(&mask, t->y_axis);
++ else
++ y = ti->valuators[t->y_axis];
++ y = rescaleValuatorAxis(y, 0.0, &y_frac,
++ (AxisInfoPtr)(t->axes + t->y_axis),
++ NULL, scr->height);
++
++ transformAbsolute(pDev, &mask, &x, &y);
++ }
++ else {
++ x = pDev->spriteInfo->sprite->hotPhys.x;
++ y = pDev->spriteInfo->sprite->hotPhys.y;
++ }
++
++ event->root_x = x;
++ event->root_y = y;
++ event->root_x_frac = x_frac;
++ event->root_y_frac = y_frac;
++ event->detail.touch = ti->client_id;
++ event->flags = flags;
++
++ set_valuators(pDev, event, &mask);
++ for (i = 0; i < t->num_axes; i++)
++ {
++ if (valuator_mask_isset(&mask, i))
++ ti->valuators[i] = valuator_mask_get(&mask, i);
++ }
++
++ return 1;
++}
++
+ /**
+ * Synthesize a single motion event for the core pointer.
+ *
+Index: b/dix/grabs.c
+===================================================================
+--- a/dix/grabs.c 2011-02-28 13:56:41.000000000 +1100
++++ b/dix/grabs.c 2011-03-09 13:11:48.103384795 +1100
+@@ -60,6 +60,7 @@
+ #include "dixgrabs.h"
+ #include "xace.h"
+ #include "exevents.h"
++#include "mi.h"
+
+ #define BITMASK(i) (((Mask)1) << ((i) & 31))
+ #define MASKIDX(i) ((i) >> 5)
+@@ -243,6 +244,25 @@
+ }
+
+ /**
++ * Returns the event type to match when comparing grabs.
++ */
++static uint32_t
++GetGrabEventMatch(GrabPtr pGrab)
++{
++ if (pGrab->grabtype != GRABTYPE_XI2)
++ return pGrab->type;
++
++ if (pGrab->type == XI_TouchBegin ||
++ pGrab->type == XI_TouchUpdate ||
++ pGrab->type == XI_TouchUpdateUnowned ||
++ pGrab->type == XI_TouchOwnership ||
++ pGrab->type == XI_TouchEnd)
++ return XI_TouchBegin;
++
++ return pGrab->type;
++}
++
++/**
+ * Compares two grabs and returns TRUE if the first grab matches the second
+ * grab.
+ *
+@@ -261,6 +281,8 @@
+ unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier :
+ (unsigned int)AnyModifier;
++ uint32_t first_type = GetGrabEventMatch(pFirstGrab);
++ uint32_t second_type = GetGrabEventMatch(pSecondGrab);
+
+ if (pFirstGrab->grabtype != pSecondGrab->grabtype)
+ return FALSE;
+@@ -288,8 +310,8 @@
+ (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice)))
+ return FALSE;
+
+- if (pFirstGrab->type != pSecondGrab->type)
+- return FALSE;
++ if (first_type != second_type)
++ return FALSE;
+
+ if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
+ GrabSupersedesSecond(pSecondGrab, pFirstGrab))
+Index: b/dix/inpututils.c
+===================================================================
+--- a/dix/inpututils.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/inpututils.c 2011-03-09 13:11:48.113385173 +1100
+@@ -36,6 +36,7 @@
+ #include "xkbsrv.h"
+ #include "xkbstr.h"
+ #include "inpututils.h"
++#include "eventstr.h"
+
+ /* Check if a button map change is okay with the device.
+ * Returns -1 for BadValue, as it collides with MappingBusy. */
+@@ -556,3 +557,158 @@
+
+ return ret;
+ }
++
++/**
++ * Given the DDX-facing ID (which is _not_ DeviceEvent::detail.touch), find the
++ * associated TouchPointInfoRec.
++ */
++TouchPointInfoPtr
++FindTouchPointByDDXID(DeviceIntPtr dev, uint32_t ddx_id)
++{
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++ int i;
++
++ if (!t)
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (ti->active && ti->ddx_id == ddx_id && !ti->ddx_pending_finish)
++ return ti;
++ }
++
++ return NULL;
++}
++
++/**
++ * Given a client-facing ID (e.g. DeviceEvent::detail.touch), find the
++ * associated TouchPointInfoRec.
++ */
++TouchPointInfoPtr
++FindTouchPointByClientID(DeviceIntPtr dev, uint32_t client_id)
++{
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++ int i;
++
++ if (!t)
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (ti->active && ti->client_id == client_id)
++ return ti;
++ }
++
++ return NULL;
++}
++
++/**
++ * Given a unique DDX ID for a touchpoint, create a touchpoint record in the
++ * server and return the client-facing ID.
++ *
++ * Returns 0 on failure (i.e. if another touch with that ID is already active,
++ * allocation failure).
++ */
++_X_EXPORT TouchPointInfoPtr
++BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id)
++{
++ int i;
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++
++ if (!t)
++ return NULL;
++
++ /* Look for another active touchpoint with the same DDX ID. It's entirely
++ * legitimate for a touchpoint to still exist with the same DDX ID but
++ * be in the pending_finish state as it waits for a client to release its
++ * grab, so allow for that. */
++ if (FindTouchPointByDDXID(dev, ddx_id))
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (!ti->active) {
++ ti->source = dev;
++ ti->active = TRUE;
++ ti->ddx_id = ddx_id;
++ ti->client_id = t->next_client_id;
++ ti->owner = -1;
++ ti->active_clients = 0;
++ ti->accepted = FALSE;
++ ti->pending_finish = FALSE;
++ t->active_touches++;
++next_touch_id:
++ t->next_client_id++;
++ if (t->next_client_id == 0)
++ t->next_client_id = 1;
++ if (FindTouchPointByClientID(dev, t->next_client_id))
++ goto next_touch_id; /* n'th time's a charm */
++ return ti;
++ }
++ }
++
++ /* If we get here, then we've run out of touches. */
++ LogMessage(X_WARNING, "%s: no more touches available\n", dev->name);
++
++ return NULL;
++}
++
++/**
++ * Releases a touchpoint for use: this must only be called after all events
++ * related to that touchpoint have been sent and finalised. Called from
++ * ProcessTouchEvent and friends. Not by you.
++ */
++void
++EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti)
++{
++ int i;
++ TouchClassPtr t = dev->touch;
++ DeviceIntPtr masterdev = dev->u.master;
++ QdEventPtr qe;
++
++ if (dev->deviceGrab.sync.event &&
++ dev->deviceGrab.sync.event->touchpoint == ti)
++ dev->deviceGrab.sync.event->touchpoint = NULL;
++
++ if (masterdev && masterdev->deviceGrab.sync.event &&
++ masterdev->deviceGrab.sync.event->touchpoint == ti)
++ masterdev->deviceGrab.sync.event->touchpoint = NULL;
++
++ ti->source = NULL;
++ ti->pending_finish = FALSE;
++ ti->sprite.spriteTraceGood = 0;
++ ti->ddx_id = 0;
++ ti->first_history = ti->history;
++ ti->next_history = ti->history;
++ ti->emulate_pointer = FALSE;
++ ti->owner = -1;
++ ti->accepted = FALSE;
++ ti->active_clients = 0;
++ ti->ddx_pending_finish = FALSE;
++ t->active_touches--;
++
++ if (dev->touch->emulate == ti)
++ {
++ dev->touch->emulate = NULL;
++ if (dev->u.master)
++ dev->u.master->emulate_dev = NULL;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if ((qe->event->any.type == ET_TouchEnd ||
++ qe->event->any.type == ET_ButtonRelease) &&
++ qe->event->device_event.touchpoint == ti)
++ qe->event->device_event.touchpoint = NULL;
++ }
++
++ for (i = 0; i < ti->num_valuators; i++)
++ ti->valuators[i] = 0;
++
++ ti->client_id = 0;
++ ti->active = FALSE;
++}
+Index: b/dix/window.c
+===================================================================
+--- a/dix/window.c 2011-02-28 13:56:41.000000000 +1100
++++ b/dix/window.c 2011-03-09 13:11:48.113385173 +1100
+@@ -110,6 +110,7 @@
+ #include "windowstr.h"
+ #include "input.h"
+ #include "inputstr.h"
++#include "exevents.h"
+ #include "resource.h"
+ #include "colormapst.h"
+ #include "cursorstr.h"
+@@ -2873,8 +2874,10 @@
+ if (!fromConfigure && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
+ }
+- if (wasRealized && !fromConfigure)
++ if (wasRealized && !fromConfigure) {
+ WindowsRestructured ();
++ WindowGone(pWin);
++ }
+ return Success;
+ }
+
+@@ -2957,8 +2960,10 @@
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap);
+ }
+- if (wasRealized)
++ if (wasRealized) {
+ WindowsRestructured ();
++ WindowGone(pWin);
++ }
+ }
+
+
+Index: b/hw/xfree86/common/xf86Module.h
+===================================================================
+--- a/hw/xfree86/common/xf86Module.h 2011-03-09 11:39:57.000000000 +1100
++++ b/hw/xfree86/common/xf86Module.h 2011-03-09 13:13:06.226385017 +1100
+@@ -83,7 +83,7 @@
+ */
+ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
+ #define ABI_VIDEODRV_VERSION SET_ABI_VERSION(10, 0)
+-#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 2)
++#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 3)
+ #define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0)
+ #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
+
+Index: b/hw/xfree86/common/xf86Xinput.c
+===================================================================
+--- a/hw/xfree86/common/xf86Xinput.c 2011-02-28 16:57:00.000000000 +1100
++++ b/hw/xfree86/common/xf86Xinput.c 2011-03-09 13:11:48.113385173 +1100
+@@ -1352,6 +1352,16 @@
+ max_res, mode);
+ }
+
++void
++xf86InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label,
++ int minval, int maxval, int resolution)
++{
++ if (!dev || !dev->touch)
++ return;
++
++ InitTouchValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution);
++}
++
+ /*
+ * Set the valuator values to be in synch with dix/event.c
+ * DefineInitialRootWindow().
+@@ -1403,4 +1413,50 @@
+ EnableDevice(dev, TRUE);
+ }
+
++/**
++ * Post a touch event with optional valuators. If this is the first touch in
++ * the sequence, at least x & y valuators must be provided. If end is TRUE,
++ * then this is taken to be the last touch in the touch sequence.
++ */
++void
++xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
++ uint32_t flags, const ValuatorMask *mask)
++{
++ int i, nevents;
++ TouchPointInfoPtr ti = FindTouchPointByDDXID(dev, touchid);
++
++ if (ti && type == XI_TouchBegin)
++ {
++ xf86Msg(X_ERROR,
++ "%s: Tried to post touch begin for existing touch %u\n",
++ dev->name, touchid);
++ return;
++ }
++
++ if (!ti)
++ {
++ if (type != XI_TouchBegin)
++ {
++ xf86Msg(X_ERROR,
++ "%s: Tried to post event for non-existent touch %u\n",
++ dev->name, touchid);
++ return;
++ }
++
++ ti = BeginTouchPoint(dev, touchid);
++ if (!ti)
++ {
++ xf86Msg(X_ERROR, "%s: Couldn't create touchpoint\n", dev->name);
++ return;
++ }
++ }
++
++ if (type == XI_TouchEnd)
++ ti->ddx_pending_finish = TRUE;
++
++ nevents = GetTouchEvents(xf86Events, dev, ti, type, flags, mask);
++ for (i = 0; i < nevents; i++)
++ mieqEnqueue(dev, (InternalEvent *)((xf86Events + i)->event));
++}
++
+ /* end of xf86Xinput.c */
+Index: b/hw/xfree86/common/xf86Xinput.h
+===================================================================
+--- a/hw/xfree86/common/xf86Xinput.h 2011-02-28 13:56:40.000000000 +1100
++++ b/hw/xfree86/common/xf86Xinput.h 2011-03-09 13:11:48.113385173 +1100
+@@ -141,6 +141,9 @@
+ const int *valuators);
+ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code,
+ int is_down);
++extern _X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid,
++ uint16_t type, uint32_t flags,
++ const ValuatorMask *mask);
+ extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
+ extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
+ extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y);
+@@ -148,6 +151,8 @@
+ extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
+ int maxval, int resolution, int min_res,
+ int max_res, int mode);
++extern _X_EXPORT void xf86InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label,
++ int minval, int maxval, int resolution);
+ extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum);
+ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
+ extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
+Index: b/include/dix.h
+===================================================================
+--- a/include/dix.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/dix.h 2011-03-09 13:11:48.113385173 +1100
+@@ -375,7 +375,7 @@
+ extern GrabPtr CheckPassiveGrabsOnWindow(
+ WindowPtr /* pWin */,
+ DeviceIntPtr /* device */,
+- DeviceEvent * /* event */,
++ InternalEvent * /* event */,
+ BOOL /* checkCore */,
+ BOOL /* activate */);
+
+@@ -515,6 +515,11 @@
+ DeviceIntPtr /* dev */,
+ xEvent* /* events */);
+
++extern void RemoveTouchEventsFromQueue(
++ DeviceIntPtr /* dev */,
++ Bool /*touch*/,
++ Bool /*ignoreOwned*/);
++
+ #ifdef PANORAMIX
+ extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
+ #endif
+@@ -526,6 +531,8 @@
+
+ extern _X_EXPORT int ffs(int i);
+
++extern void init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms);
++
+
+ /*
+ * ServerGrabCallback stuff
+@@ -569,6 +576,7 @@
+ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+ extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+ extern Bool IsPointerEvent(InternalEvent *event);
++extern Bool IsTouchEvent(InternalEvent *event);
+ extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
+
+ extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+Index: b/include/events.h
+===================================================================
+--- a/include/events.h 2011-02-28 13:56:40.000000000 +1100
++++ b/include/events.h 2011-03-09 13:11:48.113385173 +1100
+@@ -26,6 +26,7 @@
+ #define EVENTS_H
+ typedef struct _DeviceEvent DeviceEvent;
+ typedef struct _DeviceChangedEvent DeviceChangedEvent;
++typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
+ #if XFreeXDGA
+ typedef struct _DGAEvent DGAEvent;
+ #endif
+Index: b/include/eventstr.h
+===================================================================
+--- a/include/eventstr.h 2011-02-28 16:57:00.000000000 +1100
++++ b/include/eventstr.h 2011-03-09 13:11:48.113385173 +1100
+@@ -65,6 +65,11 @@
+ ET_RawButtonRelease,
+ ET_RawMotion,
+ ET_XQuartz,
++ ET_TouchBegin,
++ ET_TouchEnd,
++ ET_TouchMotion,
++ ET_TouchMotionUnowned,
++ ET_TouchOwnership,
+ ET_Internal = 0xFF /* First byte */
+ };
+
+@@ -90,6 +95,7 @@
+ union {
+ uint32_t button; /**< Button number */
+ uint32_t key; /**< Key code */
++ uint32_t touch; /**< Touch ID (client_id) */
+ } detail;
+ int16_t root_x; /**< Pos relative to root window in integral data */
+ float root_x_frac; /**< Pos relative to root window in frac part */
+@@ -117,8 +123,28 @@
+ 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 */
++ TouchPointInfoPtr touchpoint;
++ Bool check_grab;
+ };
+
++/**
++ * Generated internally whenever a touch ownership chain changes - an owner
++ * has accepted or rejected a touch, or a grab/event selection in the delivery
++ * chain has been removed.
++ */
++struct _TouchOwnershipEvent
++{
++ 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 */
++ uint32_t touchid; /**< Touch ID (client_id) */
++ uint32_t resource; /**< Provoking grab or event selection */
++ uint32_t flags; /**< Flags to be copied into the generated event */
++};
+
+ /* Flags used in DeviceChangedEvent to signal if the slave has changed */
+ #define DEVCHANGE_SLAVE_SWITCH 0x2
+@@ -234,6 +260,7 @@
+ } any;
+ DeviceEvent device_event;
+ DeviceChangedEvent changed_event;
++ TouchOwnershipEvent touch_ownership_event;
+ #if XFreeXDGA
+ DGAEvent dga_event;
+ #endif
+Index: b/include/exevents.h
+===================================================================
+--- a/include/exevents.h 2011-03-04 14:03:20.000000000 +1100
++++ b/include/exevents.h 2011-03-09 13:11:48.113385173 +1100
+@@ -51,6 +51,14 @@
+ int /* max_res */,
+ int /* mode */);
+
++extern _X_EXPORT void InitTouchValuatorAxisStruct(
++ DeviceIntPtr /* dev */,
++ int /* axnum */,
++ Atom /* label */,
++ int /* minval */,
++ int /* maxval */,
++ int /* resolution */);
++
+ /* Input device properties */
+ extern _X_EXPORT void XIDeleteAllDeviceProperties(
+ DeviceIntPtr /* device */
+@@ -199,6 +207,14 @@
+ GrabMask* /* eventMask */);
+
+ extern int
++GrabTouch(
++ ClientPtr /* client */,
++ DeviceIntPtr /* dev */,
++ DeviceIntPtr /* mod_dev */,
++ GrabParameters* /* param */,
++ GrabMask* /* eventMask */);
++
++extern int
+ SelectForWindow(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* pWin */,
+@@ -222,6 +238,10 @@
+ WindowPtr /* pWin */,
+ XID /* id */);
+
++extern void
++WindowGone(
++ WindowPtr /* win */);
++
+ extern int
+ SendEvent (
+ ClientPtr /* client */,
+@@ -309,4 +329,14 @@
+ extern int
+ XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len);
+
++extern void
++ProcessTouchOwnership(DeviceIntPtr dev, TouchPointInfoPtr ti, uint8_t reason,
++ Bool touch_grab);
++
++extern int
++DeliverTouchOwnershipEvent(TouchClientPtr client, TouchPointInfoPtr ti);
++
++extern int
++ReleaseButton(DeviceIntPtr device, int button);
++
+ #endif /* EXEVENTS_H */
+Index: b/include/input.h
+===================================================================
+--- a/include/input.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/input.h 2011-03-09 13:11:48.113385173 +1100
+@@ -104,6 +104,8 @@
+ typedef struct _DeviceIntRec *DeviceIntPtr;
+ typedef struct _ClassesRec *ClassesPtr;
+ typedef struct _SpriteRec *SpritePtr;
++typedef struct _TouchClassRec *TouchClassPtr;
++typedef struct _TouchPointInfo *TouchPointInfoPtr;
+ typedef union _GrabMask GrabMask;
+
+ typedef struct _EventList {
+@@ -314,6 +316,12 @@
+ extern _X_EXPORT Bool InitFocusClassDeviceStruct(
+ DeviceIntPtr /*device*/);
+
++extern _X_EXPORT Bool InitTouchClassDeviceStruct(
++ DeviceIntPtr /*device*/,
++ unsigned int /*max_touches*/,
++ unsigned int /*mode*/,
++ unsigned int /*numAxes*/);
++
+ typedef void (*BellProcPtr)(
+ int /*percent*/,
+ DeviceIntPtr /*device*/,
+@@ -463,6 +471,22 @@
+ int key_code,
+ const ValuatorMask *mask);
+
++extern int GetTouchEvents(
++ EventListPtr events,
++ DeviceIntPtr pDev,
++ TouchPointInfoPtr ti,
++ uint16_t type,
++ uint32_t flags,
++ const ValuatorMask *mask);
++
++extern int GetTouchOwnershipEvents(
++ EventListPtr events,
++ DeviceIntPtr pDev,
++ TouchPointInfoPtr ti,
++ uint8_t mode,
++ XID resource,
++ uint32_t flags);
++
+ extern int GetProximityEvents(
+ EventListPtr events,
+ DeviceIntPtr pDev,
+@@ -525,6 +549,18 @@
+ extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs);
+ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs);
+
++/* DDX touch API: create with CreateTouchPoint, use its returned ID to lookup
++ * with FindTouchPoint, and eventually end with FinishTouchPoint. */
++extern TouchPointInfoPtr BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id);
++extern TouchPointInfoPtr FindTouchPointByDDXID(DeviceIntPtr dev,
++ uint32_t ddx_id);
++extern TouchPointInfoPtr FindTouchPointByClientID(DeviceIntPtr dev,
++ uint32_t client_id);
++extern void EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti);
++/* Internal use only, DDX this is not for you */
++extern Bool InitTouchPoint(TouchClassPtr touch, int index);
++extern void FreeTouchPoint(DeviceIntPtr dev, int index);
++
+ /* misc event helpers */
+ extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
+ extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);
+Index: b/include/inputstr.h
+===================================================================
+--- a/include/inputstr.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/inputstr.h 2011-03-09 13:11:48.113385173 +1100
+@@ -49,6 +49,8 @@
+ #ifndef INPUTSTRUCT_H
+ #define INPUTSTRUCT_H
+
++#include <X11/extensions/XI2proto.h>
++
+ #include <pixman.h>
+ #include "input.h"
+ #include "window.h"
+@@ -71,7 +73,7 @@
+ * events to the protocol, the server will not support these events until
+ * this number here is bumped.
+ */
+-#define XI2LASTEVENT 17 /* XI_RawMotion */
++#define XI2LASTEVENT XI_TouchUpdateUnowned
+ #define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */
+
+ /**
+@@ -244,6 +246,9 @@
+
+ } SpriteRec;
+
++#define DeepestSpriteWin(sprite) \
++ ((sprite)->spriteTrace[(sprite)->spriteTraceGood - 1])
++
+ typedef struct _KeyClassRec {
+ int sourceid;
+ CARD8 down[DOWN_LENGTH];
+@@ -254,11 +259,11 @@
+
+ typedef struct _AxisInfo {
+ int resolution;
+- int min_resolution;
+- int max_resolution;
+ int min_value;
+ int max_value;
+ Atom label;
++ int min_resolution;
++ int max_resolution;
+ CARD8 mode;
+ } AxisInfo, *AxisInfoPtr;
+
+@@ -284,6 +289,75 @@
+ ValuatorAccelerationRec accelScheme;
+ } ValuatorClassRec, *ValuatorClassPtr;
+
++typedef enum {
++ TOUCH_GRAB,
++ TOUCH_SELECT,
++ TOUCH_SELECT_UNOWNED
++} TouchClientType;
++
++typedef struct _TouchClientRec {
++ ClientPtr client;
++ WindowPtr window;
++ TouchClientType type;
++ DeviceIntPtr device;
++ DeviceIntPtr source;
++ GrabPtr grab;
++} TouchClientRec, *TouchClientPtr;
++
++typedef struct _TouchPointInfo {
++ DeviceIntPtr source;
++ Bool active; /* whether or not the touch is active */
++ Bool pending_finish; /* true if the touch is physically inactive
++ * but still owned by a grab */
++ Bool ddx_pending_finish;
++ uint32_t client_id; /* touch ID as seen in client events */
++ uint32_t ddx_id; /* touch ID given by the DDX */
++ SpriteRec sprite; /* window trace for delivery */
++ TouchClientPtr clients;
++ int num_clients;
++ int active_clients;
++ int owner;
++ Bool accepted;
++ int *valuators; /* last recorded axis values */
++ int num_valuators; /* == TouchClassInfo::num_axes */
++#if 0
++ XID *listeners; /* grabs/event selection IDs receiving
++ * events for this touch */
++ int num_listeners;
++ int num_grabs; /* number of open grabs on this touch
++ * which have not accepted or rejected */
++ WindowPtr select_win;
++ Bool select_unowned;
++#endif
++ Bool emulate_pointer;
++ InternalEvent *begin_event; /* Touch begin event for history */
++ InternalEvent *history; /* Touch motion and end history events */
++ unsigned int history_size; /* Size of history ring buffer */
++ InternalEvent *first_history; /* Pointer to first event in history */
++ InternalEvent *next_history; /* Pointer to next available event */
++} TouchPointInfoRec;
++
++typedef struct _TouchAxisInfo {
++ int resolution;
++ int min_value;
++ int max_value;
++ Atom label;
++} TouchAxisInfoRec, *TouchAxisInfoPtr;
++
++typedef struct _TouchClassRec {
++ TouchAxisInfoPtr axes;
++ unsigned short num_axes;
++ TouchPointInfoPtr touches;
++ unsigned short num_touches; /* number of allocated touches */
++ unsigned short max_touches; /* maximum number of touches, may be 0 */
++ unsigned short active_touches; /* number of active touches */
++ CARD8 mode; /* ::XIDirectTouch, XIDependentTouch */
++ uint32_t next_client_id; /* next client_id to give out */
++ int x_axis; /* axis number of x axis */
++ int y_axis; /* axis number of y axis */
++ TouchPointInfoPtr emulate;
++} TouchClassRec;
++
+ typedef struct _ButtonClassRec {
+ int sourceid;
+ CARD8 numButtons;
+@@ -388,6 +462,7 @@
+ typedef struct _ClassesRec {
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
++ TouchClassPtr touch;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+@@ -512,6 +587,7 @@
+ int id;
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
++ TouchClassPtr touch;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+@@ -533,6 +609,8 @@
+ DeviceIntPtr master; /* master device */
+ DeviceIntPtr lastSlave; /* last slave device used */
+ } u;
++ DeviceIntPtr emulate_dev;
++ Bool process_touch;
+
+ /* last valuator values recorded, not posted to client;
+ * for slave devices, valuators is in device coordinates
+@@ -592,7 +670,7 @@
+ */
+ typedef struct _EventSyncInfo {
+ QdEventPtr pending, /**< list of queued events */
+- *pendtail; /**< last event in list */
++ pendtail; /**< last event in list */
+ /** The device to replay events for. Only set in AllowEvents(), in which
+ * case it is set to the device specified in the request. */
+ DeviceIntPtr replayDev; /* kludgy rock to put flag for */
+Index: b/include/protocol-versions.h
+===================================================================
+--- a/include/protocol-versions.h 2011-03-09 11:39:57.000000000 +1100
++++ b/include/protocol-versions.h 2011-03-09 13:11:48.113385173 +1100
+@@ -131,7 +131,7 @@
+
+ /* X Input */
+ #define SERVER_XI_MAJOR_VERSION 2
+-#define SERVER_XI_MINOR_VERSION 0
++#define SERVER_XI_MINOR_VERSION 1
+
+ /* XKB */
+ #define SERVER_XKB_MAJOR_VERSION 1
+Index: b/mi/mieq.c
+===================================================================
+--- a/mi/mieq.c 2011-03-09 11:19:13.000000000 +1100
++++ b/mi/mieq.c 2011-03-09 13:11:48.113385173 +1100
+@@ -269,8 +269,15 @@
+ case ET_ProximityOut:
+ case ET_Hierarchy:
+ case ET_DeviceChanged:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
+ event->device_event.deviceid = dev->id;
+ break;
++ case ET_TouchOwnership:
++ event->touch_ownership_event.deviceid = dev->id;
++ break;
+ #if XFreeXDGA
+ case ET_DGAEvent:
+ break;
+@@ -419,7 +426,7 @@
+
+ /* Check for the SD's master in case the device got detached
+ * during event processing */
+- if (master && dev->u.master)
++ if (master && dev->u.master && !IsTouchEvent(&mevent))
+ master->public.processInputProc(&mevent, master);
+ }
+ }
+Index: b/test/input.c
+===================================================================
+--- a/test/input.c 2011-03-09 11:39:57.000000000 +1100
++++ b/test/input.c 2011-03-09 13:12:49.355737608 +1100
+@@ -278,6 +278,11 @@
+ dix_event_to_core_fail(ET_ProximityOut + 1, BadImplementation);
+ dix_event_to_core_fail(ET_ProximityIn, BadMatch);
+ dix_event_to_core_fail(ET_ProximityOut, BadMatch);
++ dix_event_to_core_fail(ET_TouchBegin, BadMatch);
++ dix_event_to_core_fail(ET_TouchMotion, BadMatch);
++ dix_event_to_core_fail(ET_TouchMotionUnowned, BadMatch);
++ dix_event_to_core_fail(ET_TouchOwnership, BadMatch);
++ dix_event_to_core_fail(ET_TouchEnd, BadMatch);
+
+ dix_event_to_core(ET_KeyPress);
+ dix_event_to_core(ET_KeyRelease);
+@@ -423,6 +428,32 @@
+ }
+
+
++static void dix_event_to_xi2_conversion(void)
++{
++ DeviceEvent ev;
++ xXIDeviceEvent *xi2, *xi2_flags;
++ int rc;
++
++ memset(&ev, 0, sizeof(ev));
++
++ ev.header = 0xFF;
++ ev.length = sizeof(DeviceEvent);
++ ev.type = ET_TouchBegin;
++
++ rc = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2);
++ g_assert(rc == Success);
++ g_assert(xi2->type == GenericEvent);
++ g_assert(xi2->evtype == XI_TouchBegin);
++ g_assert(xi2->flags == 0);
++
++ rc = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2_flags);
++ g_assert(rc == Success);
++ g_assert(xi2_flags->type == GenericEvent);
++ g_assert(xi2_flags->evtype == XI_TouchBegin);
++ xi2_flags->flags = 0;
++ g_assert(memcmp(xi2, xi2_flags, sizeof(*xi2)) == 0);
++}
++
+ static void xi2_struct_sizes(void)
+ {
+ #define compare(req) \
+@@ -812,6 +843,38 @@
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
++
++ /* All touch grabs must match a TouchBegin grab. */
++ a.grabtype = GRABTYPE_XI2;
++ b.grabtype = GRABTYPE_XI2;
++ a.type = XI_TouchBegin;
++ b.type = XI_TouchUpdate;
++ a.detail.exact = 0;
++ b.detail.exact = 0;
++ a.modifiersDetail.exact = 0;
++ b.modifiersDetail.exact = 0;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchUpdateUnowned;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchOwnership;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchEnd;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
+ }
+
+ static void test_bits_to_byte(int i)
+@@ -1199,6 +1262,101 @@
+ }
+ }
+
++static void touch_create(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr ti;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ /* Make sure we get a valid touchpoint back. */
++ ti = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(ti);
++ g_assert(ti->active == TRUE);
++ g_assert(ti->ddx_id == 0xdeadbeef);
++ g_assert(ti->client_id != 0);
++ g_assert(ti->pending_finish == 0);
++ g_assert(ti->sprite.spriteTraceGood == 0);
++}
++
++static void touch_find_point(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr create_ret, find_ret;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ create_ret = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(create_ret);
++
++ /* Make sure we can find the touch by both DDX and client ID. */
++ find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
++ g_assert(create_ret == find_ret);
++ find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
++ g_assert(find_ret->active == TRUE);
++ g_assert(find_ret->ddx_id == 0xdeadbeef);
++
++ /* Touches which are pending finish must be findable by their client ID,
++ * but not by their DDX ID, as only the DIX can inject ownership change
++ * events. */
++ find_ret->ddx_pending_finish = 1;
++ find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
++ g_assert(find_ret == create_ret);
++ find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
++ g_assert(!find_ret);
++}
++
++static void touch_finish(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr ti;
++ uint32_t client_id;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ /* Make sure the touch is in a sane state once we kill it, and that we
++ * can't find it once it's gone. */
++ ti = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(ti);
++ client_id = ti->client_id;
++ EndTouchPoint(&dev, ti);
++ g_assert(ti->active == FALSE);
++ g_assert(ti->pending_finish == 0);
++ g_assert(ti->sprite.spriteTraceGood == 0);
++ g_assert(ti->client_id == 0);
++ g_assert(ti->ddx_id == 0);
++
++ g_assert(FindTouchPointByDDXID(&dev, 0xdeadbeef) == NULL);
++ g_assert(FindTouchPointByClientID(&dev, client_id) == NULL);
++}
++
+ int main(int argc, char** argv)
+ {
+ g_test_init(&argc, &argv,NULL);
+@@ -1209,6 +1367,7 @@
+ g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
+ g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
+ g_test_add_func("/dix/input/event-xi1-conversion", dix_event_to_xi1_conversion);
++ g_test_add_func("/dix/input/event-xi2-conversion", dix_event_to_xi2_conversion);
+ g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
+ g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
+ g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
+@@ -1397,6 +1397,11 @@
+ g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
+ g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
+ g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
++
++ g_test_add_func("/dix/input/touch-create", touch_create);
++ g_test_add_func("/dix/input/touch-find-point", touch_find_point);
++ g_test_add_func("/dix/input/touch-finish", touch_finish);
++
+ g_test_add_func("/dix/input/valuator-alloc", dix_valuator_alloc);
+
+ return g_test_run();
+Index: b/test/xi2/protocol-eventconvert.c
+===================================================================
+--- a/test/xi2/protocol-eventconvert.c 2011-02-28 16:57:00.000000000 +1100
++++ b/test/xi2/protocol-eventconvert.c 2011-03-09 13:11:48.123385564 +1100
+@@ -149,6 +149,59 @@
+ free(swapped);
+ }
+
++static void test_values_XITouchOwnershipEvent(TouchOwnershipEvent *in,
++ xXITouchOwnershipEvent *out,
++ BOOL swap)
++{
++ char n;
++
++ if (swap)
++ {
++ swaps(&out->sequenceNumber, n);
++ swapl(&out->length, n);
++ swaps(&out->evtype, n);
++ swaps(&out->deviceid, n);
++ swapl(&out->time, n);
++ swaps(&out->sourceid, n);
++ swapl(&out->touchid, n);
++ swapl(&out->flags, n);
++ }
++
++ g_assert(out->type == GenericEvent);
++ g_assert(out->extension == 0);
++ g_assert(out->length == bytes_to_int32(sizeof(*out) - sizeof(xEvent)));
++ g_assert(out->evtype == XI_TouchOwnership);
++ g_assert(out->deviceid == in->deviceid);
++ g_assert(out->time == in->time);
++ g_assert(out->sourceid == in->sourceid);
++ g_assert(out->touchid == in->touchid);
++ g_assert(out->flags == in->flags);
++}
++
++static void test_convert_XITouchOwnershipEvent(void)
++{
++ TouchOwnershipEvent in;
++ xXITouchOwnershipEvent *out, swapped;
++ int rc;
++
++ in.header = ET_Internal;
++ in.type = ET_TouchOwnership;
++ in.touchid = 0xdeadbeef;
++ in.time = 234;
++ in.deviceid = 12;
++ in.sourceid = 14;
++ in.resource = 0xcafebabe;
++ in.flags = 0;
++ rc = EventToXI2((InternalEvent *) &in, (xEvent **) &out);
++ g_assert(rc == Success);
++
++ test_values_XITouchOwnershipEvent(&in, out, FALSE);
++ XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)&swapped);
++ test_values_XITouchOwnershipEvent(&in, &swapped, TRUE);
++
++ free(out);
++}
++
+ static void test_convert_XIFocusEvent(void)
+ {
+ xEvent *out;
+@@ -272,7 +325,7 @@
+ int buttons, valuators;
+ int i;
+ unsigned char *ptr;
+- uint32_t flagmask = 0;
++ uint32_t flagmask;
+ FP3232 *values;
+
+ if (swap) {
+@@ -311,9 +364,16 @@
+ g_assert(out->sourceid == in->sourceid);
+
+ switch (in->type) {
++ case ET_ButtonPress:
++ case ET_ButtonRelease:
++ case ET_Motion:
++ flagmask = XIPointerEmulated;
++ break;
+ case ET_KeyPress:
+ flagmask = XIKeyRepeat;
+ break;
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
+ default:
+ flagmask = 0;
+ break;
+@@ -636,6 +696,49 @@
+ }
+ }
+
++static void test_convert_XITouch(void)
++{
++ DeviceEvent in;
++
++ memset(&in, 0, sizeof(in));
++
++ g_test_message("Testing TouchBegin");
++ in.header = ET_Internal;
++ in.type = ET_TouchBegin;
++ in.length = sizeof(DeviceEvent);
++ in.time = 0;
++ in.deviceid = 1;
++ in.sourceid = 2;
++ in.root = 3;
++ in.root_x = 4;
++ in.root_x_frac = 5;
++ in.root_y = 6;
++ in.root_y_frac = 7;
++ in.detail.button = 8;
++ in.mods.base = 9;
++ in.mods.latched = 10;
++ in.mods.locked = 11;
++ in.mods.effective = 11;
++ in.group.base = 12;
++ in.group.latched = 13;
++ in.group.locked = 14;
++ in.group.effective = 15;
++ test_XIDeviceEvent(&in);
++
++ in.flags = 0;
++ g_test_message("Testing TouchMotion");
++ in.type = ET_TouchMotion;
++ test_XIDeviceEvent(&in);
++
++ g_test_message("Testing TouchMotionUnowned");
++ in.type = ET_TouchMotionUnowned;
++ test_XIDeviceEvent(&in);
++
++ g_test_message("Testing TouchEnd");
++ in.type = ET_TouchEnd;
++ test_XIDeviceEvent(&in);
++}
++
+ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
+ xXIDeviceChangedEvent *out,
+ BOOL swap)
+@@ -912,6 +1015,8 @@
+ g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
++ g_test_add_func("/xi2/eventconvert/XITouch", test_convert_XITouch);
++ g_test_add_func("/xi2/eventconvert/XITouchOwnership", test_convert_XITouchOwnershipEvent);
+
+ return g_test_run();
+ }
+Index: b/test/xi2/protocol-xiselectevents.c
+===================================================================
+--- a/test/xi2/protocol-xiselectevents.c 2011-02-28 16:57:00.000000000 +1100
++++ b/test/xi2/protocol-xiselectevents.c 2011-03-09 13:11:48.123385564 +1100
+@@ -159,9 +159,33 @@
+ memset(bits, 0, mask->mask_len * 4);
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ ClearBit(bits, j);
++
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ ClearBit(bits, XI_TouchBegin);
++ ClearBit(bits, XI_TouchUpdate);
++ ClearBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ ClearBit(bits, XI_TouchOwnership);
++ }
+ }
+
+ /* Test 2:
+@@ -175,7 +199,23 @@
+
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ }
+
+@@ -189,7 +229,23 @@
+
+ for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, BadValue);
+ ClearBit(bits, j);
+ }
+@@ -202,7 +258,23 @@
+ memset(bits, 0, mask->mask_len * 4);
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ }
+
diff --git a/x11-base/xorg-server/files/xorg-server-1.9-nouveau-default.patch b/x11-base/xorg-server/files/xorg-server-1.9-nouveau-default.patch
new file mode 100644
index 0000000..2b05967
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-1.9-nouveau-default.patch
@@ -0,0 +1,30 @@
+diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c
+index 74016af..9c296f5 100644
+--- a/hw/xfree86/common/xf86pciBus.c
++++ b/hw/xfree86/common/xf86pciBus.c
+@@ -1118,7 +1118,23 @@ videoPtrToDriverList(struct pci_device *dev,
+ break;
+ case 0x102b: driverList[0] = "mga"; break;
+ case 0x10c8: driverList[0] = "neomagic"; break;
+- case 0x10de: case 0x12d2: driverList[0] = "nv"; break;
++ case 0x10de: case 0x12d2:
++ switch (dev->device_id) {
++ /* NV1 */
++ case 0x0008:
++ case 0x0009:
++ driverList[0] = "vesa";
++ break;
++ /* NV3 */
++ case 0x0018:
++ case 0x0019:
++ driverList[0] = "nv";
++ break;
++ default:
++ driverList[0] = "nouveau";
++ break;
++ }
++ break;
+ case 0x1106: driverList[0] = "openchrome"; break;
+ case 0x1b36: driverList[0] = "qxl"; break;
+ case 0x1163: driverList[0] = "rendition"; break;
+--
diff --git a/x11-base/xorg-server/files/xorg-server-disable-acpi.patch b/x11-base/xorg-server/files/xorg-server-disable-acpi.patch
new file mode 100644
index 0000000..cc80e6c
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-disable-acpi.patch
@@ -0,0 +1,31 @@
+From a8079882f1884edc62a9de28af915bd8b65dfbbe Mon Sep 17 00:00:00 2001
+From: Adam Jackson <ajax@redhat.com>
+Date: Wed, 11 Mar 2009 14:02:11 -0400
+Subject: [PATCH] Don't build the ACPI code.
+
+No good can come of this.
+---
+ configure.ac | 2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 72ae67e..04716f8 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1269,13 +1269,11 @@ if test "x$XORG" = xyes; then
+ case $host_cpu in
+ ia64*)
+ linux_ia64=yes
+- linux_acpi="yes"
+ ;;
+ alpha*)
+ linux_alpha=yes
+ ;;
+ i*86|amd64*|x86_64*)
+- linux_acpi="yes"
+ ;;
+ *)
+ ;;
+--
+1.6.1.3
+
diff --git a/x11-base/xorg-server/files/xorg-server-gestures-extension.patch b/x11-base/xorg-server/files/xorg-server-gestures-extension.patch
new file mode 100644
index 0000000..0dc223f
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-gestures-extension.patch
@@ -0,0 +1,1488 @@
+diff --git a/Makefile.am b/Makefile.am
+index 62c8d95..77b2ffb 100644
+--- a/Makefile.am
++++ b/Makefile.am
+@@ -17,6 +17,10 @@ if RECORD
+ RECORD_DIR=record
+ endif
+
++if GESTURES
++GESTURE_DIR=gesture
++endif
++
+ SUBDIRS = \
+ doc \
+ include \
+@@ -37,6 +41,7 @@ SUBDIRS = \
+ $(COMPOSITE_DIR) \
+ $(GLX_DIR) \
+ exa \
++ $(GESTURE_DIR) \
+ config \
+ hw \
+ test
+diff --git a/configure.ac b/configure.ac
+index 5e22ddf..d913468 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -592,6 +592,8 @@ AC_ARG_ENABLE(visibility, AC_HELP_STRING([--enable-visibility], [Enable symb
+ AC_ARG_ENABLE(pc98, AC_HELP_STRING([--enable-pc98], [Enable PC98 support in Xorg (default: auto)]),
+ [SUPPORT_PC98=$enableval],
+ [SUPPORT_PC98=auto])
++AC_ARG_ENABLE(gestures, AC_HELP_STRING([--enable-gestures], [Enable gesture support (default: disabled)]),
++ [GESTURES=$enableval])
+
+ dnl GLX build options
+ AC_ARG_ENABLE(aiglx, AS_HELP_STRING([--enable-aiglx], [Build accelerated indirect GLX (default: enabled)]),
+@@ -1349,6 +1351,13 @@ MIEXT_SYNC_INC='-I$(top_srcdir)/miext/sync'
+ MIEXT_SYNC_LIB='$(top_builddir)/miext/sync/libsync.la'
+ CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include'
+
++AM_CONDITIONAL(GESTURES, [test "x$GESTURES" = "xyes"])
++if test "x$GESTURES" = xyes; then
++ AC_DEFINE(GESTURES, 1, [Enable gesture support])
++ GESTURE_LIB='$(top_builddir)/gesture/libgesture.la'
++ GESTURE_INC='-I$(top_srcdir)/gesture'
++fi
++
+ # SHA1 hashing
+ AC_ARG_WITH([sha1],
+ [AS_HELP_STRING([--with-sha1=libc|libmd|libgcrypt|libcrypto|libsha1|CommonCrypto],
+@@ -1486,7 +1495,7 @@ AC_EGREP_CPP([I_AM_SVR4],[
+ AC_DEFINE([SVR4],1,[Define to 1 on systems derived from System V Release 4])
+ AC_MSG_RESULT([yes])], AC_MSG_RESULT([no]))
+
+-XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC"
++XSERVER_CFLAGS="$XSERVER_CFLAGS $CORE_INCS $XEXT_INC $COMPOSITE_INC $DAMAGE_INC $FIXES_INC $XI_INC $MI_INC $MIEXT_SYNC_INC $MIEXT_SHADOW_INC $MIEXT_LAYER_INC $MIEXT_DAMAGE_INC $RENDER_INC $RANDR_INC $FB_INC $GESTURE_INC"
+
+ dnl ---------------------------------------------------------------------------
+ dnl DDX section.
+@@ -1499,7 +1508,7 @@ AC_MSG_RESULT([$XVFB])
+ AM_CONDITIONAL(XVFB, [test "x$XVFB" = xyes])
+
+ if test "x$XVFB" = xyes; then
+- XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB"
++ XVFB_LIBS="$FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $GESTURE_LIB"
+ XVFB_SYS_LIBS="$XVFBMODULES_LIBS $GLX_SYS_LIBS"
+ AC_SUBST([XVFB_LIBS])
+ AC_SUBST([XVFB_SYS_LIBS])
+@@ -1520,7 +1529,7 @@ if test "x$XNEST" = xyes; then
+ if test "x$have_xnest" = xno; then
+ AC_MSG_ERROR([Xnest build explicitly requested, but required modules not found.])
+ fi
+- XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB"
++ XNEST_LIBS="$FB_LIB $FIXES_LIB $MI_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DIX_LIB $MAIN_LIB $OS_LIB $GESTURE_LIB"
+ XNEST_SYS_LIBS="$XNESTMODULES_LIBS $GLX_SYS_LIBS"
+ AC_SUBST([XNEST_LIBS])
+ AC_SUBST([XNEST_SYS_LIBS])
+@@ -1548,7 +1557,7 @@ if test "x$XORG" = xyes; then
+ XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os'
+ XORG_INCS="$XORG_DDXINCS $XORG_OSINCS"
+ XORG_CFLAGS="$XORGSERVER_CFLAGS -DHAVE_XORG_CONFIG_H"
+- XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB"
++ XORG_LIBS="$COMPOSITE_LIB $FIXES_LIB $XEXTXORG_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $GESTURE_LIB"
+
+ dnl ==================================================================
+ dnl symbol visibility
+@@ -1883,7 +1892,7 @@ if test "x$XWIN" = xyes; then
+ XWIN_SYS_LIBS=-lwinsock2
+ ;;
+ esac
+- XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB"
++ XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB $GESTURE_LIB"
+ XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS"
+ AC_SUBST(XWIN_LIBS)
+ AC_SUBST(XWIN_SERVER_NAME)
+@@ -1913,7 +1922,7 @@ if test "x$XQUARTZ" = xyes; then
+ AC_DEFINE(XQUARTZ,1,[Have Quartz])
+ AC_DEFINE(ROOTLESS,1,[Build Rootless code])
+
+- DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB"
++ DARWIN_LIBS="$MI_LIB $OS_LIB $DIX_LIB $MAIN_LIB $FB_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $XPSTUBS_LIB $GESTURE_LIB"
+ AC_SUBST([DARWIN_LIBS])
+
+ AC_CHECK_LIB([Xplugin],[xp_init],[:])
+@@ -1974,7 +1983,7 @@ if test "x$DMX" = xyes; then
+ fi
+ DMX_INCLUDES="$XEXT_INC $RENDER_INC $RECORD_INC"
+ XDMX_CFLAGS="$DMXMODULES_CFLAGS"
+- XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB"
++ XDMX_LIBS="$FB_LIB $MI_LIB $XEXT_LIB $RENDER_LIB $RECORD_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $MIEXT_SYNC_LIB $MIEXT_SHADOW_LIB $MIEXT_DAMAGE_LIB $COMPOSITE_LIB $DAMAGE_LIB $MAIN_LIB $DIX_LIB $CONFIG_LIB $OS_LIB $FIXES_LIB $GESTURE_LIB"
+ XDMX_SYS_LIBS="$DMXMODULES_LIBS"
+ AC_SUBST([XDMX_CFLAGS])
+ AC_SUBST([XDMX_LIBS])
+@@ -2085,7 +2094,7 @@ if test "$KDRIVE" = yes; then
+
+ KDRIVE_CFLAGS="$XSERVER_CFLAGS -DHAVE_KDRIVE_CONFIG_H $TSLIB_CFLAGS"
+
+- KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB"
++ KDRIVE_PURE_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $OS_LIB $GESTURE_LIB"
+ KDRIVE_LIB='$(top_builddir)/hw/kdrive/src/libkdrive.la'
+ case $host_os in
+ *linux*)
+@@ -2199,6 +2208,7 @@ Xext/Makefile
+ Xi/Makefile
+ xfixes/Makefile
+ exa/Makefile
++gesture/Makefile
+ hw/Makefile
+ hw/xfree86/Makefile
+ hw/xfree86/common/Makefile
+diff --git a/dix/events.c b/dix/events.c
+index 43803ab..5b778a1 100644
+--- a/dix/events.c
++++ b/dix/events.c
+@@ -5468,6 +5468,9 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
+ FreeResource(oc->resource, RT_NONE);
+ while ( (passive = wPassiveGrabs(pWin)) )
+ FreeResource(passive->resource, RT_NONE);
++#ifdef GESTURES
++ DeleteWindowFromGestureEvents(pWin);
++#endif
+ }
+
+ DeleteWindowFromAnyExtEvents(pWin, freeResources);
+diff --git a/dix/window.c b/dix/window.c
+index d05f76d..cc2c64f 100644
+--- a/dix/window.c
++++ b/dix/window.c
+@@ -404,6 +404,9 @@ CreateRootWindow(ScreenPtr pScreen)
+ pWin->optional->deviceCursors = NULL;
+ pWin->optional->colormap = pScreen->defColormap;
+ pWin->optional->visual = pScreen->rootVisual;
++#ifdef GESTURES
++ pWin->optional->gestureMasks = NULL;
++#endif
+
+ pWin->nextSib = NullWindow;
+
+@@ -3413,6 +3416,10 @@ CheckWindowOptionalNeed (WindowPtr w)
+ pNode = pNode->next;
+ }
+ }
++#ifdef GESTURES
++ if (optional->gestureMasks != NULL)
++ return;
++#endif
+
+ parentOptional = FindWindowWithOptional(w)->optional;
+ if (optional->visual != parentOptional->visual)
+@@ -3456,6 +3463,9 @@ MakeWindowOptional (WindowPtr pWin)
+ optional->inputShape = NULL;
+ optional->inputMasks = NULL;
+ optional->deviceCursors = NULL;
++#ifdef GESTURES
++ optional->gestureMasks = NULL;
++#endif
+
+ parentOptional = FindWindowWithOptional(pWin)->optional;
+ optional->visual = parentOptional->visual;
+diff --git a/gesture/Makefile.am b/gesture/Makefile.am
+new file mode 100644
+index 0000000..ab2543b
+--- /dev/null
++++ b/gesture/Makefile.am
+@@ -0,0 +1,10 @@
++noinst_LTLIBRARIES = libgesture.la
++
++AM_CFLAGS = $(DIX_CFLAGS)
++
++libgesture_la_SOURCES = \
++ init.c \
++ gesture.c \
++ gesture.h
++
++sdk_HEADERS = gesture.h
+diff --git a/gesture/gesture.c b/gesture/gesture.c
+new file mode 100644
+index 0000000..9d908f7
+--- /dev/null
++++ b/gesture/gesture.c
+@@ -0,0 +1,430 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Authors: Chase Douglas <chase.douglas@canonical.com>
++ *
++ */
++
++#include "windowstr.h"
++#include "gestureint.h"
++
++int
++SProcGestureQueryVersion(ClientPtr client)
++{
++ char n;
++
++ REQUEST(GestureQueryVersionReq);
++ swaps(&stuff->length, n);
++ REQUEST_AT_LEAST_SIZE(GestureQueryVersionReq);
++ swaps(&stuff->major_version, n);
++ swaps(&stuff->minor_version, n);
++ return (ProcGestureQueryVersion(client));
++}
++
++GestureExtensionVersion GestureVersion;
++/**
++ * Return the supported Gesture version.
++ *
++ * Saves the version the client claims to support as well, for future
++ * reference.
++ */
++int
++ProcGestureQueryVersion(ClientPtr client)
++{
++ GestureQueryVersionReply rep;
++ GestureClientPtr gestureClient;
++ int major, minor;
++ unsigned int sversion, cversion;
++
++ REQUEST(GestureQueryVersionReq);
++ REQUEST_SIZE_MATCH(GestureQueryVersionReq);
++
++ gestureClient = dixLookupPrivate(&client->devPrivates,
++ &GestureClientPrivateKeyRec);
++
++ sversion = GestureVersion.major_version * 1000 + GestureVersion.minor_version;
++ cversion = stuff->major_version * 1000 + stuff->minor_version;
++
++ if (sversion > cversion)
++ {
++ major = stuff->major_version;
++ minor = stuff->minor_version;
++ } else
++ {
++ major = GestureVersion.major_version;
++ minor = GestureVersion.minor_version;
++ }
++
++ gestureClient->major_version = major;
++ gestureClient->minor_version = minor;
++
++ memset(&rep, 0, sizeof(GestureQueryVersionReply));
++ rep.repType = X_Reply;
++ rep.RepType = X_GestureQueryVersion;
++ rep.length = 0;
++ rep.sequenceNumber = client->sequence;
++ rep.major_version = major;
++ rep.minor_version = minor;
++
++ WriteReplyToClient(client, sizeof(GestureQueryVersionReply), &rep);
++
++ return Success;
++}
++
++void
++SRepGestureQueryVersion(ClientPtr client, int size, GestureQueryVersionReply *rep)
++{
++ char n;
++ swaps(&rep->sequenceNumber, n);
++ swapl(&rep->length, n);
++ swaps(&rep->major_version, n);
++ swaps(&rep->minor_version, n);
++ WriteToClient(client, size, (char *)rep);
++}
++
++static Bool
++MakeGestureMasks(WindowPtr pWin)
++{
++ struct _GestureMasks *masks;
++
++ masks = calloc(1, sizeof(struct _GestureMasks));
++ if (!masks)
++ return FALSE;
++ pWin->optional->gestureMasks = masks;
++ return TRUE;
++}
++
++static int
++AddGestureClient(WindowPtr pWin, ClientPtr client)
++{
++ GestureClientsPtr others;
++
++ if (!pWin->optional && !MakeWindowOptional(pWin))
++ return BadAlloc;
++ others = calloc(1, sizeof(GestureClients));
++ if (!others)
++ return BadAlloc;
++ if (!pWin->optional->gestureMasks && !MakeGestureMasks(pWin))
++ return BadAlloc;
++ others->resource = FakeClientID(client->index);
++ others->next = pWin->optional->gestureMasks->clients;
++ pWin->optional->gestureMasks->clients = others;
++ if (!AddResource(others->resource, RT_GESTURECLIENT, (pointer) pWin))
++ return BadAlloc;
++ return Success;
++}
++
++/**
++ * Check the given mask (in len bytes) for invalid mask bits.
++ * Invalid mask bits are any bits above GestureLastEvent.
++ *
++ * @return BadValue if at least one invalid bit is set or Success otherwise.
++ */
++static int
++GestureCheckInvalidMaskBits(unsigned char *mask, int len)
++{
++ if (len >= GESTUREMASKSIZE)
++ {
++ int i;
++ for (i = GESTURELASTEVENT + 1; i < len * 8; i++)
++ if (BitIsOn(mask, i))
++ return BadValue;
++ }
++
++ return Success;
++}
++
++int
++SProcGestureSelectEvents(ClientPtr client)
++{
++ char n;
++ int i;
++
++ REQUEST(GestureSelectEventsReq);
++ swaps(&stuff->length, n);
++ REQUEST_AT_LEAST_SIZE(GestureSelectEventsReq);
++ swapl(&stuff->window, n);
++ swaps(&stuff->mask.device_id, n);
++ swaps(&stuff->mask.mask_len, n);
++
++ for (i = 0; i < stuff->mask.mask_len; i++)
++ swapl(((uint32_t *)(stuff + 1)) + i, n);
++
++ return (ProcGestureSelectEvents(client));
++}
++
++static void
++RecalculateGestureDeliverableEvents(WindowPtr win)
++{
++ GestureClientsPtr others;
++ int i;
++
++ if (!win->optional || !wGestureMasks(win))
++ return;
++
++ memset(&wGestureMasks(win)->mask, 0, sizeof(wGestureMasks(win)->mask));
++
++ for (others = wGestureMasks(win)->clients; others; others = others->next)
++ for (i = 0; i < sizeof(others->gestureMask) * 8; i++)
++ if (BitIsOn(&others->gestureMask, i))
++ SetBit(wGestureMasks(win)->mask, i % (GESTURELASTEVENT + 1));
++}
++
++static int
++GestureSetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
++ unsigned int len, unsigned char* mask)
++{
++ GestureMasks *masks;
++ GestureClientsPtr others = NULL;
++
++ masks = wGestureMasks(win);
++ if (masks)
++ {
++ for (others = masks->clients; others;
++ others = others->next) {
++ if (SameClient(others, client)) {
++ memset(others->gestureMask[dev->id], 0,
++ sizeof(others->gestureMask[dev->id]));
++ break;
++ }
++ }
++ }
++
++ len = min(len, sizeof(others->gestureMask[dev->id]));
++
++ if (len && !others)
++ {
++ if (AddGestureClient(win, client) != Success)
++ return BadAlloc;
++ masks = wGestureMasks(win);
++ others = masks->clients;
++ }
++
++ if (others)
++ memset(others->gestureMask[dev->id], 0,
++ sizeof(others->gestureMask[dev->id]));
++
++ if (len)
++ memcpy(others->gestureMask[dev->id], mask, len);
++
++ RecalculateGestureDeliverableEvents(win);
++
++ return Success;
++}
++
++int
++ProcGestureSelectEvents(ClientPtr client)
++{
++ int rc;
++ WindowPtr win;
++ DeviceIntPtr dev;
++ DeviceIntRec dummy;
++
++ REQUEST(GestureSelectEventsReq);
++ REQUEST_AT_LEAST_SIZE(GestureSelectEventsReq);
++
++ if (sizeof(GestureSelectEventsReq) + stuff->mask.mask_len * 4 >
++ stuff->length * 4)
++ return BadLength;
++
++ rc = dixLookupWindow(&win, stuff->window, client, DixReceiveAccess);
++ if (rc != Success)
++ return rc;
++
++ if (GestureCheckInvalidMaskBits((unsigned char*)(stuff + 1),
++ stuff->mask.mask_len * 4) != Success)
++ return BadValue;
++
++ if (stuff->mask.device_id == GestureAllDevices)
++ {
++ dummy.id = stuff->mask.device_id;
++ dev = &dummy;
++ } else {
++ rc = dixLookupDevice(&dev, stuff->mask.device_id, client, DixUseAccess);
++ if (rc != Success)
++ return rc;
++ }
++
++ if (GestureSetEventMask(dev, win, client, stuff->mask.mask_len * 4,
++ (unsigned char*)(stuff + 1)) != Success)
++ return BadAlloc;
++
++ return Success;
++}
++
++int
++SProcGestureGetSelectedEvents(ClientPtr client)
++{
++ char n;
++
++ REQUEST(GestureGetSelectedEventsReq);
++ swaps(&stuff->length, n);
++ REQUEST_SIZE_MATCH(GestureGetSelectedEventsReq);
++ swapl(&stuff->window, n);
++
++ return (ProcGestureGetSelectedEvents(client));
++}
++
++int
++ProcGestureGetSelectedEvents(ClientPtr client)
++{
++ int rc, i;
++ WindowPtr win;
++ char n;
++ char *buffer = NULL;
++ GestureGetSelectedEventsReply reply;
++ GestureMasks *masks;
++ GestureClientsPtr others = NULL;
++ GestureEventMask *evmask = NULL;
++ DeviceIntPtr dev;
++
++ REQUEST(GestureGetSelectedEventsReq);
++ REQUEST_SIZE_MATCH(GestureGetSelectedEventsReq);
++
++ rc = dixLookupWindow(&win, stuff->window, client, DixGetAttrAccess);
++ if (rc != Success)
++ return rc;
++
++ reply.repType = X_Reply;
++ reply.RepType = X_GestureGetSelectedEvents;
++ reply.length = 0;
++ reply.sequenceNumber = client->sequence;
++ reply.num_masks = 0;
++
++ masks = wGestureMasks(win);
++ if (masks)
++ {
++ for (others = masks->clients; others; others = others->next) {
++ if (SameClient(others, client)) {
++ break;
++ }
++ }
++ }
++
++ if (!others)
++ {
++ WriteReplyToClient(client, sizeof(GestureGetSelectedEventsReply), &reply);
++ return Success;
++ }
++
++ buffer = calloc(MAXDEVICES, sizeof(GestureEventMask) + pad_to_int32(GESTUREMASKSIZE));
++ if (!buffer)
++ return BadAlloc;
++
++ evmask = (GestureEventMask*)buffer;
++ for (i = 0; i < MAXDEVICES; i++)
++ {
++ int j;
++ unsigned char *devmask = others->gestureMask[i];
++
++ if (i > 2)
++ {
++ rc = dixLookupDevice(&dev, i, client, DixGetAttrAccess);
++ if (rc != Success)
++ continue;
++ }
++
++
++ for (j = GESTUREMASKSIZE - 1; j >= 0; j--)
++ {
++ if (devmask[j] != 0)
++ {
++ int mask_len = (j + 4)/4; /* j is an index, hence + 4, not + 3 */
++ evmask->device_id = i;
++ evmask->mask_len = mask_len;
++ reply.num_masks++;
++ reply.length += sizeof(GestureEventMask)/4 + evmask->mask_len;
++
++ if (client->swapped)
++ {
++ swaps(&evmask->device_id, n);
++ swaps(&evmask->mask_len, n);
++ }
++
++ memcpy(&evmask[1], devmask, j + 1);
++ evmask = (GestureEventMask*)((char*)evmask +
++ sizeof(GestureEventMask) + mask_len * 4);
++ break;
++ }
++ }
++ }
++
++ WriteReplyToClient(client, sizeof(GestureGetSelectedEventsReply), &reply);
++
++ if (reply.num_masks)
++ WriteToClient(client, reply.length * 4, buffer);
++
++ free(buffer);
++ return Success;
++}
++
++void
++SRepGestureGetSelectedEvents(ClientPtr client,
++ int len, GestureGetSelectedEventsReply *rep)
++{
++ char n;
++
++ swaps(&rep->sequenceNumber, n);
++ swapl(&rep->length, n);
++ swaps(&rep->num_masks, n);
++ WriteToClient(client, len, (char *)rep);
++}
++
++int
++GestureClientGone(WindowPtr pWin, XID id)
++{
++ GestureClientsPtr other, prev;
++
++ if (!wGestureMasks(pWin))
++ return (Success);
++ prev = 0;
++ for (other = wGestureMasks(pWin)->clients; other;
++ other = other->next) {
++ if (other->resource == id) {
++ if (prev) {
++ prev->next = other->next;
++ free(other);
++ } else if (!(other->next)) {
++ free(wGestureMasks(pWin));
++ pWin->optional->gestureMasks = (GestureMasks *) NULL;
++ CheckWindowOptionalNeed(pWin);
++ free(other);
++ } else {
++ wGestureMasks(pWin)->clients = other->next;
++ free(other);
++ }
++ RecalculateGestureDeliverableEvents(pWin);
++ return (Success);
++ }
++ prev = other;
++ }
++ FatalError("client not on device event list");
++}
++
++void
++DeleteWindowFromGestureEvents(WindowPtr pWin)
++{
++ struct _GestureMasks *gestureMasks;
++
++ while ((gestureMasks = wGestureMasks(pWin)) != 0)
++ FreeResource(gestureMasks->clients->resource, RT_NONE);
++}
+diff --git a/gesture/gesture.h b/gesture/gesture.h
+new file mode 100644
+index 0000000..3458b4e
+--- /dev/null
++++ b/gesture/gesture.h
+@@ -0,0 +1,78 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Authors: Chase Douglas <chase.douglas@canonical.com>
++ *
++ */
++
++#ifndef _GESTURE_H_
++#define _GESTURE_H_
++
++#ifdef HAVE_DIX_CONFIG_H
++#include <dix-config.h>
++#endif
++
++#include "inputstr.h"
++
++/* This is the last Gesture event supported by the server. If you add
++ * events to the protocol, the server will not support these events until
++ * this number here is bumped.
++ */
++#define GESTURELASTEVENT 63
++#define GESTUREMASKSIZE (GESTURELASTEVENT/8 + 1) /* no of bits for masks */
++
++extern _X_EXPORT int GestureReqCode;
++
++/**
++ * Attached to the devPrivates of each client. Specifies the version number as
++ * supported by the client.
++ */
++typedef struct _GestureClientRec {
++ int major_version;
++ int minor_version;
++} GestureClientRec, *GestureClientPtr;
++
++typedef struct _GestureClients *GestureClientsPtr;
++
++/**
++ * This struct stores the Gesture event mask for each client.
++ *
++ * Each window that has events selected has at least one of these masks. If
++ * multiple client selected for events on the same window, these masks are in
++ * a linked list.
++ */
++typedef struct _GestureClients {
++ GestureClientsPtr next; /**< Pointer to the next mask */
++ XID resource; /**< id for putting into resource manager */
++ /** Gesture event masks. One per device, each bit is a mask of (1 << type) */
++ unsigned char gestureMask[EMASKSIZE][GESTUREMASKSIZE];
++} GestureClients;
++
++typedef struct _GestureMasks {
++ GestureClientsPtr clients;
++ unsigned char mask[GESTUREMASKSIZE];
++} GestureMasks;
++
++extern int GestureClientGone(WindowPtr pWin, XID id);
++extern void DeleteWindowFromGestureEvents(WindowPtr pWin);
++
++#endif /* _GESTURE_H_ */
+diff --git a/gesture/gestureint.h b/gesture/gestureint.h
+new file mode 100644
+index 0000000..a16ada1
+--- /dev/null
++++ b/gesture/gestureint.h
+@@ -0,0 +1,49 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Authors: Chase Douglas <chase.douglas@canonical.com>
++ *
++ */
++
++#ifndef _GESTUREINT_H_
++#define _GESTUREINT_H_
++
++#include "gestureproto.h"
++
++typedef struct {
++ short major_version;
++ short minor_version;
++} GestureExtensionVersion;
++
++extern DevPrivateKeyRec GestureClientPrivateKeyRec;
++extern int RT_GESTURECLIENT;
++
++extern int ProcGestureQueryVersion(ClientPtr client);
++extern int ProcGestureSelectEvents(ClientPtr client);
++extern int ProcGestureGetSelectedEvents(ClientPtr client);
++extern int SProcGestureQueryVersion(ClientPtr client);
++extern int SProcGestureSelectEvents(ClientPtr client);
++extern int SProcGestureGetSelectedEvents(ClientPtr client);
++extern void SRepGestureQueryVersion(ClientPtr client, int size, GestureQueryVersionReply *rep);
++extern void SRepGestureGetSelectedEvents(ClientPtr client, int len, GestureGetSelectedEventsReply *rep);
++
++#endif /* _GESTUREINT_H_ */
+diff --git a/gesture/gestureproto.h b/gesture/gestureproto.h
+new file mode 100644
+index 0000000..a60dcb8
+--- /dev/null
++++ b/gesture/gestureproto.h
+@@ -0,0 +1,132 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Authors: Chase Douglas <chase.douglas@canonical.com>
++ *
++ */
++
++#ifndef _GESTUREPROTO_H_
++#define _GESTUREPROTO_H_
++
++#include <stdint.h>
++#include <X11/X.h>
++
++#define Window uint32_t
++#define Time uint32_t
++
++#define X_GestureQueryVersion 1
++#define X_GestureSelectEvents 2
++#define X_GestureGetSelectedEvents 3
++
++#define GESTUREREQUESTS (X_GestureGetSelectedEvents - X_GestureQueryVersion + 1)
++
++#define GestureAllDevices 0
++
++/**
++ * Used to select for events on a given window.
++ * Struct is followed by (mask_len * CARD8), with each bit set representing
++ * the event mask for the given type. A mask bit represents an event type if
++ * (mask == (1 << type)).
++ */
++typedef struct {
++ uint16_t device_id; /**< Device id to select for */
++ uint16_t mask_len; /**< Length of mask in 4 byte units */
++} GestureEventMask;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureQueryVersion */
++ uint16_t length; /**< Length in 4 byte units */
++ uint16_t major_version;
++ uint16_t minor_version;
++} GestureQueryVersionReq;
++
++typedef struct {
++ uint8_t repType; /**< ::X_Reply */
++ uint8_t RepType; /**< Always ::X_GestureQueryVersion */
++ uint16_t sequenceNumber;
++ uint32_t length;
++ uint16_t major_version;
++ uint16_t minor_version;
++ uint32_t pad1;
++ uint32_t pad2;
++ uint32_t pad3;
++ uint32_t pad4;
++ uint32_t pad5;
++} GestureQueryVersionReply;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureSelectEvents */
++ uint16_t length; /**< Length in 4 byte units */
++ Window window;
++ GestureEventMask mask;
++} GestureSelectEventsReq;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureGetSelectedEvents */
++ uint16_t length; /**< Length in 4 byte units */
++ Window window;
++} GestureGetSelectedEventsReq;
++
++typedef struct {
++ uint8_t repType; /**< Gesture extension major opcode */
++ uint8_t RepType; /**< Always ::X_GestureGetSelectedEvents */
++ uint16_t sequenceNumber;
++ uint32_t length;
++ uint16_t num_masks; /**< Number of GestureEventMask structs
++ trailing the reply */
++ uint16_t pad0;
++ uint32_t pad1;
++ uint32_t pad2;
++ uint32_t pad3;
++ uint32_t pad4;
++ uint32_t pad5;
++} GestureGetSelectedEventsReply;
++
++typedef struct
++{
++ uint8_t type; /**< Always GenericEvent */
++ uint8_t extension; /**< Gesture extension offset */
++ uint16_t sequenceNumber; /**< Xevent sequence number */
++ uint32_t length; /**< Length in 4 byte uints */
++ uint16_t evtype; /**< X generic event type */
++ uint16_t gesture_id; /**< Unique ID for gesture */
++ uint16_t gesture_type; /**< Gesture type (zoom, rotate, etc.) */
++ uint16_t device_id; /**< Device that generated this gesture */
++ Time time; /**< Time of gesture event */
++ Window root; /**< Root window event occurred on */
++ Window event; /**< Window selecting this event for a client */
++ Window child; /**< Top-most window of gesture event */
++/* └──────── 32 byte boundary ────────┘ */
++ float focus_x; /**< Always window coords, 16.16 fixed point */
++ float focus_y; /**< Relative to event window */
++ uint16_t status; /**< Gesture event status */
++ uint16_t num_props; /**< Number of properties for gesture event */
++/* └──── Gesture properties below ────┘ */
++} GestureEvent;
++
++#undef Window
++#undef Time
++
++#endif /* _GESTUREPROTO_H_ */
+diff --git a/gesture/init.c b/gesture/init.c
+new file mode 100644
+index 0000000..e3d7959
+--- /dev/null
++++ b/gesture/init.c
+@@ -0,0 +1,280 @@
++/************************************************************
++
++Copyright 2010 Canonical, Ltd.
++Copyright 1989, 1998 The Open Group
++
++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 Open Group 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 Open Group.
++
++Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
++
++ All Rights Reserved
++
++Permission to use, copy, modify, and distribute this software and its
++documentation for any purpose and without fee is hereby granted,
++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 Hewlett-Packard not be
++used in advertising or publicity pertaining to distribution of the
++software without specific, written prior permission.
++
++HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
++ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
++HEWLETT-PACKARD 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.
++
++********************************************************/
++
++/********************************************************************
++ *
++ * Dispatch routines and initialization routines for the X gesture extension.
++ *
++ */
++
++#define NUMTYPES 15
++
++#ifdef HAVE_DIX_CONFIG_H
++#include <dix-config.h>
++#endif
++
++#include "gcstruct.h" /* pointer for extnsionst.h */
++#include "extnsionst.h" /* extension entry */
++#include "gesture.h"
++#include "gestureint.h"
++#include <X11/extensions/geproto.h>
++#include "geext.h" /* extension interfaces for ge */
++
++#include "swaprep.h"
++#include "privates.h"
++#include "protocol-versions.h"
++#include "dixstruct.h"
++
++#define GESTURE_NAME "GestureExtension"
++#define GESTURE_EVENTS 0
++#define GESTURE_ERRORS 0
++
++void GestureExtensionInit(void);
++
++/**
++ * Dispatch vector. Functions defined in here will be called when the matching
++ * request arrives.
++ */
++static int (*ProcGestureVector[])(ClientPtr) = {
++ NULL, /* 0 */
++ ProcGestureQueryVersion, /* 1 */
++ ProcGestureSelectEvents, /* 2 */
++ ProcGestureGetSelectedEvents, /* 3 */
++};
++
++/* For swapped clients */
++static int (*SProcGestureVector[])(ClientPtr) = {
++ NULL, /* 0 */
++ SProcGestureQueryVersion, /* 1 */
++ SProcGestureSelectEvents, /* 2 */
++ SProcGestureGetSelectedEvents, /* 3 */
++};
++
++/*****************************************************************
++ *
++ * Globals referenced elsewhere in the server.
++ *
++ */
++
++int GestureReqCode = 0;
++int GestureNotify = 0;
++
++int RT_GESTURECLIENT;
++
++/*****************************************************************
++ *
++ * Externs defined elsewhere in the X server.
++ *
++ */
++
++extern GestureExtensionVersion GestureVersion;
++
++
++/*****************************************************************
++ *
++ * Versioning support
++ *
++ */
++
++DevPrivateKeyRec GestureClientPrivateKeyRec;
++
++
++/*****************************************************************
++ *
++ * Declarations of local routines.
++ *
++ */
++
++static void
++GestureClientCallback(CallbackListPtr *list,
++ pointer closure,
++ pointer data)
++{
++ NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
++ ClientPtr client = clientinfo->client;
++ GestureClientPtr gestureClient;
++
++ gestureClient = dixLookupPrivate(&client->devPrivates,
++ &GestureClientPrivateKeyRec);
++ gestureClient->major_version = 0;
++ gestureClient->minor_version = 0;
++}
++
++/*************************************************************************
++ *
++ * ProcGestureDispatch - main dispatch routine for requests to this extension.
++ * This routine is used if server and client have the same byte ordering.
++ *
++ */
++
++static int
++ProcGestureDispatch(ClientPtr client)
++{
++ REQUEST(xReq);
++ if (stuff->data > GESTUREREQUESTS || !ProcGestureVector[stuff->data])
++ return BadRequest;
++
++ return (*ProcGestureVector[stuff->data])(client);
++}
++
++/*******************************************************************************
++ *
++ * SProcXDispatch
++ *
++ * Main swapped dispatch routine for requests to this extension.
++ * This routine is used if server and client do not have the same byte ordering.
++ *
++ */
++
++static int
++SProcGestureDispatch(ClientPtr client)
++{
++ REQUEST(xReq);
++ if (stuff->data > GESTUREREQUESTS || !SProcGestureVector[stuff->data])
++ return BadRequest;
++
++ return (*SProcGestureVector[stuff->data])(client);
++}
++
++/**********************************************************************
++ *
++ * SReplyGestureDispatch
++ * Swap any replies defined in this extension.
++ *
++ */
++
++static void
++SReplyGestureDispatch(ClientPtr client, int len, GestureQueryVersionReply *rep)
++{
++ if (rep->RepType == X_GestureQueryVersion)
++ SRepGestureQueryVersion(client, len, (GestureQueryVersionReply*)rep);
++ else if (rep->RepType == X_GestureGetSelectedEvents)
++ SRepGestureGetSelectedEvents(client, len, (GestureGetSelectedEventsReply *) rep);
++ else {
++ FatalError("Gesture confused sending swapped reply");
++ }
++}
++
++static void SGestureEvent(GestureEvent *from, GestureEvent *to)
++{
++ char n;
++
++ memcpy(to, from, sizeof(xEvent) + from->length * 4);
++
++ swaps(&to->sequenceNumber, n);
++ swapl(&to->length, n);
++ swaps(&to->evtype, n);
++ swaps(&to->gesture_id, n);
++ swaps(&to->gesture_type, n);
++ swaps(&to->device_id, n);
++ swapl(&to->time, n);
++ swapl(&to->root, n);
++ swapl(&to->event, n);
++ swapl(&to->child, n);
++ swapl(&to->focus_x, n);
++ swapl(&to->focus_y, n);
++ swaps(&to->status, n);
++ swaps(&to->num_props, n);
++}
++
++static void
++GestureEventSwap(xGenericEvent *from, xGenericEvent *to)
++{
++ SGestureEvent((GestureEvent *)from, (GestureEvent *)to);
++}
++
++static void
++CloseGestureExt(ExtensionEntry *unused)
++{
++ ReplySwapVector[GestureReqCode] = ReplyNotSwappd;
++ GestureReqCode = 0;
++ GestureNotify = 0;
++}
++
++/**********************************************************************
++ *
++ * GestureExtensionInit - initialize the gesture extension.
++ *
++ * Called from InitExtensions in main() or from QueryExtension() if the
++ * extension is dynamically loaded.
++ *
++ * This extension has several events and errors.
++ */
++
++void
++GestureExtensionInit(void)
++{
++ ExtensionEntry *extEntry;
++ GestureExtensionVersion thisversion = {
++ SERVER_GESTURE_MAJOR_VERSION,
++ SERVER_GESTURE_MINOR_VERSION,
++ };
++
++ if (!dixRegisterPrivateKey(&GestureClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(GestureClientRec)))
++ FatalError("Cannot request private for Gesture.\n");
++
++ if (!AddCallback(&ClientStateCallback, GestureClientCallback, 0))
++ FatalError("Failed to add callback to Gesture.\n");
++
++ extEntry = AddExtension(GESTURE_NAME, GESTURE_EVENTS, GESTURE_ERRORS,
++ ProcGestureDispatch, SProcGestureDispatch, CloseGestureExt,
++ StandardMinorOpcode);
++ if (extEntry) {
++ GestureReqCode = extEntry->base;
++ GestureVersion = thisversion;
++ RT_GESTURECLIENT = CreateNewResourceType((DeleteType) GestureClientGone,
++ "GESTURECLIENT");
++ if (!RT_GESTURECLIENT)
++ FatalError("Failed to add resource type for Gesture.\n");
++ ReplySwapVector[GestureReqCode] = (ReplySwapPtr) SReplyGestureDispatch;
++
++ GERegisterExtension(GestureReqCode, GestureEventSwap);
++ } else {
++ FatalError("GestureExtensionInit: AddExtensions failed\n");
++ }
++}
++
+diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
+index adef044..3167656 100644
+--- a/hw/xfree86/common/xf86Xinput.c
++++ b/hw/xfree86/common/xf86Xinput.c
+@@ -99,6 +99,15 @@
+ return; \
+ }
+
++#include "gestureproto.h"
++
++_X_EXPORT void
++xf86PostGestureEvent(DeviceIntPtr dev, unsigned short x, unsigned short y,
++ unsigned short client_id, unsigned short gesture_id,
++ unsigned short gesture_type, Window root, Window event,
++ Window child, unsigned short status,
++ unsigned short num_props, float *props);
++
+ EventListPtr xf86Events = NULL;
+
+ static int
+@@ -966,6 +975,40 @@ DeleteInputDeviceRequest(DeviceIntPtr pDev)
+ */
+
+ void
++xf86PostGestureEvent(DeviceIntPtr dev, unsigned short x, unsigned short y,
++ unsigned short client_id, unsigned short gesture_id,
++ unsigned short gesture_type, Window root, Window event,
++ Window child, unsigned short status,
++ unsigned short num_props, float *props)
++{
++ DeviceEvent *ev = (DeviceEvent *)xf86Events->event;
++
++ if (num_props > MAX_GESTURE_PROPS)
++ num_props = MAX_GESTURE_PROPS;
++
++ memset(ev, 0, sizeof(DeviceEvent));
++ ev->header = ET_Internal;
++ ev->length = sizeof(DeviceEvent);
++ ev->time = GetTimeInMillis();
++ ev->deviceid = dev->id;
++ ev->sourceid = dev->id;
++ ev->type = ET_Gesture;
++ ev->root_x = x;
++ ev->root_y = y;
++ ev->gesture.client_id = client_id;
++ ev->gesture.id = gesture_id;
++ ev->gesture.type = gesture_type;
++ ev->root = root;
++ ev->gesture.event = event;
++ ev->gesture.child = child;
++ ev->gesture.status = status;
++ ev->gesture.num_props = num_props;
++ memcpy(ev->gesture.props, props, num_props * sizeof(float));
++
++ mieqEnqueue(dev, (InternalEvent*)ev);
++}
++
++void
+ xf86PostMotionEvent(DeviceIntPtr device,
+ int is_absolute,
+ int first_valuator,
+diff --git a/include/dix-config.h.in b/include/dix-config.h.in
+index 5622766..ab82016 100644
+--- a/include/dix-config.h.in
++++ b/include/dix-config.h.in
+@@ -30,6 +30,9 @@
+ /* Support Damage extension */
+ #undef DAMAGE
+
++/* Support Gesture extension */
++#undef GESTURES
++
+ /* Build for darwin with Quartz support */
+ #undef DARWIN_WITH_QUARTZ
+
+diff --git a/include/eventstr.h b/include/eventstr.h
+index cf02efe..8ab7ea7 100644
+--- a/include/eventstr.h
++++ b/include/eventstr.h
+@@ -70,6 +70,7 @@ enum EventType {
+ ET_TouchMotion,
+ ET_TouchMotionUnowned,
+ ET_TouchOwnership,
++ ET_Gesture,
+ ET_Internal = 0xFF /* First byte */
+ };
+
+@@ -77,6 +78,9 @@ enum EventType {
+ FatalError("Wrong event type %d.\n", \
+ ((InternalEvent*)(ev))->any.header);
+
++/* Should match DIM_GRAIL_PROP in grail.h */
++#define MAX_GESTURE_PROPS 32
++
+ /**
+ * Used for ALL input device events internal in the server until
+ * copied into the matching protocol event.
+@@ -120,6 +124,16 @@ struct _DeviceEvent
+ uint8_t locked; /**< XKB locked group */
+ uint8_t effective;/**< XKB effective group */
+ } group;
++ struct {
++ uint16_t client_id;
++ uint16_t id;
++ uint16_t type;
++ Window event;
++ Window child;
++ uint16_t status;
++ uint16_t num_props;
++ float props[MAX_GESTURE_PROPS];
++ } gesture;
+ Window root; /**< Root window of the event */
+ int corestate; /**< Core key/button state BEFORE the event */
+ int key_repeat; /**< Internally-generated key repeat event */
+diff --git a/include/protocol-versions.h b/include/protocol-versions.h
+index 42b7d0e..ea5d702 100644
+--- a/include/protocol-versions.h
++++ b/include/protocol-versions.h
+@@ -145,4 +145,8 @@
+ #define SERVER_XVMC_MAJOR_VERSION 1
+ #define SERVER_XVMC_MINOR_VERSION 1
+
++/* Gesture */
++#define SERVER_GESTURE_MAJOR_VERSION 0
++#define SERVER_GESTURE_MINOR_VERSION 5
++
+ #endif
+diff --git a/include/windowstr.h b/include/windowstr.h
+index 4a7a0f4..4192ade 100644
+--- a/include/windowstr.h
++++ b/include/windowstr.h
+@@ -48,6 +48,10 @@ SOFTWARE.
+ #ifndef WINDOWSTRUCT_H
+ #define WINDOWSTRUCT_H
+
++#ifdef HAVE_DIX_CONFIG_H
++#include <dix-config.h>
++#endif
++
+ #include "window.h"
+ #include "pixmapstr.h"
+ #include "regionstr.h"
+@@ -60,6 +64,10 @@ SOFTWARE.
+ #include <X11/Xprotostr.h>
+ #include "opaque.h"
+
++#ifdef GESTURES
++#include "gesture.h"
++#endif
++
+ #define GuaranteeNothing 0
+ #define GuaranteeVisBack 1
+
+@@ -94,6 +102,9 @@ typedef struct _WindowOpt {
+ RegionPtr inputShape; /* default: NULL */
+ struct _OtherInputMasks *inputMasks; /* default: NULL */
+ DevCursorList deviceCursors; /* default: NULL */
++#ifdef GESTURES
++ struct _GestureMasks *gestureMasks; /* default: NULL */
++#endif
+ } WindowOptRec, *WindowOptPtr;
+
+ #define BackgroundPixel 2L
+@@ -202,6 +213,9 @@ extern _X_EXPORT Mask DontPropagateMasks[];
+ #define wInputShape(w) wUseDefault(w, inputShape, NULL)
+ #define wClient(w) (clients[CLIENT_ID((w)->drawable.id)])
+ #define wBorderWidth(w) ((int) (w)->borderWidth)
++#ifdef GESTURES
++#define wGestureMasks(w) wUseDefault(w, gestureMasks, NULL)
++#endif
+
+ /* true when w needs a border drawn. */
+
+diff --git a/mi/mieq.c b/mi/mieq.c
+index 3a5d4e0..427c49b 100644
+--- a/mi/mieq.c
++++ b/mi/mieq.c
+@@ -58,6 +58,8 @@ in this Software without prior written authorization from The Open Group.
+ # include <X11/extensions/dpmsconst.h>
+ #endif
+
++#include "gestureproto.h"
++
+ #define QUEUE_SIZE 512
+
+ #define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen
+@@ -383,6 +385,39 @@ mieqProcessDeviceEvent(DeviceIntPtr dev,
+
+ CHECKEVENT(event);
+
++ if (event->any.header == ET_Internal && event->any.type == ET_Gesture){
++ GestureEvent gev;
++ DeviceEvent *ev = (DeviceEvent *)event;
++ ClientPtr client = clients[ev->gesture.client_id];
++
++ /* Check if client still exists */
++ if (!client)
++ return;
++
++ gev.type = GenericEvent;
++ gev.extension = GestureReqCode;
++ gev.sequenceNumber = client->sequence;
++ gev.evtype = 0;
++ gev.time = ev->time;
++ gev.length = (sizeof(GestureEvent) +
++ ev->gesture.num_props * sizeof(float) -
++ sizeof(xEvent)) / 4;
++ gev.gesture_id = ev->gesture.id;
++ gev.gesture_type = ev->gesture.type;
++ gev.device_id = ev->deviceid;
++ gev.root = ev->root;
++ gev.event = ev->gesture.event;
++ gev.child = ev->gesture.child;
++ gev.focus_x = ev->root_x;
++ gev.focus_y = ev->root_y;
++ gev.status = ev->gesture.status;
++ gev.num_props = ev->gesture.num_props;
++
++ WriteToClient(client, sizeof(GestureEvent), &gev);
++ WriteToClient(client, sizeof(float) * gev.num_props, ev->gesture.props);
++ return;
++ }
++
+ /* Custom event handler */
+ handler = miEventQueue.handlers[event->any.type];
+
+diff --git a/mi/miinitext.c b/mi/miinitext.c
+index 4499f37..2ccb6cb 100644
+--- a/mi/miinitext.c
++++ b/mi/miinitext.c
+@@ -152,6 +152,9 @@ extern Bool noSELinuxExtension;
+ #ifdef XV
+ extern Bool noXvExtension;
+ #endif
++#ifdef GESTURES
++extern Bool noGestureExtension;
++#endif
+ extern Bool noGEExtension;
+
+ #ifndef XFree86LOADER
+@@ -263,6 +266,9 @@ extern void DamageExtensionInit(INITARGS);
+ extern void CompositeExtensionInit(INITARGS);
+ #endif
+ extern void GEExtensionInit(INITARGS);
++#ifdef GESTURES
++extern void GestureExtensionInit(INITARGS);
++#endif
+
+ /* The following is only a small first step towards run-time
+ * configurable extensions.
+@@ -334,6 +340,9 @@ static ExtensionToggle ExtensionToggleList[] =
+ #ifdef XV
+ { "XVideo", &noXvExtension },
+ #endif
++#ifdef GESTURES
++ { "Gesture", &noGestureExtension },
++#endif
+ { NULL, NULL }
+ };
+
+@@ -470,6 +479,9 @@ InitExtensions(int argc, char *argv[])
+ GlxPushProvider(&__glXDRISWRastProvider);
+ if (!noGlxExtension) GlxExtensionInit();
+ #endif
++#ifdef GESTURES
++ if (!noGestureExtension) GestureExtensionInit();
++#endif
+ }
+
+ #else /* XFree86LOADER */
+@@ -511,6 +523,9 @@ static ExtensionModule staticExtensions[] = {
+ #ifdef DAMAGE
+ { DamageExtensionInit, "DAMAGE", &noDamageExtension, NULL },
+ #endif
++#ifdef GESTURES
++ { GestureExtensionInit, "GESTURE", &noGestureExtension, NULL },
++#endif
+ { NULL, NULL, NULL, NULL, NULL }
+ };
+
+diff --git a/os/utils.c b/os/utils.c
+index 18fd911..8937f8e 100644
+--- a/os/utils.c
++++ b/os/utils.c
+@@ -185,6 +185,9 @@ Bool noXvExtension = FALSE;
+ #ifdef DRI2
+ Bool noDRI2Extension = FALSE;
+ #endif
++#ifdef GESTURES
++Bool noGestureExtension = FALSE;
++#endif
+
+ Bool noGEExtension = FALSE;
+
diff --git a/x11-base/xorg-server/files/xorg-server-xf86CoordinatesToWindow.patch b/x11-base/xorg-server/files/xorg-server-xf86CoordinatesToWindow.patch
new file mode 100644
index 0000000..b823d13
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-xf86CoordinatesToWindow.patch
@@ -0,0 +1,97 @@
+diff --git a/dix/events.c b/dix/events.c
+index 8c590f0..43803ab 100644
+--- a/dix/events.c
++++ b/dix/events.c
+@@ -5837,3 +5837,47 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
+ return FALSE;
+ }
+
++WindowPtr
++CoordinatesToWindow(int x, int y, int screen)
++{
++ WindowPtr pWin;
++ WindowPtr ret = NullWindow;
++ BoxRec box;
++
++ pWin = screenInfo.screens[screen]->root;
++ 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
++ )
++ {
++ ret = pWin;
++ pWin = pWin->firstChild;
++ }
++ else
++ pWin = pWin->nextSib;
++ }
++ return ret;
++}
++
+diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
+index 9b21c31..adef044 100644
+--- a/hw/xfree86/common/xf86Xinput.c
++++ b/hw/xfree86/common/xf86Xinput.c
+@@ -1441,4 +1441,10 @@ xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
+ mieqEnqueue(dev, (InternalEvent *)((xf86Events + i)->event));
+ }
+
++WindowPtr
++xf86CoordinatesToWindow(int x, int y, int screen)
++{
++ return CoordinatesToWindow(x, y, screen);
++}
++
+ /* end of xf86Xinput.c */
+diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
+index f1afb09..b6254c6 100644
+--- a/hw/xfree86/common/xf86Xinput.h
++++ b/hw/xfree86/common/xf86Xinput.h
+@@ -184,4 +184,6 @@ extern _X_EXPORT void xf86VIDrvMsgVerb(InputInfoPtr dev,
+ /* xf86Option.c */
+ extern _X_EXPORT void xf86CollectInputOptions(InputInfoPtr pInfo, const char **defaultOpts);
+
++extern _X_EXPORT WindowPtr xf86CoordinatesToWindow(int x, int y, int screen);
++
+ #endif /* _xf86Xinput_h */
+diff --git a/include/events.h b/include/events.h
+index 222cc3d..8b87cb6 100644
+--- a/include/events.h
++++ b/include/events.h
+@@ -24,6 +24,7 @@
+
+ #ifndef EVENTS_H
+ #define EVENTS_H
++
+ typedef struct _DeviceEvent DeviceEvent;
+ typedef struct _DeviceChangedEvent DeviceChangedEvent;
+ typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
+@@ -36,4 +37,6 @@ typedef struct _XQuartzEvent XQuartzEvent;
+ #endif
+ typedef union _InternalEvent InternalEvent;
+
++extern WindowPtr CoordinatesToWindow(int x, int y, int screen);
++
+ #endif
diff --git a/x11-base/xorg-server/files/xorg-server-xi2.patch b/x11-base/xorg-server/files/xorg-server-xi2.patch
new file mode 100644
index 0000000..ed4b7b4
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-server-xi2.patch
@@ -0,0 +1,4568 @@
+
+Index: b/Xi/allowev.c
+===================================================================
+--- a/Xi/allowev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/allowev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -125,5 +125,24 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
++
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (thisdev->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = thisdev->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return Success;
+ }
+Index: b/Xi/exevents.c
+===================================================================
+--- a/Xi/exevents.c 2011-03-09 11:19:12.126789337 +1100
++++ b/Xi/exevents.c 2011-03-09 13:11:48.093384404 +1100
+@@ -44,6 +44,31 @@
+
+ ********************************************************/
+
++/*
++ * Copyright © 2010 Collabora Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Author: Daniel Stone <daniel@fooishbar.org>
++ */
++
+ /********************************************************************
+ *
+ * Routines to register and initialize extension input devices.
+@@ -77,6 +102,9 @@
+ #include "xiquerydevice.h" /* For List*Info */
+ #include "eventconvert.h"
+ #include "eventstr.h"
++#include "xserver-properties.h"
++#include "inpututils.h"
++#include "mi.h"
+
+ #include <X11/extensions/XKBproto.h>
+ #include "xkbsrv.h"
+@@ -127,6 +155,20 @@
+ return FALSE;
+ }
+
++Bool
++IsTouchEvent(InternalEvent* event)
++{
++ switch(event->any.type)
++ {
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ return TRUE;
++ default:
++ return FALSE;
++ }
++}
++
+ /**
+ * @return the device matching the deviceid of the device set in the event, or
+ * NULL if the event is not an XInput event.
+@@ -725,6 +767,46 @@
+ XISendDeviceChangedEvent(slave, device, dce);
+ }
+
++#define DEFAULT 0
++#define DONT_PROCESS 1
++int
++ReleaseButton(DeviceIntPtr device, int button)
++{
++ ButtonClassPtr b = device->button;
++ int i;
++
++ if (IsMaster(device)) {
++ DeviceIntPtr sd;
++
++ /*
++ * Leave the button down if any slave has the
++ * button still down. Note that this depends on the
++ * event being delivered through the slave first
++ */
++ for (sd = inputInfo.devices; sd; sd = sd->next) {
++ if (IsMaster(sd) || sd->u.master != device)
++ continue;
++ if (!sd->button)
++ continue;
++ for (i = 1; i <= sd->button->numButtons; i++)
++ if (sd->button->map[i] == button &&
++ button_is_down(sd, i, BUTTON_PROCESSED))
++ return DONT_PROCESS;
++ }
++ }
++ set_button_up(device, button, BUTTON_PROCESSED);
++ if (device->valuator)
++ device->valuator->motionHintWindow = NullWindow;
++ if (!b->map[button])
++ return DONT_PROCESS;
++ if (b->buttonsDown >= 1 && !--b->buttonsDown)
++ b->motionMask = 0;
++ if (b->map[button] <= 5)
++ b->state &= ~((Button1Mask >> 1) << b->map[button]);
++
++ return DEFAULT;
++}
++
+ /**
+ * Update the device state according to the data in the event.
+ *
+@@ -732,8 +814,6 @@
+ * DEFAULT ... process as normal
+ * DONT_PROCESS ... return immediately from caller
+ */
+-#define DEFAULT 0
+-#define DONT_PROCESS 1
+ int
+ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
+ {
+@@ -857,34 +937,9 @@
+
+ if (!button_is_down(device, key, BUTTON_PROCESSED))
+ return DONT_PROCESS;
+- if (IsMaster(device)) {
+- DeviceIntPtr sd;
+
+- /*
+- * Leave the button down if any slave has the
+- * button still down. Note that this depends on the
+- * event being delivered through the slave first
+- */
+- for (sd = inputInfo.devices; sd; sd = sd->next) {
+- if (IsMaster(sd) || sd->u.master != device)
+- continue;
+- if (!sd->button)
+- continue;
+- for (i = 1; i <= sd->button->numButtons; i++)
+- if (sd->button->map[i] == key &&
+- button_is_down(sd, i, BUTTON_PROCESSED))
+- return DONT_PROCESS;
+- }
+- }
+- set_button_up(device, key, BUTTON_PROCESSED);
+- if (device->valuator)
+- device->valuator->motionHintWindow = NullWindow;
+- if (!b->map[key])
++ if (ReleaseButton(device, key) == DONT_PROCESS)
+ return DONT_PROCESS;
+- if (b->buttonsDown >= 1 && !--b->buttonsDown)
+- b->motionMask = 0;
+- if (b->map[key] <= 5)
+- b->state &= ~((Button1Mask >> 1) << b->map[key]);
+
+ /* Add state and motionMask to the filter for this event */
+ mask = DevicePointerMotionMask | b->state | b->motionMask;
+@@ -926,6 +981,939 @@
+ }
+
+ /**
++ * Add a touch client to the list of clients for the touch point. Return TRUE
++ * if the caller should stop processing touch clients.
++ */
++static Bool
++AddTouchClient(TouchPointInfoPtr ti, int client_id, WindowPtr window,
++ TouchClientType type, DeviceIntPtr dev, DeviceIntPtr sourcedev,
++ GrabPtr grab)
++{
++ TouchClientPtr client;
++
++ ti->active_clients++;
++ if (ti->active_clients > ti->num_clients)
++ {
++ int num_clients = ti->num_clients ? ti->num_clients * 2 : 2;
++
++ TouchClientPtr tmp;
++ tmp = realloc(ti->clients, num_clients * sizeof(TouchClientRec));
++
++ if (tmp)
++ {
++ ti->clients = tmp;
++ ti->num_clients = num_clients;
++ } else {
++ LogMessage(X_ERROR, "failed to reallocate touch clients\n");
++ return TRUE;
++ }
++ }
++
++ client = &ti->clients[ti->active_clients - 1];
++ client->client = clients[client_id];
++ client->window = window;
++ client->type = type;
++ client->device = dev;
++ client->source = sourcedev;
++ client->grab = grab;
++
++ return FALSE;
++}
++
++/**
++ * Ensure a list of clients for a touchpoint, constructing one for TouchBegin
++ * events. Returns TRUE if a touch client exists, FALSE if none.
++ */
++static Bool
++EnsureTouchClients(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
++ InternalEvent *ev)
++{
++ TouchClassPtr t = sourcedev->touch;
++ SpritePtr sprite = &ti->sprite;
++ DeviceIntPtr masterdev = sourcedev->u.master;
++ int i;
++
++ if (ev->any.type != ET_TouchBegin)
++ return (ti->active_clients > 0);
++
++ if (ti->active_clients > 0)
++ LogMessage(X_ERROR, "Getting touch clients for active touch\n");
++
++ /* Create sprite trace for the touchpoint */
++ if (t->mode == XIDirectTouch)
++ {
++ /* Focus immediately under the touchpoint in direct touch mode.
++ * XXX: Do we need to handle crossing screens here? */
++ sprite->spriteTrace[0] =
++ sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
++ XYToWindow(sprite, ev->device_event.root_x, ev->device_event.root_y);
++ }
++ else
++ {
++ WindowPtr *trace;
++ SpritePtr srcsprite;
++
++ /* Find and reuse an existing, physically active touch's sprite and
++ * touch client list if possible, else use the device's pointer sprite
++ * and generate a new list of touch clients. */
++ for (i = 0; i < t->num_touches; i++)
++ if (!t->touches[i].ddx_pending_finish &&
++ t->touches[i].active_clients > 0)
++ break;
++ if (i < t->num_touches) {
++ srcsprite = &t->touches[i].sprite;
++ ti->active_clients = t->touches[i].active_clients;
++
++ if (ti->active_clients > ti->num_clients)
++ {
++ TouchClientPtr tmp;
++
++ tmp = realloc(ti->clients,
++ ti->active_clients * sizeof(TouchClientRec));
++ if (!tmp)
++ {
++ ti->active_clients = 0;
++ ti->owner = -1;
++ return FALSE;
++ }
++ ti->clients = tmp;
++ ti->num_clients = ti->active_clients;
++ }
++ memcpy(ti->clients, t->touches[i].clients,
++ ti->active_clients * sizeof(TouchClientRec));
++ }
++ else if (sourcedev->spriteInfo->sprite)
++ srcsprite = sourcedev->spriteInfo->sprite;
++ else
++ return FALSE;
++
++ if (srcsprite->spriteTraceGood > sprite->spriteTraceSize)
++ {
++ trace = realloc(sprite->spriteTrace,
++ srcsprite->spriteTraceSize * sizeof(*trace));
++ if (!trace)
++ {
++ sprite->spriteTraceGood = 0;
++ ti->active_clients = 0;
++ ti->owner = -1;
++ return FALSE;
++ }
++ sprite->spriteTrace = trace;
++ sprite->spriteTraceSize = srcsprite->spriteTraceGood;
++ }
++ memcpy(sprite->spriteTrace, srcsprite->spriteTrace,
++ srcsprite->spriteTraceGood * sizeof(*trace));
++ sprite->spriteTraceGood = srcsprite->spriteTraceGood;
++
++ if (ti->active_clients)
++ return TRUE;
++ }
++
++ if (sprite->spriteTraceGood <= 0)
++ return FALSE;
++
++ /* Search for touch grab clients from root to child windows. */
++ for (i = 0; i < sprite->spriteTraceGood; i++)
++ {
++ WindowPtr win = sprite->spriteTrace[i];
++ GrabPtr grab;
++ InternalEvent ev;
++
++ ev.any.type = ET_TouchBegin;
++ if ((grab = CheckPassiveGrabsOnWindow(win, sourcedev, &ev, FALSE,
++ FALSE)))
++ {
++ if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB,
++ sourcedev, sourcedev, grab))
++ goto done;
++ continue;
++ }
++ if (masterdev &&
++ (grab = CheckPassiveGrabsOnWindow(win, masterdev, &ev, FALSE,
++ FALSE)))
++ {
++ if (AddTouchClient(ti, CLIENT_ID(grab->resource), win, TOUCH_GRAB,
++ masterdev, sourcedev, grab))
++ goto done;
++ continue;
++ }
++ }
++
++ /* Search for one touch select client from child to root windows. */
++ for (i = sprite->spriteTraceGood - 1; i >= 0; i--)
++ {
++ WindowPtr win = sprite->spriteTrace[i];
++ OtherInputMasks *inputMasks = wOtherInputMasks(win);
++
++ /* Is anyone listening for unowned events on this window? */
++ if (inputMasks &&
++ (BitIsOn(inputMasks->xi2mask[XIAllDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputMasks->xi2mask[sourcedev->id],
++ XI_TouchUpdateUnowned) ||
++ (masterdev &&
++ (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputMasks->xi2mask[masterdev->id],
++ XI_TouchUpdateUnowned)))))
++ {
++ InputClientsPtr inputClients = inputMasks->inputClients;
++
++ /* Find the one client listening for unowned events. */
++ for (inputClients = inputMasks->inputClients;
++ inputClients;
++ inputClients = inputClients->next)
++ {
++ if (BitIsOn(inputClients->xi2mask[XIAllDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputClients->xi2mask[sourcedev->id],
++ XI_TouchUpdateUnowned))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource),
++ win, TOUCH_SELECT_UNOWNED, sourcedev,
++ sourcedev, NULL);
++ goto done;
++ }
++ else if (masterdev &&
++ (BitIsOn(inputClients->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdateUnowned) ||
++ BitIsOn(inputClients->xi2mask[masterdev->id],
++ XI_TouchUpdateUnowned)))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource),
++ win, TOUCH_SELECT_UNOWNED, masterdev,
++ sourcedev, NULL);
++ goto done;
++ }
++ }
++ }
++
++ /* Is anyone listening for only owned events on this window? */
++ if (inputMasks &&
++ (BitIsOn(inputMasks->xi2mask[XIAllDevices], XI_TouchUpdate) ||
++ BitIsOn(inputMasks->xi2mask[sourcedev->id], XI_TouchUpdate) ||
++ (masterdev &&
++ (BitIsOn(inputMasks->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputMasks->xi2mask[masterdev->id],
++ XI_TouchUpdate)))))
++ {
++ InputClientsPtr inputClients = inputMasks->inputClients;
++
++ /* Find the one client listening for owned events. */
++ for (inputClients = inputMasks->inputClients;
++ inputClients;
++ inputClients = inputClients->next)
++ {
++ if (BitIsOn(inputClients->xi2mask[XIAllDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputClients->xi2mask[sourcedev->id],
++ XI_TouchUpdate))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource), win,
++ TOUCH_SELECT, sourcedev, sourcedev, NULL);
++ goto done;
++ }
++ else if (masterdev &&
++ (BitIsOn(inputClients->xi2mask[XIAllMasterDevices],
++ XI_TouchUpdate) ||
++ BitIsOn(inputClients->xi2mask[masterdev->id],
++ XI_TouchUpdate)))
++ {
++ AddTouchClient(ti, CLIENT_ID(inputClients->resource), win,
++ TOUCH_SELECT, masterdev, sourcedev, NULL);
++ goto done;
++ }
++ }
++ }
++ }
++
++done:
++ return (ti->active_clients > 0);
++}
++
++/**
++ * Attempts to deliver a touch event to the given client.
++ */
++static Bool
++DeliverOneTouchEvent(TouchClientPtr client, TouchPointInfoPtr ti,
++ InternalEvent *ev)
++{
++ int err;
++ xEvent *xi2;
++ Mask filter;
++ Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
++
++ /* If we fail here, we're going to leave a client hanging. */
++ err = EventToXI2(ev, &xi2);
++ if (err != Success)
++ FatalError("[Xi] %s: XI2 conversion failed in DeliverOneTouchEvent"
++ " (%d)\n", client->device->name, err);
++
++ FixUpEventFromWindow(&ti->sprite, xi2, client->window, child, FALSE);
++ filter = GetEventFilter(client->device, xi2);
++ if (XaceHook(XACE_RECEIVE_ACCESS, client->client, client->window, xi2, 1)
++ != Success)
++ return FALSE;
++ err = TryClientEvents(client->client, client->device, xi2, 1, filter,
++ filter, NullGrab);
++ free(xi2);
++
++ /* Returning the value from TryClientEvents isn't useful, since all our
++ * resource-gone cleanups will update the delivery list anyway. */
++ return TRUE;
++}
++
++/**
++ * Deliver touch ownership event directly to client.
++ */
++int
++DeliverTouchOwnershipEvent(TouchClientPtr client, TouchPointInfoPtr ti)
++{
++ TouchOwnershipEvent event;
++
++ memset(&event, 0, sizeof(TouchOwnershipEvent));
++ event.header = ET_Internal;
++ event.type = ET_TouchOwnership;
++ event.length = sizeof(TouchOwnershipEvent);
++ event.time = GetTimeInMillis();
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++ event.touchid = ti->client_id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++
++ return 1;
++}
++
++/* Add the given event to the history for the touch point. */
++static void
++UpdateTouchHistory(TouchPointInfoPtr ti, InternalEvent *ev)
++{
++ /* Copy begin events off to the side. This prevents the ring buffer
++ overrunning and erasing the begin event. */
++ if (ev->any.type == ET_TouchBegin)
++ memcpy(ti->begin_event, ev, sizeof(InternalEvent));
++ else
++ {
++ memcpy(ti->next_history, ev, sizeof(InternalEvent));
++
++ ti->next_history++;
++ if (ti->next_history == ti->history + ti->history_size)
++ ti->next_history = ti->history;
++
++ /* If the ring overruns, advance the first pointer so we keep as many
++ events as possible. */
++ if (ti->next_history == ti->first_history)
++ {
++ ti->first_history++;
++ if (ti->first_history == ti->history + ti->history_size)
++ ti->first_history = ti->history;
++ }
++ }
++}
++
++/**
++ * Helper to get a static EventList for pointer emulation.
++ */
++static EventList *
++GetEvents(void)
++{
++ static EventList *events = NULL;
++
++ /* Allocate twice the maximum number of events for motion and button
++ * emulation. */
++ if (!events)
++ events = InitEventList(2 * GetMaximumEventsNum());
++
++ return events;
++}
++
++/* Helper function to set up touch pointer emulation. */
++static void
++SetTouchEmulationMask(InternalEvent *ev, ValuatorMask *mask, int x_axis,
++ int y_axis)
++{
++ valuator_mask_zero(mask);
++ if (BitIsOn(ev->device_event.valuators.mask, x_axis))
++ valuator_mask_set(mask, 0,
++ ev->device_event.valuators.data[x_axis]);
++ if (BitIsOn(ev->device_event.valuators.mask, y_axis))
++ valuator_mask_set(mask, 1,
++ ev->device_event.valuators.data[y_axis]);
++}
++
++/* Process touch emulation. */
++static void
++EmulateTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
++{
++ EventList *emulationEvents = GetEvents();
++ ValuatorMask mask;
++ InternalEvent mevent;
++ DeviceIntPtr master = dev->u.master;
++ enum EventType evtype = ev->any.type;
++ int nevents = 0;
++ int x_axis = dev->touch->x_axis;
++ int y_axis = dev->touch->y_axis;
++ int i;
++
++ /* Set the emulation touch for the device. Only one touch may be emulated
++ * at a time. */
++ if (dev->touch->emulate != ti)
++ return;
++
++ /* Emulate a normal event. */
++ SetTouchEmulationMask(ev, &mask, x_axis, y_axis);
++
++ if (evtype == ET_TouchBegin)
++ {
++ nevents = GetPointerEvents(emulationEvents, dev,
++ MotionNotify, 0, POINTER_ABSOLUTE, &mask);
++ nevents += GetPointerEvents(emulationEvents + nevents, dev,
++ ButtonPress, 1, POINTER_ABSOLUTE, &mask);
++ }
++ else if (evtype == ET_TouchMotion)
++ nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0,
++ POINTER_ABSOLUTE, &mask);
++ else if (evtype == ET_TouchEnd)
++ {
++ nevents = GetPointerEvents(emulationEvents, dev, MotionNotify, 0,
++ POINTER_ABSOLUTE, &mask);
++ nevents += GetPointerEvents(emulationEvents + nevents, dev,
++ ButtonRelease, 1, POINTER_ABSOLUTE, &mask);
++ }
++
++ if (ti->emulate_pointer)
++ {
++ for (i = 0; i < nevents; i++)
++ {
++ InternalEvent *event = (InternalEvent *)((emulationEvents + i)->event);
++
++ event->device_event.flags |= XIPointerEmulated;
++ event->device_event.touchpoint = ev->device_event.touchpoint;
++
++ if (master)
++ {
++ master->u.lastSlave = dev;
++
++ CopyGetMasterEvent(dev, event, &mevent);
++
++ /* If a grab has been activated but no event has been handled
++ * yet, then the grab is a touch grab. Store the pointer
++ * emulation event for now, ready for replay when the touch grab
++ * is relinquished. */
++ if (master->deviceGrab.sync.state == FROZEN_NO_EVENT)
++ {
++ GrabInfoPtr grabinfo = &master->deviceGrab;
++
++ grabinfo->sync.state = FROZEN_WITH_EVENT;
++ if (!grabinfo->sync.event)
++ grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
++ *grabinfo->sync.event = event->device_event;
++ }
++ else
++ master->public.processInputProc(&mevent, master);
++ }
++ }
++ }
++
++ /* If there are touch clients on a pointer emulated touchpoint, send touch
++ * events through traditional device processing as well. */
++ if (master && ti->active_clients > 0 &&
++ (ev->any.type != ET_TouchEnd ||
++ (ti->clients[ti->active_clients - 1].type == TOUCH_SELECT ||
++ ti->clients[ti->active_clients - 1].type == TOUCH_SELECT_UNOWNED)))
++ {
++ ev->device_event.flags |= XIPointerEmulated;
++ master->u.lastSlave = dev;
++ CopyGetMasterEvent(dev, ev, &mevent);
++ master->process_touch = TRUE;
++ master->public.processInputProc(&mevent, master);
++ master->process_touch = FALSE;
++
++ /* If grabbed by an implicit touch grab from FindFirstGrab, release it
++ * now. */
++ if (master->deviceGrab.grab &&
++ master->deviceGrab.grab->type == ET_TouchBegin &&
++ master->deviceGrab.implicitGrab)
++ master->deviceGrab.DeactivateGrab(master);
++ }
++}
++
++#define ImplicitGrabMask (1 << 7)
++/**
++ * Find the first grab of a new touchpoint. Returns TRUE if a grab was found.
++ */
++static Bool
++FindFirstGrab(DeviceIntPtr dev, TouchPointInfoPtr ti)
++{
++ DeviceIntPtr master = dev->u.master;
++ InternalEvent p_event;
++ InternalEvent t_event;
++ GrabRec tempGrab;
++ int i, j;
++
++ p_event.any.type = ET_ButtonPress;
++ t_event.any.type = ET_TouchBegin;
++
++ j = ti->owner >= 0 ? ti->owner : 0;
++
++ for (i = 0; i < ti->sprite.spriteTraceGood; i++)
++ {
++ WindowPtr win = ti->sprite.spriteTrace[i];
++ TouchClientPtr client = &ti->clients[j];
++ GrabPtr grab;
++
++ /* If master pointer is already grabbed, bypass touch grabs above. */
++ if (ti->emulate_pointer && master->deviceGrab.grab)
++ {
++ if (win == master->deviceGrab.grab->window)
++ {
++ if (j >= ti->active_clients - 1)
++ {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ } else
++ ti->owner = j + 1;
++ return TRUE;
++ } else
++ goto next;
++ }
++
++ /* Check for a touch grab on this window. */
++ if (j < ti->active_clients && win == client->window &&
++ client->type == TOUCH_GRAB)
++ {
++ client->device->deviceGrab.ActivateGrab(client->device,
++ client->grab, currentTime,
++ TRUE);
++ ti->owner = j;
++ return TRUE;
++ }
++
++ if (!ti->emulate_pointer)
++ goto next;
++
++ /* Check for a passive pointer grab on this window. */
++ grab = CheckPassiveGrabsOnWindow(win, dev, &p_event, TRUE, FALSE);
++ if (grab)
++ return TRUE;
++ else if (master)
++ {
++ grab = CheckPassiveGrabsOnWindow(win, master, &p_event, TRUE,
++ FALSE);
++ if (grab)
++ return TRUE;
++ }
++
++next:
++ if (j < ti->active_clients && win == client->window)
++ j++;
++ }
++
++ /* Even when there's no grabbing clients, we need to sync events so we can
++ * properly check for touch vs pointer selection in DeliverDeviceEvents.
++ * Create a temporary implicit touch grab here, and deactivate it after
++ * enqueuing emulated pointer events. */
++ if (ti->emulate_pointer)
++ {
++ memset(&tempGrab, 0, sizeof(GrabRec));
++ tempGrab.next = NULL;
++ tempGrab.device = master;
++ tempGrab.resource = 0;
++ tempGrab.window = ti->sprite.spriteTrace[0];
++ tempGrab.ownerEvents = FALSE;
++ tempGrab.eventMask = 0;
++ tempGrab.keyboardMode = GrabModeAsync;
++ tempGrab.pointerMode = GrabModeSync;
++ tempGrab.confineTo = NullWindow;
++ tempGrab.cursor = NullCursor;
++ tempGrab.type = ET_TouchBegin;
++ tempGrab.grabtype = GRABTYPE_XI2;
++ tempGrab.deviceMask = 0;
++
++ master->deviceGrab.ActivateGrab(master, &tempGrab, currentTime,
++ TRUE | ImplicitGrabMask);
++ }
++
++ return FALSE;
++}
++
++void
++ProcessTouchOwnership(DeviceIntPtr dev, TouchPointInfoPtr ti, uint8_t reason,
++ Bool touch_grab)
++{
++ DeviceIntPtr sourcedev = ti->source;
++ DeviceIntPtr masterdev;
++
++ masterdev = dev->u.master;
++
++ if (reason == XITouchOwnerAccept)
++ {
++ TouchClientPtr client;
++ DeviceEvent event;
++ int i;
++
++ init_event(dev, &event, GetTimeInMillis());
++ event.type = ET_TouchEnd;
++ event.detail.touch = ti->client_id;
++ event.touchpoint = ti;
++
++ for (i = ti->owner + 1; i < ti->active_clients; i++)
++ {
++ client = &ti->clients[i];
++
++ if (client->type == TOUCH_GRAB ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ {
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++ }
++ }
++
++ if (!touch_grab)
++ {
++ ti->active_clients = 0;
++ ti->owner = -1;
++ RemoveTouchEventsFromQueue(masterdev, TRUE, FALSE);
++ return;
++ }
++
++ client = &ti->clients[ti->owner];
++ ti->active_clients = ti->owner + 1;
++ ti->accepted = TRUE;
++
++ RemoveTouchEventsFromQueue(masterdev, FALSE, FALSE);
++ RemoveTouchEventsFromQueue(masterdev, TRUE, FALSE);
++ ReleaseButton(masterdev, 1);
++
++ if (ti->emulate_pointer)
++ masterdev->deviceGrab.DeactivateGrab(masterdev);
++
++ ti->emulate_pointer = FALSE;
++
++ if (ti->pending_finish)
++ {
++ event.deviceid = client->device->id;
++ event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, (InternalEvent *)&event);
++ EndTouchPoint(sourcedev, ti);
++ }
++ } else {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++ GrabPtr grab = masterdev->deviceGrab.grab;
++
++ if (touch_grab)
++ {
++ DeviceEvent event;
++
++ tc = &ti->clients[ti->owner];
++
++ init_event(tc->device, &event, GetTimeInMillis());
++ event.type = ET_TouchEnd;
++ event.detail.touch = ti->client_id;
++ event.deviceid = tc->device->id;
++ event.sourceid = tc->source->id;
++ event.touchpoint = ti;
++
++ DeliverOneTouchEvent(tc, ti, (InternalEvent *)&event);
++
++ ti->owner++;
++ }
++
++ if (ti->owner >= ti->active_clients)
++ {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ tc = NULL;
++ } else {
++ tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT && !ti->emulate_pointer)
++ {
++ InternalEvent *ev;
++ Bool ret;
++
++ /* Deliver the saved touch begin event. */
++ ret = DeliverOneTouchEvent(tc, ti, ti->begin_event);
++
++ /* Deliver all the touch motion events in the ring buffer. */
++ ev = ti->first_history;
++ while (ret && ev != ti->next_history)
++ {
++ ret = DeliverOneTouchEvent(tc, ti, ev);
++
++ if (ev->any.type == ET_TouchEnd)
++ {
++ ti->pending_finish = TRUE;
++ break;
++ }
++
++ ev++;
++ if (ev == ti->history + ti->history_size)
++ ev = ti->history;
++ }
++ } else if (tc->type == TOUCH_SELECT_UNOWNED &&
++ !ti->emulate_pointer) {
++ DeliverTouchOwnershipEvent(tc, ti);
++ }
++ }
++
++ if (ti->emulate_pointer)
++ {
++ if (ti->active_clients &&
++ ti->clients[ti->owner].type == TOUCH_SELECT_UNOWNED)
++ RemoveTouchEventsFromQueue(masterdev, TRUE, TRUE);
++
++ syncEvents.replayDev = masterdev;
++ if (touch_grab)
++ syncEvents.replayWin = grab->window->parent;
++ else
++ syncEvents.replayWin = grab->window;
++ masterdev->deviceGrab.DeactivateGrab(masterdev);
++ syncEvents.replayDev = NULL;
++ }
++
++ if (ti->pending_finish &&
++ (!tc || (tc->type == TOUCH_SELECT ||
++ tc->type == TOUCH_SELECT_UNOWNED)) &&
++ (!ti->emulate_pointer || !masterdev->deviceGrab.grab))
++ EndTouchPoint(sourcedev, ti);
++ }
++}
++
++/**
++ * Processes and delivers a TouchBegin, TouchMotion, or a TouchEnd event.
++ *
++ * Due to having rather different delivery semantics (see the Xi 2.1 protocol
++ * spec for more information), this implements its own grab and event-selection
++ * delivery logic.
++ */
++static void
++ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr sourcedev)
++{
++ DeviceIntPtr masterdev = sourcedev->u.master;
++ TouchClassPtr t = sourcedev->touch;
++ TouchPointInfoPtr ti;
++ TouchClientPtr client;
++ uint32_t touchid;
++ int i;
++
++ /* We handle deliveries to MDs through the SD, rather than copying
++ * the event and processing it twice. */
++ if (IsMaster(sourcedev))
++ return;
++
++ if (!t)
++ return;
++
++ /* If we hit 50% utilization of touches, double the number of touch
++ * frames. */
++ if (t->active_touches > t->num_touches / 2)
++ {
++ void *tmp;
++
++ tmp = realloc(t->touches, (t->num_touches * 2) * sizeof(*t->touches));
++ if (tmp)
++ {
++ t->touches = tmp;
++ memset(t->touches + t->num_touches, 0,
++ t->num_touches * sizeof(*t->touches));
++
++ for (i = t->num_touches; i < t->num_touches * 2; i++)
++ {
++ if (!InitTouchPoint(t, i))
++ {
++ LogMessage(X_ERROR,
++ "%s: failed to initialize new touchpoint %d\n",
++ sourcedev->name, i);
++ break;
++ }
++ }
++ t->num_touches = i;
++
++ LogMessage(X_INFO, "%s: reallocated %d touches\n", sourcedev->name,
++ t->num_touches);
++ } else
++ LogMessage(X_ERROR, "%s: failed to allocate more touches (%d)\n",
++ sourcedev->name, t->num_touches * 2);
++ }
++
++ touchid = ev->device_event.detail.touch;
++ ti = FindTouchPointByClientID(sourcedev, touchid);
++ if (!ti)
++ {
++ DebugF("[Xi] %s: Received event for inactive touchpoint %d\n",
++ sourcedev->name, touchid);
++ return;
++ }
++
++ /* Set the emulation touch for a direct touch device. Only one touch may be
++ * emulated per master device at a time. */
++ if (ev->any.type == ET_TouchBegin && t->mode == XIDirectTouch &&
++ masterdev && !masterdev->emulate_dev)
++ {
++ ti->emulate_pointer = TRUE;
++ sourcedev->touch->emulate = ti;
++ masterdev->emulate_dev = sourcedev;
++ }
++
++ /* Make sure we have a valid list of touch clients for event delivery. */
++ if (!EnsureTouchClients(sourcedev, ti, ev))
++ {
++ /* No touch clients, so only attempt to emulate a pointer. */
++ EmulateTouchEvents(sourcedev, ti, ev);
++
++ if (ti->active && ev->any.type == ET_TouchEnd)
++ EndTouchPoint(sourcedev, ti);
++
++ return;
++ }
++
++ if (ev->any.type == ET_TouchBegin)
++ {
++ if (ti->emulate_pointer)
++ {
++ if (!FindFirstGrab(sourcedev, ti))
++ {
++ if (ti->clients[0].type == TOUCH_SELECT)
++ {
++ ti->owner = 0;
++ EmulateTouchEvents(sourcedev, ti, ev);
++ return;
++ }
++ else if (ti->clients[0].type == TOUCH_SELECT_UNOWNED)
++ {
++ ti->owner = 0;
++ client = &ti->clients[ti->owner];
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++ DeliverOneTouchEvent(client, ti, ev);
++ EmulateTouchEvents(sourcedev, ti, ev);
++ return;
++ }
++ } else if (ti->owner < 0)
++ /* Pointer grab found, check touch grab first when replayed. */
++ ev->device_event.check_grab = TRUE;
++ }
++ else
++ ti->owner = 0;
++ }
++
++ /* Update touch history for non-emulated touches. Emulated touch history is
++ * maintained in syncEvents queue. */
++ if (!ti->emulate_pointer && !ti->accepted)
++ UpdateTouchHistory(ti, ev);
++
++ EmulateTouchEvents(sourcedev, ti, ev);
++
++ if (ti->owner >= 0)
++ client = &ti->clients[ti->owner];
++
++ /* Handle the special case where we are ending an emulated touch during an
++ * active pointer grab. */
++ if (ti == t->emulate && masterdev && masterdev->deviceGrab.grab &&
++ !masterdev->deviceGrab.fromPassiveGrab &&
++ !masterdev->deviceGrab.implicitGrab && ev->any.type == ET_TouchEnd)
++ {
++ InternalEvent mevent;
++
++ ev->device_event.flags |= XIPointerEmulated;
++
++ masterdev->u.lastSlave = sourcedev;
++ CopyGetMasterEvent(sourcedev, ev, &mevent);
++ masterdev->process_touch = TRUE;
++ masterdev->public.processInputProc(&mevent, masterdev);
++ masterdev->process_touch = FALSE;
++ if (client && (client->type == TOUCH_SELECT ||
++ client->type == TOUCH_SELECT_UNOWNED))
++ EndTouchPoint(sourcedev, ti);
++ }
++
++ /* If a touch is owned, deliver to the owning client. */
++ if (ti->owner >= 0 &&
++ (ti != t->emulate || ti->accepted ||
++ ((!client->grab && !sourcedev->deviceGrab.grab &&
++ !masterdev->deviceGrab.grab) ||
++ (client->grab && sourcedev->deviceGrab.grab &&
++ GrabMatchesSecond(sourcedev->deviceGrab.grab, client->grab, FALSE)) ||
++ (client->grab && masterdev && masterdev->deviceGrab.grab &&
++ GrabMatchesSecond(masterdev->deviceGrab.grab, client->grab, FALSE)))))
++ {
++ if (client->type == TOUCH_GRAB)
++ {
++ /* Mutate end event to a pending finish event for further
++ * clients. */
++ if (ev->any.type == ET_TouchEnd && !ti->accepted)
++ {
++ ev->any.type = ET_TouchMotion;
++ ev->device_event.flags |= XITouchPendingEnd;
++ ti->pending_finish = TRUE;
++ }
++
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ DeliverOneTouchEvent(client, ti, ev);
++ if (ev->any.type == ET_TouchBegin)
++ DeliverTouchOwnershipEvent(client, ti);
++ else if (ev->any.type == ET_TouchEnd)
++ EndTouchPoint(sourcedev, ti);
++ }
++ else if (client->type == TOUCH_SELECT ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ {
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ if (ev->any.type != ET_TouchEnd)
++ DeliverOneTouchEvent(client, ti, ev);
++
++ else if (client->type == TOUCH_SELECT_UNOWNED &&
++ ev->any.type == ET_TouchBegin)
++ DeliverTouchOwnershipEvent(client, ti);
++
++ /* An ending emulated touchpoint must release the primary mouse
++ * button. */
++ if (ev->any.type == ET_TouchEnd)
++ {
++ if (ti == sourcedev->touch->emulate)
++ ReleaseButton(masterdev, 1);
++ else
++ DeliverOneTouchEvent(client, ti, ev);
++
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++ }
++
++ /* Deliver to non-owners. */
++ if (ev->any.type == ET_TouchMotion)
++ ev->any.type = ET_TouchMotionUnowned;
++ else if (ev->any.type == ET_TouchEnd)
++ {
++ ev->any.type = ET_TouchMotionUnowned;
++ ev->device_event.flags |= XITouchPendingEnd;
++ ti->pending_finish = TRUE;
++ }
++
++ for (i = ti->owner + 1; i < ti->active_clients; i++)
++ {
++ TouchClientPtr client = &ti->clients[i];
++
++ ev->device_event.deviceid = client->device->id;
++ ev->device_event.sourceid = client->source->id;
++
++ if (client->type == TOUCH_GRAB ||
++ client->type == TOUCH_SELECT_UNOWNED)
++ DeliverOneTouchEvent(client, ti, ev);
++ }
++}
++
++/**
+ * Main device event processing function.
+ * Called from when processing the events from the event queue.
+ *
+@@ -954,6 +1942,33 @@
+ {
+ ProcessRawEvent(&ev->raw_event, device);
+ return;
++ } else if ((!syncEvents.playingEvents && !device->process_touch) &&
++ (ev->any.type == ET_TouchBegin ||
++ ev->any.type == ET_TouchMotion ||
++ ev->any.type == ET_TouchMotionUnowned ||
++ ev->any.type == ET_TouchOwnership ||
++ ev->any.type == ET_TouchEnd))
++ {
++ /* The first time through we figure out what to do with the touch.
++ * Further times through (playingEvents or process_touch), we process
++ * the event like any other. */
++ ProcessTouchEvent(ev, device);
++ return;
++ }
++
++ /* Ownership events are smaller than device events, so we must handle them
++ * first or we'll corrupt the heap. */
++ if (ev->any.type == ET_TouchOwnership)
++ {
++ grab = device->deviceGrab.grab;
++
++ if (grab)
++ DeliverGrabbedEvent(ev, device, FALSE);
++ else
++ DeliverDeviceEvents(GetSpriteWindow(device), ev, NullGrab,
++ NullWindow, device);
++
++ return;
+ }
+
+ if (IsPointerDevice(device))
+@@ -1152,6 +2167,50 @@
+ dev->proximity->in_proximity = FALSE;
+ }
+
++void
++InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
++ int maxval, int resolution)
++{
++ TouchAxisInfoPtr ax;
++
++ if (!dev || !dev->touch || minval > maxval)
++ return;
++ if (axnum >= dev->touch->num_axes)
++ return;
++
++ ax = dev->touch->axes + axnum;
++
++ ax->min_value = minval;
++ ax->max_value = maxval;
++ ax->resolution = resolution;
++ ax->label = label;
++
++ if (ax->label == XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X))
++ {
++ dev->touch->x_axis = axnum;
++ if (dev->touch->mode == XIDirectTouch &&
++ (!dev->valuator || dev->valuator->numAxes < 1 ||
++ dev->valuator->axes[0].min_value != minval ||
++ dev->valuator->axes[0].max_value != maxval ||
++ dev->valuator->axes[0].resolution != resolution))
++ LogMessage(X_WARNING, "Touch X valuator does not match pointer X "
++ "valuator, pointer emulation may be "
++ "incorrect\n");
++ }
++ else if (ax->label == XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y))
++ {
++ dev->touch->y_axis = axnum;
++ if (dev->touch->mode == XIDirectTouch &&
++ (!dev->valuator || dev->valuator->numAxes < 2 ||
++ dev->valuator->axes[1].min_value != minval ||
++ dev->valuator->axes[1].max_value != maxval ||
++ dev->valuator->axes[1].resolution != resolution))
++ LogMessage(X_WARNING, "Touch Y valuator does not match pointer Y "
++ "valuator, pointer emulation may be "
++ "incorrect\n");
++ }
++}
++
+ static void
+ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
+ ButtonClassPtr b, ValuatorClassPtr v, int first)
+@@ -1562,6 +2621,38 @@
+ return AddPassiveGrabToList(client, grab);
+ }
+
++/* Touch grab */
++int
++GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
++ GrabParameters *param, GrabMask *mask)
++{
++ WindowPtr pWin;
++ GrabPtr grab;
++ int rc;
++
++ rc = CheckGrabValues(client, param);
++ if (rc != Success)
++ return rc;
++
++ rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
++ if (rc != Success)
++ return rc;
++ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixFreezeAccess);
++ if (rc != Success)
++ return rc;
++
++ /* Touch grabs are asynchronous in protocol, but we need to freeze the
++ * pointer device if a touch grab is activated for pointer emulation. */
++ param->other_devices_mode = GrabModeSync;
++
++ grab = CreateGrab(client->index, dev, mod_dev, pWin, GRABTYPE_XI2,
++ mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
++ if (!grab)
++ return BadAlloc;
++
++ return AddPassiveGrabToList(client, grab);
++}
++
+ int
+ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
+ Mask mask, Mask exclusivemasks)
+@@ -1695,10 +2786,65 @@
+ }
+ }
+
++static void
++RemoveTouchClient(DeviceIntPtr dev, TouchPointInfoPtr ti, int index)
++{
++ TouchClientPtr tc = &ti->clients[index];
++ int i;
++
++ if (index == ti->owner) {
++ if (tc->grab && dev->deviceGrab.grab &&
++ GrabMatchesSecond(tc->grab, dev->deviceGrab.grab,
++ FALSE))
++ ProcessTouchOwnership(dev, ti, XITouchOwnerRejectEnd, TRUE);
++ else {
++ ti->owner++;
++ if (ti->owner >= ti->active_clients) {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ }
++ }
++ return;
++ }
++
++ for (i = index; i < ti->active_clients - 1; i++)
++ memcpy(ti->clients + i, ti->clients + i + 1,
++ sizeof(TouchClientRec));
++ ti->active_clients--;
++}
++
++
+ int
+ InputClientGone(WindowPtr pWin, XID id)
+ {
+ InputClientsPtr other, prev;
++ DeviceIntPtr dev;
++
++ for (dev = inputInfo.devices; dev; dev = dev->next) {
++ TouchClassPtr t = dev->touch;
++ int i;
++
++ if (!t)
++ continue;
++
++ for (i = 0; i < t->num_touches; i++) {
++ TouchPointInfoPtr ti = &t->touches[i];
++ int j;
++
++ if (!ti->active || ti->active_clients == 0)
++ continue;
++
++ j = (ti->owner < 0) ? 0 : ti->owner;
++ while (j < ti->active_clients) {
++ TouchClientPtr tc = &ti->clients[j];
++
++ if (clients[CLIENT_ID(id)] == tc->client)
++ RemoveTouchClient(dev, ti, j);
++ else
++ j++;
++ }
++ }
++ }
+
+ if (!wOtherInputMasks(pWin))
+ return Success;
+@@ -1734,6 +2880,54 @@
+ FatalError("client not on device event list");
+ }
+
++/**
++ * Search for window in each touch trace for each device. Remove the window
++ * and all its subwindows from the trace when found. The initial window
++ * order is preserved.
++ */
++void WindowGone(WindowPtr win)
++{
++ DeviceIntPtr dev;
++
++ for (dev = inputInfo.devices; dev; dev = dev->next) {
++ TouchClassPtr t = dev->touch;
++ int i;
++
++ if (!t)
++ continue;
++
++ for (i = 0; i < t->num_touches; i++) {
++ SpritePtr sprite = &t->touches[i].sprite;
++ int j;
++
++ for (j = 0; j < sprite->spriteTraceGood; j++) {
++ if (sprite->spriteTrace[j] == win) {
++ sprite->spriteTraceGood = j;
++ break;
++ }
++ }
++ }
++
++ for (i = 0; i < t->num_touches; i++) {
++ TouchPointInfoPtr ti = &t->touches[i];
++ int j;
++
++ if (!ti->active || ti->active_clients == 0)
++ continue;
++
++ j = (ti->owner < 0) ? 0 : ti->owner;
++ while (j < ti->active_clients) {
++ TouchClientPtr tc = &ti->clients[j];
++
++ if (win == tc->window)
++ RemoveTouchClient(dev, ti, j);
++ else
++ j++;
++ }
++ }
++ }
++}
++
+ int
+ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
+ xEvent * ev, Mask mask, int count)
+Index: b/Xi/extinit.c
+===================================================================
+--- a/Xi/extinit.c 2011-02-28 16:57:00.000000000 +1100
++++ b/Xi/extinit.c 2011-03-09 13:11:48.093384404 +1100
+@@ -258,7 +258,8 @@
+ ProcXIChangeProperty, /* 57 */
+ ProcXIDeleteProperty, /* 58 */
+ ProcXIGetProperty, /* 59 */
+- ProcXIGetSelectedEvents /* 60 */
++ ProcXIGetSelectedEvents, /* 60 */
++ ProcXIAllowTouchEvents, /* 61 */
+ };
+
+ /* For swapped clients */
+@@ -323,7 +324,8 @@
+ SProcXIChangeProperty, /* 57 */
+ SProcXIDeleteProperty, /* 58 */
+ SProcXIGetProperty, /* 59 */
+- SProcXIGetSelectedEvents /* 60 */
++ SProcXIGetSelectedEvents, /* 60 */
++ SProcXIAllowTouchEvents, /* 61 */
+ };
+
+ /*****************************************************************
+@@ -854,6 +856,21 @@
+ swaps(&to->valuators_len, n);
+ }
+
++static void STouchOwnershipEvent(xXITouchOwnershipEvent *from,
++ xXITouchOwnershipEvent *to)
++{
++ char n;
++
++ *to = *from;
++ swaps(&to->sequenceNumber, n);
++ swapl(&to->length, n);
++ swaps(&to->evtype, n);
++ swaps(&to->deviceid, n);
++ swapl(&to->time, n);
++ swaps(&to->sourceid, n);
++ swapl(&to->touchid, n);
++ swapl(&to->flags, n);
++}
+
+ /** Event swapping function for XI2 events. */
+ void
+@@ -881,8 +898,16 @@
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
++ case XI_TouchBegin:
++ case XI_TouchUpdate:
++ case XI_TouchUpdateUnowned:
++ case XI_TouchEnd:
+ SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
+ break;
++ case XI_TouchOwnership:
++ STouchOwnershipEvent((xXITouchOwnershipEvent*)from,
++ (xXITouchOwnershipEvent*)to);
++ break;
+ case XI_RawMotion:
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+Index: b/Xi/xiallowev.c
+===================================================================
+--- a/Xi/xiallowev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiallowev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -35,11 +35,15 @@
+
+ #include "inputstr.h" /* DeviceIntPtr */
+ #include "windowstr.h" /* window structure */
++#include "eventstr.h"
++#include "mi.h"
+ #include <X11/extensions/XI2.h>
+ #include <X11/extensions/XI2proto.h>
+
+ #include "exglobals.h" /* BadDevice */
+ #include "xiallowev.h"
++#include "exevents.h"
++#include "dixgrabs.h"
+
+ int
+ SProcXIAllowEvents(ClientPtr client)
+@@ -98,6 +102,113 @@
+ ret = BadValue;
+ }
+
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (dev->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = dev->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return ret;
+ }
+
++int
++SProcXIAllowTouchEvents(ClientPtr client)
++{
++ char n;
++
++ REQUEST(xXIAllowTouchEventsReq);
++
++ swaps(&stuff->length, n);
++ swaps(&stuff->deviceid, n);
++ swapl(&stuff->touchid, n);
++
++ return ProcXIAllowTouchEvents(client);
++}
++
++int
++ProcXIAllowTouchEvents(ClientPtr client)
++{
++ DeviceIntPtr dev;
++ TouchClassPtr t;
++ TouchPointInfoPtr ti;
++ TouchClientPtr tc;
++ int ret;
++ EventList *events = InitEventList(GetMaximumEventsNum());
++
++ REQUEST(xXIAllowTouchEventsReq);
++ REQUEST_SIZE_MATCH(xXIAllowTouchEventsReq);
++
++ if (!events)
++ return BadAlloc;
++
++ ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
++ if (ret != Success)
++ return ret;
++
++ if (!dev->touch)
++ {
++ client->errorValue = stuff->deviceid;
++ return BadDevice;
++ }
++
++ t = dev->touch;
++
++ ti = FindTouchPointByClientID(dev, stuff->touchid);
++ if (!ti)
++ {
++ client->errorValue = stuff->touchid;
++ return BadValue;
++ }
++
++ tc = &ti->clients[ti->owner];
++
++ if (client != tc->client || !tc->grab)
++ return BadAccess;
++
++ if (ti == t->emulate)
++ {
++ DeviceIntPtr master = dev->u.master;
++
++ if (!master || !master->deviceGrab.grab ||
++ !GrabMatchesSecond(master->deviceGrab.grab, tc->grab, FALSE))
++ return BadAccess;
++ }
++
++ if (stuff->mode & XITouchOwnerAccept)
++ {
++ if (stuff->mode & ~XITouchOwnerAccept)
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++ }
++ else if (stuff->mode & XITouchOwnerRejectEnd)
++ {
++ if (stuff->mode & ~XITouchOwnerRejectEnd)
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++ }
++ else
++ {
++ client->errorValue = stuff->mode;
++ return BadValue;
++ }
++
++ ProcessTouchOwnership(dev, ti, stuff->mode, TRUE);
++
++ return Success;
++}
+Index: b/Xi/xiallowev.h
+===================================================================
+--- a/Xi/xiallowev.h 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiallowev.h 2011-03-09 13:11:48.093384404 +1100
+@@ -32,5 +32,7 @@
+
+ int ProcXIAllowEvents(ClientPtr client);
+ int SProcXIAllowEvents(ClientPtr client);
++int ProcXIAllowTouchEvents(ClientPtr client);
++int SProcXIAllowTouchEvents(ClientPtr client);
+
+ #endif /* XIALLOWEV_H */
+Index: b/Xi/xipassivegrab.c
+===================================================================
+--- a/Xi/xipassivegrab.c 2011-03-09 11:19:12.000000000 +1100
++++ b/Xi/xipassivegrab.c 2011-03-09 13:11:48.093384404 +1100
+@@ -105,19 +105,30 @@
+ if (stuff->grab_type != XIGrabtypeButton &&
+ stuff->grab_type != XIGrabtypeKeycode &&
+ stuff->grab_type != XIGrabtypeEnter &&
+- stuff->grab_type != XIGrabtypeFocusIn)
++ stuff->grab_type != XIGrabtypeFocusIn &&
++ stuff->grab_type != XIGrabtypeTouchBegin)
+ {
+ client->errorValue = stuff->grab_type;
+ return BadValue;
+ }
+
+ if ((stuff->grab_type == XIGrabtypeEnter ||
+- stuff->grab_type == XIGrabtypeFocusIn) && stuff->detail != 0)
++ stuff->grab_type == XIGrabtypeFocusIn ||
++ stuff->grab_type == XIGrabtypeTouchBegin) &&
++ stuff->detail != 0)
+ {
+ client->errorValue = stuff->detail;
+ return BadValue;
+ }
+
++ if (stuff->grab_type == XIGrabtypeTouchBegin &&
++ (stuff->grab_mode != GrabModeAsync ||
++ stuff->paired_device_mode != GrabModeAsync))
++ {
++ client->errorValue = GrabModeSync;
++ return BadValue;
++ }
++
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&stuff[1],
+ stuff->mask_len * 4) != Success)
+ return BadValue;
+@@ -185,6 +196,9 @@
+ status = GrabWindow(client, dev, stuff->grab_type,
+ &param, &mask);
+ break;
++ case XIGrabtypeTouchBegin:
++ status = GrabTouch(client, dev, mod_dev, &param, &mask);
++ break;
+ }
+
+ if (status != GrabSuccess)
+Index: b/Xi/xiquerydevice.c
+===================================================================
+--- a/Xi/xiquerydevice.c 2011-03-09 11:19:12.000000000 +1100
++++ b/Xi/xiquerydevice.c 2011-03-09 13:11:48.093384404 +1100
+@@ -232,6 +232,12 @@
+ if (dev->valuator)
+ len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
+
++ if (dev->touch)
++ {
++ len += sizeof(xXITouchInfo);
++ len += sizeof(xXITouchValuatorInfo) * dev->touch->num_axes;
++ }
++
+ return len;
+ }
+
+@@ -373,6 +379,73 @@
+ swaps(&info->sourceid, n);
+ }
+
++/**
++ * List multitouch information
++ *
++ * @return The number of bytes written into info.
++ */
++int
++ListTouchInfo(DeviceIntPtr dev, xXITouchInfo *touch)
++{
++ touch->type = XITouchClass;
++ touch->length = sizeof(xXITouchInfo) >> 2;
++ touch->sourceid = dev->id;
++ touch->mode = dev->touch->mode;
++ touch->num_touches = dev->touch->num_touches;
++
++ return touch->length << 2;
++}
++
++static void
++SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo* touch)
++{
++ char n;
++ swaps(&touch->type, n);
++ swaps(&touch->length, n);
++ swaps(&touch->sourceid, n);
++}
++
++/**
++ * List multitouch axis information
++ *
++ * @return The number of bytes written into info.
++ */
++int
++ListTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val,
++ int axisnumber)
++{
++ TouchClassPtr t = dev->touch;
++
++ val->type = XITouchValuatorClass;
++ val->length = sizeof(xXITouchValuatorInfo) >> 2;
++ val->sourceid = dev->id;
++ val->number = axisnumber;
++ val->label = t->axes[axisnumber].label;
++ val->min.integral = t->axes[axisnumber].min_value;
++ val->min.frac = 0;
++ val->max.integral = t->axes[axisnumber].max_value;
++ val->max.frac = 0;
++ val->resolution = t->axes[axisnumber].resolution;
++
++ return val->length << 2;
++}
++
++static void
++SwapTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val)
++{
++ char n;
++ swaps(&val->type, n);
++ swaps(&val->length, n);
++ swaps(&val->sourceid, n);
++ swaps(&val->number, n);
++ swapl(&val->label, n);
++ swapl(&val->min.integral, n);
++ swapl(&val->min.frac, n);
++ swapl(&val->max.integral, n);
++ swapl(&val->max.frac, n);
++ swapl(&val->resolution, n);
++}
++
+ int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
+ {
+ DeviceIntPtr master = dev->u.master;
+@@ -462,6 +535,22 @@
+ total_len += len;
+ }
+
++ if (dev->touch)
++ {
++ (*nclasses)++;
++ len = ListTouchInfo(dev, (xXITouchInfo*)any);
++ any += len;
++ total_len += len;
++
++ for (i = 0; i < dev->touch->num_axes; i++)
++ {
++ (*nclasses)++;
++ len = ListTouchValuatorInfo(dev, (xXITouchValuatorInfo*)any, i);
++ any += len;
++ total_len += len;
++ }
++ }
++
+ return total_len;
+ }
+
+@@ -489,6 +578,12 @@
+ case XIValuatorClass:
+ SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
+ break;
++ case XITouchClass:
++ SwapTouchInfo(dev, (xXITouchInfo*)any);
++ break;
++ case XITouchValuatorClass:
++ SwapTouchValuatorInfo(dev, (xXITouchValuatorInfo*)any);
++ break;
+ }
+
+ any += len * 4;
+Index: b/Xi/xiquerydevice.h
+===================================================================
+--- a/Xi/xiquerydevice.h 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiquerydevice.h 2011-03-09 13:11:48.093384404 +1100
+@@ -44,4 +44,7 @@
+ int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info);
+ int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info,
+ int axisnumber, Bool reportState);
++int ListTouchInfo(DeviceIntPtr dev, xXITouchInfo* info);
++int ListTouchValuatorInfo(DeviceIntPtr dev, xXITouchValuatorInfo* val,
++ int axisnumber);
+ #endif /* QUERYDEV_H */
+Index: b/Xi/xiselectev.c
+===================================================================
+--- a/Xi/xiselectev.c 2011-02-28 13:56:41.000000000 +1100
++++ b/Xi/xiselectev.c 2011-03-09 13:11:48.093384404 +1100
+@@ -152,6 +152,60 @@
+ }
+ }
+
++ if (evmask->mask_len >= 1)
++ {
++ unsigned char *bits = (unsigned char*)&evmask[1];
++
++ /* Check validity of touch selections */
++ if (BitIsOn(bits, XI_TouchBegin) ||
++ BitIsOn(bits, XI_TouchUpdate) ||
++ BitIsOn(bits, XI_TouchEnd))
++ {
++ /* All three touch events must be selected at once */
++ if (!BitIsOn(bits, XI_TouchBegin) ||
++ !BitIsOn(bits, XI_TouchUpdate) ||
++ !BitIsOn(bits, XI_TouchEnd))
++ {
++ client->errorValue = XI_TouchBegin;
++ return BadValue;
++ }
++
++ /* Unowned and ownership events must both be selected */
++ if ((BitIsOn(bits, XI_TouchUpdateUnowned) ||
++ BitIsOn(bits, XI_TouchOwnership)) &&
++ (!BitIsOn(bits, XI_TouchUpdateUnowned) ||
++ !BitIsOn(bits, XI_TouchOwnership)))
++ {
++ client->errorValue = XI_TouchBegin;
++ return BadValue;
++ }
++ }
++
++ /* Only one client per window may select for touch events on the
++ * same devices, including master devices.
++ * XXX: This breaks if a device goes from floating to attached. */
++ if (BitIsOn(bits, XI_TouchBegin))
++ {
++ OtherInputMasks *inputMasks = wOtherInputMasks(win);
++ InputClients *iclient = NULL;
++ if (inputMasks)
++ iclient = inputMasks->inputClients;
++ for (; iclient; iclient = iclient->next)
++ {
++ if (CLIENT_ID(iclient->resource) == client->index)
++ continue;
++ if (BitIsOn(iclient->xi2mask[evmask->deviceid],
++ XI_TouchBegin) ||
++ BitIsOn(iclient->xi2mask[XIAllDevices],
++ XI_TouchBegin) ||
++ (dev && (IsMaster(dev) || dev->u.master) &&
++ BitIsOn(iclient->xi2mask[XIAllMasterDevices],
++ XI_TouchBegin)))
++ return BadAccess;
++ }
++ }
++ }
++
+ if (XICheckInvalidMaskBits(client, (unsigned char*)&evmask[1],
+ evmask->mask_len * 4) != Success)
+ return BadValue;
+Index: b/dix/devices.c
+===================================================================
+--- a/dix/devices.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/devices.c 2011-03-09 13:11:48.103384795 +1100
+@@ -754,6 +754,20 @@
+ free((*v));
+ break;
+ }
++ case XITouchClass:
++ {
++ TouchClassPtr *t = (TouchClassPtr*)class;
++ int i;
++
++ for (i = 0; i < (*t)->num_touches; i++)
++ {
++ free((*t)->touches[i].sprite.spriteTrace);
++ free((*t)->touches[i].clients);
++ }
++
++ free((*t));
++ break;
++ }
+ case FocusClass:
+ {
+ FocusClassPtr *f = (FocusClassPtr*)class;
+@@ -862,6 +876,7 @@
+
+ FreeDeviceClass(KeyClass, (pointer)&classes->key);
+ FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
++ FreeDeviceClass(XITouchClass, (pointer)&classes->touch);
+ FreeDeviceClass(ButtonClass, (pointer)&classes->button);
+ FreeDeviceClass(FocusClass, (pointer)&classes->focus);
+ FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
+@@ -1543,6 +1558,151 @@
+ InitPtrFeedbackClassDeviceStruct(dev, controlProc));
+ }
+
++Bool
++InitTouchPoint(TouchClassPtr t, int index)
++{
++ TouchPointInfoPtr ti;
++
++ if (!index >= t->num_touches)
++ return FALSE;
++ ti = &t->touches[index];
++
++ ti->valuators = calloc(t->num_axes, sizeof(*ti->valuators));
++ if (!ti->valuators)
++ return FALSE;
++ ti->num_valuators = t->num_axes;
++
++ ti->sprite.spriteTrace = calloc(32, sizeof(*ti->sprite.spriteTrace));
++ if (!ti->sprite.spriteTrace)
++ {
++ free(ti->valuators);
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ return FALSE;
++ }
++ ti->sprite.spriteTraceSize = 32;
++ ti->sprite.spriteTrace[0] = screenInfo.screens[0]->root;
++ ti->sprite.hot.pScreen = screenInfo.screens[0];
++ ti->sprite.hotPhys.pScreen = screenInfo.screens[0];
++
++ ti->ddx_id = -1;
++ ti->client_id = -1;
++
++ ti->history_size = GetMotionHistorySize();
++ ti->begin_event = malloc((ti->history_size + 1) * sizeof(InternalEvent));
++ if (!ti->begin_event)
++ {
++ free(ti->sprite.spriteTrace);
++ free(ti->valuators);
++ ti->sprite.spriteTrace = NULL;
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ return FALSE;
++ }
++ ti->history = ti->begin_event + 1;
++ ti->first_history = ti->history;
++ ti->next_history = ti->history;
++
++ return TRUE;
++}
++
++void
++FreeTouchPoint(DeviceIntPtr device, int index)
++{
++ TouchPointInfoPtr ti;
++
++ if (!device->touch || index >= device->touch->num_touches)
++ return;
++ ti = &device->touch->touches[index];
++
++ if (ti->active)
++ EndTouchPoint(device, ti);
++
++ free(ti->valuators);
++ ti->valuators = NULL;
++ ti->num_valuators = 0;
++ free(ti->sprite.spriteTrace);
++ ti->sprite.spriteTrace = NULL;
++ free(ti->begin_event);
++ ti->begin_event = NULL;
++ free(ti->clients);
++ ti->clients = NULL;
++ ti->num_clients = 0;
++}
++
++/**
++ * Sets up multitouch capabilities on @device.
++ *
++ * @max_touches The maximum number of simultaneous touches, or 0 for unlimited.
++ * @mode The mode of the touch device (XIDirectTouch or XIDependentTouch).
++ * @num_axes The number of touch valuator axes.
++ */
++Bool
++InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
++ unsigned int mode, unsigned int num_axes)
++{
++ TouchClassPtr touch;
++ int i;
++
++ if (device->touch)
++ return FALSE;
++
++ /* Check the mode is valid, and at least X and Y axes. */
++ if (mode != XIDirectTouch && mode != XIDependentTouch)
++ return FALSE;
++ if (num_axes < 2)
++ return FALSE;
++
++ if (num_axes > MAX_VALUATORS)
++ {
++ LogMessage(X_WARNING,
++ "Device '%s' has %d touch axes, only using first %d.\n",
++ device->name, num_axes, MAX_VALUATORS);
++ num_axes = MAX_VALUATORS;
++ }
++
++ touch = calloc(1, sizeof(*touch));
++ if (!touch)
++ return FALSE;
++
++ touch->axes = calloc(num_axes, sizeof(*touch->axes));
++ if (!touch->axes)
++ goto err;
++ touch->num_axes = num_axes;
++
++ touch->max_touches = max_touches;
++ if (max_touches == 0)
++ max_touches = 5; /* arbitrary number plucked out of the air */
++
++ /* Need cushion for clients who may hold on to touches after they physically
++ * end. So double the initial allocation of touches. */
++ touch->touches = calloc(max_touches * 2, sizeof(*touch->touches));
++ if (!touch->touches)
++ goto err;
++ touch->num_touches = max_touches * 2;
++ for (i = 0; i < touch->num_touches; i++)
++ InitTouchPoint(touch, i);
++
++ touch->mode = mode;
++ touch->x_axis = -1;
++ touch->y_axis = -1;
++ touch->next_client_id = 1;
++
++ device->touch = touch;
++
++ return TRUE;
++
++err:
++ for (i = 0; i < touch->num_touches; i++)
++ FreeTouchPoint(device, i);
++
++ free(touch->touches);
++ free(touch->axes);
++ free(touch);
++
++ return FALSE;
++}
++
+ /*
+ * Check if the given buffer contains elements between low (inclusive) and
+ * high (inclusive) only.
+@@ -2375,6 +2535,58 @@
+ }
+ }
+
++static void
++DropTouchSelectionsOnWindow(DeviceIntPtr dev, WindowPtr win)
++{
++ WindowPtr child;
++
++ if (wOtherInputMasks(win) &&
++ BitIsOn(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin))
++ {
++ InputClientsPtr client = wOtherInputMasks(win)->inputClients;
++
++ /* Don't bother deleting client record if there are no other
++ * selections. The client will likely reselect when it gets the
++ * HierarchyChange event. */
++ while (client)
++ {
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchEnd);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchOwnership);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdate);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdateUnowned);
++
++ client = client->next;
++ }
++
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchBegin);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchEnd);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchOwnership);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdate);
++ ClearBit(wOtherInputMasks(win)->xi2mask[dev->id], XI_TouchUpdateUnowned);
++ }
++
++ child = win->firstChild;
++ while (child)
++ {
++ DropTouchSelectionsOnWindow(dev, child);
++ child = child->nextSib;
++ }
++}
++
++static void
++DropTouchSelections(DeviceIntPtr dev)
++{
++ int i;
++
++ for (i = 0; i < screenInfo.numScreens; i++)
++ {
++ WindowPtr win = screenInfo.screens[i]->root;
++
++ DropTouchSelectionsOnWindow(dev, win);
++ }
++}
++
+ /**
+ * Attach device 'dev' to device 'master'.
+ * Client is set to the client that issued the request, or NULL if it comes
+@@ -2440,6 +2652,12 @@
+ dev->spriteInfo->spriteOwner = FALSE;
+
+ RecalculateMasterButtons(master);
++
++ /* Only one client may select for touch events from a device on a window
++ * at any time. Reattaching could break this, so drop all touch event
++ * selections for this specific slave device on all windows. */
++ if (dev->touch)
++ DropTouchSelections(dev);
+ }
+
+ /* XXX: in theory, the MD should change back to its old, original
+Index: b/dix/eventconvert.c
+===================================================================
+--- a/dix/eventconvert.c 2011-03-09 11:39:57.000000000 +1100
++++ b/dix/eventconvert.c 2011-03-09 13:11:48.103384795 +1100
+@@ -55,6 +55,7 @@
+ static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce);
+ static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
+ static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
++static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
+
+ /* Do not use, read comments below */
+ BOOL EventIsKeyRepeat(xEvent *event);
+@@ -139,6 +140,11 @@
+ case ET_RawButtonPress:
+ case ET_RawButtonRelease:
+ case ET_RawMotion:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchOwnership:
+ return BadMatch;
+ default:
+ /* XXX: */
+@@ -184,6 +190,11 @@
+ case ET_RawButtonPress:
+ case ET_RawButtonRelease:
+ case ET_RawMotion:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchOwnership:
+ *count = 0;
+ *xi = NULL;
+ return BadMatch;
+@@ -225,7 +236,13 @@
+ case ET_ButtonRelease:
+ case ET_KeyPress:
+ case ET_KeyRelease:
++ case ET_TouchBegin:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
++ case ET_TouchEnd:
+ return eventToDeviceEvent(&ev->device_event, xi);
++ case ET_TouchOwnership:
++ return eventToTouchOwnershipEvent(&ev->touch_ownership_event, xi);
+ case ET_ProximityIn:
+ case ET_ProximityOut:
+ *xi = NULL;
+@@ -588,6 +605,7 @@
+ xde->root_x = FP1616(ev->root_x, ev->root_x_frac);
+ xde->root_y = FP1616(ev->root_y, ev->root_y_frac);
+
++ xde->flags = ev->flags;
+ if (ev->key_repeat)
+ xde->flags |= XIKeyRepeat;
+
+@@ -625,6 +643,27 @@
+ }
+
+ static int
++eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi)
++{
++ int len = sizeof(xXITouchOwnershipEvent);
++ xXITouchOwnershipEvent *xtoe;
++
++ *xi = calloc(1, len);
++ xtoe = (xXITouchOwnershipEvent*)*xi;
++ xtoe->type = GenericEvent;
++ xtoe->extension = IReqCode;
++ xtoe->length = bytes_to_int32(len - sizeof(xEvent));
++ xtoe->evtype = GetXI2Type((InternalEvent*)ev);
++ xtoe->deviceid = ev->deviceid;
++ xtoe->time = ev->time;
++ xtoe->sourceid = ev->sourceid;
++ xtoe->touchid = ev->touchid;
++ xtoe->flags = ev->flags;
++
++ return Success;
++}
++
++static int
+ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
+ {
+ xXIRawEvent* raw;
+@@ -739,6 +778,11 @@
+ case ET_RawMotion: xi2type = XI_RawMotion; break;
+ case ET_FocusIn: xi2type = XI_FocusIn; break;
+ case ET_FocusOut: xi2type = XI_FocusOut; break;
++ case ET_TouchBegin: xi2type = XI_TouchBegin; break;
++ case ET_TouchEnd: xi2type = XI_TouchEnd; break;
++ case ET_TouchMotion: xi2type = XI_TouchUpdate; break;
++ case ET_TouchMotionUnowned: xi2type = XI_TouchUpdateUnowned; break;
++ case ET_TouchOwnership: xi2type = XI_TouchOwnership; break;
+ default:
+ break;
+ }
+Index: b/dix/events.c
+===================================================================
+--- a/dix/events.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/events.c 2011-03-09 13:11:48.103384795 +1100
+@@ -1089,7 +1089,7 @@
+ void
+ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
+ {
+- QdEventPtr tail = *syncEvents.pendtail;
++ QdEventPtr tail = syncEvents.pendtail;
+ QdEventPtr qe;
+ SpritePtr pSprite = device->spriteInfo->sprite;
+ int eventlen;
+@@ -1160,8 +1160,10 @@
+ qe->event = (InternalEvent *)(qe + 1);
+ memcpy(qe->event, event, eventlen);
+ if (tail)
+- syncEvents.pendtail = &tail->next;
+- *syncEvents.pendtail = qe;
++ tail->next = qe;
++ else
++ syncEvents.pending = qe;
++ syncEvents.pendtail = qe;
+ }
+
+ /**
+@@ -1176,18 +1178,19 @@
+ static void
+ PlayReleasedEvents(void)
+ {
+- QdEventPtr *prev, qe;
++ QdEventPtr prev, qe = syncEvents.pending;
+ DeviceIntPtr dev;
+ DeviceIntPtr pDev;
+
+- prev = &syncEvents.pending;
+- while ( (qe = *prev) )
++ prev = NULL;
++ while (qe)
+ {
+ if (!qe->device->deviceGrab.sync.frozen)
+ {
+- *prev = qe->next;
++ if (syncEvents.pending == qe)
++ syncEvents.pending = qe->next;
+ pDev = qe->device;
+- if (*syncEvents.pendtail == *prev)
++ if (syncEvents.pendtail == qe)
+ syncEvents.pendtail = prev;
+ if (qe->event->any.type == ET_Motion)
+ CheckVirtualMotion(pDev, qe, NullWindow);
+@@ -1219,6 +1222,7 @@
+
+ }
+ #endif
++
+ (*qe->device->public.processInputProc)(qe->event, qe->device);
+ free(qe);
+ for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
+@@ -1227,10 +1231,14 @@
+ break;
+ /* Playing the event may have unfrozen another device. */
+ /* So to play it safe, restart at the head of the queue */
+- prev = &syncEvents.pending;
++ qe = syncEvents.pending;
++ prev = NULL;
+ }
+ else
+- prev = &qe->next;
++ {
++ prev = qe;
++ qe = qe->next;
++ }
+ }
+ }
+
+@@ -1252,6 +1260,76 @@
+ dev->public.processInputProc = dev->public.realInputProc;
+ }
+
++void
++RemoveTouchEventsFromQueue(DeviceIntPtr dev, Bool touch, Bool ignoreOwned)
++{
++ QdEventPtr qe = syncEvents.pending;
++ QdEventPtr prev_qe = NULL;
++ QdEventPtr first = NULL;
++ Bool end = FALSE;
++
++ while (qe && !end)
++ {
++ QdEventPtr tmp;
++
++ if (qe->device != dev)
++ continue;
++
++ if (ignoreOwned && (qe->event->any.type == ET_TouchOwnership ||
++ qe->event->any.type == ET_TouchEnd))
++ break;
++
++ if (qe->event->any.type == ET_TouchEnd)
++ end = TRUE;
++
++ if ((touch && !IsTouchEvent(qe->event)) ||
++ (!touch && !IsPointerEvent(qe->event)) ||
++ (ignoreOwned && qe->event->any.type == ET_TouchBegin))
++ {
++ if (!first)
++ first = qe;
++ prev_qe = qe;
++ qe = qe->next;
++ continue;
++ }
++
++ tmp = qe;
++ qe = qe->next;
++ if (prev_qe)
++ prev_qe->next = qe;
++ if (syncEvents.pending == tmp)
++ syncEvents.pending = qe;
++
++ free(tmp);
++
++ if (!qe)
++ syncEvents.pendtail = prev_qe;
++ }
++
++ if (qe && !qe->next)
++ syncEvents.pendtail = qe;
++
++ if (dev->deviceGrab.sync.event &&
++ ((touch && IsTouchEvent((InternalEvent *)dev->deviceGrab.sync.event)) ||
++ (!touch &&
++ IsPointerEvent((InternalEvent *)dev->deviceGrab.sync.event))))
++ {
++ free(dev->deviceGrab.sync.event);
++ if (first)
++ {
++ dev->deviceGrab.sync.event = malloc(sizeof(DeviceEvent));
++ memcpy(dev->deviceGrab.sync.event, first->event,
++ sizeof(DeviceEvent));
++ }
++ else
++ dev->deviceGrab.sync.event = NULL;
++ syncEvents.pending = first->next;
++ free(first);
++ if (!syncEvents.pending)
++ syncEvents.pendtail = NULL;
++ }
++}
++
+ /**
+ * Unfreeze devices and replay all events to the respective clients.
+ *
+@@ -1278,6 +1356,14 @@
+ {
+ DeviceEvent* event = replayDev->deviceGrab.sync.event;
+
++ if (event->type == ET_TouchBegin)
++ {
++ ProcessTouchOwnership(replayDev, event->touchpoint,
++ XITouchOwnerAccept, FALSE);
++ if (!replayDev->deviceGrab.sync.event)
++ goto no_sync;
++ }
++
+ syncEvents.replayDev = (DeviceIntPtr)NULL;
+
+ w = XYToWindow(replayDev->spriteInfo->sprite,
+@@ -1291,6 +1377,7 @@
+ NullWindow, replayDev);
+ }
+ }
++no_sync:
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (!dev->deviceGrab.sync.frozen)
+@@ -1510,6 +1597,20 @@
+ if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
+ ReattachToOldMaster(mouse);
+
++ if (mouse->deviceGrab.sync.event &&
++ (mouse->deviceGrab.sync.event->flags & XIPointerEmulated) &&
++ (grab->grabtype != GRABTYPE_XI2 || grab->type != XI_TouchBegin))
++ {
++ InternalEvent event;
++
++ event.any.type = ET_TouchBegin;
++
++ if (CheckPassiveGrabsOnWindow(grab->window, mouse, &event, FALSE, TRUE))
++ syncEvents.playingEvents = TRUE;
++ }
++ else
++ syncEvents.playingEvents = FALSE;
++
+ ComputeFreezes();
+ }
+
+@@ -1757,6 +1858,25 @@
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
++
++ /* If this is a master pointer with an active touch emulation and the touch
++ * has physically ceased, end the touchpoint state. */
++ if (mouse->emulate_dev)
++ {
++ DeviceIntPtr sourcedev = mouse->emulate_dev;
++ TouchPointInfoPtr ti = sourcedev->touch->emulate;
++
++ if (ti->pending_finish && ti->owner < 0)
++ EndTouchPoint(sourcedev, ti);
++ else if (ti->pending_finish)
++ {
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ if (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED)
++ EndTouchPoint(sourcedev, ti);
++ }
++ }
++
+ return Success;
+ }
+
+@@ -2174,7 +2294,7 @@
+
+ static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
+ {
+- WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
++ WindowPtr w = DeepestSpriteWin(pSprite);
+ Window child = None;
+
+ /* If the search ends up past the root should the child field be
+@@ -2232,7 +2352,8 @@
+ event->evtype == XI_RawMotion ||
+ event->evtype == XI_DeviceChanged ||
+ event->evtype == XI_HierarchyChanged ||
+- event->evtype == XI_PropertyEvent)
++ event->evtype == XI_PropertyEvent ||
++ event->evtype == XI_TouchOwnership)
+ return;
+
+ event->root = RootWindow(pSprite)->drawable.id;
+@@ -2369,12 +2490,119 @@
+ xEvent core;
+ xEvent *xE = NULL;
+ int rc, mask, count = 0;
++ InternalEvent touch_dummy;
++ Bool check_touch = FALSE;
+
+ CHECKEVENT(event);
+
++ /* If we are replaying a pointer emulated button press event, find the first
++ * pointer or touch selecting client. */
++ if (syncEvents.playingEvents && event->any.type == ET_ButtonPress &&
++ (event->device_event.flags & XIPointerEmulated) &&
++ event->device_event.touchpoint &&
++ event->device_event.touchpoint->active_clients > 0)
++ {
++ QdEventPtr qe;
++ DeviceEvent *te;
++ TouchPointInfoPtr ti;
++ TouchClientPtr tc = NULL;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if (qe->device == dev && qe->event->any.type == ET_TouchBegin)
++ break;
++ if (!qe)
++ {
++ LogMessage(X_ERROR, "no touch for emulated button press\n");
++ goto no_touch_event;
++ }
++
++ te = &qe->event->device_event;
++ ti = te->touchpoint;
++
++ if (ti->active_clients > 0)
++ {
++ tc = &ti->clients[ti->active_clients - 1];
++ te->deviceid = tc->device->id;
++ }
++
++ while (pWin)
++ {
++ Bool touch = FALSE;
++ Bool pointer = FALSE;
++
++ if (tc &&
++ EventIsDeliverable(tc->device, (InternalEvent *)te, pWin) &&
++ (tc->type == TOUCH_SELECT || tc->type == TOUCH_SELECT_UNOWNED))
++ {
++ ti->owner = ti->active_clients - 1;
++ if (tc->type == TOUCH_SELECT_UNOWNED)
++ DeliverTouchOwnershipEvent(tc, ti);
++ touch = TRUE;
++ }
++
++ if (EventIsDeliverable(dev, event, pWin))
++ pointer = TRUE;
++
++ if (touch && pointer)
++ break;
++ else if (touch || pointer)
++ {
++ /* Remove unselected events from queue. */
++ RemoveTouchEventsFromQueue(dev, pointer, FALSE);
++
++ if (touch)
++ {
++ /* If only touch events are selected, release mouse
++ * button. */
++ ReleaseButton(dev, 1);
++ ti->emulate_pointer = FALSE;
++ if (IsPointerEvent(event))
++ return 0;
++ } else {
++ ti->owner = -1;
++ ti->active_clients = 0;
++ if (IsTouchEvent(event))
++ return 0;
++ }
++
++ break;
++ }
++
++ pWin = pWin->parent;
++ }
++ }
++ else if (IsPointerEvent(event) && !syncEvents.playingEvents &&
++ (event->device_event.flags & XIPointerEmulated) &&
++ event->device_event.touchpoint &&
++ event->device_event.touchpoint->active_clients > 0)
++ {
++ /* Non-grabbed emulated pointer event, so check for touch selections. */
++ check_touch = TRUE;
++ touch_dummy.any.type = ET_TouchBegin;
++ }
++ else if (IsTouchEvent(event))
++ {
++ TouchPointInfoPtr ti = event->device_event.touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ pWin = tc->window;
++ }
++
++no_touch_event:
+ while (pWin)
+ {
+- if ((mask = EventIsDeliverable(dev, event, pWin)))
++ DeviceIntPtr check_dev = dev;
++
++ if (IsTouchEvent(event))
++ {
++ TouchPointInfoPtr ti = event->device_event.touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ event->device_event.deviceid = tc->device->id;
++ check_dev = tc->device;
++ }
++
++ if ((mask = EventIsDeliverable(check_dev, event, pWin)))
+ {
+ /* XI2 events first */
+ if (mask & XI2_MASK)
+@@ -2383,10 +2611,25 @@
+ rc = EventToXI2(event, &xi2);
+ if (rc == Success)
+ {
++ if (event->any.type == ET_TouchBegin ||
++ event->any.type == ET_TouchMotionUnowned)
++ {
++ OtherInputMasks *masks = wOtherInputMasks(pWin);
++
++ if (BitIsOn(masks->xi2mask[XIAllDevices],
++ XI_TouchOwnership) ||
++ BitIsOn(masks->xi2mask[check_dev->id],
++ XI_TouchOwnership) ||
++ (IsMaster(check_dev) &&
++ BitIsOn(masks->xi2mask[XIAllMasterDevices],
++ XI_TouchOwnership)))
++ goto unwind;
++ }
++
+ /* XXX: XACE */
+- filter = GetEventFilter(dev, xi2);
++ filter = GetEventFilter(check_dev, xi2);
+ FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE);
+- deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
++ deliveries = DeliverEventsToWindow(check_dev, pWin, xi2, 1,
+ filter, grab);
+ free(xi2);
+ if (deliveries > 0)
+@@ -2439,6 +2682,14 @@
+ goto unwind;
+ }
+ }
++ else if (check_touch && EventIsDeliverable(dev, &touch_dummy, pWin))
++ {
++ /* Only touch events wanted on this window. Skip this event and
++ * stop pointer emulation. Future touch events will be sent
++ * instead. */
++ event->device_event.touchpoint->emulate_pointer = FALSE;
++ goto unwind;
++ }
+
+ child = pWin->drawable.id;
+ pWin = pWin->parent;
+@@ -2591,7 +2842,7 @@
+ else
+ pWin = pWin->nextSib;
+ }
+- return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
++ return DeepestSpriteWin(pSprite);
+ }
+
+ /**
+@@ -2629,7 +2880,8 @@
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+- rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
++ rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
++ TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
+ return rc;
+@@ -2666,7 +2918,8 @@
+ event.deviceid = dev->id;
+ event.sourceid = dev->id;
+ event.detail.button = 0;
+- rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
++ rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
++ TRUE) != NULL);
+ if (rc)
+ DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
+ return rc;
+@@ -3353,7 +3606,7 @@
+ CheckPassiveGrabsOnWindow(
+ WindowPtr pWin,
+ DeviceIntPtr device,
+- DeviceEvent *event,
++ InternalEvent *event,
+ BOOL checkCore,
+ BOOL activate)
+ {
+@@ -3370,9 +3623,22 @@
+ return NULL;
+ /* Fill out the grab details, but leave the type for later before
+ * comparing */
++ switch (event->any.type)
++ {
++ case ET_KeyPress:
++ case ET_KeyRelease:
++ tempGrab.detail.exact = event->device_event.detail.key;
++ break;
++ case ET_ButtonPress:
++ case ET_ButtonRelease:
++ tempGrab.detail.exact = event->device_event.detail.button;
++ break;
++ default:
++ tempGrab.detail.exact = 0;
++ break;
++ }
+ tempGrab.window = pWin;
+ tempGrab.device = device;
+- tempGrab.detail.exact = event->detail.key;
+ tempGrab.detail.pMask = NULL;
+ tempGrab.modifiersDetail.pMask = NULL;
+ tempGrab.next = NULL;
+@@ -3380,6 +3646,9 @@
+ {
+ DeviceIntPtr gdev;
+ XkbSrvInfoPtr xkbi = NULL;
++ int rc, count = 0;
++ xEvent *xE = NULL;
++ xEvent core;
+
+ gdev= grab->modifierDevice;
+ if (grab->grabtype == GRABTYPE_CORE)
+@@ -3405,16 +3674,15 @@
+ tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
+
+ /* Check for XI2 and XI grabs first */
+- tempGrab.type = GetXI2Type((InternalEvent*)event);
++ tempGrab.type = GetXI2Type(event);
+ tempGrab.grabtype = GRABTYPE_XI2;
+ if (GrabMatchesSecond(&tempGrab, grab, FALSE))
+ match = XI2_MATCH;
+
+- tempGrab.detail.exact = event->detail.key;
+ if (!match)
+ {
+ tempGrab.grabtype = GRABTYPE_XI;
+- if ((tempGrab.type = GetXIType((InternalEvent*)event)) &&
++ if ((tempGrab.type = GetXIType(event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, FALSE)))
+ match = XI_MATCH;
+ }
+@@ -3423,125 +3691,143 @@
+ if (!match && checkCore)
+ {
+ tempGrab.grabtype = GRABTYPE_CORE;
+- if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
++ if ((tempGrab.type = GetCoreType(event)) &&
+ (GrabMatchesSecond(&tempGrab, grab, TRUE)))
+ match = CORE_MATCH;
+ }
+
+- if (match && (!grab->confineTo ||
+- (grab->confineTo->realized &&
+- BorderSizeNotEmpty(device, grab->confineTo))))
+- {
+- int rc, count = 0;
+- xEvent *xE = NULL;
+- xEvent core;
++ if (!match || (grab->confineTo &&
++ (!grab->confineTo->realized ||
++ !BorderSizeNotEmpty(device, grab->confineTo))))
++ continue;
+
+- event->corestate &= 0x1f00;
+- event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
+- grabinfo = &device->deviceGrab;
+- /* In some cases a passive core grab may exist, but the client
+- * already has a core grab on some other device. In this case we
+- * must not get the grab, otherwise we may never ungrab the
+- * device.
+- */
+-
+- if (grab->grabtype == GRABTYPE_CORE)
+- {
+- DeviceIntPtr other;
+- BOOL interfering = FALSE;
+-
+- /* A passive grab may have been created for a different device
+- than it is assigned to at this point in time.
+- Update the grab's device and modifier device to reflect the
+- current state.
+- Since XGrabDeviceButton requires to specify the
+- modifierDevice explicitly, we don't override this choice.
+- */
+- if (tempGrab.type < GenericEvent)
+- {
+- grab->device = device;
+- grab->modifierDevice = GetPairedDevice(device);
+- }
++ grabinfo = &device->deviceGrab;
++ /* In some cases a passive core grab may exist, but the client
++ * already has a core grab on some other device. In this case we
++ * must not get the grab, otherwise we may never ungrab the
++ * device.
++ */
++
++ if (grab->grabtype == GRABTYPE_CORE)
++ {
++ DeviceIntPtr other;
++ BOOL interfering = FALSE;
++
++ /* A passive grab may have been created for a different device
++ than it is assigned to at this point in time.
++ Update the grab's device and modifier device to reflect the
++ current state.
++ Since XGrabDeviceButton requires to specify the
++ modifierDevice explicitly, we don't override this choice.
++ */
++ if (tempGrab.type < GenericEvent)
++ {
++ grab->device = device;
++ grab->modifierDevice = GetPairedDevice(device);
++ }
+
+- for (other = inputInfo.devices; other; other = other->next)
++ for (other = inputInfo.devices; other; other = other->next)
++ {
++ GrabPtr othergrab = other->deviceGrab.grab;
++ if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
++ SameClient(grab, rClient(othergrab)) &&
++ ((IsPointerDevice(grab->device) &&
++ IsPointerDevice(othergrab->device)) ||
++ (IsKeyboardDevice(grab->device) &&
++ IsKeyboardDevice(othergrab->device))))
+ {
+- GrabPtr othergrab = other->deviceGrab.grab;
+- if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
+- SameClient(grab, rClient(othergrab)) &&
+- ((IsPointerDevice(grab->device) &&
+- IsPointerDevice(othergrab->device)) ||
+- (IsKeyboardDevice(grab->device) &&
+- IsKeyboardDevice(othergrab->device))))
+- {
+- interfering = TRUE;
+- break;
+- }
++ interfering = TRUE;
++ break;
+ }
+- if (interfering)
+- continue;
+ }
++ if (interfering)
++ continue;
++ }
+
+- if (!activate)
+- return grab;
++ if (!activate)
++ {
++ return grab;
++ }
++ else if (!GetXIType(event) && !GetCoreType(event))
++ {
++ ErrorF("Event type %d in CheckPassiveGrabsOnWindow is neither"
++ " XI 1.x nor core\n", event->any.type);
++ return NULL;
++ }
+
+- if (match & CORE_MATCH)
++ /* The only consumers of corestate are Xi 1.x and core events, which
++ * are guaranteed to come from DeviceEvents. */
++ if (match & (XI_MATCH | CORE_MATCH))
++ {
++ event->device_event.corestate &= 0x1f00;
++ event->device_event.corestate |= tempGrab.modifiersDetail.exact &
++ (~0x1f00);
++ }
++
++ if (match & CORE_MATCH)
++ {
++ rc = EventToCore(event, &core);
++ if (rc != Success)
+ {
+- rc = EventToCore((InternalEvent*)event, &core);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: core conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
+- xE = &core;
+- count = 1;
+- } else if (match & XI2_MATCH)
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: core conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
++ }
++ xE = &core;
++ count = 1;
++ } else if (match & XI2_MATCH)
++ {
++ rc = EventToXI2(event, &xE);
++ if (rc != Success)
+ {
+- rc = EventToXI2((InternalEvent*)event, &xE);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
+- count = 1;
+- } else
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
++ }
++ count = 1;
++ } else
++ {
++ rc = EventToXI(event, &xE, &count);
++ if (rc != Success)
+ {
+- rc = EventToXI((InternalEvent*)event, &xE, &count);
+- if (rc != Success)
+- {
+- if (rc != BadMatch)
+- ErrorF("[dix] %s: XI conversion failed in CPGFW "
+- "(%d, %d).\n", device->name, event->type, rc);
+- continue;
+- }
++ if (rc != BadMatch)
++ ErrorF("[dix] %s: XI conversion failed in CPGFW "
++ "(%d, %d).\n", device->name, event->any.type, rc);
++ continue;
+ }
++ }
+
+- (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
++ (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
+
+- if (xE)
+- {
+- FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
++ /* Don't send touch events if you activate a touch grab. Touch grabs
++ * are handled separately. */
++ if (xE && grab->type != ET_TouchBegin)
++ {
++ FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
+
+- TryClientEvents(rClient(grab), device, xE, count,
+- GetEventFilter(device, xE),
+- GetEventFilter(device, xE), grab);
+- }
++ TryClientEvents(rClient(grab), device, xE, count,
++ GetEventFilter(device, xE),
++ GetEventFilter(device, xE), grab);
++ }
+
+- if (grabinfo->sync.state == FROZEN_NO_EVENT)
+- {
++ if (grabinfo->sync.state == FROZEN_NO_EVENT)
++ {
++ /* Touch events are enqueued differently due to pointer
++ * emulation. */
++ if (grab->type != ET_TouchBegin)
++ {
+ if (!grabinfo->sync.event)
+- grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
+- *grabinfo->sync.event = *event;
+- grabinfo->sync.state = FROZEN_WITH_EVENT;
++ grabinfo->sync.event = calloc(1, sizeof(DeviceEvent));
++ *grabinfo->sync.event = event->device_event;
+ }
++ grabinfo->sync.state = FROZEN_WITH_EVENT;
++ }
+
+- if (match & (XI_MATCH | XI2_MATCH))
+- free(xE); /* on core match xE == &core */
+- return grab;
+- }
++ if (match & (XI_MATCH | XI2_MATCH))
++ free(xE); /* on core match xE == &core */
++ return grab;
+ }
+ return NULL;
+ #undef CORE_MATCH
+@@ -3580,8 +3866,13 @@
+ {
+ int i;
+ WindowPtr pWin = NULL;
+- FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
++ FocusClassPtr focus = device->focus;
+ BOOL sendCore = (IsMaster(device) && device->coreEvents);
++ DeviceEvent *touch_event = NULL;
++
++ if (IsPointerEvent((InternalEvent *)event) ||
++ IsTouchEvent((InternalEvent *)event))
++ focus = NULL;
+
+ if (event->type != ET_ButtonPress &&
+ event->type != ET_KeyPress)
+@@ -3609,7 +3900,8 @@
+ for (; i < focus->traceGood; i++)
+ {
+ pWin = focus->trace[i];
+- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
++ if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
++ sendCore, TRUE))
+ return TRUE;
+ }
+
+@@ -3619,11 +3911,54 @@
+ return FALSE;
+ }
+
++ if (syncEvents.pending && event->type == ET_ButtonPress &&
++ (event->flags & XIPointerEmulated))
++ {
++ QdEventPtr qe;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if (qe->device == device && qe->event->any.type == ET_TouchBegin)
++ break;
++ if (qe)
++ touch_event = &qe->event->device_event;
++ }
++
+ for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
+ {
+- pWin = device->spriteInfo->sprite->spriteTrace[i];
+- if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
+- return TRUE;
++ pWin = device->spriteInfo->sprite->spriteTrace[i];
++
++ if (!pWin->optional)
++ continue;
++
++ /* Touch grabs are checked before pointer grabs. When a touch grab
++ * should be checked first, check_grab is TRUE. */
++ if (touch_event && touch_event->check_grab)
++ {
++ GrabPtr grab;
++
++ grab = CheckPassiveGrabsOnWindow(pWin, device,
++ (InternalEvent *)touch_event,
++ FALSE, FALSE);
++ if (grab)
++ {
++ TouchPointInfoPtr ti = touch_event->touchpoint;
++ TouchClientPtr tc = &ti->clients[ti->owner];
++
++ device->deviceGrab.ActivateGrab(device, grab, currentTime,
++ TRUE);
++ touch_event->check_grab = FALSE;
++ DeliverTouchOwnershipEvent(tc, ti);
++ return TRUE;
++ }
++ }
++
++ if (touch_event)
++ touch_event->check_grab = TRUE;
++
++ if (pWin->optional &&
++ CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *)event,
++ sendCore, TRUE))
++ return TRUE;
+ }
+
+ return FALSE;
+@@ -3745,6 +4080,17 @@
+ grabinfo = &thisDev->deviceGrab;
+ grab = grabinfo->grab;
+
++ /* Touch grab deliver is handled in ProcessTouchEvent. */
++ if (event->any.type == ET_TouchBegin ||
++ event->any.type == ET_TouchMotionUnowned)
++ {
++ if (BitIsOn(grab->xi2mask[XIAllDevices], XI_TouchOwnership) ||
++ BitIsOn(grab->xi2mask[thisDev->id], XI_TouchOwnership) ||
++ (IsMaster(thisDev) &&
++ BitIsOn(grab->xi2mask[XIAllMasterDevices], XI_TouchOwnership)))
++ return;
++ }
++
+ if (grab->ownerEvents)
+ {
+ WindowPtr focus;
+@@ -3821,6 +4167,9 @@
+ mask = grab->xi2mask[XIAllDevices][evtype/8] |
+ grab->xi2mask[XIAllMasterDevices][evtype/8] |
+ grab->xi2mask[thisDev->id][evtype/8];
++ if (IsTouchEvent(event))
++ mask |=
++ grab->xi2mask[event->device_event.sourceid][evtype/8];
+ /* try XI2 event */
+ FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
+ /* XXX: XACE */
+@@ -4955,7 +5304,7 @@
+ free(syncEvents.pending);
+ syncEvents.pending = next;
+ }
+- syncEvents.pendtail = &syncEvents.pending;
++ syncEvents.pendtail = NULL;
+ syncEvents.playingEvents = FALSE;
+ syncEvents.time.months = 0;
+ syncEvents.time.milliseconds = 0; /* hardly matters */
+Index: b/dix/getevents.c
+===================================================================
+--- a/dix/getevents.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/getevents.c 2011-03-09 13:11:48.103384795 +1100
+@@ -47,6 +47,7 @@
+ #include "eventstr.h"
+ #include "eventconvert.h"
+ #include "inpututils.h"
++#include "windowstr.h"
+
+ #include <X11/extensions/XKBproto.h>
+ #include "xkbsrv.h"
+@@ -160,7 +161,7 @@
+ (1 << (key_code & 7)));
+ }
+
+-static void
++void
+ init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
+ {
+ memset(event, 0, sizeof(DeviceEvent));
+@@ -172,6 +173,18 @@
+ }
+
+ static void
++init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
++{
++ memset(event, 0, sizeof(TouchOwnershipEvent));
++ event->header = ET_Internal;
++ event->type = ET_TouchOwnership;
++ event->length = sizeof(TouchOwnershipEvent);
++ event->time = ms;
++ event->deviceid = dev->id;
++ event->sourceid = dev->id;
++}
++
++static void
+ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
+ {
+ memset(event, 0, sizeof(RawDeviceEvent));
+@@ -210,7 +223,8 @@
+ if (valuator_mask_isset(mask, i))
+ {
+ SetBit(event->valuators.mask, i);
+- if (valuator_get_mode(dev, i) == Absolute)
++ if (!IsTouchEvent((InternalEvent *)event) &&
++ valuator_get_mode(dev, i) == Absolute)
+ SetBit(event->valuators.mode, i);
+ event->valuators.data[i] = valuator_mask_get(mask, i);
+ event->valuators.data_frac[i] =
+@@ -1058,23 +1072,14 @@
+ }
+
+ static void
+-transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
++transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask, int *x, int *y)
+ {
+- struct pixman_f_vector p;
+-
+- /* p' = M * p in homogeneous coordinates */
+- p.v[0] = (valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
+- dev->last.valuators[0]);
+- p.v[1] = (valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
+- dev->last.valuators[1]);
+- p.v[2] = 1.0;
++ struct pixman_f_vector p = {.v = {*x, *y, 1}};
+
+ pixman_f_transform_point(&dev->transform, &p);
+
+- if (lround(p.v[0]) != dev->last.valuators[0])
+- valuator_mask_set(mask, 0, lround(p.v[0]));
+- if (lround(p.v[1]) != dev->last.valuators[1])
+- valuator_mask_set(mask, 1, lround(p.v[1]));
++ *x = lround(p.v[0]);
++ *y = lround(p.v[1]);
+ }
+
+ /**
+@@ -1116,7 +1121,10 @@
+ switch (type)
+ {
+ case MotionNotify:
+- if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
++ if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0 ||
++ (pDev->touch && pDev->touch->active_touches > 1 &&
++ (pDev->touch->mode == XIDependentTouch ||
++ pDev->touch->mode == XISemiMultitouch)))
+ return 0;
+ break;
+ case ButtonPress:
+@@ -1165,7 +1173,16 @@
+ }
+ }
+
+- transformAbsolute(pDev, &mask);
++ x = (valuator_mask_isset(&mask, 0) ? valuator_mask_get(&mask, 0) :
++ pDev->last.valuators[0]);
++ y = (valuator_mask_isset(&mask, 1) ? valuator_mask_get(&mask, 1) :
++ pDev->last.valuators[1]);
++ transformAbsolute(pDev, &mask, &x, &y);
++ if (valuator_mask_isset(&mask, 0))
++ valuator_mask_set(&mask, 0, x);
++ if (valuator_mask_isset(&mask, 1))
++ valuator_mask_set(&mask, 1, y);
++
+ moveAbsolute(pDev, &x, &y, &mask);
+ } else {
+ if (flags & POINTER_ACCELERATE) {
+@@ -1286,6 +1303,130 @@
+ return num_events;
+ }
+
++int
++GetTouchOwnershipEvents(EventList *events, DeviceIntPtr pDev,
++ TouchPointInfoPtr ti, uint8_t reason, XID resource,
++ uint32_t flags)
++{
++ TouchClassPtr t = pDev->touch;
++ TouchOwnershipEvent *event;
++ CARD32 ms = GetTimeInMillis();
++
++ if (!pDev->enabled || !t || !ti)
++ return 0;
++
++ if (reason != XITouchOwnerAccept && reason != XITouchOwnerRejectEnd)
++ return 0;
++
++ event = (TouchOwnershipEvent *) events->event;
++ init_touch_ownership(pDev, event, ms);
++
++ event->touchid = ti->client_id;
++ event->resource = resource;
++ event->flags = flags;
++
++ return 1;
++}
++
++/**
++ * Get events for a touch. Generates a TouchBegin event if end is not set and
++ * the touch id is not active. Generates a TouchMotion event if end is not set
++ * and the touch id is active. Generates a TouchEnd event if end is set and the
++ * touch id is active.
++ *
++ * events is not NULL-terminated; the return value is the number of events.
++ * The DDX is responsible for allocating the event structure in the first
++ * place via GetMaximumEventsNum(), and for freeing it.
++ */
++int
++GetTouchEvents(EventList *events, DeviceIntPtr pDev, TouchPointInfoPtr ti,
++ uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
++{
++ ScreenPtr scr = pDev->spriteInfo->sprite->hotPhys.pScreen;
++ TouchClassPtr t = pDev->touch;
++ DeviceEvent *event;
++ CARD32 ms = GetTimeInMillis();
++ ValuatorMask mask;
++ int x, y; /* in screen co-ord space */
++ float x_frac = 0.0, y_frac = 0.0; /* as above */
++ int i;
++
++ if (!pDev->enabled || !t || t->x_axis == -1 || t->y_axis == -1)
++ return 0;
++
++ event = (DeviceEvent *) events->event;
++ init_event(pDev, event, ms);
++
++ switch (type) {
++ case XI_TouchBegin:
++ event->type = ET_TouchBegin;
++ /* If we're starting a touch, we must have x & y co-ordinates. */
++ if (!valuator_mask_isset(mask_in, t->x_axis) ||
++ !valuator_mask_isset(mask_in, t->y_axis))
++ {
++ DebugF("%s: Attempted to start touch without x/y (driver bug)\n",
++ pDev->name);
++ return 0;
++ }
++ break;
++ case XI_TouchUpdate:
++ event->type = ET_TouchMotion;
++ break;
++ case XI_TouchEnd:
++ event->type = ET_TouchEnd;
++ break;
++ default:
++ return 0;
++ }
++
++ event->touchpoint = ti;
++
++ valuator_mask_copy(&mask, mask_in);
++
++ /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y):
++ * these come from the touchpoint in Absolute mode, or the sprite in
++ * Relative. */
++ if (t->mode == XIDirectTouch) {
++ if (valuator_mask_isset(&mask, t->x_axis))
++ x = valuator_mask_get(&mask, t->x_axis);
++ else
++ x = ti->valuators[t->x_axis];
++ x = rescaleValuatorAxis(x, 0.0, &x_frac,
++ (AxisInfoPtr)(t->axes + t->x_axis),
++ NULL, scr->width);
++
++ if (valuator_mask_isset(&mask, t->y_axis))
++ y = valuator_mask_get(&mask, t->y_axis);
++ else
++ y = ti->valuators[t->y_axis];
++ y = rescaleValuatorAxis(y, 0.0, &y_frac,
++ (AxisInfoPtr)(t->axes + t->y_axis),
++ NULL, scr->height);
++
++ transformAbsolute(pDev, &mask, &x, &y);
++ }
++ else {
++ x = pDev->spriteInfo->sprite->hotPhys.x;
++ y = pDev->spriteInfo->sprite->hotPhys.y;
++ }
++
++ event->root_x = x;
++ event->root_y = y;
++ event->root_x_frac = x_frac;
++ event->root_y_frac = y_frac;
++ event->detail.touch = ti->client_id;
++ event->flags = flags;
++
++ set_valuators(pDev, event, &mask);
++ for (i = 0; i < t->num_axes; i++)
++ {
++ if (valuator_mask_isset(&mask, i))
++ ti->valuators[i] = valuator_mask_get(&mask, i);
++ }
++
++ return 1;
++}
++
+ /**
+ * Synthesize a single motion event for the core pointer.
+ *
+Index: b/dix/grabs.c
+===================================================================
+--- a/dix/grabs.c 2011-02-28 13:56:41.000000000 +1100
++++ b/dix/grabs.c 2011-03-09 13:11:48.103384795 +1100
+@@ -60,6 +60,7 @@
+ #include "dixgrabs.h"
+ #include "xace.h"
+ #include "exevents.h"
++#include "mi.h"
+
+ #define BITMASK(i) (((Mask)1) << ((i) & 31))
+ #define MASKIDX(i) ((i) >> 5)
+@@ -243,6 +244,25 @@
+ }
+
+ /**
++ * Returns the event type to match when comparing grabs.
++ */
++static uint32_t
++GetGrabEventMatch(GrabPtr pGrab)
++{
++ if (pGrab->grabtype != GRABTYPE_XI2)
++ return pGrab->type;
++
++ if (pGrab->type == XI_TouchBegin ||
++ pGrab->type == XI_TouchUpdate ||
++ pGrab->type == XI_TouchUpdateUnowned ||
++ pGrab->type == XI_TouchOwnership ||
++ pGrab->type == XI_TouchEnd)
++ return XI_TouchBegin;
++
++ return pGrab->type;
++}
++
++/**
+ * Compares two grabs and returns TRUE if the first grab matches the second
+ * grab.
+ *
+@@ -261,6 +281,8 @@
+ unsigned int any_modifier = (pFirstGrab->grabtype == GRABTYPE_XI2) ?
+ (unsigned int)XIAnyModifier :
+ (unsigned int)AnyModifier;
++ uint32_t first_type = GetGrabEventMatch(pFirstGrab);
++ uint32_t second_type = GetGrabEventMatch(pSecondGrab);
+
+ if (pFirstGrab->grabtype != pSecondGrab->grabtype)
+ return FALSE;
+@@ -288,8 +310,8 @@
+ (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice)))
+ return FALSE;
+
+- if (pFirstGrab->type != pSecondGrab->type)
+- return FALSE;
++ if (first_type != second_type)
++ return FALSE;
+
+ if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
+ GrabSupersedesSecond(pSecondGrab, pFirstGrab))
+Index: b/dix/inpututils.c
+===================================================================
+--- a/dix/inpututils.c 2011-03-09 11:19:13.000000000 +1100
++++ b/dix/inpututils.c 2011-03-09 13:11:48.113385173 +1100
+@@ -36,6 +36,7 @@
+ #include "xkbsrv.h"
+ #include "xkbstr.h"
+ #include "inpututils.h"
++#include "eventstr.h"
+
+ /* Check if a button map change is okay with the device.
+ * Returns -1 for BadValue, as it collides with MappingBusy. */
+@@ -556,3 +557,158 @@
+
+ return ret;
+ }
++
++/**
++ * Given the DDX-facing ID (which is _not_ DeviceEvent::detail.touch), find the
++ * associated TouchPointInfoRec.
++ */
++TouchPointInfoPtr
++FindTouchPointByDDXID(DeviceIntPtr dev, uint32_t ddx_id)
++{
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++ int i;
++
++ if (!t)
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (ti->active && ti->ddx_id == ddx_id && !ti->ddx_pending_finish)
++ return ti;
++ }
++
++ return NULL;
++}
++
++/**
++ * Given a client-facing ID (e.g. DeviceEvent::detail.touch), find the
++ * associated TouchPointInfoRec.
++ */
++TouchPointInfoPtr
++FindTouchPointByClientID(DeviceIntPtr dev, uint32_t client_id)
++{
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++ int i;
++
++ if (!t)
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (ti->active && ti->client_id == client_id)
++ return ti;
++ }
++
++ return NULL;
++}
++
++/**
++ * Given a unique DDX ID for a touchpoint, create a touchpoint record in the
++ * server and return the client-facing ID.
++ *
++ * Returns 0 on failure (i.e. if another touch with that ID is already active,
++ * allocation failure).
++ */
++_X_EXPORT TouchPointInfoPtr
++BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id)
++{
++ int i;
++ TouchClassPtr t = dev->touch;
++ TouchPointInfoPtr ti;
++
++ if (!t)
++ return NULL;
++
++ /* Look for another active touchpoint with the same DDX ID. It's entirely
++ * legitimate for a touchpoint to still exist with the same DDX ID but
++ * be in the pending_finish state as it waits for a client to release its
++ * grab, so allow for that. */
++ if (FindTouchPointByDDXID(dev, ddx_id))
++ return NULL;
++
++ for (i = 0; i < t->num_touches; i++)
++ {
++ ti = &t->touches[i];
++ if (!ti->active) {
++ ti->source = dev;
++ ti->active = TRUE;
++ ti->ddx_id = ddx_id;
++ ti->client_id = t->next_client_id;
++ ti->owner = -1;
++ ti->active_clients = 0;
++ ti->accepted = FALSE;
++ ti->pending_finish = FALSE;
++ t->active_touches++;
++next_touch_id:
++ t->next_client_id++;
++ if (t->next_client_id == 0)
++ t->next_client_id = 1;
++ if (FindTouchPointByClientID(dev, t->next_client_id))
++ goto next_touch_id; /* n'th time's a charm */
++ return ti;
++ }
++ }
++
++ /* If we get here, then we've run out of touches. */
++ LogMessage(X_WARNING, "%s: no more touches available\n", dev->name);
++
++ return NULL;
++}
++
++/**
++ * Releases a touchpoint for use: this must only be called after all events
++ * related to that touchpoint have been sent and finalised. Called from
++ * ProcessTouchEvent and friends. Not by you.
++ */
++void
++EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti)
++{
++ int i;
++ TouchClassPtr t = dev->touch;
++ DeviceIntPtr masterdev = dev->u.master;
++ QdEventPtr qe;
++
++ if (dev->deviceGrab.sync.event &&
++ dev->deviceGrab.sync.event->touchpoint == ti)
++ dev->deviceGrab.sync.event->touchpoint = NULL;
++
++ if (masterdev && masterdev->deviceGrab.sync.event &&
++ masterdev->deviceGrab.sync.event->touchpoint == ti)
++ masterdev->deviceGrab.sync.event->touchpoint = NULL;
++
++ ti->source = NULL;
++ ti->pending_finish = FALSE;
++ ti->sprite.spriteTraceGood = 0;
++ ti->ddx_id = 0;
++ ti->first_history = ti->history;
++ ti->next_history = ti->history;
++ ti->emulate_pointer = FALSE;
++ ti->owner = -1;
++ ti->accepted = FALSE;
++ ti->active_clients = 0;
++ ti->ddx_pending_finish = FALSE;
++ t->active_touches--;
++
++ if (dev->touch->emulate == ti)
++ {
++ dev->touch->emulate = NULL;
++ if (dev->u.master)
++ dev->u.master->emulate_dev = NULL;
++
++ for (qe = syncEvents.pending; qe; qe = qe->next)
++ if ((qe->event->any.type == ET_TouchEnd ||
++ qe->event->any.type == ET_ButtonRelease) &&
++ qe->event->device_event.touchpoint == ti)
++ qe->event->device_event.touchpoint = NULL;
++ }
++
++ for (i = 0; i < ti->num_valuators; i++)
++ ti->valuators[i] = 0;
++
++ ti->client_id = 0;
++ ti->active = FALSE;
++}
+Index: b/dix/window.c
+===================================================================
+--- a/dix/window.c 2011-02-28 13:56:41.000000000 +1100
++++ b/dix/window.c 2011-03-09 13:11:48.113385173 +1100
+@@ -110,6 +110,7 @@
+ #include "windowstr.h"
+ #include "input.h"
+ #include "inputstr.h"
++#include "exevents.h"
+ #include "resource.h"
+ #include "colormapst.h"
+ #include "cursorstr.h"
+@@ -2873,8 +2874,10 @@
+ if (!fromConfigure && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pWin, VTUnmap);
+ }
+- if (wasRealized && !fromConfigure)
++ if (wasRealized && !fromConfigure) {
+ WindowsRestructured ();
++ WindowGone(pWin);
++ }
+ return Success;
+ }
+
+@@ -2957,8 +2960,10 @@
+ if (anyMarked && pScreen->PostValidateTree)
+ (*pScreen->PostValidateTree)(pLayerWin->parent, pHead, VTUnmap);
+ }
+- if (wasRealized)
++ if (wasRealized) {
+ WindowsRestructured ();
++ WindowGone(pWin);
++ }
+ }
+
+
+Index: b/hw/xfree86/common/xf86Module.h
+===================================================================
+--- a/hw/xfree86/common/xf86Module.h 2011-03-09 11:39:57.000000000 +1100
++++ b/hw/xfree86/common/xf86Module.h 2011-03-09 13:13:06.226385017 +1100
+@@ -83,7 +83,7 @@
+ */
+ #define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
+ #define ABI_VIDEODRV_VERSION SET_ABI_VERSION(10, 0)
+-#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 2)
++#define ABI_XINPUT_VERSION SET_ABI_VERSION(12, 3)
+ #define ABI_EXTENSION_VERSION SET_ABI_VERSION(5, 0)
+ #define ABI_FONT_VERSION SET_ABI_VERSION(0, 6)
+
+Index: b/hw/xfree86/common/xf86Xinput.c
+===================================================================
+--- a/hw/xfree86/common/xf86Xinput.c 2011-02-28 16:57:00.000000000 +1100
++++ b/hw/xfree86/common/xf86Xinput.c 2011-03-09 13:11:48.113385173 +1100
+@@ -1352,6 +1352,16 @@
+ max_res, mode);
+ }
+
++void
++xf86InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label,
++ int minval, int maxval, int resolution)
++{
++ if (!dev || !dev->touch)
++ return;
++
++ InitTouchValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution);
++}
++
+ /*
+ * Set the valuator values to be in synch with dix/event.c
+ * DefineInitialRootWindow().
+@@ -1403,4 +1413,50 @@
+ EnableDevice(dev, TRUE);
+ }
+
++/**
++ * Post a touch event with optional valuators. If this is the first touch in
++ * the sequence, at least x & y valuators must be provided. If end is TRUE,
++ * then this is taken to be the last touch in the touch sequence.
++ */
++void
++xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
++ uint32_t flags, const ValuatorMask *mask)
++{
++ int i, nevents;
++ TouchPointInfoPtr ti = FindTouchPointByDDXID(dev, touchid);
++
++ if (ti && type == XI_TouchBegin)
++ {
++ xf86Msg(X_ERROR,
++ "%s: Tried to post touch begin for existing touch %u\n",
++ dev->name, touchid);
++ return;
++ }
++
++ if (!ti)
++ {
++ if (type != XI_TouchBegin)
++ {
++ xf86Msg(X_ERROR,
++ "%s: Tried to post event for non-existent touch %u\n",
++ dev->name, touchid);
++ return;
++ }
++
++ ti = BeginTouchPoint(dev, touchid);
++ if (!ti)
++ {
++ xf86Msg(X_ERROR, "%s: Couldn't create touchpoint\n", dev->name);
++ return;
++ }
++ }
++
++ if (type == XI_TouchEnd)
++ ti->ddx_pending_finish = TRUE;
++
++ nevents = GetTouchEvents(xf86Events, dev, ti, type, flags, mask);
++ for (i = 0; i < nevents; i++)
++ mieqEnqueue(dev, (InternalEvent *)((xf86Events + i)->event));
++}
++
+ /* end of xf86Xinput.c */
+Index: b/hw/xfree86/common/xf86Xinput.h
+===================================================================
+--- a/hw/xfree86/common/xf86Xinput.h 2011-02-28 13:56:40.000000000 +1100
++++ b/hw/xfree86/common/xf86Xinput.h 2011-03-09 13:11:48.113385173 +1100
+@@ -141,6 +141,9 @@
+ const int *valuators);
+ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code,
+ int is_down);
++extern _X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid,
++ uint16_t type, uint32_t flags,
++ const ValuatorMask *mask);
+ extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
+ extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min);
+ extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number, int x, int y);
+@@ -148,6 +151,8 @@
+ extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
+ int maxval, int resolution, int min_res,
+ int max_res, int mode);
++extern _X_EXPORT void xf86InitTouchValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label,
++ int minval, int maxval, int resolution);
+ extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum);
+ extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
+ extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);
+Index: b/include/dix.h
+===================================================================
+--- a/include/dix.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/dix.h 2011-03-09 13:11:48.113385173 +1100
+@@ -375,7 +375,7 @@
+ extern GrabPtr CheckPassiveGrabsOnWindow(
+ WindowPtr /* pWin */,
+ DeviceIntPtr /* device */,
+- DeviceEvent * /* event */,
++ InternalEvent * /* event */,
+ BOOL /* checkCore */,
+ BOOL /* activate */);
+
+@@ -515,6 +515,11 @@
+ DeviceIntPtr /* dev */,
+ xEvent* /* events */);
+
++extern void RemoveTouchEventsFromQueue(
++ DeviceIntPtr /* dev */,
++ Bool /*touch*/,
++ Bool /*ignoreOwned*/);
++
+ #ifdef PANORAMIX
+ extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
+ #endif
+@@ -526,6 +531,8 @@
+
+ extern _X_EXPORT int ffs(int i);
+
++extern void init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms);
++
+
+ /*
+ * ServerGrabCallback stuff
+@@ -569,6 +576,7 @@
+ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+ extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+ extern Bool IsPointerEvent(InternalEvent *event);
++extern Bool IsTouchEvent(InternalEvent *event);
+ extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
+
+ extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+Index: b/include/events.h
+===================================================================
+--- a/include/events.h 2011-02-28 13:56:40.000000000 +1100
++++ b/include/events.h 2011-03-09 13:11:48.113385173 +1100
+@@ -26,6 +26,7 @@
+ #define EVENTS_H
+ typedef struct _DeviceEvent DeviceEvent;
+ typedef struct _DeviceChangedEvent DeviceChangedEvent;
++typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
+ #if XFreeXDGA
+ typedef struct _DGAEvent DGAEvent;
+ #endif
+Index: b/include/eventstr.h
+===================================================================
+--- a/include/eventstr.h 2011-02-28 16:57:00.000000000 +1100
++++ b/include/eventstr.h 2011-03-09 13:11:48.113385173 +1100
+@@ -65,6 +65,11 @@
+ ET_RawButtonRelease,
+ ET_RawMotion,
+ ET_XQuartz,
++ ET_TouchBegin,
++ ET_TouchEnd,
++ ET_TouchMotion,
++ ET_TouchMotionUnowned,
++ ET_TouchOwnership,
+ ET_Internal = 0xFF /* First byte */
+ };
+
+@@ -90,6 +95,7 @@
+ union {
+ uint32_t button; /**< Button number */
+ uint32_t key; /**< Key code */
++ uint32_t touch; /**< Touch ID (client_id) */
+ } detail;
+ int16_t root_x; /**< Pos relative to root window in integral data */
+ float root_x_frac; /**< Pos relative to root window in frac part */
+@@ -117,8 +123,28 @@
+ 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 */
++ TouchPointInfoPtr touchpoint;
++ Bool check_grab;
+ };
+
++/**
++ * Generated internally whenever a touch ownership chain changes - an owner
++ * has accepted or rejected a touch, or a grab/event selection in the delivery
++ * chain has been removed.
++ */
++struct _TouchOwnershipEvent
++{
++ 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 */
++ uint32_t touchid; /**< Touch ID (client_id) */
++ uint32_t resource; /**< Provoking grab or event selection */
++ uint32_t flags; /**< Flags to be copied into the generated event */
++};
+
+ /* Flags used in DeviceChangedEvent to signal if the slave has changed */
+ #define DEVCHANGE_SLAVE_SWITCH 0x2
+@@ -234,6 +260,7 @@
+ } any;
+ DeviceEvent device_event;
+ DeviceChangedEvent changed_event;
++ TouchOwnershipEvent touch_ownership_event;
+ #if XFreeXDGA
+ DGAEvent dga_event;
+ #endif
+Index: b/include/exevents.h
+===================================================================
+--- a/include/exevents.h 2011-03-04 14:03:20.000000000 +1100
++++ b/include/exevents.h 2011-03-09 13:11:48.113385173 +1100
+@@ -51,6 +51,14 @@
+ int /* max_res */,
+ int /* mode */);
+
++extern _X_EXPORT void InitTouchValuatorAxisStruct(
++ DeviceIntPtr /* dev */,
++ int /* axnum */,
++ Atom /* label */,
++ int /* minval */,
++ int /* maxval */,
++ int /* resolution */);
++
+ /* Input device properties */
+ extern _X_EXPORT void XIDeleteAllDeviceProperties(
+ DeviceIntPtr /* device */
+@@ -199,6 +207,14 @@
+ GrabMask* /* eventMask */);
+
+ extern int
++GrabTouch(
++ ClientPtr /* client */,
++ DeviceIntPtr /* dev */,
++ DeviceIntPtr /* mod_dev */,
++ GrabParameters* /* param */,
++ GrabMask* /* eventMask */);
++
++extern int
+ SelectForWindow(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* pWin */,
+@@ -222,6 +238,10 @@
+ WindowPtr /* pWin */,
+ XID /* id */);
+
++extern void
++WindowGone(
++ WindowPtr /* win */);
++
+ extern int
+ SendEvent (
+ ClientPtr /* client */,
+@@ -309,4 +329,14 @@
+ extern int
+ XICheckInvalidMaskBits(ClientPtr client, unsigned char *mask, int len);
+
++extern void
++ProcessTouchOwnership(DeviceIntPtr dev, TouchPointInfoPtr ti, uint8_t reason,
++ Bool touch_grab);
++
++extern int
++DeliverTouchOwnershipEvent(TouchClientPtr client, TouchPointInfoPtr ti);
++
++extern int
++ReleaseButton(DeviceIntPtr device, int button);
++
+ #endif /* EXEVENTS_H */
+Index: b/include/input.h
+===================================================================
+--- a/include/input.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/input.h 2011-03-09 13:11:48.113385173 +1100
+@@ -104,6 +104,8 @@
+ typedef struct _DeviceIntRec *DeviceIntPtr;
+ typedef struct _ClassesRec *ClassesPtr;
+ typedef struct _SpriteRec *SpritePtr;
++typedef struct _TouchClassRec *TouchClassPtr;
++typedef struct _TouchPointInfo *TouchPointInfoPtr;
+ typedef union _GrabMask GrabMask;
+
+ typedef struct _EventList {
+@@ -314,6 +316,12 @@
+ extern _X_EXPORT Bool InitFocusClassDeviceStruct(
+ DeviceIntPtr /*device*/);
+
++extern _X_EXPORT Bool InitTouchClassDeviceStruct(
++ DeviceIntPtr /*device*/,
++ unsigned int /*max_touches*/,
++ unsigned int /*mode*/,
++ unsigned int /*numAxes*/);
++
+ typedef void (*BellProcPtr)(
+ int /*percent*/,
+ DeviceIntPtr /*device*/,
+@@ -463,6 +471,22 @@
+ int key_code,
+ const ValuatorMask *mask);
+
++extern int GetTouchEvents(
++ EventListPtr events,
++ DeviceIntPtr pDev,
++ TouchPointInfoPtr ti,
++ uint16_t type,
++ uint32_t flags,
++ const ValuatorMask *mask);
++
++extern int GetTouchOwnershipEvents(
++ EventListPtr events,
++ DeviceIntPtr pDev,
++ TouchPointInfoPtr ti,
++ uint8_t mode,
++ XID resource,
++ uint32_t flags);
++
+ extern int GetProximityEvents(
+ EventListPtr events,
+ DeviceIntPtr pDev,
+@@ -525,6 +549,18 @@
+ extern _X_EXPORT InputAttributes *DuplicateInputAttributes(InputAttributes *attrs);
+ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs);
+
++/* DDX touch API: create with CreateTouchPoint, use its returned ID to lookup
++ * with FindTouchPoint, and eventually end with FinishTouchPoint. */
++extern TouchPointInfoPtr BeginTouchPoint(DeviceIntPtr dev, uint32_t ddx_id);
++extern TouchPointInfoPtr FindTouchPointByDDXID(DeviceIntPtr dev,
++ uint32_t ddx_id);
++extern TouchPointInfoPtr FindTouchPointByClientID(DeviceIntPtr dev,
++ uint32_t client_id);
++extern void EndTouchPoint(DeviceIntPtr dev, TouchPointInfoPtr ti);
++/* Internal use only, DDX this is not for you */
++extern Bool InitTouchPoint(TouchClassPtr touch, int index);
++extern void FreeTouchPoint(DeviceIntPtr dev, int index);
++
+ /* misc event helpers */
+ extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
+ extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);
+Index: b/include/inputstr.h
+===================================================================
+--- a/include/inputstr.h 2011-03-09 11:19:13.000000000 +1100
++++ b/include/inputstr.h 2011-03-09 13:11:48.113385173 +1100
+@@ -49,6 +49,8 @@
+ #ifndef INPUTSTRUCT_H
+ #define INPUTSTRUCT_H
+
++#include <X11/extensions/XI2proto.h>
++
+ #include <pixman.h>
+ #include "input.h"
+ #include "window.h"
+@@ -71,7 +73,7 @@
+ * events to the protocol, the server will not support these events until
+ * this number here is bumped.
+ */
+-#define XI2LASTEVENT 17 /* XI_RawMotion */
++#define XI2LASTEVENT XI_TouchUpdateUnowned
+ #define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */
+
+ /**
+@@ -244,6 +246,9 @@
+
+ } SpriteRec;
+
++#define DeepestSpriteWin(sprite) \
++ ((sprite)->spriteTrace[(sprite)->spriteTraceGood - 1])
++
+ typedef struct _KeyClassRec {
+ int sourceid;
+ CARD8 down[DOWN_LENGTH];
+@@ -254,11 +259,11 @@
+
+ typedef struct _AxisInfo {
+ int resolution;
+- int min_resolution;
+- int max_resolution;
+ int min_value;
+ int max_value;
+ Atom label;
++ int min_resolution;
++ int max_resolution;
+ CARD8 mode;
+ } AxisInfo, *AxisInfoPtr;
+
+@@ -284,6 +289,75 @@
+ ValuatorAccelerationRec accelScheme;
+ } ValuatorClassRec, *ValuatorClassPtr;
+
++typedef enum {
++ TOUCH_GRAB,
++ TOUCH_SELECT,
++ TOUCH_SELECT_UNOWNED
++} TouchClientType;
++
++typedef struct _TouchClientRec {
++ ClientPtr client;
++ WindowPtr window;
++ TouchClientType type;
++ DeviceIntPtr device;
++ DeviceIntPtr source;
++ GrabPtr grab;
++} TouchClientRec, *TouchClientPtr;
++
++typedef struct _TouchPointInfo {
++ DeviceIntPtr source;
++ Bool active; /* whether or not the touch is active */
++ Bool pending_finish; /* true if the touch is physically inactive
++ * but still owned by a grab */
++ Bool ddx_pending_finish;
++ uint32_t client_id; /* touch ID as seen in client events */
++ uint32_t ddx_id; /* touch ID given by the DDX */
++ SpriteRec sprite; /* window trace for delivery */
++ TouchClientPtr clients;
++ int num_clients;
++ int active_clients;
++ int owner;
++ Bool accepted;
++ int *valuators; /* last recorded axis values */
++ int num_valuators; /* == TouchClassInfo::num_axes */
++#if 0
++ XID *listeners; /* grabs/event selection IDs receiving
++ * events for this touch */
++ int num_listeners;
++ int num_grabs; /* number of open grabs on this touch
++ * which have not accepted or rejected */
++ WindowPtr select_win;
++ Bool select_unowned;
++#endif
++ Bool emulate_pointer;
++ InternalEvent *begin_event; /* Touch begin event for history */
++ InternalEvent *history; /* Touch motion and end history events */
++ unsigned int history_size; /* Size of history ring buffer */
++ InternalEvent *first_history; /* Pointer to first event in history */
++ InternalEvent *next_history; /* Pointer to next available event */
++} TouchPointInfoRec;
++
++typedef struct _TouchAxisInfo {
++ int resolution;
++ int min_value;
++ int max_value;
++ Atom label;
++} TouchAxisInfoRec, *TouchAxisInfoPtr;
++
++typedef struct _TouchClassRec {
++ TouchAxisInfoPtr axes;
++ unsigned short num_axes;
++ TouchPointInfoPtr touches;
++ unsigned short num_touches; /* number of allocated touches */
++ unsigned short max_touches; /* maximum number of touches, may be 0 */
++ unsigned short active_touches; /* number of active touches */
++ CARD8 mode; /* ::XIDirectTouch, XIDependentTouch */
++ uint32_t next_client_id; /* next client_id to give out */
++ int x_axis; /* axis number of x axis */
++ int y_axis; /* axis number of y axis */
++ TouchPointInfoPtr emulate;
++} TouchClassRec;
++
+ typedef struct _ButtonClassRec {
+ int sourceid;
+ CARD8 numButtons;
+@@ -388,6 +462,7 @@
+ typedef struct _ClassesRec {
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
++ TouchClassPtr touch;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+@@ -512,6 +587,7 @@
+ int id;
+ KeyClassPtr key;
+ ValuatorClassPtr valuator;
++ TouchClassPtr touch;
+ ButtonClassPtr button;
+ FocusClassPtr focus;
+ ProximityClassPtr proximity;
+@@ -533,6 +609,8 @@
+ DeviceIntPtr master; /* master device */
+ DeviceIntPtr lastSlave; /* last slave device used */
+ } u;
++ DeviceIntPtr emulate_dev;
++ Bool process_touch;
+
+ /* last valuator values recorded, not posted to client;
+ * for slave devices, valuators is in device coordinates
+@@ -592,7 +670,7 @@
+ */
+ typedef struct _EventSyncInfo {
+ QdEventPtr pending, /**< list of queued events */
+- *pendtail; /**< last event in list */
++ pendtail; /**< last event in list */
+ /** The device to replay events for. Only set in AllowEvents(), in which
+ * case it is set to the device specified in the request. */
+ DeviceIntPtr replayDev; /* kludgy rock to put flag for */
+Index: b/include/protocol-versions.h
+===================================================================
+--- a/include/protocol-versions.h 2011-03-09 11:39:57.000000000 +1100
++++ b/include/protocol-versions.h 2011-03-09 13:11:48.113385173 +1100
+@@ -131,7 +131,7 @@
+
+ /* X Input */
+ #define SERVER_XI_MAJOR_VERSION 2
+-#define SERVER_XI_MINOR_VERSION 0
++#define SERVER_XI_MINOR_VERSION 1
+
+ /* XKB */
+ #define SERVER_XKB_MAJOR_VERSION 1
+Index: b/mi/mieq.c
+===================================================================
+--- a/mi/mieq.c 2011-03-09 11:19:13.000000000 +1100
++++ b/mi/mieq.c 2011-03-09 13:11:48.113385173 +1100
+@@ -269,8 +269,15 @@
+ case ET_ProximityOut:
+ case ET_Hierarchy:
+ case ET_DeviceChanged:
++ case ET_TouchBegin:
++ case ET_TouchEnd:
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
+ event->device_event.deviceid = dev->id;
+ break;
++ case ET_TouchOwnership:
++ event->touch_ownership_event.deviceid = dev->id;
++ break;
+ #if XFreeXDGA
+ case ET_DGAEvent:
+ break;
+@@ -419,7 +426,7 @@
+
+ /* Check for the SD's master in case the device got detached
+ * during event processing */
+- if (master && dev->u.master)
++ if (master && dev->u.master && !IsTouchEvent(&mevent))
+ master->public.processInputProc(&mevent, master);
+ }
+ }
+Index: b/test/input.c
+===================================================================
+--- a/test/input.c 2011-03-09 11:39:57.000000000 +1100
++++ b/test/input.c 2011-03-09 13:12:49.355737608 +1100
+@@ -278,6 +278,11 @@
+ dix_event_to_core_fail(ET_ProximityOut + 1, BadImplementation);
+ dix_event_to_core_fail(ET_ProximityIn, BadMatch);
+ dix_event_to_core_fail(ET_ProximityOut, BadMatch);
++ dix_event_to_core_fail(ET_TouchBegin, BadMatch);
++ dix_event_to_core_fail(ET_TouchMotion, BadMatch);
++ dix_event_to_core_fail(ET_TouchMotionUnowned, BadMatch);
++ dix_event_to_core_fail(ET_TouchOwnership, BadMatch);
++ dix_event_to_core_fail(ET_TouchEnd, BadMatch);
+
+ dix_event_to_core(ET_KeyPress);
+ dix_event_to_core(ET_KeyRelease);
+@@ -423,6 +428,32 @@
+ }
+
+
++static void dix_event_to_xi2_conversion(void)
++{
++ DeviceEvent ev;
++ xXIDeviceEvent *xi2, *xi2_flags;
++ int rc;
++
++ memset(&ev, 0, sizeof(ev));
++
++ ev.header = 0xFF;
++ ev.length = sizeof(DeviceEvent);
++ ev.type = ET_TouchBegin;
++
++ rc = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2);
++ g_assert(rc == Success);
++ g_assert(xi2->type == GenericEvent);
++ g_assert(xi2->evtype == XI_TouchBegin);
++ g_assert(xi2->flags == 0);
++
++ rc = EventToXI2((InternalEvent*)&ev, (xEvent**)&xi2_flags);
++ g_assert(rc == Success);
++ g_assert(xi2_flags->type == GenericEvent);
++ g_assert(xi2_flags->evtype == XI_TouchBegin);
++ xi2_flags->flags = 0;
++ g_assert(memcmp(xi2, xi2_flags, sizeof(*xi2)) == 0);
++}
++
+ static void xi2_struct_sizes(void)
+ {
+ #define compare(req) \
+@@ -812,6 +843,38 @@
+ g_assert(rc == TRUE);
+ rc = GrabMatchesSecond(&b, &a, FALSE);
+ g_assert(rc == TRUE);
++
++ /* All touch grabs must match a TouchBegin grab. */
++ a.grabtype = GRABTYPE_XI2;
++ b.grabtype = GRABTYPE_XI2;
++ a.type = XI_TouchBegin;
++ b.type = XI_TouchUpdate;
++ a.detail.exact = 0;
++ b.detail.exact = 0;
++ a.modifiersDetail.exact = 0;
++ b.modifiersDetail.exact = 0;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchUpdateUnowned;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchOwnership;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
++
++ b.type = XI_TouchEnd;
++ rc = GrabMatchesSecond(&a, &b, FALSE);
++ g_assert(rc == TRUE);
++ rc = GrabMatchesSecond(&b, &a, FALSE);
++ g_assert(rc == TRUE);
+ }
+
+ static void test_bits_to_byte(int i)
+@@ -1199,6 +1262,101 @@
+ }
+ }
+
++static void touch_create(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr ti;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ /* Make sure we get a valid touchpoint back. */
++ ti = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(ti);
++ g_assert(ti->active == TRUE);
++ g_assert(ti->ddx_id == 0xdeadbeef);
++ g_assert(ti->client_id != 0);
++ g_assert(ti->pending_finish == 0);
++ g_assert(ti->sprite.spriteTraceGood == 0);
++}
++
++static void touch_find_point(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr create_ret, find_ret;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ create_ret = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(create_ret);
++
++ /* Make sure we can find the touch by both DDX and client ID. */
++ find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
++ g_assert(create_ret == find_ret);
++ find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
++ g_assert(find_ret->active == TRUE);
++ g_assert(find_ret->ddx_id == 0xdeadbeef);
++
++ /* Touches which are pending finish must be findable by their client ID,
++ * but not by their DDX ID, as only the DIX can inject ownership change
++ * events. */
++ find_ret->ddx_pending_finish = 1;
++ find_ret = FindTouchPointByClientID(&dev, create_ret->client_id);
++ g_assert(find_ret == create_ret);
++ find_ret = FindTouchPointByDDXID(&dev, 0xdeadbeef);
++ g_assert(!find_ret);
++}
++
++static void touch_finish(void)
++{
++ DeviceIntRec dev;
++ TouchClassRec touch;
++ TouchPointInfoRec touches[2];
++ TouchPointInfoPtr ti;
++ uint32_t client_id;
++
++ memset(&dev, 0, sizeof(dev));
++ memset(&touch, 0, sizeof(touch));
++ memset(touches, 0, sizeof(*touches) * 2);
++ touch.touches = touches;
++ touch.num_touches = 2;
++ touch.num_axes = 2;
++ touch.next_client_id = 1;
++ dev.touch = &touch;
++
++ /* Make sure the touch is in a sane state once we kill it, and that we
++ * can't find it once it's gone. */
++ ti = BeginTouchPoint(&dev, 0xdeadbeef);
++ g_assert(ti);
++ client_id = ti->client_id;
++ EndTouchPoint(&dev, ti);
++ g_assert(ti->active == FALSE);
++ g_assert(ti->pending_finish == 0);
++ g_assert(ti->sprite.spriteTraceGood == 0);
++ g_assert(ti->client_id == 0);
++ g_assert(ti->ddx_id == 0);
++
++ g_assert(FindTouchPointByDDXID(&dev, 0xdeadbeef) == NULL);
++ g_assert(FindTouchPointByClientID(&dev, client_id) == NULL);
++}
++
+ int main(int argc, char** argv)
+ {
+ g_test_init(&argc, &argv,NULL);
+@@ -1209,6 +1367,7 @@
+ g_test_add_func("/dix/input/init-valuators", dix_init_valuators);
+ g_test_add_func("/dix/input/event-core-conversion", dix_event_to_core_conversion);
+ g_test_add_func("/dix/input/event-xi1-conversion", dix_event_to_xi1_conversion);
++ g_test_add_func("/dix/input/event-xi2-conversion", dix_event_to_xi2_conversion);
+ g_test_add_func("/dix/input/check-grab-values", dix_check_grab_values);
+ g_test_add_func("/dix/input/xi2-struct-sizes", xi2_struct_sizes);
+ g_test_add_func("/dix/input/grab_matching", dix_grab_matching);
+@@ -1216,7 +1375,9 @@
+ g_test_add_func("/include/byte_padding_macros", include_byte_padding_macros);
+ g_test_add_func("/include/bit_test_macros", include_bit_test_macros);
+ g_test_add_func("/Xi/xiproperty/register-unregister", xi_unregister_handlers);
+-
++ g_test_add_func("/dix/input/touch-create", touch_create);
++ g_test_add_func("/dix/input/touch-find-point", touch_find_point);
++ g_test_add_func("/dix/input/touch-finish", touch_finish);
+
+ return g_test_run();
+ }
+Index: b/test/xi2/protocol-eventconvert.c
+===================================================================
+--- a/test/xi2/protocol-eventconvert.c 2011-02-28 16:57:00.000000000 +1100
++++ b/test/xi2/protocol-eventconvert.c 2011-03-09 13:11:48.123385564 +1100
+@@ -149,6 +149,59 @@
+ free(swapped);
+ }
+
++static void test_values_XITouchOwnershipEvent(TouchOwnershipEvent *in,
++ xXITouchOwnershipEvent *out,
++ BOOL swap)
++{
++ char n;
++
++ if (swap)
++ {
++ swaps(&out->sequenceNumber, n);
++ swapl(&out->length, n);
++ swaps(&out->evtype, n);
++ swaps(&out->deviceid, n);
++ swapl(&out->time, n);
++ swaps(&out->sourceid, n);
++ swapl(&out->touchid, n);
++ swapl(&out->flags, n);
++ }
++
++ g_assert(out->type == GenericEvent);
++ g_assert(out->extension == 0);
++ g_assert(out->length == bytes_to_int32(sizeof(*out) - sizeof(xEvent)));
++ g_assert(out->evtype == XI_TouchOwnership);
++ g_assert(out->deviceid == in->deviceid);
++ g_assert(out->time == in->time);
++ g_assert(out->sourceid == in->sourceid);
++ g_assert(out->touchid == in->touchid);
++ g_assert(out->flags == in->flags);
++}
++
++static void test_convert_XITouchOwnershipEvent(void)
++{
++ TouchOwnershipEvent in;
++ xXITouchOwnershipEvent *out, swapped;
++ int rc;
++
++ in.header = ET_Internal;
++ in.type = ET_TouchOwnership;
++ in.touchid = 0xdeadbeef;
++ in.time = 234;
++ in.deviceid = 12;
++ in.sourceid = 14;
++ in.resource = 0xcafebabe;
++ in.flags = 0;
++ rc = EventToXI2((InternalEvent *) &in, (xEvent **) &out);
++ g_assert(rc == Success);
++
++ test_values_XITouchOwnershipEvent(&in, out, FALSE);
++ XI2EventSwap((xGenericEvent*)out, (xGenericEvent*)&swapped);
++ test_values_XITouchOwnershipEvent(&in, &swapped, TRUE);
++
++ free(out);
++}
++
+ static void test_convert_XIFocusEvent(void)
+ {
+ xEvent *out;
+@@ -272,7 +325,7 @@
+ int buttons, valuators;
+ int i;
+ unsigned char *ptr;
+- uint32_t flagmask = 0;
++ uint32_t flagmask;
+ FP3232 *values;
+
+ if (swap) {
+@@ -311,9 +364,16 @@
+ g_assert(out->sourceid == in->sourceid);
+
+ switch (in->type) {
++ case ET_ButtonPress:
++ case ET_ButtonRelease:
++ case ET_Motion:
++ flagmask = XIPointerEmulated;
++ break;
+ case ET_KeyPress:
+ flagmask = XIKeyRepeat;
+ break;
++ case ET_TouchMotion:
++ case ET_TouchMotionUnowned:
+ default:
+ flagmask = 0;
+ break;
+@@ -636,6 +696,49 @@
+ }
+ }
+
++static void test_convert_XITouch(void)
++{
++ DeviceEvent in;
++
++ memset(&in, 0, sizeof(in));
++
++ g_test_message("Testing TouchBegin");
++ in.header = ET_Internal;
++ in.type = ET_TouchBegin;
++ in.length = sizeof(DeviceEvent);
++ in.time = 0;
++ in.deviceid = 1;
++ in.sourceid = 2;
++ in.root = 3;
++ in.root_x = 4;
++ in.root_x_frac = 5;
++ in.root_y = 6;
++ in.root_y_frac = 7;
++ in.detail.button = 8;
++ in.mods.base = 9;
++ in.mods.latched = 10;
++ in.mods.locked = 11;
++ in.mods.effective = 11;
++ in.group.base = 12;
++ in.group.latched = 13;
++ in.group.locked = 14;
++ in.group.effective = 15;
++ test_XIDeviceEvent(&in);
++
++ in.flags = 0;
++ g_test_message("Testing TouchMotion");
++ in.type = ET_TouchMotion;
++ test_XIDeviceEvent(&in);
++
++ g_test_message("Testing TouchMotionUnowned");
++ in.type = ET_TouchMotionUnowned;
++ test_XIDeviceEvent(&in);
++
++ g_test_message("Testing TouchEnd");
++ in.type = ET_TouchEnd;
++ test_XIDeviceEvent(&in);
++}
++
+ static void test_values_XIDeviceChangedEvent(DeviceChangedEvent *in,
+ xXIDeviceChangedEvent *out,
+ BOOL swap)
+@@ -912,6 +1015,8 @@
+ g_test_add_func("/xi2/eventconvert/XIFocusEvent", test_convert_XIFocusEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceEvent", test_convert_XIDeviceEvent);
+ g_test_add_func("/xi2/eventconvert/XIDeviceChangedEvent", test_convert_XIDeviceChangedEvent);
++ g_test_add_func("/xi2/eventconvert/XITouch", test_convert_XITouch);
++ g_test_add_func("/xi2/eventconvert/XITouchOwnership", test_convert_XITouchOwnershipEvent);
+
+ return g_test_run();
+ }
+Index: b/test/xi2/protocol-xiselectevents.c
+===================================================================
+--- a/test/xi2/protocol-xiselectevents.c 2011-02-28 16:57:00.000000000 +1100
++++ b/test/xi2/protocol-xiselectevents.c 2011-03-09 13:11:48.123385564 +1100
+@@ -159,9 +159,33 @@
+ memset(bits, 0, mask->mask_len * 4);
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ ClearBit(bits, j);
++
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ ClearBit(bits, XI_TouchBegin);
++ ClearBit(bits, XI_TouchUpdate);
++ ClearBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ ClearBit(bits, XI_TouchOwnership);
++ }
+ }
+
+ /* Test 2:
+@@ -175,7 +199,23 @@
+
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ }
+
+@@ -189,7 +229,23 @@
+
+ for (j = XI2LASTEVENT + 1; j < mask->mask_len * 4; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, BadValue);
+ ClearBit(bits, j);
+ }
+@@ -202,7 +258,23 @@
+ memset(bits, 0, mask->mask_len * 4);
+ for (j = 0; j <= XI2LASTEVENT; j++)
+ {
++ /* Can't select for these events alone */
++ if (j == XI_TouchBegin || j == XI_TouchOwnership ||
++ j == XI_TouchEnd)
++ continue;
++
+ SetBit(bits, j);
++
++ /* Must select for TouchBegin + TouchMotion + TouchEnd together,
++ * and optionally also TouchMotionUnowned and TouchOwnerhip. */
++ if (j == XI_TouchUpdate || j == XI_TouchUpdateUnowned) {
++ SetBit(bits, XI_TouchBegin);
++ SetBit(bits, XI_TouchUpdate);
++ SetBit(bits, XI_TouchEnd);
++ if (j == XI_TouchUpdateUnowned)
++ SetBit(bits, XI_TouchOwnership);
++ }
++
+ request_XISelectEvent(req, Success);
+ }
+
diff --git a/x11-base/xorg-server/files/xorg-sets.conf b/x11-base/xorg-server/files/xorg-sets.conf
new file mode 100644
index 0000000..5cd8112
--- /dev/null
+++ b/x11-base/xorg-server/files/xorg-sets.conf
@@ -0,0 +1,6 @@
+# Rebuild all X11 modules (mostly useful after xorg-server ABI change).
+[x11-module-rebuild]
+class = portage.sets.dbapi.VariableSet
+world-candidate = false
+variable = CATEGORY
+includes = x11-drivers
diff --git a/x11-base/xorg-server/metadata.xml b/x11-base/xorg-server/metadata.xml
new file mode 100644
index 0000000..934e4a0
--- /dev/null
+++ b/x11-base/xorg-server/metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
+<pkgmetadata>
+<herd>x11</herd>
+<use>
+ <flag name='dmx'>Build the Distributed Multiheaded X server</flag>
+ <flag name='kdrive'>Build the kdrive X servers</flag>
+ <flag name='tslib'>Build with tslib support for touchscreen devices</flag>
+ <flag name='xorg'>Build the Xorg X server (HIGHLY RECOMMENDED)</flag>
+ <flag name='utouch'>Build with utouch support</flag>
+</use>
+</pkgmetadata>
diff --git a/x11-base/xorg-server/xorg-server-1.10.0.901-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.0.901-r1.ebuild
new file mode 100644
index 0000000..9bb8774
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.0.901-r1.ebuild
@@ -0,0 +1,254 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.0.901.ebuild,v 1.1 2011/03/30 20:08:02 chithanh Exp $
+
+EAPI=4
+
+XORG_EAUTORECONF=yes
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.15.20
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+ )
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ CONFIGURE_OPTIONS="
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ $(use_with utouch gestures)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ "
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ # Due to the limitations of CONFIGURE_OPTIONS, we have to export this
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+
+ # Incompatible with GCC 3.x SSP on x86, bug #244352
+ if use x86 ; then
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ filter-flags -fstack-protector
+ fi
+ fi
+
+ # Incompatible with GCC 3.x CPP, bug #314615
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ ewarn "GCC 3.x C preprocessor may cause build failures. Use GCC 4.x"
+ ewarn "or set CPP=cpp-4.3.4 (replace with the actual installed version)"
+ fi
+
+ # detect if we should inform user about ebuild breakage
+ if ! has_version "x11-base/xorg-server" ||
+ has_version "<x11-base/xorg-server-$(get_version_component_range 1-2)"; then
+ INFO="yes"
+ fi
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${INFO} = yes ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if ! has_version x11-base/xorg-server; then
+ if [[ -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.0.902-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.0.902-r1.ebuild
new file mode 100644
index 0000000..734ec36
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.0.902-r1.ebuild
@@ -0,0 +1,254 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.0.902.ebuild,v 1.1 2011/04/09 15:53:34 scarabeus Exp $
+
+EAPI=4
+
+XORG_EAUTORECONF=yes
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev utouch"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.15.20
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+ )
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ CONFIGURE_OPTIONS="
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ $(use_enable utouch gestures)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ "
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ # Due to the limitations of CONFIGURE_OPTIONS, we have to export this
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+
+ # Incompatible with GCC 3.x SSP on x86, bug #244352
+ if use x86 ; then
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ filter-flags -fstack-protector
+ fi
+ fi
+
+ # Incompatible with GCC 3.x CPP, bug #314615
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ ewarn "GCC 3.x C preprocessor may cause build failures. Use GCC 4.x"
+ ewarn "or set CPP=cpp-4.3.4 (replace with the actual installed version)"
+ fi
+
+ # detect if we should inform user about ebuild breakage
+ if ! has_version "x11-base/xorg-server" ||
+ has_version "<x11-base/xorg-server-$(get_version_component_range 1-2)"; then
+ INFO="yes"
+ fi
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${INFO} = yes ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if ! has_version x11-base/xorg-server; then
+ if [[ -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild
new file mode 100644
index 0000000..734ec36
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild
@@ -0,0 +1,254 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.0.902.ebuild,v 1.1 2011/04/09 15:53:34 scarabeus Exp $
+
+EAPI=4
+
+XORG_EAUTORECONF=yes
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev utouch"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.15.20
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+ )
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ CONFIGURE_OPTIONS="
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ $(use_enable utouch gestures)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ "
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ # Due to the limitations of CONFIGURE_OPTIONS, we have to export this
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+
+ # Incompatible with GCC 3.x SSP on x86, bug #244352
+ if use x86 ; then
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ filter-flags -fstack-protector
+ fi
+ fi
+
+ # Incompatible with GCC 3.x CPP, bug #314615
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ ewarn "GCC 3.x C preprocessor may cause build failures. Use GCC 4.x"
+ ewarn "or set CPP=cpp-4.3.4 (replace with the actual installed version)"
+ fi
+
+ # detect if we should inform user about ebuild breakage
+ if ! has_version "x11-base/xorg-server" ||
+ has_version "<x11-base/xorg-server-$(get_version_component_range 1-2)"; then
+ INFO="yes"
+ fi
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${INFO} = yes ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if ! has_version x11-base/xorg-server; then
+ if [[ -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.1.901-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.1.901-r1.ebuild
new file mode 100644
index 0000000..08d8f15
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.1.901-r1.ebuild
@@ -0,0 +1,241 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.1.901.ebuild,v 1.2 2011/05/08 11:52:53 scarabeus Exp $
+
+EAPI=4
+
+XORG_DOC=doc
+XORG_EAUTORECONF=yes
+
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev utouch"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.21.8
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+
+)
+
+pkg_pretend() {
+ # older gcc is not supported
+ [[ $(gcc-major-version) -lt 4 ]] && \
+ die "Sorry, but gcc earlier than 4.0 wont work for xorg-server."
+}
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ XORG_CONFIGURE_OPTIONS=(
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ )
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${PV} != 9999 && $(get_version_component_range 2 ${REPLACING_VERSIONS}) != $(get_version_component_range 2 ${PV}) ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ ewarn "or using sets from portage-2.2:"
+ ewarn " emerge @x11-module-rebuild"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if [[ -z ${REPLACED_BY_VERSION} && -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.1.ebuild b/x11-base/xorg-server/xorg-server-1.10.1.ebuild
new file mode 100644
index 0000000..2a041a1
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.1.ebuild
@@ -0,0 +1,250 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.1.ebuild,v 1.2 2011/04/20 21:28:25 chithanh Exp $
+
+EAPI=4
+
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.15.20
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-glapi_c.patch
+ )
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ CONFIGURE_OPTIONS="
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ "
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ # Due to the limitations of CONFIGURE_OPTIONS, we have to export this
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+
+ # Incompatible with GCC 3.x SSP on x86, bug #244352
+ if use x86 ; then
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ filter-flags -fstack-protector
+ fi
+ fi
+
+ # Incompatible with GCC 3.x CPP, bug #314615
+ if [[ $(gcc-major-version) -lt 4 ]]; then
+ ewarn "GCC 3.x C preprocessor may cause build failures. Use GCC 4.x"
+ ewarn "or set CPP=cpp-4.3.4 (replace with the actual installed version)"
+ fi
+
+ # detect if we should inform user about ebuild breakage
+ if ! has_version "x11-base/xorg-server" ||
+ has_version "<x11-base/xorg-server-$(get_version_component_range 1-2)"; then
+ INFO="yes"
+ fi
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${INFO} = yes ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if ! has_version x11-base/xorg-server; then
+ if [[ -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild
new file mode 100644
index 0000000..be23c7d
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild
@@ -0,0 +1,240 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.2.ebuild,v 1.1 2011/05/29 08:19:28 scarabeus Exp $
+
+EAPI=4
+
+XORG_EAUTORECONF=yes
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xorg"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev utouch"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.21.8
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? ( >=x11-proto/dmxproto-2.2.99.1 )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-1.10.2-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+)
+
+pkg_pretend() {
+ # older gcc is not supported
+ [[ $(gcc-major-version) -lt 4 ]] && \
+ die "Sorry, but gcc earlier than 4.0 wont work for xorg-server."
+}
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ XORG_CONFIGURE_OPTIONS=(
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable !minimal xvfb)
+ $(use_enable !minimal xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ $(use_enable utouch gestures)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ )
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${PV} != 9999 && $(get_version_component_range 2 ${REPLACING_VERSIONS}) != $(get_version_component_range 2 ${PV}) ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ ewarn "or using sets from portage-2.2:"
+ ewarn " emerge @x11-module-rebuild"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if [[ -z ${REPLACED_BY_VERSION} && -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild b/x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild
new file mode 100644
index 0000000..130432e
--- /dev/null
+++ b/x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild
@@ -0,0 +1,249 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/xorg-server-1.10.2.ebuild,v 1.1 2011/05/29 08:19:28 scarabeus Exp $
+
+EAPI=4
+
+XORG_EAUTORECONF=yes
+XORG_DOC=doc
+inherit xorg-2 multilib versionator
+EGIT_REPO_URI="git://anongit.freedesktop.org/git/xorg/xserver"
+
+DESCRIPTION="X.Org X servers"
+KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~sh ~sparc ~x86 ~x86-fbsd"
+
+IUSE_SERVERS="dmx kdrive xnest xorg xvfb"
+IUSE="${IUSE_SERVERS} ipv6 minimal nptl tslib +udev utouch"
+
+RDEPEND=">=app-admin/eselect-opengl-1.0.8
+ dev-libs/openssl
+ media-libs/freetype
+ >=x11-apps/iceauth-1.0.2
+ >=x11-apps/rgb-1.0.3
+ >=x11-apps/xauth-1.0.3
+ x11-apps/xkbcomp
+ >=x11-libs/libpciaccess-0.10.3
+ >=x11-libs/libXau-1.0.4
+ >=x11-libs/libXdmcp-1.0.2
+ >=x11-libs/libXfont-1.4.2
+ >=x11-libs/libxkbfile-1.0.4
+ >=x11-libs/pixman-0.21.8
+ >=x11-libs/xtrans-1.2.2
+ >=x11-misc/xbitmaps-1.0.1
+ >=x11-misc/xkeyboard-config-1.4
+ dmx? (
+ x11-libs/libXt
+ >=x11-libs/libdmx-1.0.99.1
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXaw-1.0.4
+ >=x11-libs/libXext-1.0.99.4
+ >=x11-libs/libXfixes-4.0.3
+ >=x11-libs/libXi-1.2.99.1
+ >=x11-libs/libXmu-1.0.3
+ >=x11-libs/libXres-1.0.3
+ >=x11-libs/libXtst-1.0.99.2
+ )
+ kdrive? (
+ >=x11-libs/libXext-1.0.5
+ x11-libs/libXv
+ )
+ !minimal? (
+ >=x11-libs/libX11-1.1.5
+ >=x11-libs/libXext-1.0.5
+ >=media-libs/mesa-7.8_rc[nptl=]
+ )
+ tslib? ( >=x11-libs/tslib-1.0 x11-proto/xcalibrateproto )
+ udev? ( >=sys-fs/udev-150 )
+ >=x11-apps/xinit-1.3"
+
+DEPEND="${RDEPEND}
+ sys-devel/flex
+ >=x11-proto/bigreqsproto-1.1.0
+ >=x11-proto/compositeproto-0.4
+ >=x11-proto/damageproto-1.1
+ >=x11-proto/fixesproto-4.1
+ >=x11-proto/fontsproto-2.0.2
+ >=x11-proto/glproto-1.4.11
+ >=x11-proto/inputproto-1.9.99.902
+ >=x11-proto/kbproto-1.0.3
+ >=x11-proto/randrproto-1.2.99.3
+ >=x11-proto/recordproto-1.13.99.1
+ >=x11-proto/renderproto-0.11
+ >=x11-proto/resourceproto-1.0.2
+ >=x11-proto/scrnsaverproto-1.1
+ >=x11-proto/trapproto-3.4.3
+ >=x11-proto/videoproto-2.2.2
+ >=x11-proto/xcmiscproto-1.2.0
+ >=x11-proto/xextproto-7.1.99
+ >=x11-proto/xf86dgaproto-2.0.99.1
+ >=x11-proto/xf86rushproto-1.1.2
+ >=x11-proto/xf86vidmodeproto-2.2.99.1
+ >=x11-proto/xineramaproto-1.1.3
+ >=x11-proto/xproto-7.0.17
+ dmx? (
+ >=x11-proto/dmxproto-2.2.99.1
+ doc? (
+ || (
+ www-client/links
+ www-client/lynx
+ www-client/w3m
+ )
+ )
+ )
+ !minimal? (
+ >=x11-proto/xf86driproto-2.1.0
+ >=x11-proto/dri2proto-2.3
+ >=x11-libs/libdrm-2.4.20
+ )"
+
+PDEPEND="
+ xorg? ( >=x11-base/xorg-drivers-$(get_version_component_range 1-2) )"
+
+REQUIRED_USE="!minimal? (
+ || ( ${IUSE_SERVERS} )
+ )"
+
+#UPSTREAMED_PATCHES=(
+# "${WORKDIR}/patches/"
+#)
+
+PATCHES=(
+ "${UPSTREAMED_PATCHES[@]}"
+ "${FILESDIR}"/${PN}-disable-acpi.patch
+ "${FILESDIR}"/${PN}-1.9-nouveau-default.patch
+ "${FILESDIR}"/${PN}-1.10.2-xi2.patch
+ "${FILESDIR}"/${PN}-xf86CoordinatesToWindow.patch
+ "${FILESDIR}"/${PN}-gestures-extension.patch
+)
+
+pkg_pretend() {
+ # older gcc is not supported
+ [[ $(gcc-major-version) -lt 4 ]] && \
+ die "Sorry, but gcc earlier than 4.0 wont work for xorg-server."
+}
+
+pkg_setup() {
+ xorg-2_pkg_setup
+
+ # localstatedir is used for the log location; we need to override the default
+ # from ebuild.sh
+ # sysconfdir is used for the xorg.conf location; same applies
+ # --enable-install-setuid needed because sparcs default off
+ # NOTE: fop is used for doc generating ; and i have no idea if gentoo
+ # package it somewhere
+ XORG_CONFIGURE_OPTIONS=(
+ $(use_enable ipv6)
+ $(use_enable dmx)
+ $(use_enable kdrive)
+ $(use_enable kdrive kdrive-kbd)
+ $(use_enable kdrive kdrive-mouse)
+ $(use_enable kdrive kdrive-evdev)
+ $(use_enable tslib)
+ $(use_enable tslib xcalibrate)
+ $(use_enable xvfb)
+ $(use_enable xnest)
+ $(use_enable !minimal record)
+ $(use_enable !minimal xfree86-utils)
+ $(use_enable !minimal install-libxf86config)
+ $(use_enable !minimal dri)
+ $(use_enable !minimal dri2)
+ $(use_enable !minimal glx)
+ $(use_enable xorg)
+ $(use_enable nptl glx-tls)
+ $(use_enable udev config-udev)
+ $(use_with doc doxygen)
+ $(use_with doc xmlto)
+ $(use_enable utouch gestures)
+ --sysconfdir=/etc/X11
+ --localstatedir=/var
+ --enable-install-setuid
+ --with-fontrootdir=/usr/share/fonts
+ --with-xkb-output=/var/lib/xkb
+ --disable-config-hal
+ --without-dtrace
+ --without-fop
+ --with-os-vendor=Gentoo
+ )
+
+ # Xorg-server requires includes from OS mesa which are not visible for
+ # users of binary drivers.
+ mkdir -p "${T}/mesa-symlinks/GL"
+ for i in gl glx glxmd glxproto glxtokens; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/xorg-x11/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ for i in glext glxext; do
+ ln -s "${EROOT}usr/$(get_libdir)/opengl/global/include/$i.h" "${T}/mesa-symlinks/GL/$i.h" || die
+ done
+ append-cppflags "-I${T}/mesa-symlinks"
+}
+
+src_install() {
+ xorg-2_src_install
+
+ dynamic_libgl_install
+
+ server_based_install
+
+ if ! use minimal && use xorg; then
+ # Install xorg.conf.example into docs
+ dodoc "${AUTOTOOLS_BUILD_DIR}"/hw/xfree86/xorg.conf.example
+ fi
+
+ newinitd "${FILESDIR}"/xdm-setup.initd-1 xdm-setup
+ newinitd "${FILESDIR}"/xdm.initd-3 xdm
+ newconfd "${FILESDIR}"/xdm.confd-3 xdm
+
+ # install the @x11-module-rebuild set for Portage
+ insinto /usr/share/portage/config/sets
+ newins "${FILESDIR}"/xorg-sets.conf xorg.conf
+}
+
+pkg_postinst() {
+ # sets up libGL and DRI2 symlinks if needed (ie, on a fresh install)
+ eselect opengl set xorg-x11 --use-old
+
+ if [[ ${PV} != 9999 && $(get_version_component_range 2 ${REPLACING_VERSIONS}) != $(get_version_component_range 2 ${PV}) ]]; then
+ elog "You should consider reading upgrade guide for this release:"
+ elog " http://www.gentoo.org/proj/en/desktop/x/x11/xorg-server-$(get_version_component_range 1-2)-upgrade-guide.xml"
+ echo
+ ewarn "You must rebuild all drivers if upgrading from <xorg-server-$(get_version_component_range 1-2)"
+ ewarn "because the ABI changed. If you cannot start X because"
+ ewarn "of module version mismatch errors, this is your problem."
+
+ echo
+ ewarn "You can generate a list of all installed packages in the x11-drivers"
+ ewarn "category using this command:"
+ ewarn " emerge portage-utils; qlist -I -C x11-drivers/"
+ ewarn "or using sets from portage-2.2:"
+ ewarn " emerge @x11-module-rebuild"
+ fi
+}
+
+pkg_postrm() {
+ # Get rid of module dir to ensure opengl-update works properly
+ if [[ -z ${REPLACED_BY_VERSION} && -e ${ROOT}/usr/$(get_libdir)/xorg/modules ]]; then
+ rm -rf "${ROOT}"/usr/$(get_libdir)/xorg/modules
+ fi
+}
+
+dynamic_libgl_install() {
+ # next section is to setup the dynamic libGL stuff
+ ebegin "Moving GL files for dynamic switching"
+ dodir /usr/$(get_libdir)/opengl/xorg-x11/extensions
+ local x=""
+ for x in "${D}"/usr/$(get_libdir)/xorg/modules/extensions/lib{glx,dri,dri2}*; do
+ if [ -f ${x} -o -L ${x} ]; then
+ mv -f ${x} "${D}"/usr/$(get_libdir)/opengl/xorg-x11/extensions
+ fi
+ done
+ eend 0
+}
+
+server_based_install() {
+ if ! use xorg; then
+ rm "${D}"/usr/share/man/man1/Xserver.1x \
+ "${D}"/usr/$(get_libdir)/xserver/SecurityPolicy \
+ "${D}"/usr/$(get_libdir)/pkgconfig/xorg-server.pc \
+ "${D}"/usr/share/man/man1/Xserver.1x
+ fi
+}
diff --git a/x11-drivers/xf86-input-evdev/Manifest b/x11-drivers/xf86-input-evdev/Manifest
new file mode 100644
index 0000000..f66b468
--- /dev/null
+++ b/x11-drivers/xf86-input-evdev/Manifest
@@ -0,0 +1,4 @@
+AUX xf86-input-evdev-gestures.patch 23436 RMD160 839e8cd97fe0c47b4b02ce6f6d8ddc0d5f4b84e3 SHA1 6da156d429f3cc3f9fd03e03a7799b1b19835164 SHA256 9e868d28efbe7baaa3ccc405d866668a656b8526c8d7d91ebb6f3fc2437e8541
+AUX xf86-input-evdev-xi2.1.patch 57618 RMD160 cc15cc711667a0efc9d6bdda1d4c77dd06d5c5c8 SHA1 2fb6f062900872ece9c44bf223b0d1da8b36bf4a SHA256 f774127a8aff8076d37c12a9993816fef69586e3dcf7e01e77206291dfecfd74
+DIST xf86-input-evdev-2.6.0.tar.bz2 322773 RMD160 cde3345f882a4774dffe3ec9c716ef077f25febf SHA1 fb6f7a6f5168ae07efe890e4ace9fb8af1d4e1e0 SHA256 b0e7f3991a8183a4743196c3e16d7184d439b80bf43653aa2f45b0756a6753ac
+EBUILD xf86-input-evdev-2.6.0-r1.ebuild 778 RMD160 a8c2e11dbcf32a32e9dba0cf12fd016b34de1a1b SHA1 ec5ba962c207dfb7994d12658ac60c3512354f9a SHA256 2923c72deb30b5ec8e86fd5464d69342387dbb19fa5a5ebbfc4945f2aad0e882
diff --git a/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-gestures.patch b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-gestures.patch
new file mode 100644
index 0000000..fd55d1a
--- /dev/null
+++ b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-gestures.patch
@@ -0,0 +1,664 @@
+--- a/configure.ac
++++ b/configure.ac
+@@ -68,6 +68,22 @@ sdkdir=`$PKG_CONFIG --variable=sdkdir xo
+ AC_ARG_WITH([sdkdir], [], [sdkdir="$withval"])
+ AC_SUBST([sdkdir])
+
++AC_ARG_ENABLE(utouch-grail, AS_HELP_STRING([--enable-utouch-grail], [Build with utouch-grail gesture support (default: auto)]), [GRAIL=$enableval], [GRAIL=auto])
++PKG_CHECK_MODULES(GRAIL, utouch-grail, [have_grail=yes], [have_grail=no])
++if test "x$GRAIL" = xauto; then
++ GRAIL="$have_grail"
++fi
++if test "x$GRAIL" = xyes; then
++ if test "x$have_grail" = xno; then
++ AC_MSG_ERROR([Grail build explicitly requested, but required modules not found.])
++ fi
++ AC_DEFINE(USE_GRAIL, 1, Whether to use grail or not)
++ AC_DEFINE(GESTURES, 1, Needed to interpret xorg headers properly)
++else
++ AC_DEFINE(USE_GRAIL, 0, Whether to use grail or not)
++fi
++AM_CONDITIONAL(USE_GRAIL, [test "x$GRAIL" = xyes])
++
+ DRIVER_NAME=evdev
+ AC_SUBST([DRIVER_NAME])
+
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -29,12 +29,17 @@ AM_CFLAGS = $(XORG_CFLAGS) $(CWARNFLAGS)
+ AM_CPPFLAGS =-I$(top_srcdir)/include
+
+ @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
+-@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
++@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version @GRAIL_LIBS@
+ @DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS)
+ @DRIVER_NAME@_drv_ladir = @inputdir@
+
++if USE_GRAIL
++GRAIL_SRC=evdev-grail.c evdev-grail.h
++endif
++
+ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+ @DRIVER_NAME@.h \
++ $(GRAIL_SRC) \
+ emuMB.c \
+ emuWheel.c \
+ draglock.c
+--- /dev/null
++++ b/src/evdev-grail.c
+@@ -0,0 +1,375 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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.
++ *
++ * Authors:
++ * Chase Douglas (chase.douglas@canonical.com)
++ */
++
++/* So we can get at the right data in xorg/windowstr.h */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include <xorg-server.h>
++#include <X11/Xatom.h>
++#include <xf86.h>
++#include <xf86Xinput.h>
++#include <exevents.h>
++#include <windowstr.h>
++#include <xorg/os.h>
++
++#include <evdev-properties.h>
++#include "evdev.h"
++#include "evdev-grail.h"
++#include "gestureproto.h"
++
++/* Copied from evdev.c, will be in evdev.h when xserver 1.9 is merged */
++#define EVDEV_RELATIVE_EVENTS (1 << 2)
++#define EVDEV_TOUCHPAD (1 << 4)
++
++/*
++ * Provided by the Maverick X server, we don't want to pollute the official
++ * X.org API.
++ */
++extern _X_EXPORT void xf86PostGestureEvent(DeviceIntPtr dev, unsigned short x,
++ unsigned short y, unsigned short client_id,
++ unsigned short gesture_id, unsigned short gesture_type,
++ Window root, Window event, Window child,
++ unsigned short status, unsigned short num_props,
++ float *props);
++
++static WindowPtr CommonAncestor(WindowPtr a, WindowPtr b)
++{
++ WindowPtr c;
++
++ if (a == b)
++ return a;
++
++ for (b = b; b; b = b->parent)
++ for (c = a; c; c = c->parent)
++ if (c == b)
++ return b;
++
++ return NullWindow;
++}
++
++static WindowPtr GetWindowForGestures(struct grail *grail,
++ const struct grail_coord *contacts,
++ int num_contacts)
++{
++ WindowPtr window = NULL;
++ int i;
++
++ for (i = 0; i < num_contacts; i++)
++ {
++ float screen_x = contacts[i].x;
++ float screen_y = contacts[i].y;
++ WindowPtr this_window;
++
++ this_window = xf86CoordinatesToWindow(screen_x, screen_y, 0);
++ if (!this_window)
++ return NullWindow;
++
++ if (!window)
++ window = this_window;
++ else
++ window = CommonAncestor(window, this_window);
++ }
++
++ return window;
++}
++
++static int GetClients(struct grail *grail,
++ struct grail_client_info *clients, int max_clients,
++ const struct grail_coord *contacts, int num_contacts,
++ const grail_mask_t *types, int type_bytes)
++{
++ WindowPtr child_window;
++ WindowPtr window;
++ WindowPtr root_window;
++ InputInfoPtr pInfo = grail->priv;
++ EvdevPtr pEvdev = pInfo->private;
++ int j;
++ int found_match = 0;
++ int num_clients = 0;
++ int type;
++
++ if (max_clients <= 0)
++ return 0;
++
++ if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_TOUCHPAD))
++ {
++ DeviceIntPtr master = pInfo->dev->u.master;
++ struct grail_coord cursor_coord;
++
++ /* If this mouse isn't hooked up to a cursor, don't do anything */
++ if (!master)
++ return 0;
++
++ cursor_coord.x = master->last.valuators[0];
++ cursor_coord.y = master->last.valuators[1];
++
++ child_window = GetWindowForGestures(grail, &cursor_coord, 1);
++ } else
++ child_window = GetWindowForGestures(grail, contacts, num_contacts);
++
++ if (!child_window)
++ return 0;
++
++ memset(clients, 0, sizeof(struct grail_client_info) * max_clients);
++
++ /* Find the root window. */
++ for (root_window = child_window; root_window->parent;
++ root_window = root_window->parent);
++
++ /*
++ * Check for a root client with SYSFLAG1 set. SYSFLAG1 is effectively an
++ * active grab for system gestures. We assume only one client has SYSFLAG1
++ * set.
++ */
++ window = child_window;
++ while (window)
++ {
++ /* Check if any gestures have been selected on this window. */
++ if (wGestureMasks(window))
++ {
++ GestureClientsPtr client;
++
++ /* For each client */
++ for (client = wGestureMasks(window)->clients; client;
++ client = client->next)
++ {
++ int first = 1;
++
++ /* If the client has set the SYSFLAG1 bit */
++ if (BitIsOn(client->gestureMask[0], GRAIL_TYPE_SYSFLAG1))
++ {
++ /* For each recognized gesture */
++ grail_mask_foreach(type, types, type_bytes)
++ {
++ if (type == GRAIL_TYPE_SYSFLAG1)
++ continue;
++
++ /*
++ * Check if this client selected for this gesture.
++ * Request may be for this device or all devices.
++ */
++ if (BitIsOn(client->gestureMask[pInfo->dev->id], type) ||
++ BitIsOn(client->gestureMask[0], type))
++ {
++ if (first) {
++ /* Set up new client in array */
++ clients[0].id.client = CLIENT_ID(client->resource);
++ clients[0].id.root = root_window->drawable.id;
++ clients[0].id.child = child_window->drawable.id;
++ clients[0].id.event = window->drawable.id;
++ grail_mask_clear(clients[0].mask,
++ DIM_GRAIL_TYPE_BYTES);
++ first = 0;
++ }
++
++ /* Set this gesture bit in the client's gesture mask */
++ SetBit(clients[0].mask, type);
++ num_clients = 1;
++ }
++ }
++
++ /*
++ * Either we found a gesture, or we stop looking for SYSFLAG1
++ * clients.
++ */
++ if (num_clients) {
++ SetBit(clients[0].mask, GRAIL_TYPE_SYSFLAG1);
++ goto next_window;
++ }
++ }
++ }
++ }
++
++next_window:
++ window = window->parent;
++ }
++
++ /*
++ * Traverse the window hierarchy looking for a window with a client
++ * selecting for one of the recognized gestures.
++ *
++ * All clients of the top most window with a match will receive events if
++ * they have selected for gestures that have been recognized, even if they
++ * have selected for different gestures between them.
++ *
++ * Once any gesture is matched on a window, propagation through the window
++ * hierarchy ends.
++ */
++ for (window = child_window; window && !found_match; window = window->parent)
++ {
++ /* No client selected for gestures on this window */
++ if (!wGestureMasks(window))
++ continue;
++
++ /* For each recognized gesture */
++ grail_mask_foreach(type, types, type_bytes)
++ {
++ if (type == GRAIL_TYPE_SYSFLAG1)
++ continue;
++
++ /* Check if any client selected for this gesture on the window */
++ if (BitIsOn(wGestureMasks(window)->mask, type))
++ {
++ GestureClientsPtr client;
++
++ /* For each client that selected for gestures on this window */
++ for (client = wGestureMasks(window)->clients; client;
++ client = client->next)
++ {
++ /*
++ * Check if this client selected for this gesture. Request
++ * may be for this device or all devices.
++ */
++ if (BitIsOn(client->gestureMask[pInfo->dev->id], type) ||
++ BitIsOn(client->gestureMask[0], type))
++ {
++ /*
++ * Find this client in the clients array passed back to
++ * the caller.
++ */
++ for (j = 0; j < num_clients; j++)
++ if (clients[j].id.client ==
++ CLIENT_ID(client->resource))
++ break;
++
++ /* Check if the client exists in the array yet */
++ if (j >= num_clients)
++ {
++ /* We ran out of room in the array, return error */
++ if (num_clients >= max_clients)
++ return -1;
++ /* Set up new client in array */
++ clients[j].id.client = CLIENT_ID(client->resource);
++ clients[j].id.root = root_window->drawable.id;
++ clients[j].id.child = child_window->drawable.id;
++ clients[j].id.event = window->drawable.id;
++ num_clients++;
++ }
++
++ /* Set this gesture bit in the client's gesture mask */
++ SetBit(clients[j].mask, type);
++ }
++ }
++
++ /* A match has been found, stop propagating */
++ found_match = 1;
++ }
++ }
++ }
++
++ return num_clients;
++}
++
++static void GrailEvent(struct grail *grail, const struct input_event *ev)
++{
++ InputInfoPtr pInfo = (InputInfoPtr)grail->priv;
++ EvdevProcessEvent(pInfo, (struct input_event *)ev);
++}
++
++static void GrailGesture(struct grail *grail, const struct grail_event *ev)
++{
++ InputInfoPtr pInfo = grail->priv;
++ EvdevPtr pEvdev = pInfo->private;
++ int x;
++ int y;
++
++ /* Override event focus point if this is a relative device */
++ if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_TOUCHPAD))
++ {
++ DeviceIntPtr master = pInfo->dev->u.master;
++
++ /* If this mouse isn't hooked up to a cursor, don't do anything */
++ if (!master)
++ return;
++
++ /* Note: Master device valuators are in screen coordinates */
++ x = master->last.valuators[0];
++ y = master->last.valuators[1];
++ } else {
++ x = ev->pos.x;
++ y = ev->pos.y;
++ }
++
++ xf86PostGestureEvent(pInfo->dev, x, y, ev->client_id.client, ev->id,
++ ev->type, ev->client_id.root, ev->client_id.event,
++ ev->client_id.child, ev->status,
++ ev->nprop, (float *)ev->prop);
++}
++
++int
++GrailOpen(InputInfoPtr pInfo)
++{
++ EvdevPtr pEvdev = pInfo->private;
++
++ pEvdev->grail = malloc(sizeof(struct grail));
++ if (!pEvdev->grail) {
++ xf86Msg(X_ERROR, "evdev-grail: failed to allocate grail structure\n");
++ return -1;
++ }
++
++ memset(pEvdev->grail, 0, sizeof(struct grail));
++ pEvdev->grail->get_clients = GetClients;
++ pEvdev->grail->event = GrailEvent;
++ pEvdev->grail->gesture = GrailGesture;
++ pEvdev->grail->priv = pInfo;
++
++ if (grail_open(pEvdev->grail, pInfo->fd)) {
++ xf86Msg(X_INFO,
++ "evdev-grail: failed to open grail, no gesture support\n");
++ free(pEvdev->grail);
++ pEvdev->grail = NULL;
++ return -1;
++ }
++
++ {
++ struct grail_coord min;
++ struct grail_coord max;
++
++ min.x = screenInfo.screens[0]->x;
++ min.y = screenInfo.screens[0]->y;
++ max.x = min.x + screenInfo.screens[0]->width;
++ max.y = min.y + screenInfo.screens[0]->height;
++
++ grail_set_bbox(pEvdev->grail, &min, &max);
++ }
++
++ return 0;
++}
++
++void
++GrailClose(InputInfoPtr pInfo)
++{
++ EvdevPtr pEvdev = pInfo->private;
++
++ if (pEvdev->grail) {
++ grail_close(pEvdev->grail, pInfo->fd);
++ free(pEvdev->grail);
++ pEvdev->grail = NULL;
++ }
++}
+--- /dev/null
++++ b/src/evdev-grail.h
+@@ -0,0 +1,9 @@
++#ifndef EVDEV_GRAIL_H_
++#define EVDEV_GRAIL_H_
++
++#include <grail.h>
++
++extern int GrailOpen(InputInfoPtr pInfo);
++extern void GrailClose(InputInfoPtr pInfo);
++
++#endif /* _EVDEV_GRAIL_H_ */
+--- a/src/evdev.c
++++ b/src/evdev.c
+@@ -60,6 +60,13 @@
+ #define MAXDEVICES MAX_DEVICES
+ #endif
+
++#if USE_GRAIL
++#include "evdev-grail.h"
++#else
++#define GrailOpen(pInfo)
++#define GrailClose(pInfo)
++#endif
++
+ #define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
+
+ #define MIN_KEYCODE 8
+@@ -900,7 +907,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo
+ * Process the events from the device; nothing is actually posted to the server
+ * until an EV_SYN event is received.
+ */
+-static void
++void
+ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
+ switch (ev->type) {
+@@ -934,17 +941,14 @@ EvdevReadInput(InputInfoPtr pInfo)
+
+ while (len == sizeof(ev))
+ {
+-#ifdef MULTITOUCH
++#if USE_GRAIL
+ EvdevPtr pEvdev = pInfo->private;
+
+- if (pEvdev->mtdev)
+- len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
+- sizeof(struct input_event);
++ if (pEvdev->grail)
++ len = grail_pull(pEvdev->grail, pInfo->fd);
+ else
+- len = read(pInfo->fd, &ev, sizeof(ev));
+-#else
+- len = read(pInfo->fd, &ev, sizeof(ev));
+ #endif
++ len = read(pInfo->fd, &ev, sizeof(ev));
+ if (len <= 0)
+ {
+ if (errno == ENODEV) /* May happen after resume */
+@@ -962,6 +966,11 @@ EvdevReadInput(InputInfoPtr pInfo)
+ break;
+ }
+
++#if USE_GRAIL
++ if (pEvdev->grail)
++ return;
++#endif
++
+ /* The kernel promises that we always only read a complete
+ * event, so len != sizeof ev is an error. */
+ if (len % sizeof(ev[0])) {
+@@ -1620,6 +1629,7 @@ EvdevProc(DeviceIntPtr device, int what)
+ if (pEvdev->mtdev)
+ mtdev_close(pEvdev->mtdev);
+ #endif
++ GrailClose(pInfo);
+ EvdevRemoveDevice(pInfo);
+ pEvdev->min_maj = 0;
+ break;
+@@ -1857,6 +1867,8 @@ EvdevProbe(InputInfoPtr pInfo)
+ xf86Msg(X_PROBED, "%s: Found absolute axes\n", pInfo->name);
+ pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
+
++ GrailOpen(pInfo);
++
+ if ((TestBit(ABS_X, pEvdev->abs_bitmask) &&
+ TestBit(ABS_Y, pEvdev->abs_bitmask))) {
+ xf86Msg(X_PROBED, "%s: Found x and y absolute axes\n", pInfo->name);
+--- a/src/evdev.h
++++ b/src/evdev.h
+@@ -207,8 +207,14 @@ typedef struct {
+ /* Event queue used to defer keyboard/button events until EV_SYN time. */
+ int num_queue;
+ EventQueueRec queue[EVDEV_MAXQUEUE];
++
++#if USE_GRAIL
++ struct grail *grail;
++#endif
+ } EvdevRec, *EvdevPtr;
+
++void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
++
+ /* Event posting functions */
+ void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value);
+ void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value);
+--- /dev/null
++++ b/src/gestureproto.h
+@@ -0,0 +1,132 @@
++/*
++ * Copyright © 2010 Canonical, Ltd.
++ *
++ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
++ *
++ * Authors: Chase Douglas <chase.douglas@canonical.com>
++ *
++ */
++
++#ifndef _GESTUREPROTO_H_
++#define _GESTUREPROTO_H_
++
++#include <stdint.h>
++#include <X11/X.h>
++
++#define Window uint32_t
++#define Time uint32_t
++
++#define X_GestureQueryVersion 1
++#define X_GestureSelectEvents 2
++#define X_GestureGetSelectedEvents 3
++
++#define GESTUREREQUESTS (X_GestureGetSelectedEvents - X_GestureQueryVersion + 1)
++
++#define GestureAllDevices 0
++
++/**
++ * Used to select for events on a given window.
++ * Struct is followed by (mask_len * CARD8), with each bit set representing
++ * the event mask for the given type. A mask bit represents an event type if
++ * (mask == (1 << type)).
++ */
++typedef struct {
++ uint16_t device_id; /**< Device id to select for */
++ uint16_t mask_len; /**< Length of mask in 4 byte units */
++} GestureEventMask;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureQueryVersion */
++ uint16_t length; /**< Length in 4 byte units */
++ uint16_t major_version;
++ uint16_t minor_version;
++} GestureQueryVersionReq;
++
++typedef struct {
++ uint8_t repType; /**< ::X_Reply */
++ uint8_t RepType; /**< Always ::X_GestureQueryVersion */
++ uint16_t sequenceNumber;
++ uint32_t length;
++ uint16_t major_version;
++ uint16_t minor_version;
++ uint32_t pad1;
++ uint32_t pad2;
++ uint32_t pad3;
++ uint32_t pad4;
++ uint32_t pad5;
++} GestureQueryVersionReply;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureSelectEvents */
++ uint16_t length; /**< Length in 4 byte units */
++ Window window;
++ GestureEventMask mask;
++} GestureSelectEventsReq;
++
++typedef struct {
++ uint8_t reqType; /**< Gesture extension major code */
++ uint8_t ReqType; /**< Always ::X_GestureGetSelectedEvents */
++ uint16_t length; /**< Length in 4 byte units */
++ Window window;
++} GestureGetSelectedEventsReq;
++
++typedef struct {
++ uint8_t repType; /**< Gesture extension major opcode */
++ uint8_t RepType; /**< Always ::X_GestureGetSelectedEvents */
++ uint16_t sequenceNumber;
++ uint32_t length;
++ uint16_t num_masks; /**< Number of GestureEventMask structs
++ trailing the reply */
++ uint16_t pad0;
++ uint32_t pad1;
++ uint32_t pad2;
++ uint32_t pad3;
++ uint32_t pad4;
++ uint32_t pad5;
++} GestureGetSelectedEventsReply;
++
++typedef struct
++{
++ uint8_t type; /**< Always GenericEvent */
++ uint8_t extension; /**< Gesture extension offset */
++ uint16_t sequenceNumber; /**< Xevent sequence number */
++ uint32_t length; /**< Length in 4 byte uints */
++ uint16_t evtype; /**< X generic event type */
++ uint16_t gesture_id; /**< Unique ID for gesture */
++ uint16_t gesture_type; /**< Gesture type (zoom, rotate, etc.) */
++ uint16_t device_id; /**< Device that generated this gesture */
++ Time time; /**< Time of gesture event */
++ Window root; /**< Root window event occurred on */
++ Window event; /**< Window selecting this event for a client */
++ Window child; /**< Top-most window of gesture event */
++/* └──────── 32 byte boundary ────────┘ */
++ float focus_x; /**< Always window coords, 16.16 fixed point */
++ float focus_y; /**< Relative to event window */
++ uint16_t status; /**< Gesture event status */
++ uint16_t num_props; /**< Number of properties for gesture event */
++/* └──── Gesture properties below ────┘ */
++} GestureEvent;
++
++#undef Window
++#undef Time
++
++#endif /* _GESTUREPROTO_H_ */
diff --git a/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch
new file mode 100644
index 0000000..10598f1
--- /dev/null
+++ b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch
@@ -0,0 +1,1678 @@
+diff --git a/configure.ac b/configure.ac
+index 887021c..b4b0bad 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -47,6 +47,9 @@ XORG_DEFAULT_OPTIONS
+ # Obtain compiler/linker options from server and required extensions
+ PKG_CHECK_MODULES(XORG, xorg-server xproto inputproto)
+
++# Obtain compiler/linker options for mtdev
++PKG_CHECK_MODULES(MTDEV, mtdev)
++
+ # Define a configure option for an alternate input module directory
+ AC_ARG_WITH(xorg-module-dir,
+ AC_HELP_STRING([--with-xorg-module-dir=DIR],
+diff --git a/src/Makefile.am b/src/Makefile.am
+index a5c89ac..b8d0dd9 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -30,6 +30,7 @@ AM_CPPFLAGS =-I$(top_srcdir)/include
+
+ @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
+ @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
++@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS)
+ @DRIVER_NAME@_drv_ladir = @inputdir@
+
+ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+diff --git a/src/draglock.c b/src/draglock.c
+index af80cf6..0b430f0 100644
+--- a/src/draglock.c
++++ b/src/draglock.c
+@@ -44,9 +44,7 @@
+
+ #include <evdev-properties.h>
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_dlock = 0; /* Drag lock buttons. */
+-#endif
+
+ void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
+
+@@ -211,7 +209,6 @@ EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
+ return FALSE;
+ }
+
+-#ifdef HAVE_PROPERTIES
+ /**
+ * Set the drag lock property.
+ * If only one value is supplied, then this is used as the meta button.
+@@ -319,5 +316,3 @@ EvdevDragLockInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevDragLockSetProperty, NULL, NULL);
+ }
+-
+-#endif
+diff --git a/src/emuMB.c b/src/emuMB.c
+index 764b30e..b7a57b8 100644
+--- a/src/emuMB.c
++++ b/src/emuMB.c
+@@ -43,10 +43,8 @@
+
+ #include <evdev-properties.h>
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_mbemu = 0; /* Middle button emulation on/off property */
+ static Atom prop_mbtimeout = 0; /* Middle button timeout property */
+-#endif
+ /*
+ * Lets create a simple finite-state machine for 3 button emulation:
+ *
+@@ -330,7 +328,6 @@ EvdevMBEmuFinalize(InputInfoPtr pInfo)
+
+ }
+
+-#ifdef HAVE_PROPERTIES
+ static int
+ EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+@@ -391,4 +388,3 @@ EvdevMBEmuInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL);
+ }
+-#endif
+diff --git a/src/emuWheel.c b/src/emuWheel.c
+index 9a53211..715f8d1 100644
+--- a/src/emuWheel.c
++++ b/src/emuWheel.c
+@@ -44,13 +44,11 @@
+
+ #define WHEEL_NOT_CONFIGURED 0
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_wheel_emu = 0;
+ static Atom prop_wheel_axismap = 0;
+ static Atom prop_wheel_inertia = 0;
+ static Atom prop_wheel_timeout = 0;
+ static Atom prop_wheel_button = 0;
+-#endif
+
+ /* Local Funciton Prototypes */
+ static BOOL EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name);
+@@ -120,8 +118,9 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
+
+ /* We don't want to intercept real mouse wheel events */
+ if(pEv->type == EV_ABS) {
+- oldValue = pEvdev->vals[pEvdev->axis_map[pEv->code]];
+- pEvdev->vals[pEvdev->axis_map[pEv->code]] = value;
++ int axis = pEvdev->axis_map[pEv->code];
++ oldValue = valuator_mask_get(pEvdev->vals, axis);
++ valuator_mask_set(pEvdev->vals, axis, value);
+ value -= oldValue; /* make value into a differential measurement */
+ }
+
+@@ -335,7 +334,6 @@ EvdevWheelEmuPreInit(InputInfoPtr pInfo)
+ pInfo->name, pEvdev->emulateWheel.button, inertia, timeout);
+ }
+
+-#ifdef HAVE_PROPERTIES
+ static int
+ EvdevWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+@@ -485,4 +483,3 @@ EvdevWheelEmuInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevWheelEmuSetProperty, NULL, NULL);
+ }
+-#endif
+diff --git a/src/evdev.c b/src/evdev.c
+index 45873c1..ef72f8f 100644
+--- a/src/evdev.c
++++ b/src/evdev.c
+@@ -48,23 +48,12 @@
+ #include <xorgVersion.h>
+ #include <xkbsrv.h>
+
+-#ifdef HAVE_PROPERTIES
+ #include <X11/Xatom.h>
+ #include <evdev-properties.h>
+ #include <xserver-properties.h>
+-/* 1.6 has properties, but no labels */
+-#ifdef AXIS_LABEL_PROP
+-#define HAVE_LABELS
+-#else
+-#undef HAVE_LABELS
+-#endif
+-
+-#endif
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+ /* removed from server, purge when dropping support for server 1.10 */
+ #define XI86_SEND_DRAG_EVENTS 0x08
+-#endif
+
+ #ifndef MAXDEVICES
+ #include <inputstr.h> /* for MAX_DEVICES */
+@@ -87,6 +76,14 @@
+ #define MODEFLAG 8
+ #define COMPOSEFLAG 16
+
++#ifndef ABS_MT_SLOT
++#define ABS_MT_SLOT 0x2f
++#endif
++
++#ifndef ABS_MT_TRACKING_ID
++#define ABS_MT_TRACKING_ID 0x39
++#endif
++
+ static char *evdevDefaults[] = {
+ "XkbRules", "evdev",
+ "XkbModel", "evdev",
+@@ -114,7 +111,6 @@ static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
+ static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
+ static int EvdevOpenDevice(InputInfoPtr pInfo);
+
+-#ifdef HAVE_PROPERTIES
+ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
+ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
+ static void EvdevInitProperty(DeviceIntPtr dev);
+@@ -125,7 +121,6 @@ static Atom prop_calibration = 0;
+ static Atom prop_swap = 0;
+ static Atom prop_axis_label = 0;
+ static Atom prop_btn_label = 0;
+-#endif
+
+ /* All devices the evdev driver has allocated and knows about.
+ * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
+@@ -302,22 +297,13 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
+
+ /* Filter all repeated events from device.
+ We'll do softrepeat in the server, but only since 1.6 */
+- if (value == 2
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
+- && (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
+- ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
+- ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
+- ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
+- ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
+- ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
+-#endif
+- )
+- return;
++ if (value == 2)
++ return;
+
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_KEY;
+- pQueue->key = code;
++ pQueue->detail.key = code;
+ pQueue->val = value;
+ }
+ }
+@@ -327,10 +313,14 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
+ {
+ EventQueuePtr pQueue;
+
++ /* Direct touch devices use server side pointer emulation */
++ if (pInfo->dev->touch && pInfo->dev->touch->mode == XIDirectTouch)
++ return;
++
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_BTN;
+- pQueue->key = button;
++ pQueue->detail.key = button;
+ pQueue->val = value;
+ }
+ }
+@@ -342,11 +332,27 @@ EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_PROXIMITY;
+- pQueue->key = 0;
++ pQueue->detail.key = 0;
+ pQueue->val = value;
+ }
+ }
+
++#ifdef MULTITOUCH
++void
++EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
++ uint16_t evtype)
++{
++ EventQueuePtr pQueue;
++ if ((pQueue = EvdevNextInQueue(pInfo)))
++ {
++ pQueue->type = EV_QUEUE_TOUCH;
++ pQueue->detail.touch = touch;
++ valuator_mask_copy(pQueue->touch_vals, mask);
++ pQueue->val = evtype;
++ }
++}
++#endif
++
+ /**
+ * Post button event right here, right now.
+ * Interface for MB emulation since these need to post immediately.
+@@ -368,41 +374,44 @@ EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
+ }
+ }
+
+-#define ABS_X_VALUE 0x1
+-#define ABS_Y_VALUE 0x2
+-#define ABS_VALUE 0x4
+ /**
+ * Take the valuators and process them accordingly.
+ */
+ static void
+-EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+- int *first_v)
++EvdevProcessValuators(InputInfoPtr pInfo)
+ {
+ int tmp;
+ EvdevPtr pEvdev = pInfo->private;
+-
+- *num_v = *first_v = 0;
++ int *delta = pEvdev->delta;
+
+ /* convert to relative motion for touchpads */
+ if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
+ if (pEvdev->in_proximity) {
+- if (pEvdev->old_vals[0] != -1)
+- pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
+- if (pEvdev->old_vals[1] != -1)
+- pEvdev->delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
+- if (pEvdev->abs_queued & ABS_X_VALUE)
+- pEvdev->old_vals[0] = pEvdev->vals[0];
+- if (pEvdev->abs_queued & ABS_Y_VALUE)
+- pEvdev->old_vals[1] = pEvdev->vals[1];
++ if (valuator_mask_isset(pEvdev->vals, 0))
++ {
++ if (valuator_mask_isset(pEvdev->old_vals, 0))
++ delta[REL_X] = valuator_mask_get(pEvdev->vals, 0) -
++ valuator_mask_get(pEvdev->old_vals, 0);
++ valuator_mask_set(pEvdev->old_vals, 0,
++ valuator_mask_get(pEvdev->vals, 0));
++ }
++ if (valuator_mask_isset(pEvdev->vals, 1))
++ {
++ if (valuator_mask_isset(pEvdev->old_vals, 1))
++ delta[REL_Y] = valuator_mask_get(pEvdev->vals, 1) -
++ valuator_mask_get(pEvdev->old_vals, 1);
++ valuator_mask_set(pEvdev->old_vals, 1,
++ valuator_mask_get(pEvdev->vals, 1));
++ }
+ } else {
+- pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
++ valuator_mask_zero(pEvdev->old_vals);
+ }
++ valuator_mask_zero(pEvdev->vals);
+ pEvdev->abs_queued = 0;
+ pEvdev->rel_queued = 1;
+ }
+
+ if (pEvdev->rel_queued) {
+- int first = REL_CNT, last = -1;
+ int i;
+
+ if (pEvdev->swap_axes) {
+@@ -419,19 +428,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+ {
+ int map = pEvdev->axis_map[i];
+ if (pEvdev->delta[i] && map != -1)
+- {
+- v[map] = pEvdev->delta[i];
+- if (map < first)
+- first = map;
+- if (map > last)
+- last = map;
+- }
+- }
+-
+- if (last >= 0)
+- {
+- *num_v = (last - first + 1);
+- *first_v = first;
++ valuator_mask_set(pEvdev->vals, map, pEvdev->delta[i]);
+ }
+ }
+ /*
+@@ -444,43 +441,46 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+ * just works.
+ */
+ else if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
++ int unswapped_x = valuator_mask_get(pEvdev->vals, 0);
++ int unswapped_y = valuator_mask_get(pEvdev->vals, 1);
++ int i;
+
+- if (pEvdev->swap_axes) {
+- int tmp = v[0];
+- v[0] = xf86ScaleAxis(v[1],
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum,
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum);
+- v[1] = xf86ScaleAxis(tmp,
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum,
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum);
+- }
++ for (i = 0; i <= 1; i++) {
++ int val;
++ int calib_min;
++ int calib_max;
+
+- if (pEvdev->flags & EVDEV_CALIBRATED)
+- {
+- v[0] = xf86ScaleAxis(v[0],
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum,
+- pEvdev->calibration.max_x, pEvdev->calibration.min_x);
+- v[1] = xf86ScaleAxis(v[1],
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum,
+- pEvdev->calibration.max_y, pEvdev->calibration.min_y);
+- }
++ if (!valuator_mask_isset(pEvdev->vals, i))
++ continue;
+
+- if (pEvdev->invert_x)
+- v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
+- pEvdev->absinfo[ABS_X].minimum);
+- if (pEvdev->invert_y)
+- v[1] = (pEvdev->absinfo[ABS_Y].maximum - v[1] +
+- pEvdev->absinfo[ABS_Y].minimum);
++ val = valuator_mask_get(pEvdev->vals, i);
++
++ if (i == 0) {
++ calib_min = pEvdev->calibration.min_x;
++ calib_max = pEvdev->calibration.max_x;
++ } else {
++ calib_min = pEvdev->calibration.min_y;
++ calib_max = pEvdev->calibration.max_y;
++ }
++
++ if (pEvdev->swap_axes)
++ val = xf86ScaleAxis((i == 0 ? unswapped_y : unswapped_x),
++ pEvdev->absinfo[i].maximum,
++ pEvdev->absinfo[i].minimum,
++ pEvdev->absinfo[1 - i].maximum,
++ pEvdev->absinfo[1 - i].minimum);
+
+- *num_v = pEvdev->num_vals;
+- *first_v = 0;
++ if (pEvdev->flags & EVDEV_CALIBRATED)
++ val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum,
++ pEvdev->absinfo[i].minimum, calib_max,
++ calib_min);
++
++ if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y))
++ val = (pEvdev->absinfo[i].maximum - val +
++ pEvdev->absinfo[i].minimum);
++
++ valuator_mask_set(pEvdev->vals, i, val);
++ }
+ }
+ }
+
+@@ -518,11 +518,15 @@ EvdevProcessProximityState(InputInfoPtr pInfo)
+ int prox_state = 0;
+ int i;
+
++ /* Does this device have any proximity axes? */
++ if (!pEvdev->prox)
++ return 0;
++
+ /* no proximity change in the queue */
+ if (!pEvdev->prox_queued)
+ {
+ if (pEvdev->abs_queued && !pEvdev->in_proximity)
+- pEvdev->abs_prox = pEvdev->abs_queued;
++ valuator_mask_copy(pEvdev->prox, pEvdev->vals);
+ return 0;
+ }
+
+@@ -540,10 +544,11 @@ EvdevProcessProximityState(InputInfoPtr pInfo)
+ {
+ /* We're about to go into/out of proximity but have no abs events
+ * within the EV_SYN. Use the last coordinates we have. */
+- if (!pEvdev->abs_queued && pEvdev->abs_prox)
++ if (!pEvdev->abs_queued &&
++ valuator_mask_num_valuators(pEvdev->prox) > 0)
+ {
+- pEvdev->abs_queued = pEvdev->abs_prox;
+- pEvdev->abs_prox = 0;
++ valuator_mask_copy(pEvdev->vals, pEvdev->prox);
++ valuator_mask_zero(pEvdev->prox);
+ }
+ }
+
+@@ -590,6 +595,7 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
+ int value;
+ EvdevPtr pEvdev = pInfo->private;
++ int map;
+
+ /* Get the signed value, earlier kernels had this as unsigned */
+ value = ev->value;
+@@ -622,10 +628,63 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+
+ pEvdev->rel_queued = 1;
+ pEvdev->delta[ev->code] += value;
++ map = pEvdev->axis_map[ev->code];
++ valuator_mask_set(pEvdev->vals, map, value);
+ break;
+ }
+ }
+
++#ifdef MULTITOUCH
++static void
++EvdevProcessTouch(InputInfoPtr pInfo)
++{
++ EvdevPtr pEvdev = pInfo->private;
++
++ if (pEvdev->cur_slot < 0 || !pEvdev->mt_vals ||
++ (!pEvdev->open_slot && !pEvdev->close_slot &&
++ valuator_mask_num_valuators(pEvdev->mt_vals) == 0))
++ return;
++
++ if (pEvdev->close_slot) {
++ EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_vals,
++ XI_TouchEnd);
++ pEvdev->close_slot = 0;
++ } else {
++ EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_vals,
++ pEvdev->open_slot ? XI_TouchBegin :
++ XI_TouchUpdate);
++ pEvdev->open_slot = 0;
++ }
++
++ valuator_mask_zero(pEvdev->mt_vals);
++}
++
++static void
++EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
++{
++ EvdevPtr pEvdev = pInfo->private;
++ int map;
++
++ if (ev->code == ABS_MT_SLOT) {
++ EvdevProcessTouch(pInfo);
++ pEvdev->cur_slot = ev->value;
++ } else if (ev->code == ABS_MT_TRACKING_ID) {
++ if (ev->value >= 0) {
++ pEvdev->open_slot = 1;
++ valuator_mask_copy(pEvdev->mt_vals, pEvdev->cur_vals);
++ } else
++ pEvdev->close_slot = 1;
++ } else {
++ map = pEvdev->axis_map[ev->code] - pEvdev->num_vals;
++ valuator_mask_set(pEvdev->mt_vals, map, ev->value);
++ valuator_mask_set(pEvdev->cur_vals, map, ev->value);
++ }
++}
++#else
++#define EvdevProcessTouch(pInfo)
++#define EvdevProcessTouchEvent(pInfo, ev)
++#endif /* MULTITOUCH */
++
+ /**
+ * Take the absolute motion input event and process it accordingly.
+ */
+@@ -634,6 +693,7 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
+ int value;
+ EvdevPtr pEvdev = pInfo->private;
++ int map;
+
+ /* Get the signed value, earlier kernels had this as unsigned */
+ value = ev->value;
+@@ -648,13 +708,16 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ if (EvdevWheelEmuFilterMotion(pInfo, ev))
+ return;
+
+- pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
+- if (ev->code == ABS_X)
+- pEvdev->abs_queued |= ABS_X_VALUE;
+- else if (ev->code == ABS_Y)
+- pEvdev->abs_queued |= ABS_Y_VALUE;
+- else
+- pEvdev->abs_queued |= ABS_VALUE;
++ if (ev->code >= ABS_MT_SLOT) {
++ EvdevProcessTouchEvent(pInfo, ev);
++ pEvdev->abs_queued = 1;
++ }
++ /* Direct touch devices use server side pointer emulation */
++ else if (!pInfo->dev->touch || pInfo->dev->touch->mode != XIDirectTouch) {
++ map = pEvdev->axis_map[ev->code];
++ valuator_mask_set(pEvdev->vals, map, value);
++ pEvdev->abs_queued = 1;
++ }
+ }
+
+ /**
+@@ -712,7 +775,7 @@ EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ EvdevPtr pEvdev = pInfo->private;
+
+ if (pEvdev->rel_queued) {
+- xf86PostMotionEventP(pInfo->dev, FALSE, first_v, num_v, v + first_v);
++ xf86PostMotionEventM(pInfo->dev, FALSE, pEvdev->vals);
+ }
+ }
+
+@@ -735,7 +798,7 @@ EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ * this scheme still just work.
+ */
+ if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- xf86PostMotionEventP(pInfo->dev, TRUE, first_v, num_v, v + first_v);
++ xf86PostMotionEventM(pInfo->dev, TRUE, pEvdev->vals);
+ }
+ }
+
+@@ -750,6 +813,9 @@ EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v,
+ switch (pEvdev->queue[i].type) {
+ case EV_QUEUE_KEY:
+ case EV_QUEUE_BTN:
++#ifdef MULTITOUCH
++ case EV_QUEUE_TOUCH:
++#endif
+ break;
+ case EV_QUEUE_PROXIMITY:
+ if (pEvdev->queue[i].val == which)
+@@ -772,23 +838,28 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ for (i = 0; i < pEvdev->num_queue; i++) {
+ switch (pEvdev->queue[i].type) {
+ case EV_QUEUE_KEY:
+- xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key,
++ xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val);
+ break;
+ case EV_QUEUE_BTN:
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 11
+ if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- xf86PostButtonEventP(pInfo->dev, 1, pEvdev->queue[i].key,
++ xf86PostButtonEventP(pInfo->dev, 1, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val, first_v, num_v,
+ v + first_v);
+
+ } else
+-#endif
+- xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key,
++ xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val, 0, 0);
+ break;
+ case EV_QUEUE_PROXIMITY:
+ break;
++#ifdef MULTITOUCH
++ case EV_QUEUE_TOUCH:
++ xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch,
++ pEvdev->queue[i].val, 0,
++ pEvdev->queue[i].touch_vals);
++ break;
++#endif
+ }
+ }
+ }
+@@ -806,7 +877,8 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
+
+ EvdevProcessProximityState(pInfo);
+
+- EvdevProcessValuators(pInfo, v, &num_v, &first_v);
++ EvdevProcessValuators(pInfo);
++ EvdevProcessTouch(pInfo);
+
+ EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v);
+ EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
+@@ -815,7 +887,8 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
+ EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v);
+
+ memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
+- memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
++ if (pEvdev->vals)
++ valuator_mask_zero(pEvdev->vals);
+ pEvdev->num_queue = 0;
+ pEvdev->abs_queued = 0;
+ pEvdev->rel_queued = 0;
+@@ -861,7 +934,17 @@ EvdevReadInput(InputInfoPtr pInfo)
+
+ while (len == sizeof(ev))
+ {
+- len = read(pInfo->fd, &ev, sizeof(ev));
++#ifdef MULTITOUCH
++ EvdevPtr pEvdev = pInfo->private;
++
++ if (pEvdev->mtdev)
++ len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
++ sizeof(struct input_event);
++ else
++ len = read(pInfo->fd, &ev, sizeof(ev));
++#else
++ len = read(pInfo->fd, &ev, sizeof(ev));
++#endif
+ if (len <= 0)
+ {
+ if (errno == ENODEV) /* May happen after resume */
+@@ -900,317 +983,6 @@ EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
+ /* Nothing to do, dix handles all settings */
+ }
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+-static KeySym map[] = {
+- /* 0x00 */ NoSymbol, NoSymbol,
+- /* 0x01 */ XK_Escape, NoSymbol,
+- /* 0x02 */ XK_1, XK_exclam,
+- /* 0x03 */ XK_2, XK_at,
+- /* 0x04 */ XK_3, XK_numbersign,
+- /* 0x05 */ XK_4, XK_dollar,
+- /* 0x06 */ XK_5, XK_percent,
+- /* 0x07 */ XK_6, XK_asciicircum,
+- /* 0x08 */ XK_7, XK_ampersand,
+- /* 0x09 */ XK_8, XK_asterisk,
+- /* 0x0a */ XK_9, XK_parenleft,
+- /* 0x0b */ XK_0, XK_parenright,
+- /* 0x0c */ XK_minus, XK_underscore,
+- /* 0x0d */ XK_equal, XK_plus,
+- /* 0x0e */ XK_BackSpace, NoSymbol,
+- /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,
+- /* 0x10 */ XK_Q, NoSymbol,
+- /* 0x11 */ XK_W, NoSymbol,
+- /* 0x12 */ XK_E, NoSymbol,
+- /* 0x13 */ XK_R, NoSymbol,
+- /* 0x14 */ XK_T, NoSymbol,
+- /* 0x15 */ XK_Y, NoSymbol,
+- /* 0x16 */ XK_U, NoSymbol,
+- /* 0x17 */ XK_I, NoSymbol,
+- /* 0x18 */ XK_O, NoSymbol,
+- /* 0x19 */ XK_P, NoSymbol,
+- /* 0x1a */ XK_bracketleft, XK_braceleft,
+- /* 0x1b */ XK_bracketright,XK_braceright,
+- /* 0x1c */ XK_Return, NoSymbol,
+- /* 0x1d */ XK_Control_L, NoSymbol,
+- /* 0x1e */ XK_A, NoSymbol,
+- /* 0x1f */ XK_S, NoSymbol,
+- /* 0x20 */ XK_D, NoSymbol,
+- /* 0x21 */ XK_F, NoSymbol,
+- /* 0x22 */ XK_G, NoSymbol,
+- /* 0x23 */ XK_H, NoSymbol,
+- /* 0x24 */ XK_J, NoSymbol,
+- /* 0x25 */ XK_K, NoSymbol,
+- /* 0x26 */ XK_L, NoSymbol,
+- /* 0x27 */ XK_semicolon, XK_colon,
+- /* 0x28 */ XK_quoteright, XK_quotedbl,
+- /* 0x29 */ XK_quoteleft, XK_asciitilde,
+- /* 0x2a */ XK_Shift_L, NoSymbol,
+- /* 0x2b */ XK_backslash, XK_bar,
+- /* 0x2c */ XK_Z, NoSymbol,
+- /* 0x2d */ XK_X, NoSymbol,
+- /* 0x2e */ XK_C, NoSymbol,
+- /* 0x2f */ XK_V, NoSymbol,
+- /* 0x30 */ XK_B, NoSymbol,
+- /* 0x31 */ XK_N, NoSymbol,
+- /* 0x32 */ XK_M, NoSymbol,
+- /* 0x33 */ XK_comma, XK_less,
+- /* 0x34 */ XK_period, XK_greater,
+- /* 0x35 */ XK_slash, XK_question,
+- /* 0x36 */ XK_Shift_R, NoSymbol,
+- /* 0x37 */ XK_KP_Multiply, NoSymbol,
+- /* 0x38 */ XK_Alt_L, XK_Meta_L,
+- /* 0x39 */ XK_space, NoSymbol,
+- /* 0x3a */ XK_Caps_Lock, NoSymbol,
+- /* 0x3b */ XK_F1, NoSymbol,
+- /* 0x3c */ XK_F2, NoSymbol,
+- /* 0x3d */ XK_F3, NoSymbol,
+- /* 0x3e */ XK_F4, NoSymbol,
+- /* 0x3f */ XK_F5, NoSymbol,
+- /* 0x40 */ XK_F6, NoSymbol,
+- /* 0x41 */ XK_F7, NoSymbol,
+- /* 0x42 */ XK_F8, NoSymbol,
+- /* 0x43 */ XK_F9, NoSymbol,
+- /* 0x44 */ XK_F10, NoSymbol,
+- /* 0x45 */ XK_Num_Lock, NoSymbol,
+- /* 0x46 */ XK_Scroll_Lock, NoSymbol,
+- /* These KP keys should have the KP_7 keysyms in the numlock
+- * modifer... ? */
+- /* 0x47 */ XK_KP_Home, XK_KP_7,
+- /* 0x48 */ XK_KP_Up, XK_KP_8,
+- /* 0x49 */ XK_KP_Prior, XK_KP_9,
+- /* 0x4a */ XK_KP_Subtract, NoSymbol,
+- /* 0x4b */ XK_KP_Left, XK_KP_4,
+- /* 0x4c */ XK_KP_Begin, XK_KP_5,
+- /* 0x4d */ XK_KP_Right, XK_KP_6,
+- /* 0x4e */ XK_KP_Add, NoSymbol,
+- /* 0x4f */ XK_KP_End, XK_KP_1,
+- /* 0x50 */ XK_KP_Down, XK_KP_2,
+- /* 0x51 */ XK_KP_Next, XK_KP_3,
+- /* 0x52 */ XK_KP_Insert, XK_KP_0,
+- /* 0x53 */ XK_KP_Delete, XK_KP_Decimal,
+- /* 0x54 */ NoSymbol, NoSymbol,
+- /* 0x55 */ XK_F13, NoSymbol,
+- /* 0x56 */ XK_less, XK_greater,
+- /* 0x57 */ XK_F11, NoSymbol,
+- /* 0x58 */ XK_F12, NoSymbol,
+- /* 0x59 */ XK_F14, NoSymbol,
+- /* 0x5a */ XK_F15, NoSymbol,
+- /* 0x5b */ XK_F16, NoSymbol,
+- /* 0x5c */ XK_F17, NoSymbol,
+- /* 0x5d */ XK_F18, NoSymbol,
+- /* 0x5e */ XK_F19, NoSymbol,
+- /* 0x5f */ XK_F20, NoSymbol,
+- /* 0x60 */ XK_KP_Enter, NoSymbol,
+- /* 0x61 */ XK_Control_R, NoSymbol,
+- /* 0x62 */ XK_KP_Divide, NoSymbol,
+- /* 0x63 */ XK_Print, XK_Sys_Req,
+- /* 0x64 */ XK_Alt_R, XK_Meta_R,
+- /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */
+- /* 0x66 */ XK_Home, NoSymbol,
+- /* 0x67 */ XK_Up, NoSymbol,
+- /* 0x68 */ XK_Prior, NoSymbol,
+- /* 0x69 */ XK_Left, NoSymbol,
+- /* 0x6a */ XK_Right, NoSymbol,
+- /* 0x6b */ XK_End, NoSymbol,
+- /* 0x6c */ XK_Down, NoSymbol,
+- /* 0x6d */ XK_Next, NoSymbol,
+- /* 0x6e */ XK_Insert, NoSymbol,
+- /* 0x6f */ XK_Delete, NoSymbol,
+- /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */
+- /* 0x71 */ NoSymbol, NoSymbol,
+- /* 0x72 */ NoSymbol, NoSymbol,
+- /* 0x73 */ NoSymbol, NoSymbol,
+- /* 0x74 */ NoSymbol, NoSymbol,
+- /* 0x75 */ XK_KP_Equal, NoSymbol,
+- /* 0x76 */ NoSymbol, NoSymbol,
+- /* 0x77 */ NoSymbol, NoSymbol,
+- /* 0x78 */ XK_F21, NoSymbol,
+- /* 0x79 */ XK_F22, NoSymbol,
+- /* 0x7a */ XK_F23, NoSymbol,
+- /* 0x7b */ XK_F24, NoSymbol,
+- /* 0x7c */ XK_KP_Separator, NoSymbol,
+- /* 0x7d */ XK_Meta_L, NoSymbol,
+- /* 0x7e */ XK_Meta_R, NoSymbol,
+- /* 0x7f */ XK_Multi_key, NoSymbol,
+- /* 0x80 */ NoSymbol, NoSymbol,
+- /* 0x81 */ NoSymbol, NoSymbol,
+- /* 0x82 */ NoSymbol, NoSymbol,
+- /* 0x83 */ NoSymbol, NoSymbol,
+- /* 0x84 */ NoSymbol, NoSymbol,
+- /* 0x85 */ NoSymbol, NoSymbol,
+- /* 0x86 */ NoSymbol, NoSymbol,
+- /* 0x87 */ NoSymbol, NoSymbol,
+- /* 0x88 */ NoSymbol, NoSymbol,
+- /* 0x89 */ NoSymbol, NoSymbol,
+- /* 0x8a */ NoSymbol, NoSymbol,
+- /* 0x8b */ NoSymbol, NoSymbol,
+- /* 0x8c */ NoSymbol, NoSymbol,
+- /* 0x8d */ NoSymbol, NoSymbol,
+- /* 0x8e */ NoSymbol, NoSymbol,
+- /* 0x8f */ NoSymbol, NoSymbol,
+- /* 0x90 */ NoSymbol, NoSymbol,
+- /* 0x91 */ NoSymbol, NoSymbol,
+- /* 0x92 */ NoSymbol, NoSymbol,
+- /* 0x93 */ NoSymbol, NoSymbol,
+- /* 0x94 */ NoSymbol, NoSymbol,
+- /* 0x95 */ NoSymbol, NoSymbol,
+- /* 0x96 */ NoSymbol, NoSymbol,
+- /* 0x97 */ NoSymbol, NoSymbol,
+- /* 0x98 */ NoSymbol, NoSymbol,
+- /* 0x99 */ NoSymbol, NoSymbol,
+- /* 0x9a */ NoSymbol, NoSymbol,
+- /* 0x9b */ NoSymbol, NoSymbol,
+- /* 0x9c */ NoSymbol, NoSymbol,
+- /* 0x9d */ NoSymbol, NoSymbol,
+- /* 0x9e */ NoSymbol, NoSymbol,
+- /* 0x9f */ NoSymbol, NoSymbol,
+- /* 0xa0 */ NoSymbol, NoSymbol,
+- /* 0xa1 */ NoSymbol, NoSymbol,
+- /* 0xa2 */ NoSymbol, NoSymbol,
+- /* 0xa3 */ NoSymbol, NoSymbol,
+- /* 0xa4 */ NoSymbol, NoSymbol,
+- /* 0xa5 */ NoSymbol, NoSymbol,
+- /* 0xa6 */ NoSymbol, NoSymbol,
+- /* 0xa7 */ NoSymbol, NoSymbol,
+- /* 0xa8 */ NoSymbol, NoSymbol,
+- /* 0xa9 */ NoSymbol, NoSymbol,
+- /* 0xaa */ NoSymbol, NoSymbol,
+- /* 0xab */ NoSymbol, NoSymbol,
+- /* 0xac */ NoSymbol, NoSymbol,
+- /* 0xad */ NoSymbol, NoSymbol,
+- /* 0xae */ NoSymbol, NoSymbol,
+- /* 0xaf */ NoSymbol, NoSymbol,
+- /* 0xb0 */ NoSymbol, NoSymbol,
+- /* 0xb1 */ NoSymbol, NoSymbol,
+- /* 0xb2 */ NoSymbol, NoSymbol,
+- /* 0xb3 */ NoSymbol, NoSymbol,
+- /* 0xb4 */ NoSymbol, NoSymbol,
+- /* 0xb5 */ NoSymbol, NoSymbol,
+- /* 0xb6 */ NoSymbol, NoSymbol,
+- /* 0xb7 */ NoSymbol, NoSymbol,
+- /* 0xb8 */ NoSymbol, NoSymbol,
+- /* 0xb9 */ NoSymbol, NoSymbol,
+- /* 0xba */ NoSymbol, NoSymbol,
+- /* 0xbb */ NoSymbol, NoSymbol,
+- /* 0xbc */ NoSymbol, NoSymbol,
+- /* 0xbd */ NoSymbol, NoSymbol,
+- /* 0xbe */ NoSymbol, NoSymbol,
+- /* 0xbf */ NoSymbol, NoSymbol,
+- /* 0xc0 */ NoSymbol, NoSymbol,
+- /* 0xc1 */ NoSymbol, NoSymbol,
+- /* 0xc2 */ NoSymbol, NoSymbol,
+- /* 0xc3 */ NoSymbol, NoSymbol,
+- /* 0xc4 */ NoSymbol, NoSymbol,
+- /* 0xc5 */ NoSymbol, NoSymbol,
+- /* 0xc6 */ NoSymbol, NoSymbol,
+- /* 0xc7 */ NoSymbol, NoSymbol,
+- /* 0xc8 */ NoSymbol, NoSymbol,
+- /* 0xc9 */ NoSymbol, NoSymbol,
+- /* 0xca */ NoSymbol, NoSymbol,
+- /* 0xcb */ NoSymbol, NoSymbol,
+- /* 0xcc */ NoSymbol, NoSymbol,
+- /* 0xcd */ NoSymbol, NoSymbol,
+- /* 0xce */ NoSymbol, NoSymbol,
+- /* 0xcf */ NoSymbol, NoSymbol,
+- /* 0xd0 */ NoSymbol, NoSymbol,
+- /* 0xd1 */ NoSymbol, NoSymbol,
+- /* 0xd2 */ NoSymbol, NoSymbol,
+- /* 0xd3 */ NoSymbol, NoSymbol,
+- /* 0xd4 */ NoSymbol, NoSymbol,
+- /* 0xd5 */ NoSymbol, NoSymbol,
+- /* 0xd6 */ NoSymbol, NoSymbol,
+- /* 0xd7 */ NoSymbol, NoSymbol,
+- /* 0xd8 */ NoSymbol, NoSymbol,
+- /* 0xd9 */ NoSymbol, NoSymbol,
+- /* 0xda */ NoSymbol, NoSymbol,
+- /* 0xdb */ NoSymbol, NoSymbol,
+- /* 0xdc */ NoSymbol, NoSymbol,
+- /* 0xdd */ NoSymbol, NoSymbol,
+- /* 0xde */ NoSymbol, NoSymbol,
+- /* 0xdf */ NoSymbol, NoSymbol,
+- /* 0xe0 */ NoSymbol, NoSymbol,
+- /* 0xe1 */ NoSymbol, NoSymbol,
+- /* 0xe2 */ NoSymbol, NoSymbol,
+- /* 0xe3 */ NoSymbol, NoSymbol,
+- /* 0xe4 */ NoSymbol, NoSymbol,
+- /* 0xe5 */ NoSymbol, NoSymbol,
+- /* 0xe6 */ NoSymbol, NoSymbol,
+- /* 0xe7 */ NoSymbol, NoSymbol,
+- /* 0xe8 */ NoSymbol, NoSymbol,
+- /* 0xe9 */ NoSymbol, NoSymbol,
+- /* 0xea */ NoSymbol, NoSymbol,
+- /* 0xeb */ NoSymbol, NoSymbol,
+- /* 0xec */ NoSymbol, NoSymbol,
+- /* 0xed */ NoSymbol, NoSymbol,
+- /* 0xee */ NoSymbol, NoSymbol,
+- /* 0xef */ NoSymbol, NoSymbol,
+- /* 0xf0 */ NoSymbol, NoSymbol,
+- /* 0xf1 */ NoSymbol, NoSymbol,
+- /* 0xf2 */ NoSymbol, NoSymbol,
+- /* 0xf3 */ NoSymbol, NoSymbol,
+- /* 0xf4 */ NoSymbol, NoSymbol,
+- /* 0xf5 */ NoSymbol, NoSymbol,
+- /* 0xf6 */ NoSymbol, NoSymbol,
+- /* 0xf7 */ NoSymbol, NoSymbol,
+-};
+-
+-static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
+- { XK_Shift_L, ShiftMask },
+- { XK_Shift_R, ShiftMask },
+- { XK_Control_L, ControlMask },
+- { XK_Control_R, ControlMask },
+- { XK_Caps_Lock, LockMask },
+- { XK_Alt_L, AltMask },
+- { XK_Alt_R, AltMask },
+- { XK_Meta_L, Mod4Mask },
+- { XK_Meta_R, Mod4Mask },
+- { XK_Num_Lock, NumLockMask },
+- { XK_Scroll_Lock, ScrollLockMask },
+- { XK_Mode_switch, AltLangMask }
+-};
+-
+-/* Server 1.6 and earlier */
+-static int
+-EvdevInitKeysyms(DeviceIntPtr device)
+-{
+- InputInfoPtr pInfo;
+- EvdevPtr pEvdev;
+- KeySymsRec keySyms;
+- CARD8 modMap[MAP_LENGTH];
+- KeySym sym;
+- int i, j;
+-
+- pInfo = device->public.devicePrivate;
+- pEvdev = pInfo->private;
+-
+- /* Compute the modifier map */
+- memset(modMap, 0, sizeof modMap);
+-
+- for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
+- sym = map[i * GLYPHS_PER_KEY];
+- for (j = 0; j < ArrayLength(modifiers); j++) {
+- if (modifiers[j].keysym == sym)
+- modMap[i + MIN_KEYCODE] = modifiers[j].mask;
+- }
+- }
+-
+- keySyms.map = map;
+- keySyms.mapWidth = GLYPHS_PER_KEY;
+- keySyms.minKeyCode = MIN_KEYCODE;
+- keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
+-
+- XkbSetRulesDflts(pEvdev->rmlvo.rules, pEvdev->rmlvo.model,
+- pEvdev->rmlvo.layout, pEvdev->rmlvo.variant,
+- pEvdev->rmlvo.options);
+- if (!XkbInitKeyboardDeviceStruct(device, &pEvdev->xkbnames,
+- &keySyms, modMap, NULL,
+- EvdevKbdCtrl))
+- return 0;
+-
+- return 1;
+-}
+-#endif
+-
+ static void
+ EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
+ {
+@@ -1263,14 +1035,8 @@ EvdevAddKeyClass(DeviceIntPtr device)
+ if (!pEvdev->rmlvo.options)
+ SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
+ if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
+ return !Success;
+-#else
+- if (!EvdevInitKeysyms(device))
+- return !Success;
+-
+-#endif
+
+ return Success;
+ }
+@@ -1280,53 +1046,114 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ {
+ InputInfoPtr pInfo;
+ EvdevPtr pEvdev;
+- int num_axes, axis, i = 0;
++ int num_axes, num_mt_axes, axis, i = 0;
+ Atom *atoms;
+
+ pInfo = device->public.devicePrivate;
+ pEvdev = pInfo->private;
+
+ if (!TestBit(EV_ABS, pEvdev->bitmask))
+- return !Success;
++ goto out;
+
+- num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
+- if (num_axes < 1)
+- return !Success;
++ num_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MT_SLOT);
++ num_mt_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_CNT) - num_axes;
+
+ if (num_axes > MAX_VALUATORS) {
+ xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
+ num_axes = MAX_VALUATORS;
+ }
+
++#ifdef MULTITOUCH
++ if (TestBit(ABS_MT_SLOT, pEvdev->abs_bitmask))
++ num_mt_axes--;
++ if (TestBit(ABS_MT_TRACKING_ID, pEvdev->abs_bitmask))
++ num_mt_axes--;
++
++ if (num_mt_axes > MAX_VALUATORS) {
++ xf86Msg(X_WARNING, "%s: found %d MT axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
++ num_mt_axes = MAX_VALUATORS;
++ }
++#endif
++
++ if (num_axes < 1 && num_mt_axes < 1) {
++ xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
++ device->name);
++ goto out;
++ }
++
+ pEvdev->num_vals = num_axes;
+- memset(pEvdev->vals, 0, num_axes * sizeof(int));
+- memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
+- atoms = malloc(pEvdev->num_vals * sizeof(Atom));
++ if (num_axes > 0) {
++ pEvdev->vals = valuator_mask_new(num_axes);
++ pEvdev->old_vals = valuator_mask_new(num_axes);
++ if (!pEvdev->vals || !pEvdev->old_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate valuator masks.\n",
++ device->name);
++ goto out;
++ }
++ }
++#ifdef MULTITOUCH
++ pEvdev->num_mt_vals = num_mt_axes;
++ if (num_mt_axes > 0) {
++ pEvdev->mt_vals = valuator_mask_new(num_mt_axes);
++ pEvdev->cur_vals = valuator_mask_new(num_mt_axes);
++ if (!pEvdev->mt_vals || !pEvdev->cur_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
++ device->name);
++ goto out;
++ }
+
++ for (i = 0; i < EVDEV_MAXQUEUE; i++) {
++ pEvdev->queue[i].touch_vals =
++ valuator_mask_new(num_mt_axes);
++ if (!pEvdev->queue[i].touch_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
++ "evdev event queue.\n", device->name);
++ goto out;
++ }
++ }
++ }
++#endif
++ atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom));
++
++ i = 0;
+ for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
+ pEvdev->axis_map[axis] = -1;
+- if (!TestBit(axis, pEvdev->abs_bitmask))
++ if (!TestBit(axis, pEvdev->abs_bitmask) || axis == ABS_MT_SLOT ||
++ axis == ABS_MT_TRACKING_ID)
+ continue;
+ pEvdev->axis_map[axis] = i;
+ i++;
+ }
+
+- EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
++ EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms);
+
+- if (!InitValuatorClassDeviceStruct(device, num_axes,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- atoms,
+-#endif
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+- GetMotionHistory,
+-#endif
++ if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
+ GetMotionHistorySize(), Absolute)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize valuator class device.\n",
+ device->name);
+- return !Success;
++ goto out;
++ }
++
++#ifdef MULTITOUCH
++ if (num_mt_axes > 0)
++ {
++ int num_touches = 10;
++ int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
++ XIDependentTouch : XIDirectTouch;
++
++ if (pEvdev->mtdev->caps.slot.maximum > 0)
++ num_touches = pEvdev->mtdev->caps.slot.maximum;
++
++ if (!InitTouchClassDeviceStruct(device, num_touches, mode,
++ num_mt_axes)) {
++ xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
++ device->name);
++ goto out;
++ }
+ }
++#endif
+
+- for (axis = ABS_X; axis <= ABS_MAX; axis++) {
++ for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) {
+ int axnum = pEvdev->axis_map[axis];
+ int resolution = 10000;
+
+@@ -1340,20 +1167,32 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ #endif
+
+ xf86InitValuatorAxisStruct(device, axnum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+ atoms[axnum],
+-#endif
+ pEvdev->absinfo[axis].minimum,
+ pEvdev->absinfo[axis].maximum,
+- resolution, 0, resolution
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- , Absolute
+-#endif
+- );
++ resolution, 0, resolution, Absolute);
+ xf86InitValuatorDefaults(device, axnum);
+- pEvdev->old_vals[axnum] = -1;
+ }
+
++#ifdef MULTITOUCH
++ for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
++ int axnum = pEvdev->axis_map[axis] - pEvdev->num_vals;
++ int resolution = 10000;
++
++ if (axnum < 0)
++ continue;
++
++ if (pEvdev->absinfo[axis].resolution)
++ resolution = pEvdev->absinfo[axis].resolution * 1000;
++
++ xf86InitTouchValuatorAxisStruct(device, axnum,
++ atoms[axnum + pEvdev->num_vals],
++ pEvdev->absinfo[axis].minimum,
++ pEvdev->absinfo[axis].maximum,
++ pEvdev->absinfo[axis].resolution);
++ }
++#endif
++
+ free(atoms);
+
+ for (i = 0; i < ArrayLength(proximity_bits); i++)
+@@ -1364,6 +1203,12 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ if (TestBit(proximity_bits[i], pEvdev->key_bitmask))
+ {
+ InitProximityClassDeviceStruct(device);
++ pEvdev->prox = valuator_mask_new(num_axes);
++ if (!pEvdev->prox) {
++ xf86Msg(X_ERROR, "%s: failed to allocate proximity valuator "
++ "mask.\n", device->name);
++ goto out;
++ }
+ break;
+ }
+ }
+@@ -1371,7 +1216,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize pointer feedback class "
+ "device.\n", device->name);
+- return !Success;
++ goto out;
+ }
+
+ if (pEvdev->flags & EVDEV_TOUCHPAD)
+@@ -1393,6 +1238,18 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ }
+
+ return Success;
++
++out:
++#ifdef MULTITOUCH
++ valuator_mask_free(&pEvdev->mt_vals);
++ valuator_mask_free(&pEvdev->cur_vals);
++ for (i = 0; i < EVDEV_MAXQUEUE; i++)
++ valuator_mask_free(&pEvdev->queue[i].touch_vals);
++#endif
++ valuator_mask_free(&pEvdev->vals);
++ valuator_mask_free(&pEvdev->old_vals);
++ valuator_mask_free(&pEvdev->prox);
++ return !Success;
+ }
+
+ static int
+@@ -1407,11 +1264,11 @@ EvdevAddRelClass(DeviceIntPtr device)
+ pEvdev = pInfo->private;
+
+ if (!TestBit(EV_REL, pEvdev->bitmask))
+- return !Success;
++ goto out;
+
+ num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
+ if (num_axes < 1)
+- return !Success;
++ goto out;
+
+ /* Wheels are special, we post them as button events. So let's ignore them
+ * in the axes list too */
+@@ -1423,7 +1280,7 @@ EvdevAddRelClass(DeviceIntPtr device)
+ num_axes--;
+
+ if (num_axes <= 0)
+- return !Success;
++ goto out;
+
+ if (num_axes > MAX_VALUATORS) {
+ xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
+@@ -1431,7 +1288,11 @@ EvdevAddRelClass(DeviceIntPtr device)
+ }
+
+ pEvdev->num_vals = num_axes;
+- memset(pEvdev->vals, 0, num_axes * sizeof(int));
++ if (num_axes > 0) {
++ pEvdev->vals = valuator_mask_new(num_axes);
++ if (!pEvdev->vals)
++ goto out;
++ }
+ atoms = malloc(pEvdev->num_vals * sizeof(Atom));
+
+ for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++)
+@@ -1448,23 +1309,17 @@ EvdevAddRelClass(DeviceIntPtr device)
+
+ EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
+
+- if (!InitValuatorClassDeviceStruct(device, num_axes,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- atoms,
+-#endif
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+- GetMotionHistory,
+-#endif
++ if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
+ GetMotionHistorySize(), Relative)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize valuator class device.\n",
+ device->name);
+- return !Success;
++ goto out;
+ }
+
+ if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize pointer feedback class "
+ "device.\n", device->name);
+- return !Success;
++ goto out;
+ }
+
+ for (axis = REL_X; axis <= REL_MAX; axis++)
+@@ -1473,21 +1328,18 @@ EvdevAddRelClass(DeviceIntPtr device)
+
+ if (axnum == -1)
+ continue;
+- xf86InitValuatorAxisStruct(device, axnum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- atoms[axnum],
+-#endif
+- -1, -1, 1, 0, 1
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- , Relative
+-#endif
+- );
++ xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], -1, -1, 1, 0, 1,
++ Relative);
+ xf86InitValuatorDefaults(device, axnum);
+ }
+
+ free(atoms);
+
+ return Success;
++
++out:
++ valuator_mask_free(&pEvdev->vals);
++ return !Success;
+ }
+
+ static int
+@@ -1503,10 +1355,7 @@ EvdevAddButtonClass(DeviceIntPtr device)
+ labels = malloc(pEvdev->num_buttons * sizeof(Atom));
+ EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
+
+- if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- labels,
+-#endif
++ if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, labels,
+ pEvdev->btnmap))
+ return !Success;
+
+@@ -1678,7 +1527,6 @@ EvdevInit(DeviceIntPtr device)
+ else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
+ EvdevInitAbsClass(device, pEvdev);
+
+-#ifdef HAVE_PROPERTIES
+ /* We drop the return value, the only time we ever want the handlers to
+ * unregister is when the device dies. In which case we don't have to
+ * unregister anyway */
+@@ -1687,7 +1535,6 @@ EvdevInit(DeviceIntPtr device)
+ EvdevMBEmuInitProperty(device);
+ EvdevWheelEmuInitProperty(device);
+ EvdevDragLockInitProperty(device);
+-#endif
+
+ return Success;
+ }
+@@ -1726,6 +1573,9 @@ EvdevProc(Device