Deliver raw events regardless whether there is a grab on or not for clients supporting 2.1 or later.
Signed-off-by: Peter Hutterer <[email protected]> --- Xi/exevents.c | 42 ++++++++++++++++++++++++------------------ dix/events.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index c6f9d46..2392ff1 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -876,30 +876,36 @@ UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event) return DEFAULT; } + +/** + * Raw event delivery differs between XI 2.0 and XI 2.1. + * XI 2.0: events delivered to the grabbing client only (if any) OR to all + * root windows + * XI 2.1: events delivered to all root windows, regardless of grabbing + * state + * + */ static void ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) { GrabPtr grab = device->deviceGrab.grab; + xEvent *xi; + int i; - if (grab) - DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); - else { /* deliver to all root windows */ - xEvent *xi; - int i; - - i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); - if (i != Success) - { - ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n", - device->name, i); - return; - } - - for (i = 0; i < screenInfo.numScreens; i++) - DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, - GetEventFilter(device, xi), NULL); - free(xi); + /* deliver to all root windows. For XI 2.0 clients, + * grabbed raw events will be filtered later */ + i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (i != Success) + { + ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n", + device->name, i); + return; } + + for (i = 0; i < screenInfo.numScreens; i++) + DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, + GetEventFilter(device, xi), NULL); + free(xi); } /** diff --git a/dix/events.c b/dix/events.c index f3af5ee..ee05be3 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1992,6 +1992,52 @@ out: } /** + * Filter out raw events for XI 2.0 clients. + * + * If there is a grab on the device, 2.0 clients only get raw events if they + * have the grab. 2.1+ clients get raw events in all cases. + * + * For raw events, this function may be called from DeliverEventsToWindow() + * or through DeliverGrabbedEvent(). For 2.0 we need to filter when a grab + * is on and we're coming from DeliverEventsToWindow(), for 2.1 we need to + * filter whenever we come from DeliverGrabbedEvent(). + * + * grab is non-NULL when coming from DeliverGrabbedEvent(), otherwise NULL. + * + * @return TRUE if the event should be discarded, FALSE otherwise. + */ +static BOOL +FilterRawEvents(const DeviceIntPtr dev, const xEvent *event, + const GrabPtr grab, const ClientPtr client) +{ + int rc = FALSE; + XIClientPtr client_xi_version; + + if (!is_xi2_event_of_type(event, XI_RawMotion) && + !is_xi2_event_of_type(event, XI_RawButtonPress) && + !is_xi2_event_of_type(event, XI_RawButtonRelease) && + !is_xi2_event_of_type(event, XI_RawKeyPress) && + !is_xi2_event_of_type(event, XI_RawKeyRelease)) + goto out; + + client_xi_version = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); + + /* If the client is XI 2.0, there is a grab on the device and it's not + * our grab, filter the raw event. */ + if (version_compare(client_xi_version->major_version, + client_xi_version->minor_version, 2, 0) == 0) + { + GrabPtr devgrab = dev->deviceGrab.grab; + + if (devgrab && rClient(devgrab) != client) + rc = TRUE; + } + +out: + return rc; +} + +/** * Deliver events to clients registered on the window. * * @param client_return On successful delivery, set to the recipient. @@ -2039,7 +2085,8 @@ DeliverEventToClients(DeviceIntPtr dev, WindowPtr win, xEvent *events, mask = GetEventMask(dev, events, other); if (XaceHook(XACE_RECEIVE_ACCESS, client, win, - events, count)) + events, count) || + FilterRawEvents(dev, events, grab, client)) /* do nothing */; else if ( (attempt = TryClientEvents(client, dev, events, count, -- 1.7.4.4 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
