diff options
Diffstat (limited to 'dix')
-rw-r--r-- | dix/events.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/dix/events.c b/dix/events.c index a751e3c6a..da3f6aa7e 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1729,7 +1729,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent return 0; if (!(type & EXTENSION_EVENT_BASE) && - IsInterferingGrab(wClient(pWin), pDev, pEvents)) + IsInterferingGrab(wClient(pWin), pWin, pDev, pEvents)) return 0; if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, @@ -1762,7 +1762,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent { /* core event? check for grab interference */ if (!(type & EXTENSION_EVENT_BASE) && - IsInterferingGrab(rClient(other), pDev, pEvents)) + IsInterferingGrab(rClient(other), pWin, pDev, pEvents)) continue; if ( (attempt = TryClientEvents(rClient(other), pEvents, count, @@ -5097,15 +5097,19 @@ PickKeyboard(ClientPtr client) /* A client that has one or more core grabs does not get core events from * devices it does not have a grab on. Legacy applications behave bad * otherwise because they are not used to it and the events interfere. + * The one exception is: if we're about to send an event to a window that is + * specified as grab window, we still do it. This makes popup menus + * half-useable for WMs that don't set the ClientPointer. * Only applies for core events. * * Return true if a core event from the device would interfere and should not * be delivered. */ Bool -IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) +IsInterferingGrab(ClientPtr client, WindowPtr win, DeviceIntPtr dev, xEvent* event) { - DeviceIntPtr it = inputInfo.devices; + DeviceIntPtr it; + Bool mayInterfere = FALSE; if (dev->coreGrab.grab && SameClient(dev->coreGrab.grab, client)) return FALSE; @@ -5124,19 +5128,30 @@ IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) return FALSE; } + it = inputInfo.devices; while(it) { if (it != dev) { if (it->coreGrab.grab && SameClient(it->coreGrab.grab, client)) { - return TRUE; + /* there's a client with a grab on some device. + * if we're delivering to the very same window that is + * grabbed (or a child), we're good */ + WindowPtr parent = win; + while(parent) + { + if (it->coreGrab.grab->window == parent) + return FALSE; + parent = parent->parent; + } + mayInterfere = TRUE; } } it = it->next; } - return FALSE; + return mayInterfere; } |