summaryrefslogtreecommitdiff
path: root/dix/touch.c
diff options
context:
space:
mode:
Diffstat (limited to 'dix/touch.c')
-rw-r--r--dix/touch.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/dix/touch.c b/dix/touch.c
index 792ebcdd7..0f2c0c335 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -506,3 +506,90 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
/* FIXME: deliver the event */
}
}
+
+Bool
+TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite)
+{
+ int i;
+ TouchClassPtr t = dev->touch;
+ WindowPtr *trace;
+ SpritePtr srcsprite;
+
+ /* 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)
+ break;
+ if (i < t->num_touches)
+ srcsprite = &t->touches[i].sprite;
+ else if (dev->spriteInfo->sprite)
+ srcsprite = dev->spriteInfo->sprite;
+ else
+ return FALSE;
+
+ if (srcsprite->spriteTraceGood > sprite->spriteTraceSize)
+ {
+ trace = realloc(sprite->spriteTrace,
+ srcsprite->spriteTraceSize * sizeof(*trace));
+ if (!trace)
+ {
+ sprite->spriteTraceGood = 0;
+ return FALSE;
+ }
+ sprite->spriteTrace = trace;
+ sprite->spriteTraceSize = srcsprite->spriteTraceGood;
+ }
+ memcpy(sprite->spriteTrace, srcsprite->spriteTrace,
+ srcsprite->spriteTraceGood * sizeof(*trace));
+ sprite->spriteTraceGood = srcsprite->spriteTraceGood;
+
+ return TRUE;
+}
+
+/**
+ * Ensure a window trace is present in ti->sprite, constructing one for
+ * TouchBegin events.
+ */
+Bool
+TouchEnsureSprite(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
+ InternalEvent *ev)
+{
+ TouchClassPtr t = sourcedev->touch;
+ SpritePtr sprite = &ti->sprite;
+
+ /* We may not have a sprite if there are no applicable grabs or
+ * event selections, or if they've disappeared, or if all the grab
+ * owners have rejected the touch. Don't bother delivering motion
+ * events if not, but TouchEnd events still need to be processed so
+ * we can call FinishTouchPoint and release it for later use. */
+ if (ev->any.type == ET_TouchEnd)
+ return TRUE;
+ else if (ev->any.type != ET_TouchBegin)
+ return (sprite->spriteTraceGood > 0);
+
+ if (t->mode == XIDirectTouch)
+ {
+ /* Focus immediately under the touchpoint in direct touch mode.
+ * XXX: Do we need to handle crossing screens here? */
+ sprite->spriteTrace[0] =
+ sourcedev->spriteInfo->sprite->hotPhys.pScreen->root;
+ XYToWindow(sprite, ev->device_event.root_x, ev->device_event.root_y);
+ }
+ else if (!TouchBuildDependentSpriteTrace(sourcedev, sprite))
+ return FALSE;
+
+ if (sprite->spriteTraceGood <= 0)
+ return FALSE;
+
+ /* Mark which grabs/event selections we're delivering to: max one grab per
+ * window plus the bottom-most event selection. */
+ ti->listeners = calloc(sprite->spriteTraceGood + 1, sizeof(*ti->listeners));
+ if (!ti->listeners)
+ {
+ sprite->spriteTraceGood = 0;
+ return FALSE;
+ }
+ ti->num_listeners = 0;
+
+ return TRUE;
+}