[PATCH] Xi: use correct touch event type for pointer emulation

Daniel Drake dsd at laptop.org
Tue Apr 2 07:43:11 PDT 2013


In Sugar we are seeing a problem where after using the touchscreen to select
certain UI elements (through a quick touch and release), pointer emulation
gets confused, and further movements of the mouse happen as if the left
mouse button is held down on the virtual core pointer (it is not).

What seems to be happening is:

TouchBegin happens, which creates a new TouchInfo, and 2 listeners get
added, a LISTENER_GRAB and a LISTENER_REGULAR. This must represent some
grab placed by the widget in question, plus a grab from Sugar's gesture
handler (which uses XIGrabTouchBegin).
The events here get delivered as intended, and importantly, the TouchBegin
event gets passed to UpdateDeviceState() on the virtual core pointer, causing
the "left mouse button pressed" emulation to happen.

TouchEnd then happens. The following code in DeliverTouchEndEvent() triggers:

        if ((ti->num_listeners > 1 ||
             listener->state != LISTENER_HAS_ACCEPTED) &&
            (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
            ev->any.type = ET_TouchUpdate;
            ev->device_event.flags |= TOUCH_PENDING_END;
            ti->pending_finish = TRUE;
        }

So the event is now changed to be a TouchUpdate. I think this means that we
don't actually deliver any TouchEnd event at the moment. But one important
effect that happens here is that UpdateDeviceState() is called with a
TouchUpdate event, *not* a TouchEnd event at this time, so X thinks the mouse
button is still pressed.

Then, Sugar's gesture code sends XIRejectTouch, and a lot of stuff happens
(touch history replay, etc). I don't fully understand what happens here, but
I have studied the code enough to see that UpdateDeviceState() does not get
called with a TouchEnd event, which would be required for this mouse button
emulation state to be corrected.

Taking a step back, pointer emulation seems to be mostly driven by
ProcessTouchEvents, so it seems to me that this code should also be
responsible for passing the TouchEnd event to UpdateDeviceState() to fix
the emulated mouse button state.

So, restore the original event type here so that the TouchEnd event
correctly makes it all the way to UpdateDeviceState, even if it was
previously wrangled into a TouchUpdate for reasons related to touch
history/ownership.

---

There is related work ongoing at
https://bugs.freedesktop.org/show_bug.cgi?id=56578

This patch is intended to go on top of the patches already posted on that
bug. However, in practice I'm not sure if it matters; this bug appears both
before and after the #56578 patches are applied.

Index: xorg-server-1.14.0/Xi/exevents.c
===================================================================
--- xorg-server-1.14.0.orig/Xi/exevents.c
+++ xorg-server-1.14.0/Xi/exevents.c
@@ -1614,8 +1614,13 @@ ProcessTouchEvent(InternalEvent *ev, Dev
             TouchEndTouch(dev, ti);
     }
 
-    if (emulate_pointer)
+    if (emulate_pointer) {
+        /* The event type might have been changed above. However, for pointer
+         * emulation purposes, we want to restore the original event type for
+         * correct processing of TouchEnd events. */
+        ev->any.type = type;
         UpdateDeviceState(dev, &ev->device_event);
+    }
 }
 
 static void


More information about the xorg-devel mailing list