xserver: Branch 'server-1.12-branch' - 23 commits

Jeremy Huddleston jeremyhu at kemper.freedesktop.org
Thu Apr 26 21:02:30 PDT 2012


 Xi/exevents.c    |  174 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 dix/dispatch.c   |    5 +
 dix/events.c     |   60 +++++++++++++++---
 dix/touch.c      |  117 ++++++++++++++++++++----------------
 include/input.h  |    6 +
 xkb/xkbActions.c |   26 ++++++--
 6 files changed, 295 insertions(+), 93 deletions(-)

New commits:
commit 9ef48c9ffff6704dbe7c976d86527f22b0e1d114
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 18:21:54 2012 -0700

    Replay original touch begin event instead of generated begin event
    
    The generated event does not have axes other than X and Y and has a
    newer timestamp. In particular, the newer timestamp may be newer than
    the real touch end event, which may be stuck in the syncEvents queue. If
    a client uses the timestamps for grabbing bad things may happen.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 00cf1c40b28417d7035c2917d048553eb720023c)

diff --git a/dix/touch.c b/dix/touch.c
index 67c4be2..dd16367 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -474,10 +474,22 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
     flags = TOUCH_CLIENT_ID | TOUCH_REPLAYING;
     if (ti->emulate_pointer)
         flags |= TOUCH_POINTER_EMULATED;
-    /* send fake begin event to next owner */
+    /* Generate events based on a fake touch begin event to get DCCE events if
+     * needed */
+    /* FIXME: This needs to be cleaned up */
     nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
-    for (i = 0; i < nev; i++)
-        DeliverTouchEvents(dev, ti, tel + i, resource);
+    for (i = 0; i < nev; i++) {
+        /* Send saved touch begin event */
+        if (tel[i].any.type == ET_TouchBegin) {
+            DeviceEvent *ev = &ti->history[0];
+            ev->flags |= TOUCH_REPLAYING;
+            DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource);
+        }
+        else {/* Send DCCE event */
+            tel[i].any.time = ti->history[0].time;
+            DeliverTouchEvents(dev, ti, tel + i, resource);
+        }
+    }
 
     valuator_mask_free(&mask);
     FreeEventList(tel, GetMaximumEventsNum());
commit 73cd880fe05c941391a8604406e9ecf657a77f02
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 11:15:40 2012 -0700

    Update currentTime in dispatch loop
    
    A request, like input device grabs, may check a request timestamp
    against currentTime. It is possible for currentTime to lag a previously
    sent event timestamp. If the client makes a request based on such an
    event timestamp, the request may fail the validity check against
    currentTime unless we always update the time before processing the
    request.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 312910b4e34215aaa50fc0c6092684d5878dc32f)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index bce3a0d..9a2e22f 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -393,6 +393,9 @@ Dispatch(void)
                 }
                 /* now, finally, deal with client requests */
 
+                /* Update currentTime so request time checks, such as for input
+                 * device grabs, are calculated correctly */
+                UpdateCurrentTimeIf();
                 result = ReadRequestFromClient(client);
                 if (result <= 0) {
                     if (result < 0)
commit 96d8df5bc9d400d55830b23afe5525b222f8dfc7
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 11:40:15 2012 -0700

    Update device state including when touch record does not exist
    
    If a touch is physically active, the pointer core state should reflect
    that the first button is pressed. Currently, this only occurs when there
    are active listeners of the touch sequence. By moving the device state
    updating to the beginning of touch processing we ensure it is updated
    according to the processed physical state no matter what.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit a986f2f30cbe2a00e72ded7315c4951d7703e549)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d85f01f..37ed5c7 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1597,6 +1597,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         touchid = ev->device_event.touchid;
 
+    if (emulate_pointer)
+        UpdateDeviceState(dev, &ev->device_event);
+
     if (type == ET_TouchBegin) {
         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
                              emulate_pointer);
@@ -1996,9 +1999,6 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
         DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
     }
-
-    if (ti->emulate_pointer)
-        UpdateDeviceState(dev, &ev->device_event);
 }
 
 int
diff --git a/dix/touch.c b/dix/touch.c
index f8f26c8..67c4be2 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -364,14 +364,6 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
 {
     if (ti->emulate_pointer) {
         GrabPtr grab;
-        DeviceEvent ev;
-
-        memset(&ev, 0, sizeof(ev));
-        ev.type = ET_TouchEnd;
-        ev.detail.button = 1;
-        ev.touchid = ti->client_id;
-        ev.flags = TOUCH_POINTER_EMULATED | TOUCH_END;
-        UpdateDeviceState(dev, &ev);
 
         if ((grab = dev->deviceGrab.grab)) {
             if (dev->deviceGrab.fromPassiveGrab &&
commit a9dbdb49698a15ba9bdf4172a6e2fef6133244f3
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 18 12:04:58 2012 -0700

    Check other clients' core masks properly when adding touch listener
    
    The current code checks the core event mask as though it were an XI
    mask. This change fixes the checks so the proper client and event masks
    are used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit ec9c4295830c3de610e65aca17f4da4a7af3c4c5)

diff --git a/dix/touch.c b/dix/touch.c
index 572bdfb..f8f26c8 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -811,6 +811,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (mask & EVENT_CORE_MASK) {
         int coretype = GetCoreType(TouchGetPointerEventType(ev));
         Mask core_filter = event_get_filter_from_type(dev, coretype);
+        OtherClients *oclients;
 
         /* window owner */
         if (IsMaster(dev) && (win->eventMask & core_filter)) {
@@ -822,13 +823,12 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
         }
 
         /* all others */
-        nt_list_for_each_entry(iclients, (InputClients *) wOtherClients(win),
-                               next) {
-            if (!(iclients->mask[XIAllDevices] & core_filter))
+        nt_list_for_each_entry(oclients, wOtherClients(win), next) {
+            if (!(oclients->mask & core_filter))
                 continue;
 
             TouchEventHistoryAllocate(ti);
-            TouchAddListener(ti, iclients->resource, CORE,
+            TouchAddListener(ti, oclients->resource, CORE,
                              type, LISTENER_AWAITING_BEGIN, win);
             return TRUE;
         }
commit 04431dd5e60dc91b61767157914b874515a18feb
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 11:39:10 2012 -0700

    Ensure touch is ended when last listener is rejected
    
    Currently, the touch is only logically ended if the touch has physically
    ended. If the touch hasn't physically ended, the touch record is never
    ended. If there aren't any more listeners, we don't need to keep the dix
    touch record around any more.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit e175971a6f44d94aa8306dc6b9228ccb2c8a0b4d)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a1eccaa..d85f01f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1234,14 +1234,6 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
         }
     }
 
-    /* If there are no other listeners left, and the touchpoint is pending
-     * finish, then we can just kill it now. */
-    if (ti->num_listeners == 1 && ti->pending_finish) {
-        TouchEndTouch(sourcedev, ti);
-        CheckOldestTouch(sourcedev);
-        return;
-    }
-
     /* Remove the resource from the listener list, updating
      * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
     if (TouchRemoveListener(ti, resource)) {
@@ -1254,6 +1246,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * the TouchOwnership or TouchBegin event to the new owner. */
     if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
+    else if (ti->num_listeners == 0)
+        TouchEndTouch(sourcedev, ti);
 
     CheckOldestTouch(sourcedev);
 }
commit 8ce9616a2ccd3f80bf56d69cb9e3fad89996fffb
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 10:49:14 2012 -0700

    Create a new dix touch record for an emulated touch with no listeners
    
    As a special case, if a still physically active pointer emulated touch
    has no listeners and the device is explicitly grabbed for pointer
    events, create a new dix touch record for the grab only.
    
    This allows for clients to "hand off" grabs. For example, when dragging
    a window under compiz the window decorator sees the button press and
    then ungrabs the implicit grab. It then tells compiz to grab the device,
    and compiz then moves the window with the pointer motion. This is racy,
    but is allowed by the input protocol for pointer events when there are
    no other clients with a grab on the device.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit d0449851d1233543c3133d77e0ab7233319cdf5f)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 0c483ac..a1eccaa 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1610,6 +1610,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         ti = TouchFindByClientID(dev, touchid);
 
+    /* Under the following circumstances we create a new touch record for an
+     * existing touch:
+     *
+     * - The touch may be pointer emulated
+     * - An explicit grab is active on the device
+     * - The grab is a pointer grab
+     *
+     * This allows for an explicit grab to receive pointer events for an already
+     * active touch.
+     */
+    if (!ti && type != ET_TouchBegin && emulate_pointer &&
+        dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+        (dev->deviceGrab.grab->grabtype == CORE ||
+         dev->deviceGrab.grab->grabtype == XI ||
+         !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
+        ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+                             emulate_pointer);
+        if (!ti) {
+            DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+                   "grabbed touchpoint %d\n",
+                   dev->name, type, touchid);
+            return;
+        }
+
+        TouchBuildSprite(dev, ti, ev);
+        TouchSetupListeners(dev, ti, ev);
+    }
+
     if (!ti) {
         DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
                dev->name, type, touchid);
diff --git a/dix/touch.c b/dix/touch.c
index e638a89..572bdfb 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -864,6 +864,11 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
     if (dev->deviceGrab.grab)
         TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab);
 
+    /* We set up an active touch listener for existing touches, but not any
+     * passive grab or regular listeners. */
+    if (ev->any.type != ET_TouchBegin)
+        return;
+
     /* First, find all grabbing clients from the root window down
      * to the deepest child window. */
     for (i = 0; i < sprite->spriteTraceGood; i++) {
commit da9cedb1e5e50acc7d3dc40398e1a460b7e3cfdc
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 13:56:08 2012 -0700

    Rename TouchEnsureSprite to TouchBuildSprite and event type checks
    
    The function will be used for building a sprite for pointer emulation
    after an explicit device grab. This commit refactors the code so that
    TouchBuildSprite will function with any event type and moves the checks
    to the caller.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 3d06bfe93d33cfe6150d8fb0058ee7bc8d80622b)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index eace62e..0c483ac 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1625,9 +1625,11 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
         CheckMotion(&ev->device_event, dev);
 
     /* Make sure we have a valid window trace for event delivery; must be
-     * called after event type mutation. */
+     * called after event type mutation. Touch end events are always processed
+     * in order to end touch records. */
     /* FIXME: check this */
-    if (!TouchEnsureSprite(dev, ti, ev))
+    if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+        (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
         return;
 
     /* TouchOwnership events are handled separately from the rest, as they
diff --git a/dix/touch.c b/dix/touch.c
index 72faad5..e638a89 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -542,22 +542,12 @@ TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
  * TouchBegin events.
  */
 Bool
-TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                  InternalEvent *ev)
+TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                 InternalEvent *ev)
 {
     TouchClassPtr t = sourcedev->touch;
     SpritePtr sprite = &ti->sprite;
 
-    /* We may not have a sprite if there are no applicable grabs or
-     * event selections, or if they've disappeared, or if all the grab
-     * owners have rejected the touch.  Don't bother delivering motion
-     * events if not, but TouchEnd events still need to be processed so
-     * we can call FinishTouchPoint and release it for later use. */
-    if (ev->any.type == ET_TouchEnd)
-        return TRUE;
-    else if (ev->any.type != ET_TouchBegin)
-        return (sprite->spriteTraceGood > 0);
-
     if (t->mode == XIDirectTouch) {
         /* Focus immediately under the touchpoint in direct touch mode.
          * XXX: Do we need to handle crossing screens here? */
diff --git a/include/input.h b/include/input.h
index 9a6fdfe..991d648 100644
--- a/include/input.h
+++ b/include/input.h
@@ -563,8 +563,8 @@ extern void TouchAddListener(TouchPointInfoPtr ti, XID resource,
 extern Bool TouchRemoveListener(TouchPointInfoPtr ti, XID resource);
 extern void TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti,
                                 InternalEvent *ev);
-extern Bool TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                              InternalEvent *ev);
+extern Bool TouchBuildSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+                             InternalEvent *ev);
 extern Bool TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite);
 extern int TouchConvertToPointerEvent(const InternalEvent *ev,
                                       InternalEvent *motion,
commit 7be71cb0894052943f94638ffa405cf8dd61bc4a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 17 08:39:38 2012 -0700

    When activating an explicit grab, update owning listener
    
    Pointer passive grabs may be changed by the grabbing client. This allows
    for a selecting client to change an implicit grab to an active grab,
    which is the mechanism used for pop-up windows like application menus.
    
    We need to do the same thing with touches. If the grabbing client is the
    owner of a touch sequence, change the listener record to reflect the new
    grab. If the grabbing client is not the owner, nothing changes for the
    touch.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 2efbed23c29020f9994ab7c3155ce7386950dc7a)

diff --git a/dix/events.c b/dix/events.c
index 72829c3..86336fe 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1408,6 +1408,38 @@ ReattachToOldMaster(DeviceIntPtr dev)
 }
 
 /**
+ * Update touch records when an explicit grab is activated. Any touches owned by
+ * the grabbing client are updated so the listener state reflects the new grab.
+ */
+static void
+UpdateTouchesForGrab(DeviceIntPtr mouse)
+{
+    int i;
+
+    if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
+        return;
+
+    for (i = 0; i < mouse->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+        GrabPtr grab = mouse->deviceGrab.grab;
+
+        if (ti->active &&
+            CLIENT_BITS(ti->listeners[0].listener) == grab->resource) {
+            ti->listeners[0].listener = grab->resource;
+            ti->listeners[0].level = grab->grabtype;
+            ti->listeners[0].state = LISTENER_IS_OWNER;
+            ti->listeners[0].window = grab->window;
+
+            if (grab->grabtype == CORE || grab->grabtype == XI ||
+                !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
+                ti->listeners[0].type = LISTENER_POINTER_GRAB;
+            else
+                ti->listeners[0].type = LISTENER_GRAB;
+        }
+    }
+}
+
+/**
  * Activate a pointer grab on the given device. A pointer grab will cause all
  * core pointer events of this device to be delivered to the grabbing client only.
  * No other device will send core events to the grab client while the grab is
@@ -1456,6 +1488,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
     grabinfo->fromPassiveGrab = isPassive;
     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
     PostNewCursor(mouse);
+    UpdateTouchesForGrab(mouse);
     CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
                       (Bool) grab->keyboardMode);
 }
commit 8ccc6ad63733c7de6bd64b1b11169836d941455b
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 15:53:51 2012 -0700

    Don't deactivate implicit pointer grab on fake touch end event
    
    Fake touch end events are generated by touch acceptance and rejection.
    These should not cause implicit pointer grabs to be deactivated.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit ef64b5ee97099618cf2e2cbbd3e471095695ae24)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 50b05fa..eace62e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1482,6 +1482,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
 
             if (ev->any.type == ET_TouchEnd &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
commit ea3afab228f44d9a41905daeda4c0f9236dbf8e6
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 15:31:47 2012 -0700

    End a pointer emulated touch event only on a "real" end event
    
    Fake end events are generated by touch acceptance or rejection. These
    should not end the touch point.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit fc518cd9f59060cc19bb90361767c0f47f0e25eb)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e76796a..50b05fa 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1856,7 +1856,8 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         if (ti->num_listeners > 1) {
             ev->any.type = ET_TouchUpdate;
             ev->device_event.flags |= TOUCH_PENDING_END;
-            ti->pending_finish = TRUE;
+            if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
+                ti->pending_finish = TRUE;
         }
 
         goto out;
commit fac2c4a5dc1d19bb347729eee8b1bbfc981b853a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Mon Apr 16 14:19:59 2012 -0700

    On touch accept, only process end event for owner if it has seen the end
    
    We still need to generate the touch ownership event to process the
    ending of the touch event in the case where the owner has the end
    already.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 80d7d1ec6a9d61aa96e7d019dc1bee29d90cea34)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7ef75ec..e76796a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1273,9 +1273,18 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (ev->reason == XIRejectTouch)
         TouchRejected(dev, ti, ev->resource, ev);
     else if (ev->reason == XIAcceptTouch) {
+        int i;
+
+        /* Go through the motions of ending the touch if the listener has
+         * 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);
+
         /* The touch owner has accepted the touch.  Send TouchEnd events to
          * everyone else, and truncate the list of listeners. */
-        EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
+        for (i = 1; i < ti->num_listeners; i++)
+            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
commit aaf0063bde791659009eb9001485ac8c15745ae8
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 11:14:51 2012 -0700

    Fix copy/paste error from before git history in UpdateCurrentTimeIf()
    
    See UpdateCurrentTime() for reference. I don't know what bug this might
    trigger, but it wouldn't hurt to fix this.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 8dfd98245d2c44a1eb4c8b7c275e6cfc10fe40f1)

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 104dcc9..bce3a0d 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -214,7 +214,7 @@ UpdateCurrentTimeIf(void)
     systime.milliseconds = GetTimeInMillis();
     if (systime.milliseconds < currentTime.milliseconds)
         systime.months++;
-    if (*checkForInput[0] == *checkForInput[1])
+    if (CompareTimeStamps(systime, currentTime) == LATER)
         currentTime = systime;
 }
 
commit acb74b9b36b55d4f80d85fd6a2790b7c72e197a5
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:17:25 2012 -0700

    When deactivating an explicit pointer grab, reject all grabs on touches
    
    Explicit pointer grabs are placed at the head of the touch listener
    array for pointer emulated touches. If the grab is deactivated, we must
    remove it from all touches for the device.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 6ca30cb33e829b4edd01822367e44ffe6f0951b0)

diff --git a/dix/events.c b/dix/events.c
index 30e3356..72829c3 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1472,6 +1472,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     DeviceIntPtr dev;
     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
                         mouse->deviceGrab.implicitGrab);
+    XID grab_resource = grab->resource;
+    int i;
 
     TouchRemovePointerGrab(mouse);
 
@@ -1496,6 +1498,15 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
         ReattachToOldMaster(mouse);
 
     ComputeFreezes();
+
+    /* 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++) {
+        TouchPointInfoPtr ti = mouse->touch->touches + i;
+
+        if (ti->active && TouchResourceIsOwner(ti, grab_resource))
+            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
+    }
 }
 
 /**
commit 0dea2b1c935ed4c80621e7f5d6fa5193ae09187a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:13:17 2012 -0700

    Accept touch sequence for pointer listener after second event delivery
    
    This is a bit of unimplemented code for touchscreen pointer emulation. A
    pointer grabbing client currently never accepts the touch sequence. The
    sequence must be accepted once any touch-derived event is irrevocably
    delivered to a client.
    
    The first pointer event, derived from a touch begin event, may be caught
    in a sync grab and then replayed. This is essentially a revocable
    delivery of an event. Thus, we must wait till a non-begin event is
    delivered.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit cacdb9a74065ccba7d50a82e14abdf04b36c5309)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 57a75cc..7ef75ec 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1466,6 +1466,12 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             if (!deliveries)
                 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
 
+            /* We must accept the touch sequence once a pointer listener has
+             * received one event past ButtonPress. */
+            if (deliveries && ev->any.type != ET_TouchBegin &&
+                !(ev->device_event.flags & TOUCH_CLIENT_ID))
+                TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+
             if (ev->any.type == ET_TouchEnd &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
commit 2bb2eeb05c973ba410773e380e49c2503a2fe9e6
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 11 08:12:08 2012 -0700

    Split out helper function TouchListenerAcceptReject()
    
    This will be used for accepting and rejecting touches in the future.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 447fe7a1a72513aa68145962c47894242c589cc9)

diff --git a/dix/events.c b/dix/events.c
index 8b7d460..30e3356 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1272,18 +1272,11 @@ ComputeFreezes(void)
                        event->root_x, event->root_y);
         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
             if (IsTouchEvent((InternalEvent *) event)) {
-                InternalEvent *events = InitEventList(GetMaximumEventsNum());
-                int i, nev;
                 TouchPointInfoPtr ti =
                     TouchFindByClientID(replayDev, event->touchid);
                 BUG_WARN(!ti);
-                nev =
-                    GetTouchOwnershipEvents(events, replayDev, ti,
-                                            XIRejectTouch,
-                                            ti->listeners[0].listener, 0);
-                for (i = 0; i < nev; i++)
-                    mieqProcessDeviceEvent(replayDev, events + i, NULL);
-                ProcessInputEvents();
+
+                TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
             }
             else if (replayDev->focus &&
                      !IsPointerEvent((InternalEvent *) event))
diff --git a/dix/touch.c b/dix/touch.c
index 0829b65..72faad5 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -960,15 +960,48 @@ TouchListenerGone(XID resource)
 }
 
 int
+TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, int listener,
+                          int mode)
+{
+    InternalEvent *events;
+    int nev;
+    int i;
+
+    if (listener > 0) {
+        if (mode == XIRejectTouch)
+            TouchRejected(dev, ti, ti->listeners[listener].listener, NULL);
+        else
+            ti->listeners[listener].state = LISTENER_EARLY_ACCEPT;
+
+        return Success;
+    }
+
+    events = InitEventList(GetMaximumEventsNum());
+    if (!events) {
+        BUG_WARN_MSG(TRUE, "Failed to allocate touch ownership events\n");
+        return BadAlloc;
+    }
+
+    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
+                                  ti->listeners[0].listener, 0);
+    BUG_WARN_MSG(nev == 0, "Failed to get touch ownership events\n");
+
+    for (i = 0; i < nev; i++)
+        mieqProcessDeviceEvent(dev, events + i, NULL);
+
+    ProcessInputEvents();
+
+    FreeEventList(events, GetMaximumEventsNum());
+
+    return nev ? Success : BadMatch;
+}
+
+int
 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                   uint32_t touchid, Window grab_window, XID *error)
 {
     TouchPointInfoPtr ti;
-    int nev, i;
-    InternalEvent *events = InitEventList(GetMaximumEventsNum());
-
-    if (!events)
-        return BadAlloc;
+    int i;
 
     if (!dev->touch) {
         *error = dev->id;
@@ -989,24 +1022,5 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
     if (i == ti->num_listeners)
         return BadAccess;
 
-    if (i > 0) {
-        if (mode == XIRejectTouch)
-            TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
-        else
-            ti->listeners[i].state = LISTENER_EARLY_ACCEPT;
-
-        return Success;
-    }
-
-    nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-                                  ti->listeners[0].listener, 0);
-    if (nev == 0)
-        return BadAlloc;
-    for (i = 0; i < nev; i++)
-        mieqProcessDeviceEvent(dev, events + i, NULL);
-
-    ProcessInputEvents();
-
-    FreeEventList(events, GetMaximumEventsNum());
-    return Success;
+    return TouchListenerAcceptReject(dev, ti, i, mode);
 }
diff --git a/include/input.h b/include/input.h
index d891fe5..9a6fdfe 100644
--- a/include/input.h
+++ b/include/input.h
@@ -572,6 +572,8 @@ extern int TouchConvertToPointerEvent(const InternalEvent *ev,
 extern int TouchGetPointerEventType(const InternalEvent *ev);
 extern void TouchRemovePointerGrab(DeviceIntPtr dev);
 extern void TouchListenerGone(XID resource);
+extern int TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                                     int listener, int mode);
 extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
                              uint32_t touchid, Window grab_window, XID *error);
 
commit a37539e794e2bff87ea68e0023cd0cce2bb8de60
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 4 12:59:55 2012 -0700

    Only set XI2 mask if pointer emulation is for XI2 client
    
    The current code returns a reference to memory that may not actually be
    an XI2 mask. Instead, only return a value when an XI2 client has
    selected for events.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 93c33403642a3de3c9d141ad7940a7b880846aad)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index abd68fc..57a75cc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1327,6 +1327,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
 {
     int rc;
     InputClients *iclients = NULL;
+    *mask = NULL;
 
     if (listener->type == LISTENER_GRAB ||
         listener->type == LISTENER_POINTER_GRAB) {
@@ -1378,6 +1379,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             if (!iclients)
                 return FALSE;
 
+            *mask = iclients->xi2mask;
             *client = rClient(iclients);
         }
         else if (listener->level == XI) {
@@ -1409,7 +1411,6 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             *client = oclients ? rClient(oclients) : wClient(*win);
         }
 
-        *mask = iclients ? iclients->xi2mask : NULL;
         *grab = NULL;
     }
 
commit d21d69c2d6b1eb292e9d3f6682339e93603913c9
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Wed Apr 4 12:57:40 2012 -0700

    Check core event mask properly for pointer emulated touch events
    
    The current code checks the core event mask as though it were an XI2
    mask. This change fixes the checks so the proper client and event masks
    are used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Acked-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 4c1dfd21937efc6a85fb204a73dd7d7151d54daa)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index b2dfc13..abd68fc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1377,6 +1377,8 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *client = rClient(iclients);
         }
         else if (listener->level == XI) {
             int xi_type = GetXIType(TouchGetPointerEventType(ev));
@@ -1389,20 +1391,24 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
             BUG_WARN(!iclients);
             if (!iclients)
                 return FALSE;
+
+            *client = rClient(iclients);
         }
         else {
             int coretype = GetCoreType(TouchGetPointerEventType(ev));
             Mask core_filter = event_get_filter_from_type(dev, coretype);
+            OtherClients *oclients;
 
             /* all others */
-            nt_list_for_each_entry(iclients,
-                                   (InputClients *) wOtherClients(*win), next)
-                if (iclients->mask[XIAllDevices] & core_filter)
-                break;
-            /* if owner selected, iclients is NULL */
+            nt_list_for_each_entry(oclients,
+                                   (OtherClients *) wOtherClients(*win), next)
+                if (oclients->mask & core_filter)
+                    break;
+
+            /* if owner selected, oclients is NULL */
+            *client = oclients ? rClient(oclients) : wClient(*win);
         }
 
-        *client = iclients ? rClient(iclients) : wClient(*win);
         *mask = iclients ? iclients->xi2mask : NULL;
         *grab = NULL;
     }
commit 3d3ed6023077c0324fcbf446f387edb1db677b84
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 3 17:31:01 2012 -0700

    Use touch state when querying pointer through core protocol
    
    QueryPointer is part of the core protocol. As such, it knows nothing
    about touch devices. Touches are converted to button 1 press, pointer
    motion, and button 1 release for core clients, so we should ensure the
    pointer state mask has button 1 set when XQueryPointer is used.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 12188c8a8a537b38b1ca4cf8c0de5447e19c886a)

diff --git a/dix/events.c b/dix/events.c
index f7b9456..8b7d460 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5097,8 +5097,7 @@ ProcQueryPointer(ClientPtr client)
     memset(&rep, 0, sizeof(xQueryPointerReply));
     rep.type = X_Reply;
     rep.sequenceNumber = client->sequence;
-    rep.mask = mouse->button ? (mouse->button->state) : 0;
-    rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
+    rep.mask = event_get_corestate(mouse, keyboard);
     rep.length = 0;
     rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
     rep.rootX = pSprite->hot.x;
commit 50b71dcfb8b2ec14a55a119f042509d69847d776
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:42 2012 -0700

    Ensure sequential touches are pointer emulated sequentially
    
    Issue:
    * Two sequential touches (i.e. down, up, down, up)
    * Both are grabbed by a touch grab
    * Both have a second listener in the form of a pointer grab or selection
    * The second and first touches are rejected in that order
    
    The first touch must be pointer emulated before the second touch, so the
    second touch must be paused until the first touch is rejected or
    accepted and all events are delivered to pointer clients.
    
    This change ensures all pointer emulated events are emitted
    sequentially. It necessarily imposes a delay on further touch events
    when pointer grabs and selections are used, but there is no way around
    it.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 32ece7c09bf0ebc3d99b4078aacebbd44314776a)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index fc43f02..b2dfc13 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1111,6 +1111,48 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
 }
 
 /**
+ * Find the oldest touch that still has a pointer emulation client.
+ *
+ * Pointer emulation can only be performed for the oldest touch. Otherwise, the
+ * order of events seen by the client will be wrong. This function helps us find
+ * the next touch to be emulated.
+ *
+ * @param dev The device to find touches for.
+ */
+static TouchPointInfoPtr
+FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = NULL;
+    int i;
+
+    for (i = 0; i < dev->touch->num_touches; i++) {
+        TouchPointInfoPtr ti = dev->touch->touches + i;
+        int j;
+
+        if (!ti->active || !ti->emulate_pointer)
+            continue;
+
+        for (j = 0; j < ti->num_listeners; j++) {
+            if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
+                ti->listeners[j].type == LISTENER_POINTER_REGULAR)
+                break;
+        }
+        if (j == ti->num_listeners)
+            continue;
+
+        if (!oldest) {
+            oldest = ti;
+            continue;
+        }
+
+        if (oldest->client_id - ti->client_id < UINT_MAX / 2)
+            oldest = ti;
+    }
+
+    return oldest;
+}
+
+/**
  * If the current owner has rejected the event, deliver the
  * TouchOwnership/TouchBegin to the next item in the sprite stack.
  */
@@ -1123,8 +1165,16 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
         DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
                            ti->listeners[0].listener);
-    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
+    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
+        /* We can't punt to a pointer listener unless all older pointer
+         * emulated touches have been seen already. */
+        if ((ti->listeners[0].type == LISTENER_POINTER_GRAB ||
+             ti->listeners[0].type == LISTENER_POINTER_REGULAR) &&
+            ti != FindOldestPointerEmulatedTouch(dev))
+            return;
+
         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
+    }
 
     /* If we've just removed the last grab and the touch has physically
      * ended, send a TouchEnd event too and finalise the touch. */
@@ -1139,6 +1189,25 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
 }
 
 /**
+ * Check the oldest touch to see if it needs to be replayed to its pointer
+ * owner.
+ *
+ * Touch event propagation is paused if it hits a pointer listener while an
+ * older touch with a pointer listener is waiting on accept or reject. This
+ * function will restart propagation of a paused touch if needed.
+ *
+ * @param dev The device to check touches for.
+ */
+static void
+CheckOldestTouch(DeviceIntPtr dev)
+{
+    TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
+
+    if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
+        TouchPuntToNextOwner(dev, oldest, NULL);
+}
+
+/**
  * Process a touch rejection.
  *
  * @param sourcedev The source device of the touch sequence.
@@ -1169,6 +1238,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * finish, then we can just kill it now. */
     if (ti->num_listeners == 1 && ti->pending_finish) {
         TouchEndTouch(sourcedev, ti);
+        CheckOldestTouch(sourcedev);
         return;
     }
 
@@ -1184,6 +1254,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
      * the TouchOwnership or TouchBegin event to the new owner. */
     if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
+
+    CheckOldestTouch(sourcedev);
 }
 
 /**
@@ -1391,6 +1463,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
+                CheckOldestTouch(dev);
                 return Success;
             }
         }
commit fb01dfb55a6a718affa9354c384823e462ee784a
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:41 2012 -0700

    Update event type when delivering end event to a pointer listener
    
    Just like when we deliver to a touch listener, we must convert a touch
    end event to an update event for further clients. This also ensures that
    the touch record is not deleted at the end of ProcessTouchEvent().
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 163b0f375d73c05873fb341652de3ed347337828)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 80ddfcc..fc43f02 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1757,6 +1757,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         listener->type == LISTENER_POINTER_GRAB) {
         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                        grab, xi2mask);
+
+        if (ti->num_listeners > 1) {
+            ev->any.type = ET_TouchUpdate;
+            ev->device_event.flags |= TOUCH_PENDING_END;
+            ti->pending_finish = TRUE;
+        }
+
         goto out;
     }
 
commit b56c1f95bb2d22996651e0a5ca6b6b0e71710a7b
Author: Chase Douglas <chase.douglas at canonical.com>
Date:   Tue Apr 10 17:12:40 2012 -0700

    Don't update listener after deactivating implicit pointer grab
    
    After the pointer grab is deactivated, the touch listener record is
    updated at the end of DeliverTouchEmulatedEvent. However, the touch
    record is ended when the grab is deactivated, so the update to the
    listener record is in an array of memory that has been freed.
    
    Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 210cd12c47d063f97915ff23292b61d09abfd73a)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f681a8b..80ddfcc 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1389,8 +1389,10 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
             if (ev->any.type == ET_TouchEnd &&
                 !dev->button->buttonsDown &&
-                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab))
+                dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);
+                return Success;
+            }
         }
     }
     else {
commit 8ca5a94f454d04ed5f1d0b18272a838b8e7f1e7a
Author: Andreas Wettstein <wettstein509 at solnet.ch>
Date:   Sat Feb 25 20:48:17 2012 +0100

    XKB: Redirect actions defunct with Gtk3 (XInput?)
    
    When redirect actions are used with Gtk3, Gtk3 complained about
    events not holding a GdkDevice.  This was caused by device IDs
    not being set for redirect actions.
    
    More seriously, Gtk3 did not receive state changes redirect
    actions might specify.  This was because event_set_state in
    dix/inpututils.c accesses the prev_state field, but the changes
    for the redirect action were only put into the state field.
    
    Signed-off-by: Andreas Wettstein <wettstein509 at solnet.ch>
    Reviewed-by: Peter Hutterer <peter.hutterer at who-t.net>
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 9e017cf0cf1f0c9d0d9c2cfeb82ea5dc0eb5905e)

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index c473df1..5ec1ed5 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -799,7 +799,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 {
     DeviceEvent ev;
     int x, y;
-    XkbStateRec old;
+    XkbStateRec old, old_prev;
     unsigned mods, mask;
     xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
     ProcessInputProc backupproc;
@@ -807,6 +807,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
     /* never actually used uninitialised, but gcc isn't smart enough
      * to work that out. */
     memset(&old, 0, sizeof(old));
+    memset(&old_prev, 0, sizeof(old_prev));
     memset(&ev, 0, sizeof(ev));
 
     if ((filter->keycode != 0) && (filter->keycode != keycode))
@@ -818,6 +819,11 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
     ev.time = GetTimeInMillis();
     ev.root_x = x;
     ev.root_y = y;
+    /* redirect actions do not work across devices, therefore the following is
+     * correct: */
+    ev.deviceid = xkbi->device->id;
+    /* filter->priv must be set up by the caller for the initial press. */
+    ev.sourceid = filter->priv;
 
     if (filter->keycode == 0) { /* initial press */
         if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
@@ -827,7 +833,6 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         filter->keycode = keycode;
         filter->active = 1;
         filter->filterOthers = 0;
-        filter->priv = 0;
         filter->filter = _XkbFilterRedirectKey;
         filter->upAction = *pAction;
 
@@ -845,6 +850,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 
         if (mask || mods) {
             old = xkbi->state;
+            old_prev = xkbi->prev_state;
             xkbi->state.base_mods &= ~mask;
             xkbi->state.base_mods |= (mods & mask);
             xkbi->state.latched_mods &= ~mask;
@@ -852,6 +858,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
             xkbi->state.locked_mods &= ~mask;
             xkbi->state.locked_mods |= (mods & mask);
             XkbComputeDerivedState(xkbi);
+            xkbi->prev_state = xkbi->state;
         }
 
         UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
@@ -860,8 +867,10 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
                                      xkbUnwrapProc);
 
-        if (mask || mods)
+        if (mask || mods) {
             xkbi->state = old;
+            xkbi->prev_state = old_prev;
+        }
     }
     else if (filter->keycode == keycode) {
 
@@ -879,6 +888,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
 
         if (mask || mods) {
             old = xkbi->state;
+            old_prev = xkbi->prev_state;
             xkbi->state.base_mods &= ~mask;
             xkbi->state.base_mods |= (mods & mask);
             xkbi->state.latched_mods &= ~mask;
@@ -886,6 +896,7 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
             xkbi->state.locked_mods &= ~mask;
             xkbi->state.locked_mods |= (mods & mask);
             XkbComputeDerivedState(xkbi);
+            xkbi->prev_state = xkbi->state;
         }
 
         UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
@@ -894,8 +905,10 @@ _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
         COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
                                      xkbUnwrapProc);
 
-        if (mask || mods)
+        if (mask || mods) {
             xkbi->state = old;
+            xkbi->prev_state = old_prev;
+        }
 
         filter->keycode = 0;
         filter->active = 0;
@@ -1165,6 +1178,11 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
                 break;
             case XkbSA_RedirectKey:
                 filter = _XkbNextFreeFilter(xkbi);
+                /* redirect actions must create a new DeviceEvent.  The
+                 * source device id for this event cannot be obtained from
+                 * xkbi, so we pass it here explicitly. The field deviceid
+                 * equals to xkbi->device->id. */
+                filter->priv = event->sourceid;
                 sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, &act);
                 break;
             case XkbSA_DeviceBtn:
commit d75da4eccbabc3f83937cbd4eb2d6be2fd27a4b9
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Feb 20 12:09:33 2012 +1000

    dix: IsFloating() on master devices is always false
    
    There are a few subtle bugs during startup where IsFloating() returns true
    if the device is a master device that is not yet paired with its keyboard
    device.
    
    Force IsFloating() to always return FALSE for master devices, that was the
    intent after all and any code that relies on the other behaviour should be
    fixed instead.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Reviewed-by: Jeremy Huddleston <jeremyhu at apple.com>
    Tested-by: Jon TURNEY <jon.turney at dronecode.org.uk>
    (cherry picked from commit 5497ce3da442d27c2dc7796bfef6ccd670bbadc4)

diff --git a/dix/events.c b/dix/events.c
index 0e4ba86..f7b9456 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -341,7 +341,7 @@ IsMaster(DeviceIntPtr dev)
 Bool
 IsFloating(DeviceIntPtr dev)
 {
-    return GetMaster(dev, MASTER_KEYBOARD) == NULL;
+    return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
 }
 
 /**


More information about the xorg-commit mailing list