xserver: Branch 'master' - 6 commits

Keith Packard keithp at kemper.freedesktop.org
Thu May 23 09:41:24 PDT 2013


 Xi/exevents.c |   28 ++++++++++++++++++----------
 dix/touch.c   |    2 +-
 2 files changed, 19 insertions(+), 11 deletions(-)

New commits:
commit 2ccb9fb7faa6980197eb651594a479f7879393b1
Merge: 891123c 4a28adf
Author: Keith Packard <keithp at keithp.com>
Date:   Thu May 23 10:31:33 2013 -0600

    Merge remote-tracking branch 'whot/touch-grab-race-condition-56578'

diff --cc Xi/exevents.c
index 3088257,1dc6882..c3e8e7f
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@@ -1145,14 -1145,20 +1147,20 @@@ TouchPuntToNextOwner(DeviceIntPtr dev, 
      }
  
      /* If we've just removed the last grab and the touch has physically
-      * ended, send a TouchEnd event too and finalise the touch. */
-     if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) {
-         EmitTouchEnd(dev, ti, 0, 0);
-         TouchEndTouch(dev, ti);
-         return;
+      * ended, send a TouchEnd event too and finalise the touch.
+      * If we only have an async grab left, do the same.
+      */
+     if (ti->num_listeners == 1 && ti->pending_finish) {
+         if (ti->num_grabs == 0 ||
+             ti->listeners[0].grab->grabtype != XI2 ||
+             !xi2mask_isset(ti->listeners[0].grab->xi2mask, dev, XI_TouchBegin)) {
+             EmitTouchEnd(dev, ti, 0, 0, TRUE);
+             TouchEndTouch(dev, ti);
+             return;
+         }
      }
  
 -    if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
 +    if (listener->state == LISTENER_EARLY_ACCEPT)
          ActivateEarlyAccept(dev, ti);
  }
  
commit 4a28adf35a5e90ad4b9e74a23a9ef885823cb1ba
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 13 15:12:32 2013 +1000

    Xi: if the last listener left is an async grab, finish the touch.
    
    Async grabs cannot replay events, so we don't need to keep them around. And
    non-touch grabbing clients will not accept/reject, so we need to finish the
    touch right now.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 02b7336..1dc6882 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1145,11 +1145,17 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
     }
 
     /* If we've just removed the last grab and the touch has physically
-     * ended, send a TouchEnd event too and finalise the touch. */
-    if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) {
-        EmitTouchEnd(dev, ti, 0, 0, TRUE);
-        TouchEndTouch(dev, ti);
-        return;
+     * ended, send a TouchEnd event too and finalise the touch.
+     * If we only have an async grab left, do the same.
+     */
+    if (ti->num_listeners == 1 && ti->pending_finish) {
+        if (ti->num_grabs == 0 ||
+            ti->listeners[0].grab->grabtype != XI2 ||
+            !xi2mask_isset(ti->listeners[0].grab->xi2mask, dev, XI_TouchBegin)) {
+            EmitTouchEnd(dev, ti, 0, 0, TRUE);
+            TouchEndTouch(dev, ti);
+            return;
+        }
     }
 
     if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
commit d3a8d8f40d7e337829b2bc31d5b163129a448a65
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 13 15:09:05 2013 +1000

    Xi: if a touch has ended on the last listener, update the device state
    
    If the touch has physically ended before but we had one or more grabbing
    listeners left, the touch was changed to TouchUpdate and UpdateDeviceState
    did not change the button state.
    
    When we're now ending the touch because the last listener has been
    processed, call UpdateDeviceState with the TouchEnd so we can unset the
    mask. Otherwise, an XQueryPointer will assume the button is still down, even
    after the touch has finished.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7fffdb9..02b7336 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1064,7 +1064,7 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
  * @param resource The client resource to deliver to, or 0 for all clients.
  */
 static void
-EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
+EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource, int update_device_state)
 {
     InternalEvent event;
 
@@ -1074,6 +1074,8 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
     TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
     GetDixTouchEnd(&event, dev, ti, flags);
     DeliverTouchEvents(dev, ti, &event, resource);
+    if (update_device_state && ti->emulate_pointer)
+        UpdateDeviceState(dev, &event.device_event);
 }
 
 /**
@@ -1145,7 +1147,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
     /* If we've just removed the last grab and the touch has physically
      * ended, send a TouchEnd event too and finalise the touch. */
     if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) {
-        EmitTouchEnd(dev, ti, 0, 0);
+        EmitTouchEnd(dev, ti, 0, 0, TRUE);
         TouchEndTouch(dev, ti);
         return;
     }
@@ -1194,7 +1196,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
     for (i = 0; i < ti->num_listeners; i++) {
         if (ti->listeners[i].listener == resource) {
             if (ti->listeners[i].state != LISTENER_HAS_END)
-                EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
+                EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource, FALSE);
             break;
         }
     }
@@ -1234,12 +1236,12 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
          * already seen the end. This ensures that the touch record is ended in
          * the server. */
         if (ti->listeners[0].state == LISTENER_HAS_END)
-            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener, FALSE);
 
         /* The touch owner has accepted the touch.  Send TouchEnd events to
          * everyone else, and truncate the list of listeners. */
         for (i = 1; i < ti->num_listeners; i++)
-            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener, FALSE);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
commit 3411971a7357312723dfeecca58dccd5876619f4
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 13 11:26:11 2013 +1000

    dix: don't prepend an activated passive grab to the listeners
    
    If the device is currently grabbed as the result of a passive grab
    activating, do not prepend that grab to the listeners (unlike active grabs).
    Otherwise, a client with a passive pointer grab will prevent touch grabs
    from activating higher up in the window stack.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/touch.c b/dix/touch.c
index 0db842c..a32ff34 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -874,7 +874,7 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
     SpritePtr sprite = &ti->sprite;
     WindowPtr win;
 
-    if (dev->deviceGrab.grab)
+    if (dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab)
         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
 
     /* We set up an active touch listener for existing touches, but not any
commit 8a2d2946ffa4143a20e279aeebc39e43a4a497c2
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 13 10:49:23 2013 +1000

    Xi: not having an ownership mask does not mean automatic acceptance
    
    If we only have a single touch-grabbing client, setting the client as owner
    would clean up the touch once the TouchEnd was processed. If the client then
    calls XIAllowTouches() it will receive a BadValue for the touch ID (since
    the internal record is already cleaned up).
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 609b126..7fffdb9 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1863,7 +1863,7 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
         if (has_ownershipmask)
             TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
 
-        if (!has_ownershipmask || listener->type == LISTENER_REGULAR)
+        if (listener->type == LISTENER_REGULAR)
             state = LISTENER_HAS_ACCEPTED;
         else
             state = LISTENER_IS_OWNER;
commit 2cd9c4f709f105b7a7faf31b8c10993d0949563c
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Feb 13 10:05:15 2013 +1000

    dix: don't set non-exisiting flags on touch events
    
    Unlike pointer/keyboard events, the flags field for ET_Touch* is a set of
    server-internal defines that we need to convert to XI protocol defines.
    Currently only two of those defines actually translate to the protocol, so
    make sure we don't send internal garbage down the wire.
    
    No effect to current clients since they shouldn't look at undefined bits
    anyway.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/eventconvert.c b/dix/eventconvert.c
index 2c411cf..ebc52c3 100644
--- a/dix/eventconvert.c
+++ b/dix/eventconvert.c
@@ -684,17 +684,18 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
     xde->root_x = double_to_fp1616(ev->root_x + ev->root_x_frac);
     xde->root_y = double_to_fp1616(ev->root_y + ev->root_y_frac);
 
-    if (ev->type == ET_TouchUpdate)
-        xde->flags |= (ev->flags & TOUCH_PENDING_END) ? XITouchPendingEnd : 0;
-    else
-        xde->flags = ev->flags;
+    if (IsTouchEvent((InternalEvent *)ev)) {
+        if (ev->type == ET_TouchUpdate)
+            xde->flags |= (ev->flags & TOUCH_PENDING_END) ? XITouchPendingEnd : 0;
 
-    if (IsTouchEvent((InternalEvent *) ev) &&
-        ev->flags & TOUCH_POINTER_EMULATED)
-        xde->flags |= XITouchEmulatingPointer;
+        if (ev->flags & TOUCH_POINTER_EMULATED)
+            xde->flags |= XITouchEmulatingPointer;
+    } else {
+        xde->flags = ev->flags;
 
-    if (ev->key_repeat)
-        xde->flags |= XIKeyRepeat;
+        if (ev->key_repeat)
+            xde->flags |= XIKeyRepeat;
+    }
 
     xde->mods.base_mods = ev->mods.base;
     xde->mods.latched_mods = ev->mods.latched;


More information about the xorg-commit mailing list