summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrej Gelenberg <andrej.gelenberg@udo.edu>2010-01-12 11:22:16 +0100
committerPeter Hutterer <peter.hutterer@who-t.net>2010-01-19 21:40:06 +1300
commite81cd935cfff18d3c387eed3e8083977c19c92f0 (patch)
tree6850583673cfde093045a4db101c127188c73539
parent0b5844ce677a99110730ac885fc990c4b8f4bfa9 (diff)
Implement XSetDeviceMode request handler
Implement XSetDeviceMode request handler for evdev. Devices with absolute axes can be switched in relative mode or absolute mode. Devices with relative axes can be switched only in relative mode. Other devices return BadMatch, cause they have no valuators and don't report motion events. New option "Mode" force devices with absolute axes to work in relative or absolute mode. Need xinputproto. Signed-off-by: Andrej Gelenberg <andrej.gelenberg@udo.edu>
-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;