aboutsummaryrefslogtreecommitdiff
path: root/src
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 /src
parentUpdate Sun license notices to current X.Org standard form (diff)
downloadxf86-input-evdev-e81cd935cfff18d3c387eed3e8083977c19c92f0.tar.gz
xf86-input-evdev-e81cd935cfff18d3c387eed3e8083977c19c92f0.tar.bz2
xf86-input-evdev-e81cd935cfff18d3c387eed3e8083977c19c92f0.zip
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>
Diffstat (limited to 'src')
-rw-r--r--src/evdev.c56
1 files changed, 54 insertions, 2 deletions
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;