From 81fbb96c54f78a7cd96433294ee003c7ef6a772a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 25 Feb 2011 11:08:19 +1000 Subject: [PATCH] dix: release all buttons and keys before reattaching a device (#34182) Testcase: xinput float 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 Signed-off-by: Peter Hutterer Reviewed-by: Fernando Carrijo (cherry picked from commit 9d23459415b84606ee4f38bb2d19054c432c8552) --- dix/devices.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/dix/devices.c b/dix/devices.c index 55f22cbaf..84284e778 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -2379,6 +2379,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 @@ -2412,6 +2452,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) free(dev->spriteInfo->sprite); } + ReleaseButtonsAndKeys(dev); + oldmaster = dev->u.master; dev->u.master = master;