[PATCH xserver 11/12] input: deliver raw events unconditionally for XI 2.1 clients.

Peter Hutterer peter.hutterer at who-t.net
Sun Jun 5 18:22:13 PDT 2011


On Fri, Jun 03, 2011 at 11:40:02PM -0400, Jeremy Huddleston wrote:
> 5-10, 12:
> Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
> 
> 11: 
> 
> This looks odd.  You're only going to deliver to the first client:
> 
> +        for (; inputclients; inputclients = inputclients->next)
>         {
> +            ClientPtr c; /* unused */
> +            Mask m;      /* unused */
> +            InputClients ic = *inputclients;
> 
> +            /* Because we run through the list manually, terminate the list
> +             * after our current client */
> +            ic.next = NULL;
> +            if (!FilterRawEvents(rClient(&ic), grab))
> +                DeliverEventToInputClients(device, &ic, root, xi, 1,
> +                                           filter, NULL, &c, &m);
> +        }

inputclients is a list on the window that contains all clients that
registered for events on the window. DeliverEventToInputClients delivers too
all clients in that list.

Because raw event delivery is different (we must take care to not deliver
the same event twice), we need to handle the list ourselves here.
so of the inputclients list, we copy the first list item into a temporary
list "ic", then terminate that list and deliver the event. then copy the
second one into a tmp list, etc.

it's a bit of a hack, but otherwise an XI2.1 client with a device grab will
get the raw events twice, once as part of the grab, once as part of the
normal event delivery.

Cheers,
  Peter


> On Jun 2, 2011, at 3:13 AM, Peter Hutterer wrote:
> 
> > 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 at who-t.net>
> > ---
> > dix/events.c |   87 ++++++++++++++++++++++++++++++++++++++++++++++++----------
> > 1 files changed, 72 insertions(+), 15 deletions(-)
> > 
> > diff --git a/dix/events.c b/dix/events.c
> > index ce4e59d..9225b7d 100644
> > --- a/dix/events.c
> > +++ b/dix/events.c
> > @@ -2243,35 +2243,92 @@ 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)
> > +    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 (; inputclients; inputclients = inputclients->next)
> >         {
> > -            ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
> > -                    __func__, device->name, i);
> > -            return;
> > -        }
> > +            ClientPtr c; /* unused */
> > +            Mask m;      /* unused */
> > +            InputClients ic = *inputclients;
> > 
> > -        filter = GetEventFilter(device, xi);
> > +            /* Because we run through the list manually, terminate the list
> > +             * after our current client */
> > +            ic.next = NULL;
> > 
> > -        for (i = 0; i < screenInfo.numScreens; i++)
> > -            DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
> > -                                  filter, NullGrab);
> > -        free(xi);
> > +            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.
> > -- 
> > 1.7.5.1
> > 
> > _______________________________________________
> > xorg-devel at lists.x.org: X.Org development
> > Archives: http://lists.x.org/archives/xorg-devel
> > Info: http://lists.x.org/mailman/listinfo/xorg-devel
> > 
> 
> 


More information about the xorg-devel mailing list