diff options
author | Derek Foreman <derekf@osg.samsung.com> | 2014-11-25 11:46:42 -0600 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2014-12-02 10:16:31 +1000 |
commit | 188d20b2012e73a29b7995eb911605ebdc3ae4a2 (patch) | |
tree | bd710d4a992587cbcf2fd30e72b7feeb8082fc1a | |
parent | d7106544ea1200d06ee940464e63e4c21ba450e7 (diff) | |
download | libinput-188d20b2012e73a29b7995eb911605ebdc3ae4a2.tar.gz |
evdev: Query mouse DPI from udev
Instead of using a hard coded mouse DPI value, we query it from udev.
If it's not present or the property is obviously broken we fall back
to default.
Signed-off-by: Derek Foreman <derekf@osg.samsung.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r-- | src/evdev.c | 26 | ||||
-rw-r--r-- | src/libinput-util.c | 55 | ||||
-rw-r--r-- | src/libinput-util.h | 2 | ||||
-rw-r--r-- | test/misc.c | 42 |
4 files changed, 124 insertions, 1 deletions
diff --git a/src/evdev.c b/src/evdev.c index 5d178fad..e4d79c26 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1226,6 +1226,30 @@ evdev_tag_device(struct evdev_device *device) } static inline int +evdev_read_dpi_prop(struct evdev_device *device) +{ + struct libinput *libinput = device->base.seat->libinput; + const char *mouse_dpi; + int dpi = DEFAULT_MOUSE_DPI; + + mouse_dpi = udev_device_get_property_value(device->udev_device, + "MOUSE_DPI"); + if (mouse_dpi) { + dpi = parse_mouse_dpi_property(mouse_dpi); + if (!dpi) { + log_error(libinput, "Mouse DPI property for '%s' is " + "present but invalid, using %d " + "DPI instead\n", + device->devname, + DEFAULT_MOUSE_DPI); + dpi = DEFAULT_MOUSE_DPI; + } + } + + return dpi; +} + +static inline int evdev_fix_abs_resolution(struct libevdev *evdev, unsigned int code, const struct input_absinfo *absinfo) @@ -1530,7 +1554,7 @@ evdev_device_create(struct libinput_seat *seat, device->devname = libevdev_get_name(device->evdev); device->scroll.threshold = 5.0; /* Default may be overridden */ device->scroll.direction = 0; - device->dpi = DEFAULT_MOUSE_DPI; + device->dpi = evdev_read_dpi_prop(device); /* at most 5 SYN_DROPPED log-messages per 30s */ ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5); diff --git a/src/libinput-util.c b/src/libinput-util.c index 34d55496..923e1162 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -28,7 +28,9 @@ #include "config.h" +#include <ctype.h> #include <stdarg.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> @@ -113,3 +115,56 @@ ratelimit_test(struct ratelimit *r) return RATELIMIT_EXCEEDED; } + +/* Helper function to parse the mouse DPI tag from udev. + * The tag is of the form: + * MOUSE_DPI=400 *1000 2000 + * or + * MOUSE_DPI=400@125 *1000@125 2000@125 + * Where the * indicates the default value and @number indicates device poll + * rate. + * Numbers should be in ascending order, and if rates are present they should + * be present for all entries. + * + * When parsing the mouse DPI property, if we find an error we just return 0 + * since it's obviously invalid, the caller will treat that as an error and + * use a reasonable default instead. If the property contains multiple DPI + * settings but none flagged as default, we return the last because we're + * lazy and that's a silly way to set the property anyway. + */ +int +parse_mouse_dpi_property(const char *prop) +{ + bool is_default = false; + int nread, dpi = 0, rate; + + while (*prop != 0) { + if (*prop == ' ') { + prop++; + continue; + } + if (*prop == '*') { + prop++; + is_default = true; + if (!isdigit(prop[0])) + return 0; + } + + /* While we don't do anything with the rate right now we + * will validate that, if it's present, it is non-zero and + * positive + */ + rate = 1; + nread = 0; + sscanf(prop, "%d@%d%n", &dpi, &rate, &nread); + if (!nread) + sscanf(prop, "%d%n", &dpi, &nread); + if (!nread || dpi <= 0 || rate <= 0 || prop[nread] == '@') + return 0; + + if (is_default) + break; + prop += nread; + } + return dpi; +} diff --git a/src/libinput-util.h b/src/libinput-util.h index 909c9dbd..68258414 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -296,4 +296,6 @@ struct ratelimit { void ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst); enum ratelimit_state ratelimit_test(struct ratelimit *r); +int parse_mouse_dpi_property(const char *prop); + #endif /* LIBINPUT_UTIL_H */ diff --git a/test/misc.c b/test/misc.c index 21ecf190..4d4c22ca 100644 --- a/test/misc.c +++ b/test/misc.c @@ -529,6 +529,47 @@ START_TEST(ratelimit_helpers) } END_TEST +struct parser_test { + char *tag; + int expected_dpi; +}; + +START_TEST(dpi_parser) +{ + struct parser_test tests[] = { + { "450 *1800 3200", 1800 }, + { "*450 1800 3200", 450 }, + { "450 1800 *3200", 3200 }, + { "450 1800 3200", 3200 }, + { "450 1800 failboat", 0 }, + { "450 1800 *failboat", 0 }, + { "0 450 1800 *3200", 0 }, + { "450@37 1800@12 *3200@6", 3200 }, + { "450@125 1800@125 *3200@125 ", 3200 }, + { "450@125 *1800@125 3200@125", 1800 }, + { "*this @string fails", 0 }, + { "12@34 *45@", 0 }, + { "12@a *45@", 0 }, + { "12@a *45@25", 0 }, + { " * 12, 450, 800", 0 }, + { " *12, 450, 800", 12 }, + { "*12, *450, 800", 12 }, + { "*-23412, 450, 800", 0 }, + { "112@125, 450@125, 800@125, 900@-125", 0 }, + { "", 0 }, + { " ", 0 }, + { "* ", 0 }, + { NULL } + }; + int i, dpi; + + for (i = 0; tests[i].tag != NULL; i++) { + dpi = parse_mouse_dpi_property(tests[i].tag); + ck_assert_int_eq(dpi, tests[i].expected_dpi); + } +} +END_TEST + int main (int argc, char **argv) { litest_add_no_device("events:conversion", event_conversion_device_notify); litest_add_no_device("events:conversion", event_conversion_pointer); @@ -540,6 +581,7 @@ int main (int argc, char **argv) { litest_add_no_device("misc:matrix", matrix_helpers); litest_add_no_device("misc:ratelimit", ratelimit_helpers); + litest_add_no_device("misc:dpi parser", dpi_parser); return litest_run(argc, argv); } |