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.c92
1 files changed, 70 insertions, 22 deletions
diff --git a/xorg-server/Xi/exevents.c b/xorg-server/Xi/exevents.c
index c05c22604..e9f02072a 100644
--- a/xorg-server/Xi/exevents.c
+++ b/xorg-server/Xi/exevents.c
@@ -1234,14 +1234,6 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID 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);
- CheckOldestTouch(sourcedev);
- 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, resource)) {
@@ -1254,6 +1246,8 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
* the TouchOwnership or TouchBegin event to the new owner. */
if (ev && ti->num_listeners > 0 && was_owner)
TouchPuntToNextOwner(sourcedev, ti, ev);
+ else if (ti->num_listeners == 0)
+ TouchEndTouch(sourcedev, ti);
CheckOldestTouch(sourcedev);
}
@@ -1273,9 +1267,18 @@ ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (ev->reason == XIRejectTouch)
TouchRejected(dev, ti, ev->resource, ev);
else if (ev->reason == XIAcceptTouch) {
+ int i;
+
+ /* Go through the motions of ending the touch if the listener has
+ * already seen the end. This ensures that the touch record is ended in
+ * the server. */
+ if (ti->listeners[0].state == LISTENER_HAS_END)
+ EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
+
/* The touch owner has accepted the touch. Send TouchEnd events to
* everyone else, and truncate the list of listeners. */
- EmitTouchEnd(dev, ti, TOUCH_ACCEPT, 0);
+ for (i = 1; i < ti->num_listeners; i++)
+ EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
while (ti->num_listeners > 1)
TouchRemoveListener(ti, ti->listeners[1].listener);
@@ -1327,6 +1330,7 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
{
int rc;
InputClients *iclients = NULL;
+ *mask = NULL;
if (listener->type == LISTENER_GRAB ||
listener->type == LISTENER_POINTER_GRAB) {
@@ -1377,6 +1381,9 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
BUG_WARN(!iclients);
if (!iclients)
return FALSE;
+
+ *mask = iclients->xi2mask;
+ *client = rClient(iclients);
}
else if (listener->level == XI) {
int xi_type = GetXIType(TouchGetPointerEventType(ev));
@@ -1389,21 +1396,24 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
BUG_WARN(!iclients);
if (!iclients)
return FALSE;
+
+ *client = rClient(iclients);
}
else {
int coretype = GetCoreType(TouchGetPointerEventType(ev));
Mask core_filter = event_get_filter_from_type(dev, coretype);
+ OtherClients *oclients;
/* all others */
- nt_list_for_each_entry(iclients,
- (InputClients *) wOtherClients(*win), next)
- if (iclients->mask[XIAllDevices] & core_filter)
- break;
- /* if owner selected, iclients is NULL */
+ nt_list_for_each_entry(oclients,
+ (OtherClients *) wOtherClients(*win), next)
+ if (oclients->mask & core_filter)
+ break;
+
+ /* if owner selected, oclients is NULL */
+ *client = oclients ? rClient(oclients) : wClient(*win);
}
- *client = iclients ? rClient(iclients) : wClient(*win);
- *mask = iclients ? iclients->xi2mask : NULL;
*grab = NULL;
}
@@ -1459,7 +1469,14 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (!deliveries)
DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
+ /* We must accept the touch sequence once a pointer listener has
+ * received one event past ButtonPress. */
+ if (deliveries && ev->any.type != ET_TouchBegin &&
+ !(ev->device_event.flags & TOUCH_CLIENT_ID))
+ TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
+
if (ev->any.type == ET_TouchEnd &&
+ !(ev->device_event.flags & TOUCH_CLIENT_ID) &&
!dev->button->buttonsDown &&
dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
(*dev->deviceGrab.DeactivateGrab) (dev);
@@ -1580,6 +1597,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
else
touchid = ev->device_event.touchid;
+ if (emulate_pointer)
+ UpdateDeviceState(dev, &ev->device_event);
+
if (type == ET_TouchBegin) {
ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
emulate_pointer);
@@ -1587,6 +1607,34 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
else
ti = TouchFindByClientID(dev, touchid);
+ /* Under the following circumstances we create a new touch record for an
+ * existing touch:
+ *
+ * - The touch may be pointer emulated
+ * - An explicit grab is active on the device
+ * - The grab is a pointer grab
+ *
+ * This allows for an explicit grab to receive pointer events for an already
+ * active touch.
+ */
+ if (!ti && type != ET_TouchBegin && emulate_pointer &&
+ dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
+ (dev->deviceGrab.grab->grabtype == CORE ||
+ dev->deviceGrab.grab->grabtype == XI ||
+ !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin))) {
+ ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
+ emulate_pointer);
+ if (!ti) {
+ DebugF("[Xi] %s: Failed to create new dix record for explicitly "
+ "grabbed touchpoint %d\n",
+ dev->name, type, touchid);
+ return;
+ }
+
+ TouchBuildSprite(dev, ti, ev);
+ TouchSetupListeners(dev, ti, ev);
+ }
+
if (!ti) {
DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
dev->name, type, touchid);
@@ -1602,9 +1650,11 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
CheckMotion(&ev->device_event, dev);
/* Make sure we have a valid window trace for event delivery; must be
- * called after event type mutation. */
+ * called after event type mutation. Touch end events are always processed
+ * in order to end touch records. */
/* FIXME: check this */
- if (!TouchEnsureSprite(dev, ti, ev))
+ if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) ||
+ (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
return;
/* TouchOwnership events are handled separately from the rest, as they
@@ -1834,7 +1884,8 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
if (ti->num_listeners > 1) {
ev->any.type = ET_TouchUpdate;
ev->device_event.flags |= TOUCH_PENDING_END;
- ti->pending_finish = TRUE;
+ if (!(ev->device_event.flags & TOUCH_CLIENT_ID))
+ ti->pending_finish = TRUE;
}
goto out;
@@ -1948,9 +1999,6 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
}
-
- if (ti->emulate_pointer)
- UpdateDeviceState(dev, &ev->device_event);
}
int