From c1d30b5bd7f90e68bc38404fd0cc32578d6d3018 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Thu, 21 Nov 2013 21:24:20 -0500 Subject: [PATCH 1/3] 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. Signed-off-by: Ben Gamari Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/exevents.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 5dc902054..5e1d3e0a6 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); From 23394c7fea0f5c33333198c87ecfecc9f6c6a791 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 3 Dec 2013 08:36:45 +1000 Subject: [PATCH 2/3] Xi: ungrab device when releasing a passive grab without ButtonReleaseMask (#71878) If an touch triggers an async button grab and that grab does not have the ButtonReleaseMask set, the TouchEnd is never delivered, deliveries is 0 and the grab is never deactivated. If the grab is pointer async and keyboard sync, the keyboard events are stuck in EnqueueEvent until some other pointer event terminates the grab. Change this to check for the number of listeners. If we're about to deliver a TouchEnd to a passive pointer grab, the number of listeners is already 1 - pointer grabs always accept so other listeners were removed. X.Org Bug 71878 Signed-off-by: Peter Hutterer --- Xi/exevents.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 5e1d3e0a6..dff0a92b0 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1413,7 +1413,8 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, !(ev->device_event.flags & TOUCH_CLIENT_ID)) TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); - if (deliveries && ev->any.type == ET_TouchEnd && + if (ev->any.type == ET_TouchEnd && + ti->num_listeners == 1 && !dev->button->buttonsDown && dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { (*dev->deviceGrab.DeactivateGrab) (dev); From 929795d50d788358d6269ce423f72c6cc40e334b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 3 Dec 2013 10:14:51 +1000 Subject: [PATCH 3/3] dix: fix check for grab type Signed-off-by: Peter Hutterer --- dix/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dix/events.c b/dix/events.c index 4632bb7db..4aaa54c85 100644 --- a/dix/events.c +++ b/dix/events.c @@ -4696,7 +4696,7 @@ DeviceEnterLeaveEvent(DeviceIntPtr mouse, filter = GetEventFilter(mouse, (xEvent *) event); - if (grab && grab->type == XI2) { + if (grab && grab->grabtype == XI2) { Mask mask; mask = xi2mask_isset(grab->xi2mask, mouse, type);