Parse the MOUSE_WHEEL_CLICK_ANGLE udev property if present

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
Peter Hutterer 2015-01-12 08:39:47 +10:00
parent 2708be27b2
commit c35885e87d
6 changed files with 97 additions and 4 deletions

View file

@ -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

View file

@ -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_WHEEL_CLICK_ANGLE);
-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_WHEEL_CLICK_ANGLE);
e->value * device->scroll.wheel_click_angle);
break;
}
}
@ -1239,6 +1239,29 @@ evdev_tag_device(struct evdev_device *device)
device->udev_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_WHEEL_CLICK_ANGLE;
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_WHEEL_CLICK_ANGLE);
angle = DEFAULT_WHEEL_CLICK_ANGLE;
}
}
return angle;
}
static inline int
evdev_read_dpi_prop(struct evdev_device *device)
{
@ -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);

View file

@ -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;

View file

@ -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;
}

View file

@ -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 */

View file

@ -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);
}