summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch')
-rw-r--r--x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch1678
1 files changed, 1678 insertions, 0 deletions
diff --git a/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch
new file mode 100644
index 0000000..10598f1
--- /dev/null
+++ b/x11-drivers/xf86-input-evdev/files/xf86-input-evdev-xi2.1.patch
@@ -0,0 +1,1678 @@
+diff --git a/configure.ac b/configure.ac
+index 887021c..b4b0bad 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -47,6 +47,9 @@ XORG_DEFAULT_OPTIONS
+ # Obtain compiler/linker options from server and required extensions
+ PKG_CHECK_MODULES(XORG, xorg-server xproto inputproto)
+
++# Obtain compiler/linker options for mtdev
++PKG_CHECK_MODULES(MTDEV, mtdev)
++
+ # 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/Makefile.am b/src/Makefile.am
+index a5c89ac..b8d0dd9 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -30,6 +30,7 @@ AM_CPPFLAGS =-I$(top_srcdir)/include
+
+ @DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
+ @DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
++@DRIVER_NAME@_drv_la_LIBADD = $(MTDEV_LIBS)
+ @DRIVER_NAME@_drv_ladir = @inputdir@
+
+ @DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
+diff --git a/src/draglock.c b/src/draglock.c
+index af80cf6..0b430f0 100644
+--- a/src/draglock.c
++++ b/src/draglock.c
+@@ -44,9 +44,7 @@
+
+ #include <evdev-properties.h>
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_dlock = 0; /* Drag lock buttons. */
+-#endif
+
+ void EvdevDragLockLockButton(InputInfoPtr pInfo, unsigned int button);
+
+@@ -211,7 +209,6 @@ EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value)
+ return FALSE;
+ }
+
+-#ifdef HAVE_PROPERTIES
+ /**
+ * Set the drag lock property.
+ * If only one value is supplied, then this is used as the meta button.
+@@ -319,5 +316,3 @@ EvdevDragLockInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevDragLockSetProperty, NULL, NULL);
+ }
+-
+-#endif
+diff --git a/src/emuMB.c b/src/emuMB.c
+index 764b30e..b7a57b8 100644
+--- a/src/emuMB.c
++++ b/src/emuMB.c
+@@ -43,10 +43,8 @@
+
+ #include <evdev-properties.h>
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_mbemu = 0; /* Middle button emulation on/off property */
+ static Atom prop_mbtimeout = 0; /* Middle button timeout property */
+-#endif
+ /*
+ * Lets create a simple finite-state machine for 3 button emulation:
+ *
+@@ -330,7 +328,6 @@ EvdevMBEmuFinalize(InputInfoPtr pInfo)
+
+ }
+
+-#ifdef HAVE_PROPERTIES
+ static int
+ EvdevMBEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+@@ -391,4 +388,3 @@ EvdevMBEmuInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevMBEmuSetProperty, NULL, NULL);
+ }
+-#endif
+diff --git a/src/emuWheel.c b/src/emuWheel.c
+index 9a53211..715f8d1 100644
+--- a/src/emuWheel.c
++++ b/src/emuWheel.c
+@@ -44,13 +44,11 @@
+
+ #define WHEEL_NOT_CONFIGURED 0
+
+-#ifdef HAVE_PROPERTIES
+ static Atom prop_wheel_emu = 0;
+ static Atom prop_wheel_axismap = 0;
+ static Atom prop_wheel_inertia = 0;
+ static Atom prop_wheel_timeout = 0;
+ static Atom prop_wheel_button = 0;
+-#endif
+
+ /* Local Funciton Prototypes */
+ static BOOL EvdevWheelEmuHandleButtonMap(InputInfoPtr pInfo, WheelAxisPtr pAxis, char *axis_name);
+@@ -120,8 +118,9 @@ EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv)
+
+ /* We don't want to intercept real mouse wheel events */
+ if(pEv->type == EV_ABS) {
+- oldValue = pEvdev->vals[pEvdev->axis_map[pEv->code]];
+- pEvdev->vals[pEvdev->axis_map[pEv->code]] = value;
++ int axis = pEvdev->axis_map[pEv->code];
++ oldValue = valuator_mask_get(pEvdev->vals, axis);
++ valuator_mask_set(pEvdev->vals, axis, value);
+ value -= oldValue; /* make value into a differential measurement */
+ }
+
+@@ -335,7 +334,6 @@ EvdevWheelEmuPreInit(InputInfoPtr pInfo)
+ pInfo->name, pEvdev->emulateWheel.button, inertia, timeout);
+ }
+
+-#ifdef HAVE_PROPERTIES
+ static int
+ EvdevWheelEmuSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+ BOOL checkonly)
+@@ -485,4 +483,3 @@ EvdevWheelEmuInitProperty(DeviceIntPtr dev)
+
+ XIRegisterPropertyHandler(dev, EvdevWheelEmuSetProperty, NULL, NULL);
+ }
+-#endif
+diff --git a/src/evdev.c b/src/evdev.c
+index 45873c1..ef72f8f 100644
+--- a/src/evdev.c
++++ b/src/evdev.c
+@@ -48,23 +48,12 @@
+ #include <xorgVersion.h>
+ #include <xkbsrv.h>
+
+-#ifdef HAVE_PROPERTIES
+ #include <X11/Xatom.h>
+ #include <evdev-properties.h>
+ #include <xserver-properties.h>
+-/* 1.6 has properties, but no labels */
+-#ifdef AXIS_LABEL_PROP
+-#define HAVE_LABELS
+-#else
+-#undef HAVE_LABELS
+-#endif
+-
+-#endif
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+ /* removed from server, purge when dropping support for server 1.10 */
+ #define XI86_SEND_DRAG_EVENTS 0x08
+-#endif
+
+ #ifndef MAXDEVICES
+ #include <inputstr.h> /* for MAX_DEVICES */
+@@ -87,6 +76,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",
+@@ -114,7 +111,6 @@ static BOOL EvdevGrabDevice(InputInfoPtr pInfo, int grab, int ungrab);
+ static void EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]);
+ static int EvdevOpenDevice(InputInfoPtr pInfo);
+
+-#ifdef HAVE_PROPERTIES
+ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
+ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
+ static void EvdevInitProperty(DeviceIntPtr dev);
+@@ -125,7 +121,6 @@ static Atom prop_calibration = 0;
+ static Atom prop_swap = 0;
+ static Atom prop_axis_label = 0;
+ static Atom prop_btn_label = 0;
+-#endif
+
+ /* All devices the evdev driver has allocated and knows about.
+ * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK)
+@@ -302,22 +297,13 @@ EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
+
+ /* Filter all repeated events from device.
+ We'll do softrepeat in the server, but only since 1.6 */
+- if (value == 2
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) <= 2
+- && (ev->code == KEY_LEFTCTRL || ev->code == KEY_RIGHTCTRL ||
+- ev->code == KEY_LEFTSHIFT || ev->code == KEY_RIGHTSHIFT ||
+- ev->code == KEY_LEFTALT || ev->code == KEY_RIGHTALT ||
+- ev->code == KEY_LEFTMETA || ev->code == KEY_RIGHTMETA ||
+- ev->code == KEY_CAPSLOCK || ev->code == KEY_NUMLOCK ||
+- ev->code == KEY_SCROLLLOCK) /* XXX windows keys? */
+-#endif
+- )
+- return;
++ if (value == 2)
++ return;
+
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_KEY;
+- pQueue->key = code;
++ pQueue->detail.key = code;
+ pQueue->val = value;
+ }
+ }
+@@ -327,10 +313,14 @@ EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value)
+ {
+ EventQueuePtr pQueue;
+
++ /* Direct touch devices use server side pointer emulation */
++ if (pInfo->dev->touch && pInfo->dev->touch->mode == XIDirectTouch)
++ return;
++
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_BTN;
+- pQueue->key = button;
++ pQueue->detail.key = button;
+ pQueue->val = value;
+ }
+ }
+@@ -342,11 +332,27 @@ EvdevQueueProximityEvent(InputInfoPtr pInfo, int value)
+ if ((pQueue = EvdevNextInQueue(pInfo)))
+ {
+ pQueue->type = EV_QUEUE_PROXIMITY;
+- pQueue->key = 0;
++ pQueue->detail.key = 0;
+ pQueue->val = value;
+ }
+ }
+
++#ifdef MULTITOUCH
++void
++EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch, ValuatorMask *mask,
++ uint16_t evtype)
++{
++ EventQueuePtr pQueue;
++ if ((pQueue = EvdevNextInQueue(pInfo)))
++ {
++ pQueue->type = EV_QUEUE_TOUCH;
++ pQueue->detail.touch = touch;
++ valuator_mask_copy(pQueue->touch_vals, mask);
++ pQueue->val = evtype;
++ }
++}
++#endif
++
+ /**
+ * Post button event right here, right now.
+ * Interface for MB emulation since these need to post immediately.
+@@ -368,41 +374,44 @@ EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
+ }
+ }
+
+-#define ABS_X_VALUE 0x1
+-#define ABS_Y_VALUE 0x2
+-#define ABS_VALUE 0x4
+ /**
+ * Take the valuators and process them accordingly.
+ */
+ static void
+-EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+- int *first_v)
++EvdevProcessValuators(InputInfoPtr pInfo)
+ {
+ int tmp;
+ EvdevPtr pEvdev = pInfo->private;
+-
+- *num_v = *first_v = 0;
++ int *delta = pEvdev->delta;
+
+ /* convert to relative motion for touchpads */
+ if (pEvdev->abs_queued && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
+ if (pEvdev->in_proximity) {
+- if (pEvdev->old_vals[0] != -1)
+- pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
+- if (pEvdev->old_vals[1] != -1)
+- pEvdev->delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
+- if (pEvdev->abs_queued & ABS_X_VALUE)
+- pEvdev->old_vals[0] = pEvdev->vals[0];
+- if (pEvdev->abs_queued & ABS_Y_VALUE)
+- pEvdev->old_vals[1] = pEvdev->vals[1];
++ if (valuator_mask_isset(pEvdev->vals, 0))
++ {
++ if (valuator_mask_isset(pEvdev->old_vals, 0))
++ delta[REL_X] = valuator_mask_get(pEvdev->vals, 0) -
++ valuator_mask_get(pEvdev->old_vals, 0);
++ valuator_mask_set(pEvdev->old_vals, 0,
++ valuator_mask_get(pEvdev->vals, 0));
++ }
++ if (valuator_mask_isset(pEvdev->vals, 1))
++ {
++ if (valuator_mask_isset(pEvdev->old_vals, 1))
++ delta[REL_Y] = valuator_mask_get(pEvdev->vals, 1) -
++ valuator_mask_get(pEvdev->old_vals, 1);
++ valuator_mask_set(pEvdev->old_vals, 1,
++ valuator_mask_get(pEvdev->vals, 1));
++ }
+ } else {
+- pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
++ valuator_mask_zero(pEvdev->old_vals);
+ }
++ valuator_mask_zero(pEvdev->vals);
+ pEvdev->abs_queued = 0;
+ pEvdev->rel_queued = 1;
+ }
+
+ if (pEvdev->rel_queued) {
+- int first = REL_CNT, last = -1;
+ int i;
+
+ if (pEvdev->swap_axes) {
+@@ -419,19 +428,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+ {
+ int map = pEvdev->axis_map[i];
+ if (pEvdev->delta[i] && map != -1)
+- {
+- v[map] = pEvdev->delta[i];
+- if (map < first)
+- first = map;
+- if (map > last)
+- last = map;
+- }
+- }
+-
+- if (last >= 0)
+- {
+- *num_v = (last - first + 1);
+- *first_v = first;
++ valuator_mask_set(pEvdev->vals, map, pEvdev->delta[i]);
+ }
+ }
+ /*
+@@ -444,43 +441,46 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
+ * just works.
+ */
+ else if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
++ int unswapped_x = valuator_mask_get(pEvdev->vals, 0);
++ int unswapped_y = valuator_mask_get(pEvdev->vals, 1);
++ int i;
+
+- if (pEvdev->swap_axes) {
+- int tmp = v[0];
+- v[0] = xf86ScaleAxis(v[1],
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum,
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum);
+- v[1] = xf86ScaleAxis(tmp,
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum,
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum);
+- }
++ for (i = 0; i <= 1; i++) {
++ int val;
++ int calib_min;
++ int calib_max;
+
+- if (pEvdev->flags & EVDEV_CALIBRATED)
+- {
+- v[0] = xf86ScaleAxis(v[0],
+- pEvdev->absinfo[ABS_X].maximum,
+- pEvdev->absinfo[ABS_X].minimum,
+- pEvdev->calibration.max_x, pEvdev->calibration.min_x);
+- v[1] = xf86ScaleAxis(v[1],
+- pEvdev->absinfo[ABS_Y].maximum,
+- pEvdev->absinfo[ABS_Y].minimum,
+- pEvdev->calibration.max_y, pEvdev->calibration.min_y);
+- }
++ if (!valuator_mask_isset(pEvdev->vals, i))
++ continue;
+
+- if (pEvdev->invert_x)
+- v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
+- pEvdev->absinfo[ABS_X].minimum);
+- if (pEvdev->invert_y)
+- v[1] = (pEvdev->absinfo[ABS_Y].maximum - v[1] +
+- pEvdev->absinfo[ABS_Y].minimum);
++ val = valuator_mask_get(pEvdev->vals, i);
++
++ if (i == 0) {
++ calib_min = pEvdev->calibration.min_x;
++ calib_max = pEvdev->calibration.max_x;
++ } else {
++ calib_min = pEvdev->calibration.min_y;
++ calib_max = pEvdev->calibration.max_y;
++ }
++
++ if (pEvdev->swap_axes)
++ val = xf86ScaleAxis((i == 0 ? unswapped_y : unswapped_x),
++ pEvdev->absinfo[i].maximum,
++ pEvdev->absinfo[i].minimum,
++ pEvdev->absinfo[1 - i].maximum,
++ pEvdev->absinfo[1 - i].minimum);
+
+- *num_v = pEvdev->num_vals;
+- *first_v = 0;
++ if (pEvdev->flags & EVDEV_CALIBRATED)
++ val = xf86ScaleAxis(val, pEvdev->absinfo[i].maximum,
++ pEvdev->absinfo[i].minimum, calib_max,
++ calib_min);
++
++ if ((i == 0 && pEvdev->invert_x) || (i == 1 && pEvdev->invert_y))
++ val = (pEvdev->absinfo[i].maximum - val +
++ pEvdev->absinfo[i].minimum);
++
++ valuator_mask_set(pEvdev->vals, i, val);
++ }
+ }
+ }
+
+@@ -518,11 +518,15 @@ EvdevProcessProximityState(InputInfoPtr pInfo)
+ int prox_state = 0;
+ int i;
+
++ /* Does this device have any proximity axes? */
++ if (!pEvdev->prox)
++ return 0;
++
+ /* no proximity change in the queue */
+ if (!pEvdev->prox_queued)
+ {
+ if (pEvdev->abs_queued && !pEvdev->in_proximity)
+- pEvdev->abs_prox = pEvdev->abs_queued;
++ valuator_mask_copy(pEvdev->prox, pEvdev->vals);
+ return 0;
+ }
+
+@@ -540,10 +544,11 @@ EvdevProcessProximityState(InputInfoPtr pInfo)
+ {
+ /* We're about to go into/out of proximity but have no abs events
+ * within the EV_SYN. Use the last coordinates we have. */
+- if (!pEvdev->abs_queued && pEvdev->abs_prox)
++ if (!pEvdev->abs_queued &&
++ valuator_mask_num_valuators(pEvdev->prox) > 0)
+ {
+- pEvdev->abs_queued = pEvdev->abs_prox;
+- pEvdev->abs_prox = 0;
++ valuator_mask_copy(pEvdev->vals, pEvdev->prox);
++ valuator_mask_zero(pEvdev->prox);
+ }
+ }
+
+@@ -590,6 +595,7 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
+ int value;
+ EvdevPtr pEvdev = pInfo->private;
++ int map;
+
+ /* Get the signed value, earlier kernels had this as unsigned */
+ value = ev->value;
+@@ -622,10 +628,63 @@ EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+
+ pEvdev->rel_queued = 1;
+ pEvdev->delta[ev->code] += value;
++ map = pEvdev->axis_map[ev->code];
++ valuator_mask_set(pEvdev->vals, map, value);
+ break;
+ }
+ }
+
++#ifdef MULTITOUCH
++static void
++EvdevProcessTouch(InputInfoPtr pInfo)
++{
++ EvdevPtr pEvdev = pInfo->private;
++
++ if (pEvdev->cur_slot < 0 || !pEvdev->mt_vals ||
++ (!pEvdev->open_slot && !pEvdev->close_slot &&
++ valuator_mask_num_valuators(pEvdev->mt_vals) == 0))
++ return;
++
++ if (pEvdev->close_slot) {
++ EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_vals,
++ XI_TouchEnd);
++ pEvdev->close_slot = 0;
++ } else {
++ EvdevQueueTouchEvent(pInfo, pEvdev->cur_slot, pEvdev->mt_vals,
++ pEvdev->open_slot ? XI_TouchBegin :
++ XI_TouchUpdate);
++ pEvdev->open_slot = 0;
++ }
++
++ valuator_mask_zero(pEvdev->mt_vals);
++}
++
++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 if (ev->code == ABS_MT_TRACKING_ID) {
++ if (ev->value >= 0) {
++ pEvdev->open_slot = 1;
++ valuator_mask_copy(pEvdev->mt_vals, pEvdev->cur_vals);
++ } else
++ pEvdev->close_slot = 1;
++ } else {
++ map = pEvdev->axis_map[ev->code] - pEvdev->num_vals;
++ valuator_mask_set(pEvdev->mt_vals, map, ev->value);
++ valuator_mask_set(pEvdev->cur_vals, map, ev->value);
++ }
++}
++#else
++#define EvdevProcessTouch(pInfo)
++#define EvdevProcessTouchEvent(pInfo, ev)
++#endif /* MULTITOUCH */
++
+ /**
+ * Take the absolute motion input event and process it accordingly.
+ */
+@@ -634,6 +693,7 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ {
+ int value;
+ EvdevPtr pEvdev = pInfo->private;
++ int map;
+
+ /* Get the signed value, earlier kernels had this as unsigned */
+ value = ev->value;
+@@ -648,13 +708,16 @@ EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
+ if (EvdevWheelEmuFilterMotion(pInfo, ev))
+ return;
+
+- pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
+- if (ev->code == ABS_X)
+- pEvdev->abs_queued |= ABS_X_VALUE;
+- else if (ev->code == ABS_Y)
+- pEvdev->abs_queued |= ABS_Y_VALUE;
+- else
+- pEvdev->abs_queued |= ABS_VALUE;
++ if (ev->code >= ABS_MT_SLOT) {
++ EvdevProcessTouchEvent(pInfo, ev);
++ pEvdev->abs_queued = 1;
++ }
++ /* Direct touch devices use server side pointer emulation */
++ else if (!pInfo->dev->touch || pInfo->dev->touch->mode != XIDirectTouch) {
++ map = pEvdev->axis_map[ev->code];
++ valuator_mask_set(pEvdev->vals, map, value);
++ pEvdev->abs_queued = 1;
++ }
+ }
+
+ /**
+@@ -712,7 +775,7 @@ EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ EvdevPtr pEvdev = pInfo->private;
+
+ if (pEvdev->rel_queued) {
+- xf86PostMotionEventP(pInfo->dev, FALSE, first_v, num_v, v + first_v);
++ xf86PostMotionEventM(pInfo->dev, FALSE, pEvdev->vals);
+ }
+ }
+
+@@ -735,7 +798,7 @@ EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ * this scheme still just work.
+ */
+ if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- xf86PostMotionEventP(pInfo->dev, TRUE, first_v, num_v, v + first_v);
++ xf86PostMotionEventM(pInfo->dev, TRUE, pEvdev->vals);
+ }
+ }
+
+@@ -750,6 +813,9 @@ EvdevPostProximityEvents(InputInfoPtr pInfo, int which, int num_v, int first_v,
+ switch (pEvdev->queue[i].type) {
+ case EV_QUEUE_KEY:
+ case EV_QUEUE_BTN:
++#ifdef MULTITOUCH
++ case EV_QUEUE_TOUCH:
++#endif
+ break;
+ case EV_QUEUE_PROXIMITY:
+ if (pEvdev->queue[i].val == which)
+@@ -772,23 +838,28 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int num_v, int first_v,
+ for (i = 0; i < pEvdev->num_queue; i++) {
+ switch (pEvdev->queue[i].type) {
+ case EV_QUEUE_KEY:
+- xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key,
++ xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val);
+ break;
+ case EV_QUEUE_BTN:
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 11
+ if (pEvdev->abs_queued && pEvdev->in_proximity) {
+- xf86PostButtonEventP(pInfo->dev, 1, pEvdev->queue[i].key,
++ xf86PostButtonEventP(pInfo->dev, 1, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val, first_v, num_v,
+ v + first_v);
+
+ } else
+-#endif
+- xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key,
++ xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].detail.key,
+ pEvdev->queue[i].val, 0, 0);
+ break;
+ case EV_QUEUE_PROXIMITY:
+ break;
++#ifdef MULTITOUCH
++ case EV_QUEUE_TOUCH:
++ xf86PostTouchEvent(pInfo->dev, pEvdev->queue[i].detail.touch,
++ pEvdev->queue[i].val, 0,
++ pEvdev->queue[i].touch_vals);
++ break;
++#endif
+ }
+ }
+ }
+@@ -806,7 +877,8 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
+
+ EvdevProcessProximityState(pInfo);
+
+- EvdevProcessValuators(pInfo, v, &num_v, &first_v);
++ EvdevProcessValuators(pInfo);
++ EvdevProcessTouch(pInfo);
+
+ EvdevPostProximityEvents(pInfo, TRUE, num_v, first_v, v);
+ EvdevPostRelativeMotionEvents(pInfo, num_v, first_v, v);
+@@ -815,7 +887,8 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
+ EvdevPostProximityEvents(pInfo, FALSE, num_v, first_v, v);
+
+ memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
+- memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
++ if (pEvdev->vals)
++ valuator_mask_zero(pEvdev->vals);
+ pEvdev->num_queue = 0;
+ pEvdev->abs_queued = 0;
+ pEvdev->rel_queued = 0;
+@@ -861,7 +934,17 @@ EvdevReadInput(InputInfoPtr pInfo)
+
+ while (len == sizeof(ev))
+ {
+- len = read(pInfo->fd, &ev, sizeof(ev));
++#ifdef MULTITOUCH
++ EvdevPtr pEvdev = pInfo->private;
++
++ if (pEvdev->mtdev)
++ len = mtdev_get(pEvdev->mtdev, pInfo->fd, ev, NUM_EVENTS) *
++ sizeof(struct input_event);
++ else
++ len = read(pInfo->fd, &ev, sizeof(ev));
++#else
++ len = read(pInfo->fd, &ev, sizeof(ev));
++#endif
+ if (len <= 0)
+ {
+ if (errno == ENODEV) /* May happen after resume */
+@@ -900,317 +983,6 @@ EvdevPtrCtrlProc(DeviceIntPtr device, PtrCtrl *ctrl)
+ /* Nothing to do, dix handles all settings */
+ }
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+-static KeySym map[] = {
+- /* 0x00 */ NoSymbol, NoSymbol,
+- /* 0x01 */ XK_Escape, NoSymbol,
+- /* 0x02 */ XK_1, XK_exclam,
+- /* 0x03 */ XK_2, XK_at,
+- /* 0x04 */ XK_3, XK_numbersign,
+- /* 0x05 */ XK_4, XK_dollar,
+- /* 0x06 */ XK_5, XK_percent,
+- /* 0x07 */ XK_6, XK_asciicircum,
+- /* 0x08 */ XK_7, XK_ampersand,
+- /* 0x09 */ XK_8, XK_asterisk,
+- /* 0x0a */ XK_9, XK_parenleft,
+- /* 0x0b */ XK_0, XK_parenright,
+- /* 0x0c */ XK_minus, XK_underscore,
+- /* 0x0d */ XK_equal, XK_plus,
+- /* 0x0e */ XK_BackSpace, NoSymbol,
+- /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,
+- /* 0x10 */ XK_Q, NoSymbol,
+- /* 0x11 */ XK_W, NoSymbol,
+- /* 0x12 */ XK_E, NoSymbol,
+- /* 0x13 */ XK_R, NoSymbol,
+- /* 0x14 */ XK_T, NoSymbol,
+- /* 0x15 */ XK_Y, NoSymbol,
+- /* 0x16 */ XK_U, NoSymbol,
+- /* 0x17 */ XK_I, NoSymbol,
+- /* 0x18 */ XK_O, NoSymbol,
+- /* 0x19 */ XK_P, NoSymbol,
+- /* 0x1a */ XK_bracketleft, XK_braceleft,
+- /* 0x1b */ XK_bracketright,XK_braceright,
+- /* 0x1c */ XK_Return, NoSymbol,
+- /* 0x1d */ XK_Control_L, NoSymbol,
+- /* 0x1e */ XK_A, NoSymbol,
+- /* 0x1f */ XK_S, NoSymbol,
+- /* 0x20 */ XK_D, NoSymbol,
+- /* 0x21 */ XK_F, NoSymbol,
+- /* 0x22 */ XK_G, NoSymbol,
+- /* 0x23 */ XK_H, NoSymbol,
+- /* 0x24 */ XK_J, NoSymbol,
+- /* 0x25 */ XK_K, NoSymbol,
+- /* 0x26 */ XK_L, NoSymbol,
+- /* 0x27 */ XK_semicolon, XK_colon,
+- /* 0x28 */ XK_quoteright, XK_quotedbl,
+- /* 0x29 */ XK_quoteleft, XK_asciitilde,
+- /* 0x2a */ XK_Shift_L, NoSymbol,
+- /* 0x2b */ XK_backslash, XK_bar,
+- /* 0x2c */ XK_Z, NoSymbol,
+- /* 0x2d */ XK_X, NoSymbol,
+- /* 0x2e */ XK_C, NoSymbol,
+- /* 0x2f */ XK_V, NoSymbol,
+- /* 0x30 */ XK_B, NoSymbol,
+- /* 0x31 */ XK_N, NoSymbol,
+- /* 0x32 */ XK_M, NoSymbol,
+- /* 0x33 */ XK_comma, XK_less,
+- /* 0x34 */ XK_period, XK_greater,
+- /* 0x35 */ XK_slash, XK_question,
+- /* 0x36 */ XK_Shift_R, NoSymbol,
+- /* 0x37 */ XK_KP_Multiply, NoSymbol,
+- /* 0x38 */ XK_Alt_L, XK_Meta_L,
+- /* 0x39 */ XK_space, NoSymbol,
+- /* 0x3a */ XK_Caps_Lock, NoSymbol,
+- /* 0x3b */ XK_F1, NoSymbol,
+- /* 0x3c */ XK_F2, NoSymbol,
+- /* 0x3d */ XK_F3, NoSymbol,
+- /* 0x3e */ XK_F4, NoSymbol,
+- /* 0x3f */ XK_F5, NoSymbol,
+- /* 0x40 */ XK_F6, NoSymbol,
+- /* 0x41 */ XK_F7, NoSymbol,
+- /* 0x42 */ XK_F8, NoSymbol,
+- /* 0x43 */ XK_F9, NoSymbol,
+- /* 0x44 */ XK_F10, NoSymbol,
+- /* 0x45 */ XK_Num_Lock, NoSymbol,
+- /* 0x46 */ XK_Scroll_Lock, NoSymbol,
+- /* These KP keys should have the KP_7 keysyms in the numlock
+- * modifer... ? */
+- /* 0x47 */ XK_KP_Home, XK_KP_7,
+- /* 0x48 */ XK_KP_Up, XK_KP_8,
+- /* 0x49 */ XK_KP_Prior, XK_KP_9,
+- /* 0x4a */ XK_KP_Subtract, NoSymbol,
+- /* 0x4b */ XK_KP_Left, XK_KP_4,
+- /* 0x4c */ XK_KP_Begin, XK_KP_5,
+- /* 0x4d */ XK_KP_Right, XK_KP_6,
+- /* 0x4e */ XK_KP_Add, NoSymbol,
+- /* 0x4f */ XK_KP_End, XK_KP_1,
+- /* 0x50 */ XK_KP_Down, XK_KP_2,
+- /* 0x51 */ XK_KP_Next, XK_KP_3,
+- /* 0x52 */ XK_KP_Insert, XK_KP_0,
+- /* 0x53 */ XK_KP_Delete, XK_KP_Decimal,
+- /* 0x54 */ NoSymbol, NoSymbol,
+- /* 0x55 */ XK_F13, NoSymbol,
+- /* 0x56 */ XK_less, XK_greater,
+- /* 0x57 */ XK_F11, NoSymbol,
+- /* 0x58 */ XK_F12, NoSymbol,
+- /* 0x59 */ XK_F14, NoSymbol,
+- /* 0x5a */ XK_F15, NoSymbol,
+- /* 0x5b */ XK_F16, NoSymbol,
+- /* 0x5c */ XK_F17, NoSymbol,
+- /* 0x5d */ XK_F18, NoSymbol,
+- /* 0x5e */ XK_F19, NoSymbol,
+- /* 0x5f */ XK_F20, NoSymbol,
+- /* 0x60 */ XK_KP_Enter, NoSymbol,
+- /* 0x61 */ XK_Control_R, NoSymbol,
+- /* 0x62 */ XK_KP_Divide, NoSymbol,
+- /* 0x63 */ XK_Print, XK_Sys_Req,
+- /* 0x64 */ XK_Alt_R, XK_Meta_R,
+- /* 0x65 */ NoSymbol, NoSymbol, /* KEY_LINEFEED */
+- /* 0x66 */ XK_Home, NoSymbol,
+- /* 0x67 */ XK_Up, NoSymbol,
+- /* 0x68 */ XK_Prior, NoSymbol,
+- /* 0x69 */ XK_Left, NoSymbol,
+- /* 0x6a */ XK_Right, NoSymbol,
+- /* 0x6b */ XK_End, NoSymbol,
+- /* 0x6c */ XK_Down, NoSymbol,
+- /* 0x6d */ XK_Next, NoSymbol,
+- /* 0x6e */ XK_Insert, NoSymbol,
+- /* 0x6f */ XK_Delete, NoSymbol,
+- /* 0x70 */ NoSymbol, NoSymbol, /* KEY_MACRO */
+- /* 0x71 */ NoSymbol, NoSymbol,
+- /* 0x72 */ NoSymbol, NoSymbol,
+- /* 0x73 */ NoSymbol, NoSymbol,
+- /* 0x74 */ NoSymbol, NoSymbol,
+- /* 0x75 */ XK_KP_Equal, NoSymbol,
+- /* 0x76 */ NoSymbol, NoSymbol,
+- /* 0x77 */ NoSymbol, NoSymbol,
+- /* 0x78 */ XK_F21, NoSymbol,
+- /* 0x79 */ XK_F22, NoSymbol,
+- /* 0x7a */ XK_F23, NoSymbol,
+- /* 0x7b */ XK_F24, NoSymbol,
+- /* 0x7c */ XK_KP_Separator, NoSymbol,
+- /* 0x7d */ XK_Meta_L, NoSymbol,
+- /* 0x7e */ XK_Meta_R, NoSymbol,
+- /* 0x7f */ XK_Multi_key, NoSymbol,
+- /* 0x80 */ NoSymbol, NoSymbol,
+- /* 0x81 */ NoSymbol, NoSymbol,
+- /* 0x82 */ NoSymbol, NoSymbol,
+- /* 0x83 */ NoSymbol, NoSymbol,
+- /* 0x84 */ NoSymbol, NoSymbol,
+- /* 0x85 */ NoSymbol, NoSymbol,
+- /* 0x86 */ NoSymbol, NoSymbol,
+- /* 0x87 */ NoSymbol, NoSymbol,
+- /* 0x88 */ NoSymbol, NoSymbol,
+- /* 0x89 */ NoSymbol, NoSymbol,
+- /* 0x8a */ NoSymbol, NoSymbol,
+- /* 0x8b */ NoSymbol, NoSymbol,
+- /* 0x8c */ NoSymbol, NoSymbol,
+- /* 0x8d */ NoSymbol, NoSymbol,
+- /* 0x8e */ NoSymbol, NoSymbol,
+- /* 0x8f */ NoSymbol, NoSymbol,
+- /* 0x90 */ NoSymbol, NoSymbol,
+- /* 0x91 */ NoSymbol, NoSymbol,
+- /* 0x92 */ NoSymbol, NoSymbol,
+- /* 0x93 */ NoSymbol, NoSymbol,
+- /* 0x94 */ NoSymbol, NoSymbol,
+- /* 0x95 */ NoSymbol, NoSymbol,
+- /* 0x96 */ NoSymbol, NoSymbol,
+- /* 0x97 */ NoSymbol, NoSymbol,
+- /* 0x98 */ NoSymbol, NoSymbol,
+- /* 0x99 */ NoSymbol, NoSymbol,
+- /* 0x9a */ NoSymbol, NoSymbol,
+- /* 0x9b */ NoSymbol, NoSymbol,
+- /* 0x9c */ NoSymbol, NoSymbol,
+- /* 0x9d */ NoSymbol, NoSymbol,
+- /* 0x9e */ NoSymbol, NoSymbol,
+- /* 0x9f */ NoSymbol, NoSymbol,
+- /* 0xa0 */ NoSymbol, NoSymbol,
+- /* 0xa1 */ NoSymbol, NoSymbol,
+- /* 0xa2 */ NoSymbol, NoSymbol,
+- /* 0xa3 */ NoSymbol, NoSymbol,
+- /* 0xa4 */ NoSymbol, NoSymbol,
+- /* 0xa5 */ NoSymbol, NoSymbol,
+- /* 0xa6 */ NoSymbol, NoSymbol,
+- /* 0xa7 */ NoSymbol, NoSymbol,
+- /* 0xa8 */ NoSymbol, NoSymbol,
+- /* 0xa9 */ NoSymbol, NoSymbol,
+- /* 0xaa */ NoSymbol, NoSymbol,
+- /* 0xab */ NoSymbol, NoSymbol,
+- /* 0xac */ NoSymbol, NoSymbol,
+- /* 0xad */ NoSymbol, NoSymbol,
+- /* 0xae */ NoSymbol, NoSymbol,
+- /* 0xaf */ NoSymbol, NoSymbol,
+- /* 0xb0 */ NoSymbol, NoSymbol,
+- /* 0xb1 */ NoSymbol, NoSymbol,
+- /* 0xb2 */ NoSymbol, NoSymbol,
+- /* 0xb3 */ NoSymbol, NoSymbol,
+- /* 0xb4 */ NoSymbol, NoSymbol,
+- /* 0xb5 */ NoSymbol, NoSymbol,
+- /* 0xb6 */ NoSymbol, NoSymbol,
+- /* 0xb7 */ NoSymbol, NoSymbol,
+- /* 0xb8 */ NoSymbol, NoSymbol,
+- /* 0xb9 */ NoSymbol, NoSymbol,
+- /* 0xba */ NoSymbol, NoSymbol,
+- /* 0xbb */ NoSymbol, NoSymbol,
+- /* 0xbc */ NoSymbol, NoSymbol,
+- /* 0xbd */ NoSymbol, NoSymbol,
+- /* 0xbe */ NoSymbol, NoSymbol,
+- /* 0xbf */ NoSymbol, NoSymbol,
+- /* 0xc0 */ NoSymbol, NoSymbol,
+- /* 0xc1 */ NoSymbol, NoSymbol,
+- /* 0xc2 */ NoSymbol, NoSymbol,
+- /* 0xc3 */ NoSymbol, NoSymbol,
+- /* 0xc4 */ NoSymbol, NoSymbol,
+- /* 0xc5 */ NoSymbol, NoSymbol,
+- /* 0xc6 */ NoSymbol, NoSymbol,
+- /* 0xc7 */ NoSymbol, NoSymbol,
+- /* 0xc8 */ NoSymbol, NoSymbol,
+- /* 0xc9 */ NoSymbol, NoSymbol,
+- /* 0xca */ NoSymbol, NoSymbol,
+- /* 0xcb */ NoSymbol, NoSymbol,
+- /* 0xcc */ NoSymbol, NoSymbol,
+- /* 0xcd */ NoSymbol, NoSymbol,
+- /* 0xce */ NoSymbol, NoSymbol,
+- /* 0xcf */ NoSymbol, NoSymbol,
+- /* 0xd0 */ NoSymbol, NoSymbol,
+- /* 0xd1 */ NoSymbol, NoSymbol,
+- /* 0xd2 */ NoSymbol, NoSymbol,
+- /* 0xd3 */ NoSymbol, NoSymbol,
+- /* 0xd4 */ NoSymbol, NoSymbol,
+- /* 0xd5 */ NoSymbol, NoSymbol,
+- /* 0xd6 */ NoSymbol, NoSymbol,
+- /* 0xd7 */ NoSymbol, NoSymbol,
+- /* 0xd8 */ NoSymbol, NoSymbol,
+- /* 0xd9 */ NoSymbol, NoSymbol,
+- /* 0xda */ NoSymbol, NoSymbol,
+- /* 0xdb */ NoSymbol, NoSymbol,
+- /* 0xdc */ NoSymbol, NoSymbol,
+- /* 0xdd */ NoSymbol, NoSymbol,
+- /* 0xde */ NoSymbol, NoSymbol,
+- /* 0xdf */ NoSymbol, NoSymbol,
+- /* 0xe0 */ NoSymbol, NoSymbol,
+- /* 0xe1 */ NoSymbol, NoSymbol,
+- /* 0xe2 */ NoSymbol, NoSymbol,
+- /* 0xe3 */ NoSymbol, NoSymbol,
+- /* 0xe4 */ NoSymbol, NoSymbol,
+- /* 0xe5 */ NoSymbol, NoSymbol,
+- /* 0xe6 */ NoSymbol, NoSymbol,
+- /* 0xe7 */ NoSymbol, NoSymbol,
+- /* 0xe8 */ NoSymbol, NoSymbol,
+- /* 0xe9 */ NoSymbol, NoSymbol,
+- /* 0xea */ NoSymbol, NoSymbol,
+- /* 0xeb */ NoSymbol, NoSymbol,
+- /* 0xec */ NoSymbol, NoSymbol,
+- /* 0xed */ NoSymbol, NoSymbol,
+- /* 0xee */ NoSymbol, NoSymbol,
+- /* 0xef */ NoSymbol, NoSymbol,
+- /* 0xf0 */ NoSymbol, NoSymbol,
+- /* 0xf1 */ NoSymbol, NoSymbol,
+- /* 0xf2 */ NoSymbol, NoSymbol,
+- /* 0xf3 */ NoSymbol, NoSymbol,
+- /* 0xf4 */ NoSymbol, NoSymbol,
+- /* 0xf5 */ NoSymbol, NoSymbol,
+- /* 0xf6 */ NoSymbol, NoSymbol,
+- /* 0xf7 */ NoSymbol, NoSymbol,
+-};
+-
+-static struct { KeySym keysym; CARD8 mask; } modifiers[] = {
+- { XK_Shift_L, ShiftMask },
+- { XK_Shift_R, ShiftMask },
+- { XK_Control_L, ControlMask },
+- { XK_Control_R, ControlMask },
+- { XK_Caps_Lock, LockMask },
+- { XK_Alt_L, AltMask },
+- { XK_Alt_R, AltMask },
+- { XK_Meta_L, Mod4Mask },
+- { XK_Meta_R, Mod4Mask },
+- { XK_Num_Lock, NumLockMask },
+- { XK_Scroll_Lock, ScrollLockMask },
+- { XK_Mode_switch, AltLangMask }
+-};
+-
+-/* Server 1.6 and earlier */
+-static int
+-EvdevInitKeysyms(DeviceIntPtr device)
+-{
+- InputInfoPtr pInfo;
+- EvdevPtr pEvdev;
+- KeySymsRec keySyms;
+- CARD8 modMap[MAP_LENGTH];
+- KeySym sym;
+- int i, j;
+-
+- pInfo = device->public.devicePrivate;
+- pEvdev = pInfo->private;
+-
+- /* Compute the modifier map */
+- memset(modMap, 0, sizeof modMap);
+-
+- for (i = 0; i < ArrayLength(map) / GLYPHS_PER_KEY; i++) {
+- sym = map[i * GLYPHS_PER_KEY];
+- for (j = 0; j < ArrayLength(modifiers); j++) {
+- if (modifiers[j].keysym == sym)
+- modMap[i + MIN_KEYCODE] = modifiers[j].mask;
+- }
+- }
+-
+- keySyms.map = map;
+- keySyms.mapWidth = GLYPHS_PER_KEY;
+- keySyms.minKeyCode = MIN_KEYCODE;
+- keySyms.maxKeyCode = MIN_KEYCODE + ArrayLength(map) / GLYPHS_PER_KEY - 1;
+-
+- XkbSetRulesDflts(pEvdev->rmlvo.rules, pEvdev->rmlvo.model,
+- pEvdev->rmlvo.layout, pEvdev->rmlvo.variant,
+- pEvdev->rmlvo.options);
+- if (!XkbInitKeyboardDeviceStruct(device, &pEvdev->xkbnames,
+- &keySyms, modMap, NULL,
+- EvdevKbdCtrl))
+- return 0;
+-
+- return 1;
+-}
+-#endif
+-
+ static void
+ EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl)
+ {
+@@ -1263,14 +1035,8 @@ EvdevAddKeyClass(DeviceIntPtr device)
+ if (!pEvdev->rmlvo.options)
+ SetXkbOption(pInfo, "XkbOptions", &pEvdev->rmlvo.options);
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 5
+ if (!InitKeyboardDeviceStruct(device, &pEvdev->rmlvo, NULL, EvdevKbdCtrl))
+ return !Success;
+-#else
+- if (!EvdevInitKeysyms(device))
+- return !Success;
+-
+-#endif
+
+ return Success;
+ }
+@@ -1280,53 +1046,114 @@ 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;
+ pEvdev = pInfo->private;
+
+ if (!TestBit(EV_ABS, pEvdev->bitmask))
+- return !Success;
++ goto out;
+
+- num_axes = EvdevCountBits(pEvdev->abs_bitmask, NLONGS(ABS_MAX));
+- if (num_axes < 1)
+- return !Success;
++ num_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_MT_SLOT);
++ num_mt_axes = CountBits((uint8_t *)pEvdev->abs_bitmask, ABS_CNT) - num_axes;
+
+ if (num_axes > MAX_VALUATORS) {
+ xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
+ num_axes = MAX_VALUATORS;
+ }
+
++#ifdef MULTITOUCH
++ if (TestBit(ABS_MT_SLOT, pEvdev->abs_bitmask))
++ num_mt_axes--;
++ if (TestBit(ABS_MT_TRACKING_ID, pEvdev->abs_bitmask))
++ num_mt_axes--;
++
++ 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
++
++ if (num_axes < 1 && num_mt_axes < 1) {
++ xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
++ device->name);
++ goto out;
++ }
++
+ pEvdev->num_vals = num_axes;
+- memset(pEvdev->vals, 0, num_axes * sizeof(int));
+- memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
+- atoms = malloc(pEvdev->num_vals * sizeof(Atom));
++ if (num_axes > 0) {
++ pEvdev->vals = valuator_mask_new(num_axes);
++ pEvdev->old_vals = valuator_mask_new(num_axes);
++ if (!pEvdev->vals || !pEvdev->old_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate valuator masks.\n",
++ device->name);
++ goto out;
++ }
++ }
++#ifdef MULTITOUCH
++ pEvdev->num_mt_vals = num_mt_axes;
++ if (num_mt_axes > 0) {
++ pEvdev->mt_vals = valuator_mask_new(num_mt_axes);
++ pEvdev->cur_vals = valuator_mask_new(num_mt_axes);
++ if (!pEvdev->mt_vals || !pEvdev->cur_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
++ device->name);
++ goto out;
++ }
+
++ for (i = 0; i < EVDEV_MAXQUEUE; i++) {
++ pEvdev->queue[i].touch_vals =
++ valuator_mask_new(num_mt_axes);
++ if (!pEvdev->queue[i].touch_vals) {
++ xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
++ "evdev event queue.\n", device->name);
++ goto out;
++ }
++ }
++ }
++#endif
++ atoms = malloc((pEvdev->num_vals + num_mt_axes) * sizeof(Atom));
++
++ i = 0;
+ 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 ||
++ axis == ABS_MT_TRACKING_ID)
+ 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
+- atoms,
+-#endif
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+- GetMotionHistory,
+-#endif
++ if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
+ GetMotionHistorySize(), Absolute)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize valuator class device.\n",
+ device->name);
+- return !Success;
++ goto out;
++ }
++
++#ifdef MULTITOUCH
++ if (num_mt_axes > 0)
++ {
++ int num_touches = 10;
++ int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
++ XIDependentTouch : XIDirectTouch;
++
++ if (pEvdev->mtdev->caps.slot.maximum > 0)
++ num_touches = pEvdev->mtdev->caps.slot.maximum;
++
++ if (!InitTouchClassDeviceStruct(device, num_touches, mode,
++ num_mt_axes)) {
++ xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
++ device->name);
++ goto out;
++ }
+ }
++#endif
+
+- for (axis = ABS_X; axis <= ABS_MAX; axis++) {
++ for (axis = ABS_X; axis < ABS_MT_SLOT; axis++) {
+ int axnum = pEvdev->axis_map[axis];
+ int resolution = 10000;
+
+@@ -1340,20 +1167,32 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ #endif
+
+ xf86InitValuatorAxisStruct(device, axnum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+ atoms[axnum],
+-#endif
+ pEvdev->absinfo[axis].minimum,
+ pEvdev->absinfo[axis].maximum,
+- resolution, 0, resolution
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- , Absolute
+-#endif
+- );
++ resolution, 0, resolution, Absolute);
+ xf86InitValuatorDefaults(device, axnum);
+- pEvdev->old_vals[axnum] = -1;
+ }
+
++#ifdef MULTITOUCH
++ for (axis = ABS_MT_TOUCH_MAJOR; 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++)
+@@ -1364,6 +1203,12 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ if (TestBit(proximity_bits[i], pEvdev->key_bitmask))
+ {
+ InitProximityClassDeviceStruct(device);
++ pEvdev->prox = valuator_mask_new(num_axes);
++ if (!pEvdev->prox) {
++ xf86Msg(X_ERROR, "%s: failed to allocate proximity valuator "
++ "mask.\n", device->name);
++ goto out;
++ }
+ break;
+ }
+ }
+@@ -1371,7 +1216,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize pointer feedback class "
+ "device.\n", device->name);
+- return !Success;
++ goto out;
+ }
+
+ if (pEvdev->flags & EVDEV_TOUCHPAD)
+@@ -1393,6 +1238,18 @@ EvdevAddAbsClass(DeviceIntPtr device)
+ }
+
+ return Success;
++
++out:
++#ifdef MULTITOUCH
++ valuator_mask_free(&pEvdev->mt_vals);
++ valuator_mask_free(&pEvdev->cur_vals);
++ for (i = 0; i < EVDEV_MAXQUEUE; i++)
++ valuator_mask_free(&pEvdev->queue[i].touch_vals);
++#endif
++ valuator_mask_free(&pEvdev->vals);
++ valuator_mask_free(&pEvdev->old_vals);
++ valuator_mask_free(&pEvdev->prox);
++ return !Success;
+ }
+
+ static int
+@@ -1407,11 +1264,11 @@ EvdevAddRelClass(DeviceIntPtr device)
+ pEvdev = pInfo->private;
+
+ if (!TestBit(EV_REL, pEvdev->bitmask))
+- return !Success;
++ goto out;
+
+ num_axes = EvdevCountBits(pEvdev->rel_bitmask, NLONGS(REL_MAX));
+ if (num_axes < 1)
+- return !Success;
++ goto out;
+
+ /* Wheels are special, we post them as button events. So let's ignore them
+ * in the axes list too */
+@@ -1423,7 +1280,7 @@ EvdevAddRelClass(DeviceIntPtr device)
+ num_axes--;
+
+ if (num_axes <= 0)
+- return !Success;
++ goto out;
+
+ if (num_axes > MAX_VALUATORS) {
+ xf86Msg(X_WARNING, "%s: found %d axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
+@@ -1431,7 +1288,11 @@ EvdevAddRelClass(DeviceIntPtr device)
+ }
+
+ pEvdev->num_vals = num_axes;
+- memset(pEvdev->vals, 0, num_axes * sizeof(int));
++ if (num_axes > 0) {
++ pEvdev->vals = valuator_mask_new(num_axes);
++ if (!pEvdev->vals)
++ goto out;
++ }
+ atoms = malloc(pEvdev->num_vals * sizeof(Atom));
+
+ for (axis = REL_X; i < MAX_VALUATORS && axis <= REL_MAX; axis++)
+@@ -1448,23 +1309,17 @@ EvdevAddRelClass(DeviceIntPtr device)
+
+ EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
+
+- if (!InitValuatorClassDeviceStruct(device, num_axes,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- atoms,
+-#endif
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 3
+- GetMotionHistory,
+-#endif
++ if (!InitValuatorClassDeviceStruct(device, num_axes, atoms,
+ GetMotionHistorySize(), Relative)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize valuator class device.\n",
+ device->name);
+- return !Success;
++ goto out;
+ }
+
+ if (!InitPtrFeedbackClassDeviceStruct(device, EvdevPtrCtrlProc)) {
+ xf86Msg(X_ERROR, "%s: failed to initialize pointer feedback class "
+ "device.\n", device->name);
+- return !Success;
++ goto out;
+ }
+
+ for (axis = REL_X; axis <= REL_MAX; axis++)
+@@ -1473,21 +1328,18 @@ EvdevAddRelClass(DeviceIntPtr device)
+
+ if (axnum == -1)
+ continue;
+- xf86InitValuatorAxisStruct(device, axnum,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- atoms[axnum],
+-#endif
+- -1, -1, 1, 0, 1
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+- , Relative
+-#endif
+- );
++ xf86InitValuatorAxisStruct(device, axnum, atoms[axnum], -1, -1, 1, 0, 1,
++ Relative);
+ xf86InitValuatorDefaults(device, axnum);
+ }
+
+ free(atoms);
+
+ return Success;
++
++out:
++ valuator_mask_free(&pEvdev->vals);
++ return !Success;
+ }
+
+ static int
+@@ -1503,10 +1355,7 @@ EvdevAddButtonClass(DeviceIntPtr device)
+ labels = malloc(pEvdev->num_buttons * sizeof(Atom));
+ EvdevInitButtonLabels(pEvdev, pEvdev->num_buttons, labels);
+
+- if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 7
+- labels,
+-#endif
++ if (!InitButtonClassDeviceStruct(device, pEvdev->num_buttons, labels,
+ pEvdev->btnmap))
+ return !Success;
+
+@@ -1678,7 +1527,6 @@ EvdevInit(DeviceIntPtr device)
+ else if (pEvdev->flags & EVDEV_ABSOLUTE_EVENTS)
+ EvdevInitAbsClass(device, pEvdev);
+
+-#ifdef HAVE_PROPERTIES
+ /* We drop the return value, the only time we ever want the handlers to
+ * unregister is when the device dies. In which case we don't have to
+ * unregister anyway */
+@@ -1687,7 +1535,6 @@ EvdevInit(DeviceIntPtr device)
+ EvdevMBEmuInitProperty(device);
+ EvdevWheelEmuInitProperty(device);
+ EvdevDragLockInitProperty(device);
+-#endif
+
+ return Success;
+ }
+@@ -1726,6 +1573,9 @@ EvdevProc(DeviceIntPtr device, int what)
+ {
+ InputInfoPtr pInfo;
+ EvdevPtr pEvdev;
++#ifdef MULTITOUCH
++ int i;
++#endif
+
+ pInfo = device->public.devicePrivate;
+ pEvdev = pInfo->private;
+@@ -1759,6 +1609,17 @@ EvdevProc(DeviceIntPtr device, int what)
+ close(pInfo->fd);
+ pInfo->fd = -1;
+ }
++ valuator_mask_free(&pEvdev->vals);
++ valuator_mask_free(&pEvdev->old_vals);
++ valuator_mask_free(&pEvdev->prox);
++#ifdef MULTITOUCH
++ valuator_mask_free(&pEvdev->mt_vals);
++ valuator_mask_free(&pEvdev->cur_vals);
++ for (i = 0; i < EVDEV_MAXQUEUE; i++)
++ valuator_mask_free(&pEvdev->queue[i].touch_vals);
++ if (pEvdev->mtdev)
++ mtdev_close(pEvdev->mtdev);
++#endif
+ EvdevRemoveDevice(pInfo);
+ pEvdev->min_maj = 0;
+ break;
+@@ -2015,7 +1876,6 @@ EvdevProbe(InputInfoPtr pInfo)
+ if (has_lmr || TestBit(BTN_TOOL_FINGER, pEvdev->key_bitmask)) {
+ xf86Msg(X_PROBED, "%s: Found absolute touchpad.\n", pInfo->name);
+ pEvdev->flags |= EVDEV_TOUCHPAD;
+- memset(pEvdev->old_vals, -1, sizeof(int) * pEvdev->num_vals);
+ } else {
+ xf86Msg(X_PROBED, "%s: Found absolute touchscreen\n", pInfo->name);
+ pEvdev->flags |= EVDEV_TOUCHSCREEN;
+@@ -2135,6 +1995,16 @@ EvdevOpenDevice(InputInfoPtr pInfo)
+
+ pEvdev->device = device;
+ xf86Msg(X_CONFIG, "%s: Device: \"%s\"\n", pInfo->name, device);
++
++#ifdef MULTITOUCH
++ pEvdev->mtdev = malloc(sizeof(struct mtdev));
++ if (!pEvdev->mtdev)
++ {
++ xf86Msg(X_ERROR, "%s: Couldn't allocate mtdev structure\n",
++ pInfo->name);
++ return BadAlloc;
++ }
++#endif
+ }
+
+ if (pInfo->fd < 0)
+@@ -2149,6 +2019,17 @@ EvdevOpenDevice(InputInfoPtr pInfo)
+ }
+ }
+
++#ifdef MULTITOUCH
++ if (mtdev_open(pEvdev->mtdev, pInfo->fd) == 0)
++ pEvdev->cur_slot = pEvdev->mtdev->caps.slot.value;
++ else {
++ free(pEvdev->mtdev);
++ pEvdev->mtdev = NULL;
++ xf86Msg(X_ERROR, "%s: Couldn't open mtdev device\n", pInfo->name);
++ return FALSE;
++ }
++#endif
++
+ /* Check major/minor of device node to avoid adding duplicate devices. */
+ pEvdev->min_maj = EvdevGetMajorMinor(pInfo);
+ if (EvdevIsDuplicate(pInfo))
+@@ -2162,52 +2043,8 @@ EvdevOpenDevice(InputInfoPtr pInfo)
+ return Success;
+ }
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
+-static int NewEvdevPreInit(InputDriverPtr, InputInfoPtr, int);
+-
+-static InputInfoPtr
+-EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
+-{
+- InputInfoPtr pInfo;
+-
+- if (!(pInfo = xf86AllocateInput(drv, 0)))
+- return NULL;
+-
+- /* Initialise the InputInfoRec. */
+- pInfo->fd = -1;
+- pInfo->name = dev->identifier;
+- pInfo->flags = 0;
+- pInfo->history_size = 0;
+- pInfo->control_proc = NULL;
+- pInfo->close_proc = NULL;
+- pInfo->conversion_proc = NULL;
+- pInfo->reverse_conversion_proc = NULL;
+- pInfo->dev = NULL;
+- pInfo->private_flags = 0;
+- pInfo->always_core_feedback = NULL;
+- pInfo->conf_idev = dev;
+- pInfo->private = NULL;
+-
+- xf86CollectInputOptions(pInfo, (const char**)evdevDefaults, NULL);
+- xf86ProcessCommonOptions(pInfo, pInfo->options);
+-
+- if (NewEvdevPreInit(drv, pInfo, flags) == Success)
+- {
+- pInfo->flags |= XI86_CONFIGURED;
+- return pInfo;
+- }
+-
+-
+- xf86DeleteInput(pInfo, 0);
+- return NULL;
+-}
+-
+-static int
+-NewEvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+-#else
+ static int
+ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+-#endif
+ {
+ EvdevPtr pEvdev;
+ int rc = BadAlloc;
+@@ -2225,6 +2062,10 @@ EvdevPreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
+ if (rc != Success)
+ goto error;
+
++#ifdef MULTITOUCH
++ pEvdev->cur_slot = -1;
++#endif
++
+ /*
+ * We initialize pEvdev->in_proximity to 1 so that device that doesn't use
+ * proximity will still report events.
+@@ -2279,9 +2120,7 @@ _X_EXPORT InputDriverRec EVDEV = {
+ EvdevPreInit,
+ NULL,
+ NULL,
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12
+ evdevDefaults
+-#endif
+ };
+
+ static void
+@@ -2356,8 +2195,6 @@ EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code)
+ }
+ }
+
+-#ifdef HAVE_PROPERTIES
+-#ifdef HAVE_LABELS
+ /* Aligned with linux/input.h.
+ Note that there are holes in the ABS_ range, these are simply replaced with
+ MISC here */
+@@ -2411,7 +2248,6 @@ static char* abs_labels[] = {
+ AXIS_LABEL_PROP_ABS_MISC, /* undefined */
+ AXIS_LABEL_PROP_ABS_MISC, /* undefined */
+ AXIS_LABEL_PROP_ABS_MISC, /* undefined */
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 10
+ AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR, /* 0x30 */
+ AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR, /* 0x31 */
+ AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR, /* 0x32 */
+@@ -2423,7 +2259,6 @@ static char* abs_labels[] = {
+ AXIS_LABEL_PROP_ABS_MT_BLOB_ID, /* 0x38 */
+ AXIS_LABEL_PROP_ABS_MT_TRACKING_ID, /* 0x39 */
+ AXIS_LABEL_PROP_ABS_MT_PRESSURE, /* 0x3a */
+-#endif
+ };
+
+ static char* rel_labels[] = {
+@@ -2520,11 +2355,8 @@ static char* btn_labels[][16] = {
+ }
+ };
+
+-#endif /* HAVE_LABELS */
+-
+ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
+ {
+-#ifdef HAVE_LABELS
+ Atom atom;
+ int axis;
+ char **labels;
+@@ -2557,12 +2389,10 @@ static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
+
+ atoms[pEvdev->axis_map[axis]] = atom;
+ }
+-#endif
+ }
+
+ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
+ {
+-#ifdef HAVE_LABELS
+ Atom atom;
+ int button, bmap;
+
+@@ -2600,7 +2430,6 @@ static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms)
+ atoms[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+ if (natoms > 6)
+ atoms[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+-#endif
+ }
+
+ static void
+@@ -2659,11 +2488,10 @@ EvdevInitProperty(DeviceIntPtr dev)
+
+ XISetDevicePropertyDeletable(dev, prop_swap, FALSE);
+
+-#ifdef HAVE_LABELS
+ /* Axis labelling */
+ if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP)))
+ {
+- Atom atoms[pEvdev->num_vals];
++ Atom atoms[pEvdev->num_vals + pEvdev->num_mt_vals];
+ EvdevInitAxesLabels(pEvdev, pEvdev->num_vals, atoms);
+ XIChangeDeviceProperty(dev, prop_axis_label, XA_ATOM, 32,
+ PropModeReplace, pEvdev->num_vals, atoms, FALSE);
+@@ -2678,7 +2506,6 @@ EvdevInitProperty(DeviceIntPtr dev)
+ PropModeReplace, pEvdev->num_buttons, atoms, FALSE);
+ XISetDevicePropertyDeletable(dev, prop_btn_label, FALSE);
+ }
+-#endif /* HAVE_LABELS */
+ }
+
+ }
+@@ -2723,4 +2550,3 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
+
+ return Success;
+ }
+-#endif
+diff --git a/src/evdev.h b/src/evdev.h
+index f640fdd..a590eaf 100644
+--- a/src/evdev.h
++++ b/src/evdev.h
+@@ -39,6 +39,16 @@
+ #include <xf86_OSproc.h>
+ #include <xkbstr.h>
+
++#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) * 100 + GET_ABI_MINOR(ABI_XINPUT_VERSION) < 1202
++#error "Need X server input ABI version 12.2 or greater"
++#endif
++
++#define MULTITOUCH /* Will be at least ABI 13.1, but it's not there yet */
++
++#ifdef MULTITOUCH
++#include <mtdev.h>
++#endif
++
+ #ifndef EV_CNT /* linux 2.6.23 kernels and earlier lack _CNT defines */
+ #define EV_CNT (EV_MAX+1)
+ #endif
+@@ -72,26 +82,10 @@
+ #define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
+ #define EVDEV_RELATIVE_MODE (1 << 11) /* Force relative events for devices with absolute axes */
+
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
+-#define HAVE_PROPERTIES 1
+-#endif
+-
+ #ifndef MAX_VALUATORS
+ #define MAX_VALUATORS 36
+ #endif
+
+-
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+-typedef struct {
+- char *rules;
+- char *model;
+- char *layout;
+- char *variant;
+- char *options;
+-} XkbRMLVOSet;
+-#endif
+-
+-
+ #define LONG_BITS (sizeof(long) * 8)
+
+ /* Number of longs needed to hold the given number of bits */
+@@ -110,9 +104,20 @@ typedef struct {
+ EV_QUEUE_KEY, /* xf86PostKeyboardEvent() */
+ EV_QUEUE_BTN, /* xf86PostButtonEvent() */
+ EV_QUEUE_PROXIMITY, /* xf86PostProximityEvent() */
++#ifdef MULTITOUCH
++ EV_QUEUE_TOUCH, /*xf86PostTouchEvent() */
++#endif
+ } type;
+- int key; /* May be either a key code or button number. */
+- int val; /* State of the key/button; pressed or released. */
++ union {
++ int key; /* May be either a key code or button number. */
++#ifdef MULTITOUCH
++ unsigned int touch; /* Touch ID */
++#endif
++ } detail;
++ int val; /* State of the key/button/touch; pressed or released. */
++#ifdef MULTITOUCH
++ ValuatorMask *touch_vals; /* current state of valuators for touch */
++#endif
+ } EventQueueRec, *EventQueuePtr;
+
+ typedef struct {
+@@ -121,8 +126,18 @@ typedef struct {
+
+ int num_vals; /* number of valuators */
+ int axis_map[max(ABS_CNT, REL_CNT)]; /* Map evdev <axis> to index */
+- int vals[MAX_VALUATORS];
+- int old_vals[MAX_VALUATORS]; /* Translate absolute inputs to relative */
++ ValuatorMask *vals; /* new values coming in */
++ ValuatorMask *old_vals; /* old values for calculating relative motion */
++ ValuatorMask *prox; /* last values set while not in proximity */
++#ifdef MULTITOUCH
++ int num_mt_vals;
++ ValuatorMask *mt_vals; /* multitouch values coming in */
++ ValuatorMask *cur_vals; /* current values of MT axes in evdev state */
++ int cur_slot;
++ BOOL close_slot;
++ BOOL open_slot;
++ struct mtdev *mtdev;
++#endif
+
+ int flags;
+ int in_proximity; /* device in proximity */
+@@ -134,12 +149,8 @@ typedef struct {
+
+ int delta[REL_CNT];
+ unsigned int abs_queued, rel_queued, prox_queued;
+- unsigned int abs_prox; /* valuators posted while out of prox? */
+
+ /* XKB stuff has to be per-device rather than per-driver */
+-#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
+- XkbComponentNamesRec xkbnames;
+-#endif
+ XkbRMLVOSet rmlvo;
+
+ /* Middle mouse button emulation */
+@@ -202,6 +213,10 @@ typedef struct {
+ void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value);
+ void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value);
+ void EvdevQueueProximityEvent(InputInfoPtr pInfo, int value);
++#ifdef MULTITOUCH
++void EvdevQueueTouchEvent(InputInfoPtr pInfo, unsigned int touch,
++ ValuatorMask *mask, uint16_t type);
++#endif
+ void EvdevPostButtonEvent(InputInfoPtr pInfo, int button, int value);
+ void EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count);
+ void EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int num_v, int first_v,
+@@ -228,9 +243,7 @@ BOOL EvdevWheelEmuFilterMotion(InputInfoPtr pInfo, struct input_event *pEv);
+ void EvdevDragLockPreInit(InputInfoPtr pInfo);
+ BOOL EvdevDragLockFilterEvent(InputInfoPtr pInfo, unsigned int button, int value);
+
+-#ifdef HAVE_PROPERTIES
+ void EvdevMBEmuInitProperty(DeviceIntPtr);
+ void EvdevWheelEmuInitProperty(DeviceIntPtr);
+ void EvdevDragLockInitProperty(DeviceIntPtr);
+ #endif
+-#endif