Add support for per-axis valuator modes (Relative/Absolute)

The XI2 protocol supports per-axis modes, but the server so far does
not. This change adds support in the server.

A complication is the fact that XI1 does not support per-axis modes.
The solution provided here is to set a per-device mode that defines the
mode of at least the first two valuators (X and Y). Note that initializing
the first two axes to a different mode than the device mode will fail.

For XI1 events, any axes following the first two that have the same mode
will be sent to clients, up to the first axis that has a different mode.
Thus, if a device has relative, then absolute, then relative mode axes,
only the first block of relative axes will be sent over XI1.

Since the XI2 protocol supports per-axis modes, all axes are sent to the
client.

Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
This commit is contained in:
Chase Douglas 2010-07-16 09:21:19 -04:00 committed by Peter Hutterer
parent 9696c782c8
commit 65c0fc81eb
12 changed files with 56 additions and 30 deletions

View File

@ -1127,7 +1127,7 @@ InitProximityClassDeviceStruct(DeviceIntPtr dev)
*/ */
void void
InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
int resolution, int min_res, int max_res) int resolution, int min_res, int max_res, int mode)
{ {
AxisInfoPtr ax; AxisInfoPtr ax;
@ -1144,6 +1144,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int
ax->min_resolution = min_res; ax->min_resolution = min_res;
ax->max_resolution = max_res; ax->max_resolution = max_res;
ax->label = label; ax->label = label;
ax->mode = mode;
} }
static void static void

View File

@ -349,7 +349,7 @@ ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16)); info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
info->resolution = v->axes[axisnumber].resolution; info->resolution = v->axes[axisnumber].resolution;
info->number = axisnumber; info->number = axisnumber;
info->mode = v->mode; /* Server doesn't have per-axis mode yet */ info->mode = v->axes[axisnumber].mode;
info->sourceid = v->sourceid; info->sourceid = v->sourceid;
if (!reportState) if (!reportState)

View File

@ -1260,7 +1260,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
for (i=0; i<numAxes; i++) { for (i=0; i<numAxes; i++) {
InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS, InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
0, 0, 0); 0, 0, 0, mode);
valc->axisVal[i]=0; valc->axisVal[i]=0;
} }
@ -2357,8 +2357,7 @@ RecalculateMasterButtons(DeviceIntPtr slave)
event.valuators[i].min = master->valuator->axes[i].min_value; event.valuators[i].min = master->valuator->axes[i].min_value;
event.valuators[i].max = master->valuator->axes[i].max_value; event.valuators[i].max = master->valuator->axes[i].max_value;
event.valuators[i].resolution = master->valuator->axes[i].resolution; event.valuators[i].resolution = master->valuator->axes[i].resolution;
/* This should, eventually, be a per-axis mode */ event.valuators[i].mode = master->valuator->axes[i].mode;
event.valuators[i].mode = master->valuator->mode;
event.valuators[i].name = master->valuator->axes[i].label; event.valuators[i].name = master->valuator->axes[i].label;
} }
} }

View File

@ -261,6 +261,12 @@ eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count)
} }
num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */ num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */
if (num_events <= 0)
{
*count = 0;
return BadMatch;
}
num_events++; /* the actual event event */ num_events++; /* the actual event event */
*xi = calloc(num_events, sizeof(xEvent)); *xi = calloc(num_events, sizeof(xEvent));
@ -318,6 +324,12 @@ countValuators(DeviceEvent *ev, int *first)
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
{ {
/* Assume mode of 0th valuator matches XI1 device mode. Stop when the
* event mode changes since XI1 can't handle mixed mode devices.
*/
if (ev->valuators.mode[i] != ev->valuators.mode[0])
break;
if (BitIsOn(ev->valuators.mask, i)) if (BitIsOn(ev->valuators.mask, i))
{ {
if (first_valuator == -1) if (first_valuator == -1)
@ -440,7 +452,7 @@ appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumbe
info->value.frac = 0; info->value.frac = 0;
info->resolution = dce->valuators[axisnumber].resolution; info->resolution = dce->valuators[axisnumber].resolution;
info->number = axisnumber; info->number = axisnumber;
info->mode = dce->valuators[axisnumber].mode; /* Server doesn't have per-axis mode yet */ info->mode = dce->valuators[axisnumber].mode;
info->sourceid = dce->sourceid; info->sourceid = dce->sourceid;
return info->length * 4; return info->length * 4;

View File

@ -210,7 +210,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
if (valuator_mask_isset(mask, i)) if (valuator_mask_isset(mask, i))
{ {
SetBit(event->valuators.mask, i); SetBit(event->valuators.mask, i);
if (dev->valuator->mode == Absolute) if (dev->valuator->axes[i].mode == Absolute)
SetBit(event->valuators.mode, i); SetBit(event->valuators.mode, i);
event->valuators.data[i] = valuator_mask_get(mask, i); event->valuators.data[i] = valuator_mask_get(mask, i);
event->valuators.data_frac[i] = event->valuators.data_frac[i] =
@ -255,8 +255,7 @@ CreateClassesChangedEvent(EventList* event,
dce->valuators[i].min = slave->valuator->axes[i].min_value; dce->valuators[i].min = slave->valuator->axes[i].min_value;
dce->valuators[i].max = slave->valuator->axes[i].max_value; dce->valuators[i].max = slave->valuator->axes[i].max_value;
dce->valuators[i].resolution = slave->valuator->axes[i].resolution; dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
/* This should, eventually, be a per-axis mode */ dce->valuators[i].mode = slave->valuator->axes[i].mode;
dce->valuators[i].mode = slave->valuator->mode;
dce->valuators[i].name = slave->valuator->axes[i].label; dce->valuators[i].name = slave->valuator->axes[i].label;
} }
} }
@ -374,8 +373,16 @@ AllocateMotionHistory(DeviceIntPtr pDev)
*/ */
if (IsMaster(pDev)) if (IsMaster(pDev))
size = sizeof(INT32) * 3 * MAX_VALUATORS; size = sizeof(INT32) * 3 * MAX_VALUATORS;
else else {
size = sizeof(INT32) * pDev->valuator->numAxes; ValuatorClassPtr v = pDev->valuator;
int numAxes;
/* XI1 doesn't understand mixed mode devices */
for (numAxes = 0; numAxes < v->numAxes; numAxes++)
if ((v->axes[numAxes].mode & DeviceMode) !=
(v->mode & DeviceMode))
break;
size = sizeof(INT32) * numAxes;
}
size += sizeof(Time); size += sizeof(Time);
@ -556,6 +563,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
for (i = 0; i < v->numAxes; i++) for (i = 0; i < v->numAxes; i++)
{ {
/* XI1 doesn't support mixed mode devices */
if ((pDev->valuator->axes[i].mode & DeviceMode) !=
(pDev->valuator->mode & DeviceMode))
break;
if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
{ {
buff += 3 * sizeof(INT32); buff += 3 * sizeof(INT32);
@ -769,7 +780,7 @@ moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
if (valuator_mask_isset(mask, i)) if (valuator_mask_isset(mask, i))
{ {
dev->last.valuators[i] += valuator_mask_get(mask, i); dev->last.valuators[i] += valuator_mask_get(mask, i);
if (dev->valuator->mode == Absolute) if (dev->valuator->axes[i].mode == Absolute)
clipAxis(dev, i, &dev->last.valuators[i]); clipAxis(dev, i, &dev->last.valuators[i]);
valuator_mask_set(mask, i, dev->last.valuators[i]); valuator_mask_set(mask, i, dev->last.valuators[i]);
} }

View File

@ -476,7 +476,8 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
InitValuatorAxisStruct(pDevice, i, axis_labels[i], InitValuatorAxisStruct(pDevice, i, axis_labels[i],
info.minval[i], info.maxval[i], info.minval[i], info.maxval[i],
info.res[i], info.res[i],
info.minres[i], info.maxres[i]); info.minres[i], info.maxres[i],
Relative);
} else if (info.numRelAxes) { } else if (info.numRelAxes) {
InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, InitValuatorClassDeviceStruct(pDevice, info.numRelAxes,
axis_labels, axis_labels,
@ -486,7 +487,8 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
InitValuatorAxisStruct(pDevice, i, axis_labels[i], InitValuatorAxisStruct(pDevice, i, axis_labels[i],
info.minval[i], info.minval[i],
info.maxval[i], info.res[i], info.maxval[i], info.res[i],
info.minres[i], info.maxres[i]); info.minres[i], info.maxres[i],
Relative);
} else if (info.numAbsAxes) { } else if (info.numAbsAxes) {
InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes, InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes,
axis_labels, axis_labels,
@ -497,7 +499,7 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what)
axis_labels[i], axis_labels[i],
info.minval[i], info.maxval[i], info.minval[i], info.maxval[i],
info.res[i], info.minres[i], info.res[i], info.minres[i],
info.maxres[i]); info.maxres[i], Absolute);
} }
} }
if (info.focusClass) InitFocusClassDeviceStruct(pDevice); if (info.focusClass) InitFocusClassDeviceStruct(pDevice);

View File

@ -125,12 +125,11 @@ void dmxPointerPutMotionEvent(DeviceIntPtr pDevice,
/* Initialize the data from the known /* Initialize the data from the known
* values (if Absolute) or to zero (if * values (if Absolute) or to zero (if
* Relative) */ * Relative) */
if (pDevice->valuator->mode == Absolute) { for (i = 0; i < numAxes; i++) {
for (i = 0; i < numAxes; i++) if (pDevice->valuator->axes[i].mode == Absolute)
dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] dmxLocal->history[OFFSET(dmxLocal->tail,i+1)]
= dmxLocal->valuators[i]; = dmxLocal->valuators[i];
} else { else
for (i = 0; i < numAxes; i++)
dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0; dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0;
} }

View File

@ -1325,13 +1325,13 @@ xf86XInputSetScreen(InputInfoPtr pInfo,
void void
xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval, xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
int resolution, int min_res, int max_res) int resolution, int min_res, int max_res, int mode)
{ {
if (!dev || !dev->valuator) if (!dev || !dev->valuator)
return; return;
InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res, InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, min_res,
max_res); max_res, mode);
} }
/* /*

View File

@ -147,7 +147,7 @@ extern _X_EXPORT void xf86XInputSetScreen(InputInfoPtr pInfo, int screen_number,
extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, pointer options); extern _X_EXPORT void xf86ProcessCommonOptions(InputInfoPtr pInfo, pointer options);
extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, extern _X_EXPORT void xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
int maxval, int resolution, int min_res, int maxval, int resolution, int min_res,
int max_res); int max_res, int mode);
extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum); extern _X_EXPORT void xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum);
extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo); extern _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo);
extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo); extern _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo);

View File

@ -316,8 +316,8 @@ static int DarwinMouseProc(DeviceIntPtr pPointer, int what) {
axes_labels); axes_labels);
pPointer->valuator->mode = Absolute; // Relative pPointer->valuator->mode = Absolute; // Relative
InitAbsoluteClassDeviceStruct(pPointer); InitAbsoluteClassDeviceStruct(pPointer);
// InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); // InitValuatorAxisStruct(pPointer, 0, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
// InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); // InitValuatorAxisStruct(pPointer, 1, 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
break; break;
case DEVICE_ON: case DEVICE_ON:
pPointer->public.on = TRUE; pPointer->public.on = TRUE;
@ -366,11 +366,11 @@ static int DarwinTabletProc(DeviceIntPtr pPointer, int what) {
InitProximityClassDeviceStruct(pPointer); InitProximityClassDeviceStruct(pPointer);
InitAbsoluteClassDeviceStruct(pPointer); InitAbsoluteClassDeviceStruct(pPointer);
InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); InitValuatorAxisStruct(pPointer, 0, axes_labels[0], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); InitValuatorAxisStruct(pPointer, 1, axes_labels[1], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); InitValuatorAxisStruct(pPointer, 2, axes_labels[2], 0, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); InitValuatorAxisStruct(pPointer, 3, axes_labels[3], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1); InitValuatorAxisStruct(pPointer, 4, axes_labels[4], -XQUARTZ_VALUATOR_LIMIT, XQUARTZ_VALUATOR_LIMIT, 1, 0, 1, Absolute);
// pPointer->use = IsXExtensionDevice; // pPointer->use = IsXExtensionDevice;
break; break;
case DEVICE_ON: case DEVICE_ON:

View File

@ -48,7 +48,8 @@ extern _X_EXPORT void InitValuatorAxisStruct(
int /* maxval */, int /* maxval */,
int /* resolution */, int /* resolution */,
int /* min_res */, int /* min_res */,
int /* max_res */); int /* max_res */,
int /* mode */);
/* Input device properties */ /* Input device properties */
extern _X_EXPORT void XIDeleteAllDeviceProperties( extern _X_EXPORT void XIDeleteAllDeviceProperties(

View File

@ -218,6 +218,7 @@ typedef struct _AxisInfo {
int min_value; int min_value;
int max_value; int max_value;
Atom label; Atom label;
CARD8 mode;
} AxisInfo, *AxisInfoPtr; } AxisInfo, *AxisInfoPtr;
typedef struct _ValuatorAccelerationRec { typedef struct _ValuatorAccelerationRec {