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
