From: Chase Douglas <[email protected]> This multitouch addition only supports slotted MT evdev protocol devices. Support must be enabled at configure time using --enable-multitouch. It is built on the masked valuator support in XInput ABI 12, so do not attempt to build it for an earlier ABI.
Signed-off-by: Chase Douglas <[email protected]> --- configure.ac | 11 ++++ src/evdev.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- src/evdev.h | 5 ++ 3 files changed, 167 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac index 07cd64e..cc9e721 100644 --- a/configure.ac +++ b/configure.ac @@ -47,6 +47,17 @@ XORG_DEFAULT_OPTIONS # Obtain compiler/linker options from server and required extensions PKG_CHECK_MODULES(XORG, xorg-server xproto inputproto) +# Whether to include support for experimental XI 2.1 multitouch +AC_ARG_ENABLE(multitouch, + AC_HELP_STRING([--enable-multitouch], + [Enable experimental XI 2.1 multitouch support [[default: disabled]]]), + [MULTITOUCH=$enableval], + [MULTITOUCH=no]) + +if test "x$MULTITOUCH" = xyes; then + AC_DEFINE(MULTITOUCH, 1, [Enable experimental multitouch code]) +fi + # Define a configure option for an alternate input module directory AC_ARG_WITH(xorg-module-dir, AC_HELP_STRING([--with-xorg-module-dir=DIR], diff --git a/src/evdev.c b/src/evdev.c index 4984019..8b13e9f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -87,6 +87,14 @@ #define MODEFLAG 8 #define COMPOSEFLAG 16 +#ifndef ABS_MT_SLOT +#define ABS_MT_SLOT 0x2f +#endif + +#ifndef ABS_MT_TRACKING_ID +#define ABS_MT_TRACKING_ID 0x39 +#endif + static char *evdevDefaults[] = { "XkbRules", "evdev", "XkbModel", "evdev", @@ -743,6 +751,60 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev) } } +#ifdef MULTITOUCH +static void +EvdevProcessTouch(InputInfoPtr pInfo) +{ + EvdevPtr pEvdev = pInfo->private; + int map = pEvdev->axis_map[ABS_MT_TRACKING_ID] - pEvdev->num_vals; + + if (pEvdev->cur_slot < 0 || !pEvdev->mtMask) + return; + + if (valuator_mask_isset(pEvdev->mtMask, map) && + valuator_mask_get(pEvdev->mtMask, map) < 0) { + valuator_mask_set(pEvdev->mtMask, map, + pEvdev->mt_slot_map[pEvdev->cur_slot]); + xf86PostTouchEvent(pInfo->dev, pEvdev->mtMask, 1); + pEvdev->mt_slot_map[pEvdev->cur_slot] = -1; + } else { + if (pEvdev->mt_slot_map[pEvdev->cur_slot] < 0) + if (!valuator_mask_isset(pEvdev->mtMask, map)) + xf86Msg(X_WARNING, "%s: New touch without tracking ID.\n", + pInfo->dev->name); + else { + int tracking_id = valuator_mask_get(pEvdev->mtMask, map); + pEvdev->mt_slot_map[pEvdev->cur_slot] = tracking_id; + } + else if (!valuator_mask_isset(pEvdev->mtMask, map)) + valuator_mask_set(pEvdev->mtMask, map, + pEvdev->mt_slot_map[pEvdev->cur_slot]); + + xf86PostTouchEvent(pInfo->dev, pEvdev->mtMask, 0); + } + + valuator_mask_zero(pEvdev->mtMask); +} + +static void +EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev) +{ + EvdevPtr pEvdev = pInfo->private; + int map; + + if (ev->code == ABS_MT_SLOT) { + EvdevProcessTouch(pInfo); + pEvdev->cur_slot = ev->value; + } else { + map = pEvdev->axis_map[ev->code] - pEvdev->num_vals; + valuator_mask_set(pEvdev->mtMask, map, ev->value); + } +} +#else +#define EvdevProcessTouch(pInfo) +#define EvdevProcessTouchEvent(pInfo, ev) +#endif /* MULTITOUCH */ + /** * Take the absolute motion input event and process it accordingly. */ @@ -766,11 +828,16 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev) if (EvdevWheelEmuFilterMotion(pInfo, ev)) return; - map = pEvdev->axis_map[ev->code]; #ifdef HAVE_MASKED_VALUATORS - valuator_mask_set(pEvdev->mask, map, value); - pEvdev->abs_queued = 1; + if (ev->code >= ABS_MT_SLOT) + EvdevProcessTouchEvent(pInfo, ev); + else { + map = pEvdev->axis_map[ev->code]; + valuator_mask_set(pEvdev->mask, map, value); + pEvdev->abs_queued = 1; + } #else + map = pEvdev->axis_map[ev->code]; pEvdev->vals[map] = value; if (ev->code == ABS_X) pEvdev->abs_queued |= ABS_X_VALUE; @@ -936,6 +1003,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev) #ifdef HAVE_MASKED_VALUATORS EvdevProcessValuators(pInfo); + EvdevProcessTouch(pInfo); #else EvdevProcessValuators(pInfo, v, &num_v, &first_v); #endif @@ -1416,7 +1484,7 @@ EvdevAddAbsClass(DeviceIntPtr device) { InputInfoPtr pInfo; EvdevPtr pEvdev; - int num_axes, axis, i = 0; + int num_axes, num_mt_axes, axis, i = 0; Atom *atoms; pInfo = device->public.devicePrivate; @@ -1425,7 +1493,13 @@ EvdevAddAbsClass(DeviceIntPtr device) if (!TestBit(EV_ABS, pEvdev->bitmask)) return !Success; +#ifdef HAVE_MASKED_VALUATORS + num_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MT_SLOT); + num_mt_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MAX) - num_axes; +#else num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX)); + num_mt_axes = 0; +#endif if (num_axes < 1) return !Success; @@ -1434,6 +1508,13 @@ EvdevAddAbsClass(DeviceIntPtr device) num_axes = MAX_VALUATORS; } +#ifdef MULTITOUCH + if (num_mt_axes > MAX_VALUATORS) { + xf86Msg(X_WARNING, "%s: found %d MT axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS); + num_mt_axes = MAX_VALUATORS; + } +#endif + pEvdev->num_vals = num_axes; #ifdef HAVE_MASKED_VALUATORS if (num_axes > 0) { @@ -1444,21 +1525,28 @@ EvdevAddAbsClass(DeviceIntPtr device) if (!pEvdev->oldMask) goto out; } +#ifdef MULTITOUCH + if (num_mt_axes > 0) { + pEvdev->mtMask = valuator_mask_new(num_mt_axes); + if (!pEvdev->mtMask) + goto out; + } +#endif #else memset(pEvdev->vals, 0, num_axes * sizeof(int)); memset(pEvdev->old_vals, -1, num_axes * sizeof(int)); #endif - atoms = malloc(pEvdev->num_vals * sizeof(Atom)); + atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom)); for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) { pEvdev->axis_map[axis] = -1; - if (!TestBit(axis, pEvdev->abs_bitmask)) + if (!TestBit(axis, pEvdev->abs_bitmask) || axis == ABS_MT_SLOT) continue; pEvdev->axis_map[axis] = i; i++; } - EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms); + EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms); if (!InitValuatorClassDeviceStruct(device, num_axes, #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7 @@ -1470,7 +1558,29 @@ EvdevAddAbsClass(DeviceIntPtr device) GetMotionHistorySize(), Absolute)) goto out; - for (axis = ABS_X; axis <= ABS_MAX; axis++) { +#ifdef MULTITOUCH + if (num_mt_axes > 0) + { + int num_touches = 10; + int mode = pEvdev->flags & EVDEV_TOUCHPAD ? + XIDependentTouch : XIDirectTouch; + + if (pEvdev->absinfo[ABS_MT_SLOT].maximum > 0) + num_touches = pEvdev->absinfo[ABS_MT_SLOT].maximum; + + pEvdev->mt_slot_map = malloc(num_touches * sizeof(int)); + if (!pEvdev->mt_slot_map) + goto out; + + for (i = 0; i < num_touches; i++) + pEvdev->mt_slot_map[i] = -1; + + if (!InitTouchClassDeviceStruct(device, num_touches, mode, num_mt_axes)) + goto out; + } +#endif + + for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) { int axnum = pEvdev->axis_map[axis]; int resolution = 10000; @@ -1500,6 +1610,25 @@ EvdevAddAbsClass(DeviceIntPtr device) #endif } +#ifdef MULTITOUCH + for (axis = ABS_MT_SLOT; axis <= ABS_MAX; axis++) { + int axnum = pEvdev->axis_map[axis] - pEvdev->num_vals; + int resolution = 10000; + + if (axnum < 0) + continue; + + if (pEvdev->absinfo[axis].resolution) + resolution = pEvdev->absinfo[axis].resolution * 1000; + + xf86InitTouchValuatorAxisStruct(device, axnum, + atoms[axnum + pEvdev->num_vals], + pEvdev->absinfo[axis].minimum, + pEvdev->absinfo[axis].maximum, + pEvdev->absinfo[axis].resolution); + } +#endif + free(atoms); for (i = 0; i < ArrayLength(proximity_bits); i++) @@ -1539,6 +1668,12 @@ EvdevAddAbsClass(DeviceIntPtr device) out: #ifdef HAVE_MASKED_VALUATORS +#ifdef MULTITOUCH + free(pEvdev->mtMask); + pEvdev->mtMask = NULL; + free(pEvdev->mt_slot_map); + pEvdev->mt_slot_map = NULL; +#endif free(pEvdev->mask); pEvdev->mask = NULL; free(pEvdev->oldMask); @@ -1923,6 +2058,10 @@ EvdevProc(DeviceIntPtr device, int what) free(pEvdev->mask); free(pEvdev->oldMask); free(pEvdev->proxMask); +#ifdef MULTITOUCH + free(pEvdev->mt_slot_map); + free(pEvdev->mtMask); +#endif EvdevRemoveDevice(pInfo); pEvdev->min_maj = 0; break; @@ -2439,6 +2578,10 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags) if (!EvdevOpenDevice(pInfo)) goto error; +#ifdef MULTITOUCH + pEvdev->cur_slot = -1; +#endif + /* * We initialize pEvdev->proximity to 1 so that device that doesn't use * proximity will still report events. diff --git a/src/evdev.h b/src/evdev.h index bd5cb16..63c75a3 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -129,6 +129,11 @@ typedef struct { ValuatorMask *mask; ValuatorMask *oldMask; ValuatorMask *proxMask; +#ifdef MULTITOUCH + ValuatorMask *mtMask; + int *mt_slot_map; + int cur_slot; +#endif #else int vals[MAX_VALUATORS]; int old_vals[MAX_VALUATORS]; /* Translate absolute inputs to relative */ -- 1.7.1 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
