xserver: Branch 'master' - 20 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Apr 19 08:46:30 PDT 2012


 Xi/exevents.c   |   92 +++++++++++++++++++++++++++++++++-----------
 dix/dispatch.c  |    9 ++--
 dix/events.c    |   55 ++++++++++++++++++++++----
 dix/touch.c     |  117 +++++++++++++++++++++++++++++++-------------------------
 include/input.h |    6 +-
 5 files changed, 191 insertions(+), 88 deletions(-)

New commits:
commit e6308e32fe2b5f74133d4d238ffa512257f6327c
Merge: 3720aa3... 51a8d8d...
Author: Keith Packard <keithp at keithp.com>
Date:   Thu Apr 19 10:45:07 2012 -0500

    Merge remote-tracking branch 'whot/for-keith'
    
    Touch input changes from Chase

commit 51a8d8dd19d7496fe84b37a1f0a7a03658120539
Merge: ebf2148... 00cf1c4...
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Apr 19 17:03:54 2012 +1000

    Merge branch 'input-fixes' of git://people.freedesktop.org/~cndougla/xserver into for-keith

commit 00cf1c40b28417d7035c2917d048553eb720023c
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>

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 312910b4e34215aaa50fc0c6092684d5878dc32f
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>

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 a986f2f30cbe2a00e72ded7315c4951d7703e549
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index d2b088c..e9f0207 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 ec9c4295830c3de610e65aca17f4da4a7af3c4c5
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>

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 e175971a6f44d94aa8306dc6b9228ccb2c8a0b4d
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index c8bd222..d2b088c 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 d0449851d1233543c3133d77e0ab7233319cdf5f
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index ae3652b..c8bd222 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 3d06bfe93d33cfe6150d8fb0058ee7bc8d80622b
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 28b288e..ae3652b 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 2efbed23c29020f9994ab7c3155ce7386950dc7a
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>

diff --git a/dix/events.c b/dix/events.c
index 52ce0b8..9496b6f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1409,6 +1409,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
@@ -1457,6 +1489,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 ef64b5ee97099618cf2e2cbbd3e471095695ae24
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 823da2a..28b288e 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 fc518cd9f59060cc19bb90361767c0f47f0e25eb
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 3dd3688..823da2a 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 80d7d1ec6a9d61aa96e7d019dc1bee29d90cea34
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 4629df3..3dd3688 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 8dfd98245d2c44a1eb4c8b7c275e6cfc10fe40f1
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>

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 6ca30cb33e829b4edd01822367e44ffe6f0951b0
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>

diff --git a/dix/events.c b/dix/events.c
index a137d6f..52ce0b8 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1473,6 +1473,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     DeviceIntPtr dev;
     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
                         mouse->deviceGrab.implicitGrab);
+    XID grab_resource = grab->resource;
+    int i;
 
     TouchRemovePointerGrab(mouse);
 
@@ -1497,6 +1499,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 cacdb9a74065ccba7d50a82e14abdf04b36c5309
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index ab2f044..4629df3 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 447fe7a1a72513aa68145962c47894242c589cc9
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>

diff --git a/dix/events.c b/dix/events.c
index b9f9cfa..a137d6f 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1273,18 +1273,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 93c33403642a3de3c9d141ad7940a7b880846aad
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 7da80aa..ab2f044 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 4c1dfd21937efc6a85fb204a73dd7d7151d54daa
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>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index c05c226..7da80aa 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 ebf214876a4885a98ded4f5525925b69005fae05
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Apr 18 15:56:37 2012 +1000

    dix: indentation fix
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/dispatch.c b/dix/dispatch.c
index 104dcc9..62f8ea3 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -413,8 +413,8 @@ Dispatch(void)
                 if (XSERVER_REQUEST_START_ENABLED())
                     XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
                                           client->majorOp,
-                                          ((xReq *) client->requestBuffer)->
-                                          length, client->index,
+                                          ((xReq *) client->requestBuffer)->length,
+                                          client->index,
                                           client->requestBuffer);
 #endif
                 if (result > (maxBigRequestSize << 2))


More information about the xorg-commit mailing list