diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-07-09 13:27:19 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-07-17 14:38:02 +1000 |
commit | ecd178e632a99ae2f12d2d9b6e9a48eaa421335d (patch) | |
tree | 26be3459f5c4706df0aaa311229636ae32a52886 | |
parent | 54a7ae04a8475df6ce87e52ff995de22fafc7c92 (diff) |
dix: when ungrabbing an active grab, accept pointer grabs (#66720)
Ungrabbing a device during an active touch grab rejects the grab. Ungrabbing
a device during an active pointer grab accepts the grab.
Rejection is not really an option for a pointer-emulated grab, if a client
has a button mask on the window it would get a ButtonPress emulated after
UngrabDevice. That is against the core grab behaviour.
X.Org Bug 66720 <http://bugs.freedesktop.org/show_bug.cgi?id=66720>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
(cherry picked from commit 8eeaa74bc241acb41f1d3ed64971e0b01e794776)
-rw-r--r-- | Xi/exevents.c | 35 | ||||
-rw-r--r-- | dix/events.c | 11 |
2 files changed, 32 insertions, 14 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index e1945b937..30e48f0c3 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1224,9 +1224,13 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev, else if (ev->reason == XIAcceptTouch) { int i; - /* Go through the motions of ending the touch if the listener has + + /* For pointer-emulated listeners that ungrabbed the active grab, + * the state was forced to LISTENER_HAS_END. Still go + * through the motions of ending the touch if the listener has * already seen the end. This ensures that the touch record is ended in - * the server. */ + * the server. + */ if (ti->listeners[0].state == LISTENER_HAS_END) TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); @@ -1884,16 +1888,23 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, if (listener->type == LISTENER_POINTER_REGULAR || listener->type == LISTENER_POINTER_GRAB) { - rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, - grab, xi2mask); - - /* Once we send a TouchEnd to a legacy listener, we're already well - * past the accepting/rejecting stage (can only happen on - * GrabModeSync + replay. This listener now gets the end event, - * and we can continue. - */ - if (rc == Success) - listener->state = LISTENER_HAS_END; + /* Note: If the active grab was ungrabbed, we already changed the + * state to LISTENER_HAS_END but still get here. So we mustn't + * actually send the event. + * This is part two of the hack in DeactivatePointerGrab + */ + if (listener->state != LISTENER_HAS_END) { + rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, + grab, xi2mask); + + /* Once we send a TouchEnd to a legacy listener, we're already well + * past the accepting/rejecting stage (can only happen on + * GrabModeSync + replay. This listener now gets the end event, + * and we can continue. + */ + if (rc == Success) + listener->state = LISTENER_HAS_END; + } goto out; } diff --git a/dix/events.c b/dix/events.c index 4d50a2471..f9b2ed766 100644 --- a/dix/events.c +++ b/dix/events.c @@ -1519,13 +1519,20 @@ DeactivatePointerGrab(DeviceIntPtr mouse) for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { TouchPointInfoPtr ti = mouse->touch->touches + i; if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { + int mode = XIRejectTouch; /* Rejecting will generate a TouchEnd, but we must not emulate a ButtonRelease here. So pretend the listener already has the end event */ if (grab->grabtype == CORE || grab->grabtype == XI || - !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) + !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) { + mode = XIAcceptTouch; + /* NOTE: we set the state here, but + * ProcessTouchOwnershipEvent() will still call + * TouchEmitTouchEnd for this listener. The other half of + * this hack is in DeliverTouchEndEvent */ ti->listeners[0].state = LISTENER_HAS_END; - TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch); + } + TouchListenerAcceptReject(mouse, ti, 0, mode); } } |