[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xorg-server: Changes to 'ubuntu+1'



 Xi/exevents.c      |  135 +++++++++++++++++++++++++----------------------------
 dix/eventconvert.c |   19 +++----
 dix/events.c       |   13 +++++
 dix/touch.c        |   62 +++++++++++++++++++++++-
 include/eventstr.h |    1 
 include/input.h    |    2 
 6 files changed, 149 insertions(+), 83 deletions(-)

New commits:
commit 9509d8003196c2347458d68d800c4bfa442d877d
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:21 2013 +1000

    dix: XAllowEvents() on a touch event means accepting it
    
    A sync grab is the owner once it gets events. If it doesn't replay the
    event it will get all events from this touch, equivalent to accepting it.
    
    If the touch has ended before XAllowEvents() is called, we also now need to
    send the TouchEnd event and clean-up since we won't see anything more from
    this touch.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 0512052..da9bd38 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1742,6 +1742,16 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
         }
         break;
     }
+
+    /* We've unfrozen the grab. If the grab was a touch grab, we're now the
+     * owner and expected to accept/reject it. Reject == ReplayPointer which
+     * we've handled in ComputeFreezes() (during DeactivateGrab) above,
+     * anything else is accept.
+     */
+    if (newState != NOT_GRABBED /* Replay */ &&
+        IsTouchEvent((InternalEvent*)grabinfo->sync.event)) {
+        TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid);
+    }
 }
 
 /**
diff --git a/dix/touch.c b/dix/touch.c
index 8b15da6..3918d93 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -1102,3 +1102,17 @@ TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resourc
     GetDixTouchEnd(&event, dev, ti, flags);
     DeliverTouchEvents(dev, ti, &event, resource);
 }
+
+void
+TouchAcceptAndEnd(DeviceIntPtr dev, int touchid)
+{
+    TouchPointInfoPtr ti = TouchFindByClientID(dev, touchid);
+    if (!ti)
+        return;
+
+    TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+    if (ti->pending_finish)
+        TouchEmitTouchEnd(dev, ti, 0, 0);
+    if (ti->num_listeners <= 1)
+        TouchEndTouch(dev, ti);
+}
diff --git a/include/input.h b/include/input.h
index 866879b..7eed60b 100644
--- a/include/input.h
+++ b/include/input.h
@@ -591,6 +591,7 @@ extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev);
 extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti,
                                                   Time time, XID resource);
 extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource);
+extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid);
 
 /* misc event helpers */
 extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);

commit ea00005979fd16714638d93a2f935b49f4d2f660
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:20 2013 +1000

    dix: move EmitTouchEnd to touch.c
    
    No functional changes, this just enables it to be re-used easier.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 38b39c3..80c93df 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1053,33 +1053,6 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
 }
 
 /**
- * Generate and deliver a TouchEnd event.
- *
- * @param dev The device to deliver the event for.
- * @param ti The touch point record to deliver the event for.
- * @param flags Internal event flags. The called does not need to provide
- *        TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
- *        they are set appropriately.
- * @param resource The client resource to deliver to, or 0 for all clients.
- */
-static void
-EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
-{
-    InternalEvent event;
-
-    /* We're not processing a touch end for a frozen device */
-    if (dev->deviceGrab.sync.frozen)
-        return;
-
-    flags |= TOUCH_CLIENT_ID;
-    if (ti->emulate_pointer)
-        flags |= TOUCH_POINTER_EMULATED;
-    TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
-    GetDixTouchEnd(&event, dev, ti, flags);
-    DeliverTouchEvents(dev, ti, &event, resource);
-}
-
-/**
  * Find the oldest touch that still has a pointer emulation client.
  *
  * Pointer emulation can only be performed for the oldest touch. Otherwise, the
@@ -1150,7 +1123,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
     /* New owner has Begin/Update but not end. If touch is pending_finish,
      * emulate the TouchEnd now */
     if (ti->pending_finish) {
-        EmitTouchEnd(dev, ti, 0, 0);
+        TouchEmitTouchEnd(dev, ti, 0, 0);
 
         /* If the last owner is not a touch grab, finalise the touch, we
            won't get more correspondence on this.
@@ -1208,7 +1181,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);
+                TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
             break;
         }
     }
@@ -1248,12 +1221,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);
+            TouchEmitTouchEnd(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. */
         for (i = 1; i < ti->num_listeners; i++)
-            EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
+            TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
diff --git a/dix/touch.c b/dix/touch.c
index b5b7c1e..8b15da6 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -1075,3 +1075,30 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev)
 
     FreeEventList(eventlist, GetMaximumEventsNum());
 }
+
+/**
+ * Generate and deliver a TouchEnd event.
+ *
+ * @param dev The device to deliver the event for.
+ * @param ti The touch point record to deliver the event for.
+ * @param flags Internal event flags. The called does not need to provide
+ *        TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
+ *        they are set appropriately.
+ * @param resource The client resource to deliver to, or 0 for all clients.
+ */
+void
+TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
+{
+    InternalEvent event;
+
+    /* We're not processing a touch end for a frozen device */
+    if (dev->deviceGrab.sync.frozen)
+        return;
+
+    flags |= TOUCH_CLIENT_ID;
+    if (ti->emulate_pointer)
+        flags |= TOUCH_POINTER_EMULATED;
+    TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource);
+    GetDixTouchEnd(&event, dev, ti, flags);
+    DeliverTouchEvents(dev, ti, &event, resource);
+}
diff --git a/include/input.h b/include/input.h
index 5c65597..866879b 100644
--- a/include/input.h
+++ b/include/input.h
@@ -590,6 +590,7 @@ extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
 extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev);
 extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti,
                                                   Time time, XID resource);
+extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource);
 
 /* misc event helpers */
 extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);

commit 768c5b54d137d5f357f0fa00eea39e9cb07cf13d
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:19 2013 +1000

    Xi: Don't emit a TouchEnd event to a frozen device
    
    EmitTouchEnd calls DeliverTouchEvents directly instead of through
    public.processInputProc. If a device is frozen, the TouchEnd is
    processed while the device is waiting for a XAllowEvents and thus ends the
    touch point (and the grab) before the client decided what to do with it. In
    the case of ReplayPointer, this loses the event.
    
    This is a hack, but making EmitTouchEnd use processInputProc breaks
    approximately everything, especially the touch point is cleaned up during
    ProcessTouchEvents. Working around that is a bigger hack than this.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 76c456b..38b39c3 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1067,6 +1067,10 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
 {
     InternalEvent event;
 
+    /* We're not processing a touch end for a frozen device */
+    if (dev->deviceGrab.sync.frozen)
+        return;
+
     flags |= TOUCH_CLIENT_ID;
     if (ti->emulate_pointer)
         flags |= TOUCH_POINTER_EMULATED;

commit ddce3dbe7b32967e1d9d768c9aa8c19064bf407e
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:18 2013 +1000

    Xi: use public.processInputProc to replay the touch history
    
    If a device is frozen in results to a grab, we need to enqueue the events.
    
    This makes things complicated, and hard to follow since touch events are now
    replayed in the history, pushed into EnqueueEvent, then replayed later
    during PlayReleasedEvents in response to an XAllowEvents.
    
    While the device is frozen, no touch events are processed, so if there is a
    touch client with ownership mask _below_ the grab this will delay the
    delivery and potentially screw gesture recognition. However, this is the
    behaviour we have already anyway if the top-most client is a sync pgrab or
    there is a sync grab active on the device when the TouchBegin was generated.
    
    (also note, such a client would only reliably work in case of ReplayPointer
    anyway)
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a7cd64a..76c456b 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1550,7 +1550,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
     else
         touchid = ev->device_event.touchid;
 
-    if (type == ET_TouchBegin) {
+    if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
         ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
                              emulate_pointer);
     }
@@ -1617,7 +1617,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
      * called after event type mutation. Touch end events are always processed
      * in order to end touch records. */
     /* FIXME: check this */
-    if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+    if ((type == ET_TouchBegin &&
+         !(ev->device_event.flags & TOUCH_REPLAYING) &&
+         !TouchBuildSprite(dev, ti, ev)) ||
         (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
         return;
 
@@ -1630,7 +1632,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
         /* WARNING: the event type may change to TouchUpdate in
          * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
          * owner */
-        DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
+        DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
         if (ev->any.type == ET_TouchEnd)
             TouchEndTouch(dev, ti);
     }
diff --git a/dix/touch.c b/dix/touch.c
index 2a2a733..b5b7c1e 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -474,7 +474,21 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
         DeviceEvent *ev = &ti->history[i];
 
         ev->flags |= TOUCH_REPLAYING;
-        DeliverTouchEvents(dev, ti, (InternalEvent *) ev, resource);
+        ev->resource = resource;
+        /* FIXME:
+           We're replaying ti->history which contains the TouchBegin +
+           all TouchUpdates for ti. This needs to be passed on to the next
+           listener. If that is a touch listener, everything is dandy.
+           If the TouchBegin however triggers a sync passive grab, the
+           TouchUpdate events must be sent to EnqueueEvent so the events end
+           up in syncEvents.pending to be forwarded correctly in a
+           subsequent ComputeFreeze().
+
+           However, if we just send them to EnqueueEvent the sync'ing device
+           prevents handling of touch events for ownership listeners who
+           want the events right here, right now.
+         */
+        dev->public.processInputProc((InternalEvent*)ev, dev);
     }
 }
 
diff --git a/include/eventstr.h b/include/eventstr.h
index 38fab4f..648ff8a 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -123,6 +123,7 @@ struct _DeviceEvent {
     int corestate;    /**< Core key/button state BEFORE the event */
     int key_repeat;   /**< Internally-generated key repeat event */
     uint32_t flags;   /**< Flags to be copied into the generated event */
+    uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */
 };
 
 /**

commit 406f4a9d8794737ce49567027b9050482ebd451d
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:17 2013 +1000

    Xi: when punting to a new owner, always create TouchEnd events
    
    If a touch is pending_finish and we just punted it to the next owner, that
    client must receive a TouchEnd event.
    
    If we just punted to the last owner and that owner not a touch grab, we need
    to end the touch since this is the last event to be sent, and the client
    cannot accept/reject this.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index dd5452f..a7cd64a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1143,12 +1143,21 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         TouchEventHistoryReplay(ti, dev, listener->listener);
     }
 
-    /* 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) {
+    /* New owner has Begin/Update but not end. If touch is pending_finish,
+     * emulate the TouchEnd now */
+    if (ti->pending_finish) {
         EmitTouchEnd(dev, ti, 0, 0);
-        TouchEndTouch(dev, ti);
-        return;
+
+        /* If the last owner is not a touch grab, finalise the touch, we
+           won't get more correspondence on this.
+         */
+        if (ti->num_listeners == 1 &&
+            (ti->num_grabs == 0 ||
+             listener->grab->grabtype != XI2 ||
+             !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
+            TouchEndTouch(dev, ti);
+            return;
+        }
     }
 
     if (accepted_early)

commit be0b85b833abee026071c390bd17d812ea9da268
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:16 2013 +1000

    Xi: save state for early acceptance
    
    Delivering an event changes the state to LISTENER_IS_OWNER and we thus lose
    the information of early acceptance.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 654fa06..dd5452f 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1126,10 +1126,10 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
                      TouchOwnershipEvent *ev)
 {
     TouchListener *listener = &ti->listeners[0]; /* new owner */
+    int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
 
     /* Deliver the ownership */
-    if (listener->state == LISTENER_AWAITING_OWNER ||
-        listener->state == LISTENER_EARLY_ACCEPT)
+    if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
         DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
                            listener->listener);
     else if (listener->state == LISTENER_AWAITING_BEGIN) {
@@ -1151,7 +1151,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         return;
     }
 
-    if (listener->state == LISTENER_EARLY_ACCEPT)
+    if (accepted_early)
         ActivateEarlyAccept(dev, ti);
 }
 

commit a0a7c3eb103f3e90fd605af871576d842b682f0c
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:15 2013 +1000

    Xi: if a passive async grab is activated from an emulated touch, accept
    
    Async grabs cannot replay events, they cannot reject, so we can do an early
    accept here.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 52067cf..654fa06 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1846,8 +1846,14 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
         listener->type == LISTENER_POINTER_GRAB) {
         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                        grab, xi2mask);
-        if (rc == Success)
+        if (rc == Success) {
             listener->state = LISTENER_IS_OWNER;
+            /* async grabs cannot replay, so automatically accept this touch */
+            if (dev->deviceGrab.grab &&
+                dev->deviceGrab.fromPassiveGrab &&
+                dev->deviceGrab.grab->pointerMode == GrabModeAsync)
+                ActivateEarlyAccept(dev, ti);
+        }
         goto out;
     }
 

commit 2b953b86a3de490706acd43baf7aabb7f95b9246
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:14 2013 +1000

    Xi: fix lookup in ActivateEarlyAccept
    
    ActivateEarlyAccept() can only be called from a grabbing client, so we can
    ignore the rest. And it's easy enough to get the client from that since
    9ad0fdb135a1c336771aee1f6eab75a6ad874aff.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index df80bab..52067cf 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1039,17 +1039,16 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
     int rc;
     ClientPtr client;
     XID error;
+    GrabPtr grab = ti->listeners[0].grab;
 
-    rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
-                         DixSendAccess);
-    if (rc != Success) {
-        ErrorF("[Xi] Failed to lookup early accepting client.\n");
-        return;
-    }
+    BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
+               ti->listeners[0].type != LISTENER_POINTER_GRAB);
+    BUG_RETURN(!grab);
+
+    client = rClient(grab);
 
     if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
-                          ti->listeners[0].window->drawable.id, &error) !=
-        Success)
+                          ti->listeners[0].window->drawable.id, &error) != Success)
         ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
 }
 

commit faf1f0c6f5b41e8ac4e44440e425a4fec87b2591
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:13 2013 +1000

    Xi: update the core listener state if we delivered the touch event
    
    If a TouchBegin is sent to a core client, that client is now the owner.
    
    By the time the TouchEnd is being processed, the client cannot replay
    anymore, so we can assume that this is the final touch end and we can clean
    up the touch record.
    
    Note: DeliverTouchEmulatedEvent is called for all listeners and immediately
    bails out if the client is not the owner and thus shouldn't yet get the
    event. Thus, check the return code.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 690a24e..df80bab 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1847,6 +1847,8 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
         listener->type == LISTENER_POINTER_GRAB) {
         rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
                                        grab, xi2mask);
+        if (rc == Success)
+            listener->state = LISTENER_IS_OWNER;
         goto out;
     }
 
@@ -1887,13 +1889,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         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;
-            if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
-                ti->pending_finish = TRUE;
-        }
-
+         /* Once we send a TouchEnd to a legacy listener, we're already well
+          * past the accepting/rejecting stage (can only happen on
+          * GrabModeSync + replay. This listener now gets the end event,
+          * and we can continue.
+          */
+        if (rc == Success)
+            listener->state = LISTENER_HAS_END;
         goto out;
     }
 

commit 002d9675388fff1770e09fac588ea414f421e9ce
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:12 2013 +1000

    Xi: if we delivered a TouchEnd to a passive grab, end it
    
    ef64b5ee97099618cf2e2cbbd3e471095695ae24 (which introduced the
    TOUCH_CLIENT_ID check) has a wrong assumption that generated touch events
    (TOUCH_CLIENT_ID) should not terminate passive grabs.
    This is untrue, a TouchEnd may be generated in response to a TouchReject
    higher up. If we _deliver_ an event to a client, terminate the passive grab.
    
    This requires us to count the actually delivered events too (first hunk).
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index a2a1d44..690a24e 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1410,7 +1410,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             }
 
             if (!deliveries)
-                DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
+                deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
 
             /* We must accept the touch sequence once a pointer listener has
              * received one event past ButtonPress. */
@@ -1418,8 +1418,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 !(ev->device_event.flags & TOUCH_CLIENT_ID))
                 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
 
-            if (ev->any.type == ET_TouchEnd &&
-                !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
+            if (deliveries && ev->any.type == ET_TouchEnd &&
                 !dev->button->buttonsDown &&
                 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
                 (*dev->deviceGrab.DeactivateGrab) (dev);

commit 2e588a08afcb4daebf2382e76e37c46ca2f776da
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21: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@who-t.net>

diff --git a/dix/touch.c b/dix/touch.c
index 891cc78..2a2a733 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 0280cebd06e2e42bcce586af0495a9093113bdbb
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Mar 5 16:21:10 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@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6779139..a2a1d44 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1865,7 +1865,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 456e6ce3a4b26c1334637af1ebeb0338c4470a89
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:45 2013 +1000

    Xi: add a comment to make a condition a bit clearer
    
    The commit message to 676447190190d8546165e21be242cf16dd69f5ae explains it,
    but that doesn't stop the WTF moment when reading the code.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 05685a2..6779139 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1898,6 +1898,7 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         goto out;
     }
 
+    /* A client is waiting for the begin, don't give it a TouchEnd */
     if (listener->state == LISTENER_AWAITING_BEGIN) {
         listener->state = LISTENER_HAS_END;
         goto out;

commit d23cf2bcd2b4692e43a8ed99efb85eb7373a0343
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:44 2013 +1000

    dix: update coords for touch events in PlayReleasedEvents
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/dix/events.c b/dix/events.c
index 2682ecd..0512052 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1200,6 +1200,9 @@ PlayReleasedEvents(void)
                 case ET_KeyRelease:
                 case ET_ProximityIn:
                 case ET_ProximityOut:
+                case ET_TouchBegin:
+                case ET_TouchUpdate:
+                case ET_TouchEnd:
                     ev->root_x += screenInfo.screens[0]->x -
                         pDev->spriteInfo->sprite->screen->x;
                     ev->root_y += screenInfo.screens[0]->y -

commit 4519d17c5db6004b62b420170b8e766ded646a75
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:43 2013 +1000

    Xi: compress two if statements with the same body
    
    We do the same thing here, compress them into one body.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6fcca9a..05685a2 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1904,7 +1904,9 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
     }
 
     /* Event in response to reject */
-    if (ev->device_event.flags & TOUCH_REJECT) {
+    if (ev->device_event.flags & TOUCH_REJECT ||
+        (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
+        /* Touch has been rejected, or accepted by its owner which is not this listener */
         if (listener->state != LISTENER_HAS_END)
             rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
         listener->state = LISTENER_HAS_END;
@@ -1927,12 +1929,6 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
         if (normal_end)
             listener->state = LISTENER_HAS_END;
     }
-    else if (ev->device_event.flags & TOUCH_ACCEPT) {
-        /* Touch has been accepted by its owner, which is not this listener */
-        if (listener->state != LISTENER_HAS_END)
-            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
-        listener->state = LISTENER_HAS_END;
-    }
 
  out:
     return rc;

commit 3a94aca0b0bb949f482a81beb660c049fc519940
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:42 2013 +1000

    dix: fix a comment
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/dix/touch.c b/dix/touch.c
index 0db842c..891cc78 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -902,7 +902,8 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev)
 }
 
 /**
- * Remove the touch pointer grab from the device. Called from AllowSome()
+ * Remove the touch pointer grab from the device. Called from
+ * DeactivatePointerGrab()
  */
 void
 TouchRemovePointerGrab(DeviceIntPtr dev)

commit f93074e71ab09fa3812b2d018267bf1dea9db56c
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:41 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@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;

commit 9e9f3784ff60f2124b934e4381e621cda97308d4
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:40 2013 +1000

    Xi: use a temp variable for the new listener
    
    Instead of accessing ti->listener[0] all the time.
    
    No functional changes.
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index f2268dd..6fcca9a 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1126,20 +1126,22 @@ static void
 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
                      TouchOwnershipEvent *ev)
 {
+    TouchListener *listener = &ti->listeners[0]; /* new owner */
+
     /* Deliver the ownership */
-    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
-        ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
+    if (listener->state == LISTENER_AWAITING_OWNER ||
+        listener->state == LISTENER_EARLY_ACCEPT)
         DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
-                           ti->listeners[0].listener);
-    else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
+                           listener->listener);
+    else if (listener->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) &&
+        if ((listener->type == LISTENER_POINTER_GRAB ||
+             listener->type == LISTENER_POINTER_REGULAR) &&
             ti != FindOldestPointerEmulatedTouch(dev))
             return;
 
-        TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
+        TouchEventHistoryReplay(ti, dev, listener->listener);
     }
 
     /* If we've just removed the last grab and the touch has physically
@@ -1150,7 +1152,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
         return;
     }
 
-    if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
+    if (listener->state == LISTENER_EARLY_ACCEPT)
         ActivateEarlyAccept(dev, ti);
 }
 

commit a64db97b444671c92d1d052023dbbc221bc9be2c
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon Mar 4 07:58:39 2013 +1000

    Xi: return !Success from DeliverTouchEmulatedEvent if we didn't deliver
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 609b126..f2268dd 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1376,7 +1376,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
     /* We don't deliver pointer events to non-owners */
     if (!TouchResourceIsOwner(ti, listener->listener))
-        return Success;
+        return !Success;
 
     nevents = TouchConvertToPointerEvent(ev, &motion, &button);
     BUG_RETURN_VAL(nevents == 0, BadValue);
@@ -1398,7 +1398,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
             /* 'grab' is the passive grab, but if the grab isn't active,
              * don't deliver */
             if (!dev->deviceGrab.grab)
-                return Success;
+                return !Success;
 
             if (grab->ownerEvents) {
                 WindowPtr focus = NullWindow;


Reply to: