<div dir="ltr"><div>This fixes the crash and makes pointer-emulated touch work properly on my Chromebook.<br><br></div>Reviewed-by: Jasper St. Pierre <<a href="mailto:jstpierre@mecheye.net">jstpierre@mecheye.net</a>><br>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Jul 9, 2013 at 7:01 PM, Peter Hutterer <span dir="ltr"><<a href="mailto:peter.hutterer@who-t.net" target="_blank">peter.hutterer@who-t.net</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Ungrabbing a device during an active touch grab rejects the grab. Ungrabbing<br>
a device during an active pointer grab accepts the grab.<br>
<br>
Rejection is not really an option for a pointer-emulated grab, if a client<br>
has a button mask on the window it would get a ButtonPress emulated after<br>
UngrabDevice. That is against the core grab behaviour.<br>
<br>
X.Org Bug 66720 <<a href="http://bugs.freedesktop.org/show_bug.cgi?id=66720" target="_blank">http://bugs.freedesktop.org/show_bug.cgi?id=66720</a>><br>
<br>
Signed-off-by: Peter Hutterer <<a href="mailto:peter.hutterer@who-t.net">peter.hutterer@who-t.net</a>><br>
---<br>
 Xi/exevents.c | 33 ++++++++++++++++++++++-----------<br>
 dix/events.c  | 11 +++++++++--<br>
 2 files changed, 31 insertions(+), 13 deletions(-)<br>
<br>
diff --git a/Xi/exevents.c b/Xi/exevents.c<br>
index 2bbc6f0..fd4b80c 100644<br>
--- a/Xi/exevents.c<br>
+++ b/Xi/exevents.c<br>
@@ -1223,9 +1223,13 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,<br>
     else if (ev->reason == XIAcceptTouch) {<br>
         int i;<br>
<br>
-        /* Go through the motions of ending the touch if the listener has<br>
+<br>
+        /* For pointer-emulated listeners that ungrabbed the active grab,<br>
+         * the state was forced to LISTENER_HAS_END. Still go<br>
+         * through the motions of ending the touch if the listener has<br>
          * already seen the end. This ensures that the touch record is ended in<br>
-         * the server. */<br>
+         * the server.<br>
+         */<br>
         if (ti->listeners[0].state == LISTENER_HAS_END)<br>
             TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);<br>
<br>
@@ -1883,16 +1887,23 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,<br>
<br>
     if (listener->type == LISTENER_POINTER_REGULAR ||<br>
         listener->type == LISTENER_POINTER_GRAB) {<br>
-        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,<br>
-                                       grab, xi2mask);<br>
+        /* Note: If the active grab was ungrabbed, we already changed the<br>
+         * state to LISTENER_HAS_END but still get here. So we mustn't<br>
+         * actually send the event.<br>
+         * This is part two of the hack in DeactivatePointerGrab<br>
+         */<br>
+        if (listener->state != LISTENER_HAS_END) {<br>
+            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,<br>
+                                           grab, xi2mask);<br>
<br>
-         /* Once we send a TouchEnd to a legacy listener, we're already well<br>
-          * past the accepting/rejecting stage (can only happen on<br>
-          * GrabModeSync + replay. This listener now gets the end event,<br>
-          * and we can continue.<br>
-          */<br>
-        if (rc == Success)<br>
-            listener->state = LISTENER_HAS_END;<br>
+             /* Once we send a TouchEnd to a legacy listener, we're already well<br>
+              * past the accepting/rejecting stage (can only happen on<br>
+              * GrabModeSync + replay. This listener now gets the end event,<br>
+              * and we can continue.<br>
+              */<br>
+            if (rc == Success)<br>
+                listener->state = LISTENER_HAS_END;<br>
+        }<br>
         goto out;<br>
     }<br>
<br>
diff --git a/dix/events.c b/dix/events.c<br>
index e5db348..03b2d2e 100644<br>
--- a/dix/events.c<br>
+++ b/dix/events.c<br>
@@ -1522,13 +1522,20 @@ DeactivatePointerGrab(DeviceIntPtr mouse)<br>
     for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {<br>
         TouchPointInfoPtr ti = mouse->touch->touches + i;<br>
         if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {<br>
+            int mode = XIRejectTouch;<br>
             /* Rejecting will generate a TouchEnd, but we must not<br>
                emulate a ButtonRelease here. So pretend the listener<br>
                already has the end event */<br>
             if (grab->grabtype == CORE || grab->grabtype == XI ||<br>
-                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin))<br>
+                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) {<br>
+                mode = XIAcceptTouch;<br>
+                /* NOTE: we set the state here, but<br>
+                 * ProcessTouchOwnershipEvent() will still call<br>
+                 * TouchEmitTouchEnd for this listener. The other half of<br>
+                 * this hack is in DeliverTouchEndEvent */<br>
                 ti->listeners[0].state = LISTENER_HAS_END;<br>
-            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);<br>
+            }<br>
+            TouchListenerAcceptReject(mouse, ti, 0, mode);<br>
         }<br>
     }<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
1.8.2.1<br>
<br>
_______________________________________________<br>
<a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a>: X.Org development<br>
Archives: <a href="http://lists.x.org/archives/xorg-devel" target="_blank">http://lists.x.org/archives/xorg-devel</a><br>
Info: <a href="http://lists.x.org/mailman/listinfo/xorg-devel" target="_blank">http://lists.x.org/mailman/listinfo/xorg-devel</a><br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br>  Jasper<br>
</div>