Xi: Don't ActivateEarlyAccept POINTER_REGULAR listeners
authorBen Gamari <bgamari.foss@gmail.com>
Fri, 22 Nov 2013 02:24:20 +0000 (21:24 -0500)
committerPeter Hutterer <peter.hutterer@who-t.net>
Wed, 11 Dec 2013 04:00:50 +0000 (14:00 +1000)
Bug #71878 describes a bug resulting in the server ceasing to respond to
keyboard input after a touch event. The problem might be the following:

DeliverTouchBeginEvent tries to deliver an event to a listener of type
LISTENER_POINTER_REGULAR, taking the following if branch,

    if (listener->type == LISTENER_POINTER_REGULAR ||
        listener->type == LISTENER_POINTER_GRAB) {
        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                       grab, xi2mask);
        if (rc == Success) {
            listener->state = LISTENER_IS_OWNER;
            /* async grabs cannot replay, so automatically accept this touch */
            if (dev->deviceGrab.grab &&
                dev->deviceGrab.fromPassiveGrab &&
                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
                ActivateEarlyAccept(dev, ti);
        }
        goto out;
    }

DeliverTouchEmulatedEvent succeeds.  The deviceGrab meets all
three of the conditions of the inner if, enters
ActivateEarlyAccept which then fails due to,

    BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
               ti->listeners[0].type != LISTENER_POINTER_GRAB);

That is, despite listener->type == LISTENER_POINTER_REGULAR. With my
non-existent knowledge of XINPUT, it seems like the solution here
might be to only ActivateEarlyAccept when listener->type ==
LISTENER_POINTER_GRAB.

Signed-off-by: Ben Gamari <bgamari.foss@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Xi/exevents.c

index 5dc9020..5e1d3e0 100644 (file)
@@ -1845,7 +1845,8 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
         if (rc == Success) {
             listener->state = LISTENER_IS_OWNER;
             /* async grabs cannot replay, so automatically accept this touch */
-            if (dev->deviceGrab.grab &&
+            if (listener->type == LISTENER_POINTER_GRAB &&
+                dev->deviceGrab.grab &&
                 dev->deviceGrab.fromPassiveGrab &&
                 dev->deviceGrab.grab->pointerMode == GrabModeAsync)
                 ActivateEarlyAccept(dev, ti);