aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xi')
-rw-r--r--xorg-server/Xi/exevents.c160
-rw-r--r--xorg-server/Xi/xiallowev.c81
2 files changed, 120 insertions, 121 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index 6b2db4b59..1ecc3ba5a 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -1088,20 +1088,71 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
return TRUE;
}
+static void
+ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
+{
+ int rc;
+ ClientPtr client;
+ XID error;
+
+ rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient,
+ DixSendAccess);
+ if (rc != Success)
+ {
+ ErrorF("[Xi] Failed to lookup early accepting client.\n");
+ return;
+ }
+
+ if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
+ ti->listeners[0].window->drawable.id, &error) !=
+ Success)
+ ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
+}
+
/**
- * If the current owner has rejected the event, deliver the
- * TouchOwnership/TouchBegin to the next item in the sprite stack.
+ * Generate and deliver a TouchEnd event.
+ *
+ * @param dev The device to deliver the event for.
+ * @param ti The touch point record to deliver the event for.
+ * @param flags Internal event flags. The called does not need to provide
+ * TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure
+ * they are set appropriately.
+ * @param resource The client resource to deliver to, or 0 for all clients.
*/
static void
-TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
- TouchOwnershipEvent *ev)
+EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
{
InternalEvent *tel = InitEventList(GetMaximumEventsNum());
ValuatorMask *mask = valuator_mask_new(2);
int i, nev;
+ valuator_mask_set_double(mask, 0,
+ valuator_mask_get_double(ti->valuators, 0));
+ valuator_mask_set_double(mask, 1,
+ valuator_mask_get_double(ti->valuators, 1));
+
+ flags |= TOUCH_CLIENT_ID;
+ if (ti->emulate_pointer)
+ flags |= TOUCH_POINTER_EMULATED;
+ nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
+ for (i = 0; i < nev; i++)
+ DeliverTouchEvents(dev, ti, tel + i, resource);
+
+ valuator_mask_free(&mask);
+ FreeEventList(tel, GetMaximumEventsNum());
+}
+
+/**
+ * If the current owner has rejected the event, deliver the
+ * TouchOwnership/TouchBegin to the next item in the sprite stack.
+ */
+static void
+TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
+ TouchOwnershipEvent *ev)
+{
/* Deliver the ownership */
- if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
+ if (ti->listeners[0].state == LISTENER_AWAITING_OWNER ||
+ ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
@@ -1111,52 +1162,41 @@ 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());
+ if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT)
+ ActivateEarlyAccept(dev, ti);
}
-static void
-TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
- TouchOwnershipEvent *ev)
+/**
+ * Process a touch rejection.
+ *
+ * @param sourcedev The source device of the touch sequence.
+ * @param ti The touchpoint info record.
+ * @param resource The resource of the client rejecting the touch.
+ * @param ev TouchOwnership event to send. Set to NULL if no event should be
+ * sent.
+ */
+void
+TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
+ TouchOwnershipEvent *ev)
{
- InternalEvent *tel = InitEventList(GetMaximumEventsNum());
- ValuatorMask *mask = valuator_mask_new(2);
- Bool was_owner = (ev->resource == ti->listeners[0].listener);
+ Bool was_owner = (resource == ti->listeners[0].listener);
void *grab;
- int nev, i;
-
+ int i;
/* Send a TouchEnd event to the resource being removed, but only if they
* haven't received one yet already */
- if (ti->listeners[0].state != LISTENER_HAS_END)
+ for (i = 0; i < ti->num_listeners; i++)
{
- int flags;
- valuator_mask_set_double(mask, 0,
- valuator_mask_get_double(ti->valuators, 0));
- valuator_mask_set_double(mask, 1,
- valuator_mask_get_double(ti->valuators, 1));
-
- flags = TOUCH_CLIENT_ID|TOUCH_REJECT;
- if (ti->emulate_pointer)
- flags |= TOUCH_POINTER_EMULATED;
- nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask);
- for (i = 0; i < nev; i++)
- DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource);
+ if (ti->listeners[i].listener == resource)
+ {
+ if (ti->listeners[i].state != LISTENER_HAS_END)
+ EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
+ break;
+ }
}
/* If there are no other listeners left, and the touchpoint is pending
@@ -1164,26 +1204,22 @@ TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
if (ti->num_listeners == 1 && ti->pending_finish)
{
TouchEndTouch(sourcedev, ti);
- goto out;
+ return;
}
/* Remove the resource from the listener list, updating
* ti->num_listeners, as well as ti->num_grabs if it was a grab. */
- if (TouchRemoveListener(ti, ev->resource))
+ if (TouchRemoveListener(ti, resource))
{
- if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB,
+ if (dixLookupResourceByType(&grab, resource, RT_PASSIVEGRAB,
serverClient, DixGetAttrAccess) == Success)
ti->num_grabs--;
}
/* If the current owner was removed and there are further listeners, deliver
* the TouchOwnership or TouchBegin event to the new owner. */
- if (ti->num_listeners > 0 && was_owner)
+ if (ev && ti->num_listeners > 0 && was_owner)
TouchPuntToNextOwner(sourcedev, ti, ev);
-
-out:
- FreeEventList(tel, GetMaximumEventsNum());
- valuator_mask_free(&mask);
}
/**
@@ -1199,35 +1235,11 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
{
if (ev->reason == XIRejectTouch)
- TouchEventRejected(dev, ti, ev);
+ TouchRejected(dev, ti, ev->resource, ev);
else if (ev->reason == XIAcceptTouch) {
- int flags;
- int nev, i;
- ValuatorMask *mask;
-
- InternalEvent *tel = InitEventList(GetMaximumEventsNum());
-
- mask = valuator_mask_new(dev->valuator->numAxes);
- valuator_mask_set_double(mask, 0,
- valuator_mask_get_double(ti->valuators, 0));
- valuator_mask_set_double(mask, 1,
- valuator_mask_get_double(ti->valuators, 1));
-
- /* FIXME: what about early acceptance? a client may accept before it
- * owns the touch. */
-
/* The touch owner has accepted the touch. Send TouchEnd events to
* everyone else, and truncate the list of listeners. */
- flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID;
- if (ti->emulate_pointer)
- flags |= TOUCH_POINTER_EMULATED;
- nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd,
- flags, mask);
- for (i = 0; i < nev; i++)
- DeliverTouchEvents(dev, ti, tel + i, 0);
-
- FreeEventList(tel, GetMaximumEventsNum());
- valuator_mask_free(&mask);
+ EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
while (ti->num_listeners > 1)
TouchRemoveListener(ti, ti->listeners[1].listener);
diff --git a/xorg-server/Xi/xiallowev.c b/xorg-server/Xi/xiallowev.c
index a4b2f5782..d0856b656 100644
--- a/xorg-server/Xi/xiallowev.c
+++ b/xorg-server/Xi/xiallowev.c
@@ -41,6 +41,7 @@
#include <X11/extensions/XI2proto.h>
#include "exglobals.h" /* BadDevice */
+#include "exevents.h"
#include "xiallowev.h"
int
@@ -51,51 +52,14 @@ SProcXIAllowEvents(ClientPtr client)
swaps(&stuff->length);
swaps(&stuff->deviceid);
swapl(&stuff->time);
- /* 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);
+ swapl(&req_xi22->grab_window);
}
- /* 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
@@ -104,9 +68,21 @@ ProcXIAllowEvents(ClientPtr client)
TimeStamp time;
DeviceIntPtr dev;
int ret = Success;
+ XIClientPtr xi_client;
+ Bool have_xi22 = FALSE;
+ REQUEST(xXI2_2AllowEventsReq);
- REQUEST(xXIAllowEventsReq);
- /* FIXME: check request length, 12 for XI 2.0+, 20 for XI 2.2+ */
+ xi_client = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
+ if (version_compare(xi_client->major_version,
+ xi_client->minor_version, 2, 2) >= 0)
+ {
+ REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq);
+ have_xi22 = TRUE;
+ } else
+ {
+ REQUEST_SIZE_MATCH(xXIAllowEventsReq);
+ }
ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess);
if (ret != Success)
@@ -138,9 +114,20 @@ ProcXIAllowEvents(ClientPtr client)
break;
case XIRejectTouch:
case XIAcceptTouch:
- ret = AllowTouch(client, dev,
- stuff->mode, stuff->touchid,
- &client->errorValue);
+ {
+ int rc;
+ WindowPtr win;
+
+ if (!have_xi22)
+ return BadValue;
+
+ rc = dixLookupWindow(&win, stuff->grab_window, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ ret = TouchAcceptReject(client, dev, stuff->mode, stuff->touchid,
+ stuff->grab_window, &client->errorValue);
+ }
break;
default:
client->errorValue = stuff->mode;