From 05e2888845ef46a6851eeb8817811e7f2a5172f1 Mon Sep 17 00:00:00 2001 From: Andreas Willich Date: Sat, 6 Aug 2011 22:56:54 +0200 Subject: ebuild push --- dev-libs/glib/Manifest | 31 + dev-libs/glib/files/glib-1.2.10-automake.patch | 29 + .../glib/files/glib-1.2.10-configure-LANG.patch | 44 + dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch | 41 + dev-libs/glib/files/glib-1.2.10-m4.patch | 9 + .../glib/files/glib-2.10.3-ia64-atomic-ops.patch | 39 + dev-libs/glib/files/glib-2.12.12-fbsd.patch | 21 + ...karound-gio-test-failure-without-userpriv.patch | 20 + .../glib/files/glib-2.24-assert-test-failure.patch | 19 + .../glib/files/glib-2.24-punt-python-check.patch | 20 + .../glib/files/glib-2.25-punt-python-check.patch | 20 + .../glib-2.25-skip-tests-with-dbus-keyring.patch | 22 + ...glib-2.26.0-disable-locale-sensitive-test.patch | 50 + ...-2.26.0-disable-volumemonitor-broken-test.patch | 43 + .../glib/files/glib-2.26.1-deprecation-tests.patch | 43 + .../glib/files/glib-2.26.1-gatomic-header.patch | 11 + .../glib/files/glib-2.26.1-gdatetime-test.patch | 21 + .../glib/files/glib-2.26.1-gdbus-flushes.patch | 64 + .../glib/files/glib-2.26.1-gsettings-read.patch | 25 + .../glib/files/glib-2.26.1-gsettings-rules.patch | 33 + .../glib/files/glib-2.26.1-locked-message.patch | 68 + .../files/glib-2.28.2-gio_launch_handler.patch | 234 + dev-libs/glib/glib-2.28.5-r1.ebuild | 176 + dev-libs/glib/glib-2.28.6-r1.ebuild | 176 + dev-libs/glib/glib-2.28.7-r1.ebuild | 176 + dev-libs/glib/glib-2.28.8-r1.ebuild | 203 + dev-libs/glib/metadata.xml | 10 + dev-util/editje/Manifest | 1 + dev-util/editje/editje-9999.ebuild | 14 + net-wireless/rt3572usb/Manifest | 7 + .../files/rt3572usb-2.5.0.0-Makefile.patch | 11 + .../files/rt3572usb-2.5.0.0-config.mk.patch | 15 + .../files/rt3572usb-2.5.0.0-nodebug.patch | 11 + .../files/rt3572usb-2.5.0.0-rt_linux.h.patch | 13 + .../files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch | 19 + net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild | 74 + x11-apps/ccv-bin/Manifest | 3 + x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild | 54 + x11-apps/ginn/Manifest | 2 + x11-apps/ginn/ginn-0.2.4.ebuild | 27 + x11-base/xorg-server/Manifest | 25 + x11-base/xorg-server/files/diff | 26 + x11-base/xorg-server/files/xdm-setup.initd-1 | 14 + x11-base/xorg-server/files/xdm.confd-3 | 16 + x11-base/xorg-server/files/xdm.initd-3 | 213 + .../xorg-server/files/xorg-server-1.10.2-xi2.patch | 4569 ++++++++++++++++++++ .../files/xorg-server-1.9-nouveau-default.patch | 30 + .../files/xorg-server-disable-acpi.patch | 31 + .../files/xorg-server-gestures-extension.patch | 1488 +++++++ .../xorg-server-xf86CoordinatesToWindow.patch | 97 + x11-base/xorg-server/files/xorg-server-xi2.patch | 4568 +++++++++++++++++++ x11-base/xorg-server/files/xorg-sets.conf | 6 + x11-base/xorg-server/metadata.xml | 12 + .../xorg-server/xorg-server-1.10.0.901-r1.ebuild | 254 ++ .../xorg-server/xorg-server-1.10.0.902-r1.ebuild | 254 ++ x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild | 254 ++ .../xorg-server/xorg-server-1.10.1.901-r1.ebuild | 241 ++ x11-base/xorg-server/xorg-server-1.10.1.ebuild | 250 ++ x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild | 240 + x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild | 249 ++ x11-drivers/xf86-input-evdev/Manifest | 4 + .../files/xf86-input-evdev-gestures.patch | 664 +++ .../files/xf86-input-evdev-xi2.1.patch | 1678 +++++++ .../xf86-input-evdev-2.6.0-r1.ebuild | 33 + x11-libs/bamf/Manifest | 2 + x11-libs/bamf/bamf-0.2.70.ebuild | 40 + x11-libs/libXi/Manifest | 5 + x11-libs/libXi/files/libXi-xi2.1.patch | 355 ++ x11-libs/libXi/libXi-1.4.2-r1.ebuild | 42 + x11-libs/libXi/libXi-1.4.3.ebuild | 44 + x11-libs/mtdev/Manifest | 2 + x11-libs/mtdev/mtdev-1.1.0.ebuild | 21 + x11-libs/utouch-evemu/Manifest | 2 + x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild | 21 + x11-libs/utouch-frame/Manifest | 2 + x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild | 26 + x11-libs/utouch-geis/Manifest | 6 + x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild | 26 + x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild | 26 + x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild | 26 + x11-libs/utouch-grail/Manifest | 2 + x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild | 28 + x11-plugins/e_modules-itask/Manifest | 3 + .../e_modules-itask/e_modules-itask-9999.ebuild | 16 + x11-plugins/e_modules-itask/metadata.xml | 8 + x11-proto/inputproto/Manifest | 6 + .../inputproto/files/inputproto-2.0.1-xi2.1.patch | 943 ++++ .../inputproto/files/inputproto-2.0.2-xi2.1.patch | 191 + x11-proto/inputproto/inputproto-2.0.1-r1.ebuild | 30 + x11-proto/inputproto/inputproto-2.0.2-r1.ebuild | 27 + 90 files changed, 19015 insertions(+) create mode 100644 dev-libs/glib/Manifest create mode 100644 dev-libs/glib/files/glib-1.2.10-automake.patch create mode 100644 dev-libs/glib/files/glib-1.2.10-configure-LANG.patch create mode 100644 dev-libs/glib/files/glib-1.2.10-gcc34-fix.patch create mode 100644 dev-libs/glib/files/glib-1.2.10-m4.patch create mode 100644 dev-libs/glib/files/glib-2.10.3-ia64-atomic-ops.patch create mode 100644 dev-libs/glib/files/glib-2.12.12-fbsd.patch create mode 100644 dev-libs/glib/files/glib-2.18.1-workaround-gio-test-failure-without-userpriv.patch create mode 100644 dev-libs/glib/files/glib-2.24-assert-test-failure.patch create mode 100644 dev-libs/glib/files/glib-2.24-punt-python-check.patch create mode 100644 dev-libs/glib/files/glib-2.25-punt-python-check.patch create mode 100644 dev-libs/glib/files/glib-2.25-skip-tests-with-dbus-keyring.patch create mode 100644 dev-libs/glib/files/glib-2.26.0-disable-locale-sensitive-test.patch create mode 100644 dev-libs/glib/files/glib-2.26.0-disable-volumemonitor-broken-test.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-deprecation-tests.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-gatomic-header.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-gdatetime-test.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-gdbus-flushes.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-gsettings-read.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-gsettings-rules.patch create mode 100644 dev-libs/glib/files/glib-2.26.1-locked-message.patch create mode 100644 dev-libs/glib/files/glib-2.28.2-gio_launch_handler.patch create mode 100644 dev-libs/glib/glib-2.28.5-r1.ebuild create mode 100644 dev-libs/glib/glib-2.28.6-r1.ebuild create mode 100644 dev-libs/glib/glib-2.28.7-r1.ebuild create mode 100644 dev-libs/glib/glib-2.28.8-r1.ebuild create mode 100644 dev-libs/glib/metadata.xml create mode 100644 dev-util/editje/Manifest create mode 100644 dev-util/editje/editje-9999.ebuild create mode 100644 net-wireless/rt3572usb/Manifest create mode 100644 net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-Makefile.patch create mode 100644 net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-config.mk.patch create mode 100644 net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-nodebug.patch create mode 100644 net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rt_linux.h.patch create mode 100644 net-wireless/rt3572usb/files/rt3572usb-2.5.0.0-rtusb_dev_id.c.patch create mode 100644 net-wireless/rt3572usb/rt3572usb-2.5.0.0.ebuild create mode 100644 x11-apps/ccv-bin/Manifest create mode 100644 x11-apps/ccv-bin/ccv-bin-1.4.0.ebuild create mode 100644 x11-apps/ginn/Manifest create mode 100644 x11-apps/ginn/ginn-0.2.4.ebuild create mode 100644 x11-base/xorg-server/Manifest create mode 100644 x11-base/xorg-server/files/diff create mode 100644 x11-base/xorg-server/files/xdm-setup.initd-1 create mode 100644 x11-base/xorg-server/files/xdm.confd-3 create mode 100755 x11-base/xorg-server/files/xdm.initd-3 create mode 100644 x11-base/xorg-server/files/xorg-server-1.10.2-xi2.patch create mode 100644 x11-base/xorg-server/files/xorg-server-1.9-nouveau-default.patch create mode 100644 x11-base/xorg-server/files/xorg-server-disable-acpi.patch create mode 100644 x11-base/xorg-server/files/xorg-server-gestures-extension.patch create mode 100644 x11-base/xorg-server/files/xorg-server-xf86CoordinatesToWindow.patch create mode 100644 x11-base/xorg-server/files/xorg-server-xi2.patch create mode 100644 x11-base/xorg-server/files/xorg-sets.conf create mode 100644 x11-base/xorg-server/metadata.xml create mode 100644 x11-base/xorg-server/xorg-server-1.10.0.901-r1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.0.902-r1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.1-r1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.1.901-r1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.2-r1.ebuild create mode 100644 x11-base/xorg-server/xorg-server-1.10.3-r1.ebuild create mode 100644 x11-drivers/xf86-input-evdev/Manifest create mode 100644 x11-drivers/xf86-input-evdev/files/xf86-input-evdev-gestures.patch create mode 100644 x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch create mode 100644 x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0-r1.ebuild create mode 100644 x11-libs/bamf/Manifest create mode 100644 x11-libs/bamf/bamf-0.2.70.ebuild create mode 100644 x11-libs/libXi/Manifest create mode 100644 x11-libs/libXi/files/libXi-xi2.1.patch create mode 100644 x11-libs/libXi/libXi-1.4.2-r1.ebuild create mode 100644 x11-libs/libXi/libXi-1.4.3.ebuild create mode 100644 x11-libs/mtdev/Manifest create mode 100644 x11-libs/mtdev/mtdev-1.1.0.ebuild create mode 100644 x11-libs/utouch-evemu/Manifest create mode 100644 x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild create mode 100644 x11-libs/utouch-frame/Manifest create mode 100644 x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild create mode 100644 x11-libs/utouch-geis/Manifest create mode 100644 x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild create mode 100644 x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild create mode 100644 x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild create mode 100644 x11-libs/utouch-grail/Manifest create mode 100644 x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild create mode 100644 x11-plugins/e_modules-itask/Manifest create mode 100644 x11-plugins/e_modules-itask/e_modules-itask-9999.ebuild create mode 100644 x11-plugins/e_modules-itask/metadata.xml create mode 100644 x11-proto/inputproto/Manifest create mode 100644 x11-proto/inputproto/files/inputproto-2.0.1-xi2.1.patch create mode 100644 x11-proto/inputproto/files/inputproto-2.0.2-xi2.1.patch create mode 100644 x11-proto/inputproto/inputproto-2.0.1-r1.ebuild create mode 100644 x11-proto/inputproto/inputproto-2.0.2-r1.ebuild 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 +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 +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 +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 +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 +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 +--- +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 +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 +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 +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 +--- +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 +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 ++ * Extending GIO. ++ */ ++#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 + + Use dev-libs/gobject-introspection + for introspection + Compile with support for utouch + + 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 "^[^#]+.*\" /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 ++ */ ++ + /******************************************************************** + * + * 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 + #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 + #include + + #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, + ¶m, &mask); + break; ++ case XIGrabtypeTouchBegin: ++ status = GrabTouch(client, dev, mod_dev, ¶m, &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 + #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 ++ + #include + #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 +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 ++ * ++ */ ++ ++#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 ++ * ++ */ ++ ++#ifndef _GESTURE_H_ ++#define _GESTURE_H_ ++ ++#ifdef HAVE_DIX_CONFIG_H ++#include ++#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 ++ * ++ */ ++ ++#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 ++ * ++ */ ++ ++#ifndef _GESTUREPROTO_H_ ++#define _GESTUREPROTO_H_ ++ ++#include ++#include ++ ++#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 ++#endif ++ ++#include "gcstruct.h" /* pointer for extnsionst.h */ ++#include "extnsionst.h" /* extension entry */ ++#include "gesture.h" ++#include "gestureint.h" ++#include ++#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 ++#endif ++ + #include "window.h" + #include "pixmapstr.h" + #include "regionstr.h" +@@ -60,6 +64,10 @@ SOFTWARE. + #include + #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 + #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 ++ */ ++ + /******************************************************************** + * + * 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 + #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 + #include + + #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, + ¶m, &mask); + break; ++ case XIGrabtypeTouchBegin: ++ status = GrabTouch(client, dev, mod_dev, ¶m, &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 + #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 ++ + #include + #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 @@ + + + +x11 + + Build the Distributed Multiheaded X server + Build the kdrive X servers + Build with tslib support for touchscreen devices + Build the Xorg X server (HIGHLY RECOMMENDED) + Build with utouch support + + 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 " ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#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 ++ ++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 ++ * ++ */ ++ ++#ifndef _GESTUREPROTO_H_ ++#define _GESTUREPROTO_H_ ++ ++#include ++#include ++ ++#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 + +-#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 + +-#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 + #include + +-#ifdef HAVE_PROPERTIES + #include + #include + #include +-/* 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 /* 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(DeviceIntPtr device, int what) + { + InputInfoPtr pInfo; + EvdevPtr pEvdev; ++#ifdef MULTITOUCH ++ int i; ++#endif + + pInfo = device->public.devicePrivate; + pEvdev = pInfo->private; +@@ -1759,6 +1609,17 @@ EvdevProc(DeviceIntPtr device, int what) + close(pInfo->fd); + pInfo->fd = -1; + } ++ valuator_mask_free(&pEvdev->vals); ++ valuator_mask_free(&pEvdev->old_vals); ++ valuator_mask_free(&pEvdev->prox); ++#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); ++ if (pEvdev->mtdev) ++ mtdev_close(pEvdev->mtdev); ++#endif + EvdevRemoveDevice(pInfo); + pEvdev->min_maj = 0; + break; +@@ -2015,7 +1876,6 @@ EvdevProbe(InputInfoPtr pInfo) + if (has_lmr || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) { + xf86Msg(X_PROBED, "%s: Found absolute touchpad.\n", pInfo->name); + pEvdev->flags |= EVDEV_TOUCHPAD; +- memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals); + } else { + xf86Msg(X_PROBED, "%s: Found absolute touchscreen\n", pInfo->name); + pEvdev->flags |= EVDEV_TOUCHSCREEN; +@@ -2135,6 +1995,16 @@ EvdevOpenDevice(InputInfoPtr pInfo) + + pEvdev->device = device; + xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device); ++ ++#ifdef MULTITOUCH ++ pEvdev->mtdev = malloc(sizeof(struct mtdev)); ++ if (!pEvdev->mtdev) ++ { ++ xf86Msg(X_ERROR, "%s: Couldn't allocate mtdev structure\n", ++ pInfo->name); ++ return BadAlloc; ++ } ++#endif + } + + if (pInfo->fd < 0) +@@ -2149,6 +2019,17 @@ EvdevOpenDevice(InputInfoPtr pInfo) + } + } + ++#ifdef MULTITOUCH ++ if (mtdev_open(pEvdev->mtdev, pInfo->fd) == 0) ++ pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value; ++ else { ++ free(pEvdev->mtdev); ++ pEvdev->mtdev = NULL; ++ xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name); ++ return FALSE; ++ } ++#endif ++ + /* Check major/minor of device node to avoid adding duplicate devices. */ + pEvdev->min_maj = EvdevGetMajorMinor(pInfo); + if (EvdevIsDuplicate(pInfo)) +@@ -2162,52 +2043,8 @@ EvdevOpenDevice(InputInfoPtr pInfo) + return Success; + } + +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12 +-static int NewEvdevPreInit(InputDriverPtr, InputInfoPtr, int); +- +-static InputInfoPtr +-EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags) +-{ +- InputInfoPtr pInfo; +- +- if (!(pInfo = xf86AllocateInput(drv, 0))) +- return NULL; +- +- /* Initialise the InputInfoRec. */ +- pInfo->fd = -1; +- pInfo->name = dev->identifier; +- pInfo->flags = 0; +- pInfo->history_size = 0; +- pInfo->control_proc = NULL; +- pInfo->close_proc = NULL; +- pInfo->conversion_proc = NULL; +- pInfo->reverse_conversion_proc = NULL; +- pInfo->dev = NULL; +- pInfo->private_flags = 0; +- pInfo->always_core_feedback = NULL; +- pInfo->conf_idev = dev; +- pInfo->private = NULL; +- +- xf86CollectInputOptions(pInfo, (const char**)evdevDefaults, NULL); +- xf86ProcessCommonOptions(pInfo, pInfo->options); +- +- if (NewEvdevPreInit(drv, pInfo, flags) == Success) +- { +- pInfo->flags |= XI86_CONFIGURED; +- return pInfo; +- } +- +- +- xf86DeleteInput(pInfo, 0); +- return NULL; +-} +- +-static int +-NewEvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) +-#else + static int + EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) +-#endif + { + EvdevPtr pEvdev; + int rc = BadAlloc; +@@ -2225,6 +2062,10 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) + if (rc != Success) + goto error; + ++#ifdef MULTITOUCH ++ pEvdev->cur_slot = -1; ++#endif ++ + /* + * We initialize pEvdev->in_proximity to 1 so that device that doesn't use + * proximity will still report events. +@@ -2279,9 +2120,7 @@ _X_EXPORT InputDriverRec EVDEV = { + EvdevPreInit, + NULL, + NULL, +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 + evdevDefaults +-#endif + }; + + static void +@@ -2356,8 +2195,6 @@ EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code) + } + } + +-#ifdef HAVE_PROPERTIES +-#ifdef HAVE_LABELS + /* Aligned with linux/input.h. + Note that there are holes in the ABS_ range, these are simply replaced with + MISC here */ +@@ -2411,7 +2248,6 @@ static char* abs_labels[] = { + AXIS_LABEL_PROP_ABS_MISC, /* undefined */ + AXIS_LABEL_PROP_ABS_MISC, /* undefined */ + AXIS_LABEL_PROP_ABS_MISC, /* undefined */ +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 10 + AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR, /* 0x30 */ + AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR, /* 0x31 */ + AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR, /* 0x32 */ +@@ -2423,7 +2259,6 @@ static char* abs_labels[] = { + AXIS_LABEL_PROP_ABS_MT_BLOB_ID, /* 0x38 */ + AXIS_LABEL_PROP_ABS_MT_TRACKING_ID, /* 0x39 */ + AXIS_LABEL_PROP_ABS_MT_PRESSURE, /* 0x3a */ +-#endif + }; + + static char* rel_labels[] = { +@@ -2520,11 +2355,8 @@ static char* btn_labels[][16] = { + } + }; + +-#endif /* HAVE_LABELS */ +- + static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms) + { +-#ifdef HAVE_LABELS + Atom atom; + int axis; + char **labels; +@@ -2557,12 +2389,10 @@ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms) + + atoms[pEvdev->axis_map[axis]] = atom; + } +-#endif + } + + static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms) + { +-#ifdef HAVE_LABELS + Atom atom; + int button, bmap; + +@@ -2600,7 +2430,6 @@ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms) + atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); + if (natoms > 6) + atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); +-#endif + } + + static void +@@ -2659,11 +2488,10 @@ EvdevInitProperty(DeviceIntPtr dev) + + XISetDevicePropertyDeletable(dev, prop_swap, FALSE); + +-#ifdef HAVE_LABELS + /* Axis labelling */ + if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP))) + { +- Atom atoms[pEvdev->num_vals]; ++ Atom atoms[pEvdev->num_vals + pEvdev->num_mt_vals]; + EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); + XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32, + PropModeReplace, pEvdev->num_vals, atoms, FALSE); +@@ -2678,7 +2506,6 @@ EvdevInitProperty(DeviceIntPtr dev) + PropModeReplace, pEvdev->num_buttons, atoms, FALSE); + XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE); + } +-#endif /* HAVE_LABELS */ + } + + } +@@ -2723,4 +2550,3 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, + + return Success; + } +-#endif +diff --git a/src/evdev.h b/src/evdev.h +index f640fdd..a590eaf 100644 +--- a/src/evdev.h ++++ b/src/evdev.h +@@ -39,6 +39,16 @@ + #include + #include + ++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 100 + GET_ABI_MINOR(ABI_XINPUT_VERSION) < 1202 ++#error "Need X server input ABI version 12.2 or greater" ++#endif ++ ++#define MULTITOUCH /* Will be at least ABI 13.1, but it's not there yet */ ++ ++#ifdef MULTITOUCH ++#include ++#endif ++ + #ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */ + #define EV_CNT (EV_MAX+1) + #endif +@@ -72,26 +82,10 @@ + #define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */ + #define EVDEV_RELATIVE_MODE (1 << 11) /* Force relative events for devices with absolute axes */ + +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3 +-#define HAVE_PROPERTIES 1 +-#endif +- + #ifndef MAX_VALUATORS + #define MAX_VALUATORS 36 + #endif + +- +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5 +-typedef struct { +- char *rules; +- char *model; +- char *layout; +- char *variant; +- char *options; +-} XkbRMLVOSet; +-#endif +- +- + #define LONG_BITS (sizeof(long) * 8) + + /* Number of longs needed to hold the given number of bits */ +@@ -110,9 +104,20 @@ typedef struct { + EV_QUEUE_KEY, /* xf86PostKeyboardEvent() */ + EV_QUEUE_BTN, /* xf86PostButtonEvent() */ + EV_QUEUE_PROXIMITY, /* xf86PostProximityEvent() */ ++#ifdef MULTITOUCH ++ EV_QUEUE_TOUCH, /*xf86PostTouchEvent() */ ++#endif + } type; +- int key; /* May be either a key code or button number. */ +- int val; /* State of the key/button; pressed or released. */ ++ union { ++ int key; /* May be either a key code or button number. */ ++#ifdef MULTITOUCH ++ unsigned int touch; /* Touch ID */ ++#endif ++ } detail; ++ int val; /* State of the key/button/touch; pressed or released. */ ++#ifdef MULTITOUCH ++ ValuatorMask *touch_vals; /* current state of valuators for touch */ ++#endif + } EventQueueRec, *EventQueuePtr; + + typedef struct { +@@ -121,8 +126,18 @@ typedef struct { + + int num_vals; /* number of valuators */ + int axis_map[max(ABS_CNT, REL_CNT)]; /* Map evdev to index */ +- int vals[MAX_VALUATORS]; +- int old_vals[MAX_VALUATORS]; /* Translate absolute inputs to relative */ ++ ValuatorMask *vals; /* new values coming in */ ++ ValuatorMask *old_vals; /* old values for calculating relative motion */ ++ ValuatorMask *prox; /* last values set while not in proximity */ ++#ifdef MULTITOUCH ++ int num_mt_vals; ++ ValuatorMask *mt_vals; /* multitouch values coming in */ ++ ValuatorMask *cur_vals; /* current values of MT axes in evdev state */ ++ int cur_slot; ++ BOOL close_slot; ++ BOOL open_slot; ++ struct mtdev *mtdev; ++#endif + + int flags; + int in_proximity; /* device in proximity */ +@@ -134,12 +149,8 @@ typedef struct { + + int delta[REL_CNT]; + unsigned int abs_queued, rel_queued, prox_queued; +- unsigned int abs_prox; /* valuators posted while out of prox? */ + + /* XKB stuff has to be per-device rather than per-driver */ +-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5 +- XkbComponentNamesRec xkbnames; +-#endif + XkbRMLVOSet rmlvo; + + /* Middle mouse button emulation */ +@@ -202,6 +213,10 @@ typedef struct { + void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value); + void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value); + void EvdevQueueProximityEvent(InputInfoPtr pInfo, int value); ++#ifdef MULTITOUCH ++void EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ++ ValuatorMask *mask, uint16_t type); ++#endif + void EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value); + void EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count); + void EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v, +@@ -228,9 +243,7 @@ BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv); + void EvdevDragLockPreInit(InputInfoPtr pInfo); + BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value); + +-#ifdef HAVE_PROPERTIES + void EvdevMBEmuInitProperty(DeviceIntPtr); + void EvdevWheelEmuInitProperty(DeviceIntPtr); + void EvdevDragLockInitProperty(DeviceIntPtr); + #endif +-#endif diff --git a/x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0-r1.ebuild b/x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0-r1.ebuild new file mode 100644 index 0000000..d6fe225 --- /dev/null +++ b/x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0-r1.ebuild @@ -0,0 +1,33 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/x11-drivers/xf86-input-evdev/xf86-input-evdev-2.6.0.ebuild,v 1.7 2011/03/05 18:09:14 xarthisius Exp $ + +EAPI=3 +XORG_EAUTORECONF=yes + +inherit xorg-2 + +DESCRIPTION="Generic Linux input driver" +KEYWORDS="alpha amd64 arm hppa ia64 ~mips ppc ppc64 sh sparc x86" +IUSE="utouch" + +RDEPEND=">=x11-base/xorg-server-1.6.3" +DEPEND="${RDEPEND} + >=sys-kernel/linux-headers-2.6 + x11-proto/inputproto + x11-proto/xproto" + +src_prepare() { + if use utouch ; then + epatch "${FILESDIR}/xf86-input-evdev-xi2.1.patch" + epatch "${FILESDIR}/xf86-input-evdev-gestures.patch" + fi + + xorg-2_src_prepare +} + +src_install() { + xorg-2_src_install +} + + diff --git a/x11-libs/bamf/Manifest b/x11-libs/bamf/Manifest new file mode 100644 index 0000000..6c40be2 --- /dev/null +++ b/x11-libs/bamf/Manifest @@ -0,0 +1,2 @@ +DIST bamf-0.2.70.tar.gz 495005 RMD160 945cb1c5c285123f1a6560682a58ee72baf84a71 SHA1 06c2eb0029be08c4d1f3e19d176c9b97852fad24 SHA256 7ea2256ffd1614df4ee6e213622fd30771a9ed6774a767bd4fb165e110c602e7 +EBUILD bamf-0.2.70.ebuild 764 RMD160 27520570a134a8f0bf1eed3e2b6ca63d3ff6c8e2 SHA1 fcb747372e66995d468dd9646470d8c7eb76ad2b SHA256 b5eb326621c0379db5433bdeeac629c436895ba8d33d1dd54dea3ca092abd4a3 diff --git a/x11-libs/bamf/bamf-0.2.70.ebuild b/x11-libs/bamf/bamf-0.2.70.ebuild new file mode 100644 index 0000000..7079256 --- /dev/null +++ b/x11-libs/bamf/bamf-0.2.70.ebuild @@ -0,0 +1,40 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="3" + +inherit autotools + +DESCRIPTION="BAMF Application Matching Framework" +SRC_URI="http://launchpad.net/bamf/trunk/${PV}/+download/bamf-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/bamf" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="LGPL3" +IUSE="" + +DEPEND=">=dev-lang/vala-0.11.7 + dev-util/gtk-doc" + +src_unpack() { + unpack ${A} + cd "${S}" + + sed -i -e 's/vapigen/vapigen-0.12/' configure.in + + eautoreconf +} + +src_configure() { + econf +} + +src_compile() { + emake || die +# vapigen-0.12 --library=Bamf-0.2 --directory=${D}/lib/libbamf ${D}/lib/libbamf/Bamf-0.2.gir +} + +src_install() { + emake DESTDIR="${D}" install || die +} diff --git a/x11-libs/libXi/Manifest b/x11-libs/libXi/Manifest new file mode 100644 index 0000000..1c4b4ca --- /dev/null +++ b/x11-libs/libXi/Manifest @@ -0,0 +1,5 @@ +AUX libXi-xi2.1.patch 11188 RMD160 909fcd23461eca1a854d39c2a304ae26c8e96574 SHA1 dccae93e792e9d46d60ee44150810c52ce680521 SHA256 feffa065a785326d35280ceb769873224e75c16c20d7f080be20a2afff1f240a +DIST libXi-1.4.2.tar.bz2 398801 RMD160 2753987b72a91683321bc02172901f1d5c5b5664 SHA1 97e60a60dd789287e47df807e487f4952dd4ff95 SHA256 272b8041efc0a0203fb0ba33481ddec989539aed862181b58c8c3e410e325691 +DIST libXi-1.4.3.tar.bz2 422637 RMD160 142d44e8e13abbb8a41826b7005f8ede1807e3ff SHA1 c66cfdee74e8d169a7992b5f257395e653ca761b SHA256 08c9d89a404740592621e6f5078414df86ccc78ca876e3da1af15639d81c74e0 +EBUILD libXi-1.4.2-r1.ebuild 1149 RMD160 3a78d26c6dbccd709ae2a545959292a33518ca08 SHA1 2ae24fd9709278dd035f4372712e7d9d01da980c SHA256 0b3ecc4aa481eec5caec31314f5b5528ce652e26c45af8a34ccaeed7dc7247a3 +EBUILD libXi-1.4.3.ebuild 1159 RMD160 6889dfec090e638af1820539191a2f1a9fb3c462 SHA1 8a713a869036dab8005c447acd9edaa6d3d3a738 SHA256 a2cb55e60cecf302aee545dd2c035cef4ec1843e439a1a4c12511f07b863eefb diff --git a/x11-libs/libXi/files/libXi-xi2.1.patch b/x11-libs/libXi/files/libXi-xi2.1.patch new file mode 100644 index 0000000..398a697 --- /dev/null +++ b/x11-libs/libXi/files/libXi-xi2.1.patch @@ -0,0 +1,355 @@ +--- a/include/X11/extensions/XInput2.h ++++ b/include/X11/extensions/XInput2.h +@@ -135,6 +135,25 @@ typedef struct + + typedef struct + { ++ int type; ++ int sourceid; ++ int mode; ++ int num_touches; ++} XITouchClassInfo; ++ ++typedef struct ++{ ++ int type; ++ int sourceid; ++ int number; ++ Atom label; ++ double min; ++ double max; ++ int resolution; ++} XITouchValuatorClassInfo; ++ ++typedef struct ++{ + int deviceid; + char *name; + int use; +@@ -292,6 +311,20 @@ typedef struct { + int what; + } XIPropertyEvent; + ++typedef struct { ++ int type; /* GenericEvent */ ++ unsigned long serial; /* # of last request processed by server */ ++ Bool send_event; /* true if this came from a SendEvent request */ ++ Display *display; /* Display the event was read from */ ++ int extension; /* XI extension offset */ ++ int evtype; ++ Time time; ++ int deviceid; ++ int sourceid; ++ unsigned int touchid; ++ unsigned int flags; ++} XITouchOwnershipEvent; ++ + _XFUNCPROTOBEGIN + + extern Bool XIQueryPointer( +@@ -415,6 +448,13 @@ extern Status XIAllowEvents( + Time time + ); + ++extern Status XIAllowTouchEvents( ++ Display* display, ++ int deviceid, ++ unsigned long touchid, ++ int event_mode ++); ++ + extern int XIGrabButton( + Display* display, + int deviceid, +@@ -466,6 +506,17 @@ extern int XIGrabFocusIn( + int num_modifiers, + XIGrabModifiers *modifiers_inout + ); ++ ++extern int XIGrabTouchBegin( ++ Display* display, ++ int deviceid, ++ Window grab_window, ++ int owner_events, ++ XIEventMask *mask, ++ int num_modifiers, ++ XIGrabModifiers *modifiers_inout ++); ++ + extern Status XIUngrabButton( + Display* display, + int deviceid, +@@ -496,6 +547,14 @@ extern Status XIUngrabFocusIn( + Display* display, + int deviceid, + Window grab_window, ++ int num_modifiers, ++ XIGrabModifiers *modifiers ++); ++ ++extern Status XIUngrabTouchBegin( ++ Display* display, ++ int deviceid, ++ Window grab_window, + int num_modifiers, + XIGrabModifiers *modifiers + ); +--- a/src/XExtInt.c ++++ b/src/XExtInt.c +@@ -146,6 +146,9 @@ static int + wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie); + static int + wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie); ++static int ++wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in, ++ XGenericEventCookie *cookie); + + static /* const */ XEvent emptyevent; + +@@ -268,7 +271,8 @@ static XExtensionVersion versions[] = { + XI_Add_DevicePresenceNotify_Minor}, + {XI_Present, XI_Add_DeviceProperties_Major, + XI_Add_DeviceProperties_Minor}, +-{XI_Present, XI_2_Major, XI_2_Minor} ++{XI_Present, XI_2_Major, XI_2_Minor}, ++{XI_Present, XI_2_Major, XI_2_1_Minor} + }; + + /*********************************************************************** +@@ -924,6 +928,10 @@ XInputWireToCookie( + case XI_ButtonRelease: + case XI_KeyPress: + case XI_KeyRelease: ++ case XI_TouchBegin: ++ case XI_TouchUpdate: ++ case XI_TouchUpdateUnowned: ++ case XI_TouchEnd: + *cookie = *(XGenericEventCookie*)save; + if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie)) + { +@@ -950,7 +958,16 @@ XInputWireToCookie( + break; + } + return ENQUEUE_EVENT; +- ++ case XI_TouchOwnership: ++ *cookie = *(XGenericEventCookie*)save; ++ if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event, ++ cookie)) ++ { ++ printf("XInputWireToCookie: CONVERSION FAILURE! evtype=%d\n", ++ ge->evtype); ++ break; ++ } ++ return ENQUEUE_EVENT; + case XI_RawKeyPress: + case XI_RawKeyRelease: + case XI_RawButtonPress: +@@ -1037,6 +1054,12 @@ sizeDeviceClassType(int type, int num_el + case XIValuatorClass: + l = sizeof(XIValuatorClassInfo); + break; ++ case XITouchClass: ++ l = sizeof(XITouchClassInfo); ++ break; ++ case XITouchValuatorClass: ++ l = sizeof(XITouchValuatorClassInfo); ++ break; + default: + printf("sizeDeviceClassType: unknown type %d\n", type); + break; +@@ -1239,6 +1262,22 @@ copyPropertyEvent(XGenericEventCookie *c + } + + static Bool ++copyTouchOwnershipEvent(XGenericEventCookie *cookie_in, ++ XGenericEventCookie *cookie_out) ++{ ++ XITouchOwnershipEvent *in, *out; ++ ++ in = cookie_in->data; ++ ++ out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent)); ++ if (!out) ++ return False; ++ ++ *out = *in; ++ return True; ++} ++ ++static Bool + copyRawEvent(XGenericEventCookie *cookie_in, + XGenericEventCookie *cookie_out) + { +@@ -1297,8 +1336,15 @@ XInputCopyCookie(Display *dpy, XGenericE + case XI_ButtonRelease: + case XI_KeyPress: + case XI_KeyRelease: ++ case XI_TouchBegin: ++ case XI_TouchUpdate: ++ case XI_TouchUpdateUnowned: ++ case XI_TouchEnd: + ret = copyDeviceEvent(in, out); + break; ++ case XI_TouchOwnership: ++ ret = copyTouchOwnershipEvent(in, out); ++ break; + case XI_DeviceChanged: + ret = copyDeviceChangedEvent(in, out); + break; +@@ -1427,6 +1473,12 @@ size_classes(xXIAnyInfo* from, int nclas + case XIValuatorClass: + l = sizeDeviceClassType(XIValuatorClass, 0); + break; ++ case XITouchClass: ++ l = sizeDeviceClassType(XITouchClass, 0); ++ break; ++ case XITouchValuatorClass: ++ l = sizeDeviceClassType(XITouchValuatorClass, 0); ++ break; + } + + len += l; +@@ -1527,6 +1579,35 @@ copy_classes(XIDeviceInfo* to, xXIAnyInf + + } + break; ++ case XITouchClass: ++ { ++ XITouchClassInfo *cls_lib; ++ xXITouchInfo *cls_wire; ++ ++ cls_wire = (xXITouchInfo*)any_wire; ++ cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo)); ++ ++ cls_lib->mode = cls_wire->mode; ++ cls_lib->num_touches = cls_wire->num_touches; ++ } ++ break; ++ case XITouchValuatorClass: ++ { ++ XITouchValuatorClassInfo *cls_lib; ++ xXITouchValuatorInfo *cls_wire; ++ ++ cls_wire = (xXITouchValuatorInfo*)any_wire; ++ cls_lib = next_block(&ptr_lib, ++ sizeof(XITouchValuatorClassInfo)); ++ ++ cls_lib->number = cls_wire->number; ++ cls_lib->label = cls_wire->label; ++ /* FIXME: fractional parts */ ++ cls_lib->min = cls_wire->min.integral; ++ cls_lib->max = cls_wire->max.integral; ++ cls_lib->resolution = cls_wire->resolution; ++ } ++ break; + } + len += any_wire->length * 4; + ptr_wire += any_wire->length * 4; +@@ -1697,6 +1778,28 @@ wireToEnterLeave(xXIEnterEvent *in, XGen + + return 1; + } ++ ++static int ++wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in, ++ XGenericEventCookie *cookie) ++{ ++ XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent)); ++ ++ cookie->data = out; ++ ++ out->type = in->type; ++ out->display = cookie->display; ++ out->extension = in->extension; ++ out->evtype = in->evtype; ++ out->send_event = ((in->type & 0x80) != 0); ++ out->time = in->time; ++ out->deviceid = in->deviceid; ++ out->sourceid = in->sourceid; ++ out->touchid = in->touchid; ++ out->flags = in->flags; ++ ++ return 1; ++} + + static int + wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie) +--- a/src/XIAllowEvents.c ++++ b/src/XIAllowEvents.c +@@ -51,3 +51,27 @@ XIAllowEvents(Display *dpy, int deviceid + SyncHandle(); + return Success; + } ++ ++Status ++XIAllowTouchEvents(Display *dpy, int deviceid, unsigned long touchid, ++ int event_mode) ++{ ++ xXIAllowTouchEventsReq *req; ++ ++ XExtDisplayInfo *extinfo = XInput_find_display(dpy); ++ ++ LockDisplay(dpy); ++ if (_XiCheckExtInit(dpy, XInput_2_1, extinfo) == -1) ++ return (NoSuchExtension); ++ ++ GetReq(XIAllowTouchEvents, req); ++ req->reqType = extinfo->codes->major_opcode; ++ req->ReqType = X_XIAllowTouchEvents; ++ req->deviceid = deviceid; ++ req->touchid = touchid; ++ req->mode = event_mode; ++ ++ UnlockDisplay(dpy); ++ SyncHandle(); ++ return Success; ++} +--- a/src/XIPassiveGrab.c ++++ b/src/XIPassiveGrab.c +@@ -145,6 +145,25 @@ XIGrabFocusIn(Display *dpy, int deviceid + modifiers_inout); + } + ++int ++XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window, ++ Bool owner_events, XIEventMask *mask, ++ int num_modifiers, XIGrabModifiers *modifiers_inout) ++{ ++ XExtDisplayInfo *extinfo = XInput_find_display(dpy); ++ ++ LockDisplay(dpy); ++ if (_XiCheckExtInit(dpy, XInput_2_1, extinfo) == -1) ++ return -1; ++ ++ UnlockDisplay(dpy); ++ ++ return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0, ++ grab_window, None, GrabModeAsync, GrabModeAsync, ++ owner_events, mask, num_modifiers, ++ modifiers_inout); ++} ++ + static int + _XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail, + Window grab_window, int num_modifiers, XIGrabModifiers *modifiers) +@@ -208,3 +227,19 @@ XIUngrabFocusIn(Display* display, int de + return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0, + grab_window, num_modifiers, modifiers); + } ++ ++int ++XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window, ++ int num_modifiers, XIGrabModifiers *modifiers) ++{ ++ XExtDisplayInfo *extinfo = XInput_find_display(display); ++ ++ LockDisplay(display); ++ if (_XiCheckExtInit(display, XInput_2_1, extinfo) == -1) ++ return -1; ++ ++ UnlockDisplay(display); ++ ++ return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0, ++ grab_window, num_modifiers, modifiers); ++} diff --git a/x11-libs/libXi/libXi-1.4.2-r1.ebuild b/x11-libs/libXi/libXi-1.4.2-r1.ebuild new file mode 100644 index 0000000..8b9c99f --- /dev/null +++ b/x11-libs/libXi/libXi-1.4.2-r1.ebuild @@ -0,0 +1,42 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/x11-libs/libXi/libXi-1.4.2.ebuild,v 1.1 2011/03/19 10:41:40 scarabeus Exp $ + +EAPI=4 +XORG_EAUTORECONF=yes +XORG_DOC=doc +inherit xorg-2 + +DESCRIPTION="X.Org Xi library" +KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~x86-fbsd ~x64-freebsd ~x86-freebsd ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt" +IUSE="utouch" + +RDEPEND=">=x11-libs/libX11-1.3 + >=x11-libs/libXext-1.1 + >=x11-proto/inputproto-2.0 + >=x11-proto/xproto-7.0.13 + >=x11-proto/xextproto-7.0.3" +DEPEND="${RDEPEND}" + +src_prepare() { + if use utouch ; then + epatch "${FILESDIR}/libXi-xi2.1.patch" + fi + xorg-2_src_prepare +} + + +pkg_setup() { + xorg-2_pkg_setup + CONFIGURE_OPTIONS="$(use_enable doc specs) + $(use_with doc xmlto) + $(use_with doc asciidoc) + --without-fop" +} + +pkg_postinst() { + xorg-2_pkg_postinst + + ewarn "Some special keys and keyboard layouts may stop working." + ewarn "To fix them, recompile xorg-server." +} diff --git a/x11-libs/libXi/libXi-1.4.3.ebuild b/x11-libs/libXi/libXi-1.4.3.ebuild new file mode 100644 index 0000000..89f43de --- /dev/null +++ b/x11-libs/libXi/libXi-1.4.3.ebuild @@ -0,0 +1,44 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/x11-libs/libXi/libXi-1.4.3.ebuild,v 1.1 2011/06/07 14:14:01 chithanh Exp $ + +EAPI=4 + +XORG_DOC=doc +inherit xorg-2 + +DESCRIPTION="X.Org Xi library" +KEYWORDS="~alpha ~amd64 ~arm ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86 ~x86-fbsd ~x64-freebsd ~x86-freebsd ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x86-macos ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt" +IUSE="utouch" + +RDEPEND=">=x11-libs/libX11-1.3 + >=x11-libs/libXext-1.1 + >=x11-proto/inputproto-2.0 + >=x11-proto/xproto-7.0.13 + >=x11-proto/xextproto-7.0.3" +DEPEND="${RDEPEND}" + +src_prepare() { + if use utouch ; then + epatch "${FILESDIR}/libXi-xi2.1.patch" + fi + xorg-2_src_prepare +} + + +pkg_setup() { + xorg-2_pkg_setup + XORG_CONFIGURE_OPTIONS=( + $(use_enable doc specs) + $(use_with doc xmlto) + $(use_with doc asciidoc) + --without-fop + ) +} + +pkg_postinst() { + xorg-2_pkg_postinst + + ewarn "Some special keys and keyboard layouts may stop working." + ewarn "To fix them, recompile xorg-server." +} diff --git a/x11-libs/mtdev/Manifest b/x11-libs/mtdev/Manifest new file mode 100644 index 0000000..5bada69 --- /dev/null +++ b/x11-libs/mtdev/Manifest @@ -0,0 +1,2 @@ +DIST mtdev-1.1.0.tar.gz 300940 RMD160 0ca9bb0c6a6134234989d5139b7120e16ade6fa1 SHA1 27b047394a7284e6f357b2ef6e9ac32460f60063 SHA256 8453424c52d8251aab2cf2a554bdc96b478f27be73f23ca6e9c3bf9fb7f0b392 +EBUILD mtdev-1.1.0.ebuild 459 RMD160 7ce6f986f2ce0f3ee04f7478ce6f8b7fcc8858be SHA1 160122d2bc62fe294f10c22dee0e589a3cfc1dbd SHA256 fe5c733a0554689827cb7fa90bf2f464ce855a315ca84e4a7fe639e86af24265 diff --git a/x11-libs/mtdev/mtdev-1.1.0.ebuild b/x11-libs/mtdev/mtdev-1.1.0.ebuild new file mode 100644 index 0000000..4340d5d --- /dev/null +++ b/x11-libs/mtdev/mtdev-1.1.0.ebuild @@ -0,0 +1,21 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="Kernel multi-touch transformation library" +SRC_URI="http://launchpad.net/mtdev/trunk/1.1.0/+download/mtdev-1.1.0.tar.gz" +HOMEPAGE="https://launchpad.net/hci/mtdev" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="MIT" +IUSE="" + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-evemu/Manifest b/x11-libs/utouch-evemu/Manifest new file mode 100644 index 0000000..e5425ab --- /dev/null +++ b/x11-libs/utouch-evemu/Manifest @@ -0,0 +1,2 @@ +DIST utouch-evemu-1.0.5.tar.gz 306237 RMD160 c5e34fe850e4ad03cbc3aa5a96652b4ecf5bec3c SHA1 d65a47cf97e90de90832565c3cb61e2f26552373 SHA256 407378d4271a6be7688ae0f7bcdf0839b2bcade38ed8cf0d9672dfe228d8babf +EBUILD utouch-evemu-1.0.5.ebuild 474 RMD160 3265fab0f0a9a793a88b9a8689304a254c0db5c8 SHA1 7b4bbef8190bb5ee702682c6c6b7518fda0dd2d2 SHA256 95986c4570326e4a17d3192ab4ed5fb39a9858798e038e95fecb0d6d2ba060ce diff --git a/x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild b/x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild new file mode 100644 index 0000000..e43c1b1 --- /dev/null +++ b/x11-libs/utouch-evemu/utouch-evemu-1.0.5.ebuild @@ -0,0 +1,21 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="Event Emulation for the uTouch Stack" +SRC_URI="http://launchpad.net/utouch-evemu/trunk/v${PV}/+download/utouch-evemu-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-evemu" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPL-3" +IUSE="" + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-frame/Manifest b/x11-libs/utouch-frame/Manifest new file mode 100644 index 0000000..552100e --- /dev/null +++ b/x11-libs/utouch-frame/Manifest @@ -0,0 +1,2 @@ +DIST utouch-frame-1.1.2.tar.gz 314332 RMD160 947fbe88d6c2a00609e892d868774e74e5b1fde1 SHA1 fcaf34f300af6ba203dcd253a34e3170343b874e SHA256 7a7d70524cf3ee6b229951ea9e3021c0860896b172a6fb9e5fcb63f01534fa4f +EBUILD utouch-frame-1.1.2.ebuild 517 RMD160 25c5003b543a7b64ad8f5a9be0ab156c80b28f67 SHA1 6dc296f4f96ef49b0d0a0f389e00d1ac75a1e843 SHA256 70dc1b7d0abbde99c1b1c5a2337023276faa7374753a2b68a901ff195c4e9133 diff --git a/x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild b/x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild new file mode 100644 index 0000000..d8d81c2 --- /dev/null +++ b/x11-libs/utouch-frame/utouch-frame-1.1.2.ebuild @@ -0,0 +1,26 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="Touch Frame Library " +SRC_URI="http://launchpad.net/utouch-frame/trunk/v${PV}/+download/utouch-frame-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-frame" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPV-3" +IUSE="" + + +RDEPEND="" +DEPEND="${RDEPEND} + x11-libs/utouch-evemu" + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-geis/Manifest b/x11-libs/utouch-geis/Manifest new file mode 100644 index 0000000..5d0e40f --- /dev/null +++ b/x11-libs/utouch-geis/Manifest @@ -0,0 +1,6 @@ +DIST utouch-geis-2.0.10.tar.gz 500617 RMD160 63b451699d369a4b9ee5e9f40c473d210e757c14 SHA1 4bcb3f7d8f40deabdd77ac7e495334aeb69cff82 SHA256 2994c1c903a30e365e6c135f22ffef84bce8db659ac5d00e17ca3f9090d86c7d +DIST utouch-geis-2.0.3.tar.gz 489373 RMD160 189ef8c0aabb5533780481567099f28d52b340e7 SHA1 638ba3dbac084bffe3ba7ae1e4cf38490ff62e4a SHA256 eafb4a6090313bbd7d850c49695760077074cb499055ae655cc6b2c9fa9cbdda +DIST utouch-geis-2.0.6.tar.gz 500458 RMD160 57c849df368c5855fe5d18965fda4f7515fbc7f9 SHA1 a0209218922771aa6b4f42435f2a43d059bf13bd SHA256 7a521be15c30dc88654fc9d358f4a7f28aac5c3c9f3a5476fb80997d58809800 +EBUILD utouch-geis-2.0.10.ebuild 575 RMD160 aeafb48d03b57350f8a9d468847ea61273a9a124 SHA1 8b698b82082601d4e4320cbe42f4af4af535e635 SHA256 e5861640e07f75c34f62732cc29da9ad5372c448f596aea58c783be6022d2c61 +EBUILD utouch-geis-2.0.3.ebuild 575 RMD160 aeafb48d03b57350f8a9d468847ea61273a9a124 SHA1 8b698b82082601d4e4320cbe42f4af4af535e635 SHA256 e5861640e07f75c34f62732cc29da9ad5372c448f596aea58c783be6022d2c61 +EBUILD utouch-geis-2.0.6.ebuild 575 RMD160 aeafb48d03b57350f8a9d468847ea61273a9a124 SHA1 8b698b82082601d4e4320cbe42f4af4af535e635 SHA256 e5861640e07f75c34f62732cc29da9ad5372c448f596aea58c783be6022d2c61 diff --git a/x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild b/x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild new file mode 100644 index 0000000..3b0b8da --- /dev/null +++ b/x11-libs/utouch-geis/utouch-geis-2.0.10.ebuild @@ -0,0 +1,26 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="An implementation of the GEIS (Gesture Engine Interface and Support) interface." +SRC_URI="http://launchpad.net/utouch-geis/2.x/${PV}/+download/utouch-geis-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-geis" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPL-2 LGPL-3" +IUSE="" + +RDEPEND="" +DEPEND="${RDEPEND} + x11-libs/utouch-grail + " + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild b/x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild new file mode 100644 index 0000000..3b0b8da --- /dev/null +++ b/x11-libs/utouch-geis/utouch-geis-2.0.3.ebuild @@ -0,0 +1,26 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="An implementation of the GEIS (Gesture Engine Interface and Support) interface." +SRC_URI="http://launchpad.net/utouch-geis/2.x/${PV}/+download/utouch-geis-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-geis" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPL-2 LGPL-3" +IUSE="" + +RDEPEND="" +DEPEND="${RDEPEND} + x11-libs/utouch-grail + " + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild b/x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild new file mode 100644 index 0000000..3b0b8da --- /dev/null +++ b/x11-libs/utouch-geis/utouch-geis-2.0.6.ebuild @@ -0,0 +1,26 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="An implementation of the GEIS (Gesture Engine Interface and Support) interface." +SRC_URI="http://launchpad.net/utouch-geis/2.x/${PV}/+download/utouch-geis-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-geis" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPL-2 LGPL-3" +IUSE="" + +RDEPEND="" +DEPEND="${RDEPEND} + x11-libs/utouch-grail + " + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-libs/utouch-grail/Manifest b/x11-libs/utouch-grail/Manifest new file mode 100644 index 0000000..b0b9ba8 --- /dev/null +++ b/x11-libs/utouch-grail/Manifest @@ -0,0 +1,2 @@ +DIST utouch-grail-1.0.20.tar.gz 320899 RMD160 34431697bbfcce08071fa9eccaf22d61eb6fa6b1 SHA1 9431b7fc9d22a887a586ccecf319f81b679e2518 SHA256 850fcdd64c3ec2f44c054f5362788cff07e04a263e6edd2708a28773a7a732f6 +EBUILD utouch-grail-1.0.20.ebuild 579 RMD160 5f87ca3bf9b06a74afe5dd6d0a45cdf79b343109 SHA1 b869fd513077ab2c30a880328a7b1b3bf97867dd SHA256 bd707d6d08a3c599753387cf86a7e451a59dc7f4abb98ee348de0cf1d40575e7 diff --git a/x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild b/x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild new file mode 100644 index 0000000..147c477 --- /dev/null +++ b/x11-libs/utouch-grail/utouch-grail-1.0.20.ebuild @@ -0,0 +1,28 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +DESCRIPTION="Gesture Recognition And Instantiation Library" +SRC_URI="http://launchpad.net/utouch-grail/trunk/v${PV}/+download/utouch-grail-${PV}.tar.gz" +HOMEPAGE="https://launchpad.net/utouch-grail" +KEYWORDS="~x86 ~amd64" +SLOT="0" +LICENSE="GPV-3" +IUSE="" + +RDEPEND="" +DEPEND="${RDEPEND} + x11-libs/mtdev + x11-libs/utouch-evemu + x11-libs/utouch-frame + " + +src_compile() { + econf + emake || die +} + +src_install() { + emake DESTDIR="${D}" install || die + +} diff --git a/x11-plugins/e_modules-itask/Manifest b/x11-plugins/e_modules-itask/Manifest new file mode 100644 index 0000000..215d305 --- /dev/null +++ b/x11-plugins/e_modules-itask/Manifest @@ -0,0 +1,3 @@ +EBUILD e_modules-itask-9999.ebuild 338 RMD160 1a17cc0c19652ea65ebe8a972dd7a30d4e75745a SHA1 1ca1d3935f6f91b62905f7720f06c442a72ee4d4 SHA256 326cec0588cd39a189642a27837196ae7164b048a755fce27168e99d632fb035 +MISC ChangeLog 346 RMD160 c33b174f1b6b3eee2053a3a88e72d1cb24cbe592 SHA1 1569c415c86106af3f079e3d9833a49af4f5547b SHA256 04d0cb9415abb5b841d9b63b6420ae07638aff789d5bf0615b6c574396a1c8f0 +MISC metadata.xml 228 RMD160 1890a2965ed780e661e20adcfc4f4cce5f7ca8e9 SHA1 777d2a3ad7f7075c7e75fa5055f3941440e4e875 SHA256 42ea435327140212f3beb05aafebad5053cbad84532f9bb78987de8540c6459a diff --git a/x11-plugins/e_modules-itask/e_modules-itask-9999.ebuild b/x11-plugins/e_modules-itask/e_modules-itask-9999.ebuild new file mode 100644 index 0000000..df03bd3 --- /dev/null +++ b/x11-plugins/e_modules-itask/e_modules-itask-9999.ebuild @@ -0,0 +1,16 @@ +# Copyright 1999-2010 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: $ + +EAPI="2" +ESVN_SUB_PROJECT="E-MODULES-EXTRA" +ESVN_URI_APPEND="${PN#e_modules-}" + +inherit enlightenment + +DESCRIPTION="Itask Module for E17" + +IUSE="static-libs" + +RDEPEND=">=x11-wm/enlightenment-9999" +DEPEND="${RDEPEND}" diff --git a/x11-plugins/e_modules-itask/metadata.xml b/x11-plugins/e_modules-itask/metadata.xml new file mode 100644 index 0000000..832c5fc --- /dev/null +++ b/x11-plugins/e_modules-itask/metadata.xml @@ -0,0 +1,8 @@ + + + +no-herd + + enlightenment@gentoo.org + + diff --git a/x11-proto/inputproto/Manifest b/x11-proto/inputproto/Manifest new file mode 100644 index 0000000..98b6324 --- /dev/null +++ b/x11-proto/inputproto/Manifest @@ -0,0 +1,6 @@ +AUX inputproto-2.0.1-xi2.1.patch 43399 RMD160 5052e0b6865b7beda0e1bdd21fe017bf2a6b1020 SHA1 4ce61ea1d4cfefd6800e7a01b428ba20a4d50b11 SHA256 5bc037a3e9a0b65fa23abd0aceed881f1cdd41e0b70a31f40729595dd34a4c9a +AUX inputproto-2.0.2-xi2.1.patch 7387 RMD160 b3b07056cb2040c8e8385138730a51839fb81829 SHA1 a700bf44de61fa04d932e739128548508afd5717 SHA256 0d2298bdfeb85d8c53220837f4cfbfdcf8977d89f901203a790c191b4b473b09 +DIST inputproto-2.0.1.tar.bz2 152547 RMD160 2da79ca35dca7a84a91db6af3e6278b30bc4da5f SHA1 9c11b99b7cccceafa6b4235a3084523fb7cb4621 SHA256 63663dd88df812738e0efdc52a18868c0756128f09748cbe89c8ec6d17124a44 +DIST inputproto-2.0.2.tar.bz2 155535 RMD160 0e232294719ec25386a1a606776a39641d1cd30a SHA1 a34c01c67aa2ed9058ff19ace0041978b1d8d711 SHA256 64222a590ad4a62a3c8d57805379451769e3329cc5c8c5c1f1fc0d1529ebf005 +EBUILD inputproto-2.0.1-r1.ebuild 809 RMD160 9307e37b77c0184bb1a54d164024adc1b1d5e775 SHA1 0fca9540f7fbfb9045148a4ebebb438cb6e87f51 SHA256 0677969f44fdbacb4d6c4b4390c3ee2d6916897e81828a1a32e31d8d85eccb11 +EBUILD inputproto-2.0.2-r1.ebuild 795 RMD160 cda655ff6941e94608a5b0339af4f67cdd4ae9ab SHA1 420f8a30e4482862b3798ddef0c670ccbc3041b3 SHA256 9f48dc2bbd2e166bc5eab78d8ef8a97825816299acc30edd46885797cdc8e3bb diff --git a/x11-proto/inputproto/files/inputproto-2.0.1-xi2.1.patch b/x11-proto/inputproto/files/inputproto-2.0.1-xi2.1.patch new file mode 100644 index 0000000..05de542 --- /dev/null +++ b/x11-proto/inputproto/files/inputproto-2.0.1-xi2.1.patch @@ -0,0 +1,943 @@ +--- a/XI2.h ++++ b/XI2.h +@@ -32,10 +32,12 @@ + #define Dont_Check 0 + #endif + #define XInput_2_0 7 ++#define XInput_2_1 8 + + + #define XI_2_Major 2 + #define XI_2_Minor 0 ++#define XI_2_1_Minor 1 + + /* Property event flags */ + #define XIPropertyDeleted 0 +@@ -65,6 +67,8 @@ + #define XIGrabtypeKeycode 1 + #define XIGrabtypeEnter 2 + #define XIGrabtypeFocusIn 3 ++#define XIGrabtypeTouchBegin 4 ++#define XIGrabtypeTouchBeginInert 5 + + /* Passive grab modifier */ + #define XIAnyModifier (1U << 31) +@@ -79,6 +83,11 @@ + #define XIAsyncPair 4 + #define XISyncPair 5 + ++/* XIAllowTouchEvents bitmask event-modes */ ++#define XITouchOwnerAccept (1 << 0) ++#define XITouchOwnerRejectEnd (1 << 1) ++#define XITouchOwnerRejectContinue (1 << 2) ++ + /* DeviceChangedEvent change reasons */ + #define XISlaveSwitch 1 + #define XIDeviceChange 2 +@@ -113,15 +122,27 @@ + #define XISlaveKeyboard 4 + #define XIFloatingSlave 5 + +-/* Device classes */ ++/* Device classes: classes that are not identical to Xi 1.x classes must be ++ * numbered starting from 8. */ + #define XIKeyClass 0 + #define XIButtonClass 1 + #define XIValuatorClass 2 ++#define XITouchClass 8 ++#define XITouchValuatorClass 9 + + /* Device event flags (common) */ + /* Device event flags (key events only) */ + #define XIKeyRepeat (1 << 16) +-/* Device event flags (pointer events only) */ ++/* Device event flags (pointer and touch events only) */ ++#define XIPointerEmulated (1 << 16) ++/* Device event flags (touch events only) */ ++#define XITouchPendingEnd (1 << 17) ++ ++/* Touch modes */ ++#define XIDirectTouch 1 ++#define XIDependentTouch 2 ++#define XIIndependentPointer 3 ++#define XISemiMultitouch 4 + + /* XI2 event mask macros */ + #define XISetMask(ptr, event) (((unsigned char*)(ptr))[(event)>>3] |= (1 << ((event) & 7))) +@@ -151,7 +172,12 @@ + #define XI_RawButtonPress 15 + #define XI_RawButtonRelease 16 + #define XI_RawMotion 17 +-#define XI_LASTEVENT XI_RawMotion ++#define XI_TouchBegin 18 ++#define XI_TouchEnd 19 ++#define XI_TouchOwnership 20 ++#define XI_TouchUpdate 21 ++#define XI_TouchUpdateUnowned 22 ++#define XI_LASTEVENT XI_TouchUpdateUnowned + /* NOTE: XI2LASTEVENT in xserver/include/inputstr.h must be the same value + * as XI_LASTEVENT if the server is supposed to handle masks etc. for this + * type of event. */ +@@ -177,5 +203,10 @@ + #define XI_RawButtonPressMask (1 << XI_RawButtonPress) + #define XI_RawButtonReleaseMask (1 << XI_RawButtonRelease) + #define XI_RawMotionMask (1 << XI_RawMotion) ++#define XI_TouchBeginMask (1 << XI_TouchBegin) ++#define XI_TouchEndMask (1 << XI_TouchEnd) ++#define XI_TouchOwnershipChangedMask (1 << XI_TouchOwnershipChanged) ++#define XI_TouchUpdateMask (1 << XI_TouchUpdate) ++#define XI_TouchUpdateUnownedMask (1 << XI_TouchUpdateUnowned) + + #endif /* _XI2_H_ */ +--- a/XI2proto.h ++++ b/XI2proto.h +@@ -60,6 +60,7 @@ + #include + #include + #include ++#include + + /* make sure types have right sizes for protocol structures. */ + #define Window uint32_t +@@ -91,9 +92,10 @@ + #define X_XIDeleteProperty 58 + #define X_XIGetProperty 59 + #define X_XIGetSelectedEvents 60 ++#define X_XIAllowTouchEvents 61 + + /** Number of XI requests */ +-#define XI2REQUESTS (X_XIGetSelectedEvents - X_XIQueryPointer + 1) ++#define XI2REQUESTS (X_XIAllowTouchEvents - X_XIQueryPointer + 1) + /** Number of XI2 events */ + #define XI2EVENTS (XI_LASTEVENT + 1) + +@@ -187,6 +189,31 @@ typedef struct { + uint16_t pad2; + } xXIValuatorInfo; + ++/** ++ * Denotes multitouch capability on a device. ++ */ ++typedef struct { ++ uint16_t type; /**< Always TouchClass */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint16_t sourceid; /**< source device for this class */ ++ uint8_t mode; /**< DirectTouch or DependentTouch */ ++ uint8_t num_touches; /**< Maximum number of touches (0==unlimited) */ ++} xXITouchInfo; ++ ++/** ++ * Denotes a multitouch valuator capability on a device. ++ * One XITouchValuatorInfo describes exactly one valuator (axis) on the device. ++ */ ++typedef struct { ++ uint16_t type; /**< Always TouchValuatorClass */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint16_t sourceid; /**< source device for this class */ ++ uint16_t number; /**< Valuator number */ ++ Atom label; /**< Axis label */ ++ FP3232 min; /**< Min value */ ++ FP3232 max; /**< Max value */ ++ uint32_t resolution; /**< Resolutions in units/m */ ++} xXITouchValuatorInfo; + + /** + * Used to select for events on a given window. +@@ -771,6 +798,20 @@ typedef struct { + } xXIGetPropertyReply; + #define sz_xXIGetPropertyReply 32 + ++/** ++ * Accept or reject a grabbed touch sequence. ++ */ ++typedef struct { ++ uint8_t reqType; ++ uint8_t ReqType; /**< Always ::X_XIAllowTouchEvents */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint32_t touchid; ++ uint16_t deviceid; ++ uint8_t mode; /**< bitmask */ ++ uint8_t pad; ++} xXIAllowTouchEventsReq; ++#define sz_xXIAllowTouchEventsReq 12 ++ + /************************************************************************************* + * * + * EVENTS * +@@ -856,7 +897,27 @@ typedef struct + } xXIDeviceChangedEvent; + + /** +- * Default input event for pointer or keyboard input. ++ * The owner of a touch stream has passed on ownership to another client. ++ */ ++typedef struct ++{ ++ uint8_t type; /**< Always GenericEvent */ ++ uint8_t extension; /**< XI extension offset */ ++ uint16_t sequenceNumber; ++ uint32_t length; /**< Length in 4 byte units */ ++ uint16_t evtype; /**< XI_TouchOwnership */ ++ uint16_t deviceid; /**< Device that has changed */ ++ Time time; ++ uint16_t sourceid; /**< Source of the new classes */ ++ uint16_t pad0; ++ uint32_t touchid; ++ uint32_t flags; ++ uint32_t pad1; ++ uint32_t pad2; ++} xXITouchOwnershipEvent; ++ ++/** ++ * Default input event for pointer, keyboard or touch input. + */ + typedef struct + { +--- a/XI2proto.txt ++++ b/XI2proto.txt +@@ -1,11 +1,20 @@ + + The X Input Extension + Version 2.0 ++ Version 2.1 + + Peter Hutterer + peter.hutterer@redhat.com + Red Hat, Inc. + ++ Daniel Stone ++ daniel@fooishbar.org ++ Collabora, Ltd. ++ ++ Chase Douglas ++ chase.douglas@canonical.com ++ Canonical, Ltd. ++ + + + 1. Introduction +@@ -31,6 +40,41 @@ used on applications employing the core + issues by enabling devices to be both extended and core devices and providing + device information in each event (with the exception of core events). + ++1.1 X Input Extension version 2.1 (XI 2.1) ++XI 2.1 introduces support for multi-touch devices. The traditional ++pointer/keyboard approach enforced by XI 2.0 with the master/slave device ++hierarchy is not always suitable for multi-touch devices that can provide a ++dynamic number of multiple independent input points per physical device. ++Furthermore, as such devices are often direct input devices (e.g. touchscreens, ++able to focus without a pointer), the virtual abstraction of master devices is ++not always necessary. ++ ++The additions in XI 2.1 aim to: ++- support a dynamic number of simultaneous touch points, ++- support devices that are both multi-touch and traditional pointer devices, ++- while supporting pre-XI2.1 clients through emulation of XInput and core ++ pointer events. ++ ++XI 2.1 caters for two modes of touch input devices: ++- direct multi-touch input devices such as touch screens. These devices ++ provide independent touchpoints that can occur anywhere on the screen and ++ are usually the result of direct touch interaction. ++- indirect touch input devices such as multi-touch trackpads. These devices ++ provide independent touchpoints that may need to be interpreted ++ relative to the current position of the pointer on that same device. Such ++ interactions are usually the result of a gesture performed on the device. ++ ++A device may change its touch mode at runtime. Clients are informed which ++type of touch device they are dealing with. See XIQueryDevice for more ++information. ++ ++Touch device support is only available to clients supporting version 2.1 or ++later of the X Input Extension. Clients must use the XIQueryVersion request to ++announce support of this version. ++ ++XI 2.1 requires devices to track touch points over time. Devices that cannot ++do so in hardware must employ software trackers to be usable with XI 2.1. ++ + ❧❧❧❧❧❧❧❧❧❧❧ + + 2. Notations used in this document +@@ -149,7 +193,150 @@ to P is only attempted if neither the XI + delivered on W. Once an event has been delivered as either XI or core event, + event processing stops. + +-4.4. The ClientPointer principle ++4.4 Touch device support ++ ++4.4.1 Touch event sequences ++ ++Touch event processing differs from normal event processing in a few ways, ++most notably in that touch events are processed partially out-of-band from ++pointer and keyboard events. ++ ++Touch input follows a three-stage cycle: init - move - move - ... - destroy, ++i.e. “init” the sequence by touching the device, “move” the current touch ++location any number of times, and finally “destroy” the sequence by ceasing ++to touch the device. The init and destroy stage of this sequence are always ++present, while the move stage is optional. Within this document, the term ++"touch sequence" is used to describe the above chain of events. A client ++wishing to receive touch events must register for at least TouchBegin, ++TouchUpdate, and TouchEnd simultaneously. It may also select for ++TouchUpdateUnowned and TouchOwnership events if it wants to receive the full ++touch stream while other clients own or have active grabs involving the touch. ++An example of this usage is a touch painting program that paints touches while ++a gesture recognizer has an active grab. Such clients must be able to undo state ++if the touch ends without the client receiving ownership of the touch. ++ ++A touch sequence is only considered to be meaningful in its entirety: clients ++may not capture part of a touch sequence, interpret only that part, and then ++pass a partial touch sequence on to the next client. To this end, all clients ++with “grabs” on the window hierarchy for a touch sequence receive events from ++that touch sequence, as well as potentially the client with the deepest ++selection (i.e. furthest from the root window). Clients currently in control of ++the touch sequence receive TouchUpdate events, whereas clients not in control ++receive receive TouchUpdateUnowned events. ++ ++Touch grabs are similar to standard input event grabs in that they take ++precedence over selections and are searched from the root window to the child ++window. The first grab found for a touch sequence will be the owner of that ++touch sequence, however events for that touch sequence will continue to be ++delivered to all clients with grabs in the window tree, as well as potentially ++the client with the deepest selection. The first client may either “accept” the ++touch, which claims the touch sequence and stops delivery to all other clients ++for the duration of the touch sequence, or “reject” the touch sequence, which ++will remove that client from the delivery set and pass ownership on to the ++next client. When a client, including the initial owner, becomes the owner of a ++touch, it will receive a TouchOwnership event. When an owning client accepts a ++touch, further clients receiving unowned events will receive TouchEnd events. ++ ++Clients selecting for touch events may select for either unowned events or only ++owned events. The event stream for an unowned selection is identical to a touch ++grab. When a client does not select for unowned and ownership events, it will ++receive a TouchBegin event when it becomes the owner of a touch stream. ++TouchUpdate and TouchEnd events will be received in the same manner as for touch ++grabs. ++ ++A TouchEnd event will always be sent to a client when it will receive no more ++events from a particular touch, regardless of why (grab or selection removed, ++owner accepted, the client having rejected that touch, etc). ++ ++4.4.2 Touch device modes ++ ++Touch devices come in many different forms with varying capabilities. The ++following device modes are defined for this protocol: ++ ++DirectTouch: ++ These devices map their input region to a subset of the screen region. Touch ++ events are delivered according to where the touch occurs in the mapped ++ screen region. An example of a DirectTouch device is a touchscreen. ++ ++DependentTouch: ++ These devices do not have a direct correlation between a touch location and ++ a position on the screen. Touch events are delivered according to the ++ location of the pointer on screen. An Example of a DependentTouch device ++ is a trackpad. ++ ++IndependentPointer: ++ These devices do not have any correlation between touch events and pointer ++ events. IndependentPointer devices are a subset of DependentTouch devices. ++ An example of an IndependentPointer device is a mouse with a touch surface. ++ ++SemiMultitouch: ++ These devices may report touch events that correlate to the two opposite ++ corners of the bounding box of all touches. The number of active touch ++ sequences represents the number of touches on the device, and the position ++ of any given touch event will be equal to either of the two corners of the ++ bounding box. However, the physical location of the touches is unknown. ++ SemiMultitouch devices are a subset of DependentTouch devices. Although ++ DirectTouch and IndependentPointer devices may also be SemiMultitouch ++ devices, such devices are not allowed through this protocol. ++ ++A device is identified as only one of the device modes above at any time. For ++the purposes of this protocol, IndependentPointer and SemiMultitouch devices are ++treated the same as DependentTouch devices unless stated otherwise. ++ ++4.4.3 Touch event delivery ++ ++Window sets for event propagation for direct device touches contain the windows ++from the root to the child in which the touch originated. ++ ++Dependent device window sets depend on whether other touches are active. For ++the first dependent touch on a device, the window set contains the windows from ++the root to the current window underneath the position of the device's pointer. ++For subsequent touches on the device, the window set is identical to the window ++set of the first touch. Once all touches have been released, the window set is ++reset and re-calculated on the first subsequent touch. ++ ++The delivery of touch events is not changed by any modifications to the window ++hierarchy after the window set has been determined for the touch, nor is it ++affected by new grabs or selections. ++ ++No touches from a dependent device may begin while the device is floating, as ++it does not have an associated pointer position to focus events. ++ ++Many touch devices will emit pointer events as well, usually by mapping one ++touch sequence to pointer events. In these cases, events for both the pointer ++and its associated touch sequence will have the XIPointerEmulated flag set. ++ ++4.4.4 Pointer emulation for direct touch devices ++ ++In order to facilitate backwards compatibility with legacy clients, direct touch ++devices will emulate pointer events. Pointer emulation events will only be ++delivered through the attached master device; no pointer events will be emulated ++for floating touch devices. Further, only one touch from any attached slave ++touch device may be emulated per master device at any time. ++ ++A touch event stream must be delivered to clients in a mutually exclusive ++fashion. This extends to emulated pointer events. For the purposes of ++exclusivity, emulated pointer events between an emulated button press and ++button release are considered. An emulated button press event is considered ++exclusively delivered once it has been delivered through an event selection, an ++asynchronous pointer grab, or it and a further event are delivered through a ++synchronous pointer grab. ++ ++Touch and pointer grabs are also mutually exclusive. For a given window, any ++touch grab is activated first. If the touch grab is rejected, the pointer grab ++is activated. If an emulated button press event is exclusively delivered to the ++grabbing client as outlined above, the touch sequence is ended for all clients ++still listening for unowned events. Otherwise, when the pointer stream is ++replayed the next window in the window set is checked for touch grabs. ++ ++If the touch sequence is not exclusively delivered to any client through a grab, ++the touch and emulated pointer events may be delivered to clients selecting for ++the events. Event propagation for the touch sequence ends at the first client ++selecting for touch and/or pointer events. Note that a client may receive both ++touch and emulated pointer events for the same touch sequence through event ++selection. ++ ++4.5. The ClientPointer principle + + Many core protocol and some extension requests are ambiguous when multiple + master devices are available (e.g. QueryPointer does not specfy which pointer). +@@ -271,7 +458,7 @@ are required to be 0. + name: LISTofCHAR8 + classes: LISTofCLASS } + +- CLASS { BUTTONCLASS, KEYCLASS, AXISCLASS } ++ CLASS { BUTTONCLASS, KEYCLASS, AXISCLASS, TOUCHCLASS*, TOUCHAXISCLASS* } + + BUTTONCLASS { type: ButtonClass + length: CARD16 +@@ -296,6 +483,27 @@ are required to be 0. + value: FP3232 + resolution: CARD32 } + ++ TOUCHCLASS* { type: TouchClass ++ length: CARD16 ++ sourceid: CARD16 ++ mode: TOUCHMODE ++ num_touches: CARD16 } ++ ++ TOUCHAXISCLASS* { ++ type: TouchAxisClass ++ length: CARD16 ++ sourceid: CARD16 ++ axisnumber: CARD16 ++ label: ATOM ++ min: FP3232 ++ max: FP3232 ++ resolution: CARD32 } ++ ++ TOUCHMODE* { DirectTouch, DependentTouch, IndependentPointer, ++ SemiMultitouch } ++ ++ * since XI 2.1 ++ + XIQueryDevice details information about the requested input devices. + + devices +@@ -397,6 +605,50 @@ are required to be 0. + An axis in Relative mode may specify min and max as a hint to the + client. If no min and max information is available, both must be 0. + ++ XI 2.1: ++ ++ TouchClass: ++ type ++ Always TouchClass. ++ length ++ Length in 4 byte units. ++ sourceid ++ The device this class originates from. ++ mode ++ The device type of the touch device. ++ num_touches ++ The maximum number of simultaneous touchpoints the device may send. ++ If num_touches is 0, the number of supported touches is unknown or ++ unlimited. ++ ++ A device with a TouchClass must provide one or more TOUCHAXISCLASS ++ specifiers. ++ ++ TouchAxisClass: ++ type ++ Always TouchAxisClass. ++ length ++ Length in 4 byte units. ++ sourceid ++ The device this class originates from. ++ axisnumber ++ Axis number of this axis. The axis number is in device-native ++ order and potential axis mappings are ignored. ++ label ++ Atom specifying the axis name. An Atom of None specifies an unlabeled ++ axis. ++ min ++ Minimum value for this axis. ++ max ++ Maximum value for this axis. ++ resolution ++ Resolution in counts/meter. ++ ++ Devices generating touch events must provide exactly one TouchClass and ++ two or more TouchAxisClasses. TouchAxisClasses and AxisClasses are not ++ interchangable. A TouchAxisClass may only be part of a touch event, ++ whereas an AxisClass may only be part of non-touch events. ++ + ┌─── + XISelectEvents + window: Window +@@ -439,6 +691,14 @@ are required to be 0. + The mask for XIHierarchyEvents may only be selected for XIAllDevices. + Setting it for any other device results in a BadValue error. + ++ A client selecting for any of XI_TouchBegin, XI_TouchOwnership, ++ XI_TouchUpdate or XI_TouchEnd must select for all three events at the ++ same time, else BadValue will be returned. A client selecting for ++ XI_TouchUpdateUnowned must select for all three of the other touch ++ events. If the selection for these touch events overlaps a current ++ selection by another client (e.g. selecting for a specific device when ++ another client has a selection for XIAllDevices), a BadAccess error occurs. ++ + ┌─── + XIGetSelectedEvents + window: Window +@@ -794,7 +1054,8 @@ are required to be 0. + This request actively grabs control of the specified input device. Further + input events from this device are reported only to the grabbing client. + This request overides any previous active grab by this client for this +- device. ++ device. This request does not, however, affect the processing of XI 2.1 ++ touch events. + + deviceid + The device to grab. +@@ -999,7 +1260,8 @@ are required to be 0. + └─── + + GRABTYPE { GrabtypeButton, GrabtypeKeycode, GrabtypeEnter, +- GrabtypeFocusIn} ++ GrabtypeFocusIn, GrabtypeTouchBegin, ++ GrabtypeTouchBeginInert } + + GRABMODIFIERINFO { status: Access + modifiers: CARD32 } +@@ -1015,7 +1277,8 @@ are required to be 0. + AllMasterDevices. + detail + The button number, or key symbol to grab for. +- Must be 0 for GrabtypeEnter and GrabtypeFocusIn. ++ Must be 0 for GrabtypeEnter, GrabtypeFocusIn, and ++ GrabtypeTouchBegin. + grab_type + The type of grab to establish. + grab_window +@@ -1030,6 +1293,8 @@ are required to be 0. + releasing XIAllowEvents request or until the device grab is + released. Actual device input events are not lost while the device + is frozen; they are simply queued for later processing. ++ Must be Asynchronous for GrabtypeTouchBegin and ++ GrabtypeTouchBeginInert (see section 4.4). + mask_len + Length of mask in 4 byte units. + mask +@@ -1087,6 +1352,16 @@ are required to be 0. + - a passive grab of the same grab_type + modifier combination does not + does not exist on an ancestor of grab_window. + ++ Or if grab_type is GrabtypeTouchBegin or GrabtypeTouchBeginInert, a ++ touch grab (see section 4.4) begins if: ++ - a touch begins in grab_window or one of its ancestors, and ++ - the specified modifier keys are down ++ Ownership of the touch sequence is granted to the grabbing client if: ++ - grab_type is not GrabtypeTouchBeginInert, and ++ - a TouchBegin, TouchBeginInert, or pointer passive grab with the same ++ modifier set does not exist on an ancestor of grab_window, or all ++ applicable grabs have released ownership. ++ + A modifier of GrabAnyModifier is equivalent to issuing the request for + all possible modifier combinations (including no modifiers). A client + may request a grab for GrabAnyModifier and explicit modifier +@@ -1097,6 +1372,9 @@ are required to be 0. + A GrabtypeEnter or GrabtypeFocusIn grab is released when the + pointer or focus leaves the window and all of its descendants, + independent of the state of modifier keys. ++ A GrabtypeTouchBegin or GrabtypeTouchBeginInert grab is released when ++ the touch sequence ends, or a client uses XIAllowTouchEvents to reject ++ the touch and remove itself from the touch delivery sequence. + Note that the logical state of a device (as seen by means of the + protocol) may lag the physical state if device event processing is + frozen. +@@ -1109,10 +1387,11 @@ are required to be 0. + with the same button or keycode and modifier combination, the + failed modifier combinations is returned in modifiers_return. If some + other client already has issued an XIPassiveGrabDevice request of +- grab_type XIGrabtypeEnter or XIGrabtypeFocusIn with the same +- grab_window and the same modifier combination, the failed modifier +- combinations are returned in modifiers_return. If num_modifiers_return +- is zero, all passive grabs have been successful. ++ grab_type XIGrabtypeEnter, XIGrabtypeFocusIn, XIGrabtypeTouchBegin, or ++ XIGrabtypeTouchBeginInert with the same grab_window and the same ++ modifier combination, the failed modifier combinations are returned ++ in modifiers_return. If num_modifiers_return is zero, all passive ++ grabs have been successful. + + If a button grab or enter grab activates, EnterNotify and LeaveNotify + events with mode Grab are generated as if the pointer were to suddenly +@@ -1133,6 +1412,11 @@ are required to be 0. + XIPassiveUngrabNotify are generated and sent to the grabbing client + before the grab deactivates. + ++ See section 4.4 for additional notes on touch grabs, as they do not ++ behave like traditional grabs: in particular, they do not freeze the ++ device, and delivery of touch events continues even if the device is ++ frozen due to a grab by another client. ++ + ┌─── + XIPassiveUngrabDevice + deviceid: DEVICEID +@@ -1149,7 +1433,8 @@ are required to be 0. + The device to establish the passive grab on. + detail + The button number or key symbol to ungrab. +- Must be 0 for GrabtypeEnter and GrabtypeFocusIn. ++ Must be 0 for GrabtypeEnter, GrabtypeFocusIn, and ++ GrabtypeTouchBegin. + grab_type + The type of grab to establish. + grab_window +@@ -1308,6 +1593,44 @@ are required to be 0. + deleted from the device, and a XIPropertyNotify event is generated on + the device. + ++ ┌─── ++ XIAllowTouchEvents: (since XI 2.1) ++ deviceid: DEVICEID ++ touchid: CARD32 ++ event_mode: ALLOWTOUCHMODE ++ flags: SETofALLOWTOUCHFLAGS ++ └─── ++ ++ ALLOWTOUCHMODE { TouchOwnerAccept, TouchOwnerRejectEnd, ++ TouchOwnerRejectContinue } ++ ALLOWTOUCHFLAGS (none currently defined) ++ ++ The XIAllowTouchEvents request allows the current owner of a touch ++ sequence to direct further delivery. ++ ++ deviceid ++ The slave device ID for a grabbed touch sequence. ++ touchid ++ The ID of the touch sequence to modify. ++ event_mode ++ Given TouchOwnerAccept, the client is deemed to have taken control ++ of the touch sequence; TouchEnd events will be sent to all other ++ clients listening to the touch sequence, and they will no longer ++ receive any TouchUpdate events. ++ Given TouchOwnerRejectEnd, the client is no longer interested in the ++ touch sequence, and will receive a TouchEnd event; ownership will be ++ passed on to the next listener. ++ Given TouchOwnerRejectContinue, the client is not interested in ++ ownership, but still wishes to receive TouchUpdate events; ++ ownership will be passed on to the next listener. ++ flags ++ A bitmask of applicable flags. ++ ++ A BadValue error occurs if the touch ID is invalid, or BadAccess if this ++ client is not the current owner of the specified touch ID. BadValue errors ++ also occur if an invalid value is given for event_mode. Any flags not ++ understood by the server will be ignored. ++ + + 8. Events: + +@@ -1338,6 +1661,12 @@ Version 2.0: + FocusIn + FocusOut + PropertyEvent ++Version 2.1: ++ TouchBegin ++ TouchUpdate ++ TouchUpdateUnowned ++ TouchOwnership ++ TouchEnd + + All events have a set of common fields specified as EVENTHEADER. + +@@ -1481,15 +1810,19 @@ EVENTHEADER { type: + + DEVICEEVENTFLAGS (all events): none + DEVICEEVENTFLAGS (key events only): { KeyRepeat } +- DEVICEEVENTFLAGS (pointer events only): none ++ DEVICEEVENTFLAGS (pointer and touch events only): { PointerEmulated } ++ DEVICEEVENTFLAGS (touch events only): { TouchPendingEnd } + + An XIDeviceEvent is generated whenever the logical state of a device + changes in response to a button press, a button release, a motion, a key + press or a key release. The event type may be one of KeyPress, + KeyRelease, ButtonPress, ButtonRelease, Motion. + ++ XI 2.1: The event type may also be TouchBegin, TouchUpdate, ++ TouchUpdateUnowned, or TouchEnd. ++ + detail +- The button number or key code, or 0. ++ The button number, key code, touch ID, or 0. + root + event + child +@@ -1517,8 +1850,12 @@ EVENTHEADER { type: + Button state before the event. + valuators + Bitmask of valuators provided in axisvalues. ++ XI 2.1: For event types TouchBegin, TouchUpdate, TouchUpdateUnowned, and ++ TouchEnd, the valuators are those specified as TouchAxisClass. + axisvalues + Valuator data in device-native resolution. ++ XI 2.1: For event types TouchBegin, TouchUpdate, TouchUpdateUnowned, and ++ TouchEnd, the valuators are those specified as TouchAxisClass. + flags + Miscellaneous information about this event; the union of the + common flag set and either the key or pointer flag set, +@@ -1526,6 +1863,20 @@ EVENTHEADER { type: + KeyRepeat means that this event is for repeating purposes, and + the physical state of the key has not changed. This is only + valid for KeyPress events. ++ PointerEmulated means that this event is an emulated pointer event ++ caused by a touch device. A client listening to touch events and pointer ++ events should ignore PointerEmulated events to avoid duplicate ++ processing. This is only valid for pointer events (MotionNotify, ++ ButtonPress, ButtonRelease). ++ TouchAccepted (for TouchEnd events only) means that the current owner ++ of the touch stream has “accepted” it, and this client will not receive ++ any further events from that touch sequence. ++ TouchPendingEnd (for touch events only) means that the touch ++ has physically ended, however another client still holds a grab, so the ++ touch should be considered alive until all grabbing clients have ++ accepted or passed on ownership. The touch will not generate any ++ further motion events once an event with TouchPendingEnd has been ++ received. + + Modifier state in mods is detailed as follows: + base_mods +@@ -1543,6 +1894,27 @@ EVENTHEADER { type: + locked_group + XKB locked group state. + ++ XI 2.1: ++ ++ A TouchBegin event is generated whenever a new touch sequence initializes ++ A TouchEnd event is generated whenever a touch sequence ceases. A ++ TouchUpdate event is generated whenever a touch axis valuator value ++ changes, or a flag (e.g. pending end) has changed for that touch sequence; ++ this may result in a TouchUpdate event being sent with zero valuators. A ++ TouchOwnership event is sent when a client becomes the owner of a touch. ++ ++ The average finger size is significantly larger than one pixel. The ++ selection of the hotspot of a touchpoint is implementation dependent and ++ may not be the logical center of the touch. ++ ++ Touch tracking IDs are provided in the detail field of touch events. Its ++ value is always provided in every touch event. Tracking IDs are ++ represented as unsigned 32-bit values and increase in value for each new ++ touch, wrapping back to 0 upon reaching the numerical limit of IDs. IDs are ++ unique per each slave touch device. ++ ++ Touch events do not generate enter/leave events. ++ + ┌─── + RawEvent + EVENTHEADER +@@ -1673,5 +2045,107 @@ EVENTHEADER { type: + what + Specifies what has been changed. + ++XI 2.1: ++ ++ ┌─── ++ TouchOwnershipEvent (since XI 2.1): ++ EVENTHEADER ++ sourceid: DEVICEID ++ touchid: CARD32 ++ flags: SETofTOUCHOWNERSHIPFLAGS ++ └─── ++ ++ TOUCHOWNERSHIPFLAGS: (none currently defined) ++ ++ A TouchOwnershipEvent indicates that ownership has changed, and the client ++ is now the owner of the touch sequence specified by touchid. ++ ++ sourceid ++ The source device that originally generated the event. ++ touchid ++ The identifier of the touch sequence. ++ flags ++ A bitmask of flags for this event. ++ + + ❧❧❧❧❧❧❧❧❧❧❧ ++ ++ ++Appendix A: XI 2.1 Use-cases ++ ++All use-cases that include the receiving and processing of touch events ++require the client to announce XI 2.1 support in the XIQueryVersion request. ++ ++∙ Client C wants to process touch events from a device D on window W. ++ ⊳ C calls XISelectEvent for ++ XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W. ++ ⊳ C receives TouchBegin whenever a touch sequence starts within ++ W's borders. ++ ⊳ C receives a TouchOwnership event indicating that it is now the owner ++ of the touch sequence. ++ ⊳ C receives TouchUpdate events whenever a touch axis valuator value ++ changes for a touch sequence it received a TouchBegin event for. ++ ⊳ C receives TouchEnd whenever a touch it received an TouchBegin event ++ for ceases. ++ ++∙ Client C wants to process touch events from a device D on window W, while ++ client I wants to pre-process these events. ++ ⊳ C calls XISelectEvent for ++ XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W. ++ ⊳ I calls XIPassiveGrab for ++ XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on a parent ++ window of W. ++ ⊳ I receives TouchBegin whenever a touch begins within window W, as well ++ as a TouchOwnership event indicating that it currently owns the touch ++ sequence. C receives a TouchBegin event as well, but without ++ TouchOwnership. ++ ⊳ When a touch axis valuator changes in this touch sequence, I receives a ++ TouchUpdate event, while C receives a TouchUpdateUnowned event. I may ++ process the events to determine if it is going to claim or reject the ++ touch, whereas C may perform reversible processing. ++ ⊳ If I decides it is going to claim the event for its exclusive ++ processing, it calls XIAllowTouchEvents with the XITouchOwnerAccept flag ++ set; at this point, C receives a TouchEnd event with the ++ TouchAccepted flag set, and undoes any processing it may have done ++ on the touch sequence. Further TouchUpdate events are delivered only ++ to I. ++ ⊳ Alternately, if I decides it does not want to receive further events from ++ this touch sequence, it calls XIAllowTouchEvents with the ++ XITouchOwnerReject flag set; at this point, I receives a TouchEnd event ++ confirming that it has rejected the touch. C receives a TouchOwnership ++ event confirming that it is now the new owner of the touch, and further ++ TouchUpdate events are delivered only to C. As C now owns the touch, ++ it is free to perform irreversible processing of the sequence. ++ ⊳ When the touch physically ceases, a TouchEnd event is sent to all ++ clients still receiving TouchUpdate events. ++ ++∙ Client C wants to process touch events from a device D on window W, while ++ client I wants to process pointer events on window Y, which is W's parent. ++ ⊳ I calls XIPassiveGrab for XI_{ButtonPress,MotionNotify,ButtonRelease} ++ from D on Y. ++ ⊳ C calls XISelectEvent for ++ XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W. ++ ⊳ I receives a ButtonPress event whenever a touch begins within W, and is ++ considered the owner of the event. C receives a TouchBegin event, but ++ does not receive a TouchOwnership event. ++ ⊳ When the touchpoint moves, I will receive a MotionNotify event, and C ++ will receive a TouchUpdateUnowned event. Event delivery to I will be ++ subject to the standard delivery mechanism (including being queued if ++ the device is frozen, et al), while C receives events as soon as they ++ are processed by the server. ++ ⊳ I may assert ownership by calling XIAllowEvents on Y with AsyncDevice, ++ which will cause all further events to be sent only to I, with a ++ TouchEnd event being sent to C. ++ ⊳ Alternately, I may assert disinterest by calling XIAllowEvents on Y ++ with ReplayDevice, which will cause no further events from that touch ++ to be sent to I, and a TouchOwnership event to be sent to C, with ++ subsequent motion events being sent as TouchMotion. ++ ++∙ Driver DRV provides touch support from tracked device D: ++ ⊳ DRV initializes a TouchClass for the device and a TouchAxisClass for ++ each axis available on the device. ++ ⊳ DRV parses D's device protocol and selects one touch sequence to be ++ emulated as pointer event. ++ ⊳ DRV calls the respective input driver API with the touch sequence ++ data. The touch sequence emulating a pointer has the respective flag ++ set. DRV does not submit pointer data for any touchpoint. +--- a/XIproto.txt ++++ b/XIproto.txt +@@ -1650,7 +1650,7 @@ + feedback class BellFeedback, which is reported in the + BellFeedbackState structure. The members of that structure are: + +- CLASS String: ++ CLASS Bell: + [class: CARD8 + length: CARD16 + feedback id: CARD8 +@@ -1676,7 +1676,7 @@ + class Led, which is reported in the LedFeedbackState structure. + The members of that structure are: + +- CLASS String: ++ CLASS Led: + [class: CARD8 + length: CARD16 + feedback id: CARD8 +@@ -1781,7 +1781,7 @@ + feedback id: CARD8 + int_to_display: INT32] + +- Some devices are capable of displaying an string. This is done ++ Some devices are capable of displaying a string. This is done + using feedback class StringFeedbackClass using the + StringFeedbackCtl structure. The members of that structure are + as follows: +@@ -1978,29 +1978,19 @@ Controlling Device Encoding + A server can impose restrictions on how modifiers can be + changed (for example, if certain keys do not generate up + transitions in hardware or if multiple keys per modifier are +- not supported). The status reply is Failed if some such +- restriction is violated, and none of the modifiers are changed. ++ not supported). If some such restriction is violated, the status ++ reply is MappingFailed, and none of the modifiers are changed. + +- If the new non-zero keycodes specified for a modifier differ +- from those currently defined, and any (current or new) keys for +- that modifier are logically in the down state, then the status +- reply is Busy, and none of the modifiers are changed. ++ If the new keycodes specified for a modifier differ from those ++ currently defined and any (current or new) keys for that ++ modifier are in the logically down state, the status reply is ++ MappingBusy, and none of the modifiers are changed. + + This request generates a DeviceMappingNotify event on a Success + status. The DeviceMappingNotify event will be sent only to + those clients that have expressed an interest in receiving that + event via the XSelectExtensionEvent request. + +- A X server can impose restrictions on how modifiers can be +- changed, for example, if certain keys do not generate up +- transitions in hardware or if multiple modifier keys are not +- supported. If some such restriction is violated, the status +- reply is MappingFailed , and none of the modifiers are changed. +- If the new keycodes specified for a modifier differ from those +- currently defined and any (current or new) keys for that +- modifier are in the logically down state, the status reply is +- MappingBusy, and none of the modifiers are changed. +- + 2.20 Controlling Button Mapping + + These requests are analogous to the core GetPointerMapping and +@@ -2350,7 +2340,7 @@ Controlling Device Encoding + specified device and window. Events generated by SetDeviceFocus + when the device is not grabbed have mode Normal. Events + generated by SetDeviceFocus when the device is grabbed have +- mode WhileGrabbed. Events generated when a device grab actives ++ mode WhileGrabbed. Events generated when a device grab activates + have mode Grab, and events generated when a device grab + deactivates have mode Ungrab. + diff --git a/x11-proto/inputproto/files/inputproto-2.0.2-xi2.1.patch b/x11-proto/inputproto/files/inputproto-2.0.2-xi2.1.patch new file mode 100644 index 0000000..2f07fab --- /dev/null +++ b/x11-proto/inputproto/files/inputproto-2.0.2-xi2.1.patch @@ -0,0 +1,191 @@ +--- a/XI2.h ++++ b/XI2.h +@@ -32,10 +32,12 @@ + #define Dont_Check 0 + #endif + #define XInput_2_0 7 ++#define XInput_2_1 8 + + + #define XI_2_Major 2 + #define XI_2_Minor 0 ++#define XI_2_1_Minor 1 + + /* Property event flags */ + #define XIPropertyDeleted 0 +@@ -65,6 +67,8 @@ + #define XIGrabtypeKeycode 1 + #define XIGrabtypeEnter 2 + #define XIGrabtypeFocusIn 3 ++#define XIGrabtypeTouchBegin 4 ++#define XIGrabtypeTouchBeginInert 5 + + /* Passive grab modifier */ + #define XIAnyModifier (1U << 31) +@@ -79,6 +83,11 @@ + #define XIAsyncPair 4 + #define XISyncPair 5 + ++/* XIAllowTouchEvents bitmask event-modes */ ++#define XITouchOwnerAccept (1 << 0) ++#define XITouchOwnerRejectEnd (1 << 1) ++#define XITouchOwnerRejectContinue (1 << 2) ++ + /* DeviceChangedEvent change reasons */ + #define XISlaveSwitch 1 + #define XIDeviceChange 2 +@@ -113,15 +122,27 @@ + #define XISlaveKeyboard 4 + #define XIFloatingSlave 5 + +-/* Device classes */ ++/* Device classes: classes that are not identical to Xi 1.x classes must be ++ * numbered starting from 8. */ + #define XIKeyClass 0 + #define XIButtonClass 1 + #define XIValuatorClass 2 ++#define XITouchClass 8 ++#define XITouchValuatorClass 9 + + /* Device event flags (common) */ + /* Device event flags (key events only) */ + #define XIKeyRepeat (1 << 16) +-/* Device event flags (pointer events only) */ ++/* Device event flags (pointer and touch events only) */ ++#define XIPointerEmulated (1 << 16) ++/* Device event flags (touch events only) */ ++#define XITouchPendingEnd (1 << 17) ++ ++/* Touch modes */ ++#define XIDirectTouch 1 ++#define XIDependentTouch 2 ++#define XIIndependentPointer 3 ++#define XISemiMultitouch 4 + + /* XI2 event mask macros */ + #define XISetMask(ptr, event) (((unsigned char*)(ptr))[(event)>>3] |= (1 << ((event) & 7))) +@@ -151,7 +172,12 @@ + #define XI_RawButtonPress 15 + #define XI_RawButtonRelease 16 + #define XI_RawMotion 17 +-#define XI_LASTEVENT XI_RawMotion ++#define XI_TouchBegin 18 ++#define XI_TouchEnd 19 ++#define XI_TouchOwnership 20 ++#define XI_TouchUpdate 21 ++#define XI_TouchUpdateUnowned 22 ++#define XI_LASTEVENT XI_TouchUpdateUnowned + /* NOTE: XI2LASTEVENT in xserver/include/inputstr.h must be the same value + * as XI_LASTEVENT if the server is supposed to handle masks etc. for this + * type of event. */ +@@ -177,5 +203,10 @@ + #define XI_RawButtonPressMask (1 << XI_RawButtonPress) + #define XI_RawButtonReleaseMask (1 << XI_RawButtonRelease) + #define XI_RawMotionMask (1 << XI_RawMotion) ++#define XI_TouchBeginMask (1 << XI_TouchBegin) ++#define XI_TouchEndMask (1 << XI_TouchEnd) ++#define XI_TouchOwnershipChangedMask (1 << XI_TouchOwnershipChanged) ++#define XI_TouchUpdateMask (1 << XI_TouchUpdate) ++#define XI_TouchUpdateUnownedMask (1 << XI_TouchUpdateUnowned) + + #endif /* _XI2_H_ */ +--- a/XI2proto.h.ori/XI2proto.h 2011-06-07 06:14:26.000000000 +0200 ++++ b/XI2proto.h 2011-06-19 17:39:44.085856683 +0200 +@@ -92,9 +92,10 @@ + #define X_XIDeleteProperty 58 + #define X_XIGetProperty 59 + #define X_XIGetSelectedEvents 60 ++#define X_XIAllowTouchEvents 61 + + /** Number of XI requests */ +-#define XI2REQUESTS (X_XIGetSelectedEvents - X_XIQueryPointer + 1) ++#define XI2REQUESTS (X_XIAllowTouchEvents - X_XIQueryPointer + 1) + /** Number of XI2 events */ + #define XI2EVENTS (XI_LASTEVENT + 1) + +@@ -188,6 +189,32 @@ + uint16_t pad2; + } xXIValuatorInfo; + ++/** ++ * Denotes multitouch capability on a device. ++ */ ++typedef struct { ++ uint16_t type; /**< Always TouchClass */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint16_t sourceid; /**< source device for this class */ ++ uint8_t mode; /**< DirectTouch or DependentTouch */ ++ uint8_t num_touches; /**< Maximum number of touches (0==unlimited) */ ++} xXITouchInfo; ++ ++/** ++ * Denotes a multitouch valuator capability on a device. ++ * One XITouchValuatorInfo describes exactly one valuator (axis) on the device. ++ */ ++typedef struct { ++ uint16_t type; /**< Always TouchValuatorClass */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint16_t sourceid; /**< source device for this class */ ++ uint16_t number; /**< Valuator number */ ++ Atom label; /**< Axis label */ ++ FP3232 min; /**< Min value */ ++ FP3232 max; /**< Max value */ ++ uint32_t resolution; /**< Resolutions in units/m */ ++} xXITouchValuatorInfo; ++ + + /** + * Used to select for events on a given window. +@@ -772,6 +799,22 @@ + } xXIGetPropertyReply; + #define sz_xXIGetPropertyReply 32 + ++/** ++ * Accept or reject a grabbed touch sequence. ++ */ ++typedef struct { ++ uint8_t reqType; ++ uint8_t ReqType; /**< Always ::X_XIAllowTouchEvents */ ++ uint16_t length; /**< Length in 4 byte units */ ++ uint32_t touchid; ++ uint16_t deviceid; ++ uint8_t mode; /**< bitmask */ ++ uint8_t pad; ++} xXIAllowTouchEventsReq; ++#define sz_xXIAllowTouchEventsReq 12 ++ ++ ++ + /************************************************************************************* + * * + * EVENTS * +@@ -857,7 +900,28 @@ + } xXIDeviceChangedEvent; + + /** +- * Default input event for pointer or keyboard input. ++ * The owner of a touch stream has passed on ownership to another client. ++ */ ++typedef struct ++{ ++ uint8_t type; /**< Always GenericEvent */ ++ uint8_t extension; /**< XI extension offset */ ++ uint16_t sequenceNumber; ++ uint32_t length; /**< Length in 4 byte units */ ++ uint16_t evtype; /**< XI_TouchOwnership */ ++ uint16_t deviceid; /**< Device that has changed */ ++ Time time; ++ uint16_t sourceid; /**< Source of the new classes */ ++ uint16_t pad0; ++ uint32_t touchid; ++ uint32_t flags; ++ uint32_t pad1; ++ uint32_t pad2; ++} xXITouchOwnershipEvent; ++ ++/** ++ * Default input event for pointer, keyboard or touch input. ++ + */ + typedef struct + { diff --git a/x11-proto/inputproto/inputproto-2.0.1-r1.ebuild b/x11-proto/inputproto/inputproto-2.0.1-r1.ebuild new file mode 100644 index 0000000..4d17451 --- /dev/null +++ b/x11-proto/inputproto/inputproto-2.0.1-r1.ebuild @@ -0,0 +1,30 @@ +# Copyright 1999-2011 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/x11-proto/inputproto/inputproto-2.0.1.ebuild,v 1.8 2011/03/15 21:12:16 xarthisius Exp $ + +EAPI=3 + +XORG_EAUTORECONF=yes +inherit xorg-2 + +DESCRIPTION="X.Org Input protocol headers" + +KEYWORDS="alpha amd64 arm hppa ia64 ~mips ppc ppc64 s390 sh sparc x86 ~ppc-aix ~x86-fbsd ~x64-freebsd ~x86-freebsd ~ia64-hpux ~x86-interix ~amd64-linux ~x86-linux ~ppc-macos ~x64-macos ~x86-macos ~sparc-solaris ~sparc64-solaris ~x64-solaris ~x86-solaris ~x86-winnt" +IUSE="utouch" + +RDEPEND="" +DEPEND="${RDEPEND} +!