summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derekf@osg.samsung.com>2014-11-25 11:46:42 -0600
committerPeter Hutterer <peter.hutterer@who-t.net>2014-12-02 10:16:31 +1000
commit188d20b2012e73a29b7995eb911605ebdc3ae4a2 (patch)
treebd710d4a992587cbcf2fd30e72b7feeb8082fc1a
parentd7106544ea1200d06ee940464e63e4c21ba450e7 (diff)
downloadlibinput-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.c26
-rw-r--r--src/libinput-util.c55
-rw-r--r--src/libinput-util.h2
-rw-r--r--test/misc.c42
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);
}