Don't count legacy and MT axes twice

The kernel exports both ABS_X and ABS_MT_POSITION_X (and a couple others)
for a multi-touch capable device. For such devices, only count the axis once
since we submit ABS_MT_POSITION_X through ABS_X.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
master
Peter Hutterer 14 years ago
parent 191660189a
commit e99ab2314f
  1. 107
      src/evdev.c

@ -748,12 +748,7 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
else
pEvdev->slot_state = SLOTSTATE_CLOSE;
} else {
if (ev->code == ABS_MT_POSITION_X)
map = pEvdev->axis_map[ABS_X];
else if (ev->code == ABS_MT_POSITION_Y)
map = pEvdev->axis_map[ABS_Y];
else
map = pEvdev->axis_map[ev->code] - pEvdev->num_vals;
map = pEvdev->axis_map[ev->code];
valuator_mask_set(pEvdev->mt_mask, map, ev->value);
}
}
@ -1131,6 +1126,24 @@ EvdevAddKeyClass(DeviceIntPtr device)
return Success;
}
/* MT axes are counted twice - once as ABS_X (which the kernel keeps for
* backwards compatibility), once as ABS_MT_POSITION_X. So we need to keep a
* mapping of those axes to make sure we only count them once
*/
struct mt_axis_mappings {
int mt_code;
int code;
Bool needs_mapping; /* TRUE if both code and mt_code are present */
int mapping; /* Logical mapping of 'code' axis */
};
static struct mt_axis_mappings mt_axis_mappings[] = {
{ABS_MT_POSITION_X, ABS_X},
{ABS_MT_POSITION_Y, ABS_Y},
{ABS_MT_PRESSURE, ABS_PRESSURE},
{ABS_MT_DISTANCE, ABS_DISTANCE},
};
/**
* return TRUE if the axis is not one we should count as true axis
*/
@ -1154,7 +1167,9 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
InputInfoPtr pInfo;
EvdevPtr pEvdev;
int num_axes, axis, i = 0;
int num_mt_axes = 0;
int num_mt_axes = 0, /* number of MT-only axes */
num_mt_axes_total = 0; /* total number of MT axes, including
double-counted ones, excluding blacklisted */
Atom *atoms;
pInfo = device->public.devicePrivate;
@ -1172,26 +1187,35 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
{
if (EvdevBitIsSet(pEvdev->abs_bitmask, axis))
{
int j;
Bool skip = FALSE;
for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
{
if (mt_axis_mappings[j].mt_code == axis &&
BitIsOn(pEvdev->abs_bitmask, mt_axis_mappings[j].code))
{
mt_axis_mappings[j].needs_mapping = TRUE;
skip = TRUE;
}
}
if (!is_blacklisted_axis(axis))
num_mt_axes++;
{
num_mt_axes_total++;
if (!skip)
num_mt_axes++;
}
num_axes--;
}
}
#endif
if (num_axes > MAX_VALUATORS) {
if (num_axes + num_mt_axes > MAX_VALUATORS) {
xf86IDrvMsg(pInfo, X_WARNING, "found %d axes, limiting to %d.\n", num_axes, MAX_VALUATORS);
num_axes = MAX_VALUATORS;
}
#ifdef MULTITOUCH
if (num_mt_axes > MAX_VALUATORS) {
xf86Msg(X_WARNING, "%s: found %d MT axes, limiting to %d.\n", device->name, num_axes, MAX_VALUATORS);
num_mt_axes = MAX_VALUATORS;
}
#endif
if (num_axes < 1 && num_mt_axes < 1) {
if (num_axes < 1 && num_mt_axes_total < 1) {
xf86Msg(X_WARNING, "%s: no absolute or touch axes found.\n",
device->name);
return !Success;
@ -1207,8 +1231,8 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
}
}
#ifdef MULTITOUCH
if (num_mt_axes > 0) {
pEvdev->mt_mask = valuator_mask_new(num_mt_axes);
if (num_mt_axes_total > 0) {
pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total);
if (!pEvdev->mt_mask) {
xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
device->name);
@ -1217,7 +1241,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
for (i = 0; i < EVDEV_MAXQUEUE; i++) {
pEvdev->queue[i].touchMask =
valuator_mask_new(num_mt_axes);
valuator_mask_new(num_mt_axes_total);
if (!pEvdev->queue[i].touchMask) {
xf86Msg(X_ERROR, "%s: failed to allocate MT valuator masks for "
"evdev event queue.\n", device->name);
@ -1230,12 +1254,27 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
i = 0;
for (axis = ABS_X; i < MAX_VALUATORS && axis <= ABS_MAX; axis++) {
int j;
int mapping;
pEvdev->axis_map[axis] = -1;
if (!EvdevBitIsSet(pEvdev->abs_bitmask, axis) ||
is_blacklisted_axis(axis))
continue;
pEvdev->axis_map[axis] = i;
i++;
mapping = i;
for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
{
if (mt_axis_mappings[j].code == axis)
mt_axis_mappings[j].mapping = mapping;
else if (mt_axis_mappings[j].mt_code == axis &&
mt_axis_mappings[j].needs_mapping)
mapping = mt_axis_mappings[j].mapping;
}
pEvdev->axis_map[axis] = mapping;
if (mapping == i)
i++;
}
EvdevInitAxesLabels(pEvdev, pEvdev->num_vals + num_mt_axes, atoms);
@ -1247,7 +1286,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
}
#ifdef MULTITOUCH
if (num_mt_axes > 0)
if (num_mt_axes_total > 0)
{
int num_touches = 0;
int mode = pEvdev->flags & EVDEV_TOUCHPAD ?
@ -1257,7 +1296,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
num_touches = pEvdev->mtdev->caps.slot.maximum;
if (!InitTouchClassDeviceStruct(device, num_touches, mode,
num_mt_axes)) {
num_mt_axes_total)) {
xf86Msg(X_ERROR, "%s: failed to initialize touch class device.\n",
device->name);
goto out;
@ -1288,17 +1327,31 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
#ifdef MULTITOUCH
for (axis = ABS_MT_TOUCH_MAJOR; axis <= ABS_MAX; axis++) {
int axnum = pEvdev->axis_map[axis] - pEvdev->num_vals;
int axnum = pEvdev->axis_map[axis];
int resolution = 10000;
int j;
BOOL skip = FALSE;
if (axnum < 0)
continue;
for (j = 0; j < ArrayLength(mt_axis_mappings); j++)
if (mt_axis_mappings[j].mt_code == axis &&
mt_axis_mappings[j].needs_mapping)
{
skip = TRUE;
break;
}
/* MT axis is mapped, don't set up twice */
if (skip)
continue;
if (pEvdev->absinfo[axis].resolution)
resolution = pEvdev->absinfo[axis].resolution * 1000;
xf86InitValuatorAxisStruct(device, axnum,
atoms[axnum + pEvdev->num_vals],
atoms[axnum],
pEvdev->absinfo[axis].minimum,
pEvdev->absinfo[axis].maximum,
resolution, 0, resolution,

Loading…
Cancel
Save