summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e6d73b5)
raw | patch | inline | side by side (parent: e6d73b5)
author | Christopher James Halse Rogers <raof@ubuntu.com> | |
Fri, 9 Mar 2012 08:16:02 +0000 (19:16 +1100) | ||
committer | Xavier Boudet <x-boudet@ti.com> | |
Thu, 15 Mar 2012 11:10:47 +0000 (11:10 +0000) |
30 files changed:
diff --git a/ChangeLog b/ChangeLog
index a3980c30e9376e5a68352a49f08b3495a65cd569..2415e4ff082654c4e0e9eaf7a79901c257273e89 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+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
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 6b2db4b5988060da60ffb61706edabe3576732db..f390f67393b2965d6a5ae3da44ebefff245534dc 100644 (file)
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
if (from->touch)
{
- TouchPointInfoPtr tmp;
+ TouchClassPtr t, f;
if (!to->touch)
{
classes = to->unused_classes;
} 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);
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
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);
}
/**
{
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);
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)
{
diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c
index 207c5cb07a8c1178f1668801bb11038837a8888a..6b9c795f42654899df4f79d1966901ab9a455b3e 100644 (file)
--- a/Xi/xiallowev.c
+++ b/Xi/xiallowev.c
#include <X11/extensions/XI2proto.h>
#include "exglobals.h" /* BadDevice */
+#include "exevents.h"
#include "xiallowev.h"
int
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
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)
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;
diff --git a/configure.ac b/configure.ac
index 6c83be9829c5127d8ea550bf732f7c8ad8e6154b..5e29b2a4715685263a98cb1738e2ba6ba0dbae35 100644 (file)
--- a/configure.ac
+++ b/configure.ac
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/changelog b/debian/changelog
index 1fbc21eb1def242fa3b7e06a54dfa66422290c1c..3756386efe4558065d5d36f33a7cfe738b5b2c93 100644 (file)
--- a/debian/changelog
+++ b/debian/changelog
+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:
diff --git a/debian/patches/500_pointer_barrier_thresholds.diff b/debian/patches/500_pointer_barrier_thresholds.diff
index ad8a180499bd66864ff2486d4b9de64ca4fe8672..9e255adb7edd3a5ae40f1d9308be7ad5298a0975 100644 (file)
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
/* 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;
} 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);
+ }
+}
+
+ *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;
/* 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.
*/
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) {
+ 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;
}
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) {
+ nearest->hit = TRUE;
+ }
+
-+ SendBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
++ QueueBarrierEvent(cs, nearest, *x, *y, velocity, threshold_exceeded);
}
}
+
}
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))
+ 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);
}
static int
CursorFreeBarrier(void *data, XID id)
{
-@@ -1421,6 +1629,118 @@
+@@ -1421,6 +1691,118 @@
return ProcXFixesVector[stuff->xfixesReqType](client);
}
+ 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);
+ }
+
+
+ if (!AddResource (eventClient->resource, PointerBarrierClientType, eventClient))
+ return BadAlloc;
-+
++
+ return Success;
+}
+
+ }
+
+ barrier->releaseEventID = stuff->event_id;
-+
++
+ return Success;
+}
+
Bool
XFixesCursorInit (void)
{
-@@ -1441,6 +1761,7 @@
+@@ -1441,6 +1823,7 @@
if (!cs)
return FALSE;
list_init(&cs->barriers);
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");
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 */
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_
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);
+ XID resource;
+ struct list entry;
+};
-+
-+
+
struct PointerBarrier {
+ XID barrier;
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"
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;
/* 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.
+ */
/* 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
--- /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
--- /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
+++ /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
-
diff --git a/debian/patches/series b/debian/patches/series
index dbd3796d71f862e068a2a3214383d4be2ba838ea..fde46538aba6b566026b7647ee50d89859878bad 100644 (file)
--- a/debian/patches/series
+++ b/debian/patches/series
# 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
diff --git a/dix/events.c b/dix/events.c
index 04d7fb59b0408bf2d2aee51857ca61e9d54d436e..01952551cd0906e08d47d955c15822568ba21693 100644 (file)
--- a/dix/events.c
+++ b/dix/events.c
{
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;
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;
}
WindowPtr dest = NULL;
int x, y, rc;
ScreenPtr newScreen;
- DeviceIntPtr dev, tmp, xtest_dev = NULL;
+ DeviceIntPtr dev, tmp;
SpritePtr pSprite;
REQUEST(xWarpPointerReq);
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
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
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)
{
diff --git a/dix/getevents.c b/dix/getevents.c
index 7678aa1f2dde73cf93b9f8ed2d702dfabeebafb4..306d0ff09af75dcdece51a875b0d1a17adfe07ec 100644 (file)
--- a/dix/getevents.c
+++ b/dix/getevents.c
if (i >= lastSlave->valuator->numAxes)
{
pDev->last.valuators[i] = 0;
+ valuator_mask_set_double(pDev->last.scroll, i, 0);
}
else
{
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);
}
}
}
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);
{
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;
{
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) {
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 1fb9a8a5bb5d4f4e73343a54a5e0a4c4bd1dc09d..09eef252741a632e3feebc5101d6f87222cfbc58 100644 (file)
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
* 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;
}
diff --git a/dix/touch.c b/dix/touch.c
index db0bf334ac4ddf53e0c3719b91e16dd5ef05c668..d04801c86ad327c70449aaeec747dada90b9acf2 100644 (file)
--- a/dix/touch.c
+++ b/dix/touch.c
#include "eventstr.h"
#include "exevents.h"
+#include "exglobals.h"
#include "inpututils.h"
#include "eventconvert.h"
#include "windowstr.h"
*/
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++;
}
}
TouchAddListener(ti, grab->resource, grab->grabtype,
- type, LISTENER_AWAITING_BEGIN);
+ type, LISTENER_AWAITING_BEGIN, grab->window);
ti->num_grabs++;
}
TouchEventHistoryAllocate(ti);
TouchAddListener(ti, iclients->resource, XI2,
- type, LISTENER_AWAITING_BEGIN);
+ type, LISTENER_AWAITING_BEGIN, win);
return TRUE;
}
}
TouchEventHistoryAllocate(ti);
TouchAddListener(ti, iclients->resource, XI,
- LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
+ LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
+ win);
return TRUE;
}
}
{
TouchEventHistoryAllocate(ti);
TouchAddListener(ti, win->drawable.id, CORE,
- LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN);
+ LISTENER_POINTER_REGULAR, LISTENER_AWAITING_BEGIN,
+ win);
return TRUE;
}
TouchEventHistoryAllocate(ti);
TouchAddListener(ti, iclients->resource, CORE,
- type, LISTENER_AWAITING_BEGIN);
+ type, LISTENER_AWAITING_BEGIN, win);
return TRUE;
}
}
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;
+}
diff --git a/include/exevents.h b/include/exevents.h
index 31acb30eaa327a9a1c84ec841a88a6d3ff56c7c8..fb2ef274c5318a83f549c7e6bf423dc965ec5b99 100644 (file)
--- a/include/exevents.h
+++ b/include/exevents.h
xEvent * /* ev */,
int /* count */);
+extern void
+TouchRejected(
+ DeviceIntPtr /* sourcedev */,
+ TouchPointInfoPtr /* ti */,
+ XID /* resource */,
+ TouchOwnershipEvent * /* ev */);
+
extern _X_HIDDEN void XI2EventSwap(
xGenericEvent * /* from */,
xGenericEvent * /* to */);
diff --git a/include/input.h b/include/input.h
index 049eba861913667e6dc29599777468205df0a556..1015a747dea59ef76075507236d0057526a70c9d 100644 (file)
--- a/include/input.h
+++ b/include/input.h
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 */
};
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,
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);
diff --git a/include/inputstr.h b/include/inputstr.h
index c3297db64bf4223bbb359b014a7b9f1a5f95e82d..4e28bc71d7c56b8f8d488ac795cd096bc59f02af 100644 (file)
--- a/include/inputstr.h
+++ b/include/inputstr.h
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