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]> --- On Sat, May 21, 2011 at 01:21:28PM +0100, Daniel Stone wrote: > On Wed, May 11, 2011 at 02:59:35PM +1000, Peter Hutterer wrote: > > @@ -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, > > I'd rather do the filtering in TryClientEvents, where we already do > pretty much all the filtering. Sure, why not, see below. > Speaking of: TryClientEvents will bin the event > if (grab && !SameClient(grab, client)). So don't you need to change > that to get this working as well? This whole thing relies on the right caller order. Which is a bit of a hack but until we have internal events everywhere the best way to integrate it. >From the comments in the patch: * grab is non-NULL when coming from DeliverGrabbedEvent(), otherwise NULL. So for a raw event during grabs we get called twice. The first time without a grab (where we filter for XI2.0) and the second time with a grab (where we filter for XI 2.1 and XI2.0 if grab && !SameClient()) and yes, this is a bit flimsy, I agree. Changes to v1: - Call FilterRawEvents in TryClientEvents. Xi/exevents.c | 43 ++++++++++++++++++++++++------------------- dix/events.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index c6f9d46..15f1079 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -876,30 +876,35 @@ 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; - - 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; - } + xEvent *xi; + int i; - 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 b60c299..5339a73 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1812,6 +1812,56 @@ ReleaseActiveGrabs(ClientPtr client) /************************************************************************** * The following procedures deal with delivering events * **************************************************************************/ +/** + * 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; + int evtype = xi2_get_type(event); + + switch (evtype) { + case XI_RawMotion: + case XI_RawButtonPress: + case XI_RawButtonRelease: + case XI_RawKeyPress: + case XI_RawKeyRelease: + break; + default: + return rc; + } + + 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; + } + + return rc; +} + /** * Deliver the given events to the given client. @@ -1874,6 +1924,9 @@ TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, return -1; /* don't send, but notify caller */ } + if (FilterRawEvents(dev, pEvents, grab, client)) + return 0; + type = pEvents->u.u.type; if (type == MotionNotify) { -- 1.7.5.1 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
