[PATCH 06/10] Create a new dix touch record for an emulated touch with no listeners

Chase Douglas chase.douglas at canonical.com
Tue Apr 17 16:33:25 PDT 2012


As a special case, if a pointer emulated touch has no listeners and the
device is explicitly grabbed for pointer events, create a new dix touch
record for the grab only.

This allows for clients to "hand off" grabs. For example, when dragging
a window under compiz the window decorator sees the button press and
then ungrabs the implicit grab. It then tells compiz to grab the device,
and compiz then moves the window with the pointer motion. This is racy,
but is allowed by the input protocol for pointer events when there are
no other clients with a grab on the device.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 Xi/exevents.c |   28 ++++++++++++++++++++++++++++
 dix/touch.c   |    5 +++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index ae3652b..c8bd222 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1610,6 +1610,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         ti = TouchFindByClientID(dev, touchid);
 
+    /* Under the following circumstances we create a new touch record for an
+     * existing touch:
+     *
+     * - The touch may be pointer emulated
+     * - An explicit grab is active on the device
+     * - The grab is a pointer grab
+     *
+     * This allows for an explicit grab to receive pointer events for an already
+     * active touch.
+     */
+    if (!ti && type != ET_TouchBegin && emulate_pointer &&
+        dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+        (dev->deviceGrab.grab->grabtype == CORE ||
+         dev->deviceGrab.grab->grabtype == XI ||
+         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
+        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                             emulate_pointer);
+        if (!ti) {
+            DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+                   "grabbed touchpoint %d\n",
+                   dev->name, type, touchid);
+            return;
+        }
+
+        TouchBuildSprite(dev, ti, ev);
+        TouchSetupListeners(dev, ti, ev);
+    }
+
     if (!ti) {
         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
                dev->name, type, touchid);
diff --git a/dix/touch.c b/dix/touch.c
index af32103..9f849b7 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -852,6 +852,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
     if (dev->deviceGrab.grab)
         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
 
+    /* We set up an active touch listener for existing touches, but not any
+     * passive grab or regular listeners. */
+    if (ev->any.type != ET_TouchBegin)
+        return;
+
     /* First, find all grabbing clients from the root window down
      * to the deepest child window. */
     for (i = 0; i < sprite->spriteTraceGood; i++) {
-- 
1.7.9.1



More information about the xorg-devel mailing list