From 6c7a0e843925d2dc9bf0287c876a3da1daf835be Mon Sep 17 00:00:00 2001 From: Paolo D'Apice Date: Mon, 28 Mar 2011 15:25:51 +0800 Subject: [PATCH] Added "AxesRotation" property. The evdev driver does not allow to set a custom axes rotation as the mousedrv driver does with the option "AngleOffset". This option is necessary for some trackballs, for example the Logitech Cordless Optical TrackMan which has the optical sensor off-axes (in MS Windows, the Logitech proprietary driver adjusts the offset). X.Org Bug 27688 Signed-off-by: Paolo D'Apice --- include/evdev-properties.h | 4 +++ man/evdev.man | 14 +++++++++++++ src/evdev.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ src/evdev.h | 7 ++++++ 4 files changed, 72 insertions(+), 0 deletions(-) diff --git a/include/evdev-properties.h b/include/evdev-properties.h index 16f2af7..01f9da3 100644 --- a/include/evdev-properties.h +++ b/include/evdev-properties.h @@ -75,4 +75,8 @@ /* CARD32 */ #define EVDEV_PROP_THIRDBUTTON_THRESHOLD "Evdev Third Button Emulation Threshold" +/* Axes Rotation */ +/* INT16 */ +#define EVDEV_PROP_AXES_ROTATION "Evdev Axes Rotation" + #endif diff --git a/man/evdev.man b/man/evdev.man index 931e1a1..0ac450c 100644 --- a/man/evdev.man +++ b/man/evdev.man @@ -202,6 +202,17 @@ This option has no effect on devices without absolute axes. .BI "Option \*qSwapAxes\*q \*q" Bool \*q Swap x/y axes. Default: off. Property: "Evdev Axes Swap". .TP 7 +.BI "Option \*qAxesRotation\*q \*q" integer \*q +Axes rotation (in 1/10 of degree) to apply to the pointer motion. +A positive value means clockwise rotation, a negative value means +counter-clockwise rotation. +This transformation is applied before the +.BR SwapAxes , +.BR InvertX +and +.B InvertY +transformations. Default: 0. Property: "Evdev Axes Rotation". +.TP 7 .BI "Option \*qXAxisMapping\*q \*q" "N1 N2" \*q Specifies which buttons are mapped to motion in the X direction in wheel emulation mode. Button number @@ -235,6 +246,9 @@ in-driver axis calibration. .BI "Evdev Axes Swap" 1 boolean value (8 bit, 0 or 1). 1 swaps x/y axes. .TP 7 +.BI "Evdev Axes Rotation" +1 16-bit signed value. 0 disables rotation. +.TP 7 .BI "Evdev Drag Lock Buttons" 8-bit. Either 1 value or pairs of values. Value range 0-32, 0 disables a value. diff --git a/src/evdev.c b/src/evdev.c index ab46277..59eb0ab 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,7 @@ static int EvdevSwitchMode(ClientPtr client, DeviceIntPtr device, int mode); 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); +static void EvdevSetAxesRotation(InputInfoPtr pInfo, int rotation); static void EvdevInitAxesLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); static void EvdevInitButtonLabels(EvdevPtr pEvdev, int natoms, Atom *atoms); @@ -113,6 +115,7 @@ static Atom prop_calibration; static Atom prop_swap; static Atom prop_axis_label; static Atom prop_btn_label; +static Atom prop_axes_rotation; /* All devices the evdev driver has allocated and knows about. * MAXDEVICES is safe as null-terminated array, as two devices (VCP and VCK) @@ -386,6 +389,14 @@ EvdevProcessValuators(InputInfoPtr pInfo) if (pEvdev->rel_queued) { int i; + if (pEvdev->axes_rotation.value) { + tmp = pEvdev->delta[REL_X]; + pEvdev->delta[REL_X] = (int)(pEvdev->delta[REL_X] * pEvdev->axes_rotation.cosine + - pEvdev->delta[REL_Y] * pEvdev->axes_rotation.sine); + pEvdev->delta[REL_Y] = (int)(pEvdev->delta[REL_Y] * pEvdev->axes_rotation.cosine + + tmp * pEvdev->axes_rotation.sine); + } + if (pEvdev->swap_axes) { tmp = pEvdev->delta[REL_X]; pEvdev->delta[REL_X] = pEvdev->delta[REL_Y]; @@ -1703,12 +1714,19 @@ EvdevProbe(InputInfoPtr pInfo) if (has_rel_axes || has_abs_axes) { char *str; + int rotation = 0; int num_calibration = 0, calibration[4] = { 0, 0, 0, 0 }; pEvdev->invert_x = xf86SetBoolOption(pInfo->options, "InvertX", FALSE); pEvdev->invert_y = xf86SetBoolOption(pInfo->options, "InvertY", FALSE); pEvdev->swap_axes = xf86SetBoolOption(pInfo->options, "SwapAxes", FALSE); + rotation = xf86SetIntOption(pInfo->options, "AxesRotation", 0); + EvdevSetAxesRotation(pInfo, rotation); + if (rotation) { + xf86Msg(X_CONFIG, "%s: AxesRotation: %.1f degrees\n", pInfo->name, (float)(rotation)/10); + } + str = xf86CheckStrOption(pInfo->options, "Calibration", NULL); if (str) { num_calibration = sscanf(str, "%d %d %d %d", @@ -1784,6 +1802,18 @@ EvdevSetCalibration(InputInfoPtr pInfo, int num_calibration, int calibration[4]) } } +static void +EvdevSetAxesRotation(InputInfoPtr pInfo, int rotation) +{ + EvdevPtr pEvdev = pInfo->private; + + pEvdev->axes_rotation.value = rotation; + float radians = (rotation % 3600) * M_PI / 1800.0; + + pEvdev->axes_rotation.cosine = cos(radians); + pEvdev->axes_rotation.sine = sin(radians); +} + static int EvdevOpenDevice(InputInfoPtr pInfo) { @@ -2282,6 +2312,16 @@ EvdevInitProperty(DeviceIntPtr dev) XISetDevicePropertyDeletable(dev, prop_swap, FALSE); + prop_axes_rotation = MakeAtom(EVDEV_PROP_AXES_ROTATION, + strlen(EVDEV_PROP_AXES_ROTATION), TRUE); + + rc = XIChangeDeviceProperty(dev, prop_axes_rotation, XA_INTEGER, 16, + PropModeReplace, 1, &pEvdev->axes_rotation.value, FALSE); + if (rc != Success) + return; + + XISetDevicePropertyDeletable(dev, prop_axes_rotation, FALSE); + /* Axis labelling */ if ((pEvdev->num_vals > 0) && (prop_axis_label = XIGetKnownProperty(AXIS_LABEL_PROP))) { @@ -2339,6 +2379,13 @@ EvdevSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, if (!checkonly) pEvdev->swap_axes = *((BOOL*)val->data); + } else if (atom == prop_axes_rotation) + { + if (val->format != 16 || val->type != XA_INTEGER) + return BadMatch; + + if (!checkonly) + EvdevSetAxesRotation(pInfo, *((INT16*)val->data)); } else if (atom == prop_axis_label || atom == prop_btn_label) return BadAccess; /* Axis/Button labels can't be changed */ diff --git a/src/evdev.h b/src/evdev.h index c16ccb2..c20f62b 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -121,6 +121,13 @@ typedef struct { BOOL invert_x; BOOL invert_y; + /* Axes rotation */ + struct { + int value; /* axes rotation in 1/10 of degree */ + float cosine; + float sine; + } axes_rotation; + int delta[REL_CNT]; unsigned int abs_queued, rel_queued, prox_queued; -- 1.7.4.1