diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2011-05-11 13:56:08 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2011-09-29 14:09:41 +1000 |
commit | b6b1f1b514bf14ddf6b265b8d4551f892ded0dd2 (patch) | |
tree | c3c0cfa7762ddf49e95173206286ed813b9553fb /dix/events.c | |
parent | 16244fba001826190445302f56784f5de9c59c01 (diff) |
input: deliver raw events unconditionally for XI 2.1 clients.
Deliver raw events regardless whether there is a grab on or not for clients
supporting 2.1 or later.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jeremy Huddleston <jeremyhu@apple.com>
Reviewed-by: Daniel Stone <daniel@fooishbar.org>
Diffstat (limited to 'dix/events.c')
-rw-r--r-- | dix/events.c | 93 |
1 files changed, 77 insertions, 16 deletions
diff --git a/dix/events.c b/dix/events.c index 8a4c6b9ac..2112a47db 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2243,35 +2243,96 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent return nondeliveries; } +/** + * Filter out raw events for XI 2.0 and XI 2.1 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. + * + * @return TRUE if the event should be discarded, FALSE otherwise. + */ +static BOOL +FilterRawEvents(const ClientPtr client, const GrabPtr grab) +{ + XIClientPtr client_xi_version; + int cmp; + + /* device not grabbed -> don't filter */ + if (!grab) + return FALSE; + + client_xi_version = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); + + cmp = version_compare(client_xi_version->major_version, + client_xi_version->minor_version, 2, 0); + /* XI 2.0: if device is grabbed, skip + XI 2.1: if device is grabbed by us, skip, we've already delivered */ + return (cmp == 0) ? TRUE : SameClient(grab, client); +} + +/** + * Deliver a raw event to the grab owner (if any) and to all root windows. + * + * Raw event delivery differs between XI 2.0 and XI 2.1. + * XI 2.0: events delivered to the grabbing client (if any) OR to all root + * windows + * XI 2.1: events delivered to all root windows, regardless of grabbing + * state. + */ void DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) { GrabPtr grab = device->deviceGrab.grab; + xEvent *xi; + int i; + int filter; + + i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); + if (i != Success) + { + ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", + __func__, device->name, i); + return; + } if (grab) DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE); - else { /* deliver to all root windows */ - xEvent *xi; - int i; - int filter; - i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi); - if (i != Success) - { - ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", - __func__, device->name, i); - return; - } + filter = GetEventFilter(device, xi); - filter = GetEventFilter(device, xi); + for (i = 0; i < screenInfo.numScreens; i++) + { + WindowPtr root; + InputClients *inputclients; + + root = screenInfo.screens[i]->root; + if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) + continue; - for (i = 0; i < screenInfo.numScreens; i++) - DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1, - filter, NullGrab); - free(xi); + for (; inputclients; inputclients = inputclients->next) + { + ClientPtr c; /* unused */ + Mask m; /* unused */ + InputClients ic = *inputclients; + + /* Because we run through the list manually, copy the actual + * list, shorten the copy to only have one client and then pass + * that down to DeliverEventToInputClients. This way we avoid + * double events on XI 2.1 clients that have a grab on the + * device. + */ + ic.next = NULL; + + if (!FilterRawEvents(rClient(&ic), grab)) + DeliverEventToInputClients(device, &ic, root, xi, 1, + filter, NULL, &c, &m); + } } + + free(xi); } + /* If the event goes to dontClient, don't send it and return 0. if send works, return 1 or if send didn't work, return 2. Only works for core events. |