From 5b482fb421602889cff91a148b750218de4690b7 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 | 5 +++- dix/devices.c | 55 ++++++++++++++++++++++++++++++++++++++++++ dix/getevents.c | 32 ++++++++++++++++++++++++ include/inputstr.h | 4 +++ include/xserver-properties.h | 8 ++++++ 5 files changed, 103 insertions(+), 1 deletions(-) diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index cd49460..cdc6f4f 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -165,7 +165,10 @@ static struct dev_properties {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP}, {0, BTN_LABEL_PROP_BTN_GEAR_DOWN}, - {0, BTN_LABEL_PROP_BTN_GEAR_UP} + {0, BTN_LABEL_PROP_BTN_GEAR_UP}, + + {0, XI_PROP_INVERT_AXIS}, + {0, XI_PROP_MAP_AXIS} }; static long XIPropHandlerID = 1; diff --git a/dix/devices.c b/dix/devices.c index b237e03..85e3e9d 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -118,6 +118,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) @@ -136,6 +137,35 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, DisableDevice(dev, TRUE); } } + 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; } @@ -201,6 +231,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; @@ -249,11 +280,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; @@ -363,6 +402,22 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) 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); + } + SendDevicePresenceEvent(dev->id, DeviceEnabled); if (sendevent) { diff --git a/dix/getevents.c b/dix/getevents.c index 7c018c1..7fa6b66 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -817,6 +817,32 @@ updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms) } /** + * 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. */ @@ -888,6 +914,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, set_raw_valuators(raw, first_valuator, num_valuators, valuators, raw->valuators.data_raw); + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); + if (num_valuators) clipValuators(pDev, first_valuator, num_valuators, valuators); @@ -990,6 +1018,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. @@ -1045,6 +1074,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, set_raw_valuators(raw, first_valuator, num_valuators, valuators, raw->valuators.data_raw); + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); + if (flags & POINTER_ABSOLUTE) { if (flags & POINTER_SCREEN) /* valuators are in screen coords */ @@ -1149,6 +1180,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, init_event(pDev, event, GetTimeInMillis()); event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; + invertAndMapValuators(pDev, first_valuator, num_valuators, valuators); if (num_valuators) clipValuators(pDev, first_valuator, num_valuators, valuators); diff --git a/include/inputstr.h b/include/inputstr.h index b284ea4..8654fd4 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -533,6 +533,10 @@ typedef struct _DeviceIntRec { XIPropertyPtr properties; XIPropertyHandlerPtr handlers; /* NULL-terminated */ } properties; + + /* Axis inversion and mapping */ + BOOL invert[MAX_VALUATORS]; + CARD8 axis_map[MAX_VALUATORS]; } DeviceIntRec; typedef struct { diff --git a/include/xserver-properties.h b/include/xserver-properties.h index 9b3b7bf..1fc7405 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -168,4 +168,12 @@ #define BTN_LABEL_PROP_BTN_GEAR_DOWN "Button Gear down" #define BTN_LABEL_PROP_BTN_GEAR_UP "Button Gear up" +/* 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