From 9fbc7bff4489fc05c649bfb3e7178e4e92f6f223 Mon Sep 17 00:00:00 2001
From: Ben Gamari <bgamari.foss@gmail.com>
Date: Thu, 21 Nov 2013 21:24:20 -0500
Subject: [PATCH] Xi: Don't ActivateEarlyAccept POINTER_REGULAR listeners

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`.
---
 Xi/exevents.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 067e6b3..9026415 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -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);
-- 
1.8.3.2