summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2011-12-14 14:57:46 +1000
committerChase Douglas <chase.douglas@canonical.com>2011-12-21 10:34:11 -0800
commit52e98857232a2b383b2242536c2d453e693e90b3 (patch)
tree8488da7ffc5371557fb74ea33ed35e3783748e82
parent75780c37600de2ec97c6426bd85fba69177701ba (diff)
dix: add DIX API to create touchpoints
The DIX touchpoints are the ones used for event processing. Co-authored-by: Daniel Stone <daniel@fooishbar.org> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Chase Douglas <chase.douglas@canonical.com>
-rw-r--r--dix/touch.c123
-rw-r--r--include/input.h5
-rw-r--r--test/touch.c70
3 files changed, 198 insertions, 0 deletions
diff --git a/dix/touch.c b/dix/touch.c
index b492e8238..dfb7ff041 100644
--- a/dix/touch.c
+++ b/dix/touch.c
@@ -30,6 +30,7 @@
#include "inputstr.h"
#include "scrnintstr.h"
+#include "dixgrabs.h"
#include "eventstr.h"
#include "exevents.h"
@@ -262,6 +263,9 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index)
return;
ti = &device->touch->touches[index];
+ if (ti->active)
+ TouchEndTouch(device, ti);
+
valuator_mask_free(&ti->valuators);
free(ti->sprite.spriteTrace);
ti->sprite.spriteTrace = NULL;
@@ -273,4 +277,123 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index)
ti->history_elements = 0;
}
+/**
+ * Given a client-facing ID (e.g. DeviceEvent::detail.touch), find the
+ * associated TouchPointInfoRec.
+ */
+TouchPointInfoPtr
+TouchFindByClientID(DeviceIntPtr dev, uint32_t client_id)
+{
+ TouchClassPtr t = dev->touch;
+ TouchPointInfoPtr ti;
+ int i;
+
+ if (!t)
+ return NULL;
+
+ for (i = 0; i < t->num_touches; i++)
+ {
+ ti = &t->touches[i];
+ if (ti->active && ti->client_id == client_id)
+ return ti;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Given a unique ID for a touchpoint, create a touchpoint record in the
+ * server.
+ *
+ * Returns NULL on failure (i.e. if another touch with that ID is already active,
+ * allocation failure).
+ */
+TouchPointInfoPtr
+TouchBeginTouch(DeviceIntPtr dev, int sourceid, uint32_t touchid,
+ Bool emulate_pointer)
+{
+ int i;
+ TouchClassPtr t = dev->touch;
+ TouchPointInfoPtr ti;
+ void *tmp;
+
+ if (!t)
+ return NULL;
+
+ /* Look for another active touchpoint with the same client ID. It's
+ * technically legitimate for a touchpoint to still exist with the same
+ * ID but only once the 32 bits wrap over and you've used up 4 billion
+ * touch ids without lifting that one finger off once. In which case
+ * you deserve a medal or something, but not error handling code. */
+ if (TouchFindByClientID(dev, touchid))
+ return NULL;
+
+try_find_touch:
+ for (i = 0; i < t->num_touches; i++)
+ {
+ ti = &t->touches[i];
+ if (!ti->active) {
+ ti->active = TRUE;
+ ti->client_id = touchid;
+ ti->sourceid = sourceid;
+ ti->emulate_pointer = emulate_pointer;
+ return ti;
+ }
+ }
+
+ /* If we get here, then we've run out of touches: enlarge dev->touch and
+ * try again. */
+ tmp = realloc(t->touches, (t->num_touches + 1) * sizeof(*ti));
+ if (tmp)
+ {
+ t->touches = tmp;
+ t->num_touches++;
+ if (TouchInitTouchPoint(t, dev->valuator, t->num_touches - 1))
+ goto try_find_touch;
+ }
+
+ return NULL;
+}
+
+/**
+ * Releases a touchpoint for use: this must only be called after all events
+ * related to that touchpoint have been sent and finalised. Called from
+ * ProcessTouchEvent and friends. Not by you.
+ */
+void
+TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
+{
+ if (ti->emulate_pointer)
+ {
+ GrabPtr grab;
+ DeviceEvent ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.type = ET_TouchEnd;
+ ev.detail.button = 1;
+ ev.touchid = ti->client_id;
+ ev.flags = TOUCH_POINTER_EMULATED|TOUCH_END;
+ UpdateDeviceState(dev, &ev);
+
+ if ((grab = dev->deviceGrab.grab))
+ {
+ if (dev->deviceGrab.fromPassiveGrab &&
+ !dev->button->buttonsDown &&
+ !dev->touch->buttonsDown &&
+ GrabIsPointerGrab(grab))
+ (*dev->deviceGrab.DeactivateGrab)(dev);
+ }
+ }
+
+ ti->active = FALSE;
+ ti->pending_finish = FALSE;
+ ti->sprite.spriteTraceGood = 0;
+ free(ti->listeners);
+ ti->listeners = NULL;
+ ti->num_listeners = 0;
+ ti->num_grabs = 0;
+ ti->client_id = 0;
+
+ valuator_mask_zero(ti->valuators);
+}
diff --git a/include/input.h b/include/input.h
index e79a3ee84..834dd273d 100644
--- a/include/input.h
+++ b/include/input.h
@@ -594,6 +594,11 @@ extern DDXTouchPointInfoPtr TouchFindByDDXID(DeviceIntPtr dev,
Bool create);
extern Bool TouchInitTouchPoint(TouchClassPtr touch, ValuatorClassPtr v, int index);
extern void TouchFreeTouchPoint(DeviceIntPtr dev, int index);
+extern TouchPointInfoPtr TouchBeginTouch(DeviceIntPtr dev, int sourceid,
+ uint32_t touchid, Bool emulate_pointer);
+extern TouchPointInfoPtr TouchFindByClientID(DeviceIntPtr dev,
+ uint32_t client_id);
+extern void TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti);
/* misc event helpers */
extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);
diff --git a/test/touch.c b/test/touch.c
index 1ea8f0ca5..88955cbc1 100644
--- a/test/touch.c
+++ b/test/touch.c
@@ -28,6 +28,7 @@
#include <stdint.h>
#include "inputstr.h"
#include "assert.h"
+#include "scrnintstr.h"
static void touch_grow_queue(void)
{
@@ -190,11 +191,80 @@ static void touch_begin_ddxtouch(void)
last_client_id = ti->client_id;
}
+static void touch_begin_touch(void)
+{
+ DeviceIntRec dev;
+ TouchClassRec touch;
+ ValuatorClassRec val;
+ TouchPointInfoPtr ti;
+ int touchid = 12434;
+ int sourceid = 23;
+ SpriteInfoRec sprite;
+ ScreenRec screen;
+
+ screenInfo.screens[0] = &screen;
+
+ memset(&dev, 0, sizeof(dev));
+ dev.id = 2;
+
+ memset(&sprite, 0, sizeof(sprite));
+ dev.spriteInfo = &sprite;
+
+ memset(&touch, 0, sizeof(touch));
+ touch.num_touches = 0;
+
+ memset(&val, 0, sizeof(val));
+ dev.valuator = &val;
+ val.numAxes = 2;
+
+ ti = TouchBeginTouch(&dev, sourceid, touchid, TRUE);
+ assert(!ti);
+
+ dev.touch = &touch;
+ ti = TouchBeginTouch(&dev, sourceid, touchid, TRUE);
+ assert(ti);
+ assert(ti->client_id == touchid);
+ assert(ti->active);
+ assert(ti->sourceid == sourceid);
+ assert(ti->emulate_pointer);
+
+ assert(touch.num_touches == 1);
+}
+
+static void touch_init(void)
+{
+ DeviceIntRec dev;
+ Atom labels[2] = {0};
+ int rc;
+ SpriteInfoRec sprite;
+ ScreenRec screen;
+
+ screenInfo.screens[0] = &screen;
+
+ memset(&dev, 0, sizeof(dev));
+
+ memset(&sprite, 0, sizeof(sprite));
+ dev.spriteInfo = &sprite;
+
+ InitAtoms();
+ rc = InitTouchClassDeviceStruct(&dev, 1, XIDirectTouch, 2);
+ assert(rc == FALSE);
+
+ InitValuatorClassDeviceStruct(&dev, 2, labels, 10, Absolute);
+ rc = InitTouchClassDeviceStruct(&dev, 1, XIDirectTouch, 2);
+ assert(rc == TRUE);
+ assert(dev.touch);
+}
+
+
+
int main(int argc, char** argv)
{
touch_grow_queue();
touch_find_ddxid();
touch_begin_ddxtouch();
+ touch_init();
+ touch_begin_touch();
return 0;
}