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

Reply via email to