diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-10-03 15:18:17 +0930 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-10-03 15:18:17 +0930 |
commit | 1eebb03a3190947a8102f2ddc73766cf98d34c84 (patch) | |
tree | 5194564963c2ffc9963cc238c69a793dc552f676 /dix/events.c | |
parent | 0b485067823620b5dbd9ef2b3e13bd35ad5a4410 (diff) |
dix: ignore passive grab if the client already has a grab on the device.
In some cases a button press may activate a passive core grab. If the client
owning the passive grab already has a core grab on another device, don't
actually activate it. Otherwise the client gets two simultaneous passive
core grabs, and may never ungrab the device again (only if the other grab uses
GrabModeSync).
Reproducable: fire up gnome-session, open up gnome-terminal. Click with the
ClientPointer onto the window decoration, then click with another pointer onto
an application icon in the panel. Drag the icon out, release the button and
voila - you just lost your second mouse.
Diffstat (limited to 'dix/events.c')
-rw-r--r-- | dix/events.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/dix/events.c b/dix/events.c index 64892920b..8141a4051 100644 --- a/dix/events.c +++ b/dix/events.c @@ -3297,6 +3297,35 @@ CheckPassiveGrabsOnWindow( grab->modifierDevice = GetPairedKeyboard(device); } + /* In some cases a passive core grab may exist, but the client + * already has a core grab on some other device. In this case we + * must not get the grab, otherwise we may never ungrab the + * device. + */ + + if (grab->coreGrab) + { + DeviceIntPtr other; + BOOL interfering = FALSE; + for (other = inputInfo.devices; other; other = other->next) + { + GrabPtr othergrab = other->deviceGrab.grab; + if (othergrab && othergrab->coreGrab && + SameClient(grab, rClient(othergrab)) && + ((IsPointerDevice(grab->device) && + IsPointerDevice(othergrab->device)) || + (IsKeyboardDevice(grab->device) && + IsKeyboardDevice(othergrab->device)))) + { + interfering = TRUE; + break; + } + } + if (interfering) + continue; + } + + (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); FixUpEventFromWindow(device, xE, grab->window, None, TRUE); |