diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 0a47e31..b9efea1 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -166,7 +166,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 32fd445..d18ddfe 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -119,6 +119,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) @@ -137,6 +138,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->valuator->axes[i].invert = !!invert[i]; + } + } + else if (property == XIGetKnownProperty(XI_PROP_MAP_AXIS)) + { + CARD8 *axis_map = (CARD8*)prop->data; + if (prop->format != 8 || prop->type != XA_INTEGER || + dev->valuator == NULL || prop->size != dev->valuator->numAxes) + return BadValue; + + /* 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->valuator->axes[i].map = axis_map[i]; + } return Success; } @@ -250,11 +280,13 @@ 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); + XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL); return dev; @@ -364,6 +396,31 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) XA_INTEGER, 8, PropModeReplace, 1, &enabled, TRUE); + /* Properties only for pointer devices */ + if (dev->valuator != NULL) + { + int ret, i; + Atom prop; + BOOL invert[MAX_VALUATORS]; + CARD8 axis_map[MAX_VALUATORS]; + + for (i = 0; i < MAX_VALUATORS; i++) + { + invert[i] = FALSE; + axis_map[i] = i; + } + + prop = XIGetKnownProperty(XI_PROP_INVERT_AXIS); + ret = XIChangeDeviceProperty(dev, prop, XA_INTEGER, 8, PropModeReplace, + dev->valuator->numAxes, invert, FALSE); + XISetDevicePropertyDeletable(dev, prop, FALSE); + + prop = XIGetKnownProperty(XI_PROP_MAP_AXIS); + ret = XIChangeDeviceProperty(dev, prop, XA_INTEGER, 8, PropModeReplace, + dev->valuator->numAxes, axis_map, FALSE); + XISetDevicePropertyDeletable(dev, prop, FALSE); + } + SendDevicePresenceEvent(dev->id, DeviceEnabled); if (sendevent) { diff --git a/dix/getevents.c b/dix/getevents.c index 5f00954..1e0e202 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -838,6 +838,39 @@ 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 abs If the values are seen as absolute (inversion is different) + * @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, BOOL abs, int first, int num, int *valuators) +{ + int i; + int tmp[num]; + + /* invert the valuators */ + for (i = 0; i < num; i++) + if (pDev->valuator->axes[i + first].invert) { + if (abs) { + valuators[i] = pDev->valuator->axes[i + first].max_value - + (valuators[i] - pDev->valuator->axes[i + first].min_value); + } else { + valuators[i] = -valuators[i]; + } + } + + /* remap */ + for (i = 0; i < num; i++) + tmp[i] = valuators[pDev->valuator->axes[i + first].map - first]; + for (i = 0; i < num; i++) + valuators[i] = tmp[i]; +} + +/** * Convenience wrapper around GetKeyboardValuatorEvents, that takes no * valuators. */ @@ -909,6 +942,8 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, set_raw_valuators(raw, first_valuator, num_valuators, valuators, raw->valuators.data_raw); + invertAndMapValuators(pDev, False, first_valuator, num_valuators, valuators); + if (num_valuators) clipValuators(pDev, first_valuator, num_valuators, valuators); @@ -1067,6 +1102,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, (flags & POINTER_ABSOLUTE), first_valuator, num_valuators, valuators); + if (flags & POINTER_ABSOLUTE) { if (flags & POINTER_SCREEN) /* valuators are in screen coords */ @@ -1177,6 +1214,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, init_event(pDev, event, GetTimeInMillis()); event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut; + invertAndMapValuators(pDev, False, 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 29ad5a8..4abb285 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -216,6 +216,8 @@ typedef struct _AxisInfo { int min_value; int max_value; Atom label; + BOOL invert; /* inverse the input value */ + CARD8 map; /* number of the physical axis to read */ } AxisInfo, *AxisInfoPtr; typedef struct _ValuatorAccelerationRec { diff --git a/include/xserver-properties.h b/include/xserver-properties.h index 0f18dbc..d92b581 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -170,4 +170,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