[PATCH vBrownPaperBag] dix: release all buttons and keys before reattaching a device (#34182)

Peter Hutterer peter.hutterer at who-t.net
Thu Feb 24 19:52:04 PST 2011


Testcase:
  xinput float <keyboard name>

results in the keyboard's enter key being repeated as the device is detached
while the key is still physically down. To avoid this, release all keys and
buttons before reattaching the device.

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

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---

Changes to v1:
- Free the event list after usage.
- two loops require two counters. who would have thought.

FWIW, I did test this before, and surprisingly it worked even with the
bugs...

 dix/devices.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/dix/devices.c b/dix/devices.c
index 6c0dc42..b73fb29 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2376,6 +2376,46 @@ RecalculateMasterButtons(DeviceIntPtr slave)
 }
 
 /**
+ * Generate release events for all keys/button currently down on this
+ * device.
+ */
+static void
+ReleaseButtonsAndKeys(DeviceIntPtr dev)
+{
+    EventListPtr        eventlist = InitEventList(GetMaximumEventsNum());
+    ButtonClassPtr      b = dev->button;
+    KeyClassPtr         k = dev->key;
+    int                 i, j, nevents;
+
+    if (!eventlist) /* no release events for you */
+        return;
+
+    /* Release all buttons */
+    for (i = 0; b && i < b->numButtons; i++)
+    {
+        if (BitIsOn(b->down, i))
+        {
+            nevents = GetPointerEvents(eventlist, dev, ButtonRelease, i, 0, NULL);
+            for (j = 0; j < nevents; j++)
+                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
+        }
+    }
+
+    /* Release all keys */
+    for (i = 0; k && i < MAP_LENGTH; i++)
+    {
+        if (BitIsOn(k->down, i))
+        {
+            nevents = GetKeyboardEvents(eventlist, dev, KeyRelease, i);
+            for (j = 0; j < nevents; j++)
+                mieqProcessDeviceEvent(dev, (InternalEvent*)(eventlist+j)->event, NULL);
+        }
+    }
+
+    FreeEventList(eventlist, GetMaximumEventsNum());
+}
+
+/**
  * Attach device 'dev' to device 'master'.
  * Client is set to the client that issued the request, or NULL if it comes
  * from some internal automatic pairing.
@@ -2408,6 +2448,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
         free(dev->spriteInfo->sprite);
     }
 
+    ReleaseButtonsAndKeys(dev);
+
     oldmaster = dev->u.master;
     dev->u.master = master;
 
-- 
1.7.4


More information about the xorg-devel mailing list