[PATCH] xkb: release XTEST pointer buttons on physical releases. (#28808)

Peter Hutterer peter.hutterer at who-t.net
Wed Jun 30 21:00:22 PDT 2010

If a button release event is posted for the MD pointer, post a release event
through the matching XTEST device. This way, a client who posts a button
press through the XTEST extension cannot inadvertedly lock the button.

This behaviour is required for historical reasons, until server 1.7 the core
pointer would release a button press on physical events, regardless of the
XTEST state. Clients seem to rely on this behaviour, causing seemingly stuck

The merged behaviour is kept for multiple keyboard PointerKey events, if two
physical keyboards hold the button down as a result of PointerKey actions,
the button is not released until the last keyboard releases the button.

X.Org Bug 28808 <http://bugs.freedesktop.org/show_bug.cgi?id=28808>

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
This one goes on top of the other patches, the state is now half-merged.
It seems a bit excessive, we have to look up the device for each button
press. Unfortunately, this is the only way we can get to the xtest device
easily, by the time we get here the source information is only in the event,
all the device pointers point to other devices already.

 include/xkbsrv.h |    6 ++++++
 xkb/xkbAccessX.c |   23 ++++++++++-------------
 xkb/xkbActions.c |    4 ++--
 3 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 956b224..9f1507e 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -927,6 +927,12 @@ extern int XkbGetEffectiveGroup(
 extern void XkbMergeLockedPtrBtns(
         DeviceIntPtr            /* master */);
+extern void XkbFakeDeviceButton(
+        DeviceIntPtr            /* dev */,
+        int                     /* press */,
+        int                     /* button */);
 #include "xkbfile.h"
 #include "xkbrules.h"
diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
index 81f9596..10c38ca 100644
--- a/xkb/xkbAccessX.c
+++ b/xkb/xkbAccessX.c
@@ -710,19 +710,16 @@ DeviceEvent     *event = &ev->device_event;
 	if (xkbi) {
 	    xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
-            /* Merge this MD's lockedPtrButtons with the one of all
-             * attached slave devices.
-             * The DIX uses a merged button state for MDs, not
-             * releasing buttons until the last SD has released
-             * thenm. If we unconditionally clear the
-             * lockedPtrButtons bit on the MD, a PointerKeys button
-             * release on the SD keyboard won't generate the required fake button
-             * event on the XTEST pointer, thus never processing the
-             * button event in the DIX and the XTEST pointer's
-             * buttons stay down - result is a stuck button.
-             */
-	    if (IsMaster(dev))
-                XkbMergeLockedPtrBtns(dev);
+            if (IsMaster(dev))
+            {
+                DeviceIntPtr source;
+                int rc;
+                rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
+                if (rc != Success)
+                    ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
+                else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
+                    XkbFakeDeviceButton(dev, FALSE, event->detail.key);
+            }
 	changed |= XkbPointerButtonMask;
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index 49d7b3d..96d3847 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
 DevPrivateKeyRec xkbDevicePrivateKeyRec;
-static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
+void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
 static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
@@ -1364,7 +1364,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
     FreeEventList(events, GetMaximumEventsNum());
-static void
 XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
     EventListPtr        events;

More information about the xorg-devel mailing list