summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--man/evdev.man5
-rw-r--r--src/evdev.c56
3 files changed, 62 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 9d8d0a7..759c1ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,6 +55,9 @@ AC_ARG_WITH(xorg-module-dir,
inputdir=${moduledir}/input
AC_SUBST(inputdir)
+# Checks for extensions
+XORG_DRIVER_CHECK_EXT(XINPUT, inputproto)
+
# Checks for pkg-config packages. We need to be able to override sdkdir
# to satisfy silly distcheck requirements.
PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
diff --git a/man/evdev.man b/man/evdev.man
index 4771167..bc2ee97 100644
--- a/man/evdev.man
+++ b/man/evdev.man
@@ -159,6 +159,11 @@ originally reported by the kernel (e.g. touchscreens). The scaling to the
custom coordinate system is done in-driver and the X server is unaware of
the transformation. Property: "Evdev Axis Calibration".
.TP 7
+.B Option \*qMode\*q \*qRelative\*q\fP|\fP\*qAbsolute\*q
+Sets the mode of the device if device has absolute axes.
+The default value for touchpads is relative, for other absolute.
+This option has no effect on devices without absolute axes.
+.TP 7
.BI "Option \*qSwapAxes\*q \*q" Bool \*q
Swap x/y axes. Default: off. Property: "Evdev Axes Swap".
.TP 7
diff --git a/src/evdev.c b/src/evdev.c
index 7e65c69..58ffcea 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -32,6 +32,7 @@
#endif
#include <X11/keysym.h>
+#include <X11/extensions/XI.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -92,6 +93,7 @@
#define EVDEV_TABLET (1 << 8) /* device looks like a tablet? */
#define EVDEV_UNIGNORE_ABSOLUTE (1 << 9) /* explicitly unignore abs axes */
#define EVDEV_UNIGNORE_RELATIVE (1 << 10) /* explicitly unignore rel axes */
+#define EVDEV_RELATIVE_MODE (1 << 11) /* Force relative events for devices with absolute axes */
#define MIN_KEYCODE 8
#define GLYPHS_PER_KEY 2
@@ -117,6 +119,7 @@ static const char *evdevDefaults[] = {
static int EvdevOn(DeviceIntPtr);
static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
+static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode);
#ifdef HAVE_PROPERTIES
static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms);
@@ -136,6 +139,38 @@ static Atom prop_btn_label = 0;
* cannot be used by evdev, leaving us with a space of 2 at the end. */
static EvdevPtr evdev_devices[MAXDEVICES] = {NULL};
+static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode)
+{
+ InputInfoPtr pInfo;
+ EvdevPtr pEvdev;
+
+ pInfo = device->public.devicePrivate;
+ pEvdev = pInfo->private;
+
+ if (pEvdev->flags & EVDEV_RELATIVE_EVENTS)
+ {
+ if (mode == Relative)
+ return Success;
+ else
+ return XI_BadMode;
+ }
+
+ switch (mode) {
+ case Absolute:
+ pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
+ break;
+
+ case Relative:
+ pEvdev->flags |= EVDEV_RELATIVE_MODE;
+ break;
+
+ default:
+ return XI_BadMode;
+ }
+
+ return Success;
+}
+
static size_t CountBits(unsigned long *array, size_t nlongs)
{
unsigned int i;
@@ -341,7 +376,7 @@ EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
*num_v = *first_v = 0;
/* convert to relative motion for touchpads */
- if (pEvdev->abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
+ if (pEvdev->abs && (pEvdev->flags & EVDEV_RELATIVE_MODE)) {
if (pEvdev->tool) { /* meaning, touch is active */
if (pEvdev->old_vals[0] != -1)
pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
@@ -1129,6 +1164,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
EvdevPtr pEvdev;
int num_axes, axis, i = 0;
Atom *atoms;
+ const char *mode;
pInfo = device->public.devicePrivate;
pEvdev = pInfo->private;
@@ -1200,6 +1236,22 @@ EvdevAddAbsClass(DeviceIntPtr device)
TestBit(ABS_TILT_Y, pEvdev->abs_bitmask)))
pInfo->flags |= XI86_POINTER_CAPABLE;
+ if (pEvdev->flags & EVDEV_TOUCHPAD)
+ pEvdev->flags |= EVDEV_RELATIVE_MODE;
+ else
+ pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
+
+ if (xf86FindOption(pInfo->options, "Mode"))
+ {
+ mode = xf86SetStrOption(pInfo->options, "Mode", NULL);
+ if (!strcasecmp("absolute", mode))
+ pEvdev->flags &= ~EVDEV_RELATIVE_MODE;
+ else if (!strcasecmp("relative", mode))
+ pEvdev->flags |= EVDEV_RELATIVE_MODE;
+ else
+ xf86Msg(X_INFO, "%s: unknown mode, use default\n", pInfo->name);
+ }
+
return Success;
}
@@ -1966,7 +2018,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
pInfo->history_size = 0;
pInfo->control_proc = NULL;
pInfo->close_proc = NULL;
- pInfo->switch_mode = NULL;
+ pInfo->switch_mode = EvdevSwitchMode;
pInfo->conversion_proc = NULL;
pInfo->reverse_conversion_proc = NULL;
pInfo->dev = NULL;