[PATCH libinput 2/2] Parse the MOUSE_WHEEL_CLICK_ANGLE udev property if present
Peter Hutterer
peter.hutterer at who-t.net
Sun Jan 11 15:12:36 PST 2015
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
doc/device-configuration-via-udev.dox | 4 ++++
src/evdev.c | 29 +++++++++++++++++++++++++++--
src/evdev.h | 3 +++
src/libinput-util.c | 30 ++++++++++++++++++++++++++++++
src/libinput-util.h | 1 +
test/misc.c | 34 ++++++++++++++++++++++++++++++++--
6 files changed, 97 insertions(+), 4 deletions(-)
diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox
index b854035..bee3659 100644
--- a/doc/device-configuration-via-udev.dox
+++ b/doc/device-configuration-via-udev.dox
@@ -23,6 +23,10 @@ context. Defaults to "default".</dd>
<dd>HW resolution and sampling frequency of a relative pointer device.
See @ref motion_normalization for details.
</dd>
+<dt>MOUSE_WHEEL_CLICK_ANGLE</dt>
+<dd>The angle in degrees for each click on a mouse wheel. See
+libinput_pointer_get_axis_source() for details.
+</dd>
</dl>
Below is an example udev rule to assign "seat1" to a device from vendor
diff --git a/src/evdev.c b/src/evdev.c
index 4fb37d6..f35ee34 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -577,7 +577,7 @@ evdev_process_relative(struct evdev_device *device,
time,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
- -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
+ -1 * e->value * device->scroll.wheel_click_angle);
break;
case REL_HWHEEL:
evdev_flush_pending_event(device, time);
@@ -586,7 +586,7 @@ evdev_process_relative(struct evdev_device *device,
time,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL,
LIBINPUT_POINTER_AXIS_SOURCE_WHEEL,
- e->value * DEFAULT_AXIS_STEP_DISTANCE);
+ e->value * device->scroll.wheel_click_angle);
break;
}
}
@@ -1240,6 +1240,29 @@ evdev_tag_device(struct evdev_device *device)
}
static inline int
+evdev_read_wheel_click_prop(struct evdev_device *device)
+{
+ struct libinput *libinput = device->base.seat->libinput;
+ const char *prop;
+ int angle = DEFAULT_AXIS_STEP_DISTANCE;
+
+ prop = udev_device_get_property_value(device->udev_device,
+ "MOUSE_WHEEL_CLICK_ANGLE");
+ if (prop) {
+ angle = parse_mouse_wheel_click_angle_property(prop);
+ if (!angle) {
+ log_error(libinput,
+ "Mouse wheel click angle '%s' is present but invalid,"
+ "using %d degrees instead\n",
+ device->devname,
+ DEFAULT_AXIS_STEP_DISTANCE);
+ angle = DEFAULT_AXIS_STEP_DISTANCE;
+ }
+ }
+
+ return angle;
+}
+static inline int
evdev_read_dpi_prop(struct evdev_device *device)
{
struct libinput *libinput = device->base.seat->libinput;
@@ -1568,6 +1591,8 @@ 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->scroll.wheel_click_angle =
+ evdev_read_wheel_click_prop(device);
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/evdev.h b/src/evdev.h
index a75dd13..2171c5a 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -119,6 +119,9 @@ struct evdev_device {
/* set during device init if we want natural scrolling,
* used at runtime to enable/disable the feature */
bool natural_scrolling_enabled;
+
+ /* angle per REL_WHEEL click in degrees */
+ int wheel_click_angle;
} scroll;
enum evdev_event_type pending_event;
diff --git a/src/libinput-util.c b/src/libinput-util.c
index c16de1b..49e297a 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -171,3 +171,33 @@ parse_mouse_dpi_property(const char *prop)
}
return dpi;
}
+
+/**
+ * Helper function to parse the MOUSE_WHEEL_CLICK_ANGLE property from udev.
+ * Property is of the form:
+ * MOUSE_WHEEL_CLICK_ANGLE=<integer>
+ * Where the number indicates the degrees travelled for each click.
+ *
+ * We skip preceding whitespaces and parse the first number seen. If
+ * multiple numbers are specified, we ignore those.
+ *
+ * @param prop The value of the udev property (without the MOUSE_WHEEL_CLICK_ANGLE=)
+ * @return The angle of the wheel (may be negative) or 0 on error.
+ */
+int
+parse_mouse_wheel_click_angle_property(const char *prop)
+{
+ int angle = 0,
+ nread = 0;
+
+ while(*prop != 0 && *prop == ' ')
+ prop++;
+
+ sscanf(prop, "%d%n", &angle, &nread);
+ if (nread == 0 || angle == 0 || abs(angle) > 360)
+ return 0;
+ if (prop[nread] != ' ' && prop[nread] != '\0')
+ return 0;
+
+ return angle;
+}
diff --git a/src/libinput-util.h b/src/libinput-util.h
index 6825841..dc70bcd 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -297,5 +297,6 @@ 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);
+int parse_mouse_wheel_click_angle_property(const char *prop);
#endif /* LIBINPUT_UTIL_H */
diff --git a/test/misc.c b/test/misc.c
index c7d9ddf..779b600 100644
--- a/test/misc.c
+++ b/test/misc.c
@@ -531,7 +531,7 @@ END_TEST
struct parser_test {
char *tag;
- int expected_dpi;
+ int expected_value;
};
START_TEST(dpi_parser)
@@ -565,7 +565,36 @@ START_TEST(dpi_parser)
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);
+ ck_assert_int_eq(dpi, tests[i].expected_value);
+ }
+}
+END_TEST
+
+START_TEST(wheel_click_parser)
+{
+ struct parser_test tests[] = {
+ { "1", 1 },
+ { "10", 10 },
+ { "-12", -12 },
+ { "360", 360 },
+ { "66 ", 66 },
+ { " 100 ", 100 },
+
+ { "0", 0 },
+ { "-0", 0 },
+ { "a", 0 },
+ { "10a", 0 },
+ { "10-", 0 },
+ { "sadfasfd", 0 },
+ { "361", 0 },
+ { NULL, 0 }
+ };
+
+ int i, angle;
+
+ for (i = 0; tests[i].tag != NULL; i++) {
+ angle = parse_mouse_wheel_click_angle_property(tests[i].tag);
+ ck_assert_int_eq(angle, tests[i].expected_value);
}
}
END_TEST
@@ -582,6 +611,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);
+ litest_add_no_device("misc:wheel click parser", wheel_click_parser);
return litest_run(argc, argv);
}
--
2.1.0
More information about the wayland-devel
mailing list