mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-10 06:50:17 +01:00
touchpad: parse the TOUCHPAD_RESOLUTION property
Not all touchpad kernel drivers supply the x/y resolution. Let the udev hwdb fix this up where possible and read the value from it. This is intentionally only used on touchpads, touchscreen devices without resolution should be considered buggy and fixed in the kernel. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
parent
1e4116beb9
commit
0e64837f30
5 changed files with 115 additions and 0 deletions
|
|
@ -57,6 +57,11 @@ See @ref motion_normalization for details.
|
|||
<dd>The angle in degrees for each click on a mouse wheel. See
|
||||
libinput_pointer_get_axis_source() for details.
|
||||
</dd>
|
||||
<dt>TOUCHPAD_RESOLUTION</dt>
|
||||
<dd>The x and y resolution in units/mm for a touchpad. This value is only
|
||||
used if the touchpad kernel driver does not supply a valid resolution. It
|
||||
is only used on touchpad devices. The format is two unsigned integer values
|
||||
separated by a literal 'x', e.g. "42x129".</dd>
|
||||
</dl>
|
||||
|
||||
Below is an example udev rule to assign "seat1" to a device from vendor
|
||||
|
|
|
|||
|
|
@ -1117,6 +1117,32 @@ tp_init_sendevents(struct tp_dispatch *tp,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tp_fix_resolution(struct tp_dispatch *tp, struct evdev_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->base.seat->libinput;
|
||||
const char *prop;
|
||||
unsigned int resx, resy;
|
||||
|
||||
prop = udev_device_get_property_value(device->udev_device,
|
||||
"TOUCHPAD_RESOLUTION");
|
||||
if (!prop)
|
||||
return;
|
||||
|
||||
if (parse_touchpad_resolution_property(prop, &resx, &resy) == -1) {
|
||||
log_error(libinput,
|
||||
"Touchpad resolution property set for '%s', but invalid.\n",
|
||||
device->devname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (evdev_fix_abs_resolution(device,
|
||||
tp->has_mt ? ABS_MT_POSITION_X : ABS_X,
|
||||
tp->has_mt ? ABS_MT_POSITION_Y : ABS_Y,
|
||||
resx, resy))
|
||||
device->abs.fake_resolution = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
tp_init(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
|
|
@ -1130,6 +1156,8 @@ tp_init(struct tp_dispatch *tp,
|
|||
if (tp_init_slots(tp, device) != 0)
|
||||
return -1;
|
||||
|
||||
tp_fix_resolution(tp, device);
|
||||
|
||||
width = abs(device->abs.absinfo_x->maximum -
|
||||
device->abs.absinfo_x->minimum);
|
||||
height = abs(device->abs.absinfo_y->maximum -
|
||||
|
|
|
|||
|
|
@ -201,3 +201,33 @@ parse_mouse_wheel_click_angle_property(const char *prop)
|
|||
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to parse the TOUCHPAD_RESOLUTION property from udev.
|
||||
* Property is of the form
|
||||
* TOUCHPAD_RESOLUTION=<integer>x<integer>
|
||||
* With both integer values in device units per mm.
|
||||
* @param prop The value of the udev property (without the
|
||||
* TOUCHPAD_RESOLUTION=)
|
||||
* @return
|
||||
*/
|
||||
int
|
||||
parse_touchpad_resolution_property(const char *prop,
|
||||
unsigned int *res_x,
|
||||
unsigned int *res_y)
|
||||
{
|
||||
int nconverted = 0;
|
||||
unsigned int rx, ry;
|
||||
nconverted = sscanf(prop, "%ux%u", &rx, &ry);
|
||||
if (nconverted != 2 || rx == 0 || ry == 0)
|
||||
return -1;
|
||||
|
||||
if (rx > 1000 || ry > 1000 || /* yeah, right... */
|
||||
rx < 10 || ry < 10) /* what is this? the 90s? */
|
||||
return -1;
|
||||
|
||||
*res_x = rx;
|
||||
*res_y = ry;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -299,5 +299,8 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r);
|
|||
|
||||
int parse_mouse_dpi_property(const char *prop);
|
||||
int parse_mouse_wheel_click_angle_property(const char *prop);
|
||||
int parse_touchpad_resolution_property(const char *prop,
|
||||
unsigned int *res_x,
|
||||
unsigned int *res_y);
|
||||
|
||||
#endif /* LIBINPUT_UTIL_H */
|
||||
|
|
|
|||
49
test/misc.c
49
test/misc.c
|
|
@ -557,6 +557,54 @@ START_TEST(wheel_click_parser)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
struct res_parser_test {
|
||||
const char *value;
|
||||
int retvalue;
|
||||
int rx, ry;
|
||||
};
|
||||
|
||||
START_TEST(touchpad_resolution_parser)
|
||||
{
|
||||
struct res_parser_test tests[] = {
|
||||
{ "43x85", 0, 43, 85},
|
||||
{ "242x428", 0, 242, 428 },
|
||||
{ "1x1", -1, 0, 0},
|
||||
{ "abcd", -1, 0, 0},
|
||||
{ "", -1, 0, 0 },
|
||||
{ "x", -1, 0, 0 },
|
||||
{ "23x", -1, 0, 0 },
|
||||
{ "x58", -1, 0, 0 },
|
||||
{ "1x1", -1, 0, 0 },
|
||||
{ "9x9", -1, 0, 0 },
|
||||
{ "-34x-19", -1, 0, 0 },
|
||||
{ "-34x19", -1, 0, 0 },
|
||||
{ "34x-19", -1, 0, 0 },
|
||||
{ NULL, 0, 0, 0 }
|
||||
|
||||
};
|
||||
|
||||
struct res_parser_test *test = tests;
|
||||
int rc;
|
||||
unsigned int rx, ry;
|
||||
|
||||
while (test->value != NULL) {
|
||||
rx = 0xab;
|
||||
ry = 0xcd;
|
||||
rc = parse_touchpad_resolution_property(test->value, &rx, &ry);
|
||||
ck_assert_int_eq(rc, test->retvalue);
|
||||
if (rc == 0) {
|
||||
ck_assert_int_eq(rx, test->rx);
|
||||
ck_assert_int_eq(ry, test->ry);
|
||||
} else {
|
||||
ck_assert_int_eq(rx, 0xab);
|
||||
ck_assert_int_eq(ry, 0xcd);
|
||||
}
|
||||
|
||||
test++;
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
int main (int argc, char **argv) {
|
||||
litest_add_no_device("events:conversion", event_conversion_device_notify);
|
||||
litest_add_for_device("events:conversion", event_conversion_pointer, LITEST_MOUSE);
|
||||
|
|
@ -572,6 +620,7 @@ int main (int argc, char **argv) {
|
|||
litest_add_no_device("misc:ratelimit", ratelimit_helpers);
|
||||
litest_add_no_device("misc:dpi parser", dpi_parser);
|
||||
litest_add_no_device("misc:wheel click parser", wheel_click_parser);
|
||||
litest_add_no_device("misc:touchpad resolution parser", touchpad_resolution_parser);
|
||||
|
||||
return litest_run(argc, argv);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue