The step one in implementing multitouch in evdev is to report all the
touches in different valuators.
This patch just creates the extra valuators required for multitouch.

Note that I currently assume that all definitions above ABS_MT_TOUCH_MAJOR
and below ABS_MAX are MT-related.

Signed-off-by: Benjamin Tissoires <[email protected]>
---
 src/evdev.c |   51 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/evdev.h |    5 +++++
 2 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index b84af7f..7e59601 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1156,7 +1156,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
 {
     InputInfoPtr pInfo;
     EvdevPtr pEvdev;
-    int num_axes, axis, i = 0;
+    int num_axes, axis, mt_first_valuator, i = 0, j = 0;
     Atom *atoms;
     const char *mode;
 
@@ -1167,8 +1167,35 @@ EvdevAddAbsClass(DeviceIntPtr device)
             return !Success;
 
     num_axes = CountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
+    pEvdev->mt_num_valuators = 0;
     if (num_axes < 1)
         return !Success;
+
+    if (pEvdev->flags & EVDEV_MULTITOUCH) {
+        /* in case of multitouch devices, we force the axis Tracking ID if not 
reported by the kernel */
+        if (!TestBit(ABS_MT_TRACKING_ID, pEvdev->abs_bitmask)) {
+            num_axes++;
+            pEvdev->mt_num_valuators++;
+        }
+
+        /* count the number of valuators mt-related.
+         * assume that mt values are in the range
+         * ABS_MT_TOUCH_MAJOR..ABS_MAX */
+        mt_first_valuator = 0;
+        for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
+            if (!TestBit(axis, pEvdev->abs_bitmask))
+                continue;
+            if (!mt_first_valuator)
+                mt_first_valuator = axis;
+            pEvdev->mt_num_valuators++;
+        }
+
+        /* now add the extra axes to the count of reported axes
+         * the -1 is due to the already registered collection of
+         * multitouch events */
+        num_axes += (EVDEV_MAX_TOUCHPOINTS - 1) * pEvdev->mt_num_valuators;
+    }
+
     pEvdev->num_vals = num_axes;
     memset(pEvdev->vals, 0, num_axes * sizeof(int));
     memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
@@ -1182,6 +1209,9 @@ EvdevAddAbsClass(DeviceIntPtr device)
         i++;
     }
 
+    if (pEvdev->flags & EVDEV_MULTITOUCH)
+        pEvdev->mt_first_axis = pEvdev->axis_map[mt_first_valuator];
+
     EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
 
     if (!InitValuatorClassDeviceStruct(device, num_axes,
@@ -1209,6 +1239,25 @@ EvdevAddAbsClass(DeviceIntPtr device)
         pEvdev->old_vals[axnum] = -1;
     }
 
+    /* initialize the extra mt-axes */
+    for (j = 1; j < EVDEV_MAX_TOUCHPOINTS; j++) {
+        for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
+            int axnum = pEvdev->axis_map[axis];
+            int real_axnum = axnum + j * pEvdev->mt_num_valuators;
+            if (axnum == -1)
+                continue;
+            xf86InitValuatorAxisStruct(device, real_axnum,
+    #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+                                       atoms[axnum],
+    #endif
+                                       pEvdev->absinfo[axis].minimum,
+                                       pEvdev->absinfo[axis].maximum,
+                                       10000, 0, 10000);
+            xf86InitValuatorDefaults(device, real_axnum);
+            pEvdev->old_vals[real_axnum] = -1;
+        }
+    }
+
     xfree(atoms);
 
     if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc))
diff --git a/src/evdev.h b/src/evdev.h
index 0e115f3..383a904 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -80,6 +80,8 @@
 #define MAX_VALUATORS 36
 #endif
 
+/* the number of simultaneous touchpoints the driver can support */
+#define EVDEV_MAX_TOUCHPOINTS 5 /* currently as MAX_VALUATORS == 36 */
 
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
 typedef struct {
@@ -193,6 +195,9 @@ typedef struct {
     /* Event queue used to defer keyboard/button events until EV_SYN time. */
     int                     num_queue;
     EventQueueRec           queue[EVDEV_MAXQUEUE];
+
+    unsigned int mt_first_axis;
+    unsigned int mt_num_valuators;
 } EvdevRec, *EvdevPtr;
 
 /* Event posting functions */
-- 
1.6.6.1

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to