summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 ae3652b68..c8bd222e9 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++) {