summaryrefslogtreecommitdiff
path: root/src/evdev.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2011-12-20 15:08:06 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2011-12-20 15:11:56 +1000
commite99ab2314f712df8dd705b16008755f8b3095707 (patch)
tree1c58f14ac92463259346f430983231d0fc1f81a9 /src/evdev.c
parent191660189a01b9c96bb4c0fa1a2e5008ae666238 (diff)
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>
Diffstat (limited to 'src/evdev.c')
-rw-r--r--src/evdev.c107
1 files changed, 80 insertions, 27 deletions
diff --git a/src/evdev.c b/src/evdev.c
index 00c9935..aef1d6e 100644
--- a/src/evdev.c
+++ b/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,