Protocol (sort-of [1]) requires us to deliver motion events before button events. For emulated events, the requirement is: * TouchBegin: motion + button press * TouchUpdate: motion * TouchEnd: motion + button release
The TouchUpdate was handled through normal deliver, changing the TouchUpdate event in to a pointer event where required and delivering it. Being touch events by nature, we can assume that any touch sequence is always grabbed (or discarded). Thus, the TouchUpdate events were discarded if we didn't have listeners. The motion before the TouchBegin however needs to be sent regardless of listeners since it comes before the emulated ButtonPress. For TouchEnd, we used the same hook as for TouchBegin, but that's bogus. A client listening to motion events but not button events would get the motion before the TouchBegin, no others and then again the motion before the TouchEnd (with the button mask set). This patch changes the hook, so we still do the out-of-band motion for TouchBegin, but hook up the motion-before-end through the same mechanism as the TouchUpdate. This is mostly just shuffling around, making sure we do send the motion event that we previously skipped. [1] And by "sort-of" I mean "It's not explicitly required in the spec, but could be implicitly read as such though and we appear to have always done so and I'm not about to find out what breaks if we stop doing so." Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- Xi/exevents.c | 83 ++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index be62667..913d0db 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1364,30 +1364,12 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti, } static int -DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, - InternalEvent *ev, TouchListener * listener, - ClientPtr client, WindowPtr win, GrabPtr grab, - XI2Mask *xi2mask) +DeliverTouchEmulatedPointerEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + InternalEvent *ptrev, + InternalEvent *ev, TouchListener * listener, + ClientPtr client, WindowPtr win, GrabPtr grab, + XI2Mask *xi2mask) { - InternalEvent motion, button; - InternalEvent *ptrev = &motion; - int nevents; - DeviceIntPtr kbd; - - /* We don't deliver pointer events to non-owners */ - if (!TouchResourceIsOwner(ti, listener->listener)) - return Success; - - nevents = TouchConvertToPointerEvent(ev, &motion, &button); - BUG_RETURN_VAL(nevents == 0, BadValue); - - if (nevents > 1) - ptrev = &button; - - kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); - event_set_state(dev, kbd, &ptrev->device_event); - ptrev->device_event.corestate = event_get_corestate(dev, kbd); - if (grab) { /* this side-steps the usual activation mechanisms, but... */ if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab) @@ -1465,6 +1447,56 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, return Success; } +static int +DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + InternalEvent *ev, TouchListener * listener, + ClientPtr client, WindowPtr win, GrabPtr grab, + XI2Mask *xi2mask) +{ + InternalEvent motion, button; + int nevents; + DeviceIntPtr kbd; + int rc; + + /* We don't deliver pointer events to non-owners */ + if (!TouchResourceIsOwner(ti, listener->listener)) + return Success; + + nevents = TouchConvertToPointerEvent(ev, &motion, &button); + BUG_RETURN_VAL(nevents == 0, BadValue); + + kbd = GetMaster(dev, KEYBOARD_OR_FLOAT); + event_set_state(dev, kbd, &motion.device_event); + motion.device_event.corestate = event_get_corestate(dev, kbd); + + if (nevents > 1) { + event_set_state(dev, kbd, &button.device_event); + button.device_event.corestate = event_get_corestate(dev, kbd); + } + + /* TouchBegin sends the emulated motion event in ProcessTouchEvents. + That first motion event must be delivered regardless of touch + listener state. For Update/End, we only deliver to listeners */ + if (ev->any.type != ET_TouchBegin) { + /* Save the event type, because if we pass a TouchEnd through to + DTEPE it will cancel any implicit grabs. + */ + int type = ev->any.type; + ev->any.type = ET_TouchUpdate; + rc = DeliverTouchEmulatedPointerEvent(dev, ti, &motion, ev, + listener, client, win, + grab, xi2mask); + ev->any.type = type; + } + + if (nevents > 1) + rc = DeliverTouchEmulatedPointerEvent(dev, ti, &button, ev, + listener, client, win, + grab, xi2mask); + + return rc; +} + static void DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev) @@ -1592,9 +1624,8 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) } /* if emulate_pointer is set, emulate the motion event right - * here, so we can ignore it for button event emulation. TouchUpdate - * events which _only_ emulate motion just work normally */ - if (emulate_pointer && ev->any.type != ET_TouchUpdate) + * here, so it doesn't depend on listeners */ + if (emulate_pointer && ev->any.type == ET_TouchBegin) DeliverEmulatedMotionEvent(dev, ti, ev); if (emulate_pointer && IsMaster(dev)) -- 1.8.1 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel