dix: Send touch end to clients that do async grab without touch events

If a XI2 client started listening to touches due to a selection and then
creates an active async grab that does not include touch events, then it
currently won't get the touch end event which will produce inconsistent
view of the pending touches.

Note that we only need to consider touch listeners and can ignore
pointer emulation. Under XI2 if a active grab replaces a passive
implicit grab and the active grab does not include the button release
event, the client won't get it either.
This commit is contained in:
Povilas Kanapickas 2021-02-08 05:21:29 +02:00
parent c7730cfe55
commit f682e0563f
1 changed files with 16 additions and 3 deletions

View File

@ -1482,14 +1482,27 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
CLIENT_BITS(listener->listener) == grab->resource) {
listener->listener = grab->resource;
listener->level = grab->grabtype;
listener->state = TOUCH_LISTENER_IS_OWNER;
listener->window = grab->window;
if (grab->grabtype == CORE || grab->grabtype == XI ||
!xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
!xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
if (listener->type == TOUCH_LISTENER_REGULAR &&
listener->state != TOUCH_LISTENER_AWAITING_BEGIN &&
listener->state != TOUCH_LISTENER_HAS_END) {
/* if the listener already got any events relating to the touch, we must send
a touch end because the grab overrides the previous listener and won't
itself send any touch events.
*/
TouchEmitTouchEnd(mouse, ti, 0, listener->listener);
}
listener->type = TOUCH_LISTENER_POINTER_GRAB;
else
} else {
listener->type = TOUCH_LISTENER_GRAB;
}
listener->state = TOUCH_LISTENER_IS_OWNER;
if (listener->grab)
FreeGrab(listener->grab);
listener->grab = AllocGrab(grab);