Problem with touchscreen events and grabs
Peter Hutterer
peter.hutterer at who-t.net
Sun Oct 21 23:47:14 PDT 2012
On Tue, Oct 16, 2012 at 09:54:23PM -0400, Thomas Jaeger wrote:
> I've noticed an issue with grabs as well, not sure if it's related to
> this one. It's really easy to reproduce, though: All you need is a
> little test client that passively grabs button 1 on the MD (like the one
> attached). A passive core grab will do as well. What happens is that
> (1) clients selecting for core events will receive emulated pointer
> events despite the passive grab and (2) sometimes ButtonRelease events
> go missing (this goes both for the grabbing and non-grabbing clients,
> but not necessarily at the same time).
btw, did you file a bug for this one? I've got a preliminary patch
(attached) but I'm not sure of the side-effects yet.
Cheers,
Peter
> On 10/15/2012 11:09 PM, Peter Hutterer wrote:
> > On Fri, Oct 12, 2012 at 03:38:24PM +0200, Thierry Reding wrote:
> >> Hi,
> >>
> >> I've been seeing a very strange issue. Originally this was observed when
> >> using a browser with an onscreen keyboard. It would sometimes happen
> >> that the keys on the keyboard would get stuck and be repeatedly sent.
> >
> > But on the whole, this issue looks convoluted enough that you may have to
> > write a little test application to reliably reproduce this.
> >
> > Cheers,
> > Peter
> /* gcc -Wall grab.c -o grab -lXi -lX11 */
>
> #include <X11/Xlib.h>
> #include <X11/extensions/XInput2.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <stdbool.h>
>
> Display *dpy;
> Window root;
> int opcode;
>
> void init_xi2() {
> int event, error;
> int major = 2, minor = 0;
> if (!XQueryExtension(dpy, "XInputExtension", &opcode, &event, &error) ||
> XIQueryVersion(dpy, &major, &minor) == BadRequest ||
> major < 2) {
> printf("Error: XI2 required\n");
> exit(EXIT_FAILURE);
> }
> }
>
> void grab(int dev) {
> unsigned char mask_data[2] = {0,};
> XISetMask(mask_data, XI_ButtonPress);
> XISetMask(mask_data, XI_ButtonRelease);
> XIEventMask mask = { XIAllDevices, sizeof(mask_data), mask_data };
> XIGrabModifiers mods = { XIAnyModifier };
> XIGrabButton(dpy, dev, 1, root, None, GrabModeAsync, GrabModeAsync, False, &mask, 1, &mods);
> }
>
>
> int main(int argc, char *argv[]) {
> dpy = XOpenDisplay(NULL);
> root = DefaultRootWindow(dpy);
>
> init_xi2();
> if (argc < 2 || atoi(argv[1]) <= 0) {
> printf("Usage: %s <device number>\n", argv[0]);
> return EXIT_FAILURE;
> }
> int dev = atoi(argv[1]);
>
> grab(dev);
>
> while (true) {
> XEvent ev;
> XNextEvent(dpy, &ev);
> if (XGetEventData(dpy, &ev.xcookie) && ev.xcookie.extension == opcode) {
> switch (ev.xcookie.evtype) {
> case XI_ButtonPress:
> printf("Press\n");
> break;
> case XI_ButtonRelease:
> printf("Release\n");
> break;
> }
> }
> XFreeEventData(dpy, &ev.xcookie);
> }
>
> return EXIT_SUCCESS;
> }
-------------- next part --------------
>From af01bee404728248faa608ec8ffb78e813d9e734 Mon Sep 17 00:00:00 2001
From: Peter Hutterer <peter.hutterer at who-t.net>
Date: Mon, 22 Oct 2012 14:58:05 +1000
Subject: [PATCH] dix: don't remove the device grab from a terminating passive
grab
A TouchEnd will terminate a passive grab for that touch point. If that is
the case, don't try to remove that grab from all other touch points as well.
This fixes two bugs.
Bug 1:
If the number of touches is equal or larger than max_touches for the device,
we trigger infinite recursion.
Test case:
Register for passive button 1 grab on the root window, then
initiate and end max_touches + 1 touch points in quick
succession, i.e. before the server gets to actually process them.
Terminating the first will cause the passive pointer grab to be deactivated,
which erroneously triggered a removal of the device grab from all other
touch points - causing more TouchEnd events that tried to do the same.
Bug 2:
If a client has an async pointer grab on a window and another client a
(non-ownership) touch selection on that same window, the client must never
receive touch events. Pointer grab async is akin to TouchAccept, so no touch
event ever goes past the grab.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
dix/events.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dix/events.c b/dix/events.c
index ddb5b34..c5689e0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1505,6 +1505,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
DeviceIntPtr dev;
Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
mouse->deviceGrab.implicitGrab);
+ Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
XID grab_resource = grab->resource;
int i;
@@ -1534,7 +1535,7 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
/* If an explicit grab was deactivated, we must remove it from the head of
* all the touches' listener lists. */
- for (i = 0; mouse->touch && i < mouse->touch->num_touches; i++) {
+ 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))
--
1.7.11.7
More information about the xorg-devel
mailing list