summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChase Douglas <chase.douglas@canonical.com>2012-04-17 10:49:14 -0700
committerPeter Hutterer <peter.hutterer@who-t.net>2012-04-26 13:35:13 +1000
commit8ce9616a2ccd3f80bf56d69cb9e3fad89996fffb (patch)
treea4a4d7942382c8e5903403c5f18f7c1b702fe6df
parentda9cedb1e5e50acc7d3dc40398e1a460b7e3cfdc (diff)
Create a new dix touch record for an emulated touch with no listeners
As a special case, if a still physically active 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@canonical.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> (cherry picked from commit d0449851d1233543c3133d77e0ab7233319cdf5f)
-rw-r--r--Xi/exevents.c28
-rw-r--r--dix/touch.c5
2 files changed, 33 insertions, 0 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 0c483acbb..a1eccaa9a 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 e638a894a..572bdfb94 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -864,6 +864,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++) {