From ea1c39f702110ddff3367789093d219604c5da87 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 18 Mar 2015 10:01:03 +1000 Subject: [PATCH 1/9] Revert "touchpad: force a resolution onto the apple touchpads" This reverts commit d101d43dd0f7516167ec5d9964268f838a03cff1. This commit was accidentally merged, it was sitting on top of the wip branch. With the 0e64837f30c310da878f28961a6db7c4bcd4f282 commit this isn't necessary anymore. Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 62d80195..998249ff 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -966,22 +966,6 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) res_x = tp->device->abs.absinfo_x->resolution; res_y = tp->device->abs.absinfo_y->resolution; - /* Mac touchpads seem to all be the same size (except the most - * recent ones) - * http://www.moshi.com/trackpad-protector-trackguard-macbook-pro#silver - */ - if (tp->model == MODEL_UNIBODY_MACBOOK && tp->device->abs.fake_resolution) { - const struct input_absinfo *abs; - int width, height; - - abs = tp->device->abs.absinfo_x; - width = abs->maximum - abs->minimum; - abs = tp->device->abs.absinfo_y; - height = abs->maximum - abs->minimum; - res_x = width/104.4; - res_y = height/75.4; - } - /* * Not all touchpads report the same amount of units/mm (resolution). * Normalize motion events to the default mouse DPI as base From 69d5bbbeba90ca67825db868a272e84777b33a1d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 19 Mar 2015 11:02:51 +1000 Subject: [PATCH 2/9] filter: switch to normalized_coords Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 26 ++++++++++++--------- src/evdev.c | 7 +----- src/filter-private.h | 7 +++--- src/filter.c | 50 +++++++++++++++++++---------------------- src/filter.h | 8 +++---- 5 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 998249ff..d4995c9e 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -64,21 +64,27 @@ tp_filter_motion(struct tp_dispatch *tp, double *dx_unaccel, double *dy_unaccel, uint64_t time) { - struct motion_params motion; + struct normalized_coords unaccelerated; + struct normalized_coords accelerated; - motion.dx = *dx; - motion.dy = *dy; + unaccelerated.x = *dx; + unaccelerated.y = *dy; + + if (unaccelerated.x != 0.0 || unaccelerated.y != 0.0) + accelerated = filter_dispatch(tp->device->pointer.filter, + &unaccelerated, + tp, + time); + else + accelerated = unaccelerated; if (dx_unaccel) - *dx_unaccel = motion.dx; + *dx_unaccel = unaccelerated.x; if (dy_unaccel) - *dy_unaccel = motion.dy; + *dy_unaccel = unaccelerated.y; - if (motion.dx != 0.0 || motion.dy != 0.0) - filter_dispatch(tp->device->pointer.filter, &motion, tp, time); - - *dx = motion.dx; - *dy = motion.dy; + *dx = accelerated.x; + *dy = accelerated.y; } static inline void diff --git a/src/evdev.c b/src/evdev.c index 284aa1fb..bcaf3385 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -238,7 +238,6 @@ static void evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { struct libinput *libinput = device->base.seat->libinput; - struct motion_params motion; int slot; int seat_slot; struct libinput_device *base = &device->base; @@ -267,11 +266,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) } /* Apply pointer acceleration. */ - motion.dx = unaccel.x; - motion.dy = unaccel.y; - filter_dispatch(device->pointer.filter, &motion, device, time); - accel.x = motion.dx; - accel.y = motion.dy; + accel = filter_dispatch(device->pointer.filter, &unaccel, device, time); if (accel.x == 0.0 && accel.y == 0.0 && unaccel.x == 0.0 && unaccel.y == 0.0) { diff --git a/src/filter-private.h b/src/filter-private.h index f0d35b40..0e796f1a 100644 --- a/src/filter-private.h +++ b/src/filter-private.h @@ -28,9 +28,10 @@ #include "filter.h" struct motion_filter_interface { - void (*filter)(struct motion_filter *filter, - struct motion_params *motion, - void *data, uint64_t time); + struct normalized_coords (*filter)( + struct motion_filter *filter, + const struct normalized_coords *unaccelerated, + void *data, uint64_t time); void (*destroy)(struct motion_filter *filter); bool (*set_speed)(struct motion_filter *filter, double speed); diff --git a/src/filter.c b/src/filter.c index 306a2fe6..7e935bff 100644 --- a/src/filter.c +++ b/src/filter.c @@ -33,12 +33,12 @@ #include "libinput-util.h" #include "filter-private.h" -void +struct normalized_coords filter_dispatch(struct motion_filter *filter, - struct motion_params *motion, + const struct normalized_coords *unaccelerated, void *data, uint64_t time) { - filter->interface->filter(filter, motion, data, time); + return filter->interface->filter(filter, unaccelerated, data, time); } void @@ -80,8 +80,7 @@ filter_get_speed(struct motion_filter *filter) #define NUM_POINTER_TRACKERS 16 struct pointer_tracker { - double dx; /* delta to most recent event, in device units */ - double dy; /* delta to most recent event, in device units */ + struct normalized_coords delta; /* delta to most recent event */ uint64_t time; /* ms */ int dir; }; @@ -94,8 +93,7 @@ struct pointer_accelerator { double velocity; /* units/ms */ double last_velocity; /* units/ms */ - int last_dx; /* device units */ - int last_dy; /* device units */ + struct normalized_coords last; struct pointer_tracker *trackers; int cur_tracker; @@ -107,24 +105,24 @@ struct pointer_accelerator { static void feed_trackers(struct pointer_accelerator *accel, - double dx, double dy, + const struct normalized_coords *delta, uint64_t time) { int i, current; struct pointer_tracker *trackers = accel->trackers; for (i = 0; i < NUM_POINTER_TRACKERS; i++) { - trackers[i].dx += dx; - trackers[i].dy += dy; + trackers[i].delta.x += delta->x; + trackers[i].delta.y += delta->y; } current = (accel->cur_tracker + 1) % NUM_POINTER_TRACKERS; accel->cur_tracker = current; - trackers[current].dx = 0.0; - trackers[current].dy = 0.0; + trackers[current].delta.x = 0.0; + trackers[current].delta.y = 0.0; trackers[current].time = time; - trackers[current].dir = vector_get_direction(dx, dy); + trackers[current].dir = vector_get_direction(delta->x, delta->y); } static struct pointer_tracker * @@ -139,13 +137,9 @@ tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset) static double calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { - double dx; - double dy; double distance; - dx = tracker->dx; - dy = tracker->dy; - distance = sqrt(dx*dx + dy*dy); + distance = hypot(tracker->delta.x, tracker->delta.y); return distance / (double)(time - tracker->time); /* units/ms */ } @@ -220,27 +214,29 @@ calculate_acceleration(struct pointer_accelerator *accel, return factor; /* unitless factor */ } -static void +static struct normalized_coords accelerator_filter(struct motion_filter *filter, - struct motion_params *motion, + const struct normalized_coords *unaccelerated, void *data, uint64_t time) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; double velocity; /* units/ms */ double accel_value; /* unitless factor */ + struct normalized_coords accelerated; - feed_trackers(accel, motion->dx, motion->dy, time); + feed_trackers(accel, unaccelerated, time); velocity = calculate_velocity(accel, time); accel_value = calculate_acceleration(accel, data, velocity, time); - motion->dx = accel_value * motion->dx; - motion->dy = accel_value * motion->dy; + accelerated.x = accel_value * unaccelerated->x; + accelerated.y = accel_value * unaccelerated->y; - accel->last_dx = motion->dx; - accel->last_dy = motion->dy; + accel->last = *unaccelerated; accel->last_velocity = velocity; + + return accelerated; } static void @@ -294,8 +290,8 @@ create_pointer_accelerator_filter(accel_profile_func_t profile) filter->profile = profile; filter->last_velocity = 0.0; - filter->last_dx = 0; - filter->last_dy = 0; + filter->last.x = 0; + filter->last.y = 0; filter->trackers = calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); diff --git a/src/filter.h b/src/filter.h index f23b691b..70363a62 100644 --- a/src/filter.h +++ b/src/filter.h @@ -28,15 +28,13 @@ #include #include -struct motion_params { - double dx, dy; /* in units/ms @ DEFAULT_MOUSE_DPI resolution */ -}; +#include "libinput-private.h" struct motion_filter; -void +struct normalized_coords filter_dispatch(struct motion_filter *filter, - struct motion_params *motion, + const struct normalized_coords *unaccelerated, void *data, uint64_t time); void filter_destroy(struct motion_filter *filter); From cea13bb4948548a290eba7eafa562f9cc723a10d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 19 Mar 2015 11:10:37 +1000 Subject: [PATCH 3/9] Switch vector_get_direction to use doubles Delta movements on most slower movements are less than 1.0 per event, so we'd end up with an undefined direction for all of them. This led to the velocity being calculated across opposite movements rather than (as intended) across movements within a shared octant. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput-util.h | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libinput-util.h b/src/libinput-util.h index bd71a1ff..91918235 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -111,28 +111,28 @@ enum directions { }; static inline int -vector_get_direction(int dx, int dy) +vector_get_direction(double dx, double dy) { int dir = UNDEFINED_DIRECTION; int d1, d2; double r; - if (abs(dx) < 2 && abs(dy) < 2) { - if (dx > 0 && dy > 0) + if (fabs(dx) < 2.0 && fabs(dy) < 2.0) { + if (dx > 0.0 && dy > 0.0) dir = S | SE | E; - else if (dx > 0 && dy < 0) + else if (dx > 0.0 && dy < 0.0) dir = N | NE | E; - else if (dx < 0 && dy > 0) + else if (dx < 0.0 && dy > 0.0) dir = S | SW | W; - else if (dx < 0 && dy < 0) + else if (dx < 0.0 && dy < 0.0) dir = N | NW | W; - else if (dx > 0) + else if (dx > 0.0) dir = NE | E | SE; - else if (dx < 0) + else if (dx < 0.0) dir = NW | W | SW; - else if (dy > 0) + else if (dy > 0.0) dir = SE | S | SW; - else if (dy < 0) + else if (dy < 0.0) dir = NE | N | NW; } else { /* Calculate r within the interval [0 to 8) From 5f123a1dbbc22383f86d51aaea1387b8ec292c94 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 19 Mar 2015 11:33:55 +1000 Subject: [PATCH 4/9] filter: calculate the time delta correctly If the delta is 0, the distance is the number of units (within this ms). Delta 1 means velocity across 2 ms, etc. Bonus: this doesn't return infinite speed anymore if we get more than one event per ms. This can happen on any device approaching 1000Hz poll rate, but definitely got triggered by the test suite. Actual effect was limited, since we cap out acceleration at max_accel we just hit this earlier and it stayed there. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/filter.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/filter.c b/src/filter.c index 7e935bff..dc299286 100644 --- a/src/filter.c +++ b/src/filter.c @@ -138,9 +138,10 @@ static double calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { double distance; + double tdelta = time - tracker->time + 1; distance = hypot(tracker->delta.x, tracker->delta.y); - return distance / (double)(time - tracker->time); /* units/ms */ + return distance / tdelta; /* units/ms */ } static double From b69905deef7aa97968ba0545d275f6eb06c620fc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 19 Mar 2015 11:43:49 +1000 Subject: [PATCH 5/9] test: add accel test for direction change Make sure that if we go in one direction, then change flip over to the other direction we actually stop going into that direction, and the delta is lower than whatever the previous delta was (i.e. acceleration resets). Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/pointer.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/test/pointer.c b/test/pointer.c index 23bf0d7c..745af638 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -812,6 +812,48 @@ START_TEST(pointer_accel_defaults_absolute) } END_TEST +START_TEST(pointer_accel_direction_change) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *pev; + int i; + double delta; + double max_accel; + + litest_drain_events(li); + + for (i = 0; i < 10; i++) { + litest_event(dev, EV_REL, REL_X, -1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + } + litest_event(dev, EV_REL, REL_X, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + litest_wait_for_event_of_type(li, + LIBINPUT_EVENT_POINTER_MOTION, + -1); + event = libinput_get_event(li); + do { + pev = libinput_event_get_pointer_event(event); + + delta = libinput_event_pointer_get_dx(pev); + ck_assert(delta <= 0.0); + max_accel = delta; + libinput_event_destroy(event); + event = libinput_get_event(li); + } while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE); + + pev = libinput_event_get_pointer_event(event); + delta = libinput_event_pointer_get_dx(pev); + ck_assert(delta > 0.0); + ck_assert(delta < -max_accel); + libinput_event_destroy(event); +} +END_TEST + int main (int argc, char **argv) { litest_add("pointer:motion", pointer_motion_relative, LITEST_RELATIVE, LITEST_ANY); @@ -837,6 +879,7 @@ int main (int argc, char **argv) { litest_add("pointer:accel", pointer_accel_defaults, LITEST_RELATIVE, LITEST_ANY); litest_add("pointer:accel", pointer_accel_invalid, LITEST_RELATIVE, LITEST_ANY); litest_add("pointer:accel", pointer_accel_defaults_absolute, LITEST_ABSOLUTE, LITEST_ANY); + litest_add("pointer:accel", pointer_accel_direction_change, LITEST_RELATIVE, LITEST_ANY); return litest_run(argc, argv); } From 1ed07fedce45d817f70f56439aba6e13be7a8674 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 18 Mar 2015 09:44:09 +1000 Subject: [PATCH 6/9] tools: don't use deprecated gdk_cursor_new() Replaced by gdk_cursor_new_from_display() which means we need to tickle the event until it spits out a GdkDisplay. Deprecated in gdk 3.16 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- tools/event-gui.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/event-gui.c b/tools/event-gui.c index 85c5ab13..75e4e194 100644 --- a/tools/event-gui.c +++ b/tools/event-gui.c @@ -172,6 +172,8 @@ static void map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { struct window *w = data; + GdkDisplay *display; + GdkWindow *window; gtk_window_get_size(GTK_WINDOW(widget), &w->width, &w->height); @@ -185,8 +187,12 @@ map_event_cb(GtkWidget *widget, GdkEvent *event, gpointer data) g_signal_connect(G_OBJECT(w->area), "draw", G_CALLBACK(draw), w); + window = gdk_event_get_window(event); + display = gdk_window_get_display(window); + gdk_window_set_cursor(gtk_widget_get_window(w->win), - gdk_cursor_new(GDK_BLANK_CURSOR)); + gdk_cursor_new_for_display(display, + GDK_BLANK_CURSOR)); } static void From ee376b0b56a2441554ba4bcbf4bb185d7063e3cb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 20 Mar 2015 11:09:05 +1000 Subject: [PATCH 7/9] Revert "touchpad: parse the TOUCHPAD_RESOLUTION property" This reverts commit 0e64837f30c310da878f28961a6db7c4bcd4f282. Rather than a customized touchpad property, let udev handle this and set the absinfo struct during the normal setup procedures. No need for libinput to have a custom workaround here. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/device-configuration-via-udev.dox | 5 --- src/evdev-mt-touchpad.c | 28 --------------- src/libinput-util.c | 30 ---------------- src/libinput-util.h | 3 -- test/misc.c | 49 --------------------------- 5 files changed, 115 deletions(-) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index 87e92e6e..fc1c0af8 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -57,11 +57,6 @@ See @ref motion_normalization for details.
The angle in degrees for each click on a mouse wheel. See libinput_pointer_get_axis_source() for details.
-
TOUCHPAD_RESOLUTION
-
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".
Below is an example udev rule to assign "seat1" to a device from vendor diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d4995c9e..856af4a2 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1123,32 +1123,6 @@ 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) @@ -1162,8 +1136,6 @@ 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 - diff --git a/src/libinput-util.c b/src/libinput-util.c index cd3b18dc..49e297af 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -201,33 +201,3 @@ 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=x - * 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; -} diff --git a/src/libinput-util.h b/src/libinput-util.h index 91918235..04515d6d 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -299,8 +299,5 @@ 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 */ diff --git a/test/misc.c b/test/misc.c index 414d7cb3..db26d67e 100644 --- a/test/misc.c +++ b/test/misc.c @@ -557,54 +557,6 @@ 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); @@ -620,7 +572,6 @@ 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); } From 0e262e55bc5321eff4619634b9ed3c5b99f9db99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 23 Mar 2015 12:08:14 +1000 Subject: [PATCH 8/9] evdev: reject devices with a min == max axis range Except for a few axes where this may be correct, a min == max axis range indicates a broken kernel driver. To avoid potential divisions by zero when scaling this axis later, reject such a device outright. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 34 +++++++++++++++++++++ test/device.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index bcaf3385..52b89d38 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1452,10 +1452,32 @@ evdev_fix_android_mt(struct evdev_device *device) libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y)); } +static inline int +evdev_check_min_max(struct evdev_device *device, unsigned int code) +{ + struct libevdev *evdev = device->evdev; + const struct input_absinfo *absinfo; + + if (!libevdev_has_event_code(evdev, EV_ABS, code)) + return 0; + + absinfo = libevdev_get_abs_info(evdev, code); + if (absinfo->minimum == absinfo->maximum) { + log_bug_kernel(device->base.seat->libinput, + "Device '%s' has min == max on %s\n", + device->devname, + libevdev_event_code_get_name(EV_ABS, code)); + return -1; + } + + return 0; +} + static int evdev_reject_device(struct evdev_device *device) { struct libevdev *evdev = device->evdev; + unsigned int code; if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^ libevdev_has_event_code(evdev, EV_ABS, ABS_Y)) @@ -1465,6 +1487,18 @@ evdev_reject_device(struct evdev_device *device) libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) return -1; + for (code = 0; code < ABS_CNT; code++) { + switch (code) { + case ABS_MISC: + case ABS_MT_SLOT: + case ABS_MT_TOOL_TYPE: + break; + default: + if (evdev_check_min_max(device, code) == -1) + return -1; + } + } + return 0; } diff --git a/test/device.c b/test/device.c index a18ec82d..c9d52556 100644 --- a/test/device.c +++ b/test/device.c @@ -814,6 +814,86 @@ START_TEST(abs_mt_device_no_absx) } END_TEST +START_TEST(abs_device_no_range) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + int code; + /* set x/y so libinput doesn't just reject for missing axes */ + struct input_absinfo absinfo[] = { + { ABS_X, 0, 10, 0, 0, 0 }, + { ABS_Y, 0, 10, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, -1, -1, -1, -1, -1 } + }; + + li = litest_create_context(); + litest_disable_log_handler(li); + + for (code = 0; code < ABS_MT_SLOT; code++) { + if (code == ABS_MISC) + continue; + absinfo[2].value = code; + uinput = litest_create_uinput_abs_device("test device", NULL, + absinfo, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + -1); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device == NULL); + libevdev_uinput_destroy(uinput); + } + + litest_restore_log_handler(li); + libinput_unref(li); +} +END_TEST + +START_TEST(abs_mt_device_no_range) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + int code; + /* set x/y so libinput doesn't just reject for missing axes */ + struct input_absinfo absinfo[] = { + { ABS_X, 0, 10, 0, 0, 0 }, + { ABS_Y, 0, 10, 0, 0, 0 }, + { ABS_MT_SLOT, 0, 10, 0, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 255, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 10, 0, 0, 0 }, + { ABS_MT_POSITION_Y, 0, 10, 0, 0, 0 }, + { -1, 0, 0, 0, 0, 0 }, + { -1, -1, -1, -1, -1, -1 } + }; + + li = litest_create_context(); + litest_disable_log_handler(li); + + for (code = ABS_MT_SLOT + 1; code < ABS_CNT; code++) { + if (code == ABS_MT_TOOL_TYPE || + code == ABS_MT_TRACKING_ID) /* kernel overrides it */ + continue; + + absinfo[6].value = code; + uinput = litest_create_uinput_abs_device("test device", NULL, + absinfo, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + -1); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + ck_assert(device == NULL); + libevdev_uinput_destroy(uinput); + } + + litest_restore_log_handler(li); + libinput_unref(li); +} +END_TEST + int main (int argc, char **argv) { litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD); @@ -846,6 +926,8 @@ int main (int argc, char **argv) litest_add_no_device("device:invalid devices", abs_device_no_absy); litest_add_no_device("device:invalid devices", abs_mt_device_no_absx); litest_add_no_device("device:invalid devices", abs_mt_device_no_absy); + litest_add_no_device("device:invalid devices", abs_device_no_range); + litest_add_no_device("device:invalid devices", abs_mt_device_no_range); return litest_run(argc, argv); } From f893f2bf9bb1aeaffffc4635ec15bc253d2f5ee9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 24 Mar 2015 15:49:41 +1000 Subject: [PATCH 9/9] configure.ac: libinput 0.13.0 Signed-off-by: Peter Hutterer --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index ed0945e0..23354542 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.64]) m4_define([libinput_major_version], [0]) -m4_define([libinput_minor_version], [12]) +m4_define([libinput_minor_version], [13]) m4_define([libinput_micro_version], [0]) m4_define([libinput_version], [libinput_major_version.libinput_minor_version.libinput_micro_version]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) # b) If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # c) If the interface is the same as the previous version, change to C:R+1:A -LIBINPUT_LT_VERSION=10:0:0 +LIBINPUT_LT_VERSION=10:1:0 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes])