summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2011-02-25 11:08:19 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2011-06-20 15:31:40 +1000
commit160a412e36fd945119e4c10f5d22682fcd0cc637 (patch)
treec750ed047951e24b83f4af41300ec6054d9f8a70
parentc9336d13a6b231edf16412706c52318947fcd000 (diff)
dix: release all buttons and keys before reattaching a device (#34182)
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@who-t.net> Reviewed-by: Fernando Carrijo <fcarrijo@freedesktop.org> (cherry picked from commit 9d23459415b84606ee4f38bb2d19054c432c8552) (cherry picked from commit 81fbb96c54f78a7cd96433294ee003c7ef6a772a)
-rw-r--r--dix/devices.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/dix/devices.c b/dix/devices.c
index fed05f5e2..827c328f9 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2407,6 +2407,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.
@@ -2439,6 +2479,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
free(dev->spriteInfo->sprite);
}
+ ReleaseButtonsAndKeys(dev);
+
oldmaster = dev->u.master;
dev->u.master = master;