From 5b89b4144e59ba1a022f83f0d28bea452d12c15f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 31 Aug 2009 15:45:48 +1000 Subject: [PATCH] input: provide "Axis Mapping" DIX property This patch provides a new server-supported property: "Axis Mapping" In the default axis mapping (0, 1, 2...) the physical axis N is mapped to the logical axis N. If the property is changed, a physical axis N may be mapped to logical axis M. Limitations: - An axis can only be mapped onto an existing axis. - The property allows two physical axes to be mapped onto the same logical axis. The behaviour for events that include values for both axes is undefined. Signed-off-by: Peter Hutterer --- Xi/xiproperty.c | 3 +- dix/devices.c | 38 +++++++++ dix/getevents.c | 190 +++++++++++++++++++++--------------------- dix/inpututils.c | 2 + include/inputstr.h | 1 + include/xserver-properties.h | 3 + 6 files changed, 142 insertions(+), 95 deletions(-) diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 742a0d5..ae33994 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -168,7 +168,8 @@ static struct dev_properties {0, BTN_LABEL_PROP_BTN_GEAR_DOWN}, {0, BTN_LABEL_PROP_BTN_GEAR_UP}, - {0, XI_PROP_BUTTONMAPPING} + {0, XI_PROP_BUTTONMAPPING}, + {0, XI_PROP_AXISMAPPING} }; static long XIPropHandlerID = 1; diff --git a/dix/devices.c b/dix/devices.c index 13f928f..3fc1ef2 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -145,6 +145,30 @@ DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop, } } else ApplyButtonMap(dev, mapping, prop->size); + } else if (property == XIGetKnownProperty(XI_PROP_AXISMAPPING)) + { + CARD8 *mapping; + + if (prop->format != 8 || prop->type != XA_INTEGER) + return BadMatch; + + if (!dev->valuator) + return BadValue; + + mapping = (CARD8*)prop->data; + + if (checkonly) + { + int i; + for (i = 0; i < prop->size; i++) + if (mapping[i] >= dev->valuator->numAxes) + return BadValue; + } else + { + OsBlockSignals(); + memcpy(dev->valuator->map, mapping, prop->size); + OsReleaseSignals(); + } } return Success; @@ -387,6 +411,19 @@ EnableDevice(DeviceIntPtr dev, BOOL sendevent) XISetDevicePropertyDeletable(dev, prop, FALSE); } + if (dev->valuator) + { + int ret; + Atom prop; + + prop = XIGetKnownProperty(XI_PROP_AXISMAPPING); + ret = XIChangeDeviceProperty(dev, prop, XA_INTEGER, 8, + PropModeReplace, + dev->valuator->numAxes, + dev->valuator->map, FALSE); + XISetDevicePropertyDeletable(dev, prop, FALSE); + } + SendDevicePresenceEvent(dev->id, DeviceEnabled); if (sendevent) { @@ -1232,6 +1269,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels, InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0); valc->axisVal[i]=0; + dev->valuator->map[i] = i; } dev->last.numValuators = numAxes; diff --git a/dix/getevents.c b/dix/getevents.c index 2912c1e..9c38148 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -169,16 +169,14 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator, for (i = first_valuator; i < first_valuator + num_valuators; i++) { - SetBit(event->valuators.mask, i); + int mapped_idx = dev->valuator->map[i]; + SetBit(event->valuators.mask, mapped_idx); if (dev->valuator->mode == Absolute) - SetBit(event->valuators.mode, i); - event->valuators.data_frac[i] = - dev->last.remainder[i] * (1 << 16) * (1 << 16); + SetBit(event->valuators.mode, mapped_idx); + event->valuators.data_frac[mapped_idx] = + dev->last.remainder[mapped_idx] * (1 << 16) * (1 << 16); + event->valuators.data[mapped_idx] = valuators[i - first_valuator]; } - - memcpy(&event->valuators.data[first_valuator], - valuators, num_valuators * sizeof(uint32_t)); - } void @@ -650,77 +648,44 @@ updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_event * @first+@num. */ static void -moveAbsolute(DeviceIntPtr dev, int *x, int *y, - int first, int num, int *valuators) +getXY(DeviceIntPtr dev, int *x, int *y) { int i; + int stop = 0; - - if (num >= 1 && first == 0) - *x = *(valuators + 0); - else - *x = dev->last.valuators[0]; - - if (first <= 1 && num >= (2 - first)) - *y = *(valuators + 1 - first); - else - *y = dev->last.valuators[1]; - - clipAxis(dev, 0, x); - clipAxis(dev, 1, y); - - i = (first > 2) ? 0 : 2; - for (; i < num; i++) + for (i = 0; i < dev->valuator->numAxes && stop < 3; i++) { - dev->last.valuators[i + first] = valuators[i]; - clipAxis(dev, i, &dev->last.valuators[i + first]); + if (dev->valuator->map[i] == 0) + { + *x = dev->last.valuators[i]; + stop |= 0x1; + } else if (dev->valuator->map[i] == 1) + { + *y = dev->last.valuators[i]; + stop |= 0x2; + } } } -/** - * Move the device's pointer by the values given in @valuators. - * - * @param dev The device which's pointer is to be moved. - * @param x Returns the x position of the pointer after the move. - * @param y Returns the y position of the pointer after the move. - * @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 -moveRelative(DeviceIntPtr dev, int *x, int *y, - int first, int num, int *valuators) +updateValuators(DeviceIntPtr dev, int first, int num, int *valuators, int absolute) { int i; - *x = dev->last.valuators[0]; - *y = dev->last.valuators[1]; - - if (num >= 1 && first == 0) - *x += *(valuators +0); - - if (first <= 1 && num >= (2 - first)) - *y += *(valuators + 1 - first); - - /* if attached, clip both x and y to the defined limits (usually - * co-ord space limit). If it is attached, we need x/y to go over the - * limits to be able to change screens. */ - if(dev->u.master) { - clipAxis(dev, 0, x); - clipAxis(dev, 1, y); - } - - /* calc other axes, clip, drop back into valuators */ - i = (first > 2) ? 0 : 2; - for (; i < num; i++) + for (i = 0; i < num; i++) { - dev->last.valuators[i + first] += valuators[i]; - clipAxis(dev, i, &dev->last.valuators[i + first]); - valuators[i] = dev->last.valuators[i + first]; + if (absolute) + { + dev->last.valuators[i + first] = valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + } else + { + dev->last.valuators[i + first] += valuators[i]; + clipAxis(dev, i, &dev->last.valuators[i + first]); + valuators[i] = dev->last.valuators[i + first]; + } } } - /** * Accelerate the data in valuators based on the device's acceleration scheme. * @@ -762,11 +727,21 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac) { int old_screenx, old_screeny; + int i; + int x_axis = 0, y_axis = 1; /* index of axis mapped to 0 and 1 */ + + for (i = 0; i < dev->valuator->numAxes; i++) + { + if (dev->valuator->map[i] == 0) + x_axis = i; + else if (dev->valuator->map[i] == 1) + y_axis = i; + } /* scale x&y to screen */ if (dev->valuator->numAxes > 0) { *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac, - dev->valuator->axes + 0, NULL, scr->width); + &dev->valuator->axes[x_axis], NULL, scr->width); } else { *screenx = dev->last.valuators[0]; *screenx_frac = dev->last.remainder[0]; @@ -774,7 +749,7 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, if (dev->valuator->numAxes > 1) { *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac, - dev->valuator->axes + 1, NULL, scr->height); + &dev->valuator->axes[y_axis], NULL, scr->height); } else { *screeny = dev->last.valuators[1]; *screeny_frac = dev->last.remainder[1]; @@ -787,10 +762,18 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, miPointerSetPosition(dev, screenx, screeny); if (dev->u.master) { - dev->u.master->last.valuators[0] = *screenx; - dev->u.master->last.valuators[1] = *screeny; - dev->u.master->last.remainder[0] = *screenx_frac; - dev->u.master->last.remainder[1] = *screeny_frac; + for (i = 0; i < dev->valuator->numAxes; i++) + { + if (dev->valuator->map[i] == 0) + { + dev->u.master->last.valuators[i] = *screenx; + dev->u.master->last.remainder[i] = *screenx_frac; + } else if (dev->valuator->map[i] == 1) + { + dev->u.master->last.valuators[i] = *screeny; + dev->u.master->last.remainder[i] = *screeny_frac; + } + } } /* Crossed screen? Scale back to device coordiantes */ @@ -798,20 +781,20 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac, { scr = miPointerGetScreen(dev); *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL, - dev->valuator->axes + 0, scr->width); + &dev->valuator->axes[x_axis], scr->width); } if(*screeny != old_screeny) { scr = miPointerGetScreen(dev); *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL, - dev->valuator->axes + 1, scr->height); + &dev->valuator->axes[y_axis], scr->height); } /* dropy x/y (device coordinates) back into valuators for next event */ - dev->last.valuators[0] = *x; - dev->last.valuators[1] = *y; - dev->last.remainder[0] = x_frac; - dev->last.remainder[1] = y_frac; + dev->last.valuators[x_axis] = *x; + dev->last.valuators[y_axis] = *y; + dev->last.remainder[x_axis] = x_frac; + dev->last.remainder[y_axis] = y_frac; } /** @@ -1037,6 +1020,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, int x = 0, y = 0, /* device coords */ cx, cy; /* only screen coordinates */ float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac; + int i; ScreenPtr scr = miPointerGetScreen(pDev); /* refuse events from disabled devices */ @@ -1067,29 +1051,44 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, { if (flags & POINTER_SCREEN) /* valuators are in screen coords */ { - - if (num_valuators >= 1 && first_valuator == 0) - valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL, - pDev->valuator->axes + 0, - scr->width); - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL, - pDev->valuator->axes + 1, - scr->height); + for (i = 0; i < num_valuators; i++) + { + if (pDev->valuator->map[first_valuator + i] == 0) + { + valuators[i] = rescaleValuatorAxis(valuators[i], 0.0, &y_frac, NULL, + &pDev->valuator->axes[first_valuator + i], + scr->height); + } else if (pDev->valuator->map[first_valuator + i] == 1) + { + valuators[i] = rescaleValuatorAxis(valuators[i], 0.0, &x_frac, NULL, + &pDev->valuator->axes[first_valuator + i], + scr->width); + } + } } - moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators); + updateValuators(pDev, first_valuator, num_valuators, valuators, TRUE); } else { if (flags & POINTER_ACCELERATE) { + int i; + accelPointer(pDev, first_valuator, num_valuators, valuators, ms); + /* The pointer acceleration code modifies the fractional part * in-place, so we need to extract this information first */ - x_frac = pDev->last.remainder[0]; - y_frac = pDev->last.remainder[1]; + for (i = 0; i < pDev->valuator->numAxes; i++) + { + if (pDev->valuator->map[i] == 0) + x_frac = pDev->last.remainder[i]; + else if (pDev->valuator->map[i] == 1) + y_frac = pDev->last.remainder[i]; + } } - moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators); + updateValuators(pDev, first_valuator, num_valuators, valuators, FALSE); } + getXY(pDev, &x, &y); + set_raw_valuators(raw, first_valuator, num_valuators, valuators, raw->valuators.data); @@ -1097,10 +1096,13 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, updateHistory(pDev, first_valuator, num_valuators, ms); /* Update the valuators with the true value sent to the client*/ - if (num_valuators >= 1 && first_valuator == 0) - valuators[0] = x; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - valuators[1 - first_valuator] = y; + for (i = 0; i < num_valuators && pDev->valuator; i++) + { + if (pDev->valuator->map[first_valuator + i] == 0) + valuators[i] = x; + else if (pDev->valuator->map[first_valuator + i] == 1) + valuators[i] = y; + } if (num_valuators) clipValuators(pDev, first_valuator, num_valuators, valuators); diff --git a/dix/inpututils.c b/dix/inpututils.c index d88316d..935d97a 100644 --- a/dix/inpututils.c +++ b/dix/inpututils.c @@ -323,3 +323,5 @@ int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, return Success; } + + diff --git a/include/inputstr.h b/include/inputstr.h index 29ad5a8..759e187 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -239,6 +239,7 @@ typedef struct _ValuatorClassRec { double *axisVal; /* always absolute, but device-coord system */ CARD8 mode; ValuatorAccelerationRec accelScheme; + CARD8 map[MAX_VALUATORS]; } ValuatorClassRec, *ValuatorClassPtr; typedef struct _ButtonClassRec { diff --git a/include/xserver-properties.h b/include/xserver-properties.h index ef395f2..ab40575 100644 --- a/include/xserver-properties.h +++ b/include/xserver-properties.h @@ -39,6 +39,9 @@ * BadValue if property is invalid. * BadAccess if property cannot be changed right now. */ #define XI_PROP_BUTTONMAPPING "Button Mapping" +/** Axis mapping */ +/* CARD8, number of axes on the device. */ +#define XI_PROP_AXISMAPPING "Axis Mapping" /* Pointer acceleration properties */ /* INTEGER of any format */ -- 1.6.3.rc1.2.g0164.dirty