summaryrefslogtreecommitdiff
path: root/dix/events.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-10-03 15:18:17 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-10-03 15:18:17 +0930
commit1eebb03a3190947a8102f2ddc73766cf98d34c84 (patch)
tree5194564963c2ffc9963cc238c69a793dc552f676 /dix/events.c
parent0b485067823620b5dbd9ef2b3e13bd35ad5a4410 (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.c29
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);