diff options
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.patch | 1678 |
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 |