summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2012-04-15 21:05:30 -0700
committerKeith Packard <keithp@keithp.com>2012-04-15 21:05:30 -0700
commit80fefc42f5e67e6b4a4b440d8991bee7e5f38359 (patch)
treea51c4a5e2b9f4e511ef458016fdd5810d8014ccc
parent9779b904c7c0b49c74054c22c420012c40595cdc (diff)
parent12188c8a8a537b38b1ca4cf8c0de5447e19c886a (diff)
Merge remote-tracking branch 'whot/for-keith'
-rw-r--r--Xi/exevents.c86
-rw-r--r--Xi/xiquerydevice.c2
-rw-r--r--dix/events.c3
-rw-r--r--dix/getevents.c2
-rw-r--r--hw/xfree86/common/xf86Events.c8
-rw-r--r--hw/xfree86/common/xf86Xinput.h3
6 files changed, 96 insertions, 8 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c
index ff2224094..c05c22604 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1111,6 +1111,48 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource)
}
/**
+ * Find the oldest touch that still has a pointer emulation client.
+ *
+ * Pointer emulation can only be performed for the oldest touch. Otherwise, the
+ * order of events seen by the client will be wrong. This function helps us find
+ * the next touch to be emulated.
+ *
+ * @param dev The device to find touches for.
+ */
+static TouchPointInfoPtr
+FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
+{
+ TouchPointInfoPtr oldest = NULL;
+ int i;
+
+ for (i = 0; i < dev->touch->num_touches; i++) {
+ TouchPointInfoPtr ti = dev->touch->touches + i;
+ int j;
+
+ if (!ti->active || !ti->emulate_pointer)
+ continue;
+
+ for (j = 0; j < ti->num_listeners; j++) {
+ if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
+ ti->listeners[j].type == LISTENER_POINTER_REGULAR)
+ break;
+ }
+ if (j == ti->num_listeners)
+ continue;
+
+ if (!oldest) {
+ oldest = ti;
+ continue;
+ }
+
+ if (oldest->client_id - ti->client_id < UINT_MAX / 2)
+ oldest = ti;
+ }
+
+ return oldest;
+}
+
+/**
* If the current owner has rejected the event, deliver the
* TouchOwnership/TouchBegin to the next item in the sprite stack.
*/
@@ -1123,8 +1165,16 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
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)
+ else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) {
+ /* We can't punt to a pointer listener unless all older pointer
+ * emulated touches have been seen already. */
+ if ((ti->listeners[0].type == LISTENER_POINTER_GRAB ||
+ ti->listeners[0].type == LISTENER_POINTER_REGULAR) &&
+ ti != FindOldestPointerEmulatedTouch(dev))
+ return;
+
TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
+ }
/* If we've just removed the last grab and the touch has physically
* ended, send a TouchEnd event too and finalise the touch. */
@@ -1139,6 +1189,25 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
}
/**
+ * Check the oldest touch to see if it needs to be replayed to its pointer
+ * owner.
+ *
+ * Touch event propagation is paused if it hits a pointer listener while an
+ * older touch with a pointer listener is waiting on accept or reject. This
+ * function will restart propagation of a paused touch if needed.
+ *
+ * @param dev The device to check touches for.
+ */
+static void
+CheckOldestTouch(DeviceIntPtr dev)
+{
+ TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
+
+ if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
+ TouchPuntToNextOwner(dev, oldest, NULL);
+}
+
+/**
* Process a touch rejection.
*
* @param sourcedev The source device of the touch sequence.
@@ -1169,6 +1238,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
* finish, then we can just kill it now. */
if (ti->num_listeners == 1 && ti->pending_finish) {
TouchEndTouch(sourcedev, ti);
+ CheckOldestTouch(sourcedev);
return;
}
@@ -1184,6 +1254,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);
+
+ CheckOldestTouch(sourcedev);
}
/**
@@ -1389,8 +1461,11 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
if (ev->any.type == ET_TouchEnd &&
!dev->button->buttonsDown &&
- dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab))
+ dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
(*dev->deviceGrab.DeactivateGrab) (dev);
+ CheckOldestTouch(dev);
+ return Success;
+ }
}
}
else {
@@ -1755,6 +1830,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
listener->type == LISTENER_POINTER_GRAB) {
rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
grab, xi2mask);
+
+ if (ti->num_listeners > 1) {
+ ev->any.type = ET_TouchUpdate;
+ ev->device_event.flags |= TOUCH_PENDING_END;
+ ti->pending_finish = TRUE;
+ }
+
goto out;
}
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index 749bc24c9..15c8b2a7b 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -430,7 +430,7 @@ ListTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
{
touch->type = XITouchClass;
touch->length = sizeof(xXITouchInfo) >> 2;
- touch->sourceid = touch->sourceid;
+ touch->sourceid = dev->touch->sourceid;
touch->mode = dev->touch->mode;
touch->num_touches = dev->touch->num_touches;
diff --git a/dix/events.c b/dix/events.c
index 447094757..b9f9cfa3c 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -5098,8 +5098,7 @@ ProcQueryPointer(ClientPtr client)
memset(&rep, 0, sizeof(xQueryPointerReply));
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
- rep.mask = mouse->button ? (mouse->button->state) : 0;
- rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
+ rep.mask = event_get_corestate(mouse, keyboard);
rep.length = 0;
rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
rep.rootX = pSprite->hot.x;
diff --git a/dix/getevents.c b/dix/getevents.c
index 3093786c3..23bbe065c 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -848,7 +848,7 @@ scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
ScreenPtr scr = miPointerGetScreen(dev);
double x, y;
- BUG_WARN(!dev->valuator || 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 */
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c
index 058057e92..5896f220c 100644
--- a/hw/xfree86/common/xf86Events.c
+++ b/hw/xfree86/common/xf86Events.c
@@ -449,6 +449,8 @@ xf86VTSwitch(void)
xf86DisableInputHandler(ih);
for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
if (pInfo->dev) {
+ if (!pInfo->dev->enabled)
+ pInfo->flags |= XI86_DEVICE_DISABLED;
xf86ReleaseKeys(pInfo->dev);
ProcessInputEvents();
DisableDevice(pInfo->dev, TRUE);
@@ -482,8 +484,9 @@ xf86VTSwitch(void)
pInfo = xf86InputDevs;
while (pInfo) {
- if (pInfo->dev)
+ if (pInfo->dev && (pInfo->flags & XI86_DEVICE_DISABLED) == 0)
EnableDevice(pInfo->dev, TRUE);
+ pInfo->flags &= ~XI86_DEVICE_DISABLED;
pInfo = pInfo->next;
}
for (ih = InputHandlers; ih; ih = ih->next)
@@ -537,8 +540,9 @@ xf86VTSwitch(void)
pInfo = xf86InputDevs;
while (pInfo) {
- if (pInfo->dev)
+ if (pInfo->dev && (pInfo->flags & XI86_DEVICE_DISABLED) == 0)
EnableDevice(pInfo->dev, TRUE);
+ pInfo->flags &= ~XI86_DEVICE_DISABLED;
pInfo = pInfo->next;
}
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 3731a34d5..1d4363a50 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -61,6 +61,9 @@
#define XI86_ALWAYS_CORE 0x04 /* device always controls the pointer */
/* the device sends Xinput and core pointer events */
#define XI86_SEND_CORE_EVENTS XI86_ALWAYS_CORE
+/* 0x08 is reserved for legacy XI86_SEND_DRAG_EVENTS, do not use for now */
+/* server-internal only */
+#define XI86_DEVICE_DISABLED 0x10 /* device was disabled before vt switch */
/* This holds the input driver entry and module information. */
typedef struct _InputDriverRec {