Imported Debian patch 2:1.11.4-0ubuntu6
authorChristopher James Halse Rogers <raof@ubuntu.com>
Fri, 9 Mar 2012 08:16:02 +0000 (19:16 +1100)
committerXavier Boudet <x-boudet@ti.com>
Thu, 15 Mar 2012 11:10:47 +0000 (11:10 +0000)
30 files changed:
ChangeLog
Xi/exevents.c
Xi/xiallowev.c
configure.ac
debian/changelog
debian/patches/500_pointer_barrier_thresholds.diff
debian/patches/501_touch_accept_end.patch [new file with mode: 0644]
debian/patches/502_indirect_touch_window_set.patch [new file with mode: 0644]
debian/patches/600-Revert-dix-deduplicate-callers-of-DeliverDeviceEvent.patch [deleted file]
debian/patches/601-Store-window-pointer-in-touch-listener-record.patch [deleted file]
debian/patches/602-Factor-out-TouchEnd-generation-and-delivery.patch [deleted file]
debian/patches/603-Export-TouchEventRejected-as-TouchRejected.patch [deleted file]
debian/patches/604-Move-AllowTouch-to-dix-touch.c-and-rename-to-TouchAc.patch [deleted file]
debian/patches/605-Check-for-proper-window-ID-when-processing-touch-all.patch [deleted file]
debian/patches/606-Implement-early-touch-reject.patch [deleted file]
debian/patches/607-Implement-touch-early-accept.patch [deleted file]
debian/patches/608-dix-fix-an-out-of-memory-crash.patch [deleted file]
debian/patches/609-Xi-handle-new-XIAllowEvents-request-in-inputproto-2..patch [deleted file]
debian/patches/610-Fix-scrolling.patch [deleted file]
debian/patches/611-Fix-touch-punt-crash.patch [deleted file]
debian/patches/612-Fix-vcp-touches-corruption.patch [deleted file]
debian/patches/613-Keep-vcp-touch-class.patch [deleted file]
debian/patches/series
dix/events.c
dix/getevents.c
dix/inpututils.c
dix/touch.c
include/exevents.h
include/input.h
include/inputstr.h

index a3980c30e9376e5a68352a49f08b3495a65cd569..2415e4ff082654c4e0e9eaf7a79901c257273e89 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,235 @@
+commit 0e7b1080415c85f55462ad863de36df7011bf869
+Author: Gaetan Nadon <memsize@videotron.ca>
+Date:   Sun Feb 26 17:51:50 2012 -0500
+
+    test: add new test cases to .gitignore
+    
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Signed-off-by: Gaetan Nadon <memsize@videotron.ca>
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+    (cherry picked from commit e08ed0b757b9b48344a301f612fabb3e39ffec78)
+    
+    Conflicts:
+    
+       test/.gitignore
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit ab03aafffdbad2966dc01334ecd5d328512acf90
+Author: Peter Hutterer <peter.hutterer@who-t.net>
+Date:   Wed Feb 22 15:32:56 2012 +1000
+
+    dix: avoid NULL-pointer dereference on button-only devices (#38313)
+    
+    And for such devices simply take the last.valuators[] which must be valid at
+    all times anyway. UpdateSlaveDeviceCoords takes care of that.
+    
+    X.Org Bug 38313 <http://bugs.freedesktop.org/show_bug.cgi?id=38313>
+    
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
+    (cherry picked from commit 2416ee4a015068359807a10f433e8c54192c78a9)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit b533a9bc374ddd863e29eafd9b30018a494b63aa
+Author: Jeremy Huddleston <jeremyhu@apple.com>
+Date:   Tue Jan 31 11:06:21 2012 -0800
+
+    Revert "dix: don't XWarpPointer through the last slave anymore (#38313)"
+    
+    This reverts commit 2bfb802839688ecf328119c4c6979390fc60348d.
+    
+    This commit caused a regression.
+    
+    See: http://xquartz.macosforge.org/trac/ticket/517#comment:10
+    
+    Acked-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 38000e7d1f958f5944e641de3e716944a5876d41)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit ac98fb5a83b458ebecf1a2dfd2d35c9a9c8b1643
+Author: Keith Packard <keithp@keithp.com>
+Date:   Wed Feb 22 18:07:20 2012 +1300
+
+    Merge remote-tracking branch 'whot/for-keith'
+    (cherry picked from commit 71594746c7da32e1c7986341a0da30f241a7a2be)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 453020e435db12eca2a3f21c1944a6e855c2349d
+Author: Peter Hutterer <peter.hutterer@who-t.net>
+Date:   Fri Jan 27 12:41:09 2012 +1000
+
+    Xi: handle new XIAllowEvents request in inputproto 2.1.99.6
+    
+    grab_window and touchid were removed from the struct for ABI compatibility
+    reasons, we need to pull in the new, XI 2.2-specific struct.
+    
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Keith Packard <keithp@keithp.com>
+    Signed-off-by: Keith Packard <keithp@keithp.com>
+    (cherry picked from commit 7674d00b04da5cf73cfa5c7ed1d3a9f42b59960e)
+    
+    Conflicts:
+    
+       Xi/xiallowev.c
+       configure.ac
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 4d7d1bd15a6a63f82f6075b2efe1e4596c41d322
+Author: Benjamin Otte <otte@redhat.com>
+Date:   Tue Feb 7 18:01:25 2012 +1000
+
+    dix: fix an out-of-memory crash
+    
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit b96275c4cdb164aa71f7aa9fbf88be18886d1936)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit a569ffd93767f6b496eb9f0f3f87f1bf1d03fa3f
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:11 2012 -0800
+
+    Implement touch early accept
+    
+    This doesn't really implement early accept as it should. Ideally, the
+    server should send end events to all subsequent touch clients as soon as
+    an early accept comes in. However, this implementation is still protocol
+    compliant. We can always improve it later.
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 6241b5e4fdbdb08d30cc8787d858ac27122d2d49)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit d6f746e7177fa050e61f6d24e62fe060af829cca
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:10 2012 -0800
+
+    Implement early touch reject
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit b0c54856df71f9cabf9dad176fdade960ef8c5d9)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 50f22a606cd101ece109c46173ba6edcead9e94e
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:09 2012 -0800
+
+    Check for proper window ID when processing touch allow requests
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 656ab879f20892975510723ce8fe78faf64aadb4)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 5eb65eaf9c914322faa413746d9546ff70a1724f
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:08 2012 -0800
+
+    Move AllowTouch to dix/touch.c, and rename to TouchAcceptReject
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 9a260e9af83feb5c53ffd3b2da2dc3adf06240a1)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit f8c27e7765dbb0f08c160ed2f0b3ffedd0610906
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:07 2012 -0800
+
+    Export TouchEventRejected as TouchRejected
+    
+    This function is mostly correct for early reject usage. With a small
+    change to pass the client resource explicitly and making the
+    TouchOwnership event optional, it is usable for all rejection scenarios.
+    This change exports it for use outside Xi/exevents.c and modifies the
+    name accordingly.
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 192b2c9a2ec04522655675ddfe71de5cf974cc7b)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit e6459ad03851a4d667186c863a4cb1d5b6a5471a
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:06 2012 -0800
+
+    Factor out TouchEnd generation and delivery
+    
+    The server often needs to generate and deliver TouchEnd events for
+    circumstances including touch grab acceptance and rejection. This change
+    refactors the code so it can be used more easily.
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit 19073425e5df1317f73f74ce0b95ab24e0e0da14)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 52d4b2fded097475fbe454d1433caa3f8b1b83dd
+Author: Chase Douglas <chase.douglas@canonical.com>
+Date:   Fri Feb 3 16:19:05 2012 -0800
+
+    Store window pointer in touch listener record
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+    (cherry picked from commit ab60cadc2afb9d8882144e30fde11c3ef0f999cd)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 5893d32d1114628fb09fc0caf9569e74966afe4f
+Author: Peter Hutterer <peter.hutterer@who-t.net>
+Date:   Sat Feb 4 19:27:21 2012 +1000
+
+    Revert "dix: deduplicate callers of DeliverDeviceEvents in DeliverGrabbedEvents"
+    
+    This call was supposed to have no functional changes but in some cases
+    DeliverDeviceEvents() was called with a uninitialised win variable.
+    Revert, safer than trying to sort this out otherwise.
+    
+    This reverts commit 6eff14a789341d366b3013c5aa020e959c954651.
+    
+    Reported-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
+    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
+    Reviewed-by: Keith Packard <keithp@keithp.com>
+    (cherry picked from commit f92ba92adfce0e1975feb54ab0e1165b7c2a7bea)
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
+commit 428aaf7252b2e341427a0cf36c22e0fea3ddcbe4
+Author: Keith Packard <keithp@keithp.com>
+Date:   Mon Jan 9 13:17:37 2012 -0800
+
+    Merge remote-tracking branch 'whot/multitouch'
+    
+    (cherry picked from commit e476af417d83730b11054f4e5b127ab5540bb332)
+    
+    Conflicts:
+    
+       configure.ac
+    
+    Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+
 commit 03e15dc10aa7cec2d1db294beb0c006ea0e24e25
 Author: Chase Douglas <chase.douglas@canonical.com>
 Date:   Wed Jan 18 19:09:21 2012 -0800
index 6b2db4b5988060da60ffb61706edabe3576732db..f390f67393b2965d6a5ae3da44ebefff245534dc 100644 (file)
@@ -671,7 +671,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
 
     if (from->touch)
     {
-        TouchPointInfoPtr tmp;
+        TouchClassPtr t, f;
         if (!to->touch)
         {
             classes = to->unused_classes;
@@ -692,17 +692,22 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
             } else
                 classes->touch = NULL;
         }
-        tmp = to->touch->touches;
-        memcpy(to->touch, from->touch, sizeof(TouchClassRec));
-        to->touch->touches = tmp;
-        to->touch->sourceid = from->id;
-    } else if (to->touch)
-    {
-        ClassesPtr classes;
-        classes = to->unused_classes;
-        classes->touch = to->touch;
-        to->touch      = NULL;
+
+
+        t = to->touch;
+        f = from->touch;
+        t->sourceid = f->sourceid;
+        t->max_touches = f->max_touches;
+        t->mode = f->mode;
+        t->buttonsDown = f->buttonsDown;
+        t->state = f->state;
+        t->motionMask = f->motionMask;
+        /* to->touches and to->num_touches are separate on the master,
+         * don't copy */
     }
+    /* Don't remove touch class if from->touch is non-existent. The to device
+     * may have an active touch grab, so we need to keep the touch class record
+     * around. */
 }
 
 /**
@@ -1088,20 +1093,71 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
     return TRUE;
 }
 
+static void
+ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
+{
+    int rc;
+    ClientPtr client;
+    XID error;
+
+    rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
+                         DixSendAccess);
+    if (rc != Success)
+    {
+        ErrorF("[Xi] Failed to lookup early accepting client.\n");
+        return;
+    }
+
+    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
+                          ti->listeners[0].window->drawable.id, &error) !=
+        Success)
+        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
+}
+
 /**
- * If the current owner has rejected the event, deliver the
- * TouchOwnership/TouchBegin to the next item in the sprite stack.
+ * 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
-TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-                     TouchOwnershipEvent *ev)
+EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
 {
     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
     ValuatorMask *mask = valuator_mask_new(2);
     int i, nev;
 
+    valuator_mask_set_double(mask, 0,
+                             valuator_mask_get_double(ti->valuators, 0));
+    valuator_mask_set_double(mask, 1,
+                             valuator_mask_get_double(ti->valuators, 1));
+
+    flags |= TOUCH_CLIENT_ID;
+    if (ti->emulate_pointer)
+        flags |= TOUCH_POINTER_EMULATED;
+    nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
+    for (i = 0; i < nev; i++)
+        DeliverTouchEvents(dev, ti, tel + i, resource);
+
+    valuator_mask_free(&mask);
+    FreeEventList(tel, GetMaximumEventsNum());
+}
+
+/**
+ * If the current owner has rejected the event, deliver the
+ * TouchOwnership/TouchBegin to the next item in the sprite stack.
+ */
+static void
+TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
+                     TouchOwnershipEvent *ev)
+{
     /* Deliver the ownership */
-    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
+    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
+        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)
         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
@@ -1111,52 +1167,42 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
     if (ti->num_listeners == 1 && ti->num_grabs == 0 &&
             ti->pending_finish)
     {
-        int flags;
-        valuator_mask_set_double(mask, 0,
-                                 valuator_mask_get_double(ti->valuators, 0));
-        valuator_mask_set_double(mask, 1,
-                                 valuator_mask_get_double(ti->valuators, 1));
-
-        flags = TOUCH_CLIENT_ID;
-        if (ti->emulate_pointer)
-            flags |= TOUCH_POINTER_EMULATED;
-        nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
-        for (i = 0; i < nev; i++)
-            DeliverTouchEvents(dev, ti, tel + i, 0);
+        EmitTouchEnd(dev, ti, 0, 0);
         TouchEndTouch(dev, ti);
+        return;
     }
 
-    valuator_mask_free(&mask);
-    FreeEventList(tel, GetMaximumEventsNum());
+    if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
+        ActivateEarlyAccept(dev, ti);
 }
 
-static void
-TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                   TouchOwnershipEvent *ev)
+/**
+ * Process a touch rejection.
+ *
+ * @param sourcedev The source device of the touch sequence.
+ * @param ti The touchpoint info record.
+ * @param resource The resource of the client rejecting the touch.
+ * @param ev TouchOwnership event to send. Set to NULL if no event should be
+ *        sent.
+ */
+void
+TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
+              TouchOwnershipEvent *ev)
 {
-    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
-    ValuatorMask *mask = valuator_mask_new(2);
-    Bool was_owner = (ev->resource == ti->listeners[0].listener);
+    Bool was_owner = (resource == ti->listeners[0].listener);
     void *grab;
-    int nev, i;
-
+    int i;
 
     /* Send a TouchEnd event to the resource being removed, but only if they
      * haven't received one yet already */
-    if (ti->listeners[0].state != LISTENER_HAS_END)
+    for (i = 0; i < ti->num_listeners; i++)
     {
-        int flags;
-        valuator_mask_set_double(mask, 0,
-                                 valuator_mask_get_double(ti->valuators, 0));
-        valuator_mask_set_double(mask, 1,
-                                 valuator_mask_get_double(ti->valuators, 1));
-
-        flags = TOUCH_CLIENT_ID|TOUCH_REJECT;
-        if (ti->emulate_pointer)
-            flags |= TOUCH_POINTER_EMULATED;
-        nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask);
-        for (i = 0; i < nev; i++)
-            DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource);
+        if (ti->listeners[i].listener == resource)
+        {
+            if (ti->listeners[i].state != LISTENER_HAS_END)
+                EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
+            break;
+        }
     }
 
     /* If there are no other listeners left, and the touchpoint is pending
@@ -1164,26 +1210,22 @@ TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
     if (ti->num_listeners == 1 && ti->pending_finish)
     {
         TouchEndTouch(sourcedev, ti);
-        goto out;
+        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, ev->resource))
+    if (TouchRemoveListener(ti, resource))
     {
-        if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB,
+        if (dixLookupResourceByType(&grab, resource, RT_PASSIVEGRAB,
                                     serverClient, DixGetAttrAccess) == Success)
             ti->num_grabs--;
     }
 
     /* If the current owner was removed and there are further listeners, deliver
      * the TouchOwnership or TouchBegin event to the new owner. */
-    if (ti->num_listeners > 0 && was_owner)
+    if (ev && ti->num_listeners > 0 && was_owner)
         TouchPuntToNextOwner(sourcedev, ti, ev);
-
-out:
-    FreeEventList(tel, GetMaximumEventsNum());
-    valuator_mask_free(&mask);
 }
 
 /**
@@ -1199,35 +1241,11 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
 {
 
     if (ev->reason == XIRejectTouch)
-        TouchEventRejected(dev, ti, ev);
+        TouchRejected(dev, ti, ev->resource, ev);
     else if (ev->reason == XIAcceptTouch) {
-        int flags;
-        int nev, i;
-        ValuatorMask *mask;
-
-        InternalEvent *tel = InitEventList(GetMaximumEventsNum());
-
-        mask = valuator_mask_new(dev->valuator->numAxes);
-        valuator_mask_set_double(mask, 0,
-                                 valuator_mask_get_double(ti->valuators, 0));
-        valuator_mask_set_double(mask, 1,
-                                 valuator_mask_get_double(ti->valuators, 1));
-
-        /* FIXME: what about early acceptance? a client may accept before it
-         * owns the touch. */
-
         /* The touch owner has accepted the touch.  Send TouchEnd events to
          * everyone else, and truncate the list of listeners. */
-        flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID;
-        if (ti->emulate_pointer)
-            flags |= TOUCH_POINTER_EMULATED;
-        nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd,
-                             flags, mask);
-        for (i = 0; i < nev; i++)
-            DeliverTouchEvents(dev, ti, tel + i, 0);
-
-        FreeEventList(tel, GetMaximumEventsNum());
-        valuator_mask_free(&mask);
+        EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
 
         while (ti->num_listeners > 1)
             TouchRemoveListener(ti, ti->listeners[1].listener);
@@ -2203,7 +2221,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
 
     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
         if (BitIsOn(mouse->button->down, i))
-            SetBit(&xi2event[1], i);
+            SetBit(&xi2event[1], mouse->button->map[i]);
 
     if (dev->key)
     {
index 207c5cb07a8c1178f1668801bb11038837a8888a..6b9c795f42654899df4f79d1966901ab9a455b3e 100644 (file)
@@ -41,6 +41,7 @@
 #include <X11/extensions/XI2proto.h>
 
 #include "exglobals.h" /* BadDevice */
+#include "exevents.h"
 #include "xiallowev.h"
 
 int
@@ -53,51 +54,14 @@ SProcXIAllowEvents(ClientPtr client)
     swaps(&stuff->length, n);
     swaps(&stuff->deviceid, n);
     swapl(&stuff->time, n);
-    /* FIXME swap touchid */
-    /* FIXME swap window */
-
-    return ProcXIAllowEvents(client);
-}
-
-static int
-AllowTouch(ClientPtr client, DeviceIntPtr dev, int mode, uint32_t touchid, XID *error)
-{
-    TouchPointInfoPtr ti;
-    int nev, i;
-    InternalEvent *events = InitEventList(GetMaximumEventsNum());
-
-    if (!events)
-        return BadAlloc;
-
-    if (!dev->touch)
-    {
-        *error = dev->id;
-        return BadDevice;
-    }
-
-    /* FIXME window is unhandled */
-
-    ti = TouchFindByClientID(dev, touchid);
-    if (!ti)
+    if (stuff->length > 3)
     {
-        *error = touchid;
-        return BadValue;
+        xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq*)stuff;
+        swapl(&req_xi22->touchid, n);
+        swapl(&req_xi22->grab_window, n);
     }
 
-    /* FIXME: Allow for early accept */
-    if (ti->num_listeners == 0 || CLIENT_ID(ti->listeners[0].listener) != client->index)
-        return BadAccess;
-
-    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 ProcXIAllowEvents(client);
 }
 
 int
@@ -106,9 +70,21 @@ ProcXIAllowEvents(ClientPtr client)
     TimeStamp time;
     DeviceIntPtr dev;
     int ret = Success;
+    XIClientPtr xi_client;
+    Bool have_xi22 = FALSE;
+    REQUEST(xXI2_2AllowEventsReq);
 
-    REQUEST(xXIAllowEventsReq);
-    /* FIXME: check request length, 12 for XI 2.0+, 20 for XI 2.2+ */
+    xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
+    if (version_compare(xi_client->major_version,
+                        xi_client->minor_version, 2, 2) >= 0)
+    {
+        REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq);
+        have_xi22 = TRUE;
+    } else
+    {
+        REQUEST_SIZE_MATCH(xXIAllowEventsReq);
+    }
 
     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
     if (ret != Success)
@@ -140,9 +116,20 @@ ProcXIAllowEvents(ClientPtr client)
        break;
     case XIRejectTouch:
     case XIAcceptTouch:
-        ret = AllowTouch(client, dev,
-                         stuff->mode, stuff->touchid,
-                         &client->errorValue);
+        {
+            int rc;
+            WindowPtr win;
+
+            if (!have_xi22)
+                return BadValue;
+
+            rc = dixLookupWindow(&win, stuff->grab_window, client, DixReadAccess);
+            if (rc != Success)
+                return rc;
+
+            ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
+                                    stuff->grab_window, &client->errorValue);
+        }
         break;
     default:
        client->errorValue = stuff->mode;
index 6c83be9829c5127d8ea550bf732f7c8ad8e6154b..5e29b2a4715685263a98cb1738e2ba6ba0dbae35 100644 (file)
@@ -785,7 +785,7 @@ WINDOWSWMPROTO="windowswmproto"
 APPLEWMPROTO="applewmproto >= 1.4"
 
 dnl Core modules for most extensions, et al.
-SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 2.1.99.5] [kbproto >= 1.0.3] fontsproto"
+SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 2.1.99.6] [kbproto >= 1.0.3] fontsproto"
 # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
 AC_SUBST(SDK_REQUIRED_MODULES)
 
index 1fbc21eb1def242fa3b7e06a54dfa66422290c1c..3756386efe4558065d5d36f33a7cfe738b5b2c93 100644 (file)
@@ -1,3 +1,38 @@
+xorg-server (2:1.11.4-0ubuntu6) precise; urgency=low
+
+  * debian/patches/500_pointer_barrier_thresholds.diff:
+    - Don't try to send events from the context of the SIGIO handler.  That
+      leads to the dark side, or at least to server freezes when trying to
+      reveal the launcher in Unity (LP: #946954).  May also fix other seemingly
+      random X server crashes.
+    - Add build-time tests to make check for barrier behaviour.  These are
+      disabled, pending gtest, xorg-gtest, and xserver-xorg-video-dummy MIRs.
+
+ -- Christopher James Halse Rogers <raof@ubuntu.com>  Fri, 09 Mar 2012 19:16:02 +1100
+
+xorg-server (2:1.11.4-0ubuntu5) precise; urgency=low
+  * Update to 1.12 input stack 
+  * Drop input patches that have been merged upstream:
+    - 600-Revert-dix-deduplicate-callers-of-DeliverDeviceEvent.patch
+    - 601-Store-window-pointer-in-touch-listener-record.patch
+    - 602-Factor-out-TouchEnd-generation-and-delivery.patch
+    - 603-Export-TouchEventRejected-as-TouchRejected.patch
+    - 604-Move-AllowTouch-to-dix-touch.c-and-rename-to-TouchAc.patch
+    - 605-Check-for-proper-window-ID-when-processing-touch-all.patch
+    - 606-Implement-early-touch-reject.patch
+    - 607-Implement-touch-early-accept.patch
+    - 608-dix-fix-an-out-of-memory-crash.patch
+    - 609-Xi-handle-new-XIAllowEvents-request-in-inputproto-2..patch
+    - 610-Fix-scrolling.patch
+    - 611-Fix-touch-punt-crash.patch
+    - 612-Fix-vcp-touches-corruption.patch
+    - 613-Keep-vcp-touch-class.patch
+  * Fix indirect touch grab handling (LP: #929408)
+    - Add temporary patch 501_touch_accept_end.patch
+    - Add temporary patch 502_indirect_touch_window_set.patch
+
+ -- Chase Douglas <chase.douglas@ubuntu.com>  Wed, 07 Mar 2012 15:36:20 -0800
+
 xorg-server (2:1.11.4-0ubuntu4) precise; urgency=low
 
   * debian/patches/500_pointer_barrier_thresholds.diff:
index ad8a180499bd66864ff2486d4b9de64ca4fe8672..9e255adb7edd3a5ae40f1d9308be7ad5298a0975 100644 (file)
@@ -1,7 +1,7 @@
 Index: xorg-server/include/protocol-versions.h
 ===================================================================
---- xorg-server.orig/include/protocol-versions.h       2012-02-21 18:14:17.631996352 +1100
-+++ xorg-server/include/protocol-versions.h    2012-02-22 11:39:06.722090873 +1100
+--- xorg-server.orig/include/protocol-versions.h       2012-03-07 22:24:45.540697115 +1100
++++ xorg-server/include/protocol-versions.h    2012-03-08 07:40:35.472111389 +1100
 @@ -122,7 +122,7 @@
  #define SERVER_XF86VIDMODE_MINOR_VERSION      2
  
@@ -13,8 +13,8 @@ Index: xorg-server/include/protocol-versions.h
  /* X Input */
 Index: xorg-server/xfixes/cursor.c
 ===================================================================
---- xorg-server.orig/xfixes/cursor.c   2012-02-21 18:14:17.647996351 +1100
-+++ xorg-server/xfixes/cursor.c        2012-02-22 11:39:06.722090873 +1100
+--- xorg-server.orig/xfixes/cursor.c   2012-03-07 22:24:45.580697117 +1100
++++ xorg-server/xfixes/cursor.c        2012-03-08 11:00:53.155469738 +1100
 @@ -61,6 +61,7 @@
  static RESTYPE                CursorHideCountType;
  static RESTYPE                CursorWindowType;
@@ -43,38 +43,119 @@ Index: xorg-server/xfixes/cursor.c
  } CursorScreenRec, *CursorScreenPtr;
  
  #define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
-@@ -1232,18 +1239,90 @@
+@@ -1118,7 +1125,8 @@
+     /* Algorithm below doesn't handle edge cases well, hence the extra
+      * checks. */
+-    if (barrier_is_vertical(barrier)) {
++    if (barrier_is_vertical(barrier) &&
++      (dir & (BarrierPositiveX | BarrierNegativeX))) {
+       /* handle immediate barrier adjacency, moving away */
+       if (dir & BarrierPositiveX && x1 == barrier->x1)
+           return FALSE;
+@@ -1129,7 +1137,8 @@
+           *distance = 0;
+           return TRUE;
+       }
+-    } else {
++    } else if (barrier_is_horizontal(barrier) &&
++              (dir & (BarrierPositiveY | BarrierNegativeY))){
+       /* handle immediate barrier adjacency, moving away */
+       if (dir & BarrierPositiveY && y1 == barrier->y1)
+           return FALSE;
+@@ -1231,6 +1240,127 @@
+     }
  }
  
- static void
-+SendBarrierEvent(CursorScreenPtr cs, struct PointerBarrier *barrier,
-+               int x, int y, int velocity, Bool threshold_exceeded)
++/*
++ * ConstrainCursorHarder is called from the SIGIO context.
++ * This means we cannot safely send a client event from anything in
++ * CursorConstrainCursorHarder's callgraph.
++ *
++ * Allocate a set of WorkQueue items to use.
++ */
++
++struct BarrierEventStore {
++    WorkQueueRec wq_item;
++    xXFixesBarrierNotifyEvent ev;
++    Bool in_use;
++};
++
++/* Let's guess that 100 events is enough of a buffer. */
++#define BARRIER_EVENT_QUEUE_SIZE 100
++struct BarrierEventStore barrierEventQueue[BARRIER_EVENT_QUEUE_SIZE];
++
++static void
++CursorWorkQueueDestroyProc (WorkQueuePtr this)
++{
++    struct BarrierEventStore *store;
++    store = container_of (this, struct BarrierEventStore, wq_item);
++
++    store->in_use = FALSE;
++}
++
++static Bool
++CursorSendBarrierEvent (ClientPtr client, pointer eventStore)
++{
++    struct BarrierEventStore *store = (struct BarrierEventStore *)eventStore;
++    WriteEventsToClient (client, 1, (xEvent *)&store->ev);
++
++    return TRUE;
++}
++
++static struct BarrierEventStore *
++CursorFindFreeEventStore (void)
++{
++    for (int i = 0; i < BARRIER_EVENT_QUEUE_SIZE; ++i) {
++      if (!barrierEventQueue[i].in_use) {
++          return &barrierEventQueue[i];
++      }
++    }
++    return NULL;
++}
++
++static void
++QueueBarrierEvent(CursorScreenPtr cs, struct PointerBarrier *barrier,
++                int x, int y, int velocity, Bool threshold_exceeded)
 +{
 +    PointerBarrierEventClientPtr client;
++    struct BarrierEventStore *store;
 +    list_for_each_entry(client, &cs->barrierClients, entry) {
-+      xXFixesBarrierNotifyEvent       ev;
-+      ev.type = XFixesEventBase + XFixesBarrierNotify;
-+      ev.subtype = threshold_exceeded ? XFixesBarrierThresholdExceededNotify :
-+                                        XFixesBarrierHitNotify;
-+      ev.event_id = barrier->barrierEventID;
-+      ev.barrier = barrier->barrier;
-+      ev.x = x;
-+      ev.y = y;
-+      ev.velocity = velocity;
-+      ev.timestamp = currentTime.milliseconds;
++      store = CursorFindFreeEventStore ();
++      if (store == NULL) {
++          ErrorF ("[xfixes] Barrier event queue full.  Dropping further events\n");
++          return;
++      }
++
++      store->in_use = TRUE;
++
++      store->ev.type = XFixesEventBase + XFixesBarrierNotify;
++      store->ev.subtype = threshold_exceeded ? XFixesBarrierThresholdExceededNotify :
++                                               XFixesBarrierHitNotify;
++      store->ev.event_id = barrier->barrierEventID;
++      store->ev.barrier = barrier->barrier;
++      store->ev.x = x;
++      store->ev.y = y;
++      store->ev.velocity = velocity;
++      store->ev.timestamp = currentTime.milliseconds;
 +
 +      if (client->client->swapped) {
 +          int n;
 +
-+          swapl(&ev.event_id, n);
-+          swapl(&ev.barrier, n);
-+          swaps(&ev.x, n);
-+          swaps(&ev.y, n);
-+          swapl(&ev.velocity, n);
-+          swapl(&ev.timestamp, n);
++          swapl(&store->ev.event_id, n);
++          swapl(&store->ev.barrier, n);
++          swaps(&store->ev.x, n);
++          swaps(&store->ev.y, n);
++          swapl(&store->ev.velocity, n);
++          swapl(&store->ev.timestamp, n);
 +      }
-+      
-+      WriteEventsToClient (client->client, 1, (xEvent *) &ev);
++
++      store->wq_item.function = CursorSendBarrierEvent;
++      store->wq_item.client = client->client;
++      store->wq_item.closure = store;
++      store->wq_item.destroyProc = CursorWorkQueueDestroyProc;
++
++      QueueWorkItem (&store->wq_item); 
 +    }
 +}
 +
@@ -104,13 +185,13 @@ Index: xorg-server/xfixes/cursor.c
 +    *vel_x = abs(dx) * 1000.0 / dt;
 +    *vel_y = abs(dy) * 1000.0 / dt;
 +
-+    last_timestamp = timestamp;  
++    last_timestamp = timestamp;
 +}
 +
-+static void
+ static void
  CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
  {
-     CursorScreenPtr cs = GetCursorScreen(screen);
+@@ -1238,12 +1368,23 @@
  
      if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
        int ox, oy;
@@ -134,7 +215,7 @@ Index: xorg-server/xfixes/cursor.c
        /* How this works:
         * Given the origin and the movement vector, get the nearest barrier
         * to the origin that is blocking the movement.
-@@ -1251,12 +1330,28 @@
+@@ -1251,11 +1392,27 @@
         * Then, check from the clamped intersection to the original
         * destination, again finding the nearest barrier and clamping.
         */
@@ -147,7 +228,7 @@ Index: xorg-server/xfixes/cursor.c
        if (nearest) {
 -          barrier_clamp_to_barrier(nearest, dir, x, y);
 +          int velocity = barrier_is_vertical(nearest) ? vel_x : vel_y;
-+          Bool threshold_exceeded = (nearest->velocity == 0) ||
++          Bool threshold_exceeded = (nearest->velocity != 0) &&
 +                                    (velocity > nearest->velocity);
 +
 +          if (!nearest->lastHit) {
@@ -160,13 +241,12 @@ Index: xorg-server/xfixes/cursor.c
 +              barrier_clamp_to_barrier(nearest, dir, x, y);
 +              nearest->hit = TRUE;
 +          }
++
++          QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
  
-+          SendBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
-+              
            if (barrier_is_vertical(nearest)) {
                dir &= ~(BarrierNegativeX | BarrierPositiveX);
-               ox = *x;
-@@ -1265,11 +1360,31 @@
+@@ -1265,11 +1422,31 @@
                oy = *y;
            }
  
@@ -175,7 +255,7 @@ Index: xorg-server/xfixes/cursor.c
            if (nearest) {
 -              barrier_clamp_to_barrier(nearest, dir, x, y);
 +              velocity = barrier_is_vertical(nearest) ? vel_x : vel_y;
-+              threshold_exceeded = (nearest->velocity == 0) ||
++              threshold_exceeded = (nearest->velocity != 0) &&
 +                                   (velocity > nearest->velocity);
 +
 +              if (!nearest->lastHit) {
@@ -189,7 +269,7 @@ Index: xorg-server/xfixes/cursor.c
 +                  nearest->hit = TRUE;
 +              }
 +
-+              SendBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
++              QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
            }
        }
 +
@@ -200,16 +280,21 @@ Index: xorg-server/xfixes/cursor.c
      }
  
      if (cs->ConstrainCursorHarder) {
-@@ -1288,11 +1403,41 @@
+@@ -1284,15 +1461,45 @@
+                          xXFixesCreatePointerBarrierReq *stuff)
+ {
+     CursorScreenPtr cs = GetCursorScreen(screen);
+-    struct PointerBarrierClient *ret = malloc(sizeof(*ret));
++    struct PointerBarrierClient *ret = calloc(sizeof(*ret), 1);
  
      if (ret) {
        ret->screen = screen;
 +      ret->barrier.barrier = stuff->barrier;
-+      ret->barrier.x1 = min(stuff->x1, stuff->x2);
-+      ret->barrier.x2 = max(stuff->x1, stuff->x2);
-+      ret->barrier.y1 = min(stuff->y1, stuff->y2);
-+      ret->barrier.y2 = max(stuff->y1, stuff->y2);
-+      ret->barrier.directions = stuff->directions & 0x0f;
+       ret->barrier.x1 = min(stuff->x1, stuff->x2);
+       ret->barrier.x2 = max(stuff->x1, stuff->x2);
+       ret->barrier.y1 = min(stuff->y1, stuff->y2);
+       ret->barrier.y2 = max(stuff->y1, stuff->y2);
+       ret->barrier.directions = stuff->directions & 0x0f;
 +      ret->barrier.velocity = 0;
 +      ret->barrier.barrierEventID = 0;
 +      if (barrier_is_horizontal(&ret->barrier))
@@ -227,22 +312,22 @@ Index: xorg-server/xfixes/cursor.c
 +                         xXFixesCreatePointerBarrierVelocityReq *stuff)
 +{
 +    CursorScreenPtr cs = GetCursorScreen(screen);
-+    struct PointerBarrierClient *ret = malloc(sizeof(*ret));
++    struct PointerBarrierClient *ret = calloc(sizeof(*ret), 1);
 +
 +    if (ret) {
 +      ret->screen = screen;
 +      ret->barrier.barrier = stuff->barrier;
-       ret->barrier.x1 = min(stuff->x1, stuff->x2);
-       ret->barrier.x2 = max(stuff->x1, stuff->x2);
-       ret->barrier.y1 = min(stuff->y1, stuff->y2);
-       ret->barrier.y2 = max(stuff->y1, stuff->y2);
-       ret->barrier.directions = stuff->directions & 0x0f;
++      ret->barrier.x1 = min(stuff->x1, stuff->x2);
++      ret->barrier.x2 = max(stuff->x1, stuff->x2);
++      ret->barrier.y1 = min(stuff->y1, stuff->y2);
++      ret->barrier.y2 = max(stuff->y1, stuff->y2);
++      ret->barrier.directions = stuff->directions & 0x0f;
 +      ret->barrier.velocity = stuff->velocity;
 +      ret->barrier.barrierEventID = 0;
        if (barrier_is_horizontal(&ret->barrier))
            ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
        if (barrier_is_vertical(&ret->barrier))
-@@ -1365,6 +1510,69 @@
+@@ -1365,6 +1572,69 @@
      return ProcXFixesVector[stuff->xfixesReqType](client);
  }
  
@@ -312,7 +397,7 @@ Index: xorg-server/xfixes/cursor.c
  static int
  CursorFreeBarrier(void *data, XID id)
  {
-@@ -1421,6 +1629,118 @@
+@@ -1421,6 +1691,118 @@
      return ProcXFixesVector[stuff->xfixesReqType](client);
  }
  
@@ -347,7 +432,7 @@ Index: xorg-server/xfixes/cursor.c
 +      ret->client = client;
 +      ret->eventMask = stuff->eventMask;
 +      ret->window = stuff->window;
-+      ret->resource = FakeClientID (client->index);      
++      ret->resource = FakeClientID (client->index);
 +      list_add(&ret->entry, &cs->barrierClients);
 +    }
 +
@@ -377,7 +462,7 @@ Index: xorg-server/xfixes/cursor.c
 +
 +    if (!AddResource (eventClient->resource, PointerBarrierClientType, eventClient))
 +      return BadAlloc;
-+    
++
 +    return Success;
 +}
 +
@@ -411,7 +496,7 @@ Index: xorg-server/xfixes/cursor.c
 +    }
 +
 +    barrier->releaseEventID = stuff->event_id;
-+    
++
 +    return Success;
 +}
 +
@@ -431,7 +516,7 @@ Index: xorg-server/xfixes/cursor.c
  Bool
  XFixesCursorInit (void)
  {
-@@ -1441,6 +1761,7 @@
+@@ -1441,6 +1823,7 @@
        if (!cs)
            return FALSE;
        list_init(&cs->barriers);
@@ -439,7 +524,7 @@ Index: xorg-server/xfixes/cursor.c
        Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
        Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
        Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
-@@ -1455,8 +1776,10 @@
+@@ -1455,8 +1838,10 @@
                                             "XFixesCursorWindow");
      PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
                                              "XFixesPointerBarrier");
@@ -453,8 +538,8 @@ Index: xorg-server/xfixes/cursor.c
  
 Index: xorg-server/xfixes/xfixes.c
 ===================================================================
---- xorg-server.orig/xfixes/xfixes.c   2012-02-21 18:14:17.655996351 +1100
-+++ xorg-server/xfixes/xfixes.c        2012-02-22 11:39:06.726090873 +1100
+--- xorg-server.orig/xfixes/xfixes.c   2012-03-07 22:24:45.592697117 +1100
++++ xorg-server/xfixes/xfixes.c        2012-03-08 07:40:35.480111388 +1100
 @@ -100,6 +100,7 @@
      X_XFixesExpandRegion,         /* Version 3 */
      X_XFixesShowCursor,                   /* Version 4 */
@@ -487,8 +572,8 @@ Index: xorg-server/xfixes/xfixes.c
  static int
 Index: xorg-server/xfixes/xfixes.h
 ===================================================================
---- xorg-server.orig/xfixes/xfixes.h   2012-02-21 18:14:17.671996350 +1100
-+++ xorg-server/xfixes/xfixes.h        2012-02-22 11:39:06.726090873 +1100
+--- xorg-server.orig/xfixes/xfixes.h   2012-03-07 22:24:45.608697118 +1100
++++ xorg-server/xfixes/xfixes.h        2012-03-08 07:40:35.480111388 +1100
 @@ -28,6 +28,7 @@
  #define _XFIXES_H_
  
@@ -497,7 +582,7 @@ Index: xorg-server/xfixes/xfixes.h
  
  extern _X_EXPORT RESTYPE RegionResType;
  extern _X_EXPORT RESTYPE PointerBarrierType;
-@@ -52,9 +53,27 @@
+@@ -52,9 +53,25 @@
  extern _X_EXPORT RegionPtr
  XFixesRegionCopy (RegionPtr pRegion);
  
@@ -511,8 +596,6 @@ Index: xorg-server/xfixes/xfixes.h
 +    XID resource;
 +    struct list entry;
 +};
-+
-+  
 +
  struct PointerBarrier {
 +    XID    barrier;
@@ -527,8 +610,8 @@ Index: xorg-server/xfixes/xfixes.h
  
 Index: xorg-server/xfixes/xfixesint.h
 ===================================================================
---- xorg-server.orig/xfixes/xfixesint.h        2012-02-21 18:14:17.683996349 +1100
-+++ xorg-server/xfixes/xfixesint.h     2012-02-22 11:39:06.726090873 +1100
+--- xorg-server.orig/xfixes/xfixesint.h        2012-03-07 22:24:45.616697118 +1100
++++ xorg-server/xfixes/xfixesint.h     2012-03-08 07:40:35.480111388 +1100
 @@ -59,6 +59,7 @@
  #include "windowstr.h"
  #include "selection.h"
@@ -566,8 +649,8 @@ Index: xorg-server/xfixes/xfixesint.h
  void PanoramiXFixesInit (void);
 Index: xorg-server/dix/getevents.c
 ===================================================================
---- xorg-server.orig/dix/getevents.c   2012-02-21 18:14:17.703996348 +1100
-+++ xorg-server/dix/getevents.c        2012-02-22 12:09:46.441992647 +1100
+--- xorg-server.orig/dix/getevents.c   2012-03-07 22:24:45.624697119 +1100
++++ xorg-server/dix/getevents.c        2012-03-08 11:02:31.739464474 +1100
 @@ -79,6 +79,12 @@
  InternalEvent* InputEventList = NULL;
  
@@ -585,7 +668,7 @@ Index: xorg-server/dix/getevents.c
      /* miPointerSetPosition takes care of crossing screens for us, as well as
       * clipping to the current screen. Coordinates returned are in desktop
       * coord system */
-+    /** 
++    /**
 +     * Hack to pass the unclipped values through to the pointer barrier code.
 +     * Required (for now) to calculate the velocity.
 +     */
@@ -597,3 +680,1015 @@ Index: xorg-server/dix/getevents.c
  
      /* If we were constrained, rescale x/y from the screen coordinates so
       * the device valuators reflect the correct position. For screen
+Index: xorg-server/test/gtest/xfixes_barriers.cpp
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ xorg-server/test/gtest/xfixes_barriers.cpp 2012-03-08 07:42:49.188104249 +1100
+@@ -0,0 +1,828 @@
++/*
++
++Copyright (c) 2012, Canonical Ltd
++
++Permission is hereby granted, free of charge, to any person obtaining a
++copy of this software and associated documentation files (the "Software"),
++to deal in the Software without restriction, including without limitation
++the rights to use, copy, modify, merge, publish, distribute, sublicense,
++and/or sell copies of the Software, and to permit persons to whom the
++Software is furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice (including the next
++paragraph) shall be included in all copies or substantial portions of the
++Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++*/
++
++#include <iostream>
++#include <sys/time.h>
++#include <unistd.h>
++#include <gtest/gtest.h>
++#include <xorg/gtest/test.h>
++#include <xorg/gtest/environment.h>
++#include <X11/Xlib.h>
++#include <X11/extensions/XTest.h>
++#include <X11/extensions/Xfixes.h>
++
++
++int main (int argc, char **argv)
++{
++    ::testing::InitGoogleTest (&argc, argv);
++    xorg::testing::Environment* environment = new xorg::testing::Environment ();
++    environment->set_conf_file (XORG_DUMMY_CONF);
++    environment->set_server (XORG_BINARY);
++    testing::AddGlobalTestEnvironment (environment);
++    return RUN_ALL_TESTS ();
++}
++
++class BarrierTest : public xorg::testing::Test {
++    public:
++    ::Display *dpy;
++    static XErrorEvent *lastError;
++    int xtest_eventbase;
++    int xtest_errorbase;
++    int fixes_eventbase;
++    int fixes_errorbase;
++
++    void AssertPointerPosition (int expected_x, int expected_y)
++    {
++        int x, y, unused_int;
++        unsigned int unused_uint;
++        Window unused_win;
++
++        XQueryPointer (Display (), DefaultRootWindow (Display ()),
++                       &unused_win, &unused_win, &x, &y,
++                       &unused_int, &unused_int, &unused_uint);
++
++        ASSERT_TRUE (x == expected_x && y == expected_y) <<
++            "Incorrect pointer position: Expected ("<<
++            expected_x<< ", "<<expected_y<<"), got "<<
++            "("<<x<<", "<<y<<")\n";
++    }
++
++    bool WaitForXEvent (int msTimeout = 1000)
++    {
++        fd_set fds;
++        int xfd = ConnectionNumber (Display ());
++        struct timeval tv;
++        int retval;
++
++        FD_ZERO (&fds);
++        FD_SET (xfd, &fds);
++
++        tv.tv_sec = msTimeout / 1000;
++        tv.tv_usec = (msTimeout % 1000) * 1000;
++
++        retval = select (xfd + 1, &fds, NULL, NULL, &tv);
++
++        EXPECT_NE (-1, retval)<<"Error waiting for X event";
++
++        return retval;
++    }
++
++    protected:
++    virtual void SetUp ()
++    {
++        ASSERT_NO_FATAL_FAILURE (xorg::testing::Test::SetUp());
++
++        dpy = Display ();
++        int major = 2, minor = 2;
++        ASSERT_TRUE (XTestQueryExtension (dpy,
++                                          &xtest_eventbase, &xtest_errorbase,
++                                          &major, &minor));
++        ASSERT_EQ (2, major);
++        ASSERT_TRUE (minor >= 2);
++
++        major = 6;
++        minor = 0;
++        XFixesQueryVersion (dpy, &major, &minor);
++        ASSERT_EQ (6, major);
++        ASSERT_TRUE (minor >= 0);
++
++        ASSERT_TRUE (XFixesQueryExtension (dpy,
++                                           &fixes_eventbase, &fixes_errorbase));
++
++        lastError = new XErrorEvent;
++        XSetErrorHandler (ErrorHandler);
++    }
++
++    private:
++    static int ErrorHandler (::Display *dpy, XErrorEvent *error)
++    {
++        memcpy (lastError, error, sizeof (*lastError));
++        return 0;
++    }
++};
++
++XErrorEvent *BarrierTest::lastError = NULL;
++
++TEST_F (BarrierTest, CreateVerticalBarrierSucceeds)
++{
++    PointerBarrier barrier;
++    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
++                                          100, 0,
++                                          100, 100,
++                                          0,
++                                          0, NULL);
++    ASSERT_NE(None, barrier);
++}
++
++TEST_F (BarrierTest, CreateHorizontalBarrierSucceds)
++{
++    PointerBarrier barrier;
++    barrier = XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
++                                          100, 100,
++                                          200, 100,
++                                          0,
++                                          0, NULL);
++    ASSERT_NE(None, barrier);
++}
++
++TEST_F (BarrierTest, CreateNonAxisAlignedBarrierFails)
++{
++    XFixesCreatePointerBarrier (dpy, DefaultRootWindow(dpy),
++                                0, 0,
++                                100, 100,
++                                0,
++                                0, NULL);
++    XSync (Display (), false);
++    ASSERT_EQ(BadValue, lastError->error_code);
++}
++
++TEST_F (BarrierTest, VerticalBidirectionalBarrierBlocksRelativeMotion)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion should block on barrier
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y));
++}
++
++TEST_F (BarrierTest, VerticalPositiveXBarrierBlocksMotion)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierPositiveX, 0, NULL);
++    int x = 200, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve X direction should block on barrier
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = 0, y = 100, dx = 200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve X direction should ignore barrier
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, VerticalNegativeXBarrierBlocksMotion)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierNegativeX,
++                                0, NULL);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve X direction should ignore barrier
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = 0, y = 100, dx = 200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve X direction should block on barrier
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
++}
++
++TEST_F (BarrierTest, HorizontalBidirectionalBarrierBlocksRelativeMotion)
++{
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                0, 0, NULL);
++
++    int x = 200, y = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve Y direction should block on barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = 100, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve Y direction should block on barrier
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
++}
++
++TEST_F (BarrierTest, HorizontalPositiveYBarrierBlocksMotion)
++{
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                BarrierPositiveY, 0, NULL);
++
++    int x = 200, y = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve Y direction should ignore barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = 100, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve Y direction should block on barrier
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
++}
++
++TEST_F (BarrierTest, HorizontalNegativeYBarrierBlocksMotion)
++{
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0,   barrier_y,
++                                300, barrier_y,
++                                BarrierNegativeY, 0, NULL);
++
++    int x = 200, y = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in +ve Y direction should block on barrier
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = 100, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Relative motion in -ve Y direction should ignore barrier
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, DestroyPointerBarrierSucceeds)
++{
++    int barrier_x = 100;
++    PointerBarrier barrier;
++    barrier = XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                          barrier_x, 0,
++                                          barrier_x, 300,
++                                          0, 0, NULL);
++
++    int x = 0, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Check that the barrier exists before we destroy it.
++    int dx = 200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
++
++    // Destroy the barrier...
++    XFixesDestroyPointerBarrier (Display (), barrier);
++
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // There should be no barrier to block this.
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, BarrierIgnoresNonsensicalDirections)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                BarrierPositiveY | BarrierNegativeY,
++                                0, NULL);
++
++    int x = 200, y = 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    int dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    int barrier_y = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                               0,   barrier_y,
++                               400, barrier_y,
++                               BarrierPositiveX | BarrierNegativeX,
++                               0, NULL);
++
++    x = 100, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 0, dy = -200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
++}
++
++TEST_F (BarrierTest, VerticalBarrierEdges)
++{
++    int barrier_x = 300, barrier_y1 = 300 , barrier_y2 = 500;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, barrier_y1,
++                                barrier_x, barrier_y2,
++                                0, 0, NULL);
++
++    int x = barrier_x + 100, y = barrier_y1 - 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the top of the barrier...
++    int dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = barrier_x + 100, y = barrier_y1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the top of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = barrier_x + 100, y = barrier_y2;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the bottom of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = barrier_x + 100, y = barrier_y2 + 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the bottom of the barrier...
++    dx = -200, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, HorizontalBarrierEdges)
++{
++    int barrier_x1 = 200, barrier_x2 = 500, barrier_y = 300;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x1, barrier_y,
++                                barrier_x2, barrier_y,
++                                0, 0, NULL);
++
++    int x = barrier_x1 - 1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the left edge of the barrier...
++    int dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = barrier_x1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the top of the barrier...
++    dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, barrier_y - 1));
++
++    x = barrier_x2, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should hit the bottom of the barrier...
++    dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = barrier_x2 + 1, y = barrier_y - 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    // Motion should take us past the bottom of the barrier...
++    dx = 0, dy = 200;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, CornerBlocksMotion)
++{
++    int corner_x, corner_y;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                corner_x, corner_y,
++                                corner_x, corner_y + 300,
++                                0, 0, NULL);
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                corner_x, corner_y,
++                                corner_x + 300, corner_y,
++                                0, 0, NULL);
++
++    int x = corner_x + 100, y = corner_y + 100;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    XTestFakeRelativeMotionEvent (Display (), -200, -200, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (corner_x, corner_y));
++}
++
++TEST_F (BarrierTest, VerticalBarrierWithAdjacentStart)
++{
++    int barrier_x = 350;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 100,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    int x = barrier_x, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    int dx = -10, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x, y + dy));
++
++    x = barrier_x, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 10, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = barrier_x - 1, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 10, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (barrier_x - 1, y + dy));
++
++    x = barrier_x - 1, y = 200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = -10, dy = 0;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, HorizontalBarrierWithAdjacentStart)
++{
++    int barrier_y = 300;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                100, barrier_y,
++                                400, barrier_y,
++                                0, 0, NULL);
++
++    int x = 240, y = barrier_y;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    int dx = 0, dy = -10;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y));
++
++    x = 240, y = barrier_y;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 0, dy = 10;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++
++    x = 240, y = barrier_y - 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 0, dy = 10;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, barrier_y - 1));
++
++    x = 240, y = barrier_y - 1;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    dx = 0, dy = -10;
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x + dx, y + dy));
++}
++
++TEST_F (BarrierTest, BarrierNotifyEventFires)
++{
++    int barrier_y = 300;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                100, barrier_y,
++                                400, barrier_y,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 240, y = barrier_y + 50;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    XTestFakeRelativeMotionEvent (Display (), 0, -100, 0);
++
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                return;
++        }
++    }
++    FAIL () << "Failed to recieve BarrierNotify event";
++}
++
++TEST_F (BarrierTest, RecieveOneNotifyEventPerHit)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    /* Generate 5 barrier events */
++    for (int i = 0; i < 5; ++i) {
++        XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    }
++
++    int barrierEventCount = 0;
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                barrierEventCount++;
++                break;
++        }
++    }
++    ASSERT_EQ (5, barrierEventCount);
++}
++
++TEST_F (BarrierTest, BarrierEventHasNonZeroVelocity)
++{
++    int barrier_x = 100;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 200, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    /* One relative event to ensure the server has a non-zero
++     * last-event-time */
++    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
++    /* Run the pointer into the barrier */
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
++                ASSERT_LT (0, notify->velocity);
++                return;
++        }
++    }
++    FAIL () << "Failed to receive barrier event";
++}
++
++TEST_F (BarrierTest, ScreenEdgeVerticalBarrierEventHasNonZeroVelocity)
++{
++    int barrier_x = 0;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 100, y = 100, dx = -200, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    /* One relative event to ensure the server has a non-zero
++     * last-event-time */
++    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
++    /* Run the pointer into the barrier */
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
++                ASSERT_LT (0, notify->velocity);
++                return;
++        }
++    }
++    FAIL () << "Failed to receive barrier event";
++}
++
++TEST_F (BarrierTest, ScreenEdgeHorizontalBarrierEventHasNonZeroVelocity)
++{
++    int barrier_y = 0;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                0, barrier_y,
++                                300, barrier_y,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 100, y = 100, dx = 0, dy = -200;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    /* One relative event to ensure the server has a non-zero
++     * last-event-time */
++    XTestFakeRelativeMotionEvent (Display (), 10, 10, 0);
++    /* Run the pointer into the barrier */
++    XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                XFixesBarrierNotifyEvent *notify = (XFixesBarrierNotifyEvent *)&e;
++                ASSERT_LT (0, notify->velocity);
++                return;
++        }
++    }
++    FAIL () << "Failed to receive barrier event";
++}
++
++TEST_F (BarrierTest, ReceiveOneBarrierEventPerHitOnScreenEdge)
++{
++    int barrier_x = 0;
++    XFixesCreatePointerBarrier (Display (), DefaultRootWindow (Display ()),
++                                barrier_x, 0,
++                                barrier_x, 300,
++                                0, 0, NULL);
++
++    XFixesSelectBarrierInput (Display (), DefaultRootWindow (Display ()),
++                              XFixesBarrierHitNotifyMask);
++
++    int x = 20, y = 100, dx = -40, dy = 0;
++    XTestFakeMotionEvent (Display (), DefaultScreen (Display ()),
++                          x, y, 0);
++    ASSERT_NO_FATAL_FAILURE (AssertPointerPosition (x, y));
++
++    /* Generate 5 barrier events */
++    for (int i = 0; i < 5; ++i) {
++        XTestFakeRelativeMotionEvent (Display (), dx, dy, 0);
++    }
++
++    int barrierEventCount = 0;
++    XFlush (Display ());
++    ASSERT_TRUE (WaitForXEvent ())<<"Timed out waiting to receive X event";
++    while (XPending (Display ())) {
++        XEvent e;
++        XNextEvent (Display (), &e);
++        switch (e.xany.type - fixes_eventbase) {
++            case XFixesBarrierNotify:
++                barrierEventCount++;
++                break;
++        }
++    }
++    ASSERT_EQ (5, barrierEventCount);
++}
+Index: xorg-server/configure.ac
+===================================================================
+--- xorg-server.orig/configure.ac      2012-03-08 07:40:35.416111392 +1100
++++ xorg-server/configure.ac   2012-03-08 11:02:31.783464472 +1100
+@@ -2155,6 +2155,25 @@
+ AC_CONFIG_COMMANDS([sdksyms], [touch hw/xfree86/sdksyms.dep])
++AC_PROG_CXX
++
++PKG_CHECK_MODULES(XORG_GTEST, xorg-gtest,
++        [have_xorg_gtest="yes"],
++        [AC_MSG_WARN([xorg-gtest not installed, tests will not be built])])
++AM_CONDITIONAL([HAVE_XORG_GTEST], [test "x$have_xorg_gtest" = xyes])
++AC_SUBST([XORG_GTEST_CFLAGS])
++AC_SUBST([XORG_GTEST_LIBS])
++
++PKG_CHECK_MODULES([XFIXES], xfixes, [have_xfixes="yes"], [have_xfixes="no"])
++AM_CONDITIONAL([HAVE_XFIXES], [test "x$have_xfixes" = xyes])
++AC_SUBST([XFIXES_CFLAGS])
++AC_SUBST([XFIXES_LIBS])
++
++PKG_CHECK_MODULES([XTEST], xtst, [have_xtest="yes"], [have_xtest="no"])
++AM_CONDITIONAL([HAVE_XTEST], [test "x$have_xtest" = xyes])
++AC_SUBST([XTEST_CFLAGS])
++AC_SUBST([XTEST_LIBS])
++
+ AC_OUTPUT([
+ Makefile
+ glx/Makefile
+@@ -2254,6 +2273,7 @@
+ hw/kdrive/src/Makefile
+ test/Makefile
+ test/xi2/Makefile
++test/gtest/Makefile
+ xserver.ent
+ xorg-server.pc
+ ])
+Index: xorg-server/test/gtest/Makefile.am
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ xorg-server/test/gtest/Makefile.am 2012-03-08 07:40:35.488111388 +1100
+@@ -0,0 +1,27 @@
++check_PROGRAMS = xfixes_barriers
++check_DATA = dummy.conf
++
++TESTS=xfixes_barriers
++
++GTEST_SRC_DIR = /usr/src/gtest
++GTEST_SOURCES = $(GTEST_SRC_DIR)/src/gtest-all.cc
++
++xfixes_barriers_CXXFLAGS = $(AM_CXXFLAGS) \
++      -I$(GTEST_SRC_DIR) \
++      $(XORG_GTEST_CFLAGS) \
++      $(XTEST_CFLAGS) \
++      $(XFIXES_CFLAGS) \
++      -DXORG_BINARY=\"$(top_builddir)/hw/xfree86/Xorg\" \
++      -DXORG_DUMMY_CONF=\"$(abs_srcdir)/dummy.conf\"
++
++xfixes_barriers_LDADD = \
++      $(XFIXES_LIBS) \
++      $(XTEST_LIBS) \
++      $(XORG_GTEST_LIBS) \
++      -lpthread
++
++xfixes_barriers_SOURCES = \
++      xfixes_barriers.cpp
++
++nodist_xfixes_barriers_SOURCES = \
++      $(GTEST_SOURCES)
+Index: xorg-server/test/Makefile.am
+===================================================================
+--- xorg-server.orig/test/Makefile.am  2012-03-07 22:24:45.684697122 +1100
++++ xorg-server/test/Makefile.am       2012-03-08 07:40:35.488111388 +1100
+@@ -1,5 +1,10 @@
+ if ENABLE_UNIT_TESTS
+ SUBDIRS= . xi2
++
++if HAVE_XORG_GTEST
++SUBDIRS+= gtest
++endif
++
+ noinst_PROGRAMS = xkb input xtest list misc fixes xfree86 touch
+ check_LTLIBRARIES = libxservertest.la
+Index: xorg-server/test/gtest/dummy.conf
+===================================================================
+--- /dev/null  1970-01-01 00:00:00.000000000 +0000
++++ xorg-server/test/gtest/dummy.conf  2012-03-08 07:40:35.488111388 +1100
+@@ -0,0 +1,4 @@
++Section "Device"
++    Identifier "Dummy video device"
++    Driver "dummy"
++EndSection
+Index: xorg-server/dix/dixutils.c
+===================================================================
+--- xorg-server.orig/dix/dixutils.c    2012-03-08 07:40:35.392111393 +1100
++++ xorg-server/dix/dixutils.c 2012-03-08 07:40:35.488111388 +1100
+@@ -537,7 +537,7 @@
+       {
+           /* remove q from the list */
+           *p = q->next;    /* don't fetch until after func called */
+-          free(q);
++          (*q->destroyProc) (q);
+       }
+       else
+       {
+@@ -560,7 +560,7 @@
+           (void) (*q->function) (q->client, q->closure);
+           /* remove q from the list */
+           *p = q->next;    /* don't fetch until after func called */
+-          free(q);
++          (*q->destroyProc) (q);
+       }
+       else
+       {
+@@ -570,6 +570,12 @@
+     workQueueLast = p;
+ }
++static void
++FreeWorkQueueItem (WorkQueuePtr this)
++{
++    free(this);
++}
++
+ Bool
+ QueueWorkProc (
+     Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
+@@ -583,12 +589,22 @@
+     q->function = function;
+     q->client = client;
+     q->closure = closure;
++    q->destroyProc = FreeWorkQueueItem;
+     q->next = NULL;
+     *workQueueLast = q;
+     workQueueLast = &q->next;
+     return TRUE;
+ }
++Bool
++QueueWorkItem (WorkQueuePtr item)
++{
++    item->next = NULL;
++    *workQueueLast = item;
++    workQueueLast = &item->next;
++    return TRUE;
++}
++
+ /*
+  * Manage a queue of sleeping clients, awakening them
+  * when requested, by using the OS functions IgnoreClient
+Index: xorg-server/include/dixstruct.h
+===================================================================
+--- xorg-server.orig/include/dixstruct.h       2012-03-07 22:24:45.552697115 +1100
++++ xorg-server/include/dixstruct.h    2012-03-08 07:40:35.492111388 +1100
+@@ -153,6 +153,9 @@
+ );
+     ClientPtr   client;
+     pointer     closure;
++    void       (*destroyProc) (
++                struct _WorkQueue * /* this */
++);
+ }           WorkQueueRec;
+ extern _X_EXPORT TimeStamp currentTime;
+Index: xorg-server/include/dix.h
+===================================================================
+--- xorg-server.orig/include/dix.h     2012-03-07 22:24:45.568697116 +1100
++++ xorg-server/include/dix.h  2012-03-08 07:40:35.492111388 +1100
+@@ -266,6 +266,8 @@
+     pointer /*closure*/
+ );
++extern _X_EXPORT Bool QueueWorkItem(WorkQueuePtr item);
++
+ typedef Bool (* ClientSleepProcPtr)(
+     ClientPtr /*client*/,
+     pointer /*closure*/);
diff --git a/debian/patches/501_touch_accept_end.patch b/debian/patches/501_touch_accept_end.patch
new file mode 100644 (file)
index 0000000..03f7524
--- /dev/null
@@ -0,0 +1,95 @@
+From 40cd6abb66787c79465cda03c17297a06d1cd848 Mon Sep 17 00:00:00 2001
+From: Chase Douglas <chase.douglas@canonical.com>
+Date: Fri, 2 Mar 2012 14:40:07 -0800
+Subject: [PATCH 1/2] Xi: Fix TouchEnd to TouchUpdate change for one accepted
+ grab
+
+If there is only one listener of a touch, the listener is a grab, and is
+accepted before the touch has ended, the current code will not end the
+touch record when the touch does end.
+
+This change adds a listener state for when a touch is accepted but has
+not yet ended. We now keep the touch record alive in this state, but end
+it when the touch ends.
+
+Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+---
+ Xi/exevents.c   |   25 ++++++++++++++++---------
+ include/input.h |    3 ++-
+ 2 files changed, 18 insertions(+), 10 deletions(-)
+
+diff --git a/Xi/exevents.c b/Xi/exevents.c
+index f390f67..d71e604 100644
+--- a/Xi/exevents.c
++++ b/Xi/exevents.c
+@@ -1252,6 +1252,8 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
+         /* Owner accepted after receiving end */
+         if (ti->listeners[0].state == LISTENER_HAS_END)
+             TouchEndTouch(dev, ti);
++        else
++            ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
+     } else { /* this is the very first ownership event for a grab */
+         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ev->resource);
+     }
+@@ -1781,7 +1783,11 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev
+     {
+         if (has_ownershipmask)
+             TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
+-        state = LISTENER_IS_OWNER;
++
++        if (!has_ownershipmask || listener->type == LISTENER_REGULAR)
++            state = LISTENER_HAS_ACCEPTED;
++        else
++            state = LISTENER_IS_OWNER;
+     }
+     listener->state = state;
+@@ -1812,22 +1818,23 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
+         listener->state = LISTENER_HAS_END;
+     } else if (TouchResourceIsOwner(ti, listener->listener))
+     {
++        Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
++
+         /* FIXME: what about early acceptance */
+-        if (!(ev->device_event.flags & TOUCH_ACCEPT))
+-        {
+-            if (listener->state != LISTENER_HAS_END)
+-                rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
+-            listener->state = LISTENER_HAS_END;
+-        }
++        if (normal_end && listener->state != LISTENER_HAS_END)
++            rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
++
+         if ((ti->num_listeners > 1 ||
+-             (listener->type == LISTENER_GRAB &&
+-              xi2mask_isset(xi2mask, dev, XI_TouchOwnership))) &&
++             listener->state != LISTENER_HAS_ACCEPTED) &&
+             (ev->device_event.flags & (TOUCH_ACCEPT|TOUCH_REJECT)) == 0)
+         {
+             ev->any.type = ET_TouchUpdate;
+             ev->device_event.flags |= TOUCH_PENDING_END;
+             ti->pending_finish = TRUE;
+         }
++
++        if (normal_end)
++            listener->state = LISTENER_HAS_END;
+     }
+ out:
+diff --git a/include/input.h b/include/input.h
+index b7825a7..1e9e0fd 100644
+--- a/include/input.h
++++ b/include/input.h
+@@ -585,7 +585,8 @@ enum TouchListenerState{
+     LISTENER_AWAITING_OWNER,       /**< Waiting for a TouchOwnership event */
+     LISTENER_EARLY_ACCEPT,         /**< Waiting for ownership, has already
+                                         accepted */
+-    LISTENER_IS_OWNER,             /**< Is the current owner */
++    LISTENER_IS_OWNER,             /**< Is the current owner, hasn't accepted */
++    LISTENER_HAS_ACCEPTED,         /**< Is the current owner, has accepted */
+     LISTENER_HAS_END,              /**< Has already received the end event */
+ };
+-- 
+1.7.9
+
diff --git a/debian/patches/502_indirect_touch_window_set.patch b/debian/patches/502_indirect_touch_window_set.patch
new file mode 100644 (file)
index 0000000..5eafe81
--- /dev/null
@@ -0,0 +1,40 @@
+From d128edad09452246e18b38cef151cad226f1c5f5 Mon Sep 17 00:00:00 2001
+From: Chase Douglas <chase.douglas@canonical.com>
+Date: Wed, 7 Mar 2012 15:20:12 -0800
+Subject: [PATCH 2/2] Use a new sprite trace for indirect touches when all
+ touches have physically ended
+
+All touches of an indirect device, such as a trackpad, are sent to the
+same window set. When there are no active touches, a new window set is
+created; otherwise, the window set of an existing touch is copied.
+
+The current code checks for any logically active touches. This includes
+touches that have physically ended but are still logically active due to
+unhandled touch grabs. Instead, we want a new window set whenever there
+are no physically active touches.
+
+This change skips over logically active but pending end touches, which
+are touches that have physically ended.
+
+Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
+---
+ dix/touch.c |    3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/dix/touch.c b/dix/touch.c
+index d04801c..0aa24f2 100644
+--- a/dix/touch.c
++++ b/dix/touch.c
+@@ -524,7 +524,8 @@ TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
+     /* All touches should have the same sprite trace, so find and reuse an
+      * existing touch's sprite if possible, else use the device's sprite. */
+     for (i = 0; i < t->num_touches; i++)
+-        if (t->touches[i].sprite.spriteTraceGood > 0)
++        if (!t->touches[i].pending_finish &&
++            t->touches[i].sprite.spriteTraceGood > 0)
+             break;
+     if (i < t->num_touches)
+         srcsprite = &t->touches[i].sprite;
+-- 
+1.7.9
+
diff --git a/debian/patches/600-Revert-dix-deduplicate-callers-of-DeliverDeviceEvent.patch b/debian/patches/600-Revert-dix-deduplicate-callers-of-DeliverDeviceEvent.patch
deleted file mode 100644 (file)
index 2630963..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-From f92ba92adfce0e1975feb54ab0e1165b7c2a7bea Mon Sep 17 00:00:00 2001
-From: Peter Hutterer <peter.hutterer@who-t.net>
-Date: Sat, 4 Feb 2012 19:27:21 +1000
-Subject: [PATCH] Revert "dix: deduplicate callers of DeliverDeviceEvents in
- DeliverGrabbedEvents"
-
-This call was supposed to have no functional changes but in some cases
-DeliverDeviceEvents() was called with a uninitialised win variable.
-Revert, safer than trying to sort this out otherwise.
-
-This reverts commit 6eff14a789341d366b3013c5aa020e959c954651.
-
-Reported-by: Mathieu Taillefumier <mathieu.taillefumier@free.fr>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Keith Packard <keithp@keithp.com>
----
- dix/events.c |   18 ++++++++----------
- 1 files changed, 8 insertions(+), 10 deletions(-)
-
-diff --git a/dix/events.c b/dix/events.c
-index 04d7fb5..3c7d5d0 100644
---- a/dix/events.c
-+++ b/dix/events.c
-@@ -4266,7 +4266,6 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
-     if (grab->ownerEvents)
-     {
-       WindowPtr focus;
--      WindowPtr win;
-         /* Hack: Some pointer device have a focus class. So we need to check
-          * for the type of event, to see if we really want to deliver it to
-@@ -4283,16 +4282,15 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
-       else
-           focus = PointerRootWin;
-       if (focus == PointerRootWin)
--      {
--          win = pSprite->win;
--          focus = NullWindow;
--      } else if (focus && (focus == pSprite->win ||
--                  IsParent(focus, pSprite->win)))
--          win = pSprite->win;
-+          deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
-+                                             NullWindow, thisDev);
-+      else if (focus && (focus == pSprite->win ||
-+                    IsParent(focus, pSprite->win)))
-+          deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
-+                                           thisDev);
-       else if (focus)
--          win = focus;
--
--      deliveries = DeliverDeviceEvents(win, event, grab, focus, thisDev);
-+          deliveries = DeliverDeviceEvents(focus, event, grab, focus,
-+                                           thisDev);
-     }
-     if (!deliveries)
-     {
--- 
-1.7.8.3
-
diff --git a/debian/patches/601-Store-window-pointer-in-touch-listener-record.patch b/debian/patches/601-Store-window-pointer-in-touch-listener-record.patch
deleted file mode 100644 (file)
index 58ee8db..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-From ab60cadc2afb9d8882144e30fde11c3ef0f999cd Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:05 -0800
-Subject: [PATCH] Store window pointer in touch listener record
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- dix/touch.c        |   16 ++++++++++------
- include/input.h    |    3 ++-
- include/inputstr.h |    1 +
- 3 files changed, 13 insertions(+), 7 deletions(-)
-
-diff --git a/dix/touch.c b/dix/touch.c
-index db0bf33..b42859d 100644
---- a/dix/touch.c
-+++ b/dix/touch.c
-@@ -697,12 +697,14 @@ TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource)
-  */
- void
- TouchAddListener(TouchPointInfoPtr ti, XID resource, enum InputLevel level,
--                 enum TouchListenerType type, enum TouchListenerState state)
-+                 enum TouchListenerType type, enum TouchListenerState state,
-+                 WindowPtr window)
- {
-     ti->listeners[ti->num_listeners].listener = resource;
-     ti->listeners[ti->num_listeners].level = level;
-     ti->listeners[ti->num_listeners].state = state;
-     ti->listeners[ti->num_listeners].type = type;
-+    ti->listeners[ti->num_listeners].window = window;
-     ti->num_listeners++;
- }
-@@ -753,7 +755,7 @@ TouchAddGrabListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
-     }
-     TouchAddListener(ti, grab->resource, grab->grabtype,
--                     type, LISTENER_AWAITING_BEGIN);
-+                     type, LISTENER_AWAITING_BEGIN, grab->window);
-     ti->num_grabs++;
- }
-@@ -814,7 +816,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
-                 TouchEventHistoryAllocate(ti);
-             TouchAddListener(ti, iclients->resource, XI2,
--                             type, LISTENER_AWAITING_BEGIN);
-+                             type, LISTENER_AWAITING_BEGIN, win);
-             return TRUE;
-         }
-     }
-@@ -830,7 +832,8 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
-             TouchEventHistoryAllocate(ti);
-             TouchAddListener(ti, iclients->resource, XI,
--                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
-+                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
-+                             win);
-             return TRUE;
-         }
-     }
-@@ -845,7 +848,8 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
-         {
-             TouchEventHistoryAllocate(ti);
-             TouchAddListener(ti, win->drawable.id, CORE,
--                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
-+                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
-+                             win);
-             return TRUE;
-         }
-@@ -857,7 +861,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
-             TouchEventHistoryAllocate(ti);
-             TouchAddListener(ti, iclients->resource, CORE,
--                             type, LISTENER_AWAITING_BEGIN);
-+                             type, LISTENER_AWAITING_BEGIN, win);
-             return TRUE;
-         }
-     }
-diff --git a/include/input.h b/include/input.h
-index fb45617..53645b4 100644
---- a/include/input.h
-+++ b/include/input.h
-@@ -613,7 +613,8 @@ extern void TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev);
- extern void TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource);
- extern Bool TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource);
- extern void TouchAddListener(TouchPointInfoPtr ti, XID resource, enum InputLevel level,
--                                     enum TouchListenerType type, enum TouchListenerState state);
-+                             enum TouchListenerType type, enum TouchListenerState state,
-+                             WindowPtr window);
- extern Bool TouchRemoveListener(TouchPointInfoPtr ti, XID resource);
- extern void TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev);
- extern Bool TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-diff --git a/include/inputstr.h b/include/inputstr.h
-index c3297db..4e28bc7 100644
---- a/include/inputstr.h
-+++ b/include/inputstr.h
-@@ -314,6 +314,7 @@ typedef struct _TouchPointInfo {
-         enum TouchListenerType type;
-         enum TouchListenerState state;
-         enum InputLevel level;      /* matters only for emulating touches */
-+        WindowPtr window;
-     } *listeners;
-     int         num_listeners;
-     int         num_grabs;          /* number of open grabs on this touch
--- 
-1.7.8.3
-
diff --git a/debian/patches/602-Factor-out-TouchEnd-generation-and-delivery.patch b/debian/patches/602-Factor-out-TouchEnd-generation-and-delivery.patch
deleted file mode 100644 (file)
index 1202d02..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-From 19073425e5df1317f73f74ce0b95ab24e0e0da14 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:06 -0800
-Subject: [PATCH] Factor out TouchEnd generation and delivery
-
-The server often needs to generate and deliver TouchEnd events for
-circumstances including touch grab acceptance and rejection. This change
-refactors the code so it can be used more easily.
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/exevents.c |  103 ++++++++++++++++++++------------------------------------
- 1 files changed, 37 insertions(+), 66 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index 6b2db4b..218df2a 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -1089,17 +1089,46 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
- }
- /**
-- * If the current owner has rejected the event, deliver the
-- * TouchOwnership/TouchBegin to the next item in the sprite stack.
-+ * 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
--TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
--                     TouchOwnershipEvent *ev)
-+EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
- {
-     InternalEvent *tel = InitEventList(GetMaximumEventsNum());
-     ValuatorMask *mask = valuator_mask_new(2);
-     int i, nev;
-+    valuator_mask_set_double(mask, 0,
-+                             valuator_mask_get_double(ti->valuators, 0));
-+    valuator_mask_set_double(mask, 1,
-+                             valuator_mask_get_double(ti->valuators, 1));
-+
-+    flags |= TOUCH_CLIENT_ID;
-+    if (ti->emulate_pointer)
-+        flags |= TOUCH_POINTER_EMULATED;
-+    nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
-+    for (i = 0; i < nev; i++)
-+        DeliverTouchEvents(dev, ti, tel + i, resource);
-+
-+    valuator_mask_free(&mask);
-+    FreeEventList(tel, GetMaximumEventsNum());
-+}
-+
-+/**
-+ * If the current owner has rejected the event, deliver the
-+ * TouchOwnership/TouchBegin to the next item in the sprite stack.
-+ */
-+static void
-+TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-+                     TouchOwnershipEvent *ev)
-+{
-     /* Deliver the ownership */
-     if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
-         DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
-@@ -1111,60 +1140,30 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-     if (ti->num_listeners == 1 && ti->num_grabs == 0 &&
-             ti->pending_finish)
-     {
--        int flags;
--        valuator_mask_set_double(mask, 0,
--                                 valuator_mask_get_double(ti->valuators, 0));
--        valuator_mask_set_double(mask, 1,
--                                 valuator_mask_get_double(ti->valuators, 1));
--
--        flags = TOUCH_CLIENT_ID;
--        if (ti->emulate_pointer)
--            flags |= TOUCH_POINTER_EMULATED;
--        nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
--        for (i = 0; i < nev; i++)
--            DeliverTouchEvents(dev, ti, tel + i, 0);
-+        EmitTouchEnd(dev, ti, 0, 0);
-         TouchEndTouch(dev, ti);
-     }
--
--    valuator_mask_free(&mask);
--    FreeEventList(tel, GetMaximumEventsNum());
- }
- static void
- TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-                    TouchOwnershipEvent *ev)
- {
--    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
--    ValuatorMask *mask = valuator_mask_new(2);
-     Bool was_owner = (ev->resource == ti->listeners[0].listener);
-     void *grab;
--    int nev, i;
-     /* Send a TouchEnd event to the resource being removed, but only if they
-      * haven't received one yet already */
-     if (ti->listeners[0].state != LISTENER_HAS_END)
--    {
--        int flags;
--        valuator_mask_set_double(mask, 0,
--                                 valuator_mask_get_double(ti->valuators, 0));
--        valuator_mask_set_double(mask, 1,
--                                 valuator_mask_get_double(ti->valuators, 1));
--
--        flags = TOUCH_CLIENT_ID|TOUCH_REJECT;
--        if (ti->emulate_pointer)
--            flags |= TOUCH_POINTER_EMULATED;
--        nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask);
--        for (i = 0; i < nev; i++)
--            DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource);
--    }
-+        EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, ev->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);
--        goto out;
-+        return;
-     }
-     /* Remove the resource from the listener list, updating
-@@ -1180,10 +1179,6 @@ TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-      * the TouchOwnership or TouchBegin event to the new owner. */
-     if (ti->num_listeners > 0 && was_owner)
-         TouchPuntToNextOwner(sourcedev, ti, ev);
--
--out:
--    FreeEventList(tel, GetMaximumEventsNum());
--    valuator_mask_free(&mask);
- }
- /**
-@@ -1201,33 +1196,9 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
-     if (ev->reason == XIRejectTouch)
-         TouchEventRejected(dev, ti, ev);
-     else if (ev->reason == XIAcceptTouch) {
--        int flags;
--        int nev, i;
--        ValuatorMask *mask;
--
--        InternalEvent *tel = InitEventList(GetMaximumEventsNum());
--
--        mask = valuator_mask_new(dev->valuator->numAxes);
--        valuator_mask_set_double(mask, 0,
--                                 valuator_mask_get_double(ti->valuators, 0));
--        valuator_mask_set_double(mask, 1,
--                                 valuator_mask_get_double(ti->valuators, 1));
--
--        /* FIXME: what about early acceptance? a client may accept before it
--         * owns the touch. */
--
-         /* The touch owner has accepted the touch.  Send TouchEnd events to
-          * everyone else, and truncate the list of listeners. */
--        flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID;
--        if (ti->emulate_pointer)
--            flags |= TOUCH_POINTER_EMULATED;
--        nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd,
--                             flags, mask);
--        for (i = 0; i < nev; i++)
--            DeliverTouchEvents(dev, ti, tel + i, 0);
--
--        FreeEventList(tel, GetMaximumEventsNum());
--        valuator_mask_free(&mask);
-+        EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
-         while (ti->num_listeners > 1)
-             TouchRemoveListener(ti, ti->listeners[1].listener);
--- 
-1.7.8.3
-
diff --git a/debian/patches/603-Export-TouchEventRejected-as-TouchRejected.patch b/debian/patches/603-Export-TouchEventRejected-as-TouchRejected.patch
deleted file mode 100644 (file)
index 5701ece..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-From 192b2c9a2ec04522655675ddfe71de5cf974cc7b Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:07 -0800
-Subject: [PATCH] Export TouchEventRejected as TouchRejected
-
-This function is mostly correct for early reject usage. With a small
-change to pass the client resource explicitly and making the
-TouchOwnership event optional, it is usable for all rejection scenarios.
-This change exports it for use outside Xi/exevents.c and modifies the
-name accordingly.
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/exevents.c      |   38 +++++++++++++++++++++++++++-----------
- include/exevents.h |    7 +++++++
- 2 files changed, 34 insertions(+), 11 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index 218df2a..b0832d0 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -1145,18 +1145,34 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-     }
- }
--static void
--TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
--                   TouchOwnershipEvent *ev)
-+/**
-+ * Process a touch rejection.
-+ *
-+ * @param sourcedev The source device of the touch sequence.
-+ * @param ti The touchpoint info record.
-+ * @param resource The resource of the client rejecting the touch.
-+ * @param ev TouchOwnership event to send. Set to NULL if no event should be
-+ *        sent.
-+ */
-+void
-+TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
-+              TouchOwnershipEvent *ev)
- {
--    Bool was_owner = (ev->resource == ti->listeners[0].listener);
-+    Bool was_owner = (resource == ti->listeners[0].listener);
-     void *grab;
--
-+    int i;
-     /* Send a TouchEnd event to the resource being removed, but only if they
-      * haven't received one yet already */
--    if (ti->listeners[0].state != LISTENER_HAS_END)
--        EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, ev->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);
-+            break;
-+        }
-+    }
-     /* If there are no other listeners left, and the touchpoint is pending
-      * finish, then we can just kill it now. */
-@@ -1168,16 +1184,16 @@ TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
-     /* 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, ev->resource))
-+    if (TouchRemoveListener(ti, resource))
-     {
--        if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB,
-+        if (dixLookupResourceByType(&grab, resource, RT_PASSIVEGRAB,
-                                     serverClient, DixGetAttrAccess) == Success)
-             ti->num_grabs--;
-     }
-     /* If the current owner was removed and there are further listeners, deliver
-      * the TouchOwnership or TouchBegin event to the new owner. */
--    if (ti->num_listeners > 0 && was_owner)
-+    if (ev && ti->num_listeners > 0 && was_owner)
-         TouchPuntToNextOwner(sourcedev, ti, ev);
- }
-@@ -1194,7 +1210,7 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
- {
-     if (ev->reason == XIRejectTouch)
--        TouchEventRejected(dev, ti, ev);
-+        TouchRejected(dev, ti, ev->resource, ev);
-     else if (ev->reason == XIAcceptTouch) {
-         /* The touch owner has accepted the touch.  Send TouchEnd events to
-          * everyone else, and truncate the list of listeners. */
-diff --git a/include/exevents.h b/include/exevents.h
-index 31acb30..fb2ef27 100644
---- a/include/exevents.h
-+++ b/include/exevents.h
-@@ -323,6 +323,13 @@ SendEventToAllWindows(
-         xEvent *               /* ev */,
-         int                    /* count */);
-+extern void
-+TouchRejected(
-+        DeviceIntPtr           /* sourcedev */,
-+        TouchPointInfoPtr      /* ti */,
-+        XID                    /* resource */,
-+        TouchOwnershipEvent *  /* ev */);
-+
- extern _X_HIDDEN void XI2EventSwap(
-         xGenericEvent  *              /* from */,
-         xGenericEvent  *              /* to */);
--- 
-1.7.8.3
-
diff --git a/debian/patches/604-Move-AllowTouch-to-dix-touch.c-and-rename-to-TouchAc.patch b/debian/patches/604-Move-AllowTouch-to-dix-touch.c-and-rename-to-TouchAc.patch
deleted file mode 100644 (file)
index 62207be..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-From 9a260e9af83feb5c53ffd3b2da2dc3adf06240a1 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:08 -0800
-Subject: [PATCH] Move AllowTouch to dix/touch.c, and rename to
- TouchAcceptReject
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/xiallowev.c  |   46 ++--------------------------------------------
- dix/touch.c     |   45 +++++++++++++++++++++++++++++++++++++++++++++
- include/input.h |    2 ++
- 3 files changed, 49 insertions(+), 44 deletions(-)
-
-diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
-index a4b2f57..dab3393 100644
---- a/Xi/xiallowev.c
-+++ b/Xi/xiallowev.c
-@@ -57,47 +57,6 @@ SProcXIAllowEvents(ClientPtr client)
-     return ProcXIAllowEvents(client);
- }
--static int
--AllowTouch(ClientPtr client, DeviceIntPtr dev, int mode, uint32_t touchid, XID *error)
--{
--    TouchPointInfoPtr ti;
--    int nev, i;
--    InternalEvent *events = InitEventList(GetMaximumEventsNum());
--
--    if (!events)
--        return BadAlloc;
--
--    if (!dev->touch)
--    {
--        *error = dev->id;
--        return BadDevice;
--    }
--
--    /* FIXME window is unhandled */
--
--    ti = TouchFindByClientID(dev, touchid);
--    if (!ti)
--    {
--        *error = touchid;
--        return BadValue;
--    }
--
--    /* FIXME: Allow for early accept */
--    if (ti->num_listeners == 0 || CLIENT_ID(ti->listeners[0].listener) != client->index)
--        return BadAccess;
--
--    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;
--}
--
- int
- ProcXIAllowEvents(ClientPtr client)
- {
-@@ -138,9 +97,8 @@ ProcXIAllowEvents(ClientPtr client)
-       break;
-     case XIRejectTouch:
-     case XIAcceptTouch:
--        ret = AllowTouch(client, dev,
--                         stuff->mode, stuff->touchid,
--                         &client->errorValue);
-+        ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
-+                                &client->errorValue);
-         break;
-     default:
-       client->errorValue = stuff->mode;
-diff --git a/dix/touch.c b/dix/touch.c
-index b42859d..4a116ee 100644
---- a/dix/touch.c
-+++ b/dix/touch.c
-@@ -34,6 +34,7 @@
- #include "eventstr.h"
- #include "exevents.h"
-+#include "exglobals.h"
- #include "inpututils.h"
- #include "eventconvert.h"
- #include "windowstr.h"
-@@ -984,3 +985,47 @@ TouchListenerGone(XID resource)
-     FreeEventList(events, GetMaximumEventsNum());
- }
-+
-+int
-+TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-+                  uint32_t touchid, XID *error)
-+{
-+    TouchPointInfoPtr ti;
-+    int nev, i;
-+    InternalEvent *events = InitEventList(GetMaximumEventsNum());
-+
-+    if (!events)
-+        return BadAlloc;
-+
-+    if (!dev->touch)
-+    {
-+        *error = dev->id;
-+        return BadDevice;
-+    }
-+
-+    /* FIXME window is unhandled */
-+
-+    ti = TouchFindByClientID(dev, touchid);
-+    if (!ti)
-+    {
-+        *error = touchid;
-+        return BadValue;
-+    }
-+
-+    /* FIXME: Allow for early accept */
-+    if (ti->num_listeners == 0 ||
-+        CLIENT_ID(ti->listeners[0].listener) != client->index)
-+        return BadAccess;
-+
-+    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;
-+}
-diff --git a/include/input.h b/include/input.h
-index 53645b4..605e74d 100644
---- a/include/input.h
-+++ b/include/input.h
-@@ -625,6 +625,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 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-+                             uint32_t touchid, XID *error);
- /* misc event helpers */
- extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
--- 
-1.7.8.3
-
diff --git a/debian/patches/605-Check-for-proper-window-ID-when-processing-touch-all.patch b/debian/patches/605-Check-for-proper-window-ID-when-processing-touch-all.patch
deleted file mode 100644 (file)
index 0f328a6..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-From 656ab879f20892975510723ce8fe78faf64aadb4 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:09 -0800
-Subject: [PATCH] Check for proper window ID when processing touch allow
- requests
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/xiallowev.c  |    2 +-
- dix/touch.c     |   18 ++++++++++++------
- include/input.h |    2 +-
- 3 files changed, 14 insertions(+), 8 deletions(-)
-
-diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
-index dab3393..38967b2 100644
---- a/Xi/xiallowev.c
-+++ b/Xi/xiallowev.c
-@@ -98,7 +98,7 @@ ProcXIAllowEvents(ClientPtr client)
-     case XIRejectTouch:
-     case XIAcceptTouch:
-         ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
--                                &client->errorValue);
-+                                stuff->grab_window, &client->errorValue);
-         break;
-     default:
-       client->errorValue = stuff->mode;
-diff --git a/dix/touch.c b/dix/touch.c
-index 4a116ee..7daf81b 100644
---- a/dix/touch.c
-+++ b/dix/touch.c
-@@ -988,7 +988,7 @@ TouchListenerGone(XID resource)
- int
- TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
--                  uint32_t touchid, XID *error)
-+                  uint32_t touchid, Window grab_window, XID *error)
- {
-     TouchPointInfoPtr ti;
-     int nev, i;
-@@ -1003,8 +1003,6 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-         return BadDevice;
-     }
--    /* FIXME window is unhandled */
--
-     ti = TouchFindByClientID(dev, touchid);
-     if (!ti)
-     {
-@@ -1012,9 +1010,17 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-         return BadValue;
-     }
--    /* FIXME: Allow for early accept */
--    if (ti->num_listeners == 0 ||
--        CLIENT_ID(ti->listeners[0].listener) != client->index)
-+    for (i = 0; i < ti->num_listeners; i++)
-+    {
-+        if (CLIENT_ID(ti->listeners[i].listener) == client->index &&
-+            ti->listeners[i].window->drawable.id == grab_window)
-+            break;
-+    }
-+    if (i == ti->num_listeners)
-+        return BadAccess;
-+
-+    /* FIXME: Implement early accept/reject */
-+    if (i > 0)
-         return BadAccess;
-     nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-diff --git a/include/input.h b/include/input.h
-index 605e74d..fea5a31 100644
---- a/include/input.h
-+++ b/include/input.h
-@@ -626,7 +626,7 @@ extern int TouchGetPointerEventType(const InternalEvent *ev);
- extern void TouchRemovePointerGrab(DeviceIntPtr dev);
- extern void TouchListenerGone(XID resource);
- extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
--                             uint32_t touchid, XID *error);
-+                             uint32_t touchid, Window grab_window, XID *error);
- /* misc event helpers */
- extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
--- 
-1.7.8.3
-
diff --git a/debian/patches/606-Implement-early-touch-reject.patch b/debian/patches/606-Implement-early-touch-reject.patch
deleted file mode 100644 (file)
index bd8f4b1..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-From b0c54856df71f9cabf9dad176fdade960ef8c5d9 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:10 -0800
-Subject: [PATCH] Implement early touch reject
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- dix/touch.c |    9 ++++++++-
- 1 files changed, 8 insertions(+), 1 deletions(-)
-
-diff --git a/dix/touch.c b/dix/touch.c
-index 7daf81b..f55bb8c 100644
---- a/dix/touch.c
-+++ b/dix/touch.c
-@@ -1019,9 +1019,16 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-     if (i == ti->num_listeners)
-         return BadAccess;
--    /* FIXME: Implement early accept/reject */
-     if (i > 0)
-+    {
-+        if (mode == XIRejectTouch)
-+        {
-+            TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
-+            return Success;
-+        }
-+        /* FIXME: Implement early accept */
-         return BadAccess;
-+    }
-     nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-                                   ti->listeners[0].listener, 0);
--- 
-1.7.8.3
-
diff --git a/debian/patches/607-Implement-touch-early-accept.patch b/debian/patches/607-Implement-touch-early-accept.patch
deleted file mode 100644 (file)
index 1d92132..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-From 6241b5e4fdbdb08d30cc8787d858ac27122d2d49 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Fri, 3 Feb 2012 16:19:11 -0800
-Subject: [PATCH] Implement touch early accept
-
-This doesn't really implement early accept as it should. Ideally, the
-server should send end events to all subsequent touch clients as soon as
-an early accept comes in. However, this implementation is still protocol
-compliant. We can always improve it later.
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/exevents.c   |   27 ++++++++++++++++++++++++++-
- dix/touch.c     |    9 ++++-----
- include/input.h |    2 ++
- 3 files changed, 32 insertions(+), 6 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index b0832d0..1ecc3ba 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -1088,6 +1088,27 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
-     return TRUE;
- }
-+static void
-+ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
-+{
-+    int rc;
-+    ClientPtr client;
-+    XID error;
-+
-+    rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
-+                         DixSendAccess);
-+    if (rc != Success)
-+    {
-+        ErrorF("[Xi] Failed to lookup early accepting client.\n");
-+        return;
-+    }
-+
-+    if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
-+                          ti->listeners[0].window->drawable.id, &error) !=
-+        Success)
-+        ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
-+}
-+
- /**
-  * Generate and deliver a TouchEnd event.
-  *
-@@ -1130,7 +1151,8 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-                      TouchOwnershipEvent *ev)
- {
-     /* Deliver the ownership */
--    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
-+    if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
-+        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)
-         TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
-@@ -1143,6 +1165,9 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-         EmitTouchEnd(dev, ti, 0, 0);
-         TouchEndTouch(dev, ti);
-     }
-+
-+    if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
-+        ActivateEarlyAccept(dev, ti);
- }
- /**
-diff --git a/dix/touch.c b/dix/touch.c
-index f55bb8c..d04801c 100644
---- a/dix/touch.c
-+++ b/dix/touch.c
-@@ -1022,12 +1022,11 @@ TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
-     if (i > 0)
-     {
-         if (mode == XIRejectTouch)
--        {
-             TouchRejected(dev, ti, ti->listeners[i].listener, NULL);
--            return Success;
--        }
--        /* FIXME: Implement early accept */
--        return BadAccess;
-+        else
-+            ti->listeners[i].state = LISTENER_EARLY_ACCEPT;
-+
-+        return Success;
-     }
-     nev = GetTouchOwnershipEvents(events, dev, ti, mode,
-diff --git a/include/input.h b/include/input.h
-index fea5a31..b7825a7 100644
---- a/include/input.h
-+++ b/include/input.h
-@@ -583,6 +583,8 @@ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs);
- enum TouchListenerState{
-     LISTENER_AWAITING_BEGIN = 0,   /**< Waiting for a TouchBegin event */
-     LISTENER_AWAITING_OWNER,       /**< Waiting for a TouchOwnership event */
-+    LISTENER_EARLY_ACCEPT,         /**< Waiting for ownership, has already
-+                                        accepted */
-     LISTENER_IS_OWNER,             /**< Is the current owner */
-     LISTENER_HAS_END,              /**< Has already received the end event */
- };
--- 
-1.7.8.3
-
diff --git a/debian/patches/608-dix-fix-an-out-of-memory-crash.patch b/debian/patches/608-dix-fix-an-out-of-memory-crash.patch
deleted file mode 100644 (file)
index 78f538a..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-From b96275c4cdb164aa71f7aa9fbf88be18886d1936 Mon Sep 17 00:00:00 2001
-From: Benjamin Otte <otte@redhat.com>
-Date: Tue, 7 Feb 2012 18:01:25 +1000
-Subject: [PATCH] dix: fix an out-of-memory crash
-
-Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- dix/inpututils.c |    3 +++
- 1 files changed, 3 insertions(+), 0 deletions(-)
-
-diff --git a/dix/inpututils.c b/dix/inpututils.c
-index d279c1d..9e0c551 100644
---- a/dix/inpututils.c
-+++ b/dix/inpututils.c
-@@ -432,6 +432,9 @@ valuator_mask_new(int num_valuators)
-      * flying-car future, when we can dynamically alloc the masks and are
-      * not constrained by signals, we can start using num_valuators */
-     ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
-+    if (mask == NULL)
-+        return NULL;
-+
-     mask->last_bit = -1;
-     return mask;
- }
--- 
-1.7.8.3
-
diff --git a/debian/patches/609-Xi-handle-new-XIAllowEvents-request-in-inputproto-2..patch b/debian/patches/609-Xi-handle-new-XIAllowEvents-request-in-inputproto-2..patch
deleted file mode 100644 (file)
index 7f82ae1..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-From ceb026c6a6f1eea8b34e745f06f1ebcd652c0ba1 Mon Sep 17 00:00:00 2001
-From: Peter Hutterer <peter.hutterer@who-t.net>
-Date: Fri, 27 Jan 2012 12:41:09 +1000
-Subject: [PATCH] Xi: handle new XIAllowEvents request in inputproto 2.1.99.6
-
-grab_window and touchid were removed from the struct for ABI compatibility
-reasons, we need to pull in the new, XI 2.2-specific struct.
-
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
----
- Xi/xiallowev.c |   41 +++++++++++++++++++++++++++++++++++------
- configure.ac   |    2 +-
- 2 files changed, 36 insertions(+), 7 deletions(-)
-
-Index: xorg-server/Xi/xiallowev.c
-===================================================================
---- xorg-server.orig/Xi/xiallowev.c    2012-02-11 00:19:36.000000000 +0100
-+++ xorg-server/Xi/xiallowev.c 2012-02-11 00:20:41.372346001 +0100
-@@ -41,6 +41,7 @@
- #include <X11/extensions/XI2proto.h>
- #include "exglobals.h" /* BadDevice */
-+#include "exevents.h"
- #include "xiallowev.h"
- int
-@@ -53,8 +54,12 @@ SProcXIAllowEvents(ClientPtr client)
-     swaps(&stuff->length, n);
-     swaps(&stuff->deviceid, n);
-     swapl(&stuff->time, n);
--    /* FIXME swap touchid */
--    /* FIXME swap window */
-+    if (stuff->length > 3)
-+    {
-+        xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq*)stuff;
-+        swapl(&req_xi22->touchid, n);
-+        swapl(&req_xi22->grab_window, n);
-+    }
-     return ProcXIAllowEvents(client);
- }
-@@ -65,9 +70,21 @@ ProcXIAllowEvents(ClientPtr client)
-     TimeStamp time;
-     DeviceIntPtr dev;
-     int ret = Success;
--
--    REQUEST(xXIAllowEventsReq);
--    /* FIXME: check request length, 12 for XI 2.0+, 20 for XI 2.2+ */
-+    XIClientPtr xi_client;
-+    Bool have_xi22 = FALSE;
-+    REQUEST(xXI2_2AllowEventsReq);
-+
-+    xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
-+
-+    if (version_compare(xi_client->major_version,
-+                        xi_client->minor_version, 2, 2) >= 0)
-+    {
-+        REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq);
-+        have_xi22 = TRUE;
-+    } else
-+    {
-+        REQUEST_SIZE_MATCH(xXIAllowEventsReq);
-+    }
-     ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
-     if (ret != Success)
-@@ -99,8 +116,20 @@ ProcXIAllowEvents(ClientPtr client)
-       break;
-     case XIRejectTouch:
-     case XIAcceptTouch:
--        ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
--                                stuff->grab_window, &client->errorValue);
-+        {
-+            int rc;
-+            WindowPtr win;
-+
-+            if (!have_xi22)
-+                return BadValue;
-+
-+            rc = dixLookupWindow(&win, stuff->grab_window, client, DixReadAccess);
-+            if (rc != Success)
-+                return rc;
-+
-+            ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
-+                                    stuff->grab_window, &client->errorValue);
-+        }
-         break;
-     default:
-       client->errorValue = stuff->mode;
-Index: xorg-server/configure.ac
-===================================================================
---- xorg-server.orig/configure.ac      2012-02-11 00:19:36.000000000 +0100
-+++ xorg-server/configure.ac   2012-02-11 00:20:18.960345999 +0100
-@@ -790,7 +790,7 @@ WINDOWSWMPROTO="windowswmproto"
- APPLEWMPROTO="applewmproto >= 1.4"
- dnl Core modules for most extensions, et al.
--SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 2.1.99.5] [kbproto >= 1.0.3] fontsproto"
-+SDK_REQUIRED_MODULES="[xproto >= 7.0.22] [randrproto >= 1.2.99.3] [renderproto >= 0.11] [xextproto >= 7.1.99] [inputproto >= 2.1.99.6] [kbproto >= 1.0.3] fontsproto"
- # Make SDK_REQUIRED_MODULES available for inclusion in xorg-server.pc
- AC_SUBST(SDK_REQUIRED_MODULES)
diff --git a/debian/patches/610-Fix-scrolling.patch b/debian/patches/610-Fix-scrolling.patch
deleted file mode 100644 (file)
index 2a9bde7..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-Return-Path: <xorg-devel-bounces+chase.douglas=canonical.com@lists.x.org>\r
-X-Original-To: cndougla@mail.canonical.com\r
-Delivered-To: cndougla@mail.canonical.com\r
-Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145])\r
-       by grenadilla.canonical.com (Postfix) with ESMTP id 06AB914721B9\r
-       for <cndougla@mail.canonical.com>; Fri, 10 Feb 2012 17:11:13 +0000 (UTC)\r
-Received: from cluster-e.mailcontrol.com (cluster-e.mailcontrol.com [85.115.58.190])\r
-       by fiordland.canonical.com (Postfix) with ESMTP id EEEDFA183BE\r
-       for <chase.douglas@cleanmail.canonical.com>; Fri, 10 Feb 2012 17:11:12 +0000 (UTC)\r
-Received: from arctowski.canonical.com (arctowski.canonical.com [91.189.94.158])\r
-       by rly08e.srv.mailcontrol.com (MailControl) with ESMTP id q1AHBB8v013234\r
-       for <chase.douglas@cleanmail.canonical.com>; Fri, 10 Feb 2012 17:11:11 GMT\r
-Received: from fiordland.canonical.com ([91.189.94.145])\r
-       by arctowski.canonical.com with esmtp (Exim 4.71)\r
-       (envelope-from <xorg-devel-bounces+chase.douglas=canonical.com@lists.x.org>)\r
-       id 1Rvu07-0008BT-Bu\r
-       for chase.douglas@cleanmail.canonical.com; Fri, 10 Feb 2012 17:11:11 +0000\r
-Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177])\r
-       by fiordland.canonical.com (Postfix) with ESMTP id 007A4A183C9\r
-       for <chase.douglas@canonical.com>; Fri, 10 Feb 2012 17:11:11 +0000 (UTC)\r
-Received: from gabe.freedesktop.org (localhost [127.0.0.1])\r
-       by gabe.freedesktop.org (Postfix) with ESMTP id 7E3AAA0D8B\r
-       for <chase.douglas@canonical.com>; Fri, 10 Feb 2012 09:11:10 -0800 (PST)\r
-X-Original-To: xorg-devel@lists.freedesktop.org\r
-Delivered-To: xorg-devel@lists.freedesktop.org\r
-Received: from mail.clearchain.com (leo.clearchain.com [199.73.29.74])\r
-       by gabe.freedesktop.org (Postfix) with ESMTP id 75D04A0DA7\r
-       for <xorg-devel@lists.freedesktop.org>;\r
-       Fri, 10 Feb 2012 09:10:29 -0800 (PST)\r
-Received: from leo.clearchain.com (localhost [127.0.0.1])\r
-       by mail.clearchain.com (8.14.5/8.14.5) with ESMTP id q1AHARrY005234\r
-       (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO)\r
-       for <xorg-devel@lists.freedesktop.org>;\r
-       Sat, 11 Feb 2012 03:40:27 +1030 (CST)\r
-       (envelope-from peter.hutterer@who-t.net)\r
-Received: (from whot@localhost)\r
-       by leo.clearchain.com (8.14.5/8.14.5/Submit) id q1AHARTs005232\r
-       for xorg-devel@lists.freedesktop.org;\r
-       Sat, 11 Feb 2012 03:40:27 +1030 (CST)\r
-       (envelope-from peter.hutterer@who-t.net)\r
-X-Authentication-Warning: leo.clearchain.com: whot set sender to\r
-       peter.hutterer@who-t.net using -f\r
-Date: Sat, 11 Feb 2012 03:12:28 +1000\r
-From: Peter Hutterer <peter.hutterer@who-t.net>\r
-To: "X.Org Devel List" <xorg-devel@lists.freedesktop.org>\r
-Subject: [PATCH] dix: reset last.scroll when resetting the valuator (#45611)\r
-Message-ID: <20120210171228.GA5823@yabbi.redhat.com>\r
-MIME-Version: 1.0\r
-Content-Disposition: inline\r
-User-Agent: Mutt/1.5.21 (2010-09-15)\r
-X-Greylist: Sender is SPF-compliant, not delayed by milter-greylist-4.0.1\r
-       (mail.clearchain.com [127.0.0.1]);\r
-       Sat, 11 Feb 2012 03:40:28 +1030 (CST)\r
-X-BeenThere: xorg-devel@lists.x.org\r
-X-Mailman-Version: 2.1.11\r
-Precedence: list\r
-List-Id: "X.Org development list" <xorg-devel.lists.x.org>\r
-List-Unsubscribe: <http://lists.x.org/mailman/options/xorg-devel>,\r
-       <mailto:xorg-devel-request@lists.x.org?subject=unsubscribe>\r
-List-Archive: <http://lists.x.org/archives/xorg-devel>\r
-List-Post: <mailto:xorg-devel@lists.x.org>\r
-List-Help: <mailto:xorg-devel-request@lists.x.org?subject=help>\r
-List-Subscribe: <http://lists.x.org/mailman/listinfo/xorg-devel>,\r
-       <mailto:xorg-devel-request@lists.x.org?subject=subscribe>\r
-Content-Type: text/plain; charset="us-ascii"\r
-Content-Transfer-Encoding: 7bit\r
-Sender: xorg-devel-bounces+chase.douglas=canonical.com@lists.x.org\r
-Errors-To: xorg-devel-bounces+chase.douglas=canonical.com@lists.x.org\r
-X-Mailcontrol-Inbound: uq3drnD2P+ps5SfEb0fvr78+NoP1DHBZwGqKpaXB2eTgNv8D6KLIxb8+NoP1DHBZ8VSaBg0k0xw=\r
-X-Spam-Score: -0.5\r
-X-Scanned-By: MailControl 7.6.6 (www.mailcontrol.com) on 10.69.0.118\r
-\r
-last.scroll remained on the last-submitted scrolling value but last.valuator\r
-was changed whenever the slave device changed. The first scrolling delta\r
-after a switch was then calculated as (last.scroll - new abs value), causing\r
-erroneous scrolling events.\r
-\r
-Test case:\r
-- synaptics with a scrolling method enabled, other device with 3+ axes (e.g.\r
-  wacom)\r
-- scroll on touchpad\r
-- use other device\r
-- scroll on touchpad\r
-\r
-The second scroll caused erroneous button press/release events.\r
-\r
-X.Org Bug 45611 <http://bugs.freedesktop.org/show_bug.cgi?id=45611>\r
-\r
-Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>\r
-Tested-by: Timo Aaltonen <timo.aaltonen@canonical.com>\r
----\r
- dix/getevents.c |    2 ++\r
- 1 files changed, 2 insertions(+), 0 deletions(-)\r
-\r
-diff --git a/dix/getevents.c b/dix/getevents.c\r
-index 7678aa1..6ea4ba0 100644\r
---- a/dix/getevents.c\r
-+++ b/dix/getevents.c\r
-@@ -360,6 +360,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)\r
-             if (i >= lastSlave->valuator->numAxes)\r
-             {\r
-                 pDev->last.valuators[i] = 0;\r
-+                valuator_mask_set_double(pDev->last.scroll, i, 0);\r
-             }\r
-             else\r
-             {\r
-@@ -367,6 +368,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)\r
-                 val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,\r
-                                           pDev->valuator->axes + i, 0, 0);\r
-                 pDev->last.valuators[i] = val;\r
-+                valuator_mask_set_double(pDev->last.scroll, i, val);\r
-             }\r
-         }\r
-     }\r
--- \r
-1.7.7.5\r
-_______________________________________________\r
-xorg-devel@lists.x.org: X.Org development\r
-Archives: http://lists.x.org/archives/xorg-devel\r
-Info: http://lists.x.org/mailman/listinfo/xorg-devel\r
-\r
diff --git a/debian/patches/611-Fix-touch-punt-crash.patch b/debian/patches/611-Fix-touch-punt-crash.patch
deleted file mode 100644 (file)
index 8b4bac2..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-From 832d940d28f506e2adcc9b678a315edbaec9d353 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@ubuntu.com>
-Date: Mon, 13 Feb 2012 11:55:57 -0800
-Subject: [PATCH] Don't dereference a touch after it has been ended when
- punting to next owner
-
-In this case, we have ended the touch because the last owner has
-rejected it. We need to return from the function right now so we don't
-attempt to dereference another touch client for early acceptance
-processing.
-
-Signed-off-by: Chase Douglas <chase.douglas@ubuntu.com>
----
- Xi/exevents.c |    1 +
- 1 files changed, 1 insertions(+), 0 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index 1ecc3ba..9bc8dfb 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -1164,6 +1164,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
-     {
-         EmitTouchEnd(dev, ti, 0, 0);
-         TouchEndTouch(dev, ti);
-+        return;
-     }
-     if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
--- 
-1.7.9
-
diff --git a/debian/patches/612-Fix-vcp-touches-corruption.patch b/debian/patches/612-Fix-vcp-touches-corruption.patch
deleted file mode 100644 (file)
index 53bf3e1..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-From 347e785fa6177b5cac29d6c361e7c54289006a7c Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Mon, 13 Feb 2012 15:44:41 -0800
-Subject: [PATCH 1/2] Don't clobber virtual core pointer touches array length
-
-When copying the touch class, the VCP has its own touches array. The
-length of this array must be kept alongside the array itself or we get
-memory corruption.
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
----
- Xi/exevents.c |    9 ++++++---
- 1 files changed, 6 insertions(+), 3 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index 671c051..51f991c 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -671,7 +671,8 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
-     if (from->touch)
-     {
--        TouchPointInfoPtr tmp;
-+        TouchPointInfoPtr to_touches_array_tmp;
-+        int to_num_touches_tmp;
-         if (!to->touch)
-         {
-             classes = to->unused_classes;
-@@ -692,9 +693,11 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
-             } else
-                 classes->touch = NULL;
-         }
--        tmp = to->touch->touches;
-+        to_touches_array_tmp = to->touch->touches;
-+        to_num_touches_tmp = to->touch->num_touches;
-         memcpy(to->touch, from->touch, sizeof(TouchClassRec));
--        to->touch->touches = tmp;
-+        to->touch->touches = to_touches_array_tmp;
-+        to->touch->num_touches = to_num_touches_tmp;
-         to->touch->sourceid = from->id;
-     } else if (to->touch)
-     {
--- 
-1.7.9
-
diff --git a/debian/patches/613-Keep-vcp-touch-class.patch b/debian/patches/613-Keep-vcp-touch-class.patch
deleted file mode 100644 (file)
index 03f5e5d..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-From 9c672e0fff52e99c3cc2a1cb1d50147c13663152 Mon Sep 17 00:00:00 2001
-From: Chase Douglas <chase.douglas@canonical.com>
-Date: Mon, 13 Feb 2012 15:48:18 -0800
-Subject: [PATCH 2/2] Keep virtual core pointer touch class around if new
- slave doesn't have one
-
-The VCP may have active touch grabs. The touch records must be kept so
-these touch grabs may be accepted/rejected in the future. This means the
-touch class list will not represent the touch class of the attached
-slave device if it does not have a touch class, but we already were
-breaking that assumption by keeping a separate touches array for the
-VCP.
-
-Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
----
- Xi/exevents.c |    9 +++------
- 1 files changed, 3 insertions(+), 6 deletions(-)
-
-diff --git a/Xi/exevents.c b/Xi/exevents.c
-index 51f991c..069a52c 100644
---- a/Xi/exevents.c
-+++ b/Xi/exevents.c
-@@ -699,13 +699,10 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
-         to->touch->touches = to_touches_array_tmp;
-         to->touch->num_touches = to_num_touches_tmp;
-         to->touch->sourceid = from->id;
--    } else if (to->touch)
--    {
--        ClassesPtr classes;
--        classes = to->unused_classes;
--        classes->touch = to->touch;
--        to->touch      = NULL;
-     }
-+    /* Don't remove touch class if from->touch is non-existent. The to device
-+     * may have an active touch grab, so we need to keep the touch class record
-+     * around. */
- }
- /**
--- 
-1.7.9
-
index dbd3796d71f862e068a2a3214383d4be2ba838ea..fde46538aba6b566026b7647ee50d89859878bad 100644 (file)
 
 # Temporary, until it's reviewed & accepted upstream
 500_pointer_barrier_thresholds.diff
-
-# Temporary, until they are merged upstream
-600-Revert-dix-deduplicate-callers-of-DeliverDeviceEvent.patch
-601-Store-window-pointer-in-touch-listener-record.patch
-602-Factor-out-TouchEnd-generation-and-delivery.patch
-603-Export-TouchEventRejected-as-TouchRejected.patch
-604-Move-AllowTouch-to-dix-touch.c-and-rename-to-TouchAc.patch
-605-Check-for-proper-window-ID-when-processing-touch-all.patch
-606-Implement-early-touch-reject.patch
-607-Implement-touch-early-accept.patch
-608-dix-fix-an-out-of-memory-crash.patch
-609-Xi-handle-new-XIAllowEvents-request-in-inputproto-2..patch
-610-Fix-scrolling.patch
-611-Fix-touch-punt-crash.patch
-612-Fix-vcp-touches-corruption.patch
-613-Keep-vcp-touch-class.patch
+501_touch_accept_end.patch
+502_indirect_touch_window_set.patch
index 04d7fb59b0408bf2d2aee51857ca61e9d54d436e..01952551cd0906e08d47d955c15822568ba21693 100644 (file)
@@ -3449,21 +3449,16 @@ XineramaWarpPointer(ClientPtr client)
 {
     WindowPtr  dest = NULL;
     int                x, y, rc;
-    DeviceIntPtr dev;
-    SpritePtr   pSprite;
+    SpritePtr   pSprite = PickPointer(client)->spriteInfo->sprite;
 
     REQUEST(xWarpPointerReq);
 
+
     if (stuff->dstWid != None) {
        rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
        if (rc != Success)
            return rc;
     }
-
-    /* Post through the XTest device */
-    dev = PickPointer(client);
-    dev = GetXTestDevice(dev);
-    pSprite = dev->spriteInfo->sprite;
     x = pSprite->hotPhys.x;
     y = pSprite->hotPhys.y;
 
@@ -3513,9 +3508,9 @@ XineramaWarpPointer(ClientPtr client)
     else if (y >= pSprite->physLimits.y2)
        y = pSprite->physLimits.y2 - 1;
     if (pSprite->hotShape)
-       ConfineToShape(dev, pSprite->hotShape, &x, &y);
+       ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
 
-    XineramaSetCursorPosition(dev, x, y, TRUE);
+    XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
 
     return Success;
 }
@@ -3533,7 +3528,7 @@ ProcWarpPointer(ClientPtr client)
     WindowPtr  dest = NULL;
     int                x, y, rc;
     ScreenPtr  newScreen;
-    DeviceIntPtr dev, tmp, xtest_dev = NULL;
+    DeviceIntPtr dev, tmp;
     SpritePtr   pSprite;
 
     REQUEST(xWarpPointerReq);
@@ -3546,13 +3541,11 @@ ProcWarpPointer(ClientPtr client)
            rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
            if (rc != Success)
                return rc;
-            if (IsXTestDevice(tmp, dev))
-                xtest_dev = tmp;
        }
     }
 
-    /* Use the XTest device to actually move the pointer */
-    dev = xtest_dev;
+    if (dev->lastSlave)
+        dev = dev->lastSlave;
     pSprite = dev->spriteInfo->sprite;
 
 #ifdef PANORAMIX
@@ -4266,7 +4259,6 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
     if (grab->ownerEvents)
     {
        WindowPtr focus;
-       WindowPtr win;
 
         /* Hack: Some pointer device have a focus class. So we need to check
          * for the type of event, to see if we really want to deliver it to
@@ -4283,16 +4275,15 @@ DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
        else
            focus = PointerRootWin;
        if (focus == PointerRootWin)
-       {
-           win = pSprite->win;
-           focus = NullWindow;
-       } else if (focus && (focus == pSprite->win ||
-                   IsParent(focus, pSprite->win)))
-           win = pSprite->win;
+           deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
+                                             NullWindow, thisDev);
+       else if (focus && (focus == pSprite->win ||
+                    IsParent(focus, pSprite->win)))
+           deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
+                                            thisDev);
        else if (focus)
-           win = focus;
-
-       deliveries = DeliverDeviceEvents(win, event, grab, focus, thisDev);
+           deliveries = DeliverDeviceEvents(focus, event, grab, focus,
+                                            thisDev);
     }
     if (!deliveries)
     {
index 7678aa1f2dde73cf93b9f8ed2d702dfabeebafb4..306d0ff09af75dcdece51a875b0d1a17adfe07ec 100644 (file)
@@ -360,6 +360,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
             if (i >= lastSlave->valuator->numAxes)
             {
                 pDev->last.valuators[i] = 0;
+                valuator_mask_set_double(pDev->last.scroll, i, 0);
             }
             else
             {
@@ -367,6 +368,7 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
                 val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
                                           pDev->valuator->axes + i, 0, 0);
                 pDev->last.valuators[i] = val;
+                valuator_mask_set_double(pDev->last.scroll, i, val);
             }
         }
     }
@@ -838,10 +840,15 @@ scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
     ScreenPtr scr = miPointerGetScreen(dev);
     double x, y;
 
-    BUG_WARN(!dev->valuator);
-    BUG_WARN(dev->valuator->numAxes < 2);
+    BUG_WARN(!dev->valuator || dev->valuator->numAxes < 2);
     if (!dev->valuator || dev->valuator->numAxes < 2)
+    {
+        /* if we have no axes, last.valuators must be in screen coords
+         * anyway */
+        *devx = *screenx = dev->last.valuators[0];
+        *devy = *screeny = dev->last.valuators[1];
         return scr;
+    }
 
     if (valuator_mask_isset(mask, 0))
         x = valuator_mask_get_double(mask, 0);
@@ -1491,8 +1498,6 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
 {
     CARD32 ms = GetTimeInMillis();
     int num_events = 0, nev_tmp;
-    int h_scroll_axis = pDev->valuator->h_scroll_axis;
-    int v_scroll_axis = pDev->valuator->v_scroll_axis;
     ValuatorMask mask;
     ValuatorMask scroll;
     int i;
@@ -1517,6 +1522,14 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
     {
         double val, adj;
         int axis;
+        int h_scroll_axis = -1;
+        int v_scroll_axis = -1;
+
+        if (pDev->valuator)
+        {
+            h_scroll_axis = pDev->valuator->h_scroll_axis;
+            v_scroll_axis = pDev->valuator->v_scroll_axis;
+        }
 
         /* Up is negative on valuators, down positive */
         switch (buttons) {
index 1fb9a8a5bb5d4f4e73343a54a5e0a4c4bd1dc09d..09eef252741a632e3feebc5101d6f87222cfbc58 100644 (file)
@@ -431,6 +431,9 @@ valuator_mask_new(int num_valuators)
      * flying-car future, when we can dynamically alloc the masks and are
      * not constrained by signals, we can start using num_valuators */
     ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
+    if (mask == NULL)
+        return NULL;
+
     mask->last_bit = -1;
     return mask;
 }
index db0bf334ac4ddf53e0c3719b91e16dd5ef05c668..d04801c86ad327c70449aaeec747dada90b9acf2 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "eventstr.h"
 #include "exevents.h"
+#include "exglobals.h"
 #include "inpututils.h"
 #include "eventconvert.h"
 #include "windowstr.h"
@@ -697,12 +698,14 @@ TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource)
  */
 void
 TouchAddListener(TouchPointInfoPtr ti, XID resource, enum InputLevel level,
-                 enum TouchListenerType type, enum TouchListenerState state)
+                 enum TouchListenerType type, enum TouchListenerState state,
+                 WindowPtr window)
 {
     ti->listeners[ti->num_listeners].listener = resource;
     ti->listeners[ti->num_listeners].level = level;
     ti->listeners[ti->num_listeners].state = state;
     ti->listeners[ti->num_listeners].type = type;
+    ti->listeners[ti->num_listeners].window = window;
     ti->num_listeners++;
 }
 
@@ -753,7 +756,7 @@ TouchAddGrabListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
     }
 
     TouchAddListener(ti, grab->resource, grab->grabtype,
-                     type, LISTENER_AWAITING_BEGIN);
+                     type, LISTENER_AWAITING_BEGIN, grab->window);
     ti->num_grabs++;
 }
 
@@ -814,7 +817,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
                 TouchEventHistoryAllocate(ti);
 
             TouchAddListener(ti, iclients->resource, XI2,
-                             type, LISTENER_AWAITING_BEGIN);
+                             type, LISTENER_AWAITING_BEGIN, win);
             return TRUE;
         }
     }
@@ -830,7 +833,8 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
             TouchEventHistoryAllocate(ti);
             TouchAddListener(ti, iclients->resource, XI,
-                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
+                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
+                             win);
             return TRUE;
         }
     }
@@ -845,7 +849,8 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
         {
             TouchEventHistoryAllocate(ti);
             TouchAddListener(ti, win->drawable.id, CORE,
-                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
+                             LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
+                             win);
             return TRUE;
         }
 
@@ -857,7 +862,7 @@ TouchAddRegularListener(DeviceIntPtr dev, TouchPointInfoPtr ti,
 
             TouchEventHistoryAllocate(ti);
             TouchAddListener(ti, iclients->resource, CORE,
-                             type, LISTENER_AWAITING_BEGIN);
+                             type, LISTENER_AWAITING_BEGIN, win);
             return TRUE;
         }
     }
@@ -980,3 +985,59 @@ TouchListenerGone(XID resource)
 
     FreeEventList(events, GetMaximumEventsNum());
 }
+
+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;
+
+    if (!dev->touch)
+    {
+        *error = dev->id;
+        return BadDevice;
+    }
+
+    ti = TouchFindByClientID(dev, touchid);
+    if (!ti)
+    {
+        *error = touchid;
+        return BadValue;
+    }
+
+    for (i = 0; i < ti->num_listeners; i++)
+    {
+        if (CLIENT_ID(ti->listeners[i].listener) == client->index &&
+            ti->listeners[i].window->drawable.id == grab_window)
+            break;
+    }
+    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;
+}
index 31acb30eaa327a9a1c84ec841a88a6d3ff56c7c8..fb2ef274c5318a83f549c7e6bf423dc965ec5b99 100644 (file)
@@ -323,6 +323,13 @@ SendEventToAllWindows(
         xEvent *               /* ev */,
         int                    /* count */);
 
+extern void
+TouchRejected(
+        DeviceIntPtr           /* sourcedev */,
+        TouchPointInfoPtr      /* ti */,
+        XID                    /* resource */,
+        TouchOwnershipEvent *  /* ev */);
+
 extern _X_HIDDEN void XI2EventSwap(
         xGenericEvent  *              /* from */,
         xGenericEvent  *              /* to */);
index 049eba861913667e6dc29599777468205df0a556..1015a747dea59ef76075507236d0057526a70c9d 100644 (file)
@@ -587,6 +587,8 @@ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs);
 enum TouchListenerState{
     LISTENER_AWAITING_BEGIN = 0,   /**< Waiting for a TouchBegin event */
     LISTENER_AWAITING_OWNER,       /**< Waiting for a TouchOwnership event */
+    LISTENER_EARLY_ACCEPT,         /**< Waiting for ownership, has already
+                                        accepted */
     LISTENER_IS_OWNER,             /**< Is the current owner */
     LISTENER_HAS_END,              /**< Has already received the end event */
 };
@@ -617,7 +619,8 @@ extern void TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev);
 extern void TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource);
 extern Bool TouchResourceIsOwner(TouchPointInfoPtr ti, XID resource);
 extern void TouchAddListener(TouchPointInfoPtr ti, XID resource, enum InputLevel level,
-                                     enum TouchListenerType type, enum TouchListenerState state);
+                             enum TouchListenerType type, enum TouchListenerState state,
+                             WindowPtr window);
 extern Bool TouchRemoveListener(TouchPointInfoPtr ti, XID resource);
 extern void TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev);
 extern Bool TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
@@ -628,6 +631,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 TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode,
+                             uint32_t touchid, Window grab_window, XID *error);
 
 /* misc event helpers */
 extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
index c3297db64bf4223bbb359b014a7b9f1a5f95e82d..4e28bc71d7c56b8f8d488ac795cd096bc59f02af 100644 (file)
@@ -314,6 +314,7 @@ typedef struct _TouchPointInfo {
         enum TouchListenerType type;
         enum TouchListenerState state;
         enum InputLevel level;      /* matters only for emulating touches */
+        WindowPtr window;
     } *listeners;
     int         num_listeners;
     int         num_grabs;          /* number of open grabs on this touch