aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/Xi/exevents.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/Xi/exevents.c')
-rw-r--r--xorg-server/Xi/exevents.c160
1 files changed, 86 insertions, 74 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);