From 20b6268d8081d59b6a4d35e40023810d81cfe9a0 Mon Sep 17 00:00:00 2001 From: Eric Piel Date: Sun, 24 May 2009 13:43:13 +0200 Subject: [PATCH] xinput: add inversion and axis mapping input properties Inversion and axis mapping properties of a pointer device allow to change the default direct mapping between the physical valuators and the deplacement of the pointer. The main goal is to have the devices follow the same rotation/reflection as the display. The evdev has already similar properties, but with this patch all the pointer devices benefits of them. --- Xi/xiproperty.c | 2 + dix/devices.c | 55 ++++++++++++++++++++++++++++++++++++++++++ dix/getevents.c | 31 +++++++++++++++++++++++ include/inputstr.h | 4 +++ include/xserver-properties.h | 8 ++++++ 5 files changed, 100 insertions(+), 0 deletions(-) diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index b04ee94..120ad71 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -50,6 +50,8 @@ static struct dev_properties char *name; } dev_properties[] = { {0, XI_PROP_ENABLED}, + {0, XI_PROP_INVERT_AXIS}, + {0, XI_PROP_MAP_AXIS}, {0, XATOM_FLOAT} }; diff --git a/dix/devices.c b/dix/devices.c index 0858f20..02cdaf7 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -107,6 +107,7 @@ static int DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, BOOL checkonly) { + int i; if (property == XIGetKnownProperty(XI_PROP_ENABLED)) { if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1) @@ -125,6 +126,35 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, DisableDevice(dev); } } + else if (property == XIGetKnownProperty(XI_PROP_INVERT_AXIS)) + { + if (prop->format != 8 || prop->type != XA_INTEGER || + dev->valuator == NULL || prop->size != dev->valuator->numAxes) + return BadValue; + + if (!checkonly) + { + BOOL *invert = (BOOL*)prop->data; + for (i = 0; i < prop->size; i++) + dev->invert[i] = !!invert[i]; + } + } + else if (property == XIGetKnownProperty(XI_PROP_MAP_AXIS)) + { + if (prop->format != 8 || prop->type != XA_INTEGER || + dev->valuator == NULL || prop->size != dev->valuator->numAxes) + return BadValue; + + CARD8 *axis_map = (CARD8*)prop->data; + /* Can only map to an existing axis (but we don't mind several axis mapped to the same one */ + for (i = 0; i < prop->size; i++) + if (axis_map[i] >= dev->valuator->numAxes) + return BadValue; + + if (!checkonly) + for (i = 0; i < prop->size; i++) + dev->axis_map[i] = axis_map[i]; + } return Success; } @@ -190,6 +220,7 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) DeviceIntPtr dev, *prev; /* not a typo */ DeviceIntPtr devtmp; int devid; + int i; char devind[MAXDEVICES]; BOOL enabled; @@ -236,11 +267,19 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) *prev = dev; dev->next = NULL; + /* Input properties */ enabled = FALSE; XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED), XA_INTEGER, 8, PropModeReplace, 1, &enabled, FALSE); XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE); + + for (i = 0; i < MAX_VALUATORS; i++) + { + dev->invert[i] = FALSE; + dev->axis_map[i] = i; + } + XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); return dev; @@ -335,6 +374,22 @@ EnableDevice(DeviceIntPtr dev) XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE); + /* Properties only for pointer devices */ + if (dev->valuator != NULL) + { + int ret; + Atom prop; + prop = XIGetKnownProperty(XI_PROP_INVERT_AXIS); + ret = XIChangeDeviceProperty(dev, prop, XA_INTEGER, 8, PropModeReplace, + dev->valuator->numAxes, dev->invert, FALSE); + XISetDevicePropertyDeletable(dev, prop, FALSE); + + prop = XIGetKnownProperty(XI_PROP_MAP_AXIS); + ret = XIChangeDeviceProperty(dev, prop, XA_INTEGER, 8, PropModeReplace, + dev->valuator->numAxes, dev->axis_map, FALSE); + XISetDevicePropertyDeletable(dev, prop, FALSE); + } + ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceEnabled; diff --git a/dix/getevents.c b/dix/getevents.c index 9747b35..b1bb2d7 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -735,6 +735,32 @@ countValuatorEvents(int num_valuators) } /** + * Invert and remap the axes of a device according to its input properties + * @param pDev The device which's pointer is to be moved. + * @param first The first valuator in @valuators + * @param num Total number of valuators in @valuators. + * @param valuators Valuator data for each axis between @first and + * @first+@num. + */ +static void +invertAndMapValuators(DeviceIntPtr pDev, int first, int num, int *valuators) +{ + int i; + int tmp[num]; + + /* invert the valuators */ + for (i = 0; i < num; i++) + if (pDev->invert[i + first]) + valuators[i] = -valuators[i]; + + /* remap */ + for (i = 0; i < num; i++) + tmp[i] = valuators[pDev->axis_map[i + first] - first]; + for (i = 0; i < num; i++) + valuators[i] = tmp[i]; +} + +/** * Convenience wrapper around GetKeyboardValuatorEvents, that takes no * valuators. */ @@ -850,6 +876,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, events++; if (num_valuators) { kbp->deviceid |= MORE_EVENTS; + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); clipValuators(pDev, first_valuator, num_valuators, valuators); events = getValuatorEvents(events, pDev, first_valuator, num_valuators, valuators); @@ -933,6 +960,7 @@ FreeEventList(EventListPtr list, int num_events) xfree(list); } + /** * Generate a series of xEvents (filled into the EventList) representing * pointer motion, or button presses. Xi and XKB-aware. @@ -976,6 +1004,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, events = updateFromMaster(events, pDev, &num_events); + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); + if (flags & POINTER_ABSOLUTE) { if (flags & POINTER_SCREEN) /* valuators are in screen coords */ @@ -1089,6 +1119,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, if (num_valuators) { kbp->deviceid |= MORE_EVENTS; events++; + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); clipValuators(pDev, first_valuator, num_valuators, valuators); events = getValuatorEvents(events, pDev, first_valuator, num_valuators, valuators); diff --git a/include/inputstr.h b/include/inputstr.h index a6f823c..3fc05db 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -475,6 +475,10 @@ typedef struct _DeviceIntRec { int numValuators; } last; + /* Axis inversion and mapping */ + BOOL invert[MAX_VALUATORS]; + CARD8 axis_map[MAX_VALUATORS]; + /* Input device property handling. */ struct { XIPropertyPtr properties; diff --git a/include/xserver-properties.h b/include/xserver-properties.h index f8aeab6..ee808bf 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -33,4 +33,12 @@ /* BOOL. 0 - device disabled, 1 - device enabled */ #define XI_PROP_ENABLED "Device Enabled" +/* Axis inversion */ +/* BOOL, list as long as there are axes in the device, 1 inverts axis */ +#define XI_PROP_INVERT_AXIS "Axis Inversion" + +/* Axis mapping */ +/* CARD8, list as long as there are axes in the device, 0 1 2... is the default */ +#define XI_PROP_MAP_AXIS "Axis Mapping" + #endif -- 1.6.3.2