[PATCH 17/42] dix: add DIX API to create touchpoints

Peter Hutterer peter.hutterer at who-t.net
Wed Dec 14 19:01:54 PST 2011


The DIX touchpoints are the ones used for event processing.

Co-authored-by: Daniel Stone <daniel at fooishbar.org>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 dix/touch.c     |  123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/input.h |    5 ++
 test/touch.c    |   70 +++++++++++++++++++++++++++++++
 3 files changed, 198 insertions(+), 0 deletions(-)

diff --git a/dix/touch.c b/dix/touch.c
index f59cfad..5f895a0 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"
@@ -261,6 +262,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;
@@ -272,4 +276,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 e79a3ee..834dd27 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 1ea8f0c..88955cb 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;
 }
-- 
1.7.7.1



More information about the xorg-devel mailing list