From 2ab0db9ee9d933d18916f95d43ed06a3878b717d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Mar 2015 20:05:24 +0100 Subject: [PATCH 01/33] litest: Make touchpad_2fg_scroll_slow_distance take resolution into account Currently touchpad_2fg_scroll_slow_distance always moves the touches 10% of the touchpad height during the test. On the wacom-intuos-finger test device this is a much larger distance then on the synaptics test device, triggering ck_assert(axisval < 5.0) errors with further patches in this set, this commit fixes this. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- test/touchpad.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index ff4edb04..36fe6e43 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1864,13 +1864,24 @@ START_TEST(touchpad_2fg_scroll_slow_distance) struct libinput *li = dev->libinput; struct libinput_event *event; struct libinput_event_pointer *ptrev; + const struct input_absinfo *y; + double y_move; + + /* We want to move > 5 mm. */ + y = libevdev_get_abs_info(dev->evdev, ABS_Y); + if (y->resolution) { + y_move = 7.0 * y->resolution / + (y->maximum - y->minimum) * 100; + } else { + y_move = 10.0; + } litest_drain_events(li); litest_touch_down(dev, 0, 20, 30); litest_touch_down(dev, 1, 40, 30); - litest_touch_move_to(dev, 0, 20, 30, 20, 40, 70, 10); - litest_touch_move_to(dev, 1, 40, 30, 40, 40, 70, 10); + litest_touch_move_to(dev, 0, 20, 30, 20, 30 + y_move, 70, 10); + litest_touch_move_to(dev, 1, 40, 30, 40, 30 + y_move, 70, 10); litest_touch_up(dev, 1); litest_touch_up(dev, 0); libinput_dispatch(li); From a8eb6c84a27d5b8185f3ee5158d0af73eb6188ce Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Mar 2015 20:05:25 +0100 Subject: [PATCH 02/33] litest: Add a litest_touch_move_two_touches helper function Currently all the touchpad 2fg tests move the 2 fingers 1 at a time, causing a finger motion which looks more like a pinch zoom in followed by a zoom out than an actual 2fg scroll gesture. Add a helper function which can move 2 fingers at the same time (more or less), and use this where relevant. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- test/litest.c | 22 ++++++++++++++++++++++ test/litest.h | 5 +++++ test/touchpad.c | 17 ++++++----------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/test/litest.c b/test/litest.c index 36464462..fc4b1fb3 100644 --- a/test/litest.c +++ b/test/litest.c @@ -903,6 +903,28 @@ litest_touch_move_to(struct litest_device *d, litest_touch_move(d, slot, x_to, y_to); } +void +litest_touch_move_two_touches(struct litest_device *d, + double x0, double y0, + double x1, double y1, + double dx, double dy, + int steps, int sleep_ms) +{ + for (int i = 0; i < steps - 1; i++) { + litest_touch_move(d, 0, x0 + dx / steps * i, + y0 + dy / steps * i); + litest_touch_move(d, 1, x1 + dx / steps * i, + y1 + dy / steps * i); + if (sleep_ms) { + libinput_dispatch(d->libinput); + msleep(sleep_ms); + libinput_dispatch(d->libinput); + } + } + litest_touch_move(d, 0, x0 + dx, y0 + dy); + litest_touch_move(d, 1, x1 + dx, y1 + dy); +} + void litest_button_click(struct litest_device *d, unsigned int button, bool is_press) { diff --git a/test/litest.h b/test/litest.h index e85b511e..a48daf43 100644 --- a/test/litest.h +++ b/test/litest.h @@ -150,6 +150,11 @@ void litest_touch_move_to(struct litest_device *d, double x_from, double y_from, double x_to, double y_to, int steps, int sleep_ms); +void litest_touch_move_two_touches(struct litest_device *d, + double x0, double y0, + double x1, double y1, + double dx, double dy, + int steps, int sleep_ms); void litest_button_click(struct litest_device *d, unsigned int button, bool is_press); diff --git a/test/touchpad.c b/test/touchpad.c index 36fe6e43..140d770d 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1820,8 +1820,7 @@ test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep) litest_touch_down(dev, 0, 47, 50); litest_touch_down(dev, 1, 53, 50); - litest_touch_move_to(dev, 0, 47, 50, 47 + dx, 50 + dy, 5, 0); - litest_touch_move_to(dev, 1, 53, 50, 53 + dx, 50 + dy, 5, 0); + litest_touch_move_two_touches(dev, 47, 50, 53, 50, dx, dy, 5, 0); /* Avoid a small scroll being seen as a tap */ if (want_sleep) { @@ -1880,8 +1879,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance) litest_touch_down(dev, 0, 20, 30); litest_touch_down(dev, 1, 40, 30); - litest_touch_move_to(dev, 0, 20, 30, 20, 30 + y_move, 70, 10); - litest_touch_move_to(dev, 1, 40, 30, 40, 30 + y_move, 70, 10); + litest_touch_move_two_touches(dev, 20, 30, 40, 30, 0, y_move, 70, 10); litest_touch_up(dev, 1); litest_touch_up(dev, 0); libinput_dispatch(li); @@ -1951,8 +1949,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) /* 2fg scroll */ litest_touch_down(dev, 1, 53, 50); - litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); - litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); + litest_touch_move_two_touches(dev, 47, 50, 53, 50, 0, 20, 5, 0); litest_touch_up(dev, 1); libinput_dispatch(li); litest_timeout_finger_switch(); @@ -1963,9 +1960,8 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); /* back to 2fg scroll, lifting the other finger */ - litest_touch_down(dev, 1, 50, 50); - litest_touch_move_to(dev, 0, 47, 50, 47, 70, 5, 0); - litest_touch_move_to(dev, 1, 53, 50, 53, 70, 5, 0); + litest_touch_down(dev, 1, 53, 50); + litest_touch_move_two_touches(dev, 47, 50, 53, 50, 0, 20, 5, 0); litest_touch_up(dev, 0); libinput_dispatch(li); litest_timeout_finger_switch(); @@ -3273,8 +3269,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) litest_touch_down(touchpad, 0, 40, 70); litest_touch_down(touchpad, 1, 60, 70); - litest_touch_move_to(touchpad, 0, 40, 70, 40, 30, 10, 0); - litest_touch_move_to(touchpad, 1, 60, 70, 60, 30, 10, 0); + litest_touch_move_two_touches(touchpad, 40, 70, 60, 70, 0, -40, 10, 0); libinput_dispatch(li); litest_wait_for_event(li); From db6f1b556a14a6e10ce4f6fd7eaeb2e08e04cfa3 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 12 Mar 2015 20:05:26 +0100 Subject: [PATCH 03/33] litest: Put fingers down closer together for 2fg scroll tests The current default start location for the 2fg scroll tests: 47%, 50% and 53%, 50% are further than 3cm apart on the wacom-intuos-finger test device, causing test failures when pinch gesture support gets added. This fixes this, and also switches the fingers in the touchpad_2fg_scroll_slow_distance and touchpad_trackpoint_buttons_2fg_scroll tests to the default locations rather than putting them pretty far apart. Signed-off-by: Hans de Goede Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- test/touchpad.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 140d770d..6fa23016 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1817,10 +1817,10 @@ test_2fg_scroll(struct litest_device *dev, double dx, double dy, int want_sleep) { struct libinput *li = dev->libinput; - litest_touch_down(dev, 0, 47, 50); - litest_touch_down(dev, 1, 53, 50); + litest_touch_down(dev, 0, 49, 50); + litest_touch_down(dev, 1, 51, 50); - litest_touch_move_two_touches(dev, 47, 50, 53, 50, dx, dy, 5, 0); + litest_touch_move_two_touches(dev, 49, 50, 51, 50, dx, dy, 5, 0); /* Avoid a small scroll being seen as a tap */ if (want_sleep) { @@ -1877,9 +1877,9 @@ START_TEST(touchpad_2fg_scroll_slow_distance) litest_drain_events(li); - litest_touch_down(dev, 0, 20, 30); - litest_touch_down(dev, 1, 40, 30); - litest_touch_move_two_touches(dev, 20, 30, 40, 30, 0, y_move, 70, 10); + litest_touch_down(dev, 0, 49, 50); + litest_touch_down(dev, 1, 51, 50); + litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, y_move, 70, 10); litest_touch_up(dev, 1); litest_touch_up(dev, 0); libinput_dispatch(li); @@ -1944,24 +1944,24 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) /* start with motion */ litest_touch_down(dev, 0, 70, 70); - litest_touch_move_to(dev, 0, 70, 70, 47, 50, 10, 0); + litest_touch_move_to(dev, 0, 70, 70, 49, 50, 10, 0); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); /* 2fg scroll */ - litest_touch_down(dev, 1, 53, 50); - litest_touch_move_two_touches(dev, 47, 50, 53, 50, 0, 20, 5, 0); + litest_touch_down(dev, 1, 51, 50); + litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0); litest_touch_up(dev, 1); libinput_dispatch(li); litest_timeout_finger_switch(); libinput_dispatch(li); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); - litest_touch_move_to(dev, 0, 47, 70, 47, 50, 10, 0); + litest_touch_move_to(dev, 0, 49, 70, 49, 50, 10, 0); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); /* back to 2fg scroll, lifting the other finger */ - litest_touch_down(dev, 1, 53, 50); - litest_touch_move_two_touches(dev, 47, 50, 53, 50, 0, 20, 5, 0); + litest_touch_down(dev, 1, 51, 50); + litest_touch_move_two_touches(dev, 49, 50, 51, 50, 0, 20, 5, 0); litest_touch_up(dev, 0); libinput_dispatch(li); litest_timeout_finger_switch(); @@ -1969,7 +1969,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* move with second finger */ - litest_touch_move_to(dev, 1, 53, 70, 53, 50, 10, 0); + litest_touch_move_to(dev, 1, 51, 70, 51, 50, 10, 0); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); litest_touch_up(dev, 1); @@ -3267,9 +3267,9 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) litest_drain_events(li); - litest_touch_down(touchpad, 0, 40, 70); - litest_touch_down(touchpad, 1, 60, 70); - litest_touch_move_two_touches(touchpad, 40, 70, 60, 70, 0, -40, 10, 0); + litest_touch_down(touchpad, 0, 49, 70); + litest_touch_down(touchpad, 1, 51, 70); + litest_touch_move_two_touches(touchpad, 49, 70, 51, 70, 0, -40, 10, 0); libinput_dispatch(li); litest_wait_for_event(li); From 3c7b83e0e08115e7bccb61f489376c41f7f902e1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 09:38:48 +1000 Subject: [PATCH 04/33] Calling has_axis on a non-axis pointer event is a bug, note this Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libinput.h b/src/libinput.h index ca08c3e8..9a7829ea 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -668,6 +668,12 @@ libinput_event_pointer_get_seat_button_count( * libinput_event_pointer_get_axis_value() returns a value of 0, the event * is a scroll stop event. * + * For pointer events that are not of type @ref LIBINPUT_EVENT_POINTER_AXIS, + * this function returns 0. + * + * @note It is an application bug to call this function for events other than + * @ref LIBINPUT_EVENT_POINTER_AXIS. + * * @return Non-zero if this event contains a value for this axis */ int From 1447f1e3ede407c1e8162117c5b2534b40fa9aa4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 09:50:07 +1000 Subject: [PATCH 05/33] Correct documentation on get_slot and get_seat_slot() We don't actually use TOUCH_CANCEL in libinput, but either way calling the slot on a cancel should be valid. Calling it on a FRAME event is not. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libinput.h b/src/libinput.h index 9a7829ea..f978b37f 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -797,8 +797,13 @@ libinput_event_touch_get_time(struct libinput_event_touch *event); * If the touch event has no assigned slot, for example if it is from a * single touch device, this function returns -1. * - * @note this function should not be called for @ref - * LIBINPUT_EVENT_TOUCH_CANCEL or @ref LIBINPUT_EVENT_TOUCH_FRAME. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref + * LIBINPUT_EVENT_TOUCH_CANCEL, this function returns 0. + * + * @note It is an application bug to call this function for events of type + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_UP, + * @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref LIBINPUT_EVENT_TOUCH_CANCEL. * * @return The slot of this touch event */ @@ -814,8 +819,13 @@ libinput_event_touch_get_slot(struct libinput_event_touch *event); * Events from single touch devices will be represented as one individual * touch point per device. * - * @note this function should not be called for @ref - * LIBINPUT_EVENT_TOUCH_CANCEL or @ref LIBINPUT_EVENT_TOUCH_FRAME. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_UP, @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref + * LIBINPUT_EVENT_TOUCH_CANCEL, this function returns 0. + * + * @note It is an application bug to call this function for events of type + * other than @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref LIBINPUT_EVENT_TOUCH_UP, + * @ref LIBINPUT_EVENT_TOUCH_MOTION or @ref LIBINPUT_EVENT_TOUCH_CANCEL. * * @return The seat slot of the touch event */ From 8b60578c8f2eec7c4cf0ef7d19792adfa8875468 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 09:56:36 +1000 Subject: [PATCH 06/33] Expand documentation on touch events, listing what is permitted when Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libinput.h b/src/libinput.h index f978b37f..356c1bf0 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -839,8 +839,11 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event); * the top left corner of the device. To get the corresponding output screen * coordinate, use libinput_event_touch_get_x_transformed(). * - * @note this function should only be called for @ref - * LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. + * + * @note It is an application bug to call this function for events of type + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @return The current absolute x coordinate @@ -855,10 +858,11 @@ libinput_event_touch_get_x(struct libinput_event_touch *event); * the top left corner of the device. To get the corresponding output screen * coordinate, use libinput_event_touch_get_y_transformed(). * - * For @ref LIBINPUT_EVENT_TOUCH_UP 0 is returned. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. * - * @note this function should only be called for @ref LIBINPUT_EVENT_TOUCH_DOWN and - * @ref LIBINPUT_EVENT_TOUCH_MOTION. + * @note It is an application bug to call this function for events of type + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @return The current absolute y coordinate @@ -872,8 +876,11 @@ libinput_event_touch_get_y(struct libinput_event_touch *event); * Return the current absolute x coordinate of the touch event, transformed to * screen coordinates. * - * @note this function should only be called for @ref - * LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. + * + * @note It is an application bug to call this function for events of type + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @param width The current output screen width @@ -889,8 +896,11 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, * Return the current absolute y coordinate of the touch event, transformed to * screen coordinates. * - * @note this function should only be called for @ref - * LIBINPUT_EVENT_TOUCH_DOWN and @ref LIBINPUT_EVENT_TOUCH_MOTION. + * For events not of type @ref LIBINPUT_EVENT_TOUCH_DOWN, @ref + * LIBINPUT_EVENT_TOUCH_MOTION, this function returns 0. + * + * @note It is an application bug to call this function for events of type + * @ref LIBINPUT_EVENT_TOUCH_DOWN or @ref LIBINPUT_EVENT_TOUCH_MOTION. * * @param event The libinput touch event * @param height The current output screen height From 44f7446b2aa1a88157776f791b2ca9e4cf45013a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 10:11:41 +1000 Subject: [PATCH 07/33] test: abort() for invalid logging priorities Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/litest.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/litest.c b/test/litest.c index fc4b1fb3..b5e4230d 100644 --- a/test/litest.c +++ b/test/litest.c @@ -372,6 +372,8 @@ litest_log_handler(struct libinput *libinput, case LIBINPUT_LOG_PRIORITY_INFO: priority = "info"; break; case LIBINPUT_LOG_PRIORITY_ERROR: priority = "error"; break; case LIBINPUT_LOG_PRIORITY_DEBUG: priority = "debug"; break; + default: + abort(); } fprintf(stderr, "litest %s: ", priority); From 7f28b714d858e8db831771d011096e60feb15e79 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 09:32:37 +1000 Subject: [PATCH 08/33] Replace event type check switch statements with a helper macro/function The helper function now prints an error message if the event type passed is not allowed. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.c | 142 ++++++++++++++++++++++--------------------------- test/litest.c | 12 +++++ test/litest.h | 2 + test/misc.c | 10 ++++ 4 files changed, 88 insertions(+), 78 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 42354ba9..4d88c46b 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -35,6 +35,42 @@ #include "evdev.h" #include "timer.h" +#define require_event_type(li_, type_, retval_, ...) \ + if (type_ == LIBINPUT_EVENT_NONE) abort(); \ + if (!check_event_type(li_, __func__, type_, __VA_ARGS__, -1)) \ + return retval_; \ + +static inline bool +check_event_type(struct libinput *libinput, + const char *function_name, + enum libinput_event_type type_in, + ...) +{ + bool rc = false; + va_list args; + unsigned int type_permitted; + + va_start(args, type_in); + type_permitted = va_arg(args, unsigned int); + + while (type_permitted != (unsigned int)-1) { + if (type_permitted == type_in) { + rc = true; + break; + } + type_permitted = va_arg(args, unsigned int); + } + + va_end(args); + + if (!rc) + log_bug_client(libinput, + "Invalid event type %d passed to %s()\n", + type_in, function_name); + + return rc; +} + struct libinput_source { libinput_source_dispatch_t dispatch; void *user_data; @@ -165,103 +201,53 @@ libinput_event_get_device(struct libinput_event *event) LIBINPUT_EXPORT struct libinput_event_pointer * libinput_event_get_pointer_event(struct libinput_event *event) { - switch (event->type) { - case LIBINPUT_EVENT_NONE: - abort(); /* not used as actual event type */ - case LIBINPUT_EVENT_DEVICE_ADDED: - case LIBINPUT_EVENT_DEVICE_REMOVED: - case LIBINPUT_EVENT_KEYBOARD_KEY: - break; - case LIBINPUT_EVENT_POINTER_MOTION: - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - case LIBINPUT_EVENT_POINTER_BUTTON: - case LIBINPUT_EVENT_POINTER_AXIS: - return (struct libinput_event_pointer *) event; - case LIBINPUT_EVENT_TOUCH_DOWN: - case LIBINPUT_EVENT_TOUCH_UP: - case LIBINPUT_EVENT_TOUCH_MOTION: - case LIBINPUT_EVENT_TOUCH_CANCEL: - case LIBINPUT_EVENT_TOUCH_FRAME: - break; - } + require_event_type(libinput_event_get_context(event), + event->type, + NULL, + LIBINPUT_EVENT_POINTER_MOTION, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS); - return NULL; + return (struct libinput_event_pointer *) event; } LIBINPUT_EXPORT struct libinput_event_keyboard * libinput_event_get_keyboard_event(struct libinput_event *event) { - switch (event->type) { - case LIBINPUT_EVENT_NONE: - abort(); /* not used as actual event type */ - case LIBINPUT_EVENT_DEVICE_ADDED: - case LIBINPUT_EVENT_DEVICE_REMOVED: - break; - case LIBINPUT_EVENT_KEYBOARD_KEY: - return (struct libinput_event_keyboard *) event; - case LIBINPUT_EVENT_POINTER_MOTION: - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - case LIBINPUT_EVENT_POINTER_BUTTON: - case LIBINPUT_EVENT_POINTER_AXIS: - case LIBINPUT_EVENT_TOUCH_DOWN: - case LIBINPUT_EVENT_TOUCH_UP: - case LIBINPUT_EVENT_TOUCH_MOTION: - case LIBINPUT_EVENT_TOUCH_CANCEL: - case LIBINPUT_EVENT_TOUCH_FRAME: - break; - } + require_event_type(libinput_event_get_context(event), + event->type, + NULL, + LIBINPUT_EVENT_KEYBOARD_KEY); - return NULL; + return (struct libinput_event_keyboard *) event; } LIBINPUT_EXPORT struct libinput_event_touch * libinput_event_get_touch_event(struct libinput_event *event) { - switch (event->type) { - case LIBINPUT_EVENT_NONE: - abort(); /* not used as actual event type */ - case LIBINPUT_EVENT_DEVICE_ADDED: - case LIBINPUT_EVENT_DEVICE_REMOVED: - case LIBINPUT_EVENT_KEYBOARD_KEY: - case LIBINPUT_EVENT_POINTER_MOTION: - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - case LIBINPUT_EVENT_POINTER_BUTTON: - case LIBINPUT_EVENT_POINTER_AXIS: - break; - case LIBINPUT_EVENT_TOUCH_DOWN: - case LIBINPUT_EVENT_TOUCH_UP: - case LIBINPUT_EVENT_TOUCH_MOTION: - case LIBINPUT_EVENT_TOUCH_CANCEL: - case LIBINPUT_EVENT_TOUCH_FRAME: - return (struct libinput_event_touch *) event; - } + require_event_type(libinput_event_get_context(event), + event->type, + NULL, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL, + LIBINPUT_EVENT_TOUCH_FRAME); - return NULL; + return (struct libinput_event_touch *) event; } LIBINPUT_EXPORT struct libinput_event_device_notify * libinput_event_get_device_notify_event(struct libinput_event *event) { - switch (event->type) { - case LIBINPUT_EVENT_NONE: - abort(); /* not used as actual event type */ - case LIBINPUT_EVENT_DEVICE_ADDED: - case LIBINPUT_EVENT_DEVICE_REMOVED: - return (struct libinput_event_device_notify *) event; - case LIBINPUT_EVENT_KEYBOARD_KEY: - case LIBINPUT_EVENT_POINTER_MOTION: - case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: - case LIBINPUT_EVENT_POINTER_BUTTON: - case LIBINPUT_EVENT_POINTER_AXIS: - case LIBINPUT_EVENT_TOUCH_DOWN: - case LIBINPUT_EVENT_TOUCH_UP: - case LIBINPUT_EVENT_TOUCH_MOTION: - case LIBINPUT_EVENT_TOUCH_CANCEL: - case LIBINPUT_EVENT_TOUCH_FRAME: - break; - } + require_event_type(libinput_event_get_context(event), + event->type, + NULL, + LIBINPUT_EVENT_DEVICE_ADDED, + LIBINPUT_EVENT_DEVICE_REMOVED); - return NULL; + return (struct libinput_event_device_notify *) event; } LIBINPUT_EXPORT uint32_t diff --git a/test/litest.c b/test/litest.c index b5e4230d..e6ae1617 100644 --- a/test/litest.c +++ b/test/litest.c @@ -642,6 +642,18 @@ litest_create_context(void) return libinput; } +void +litest_disable_log_handler(struct libinput *libinput) +{ + libinput_log_set_handler(libinput, NULL); +} + +void +litest_restore_log_handler(struct libinput *libinput) +{ + libinput_log_set_handler(libinput, litest_log_handler); +} + struct litest_device * litest_add_device_with_overrides(struct libinput *libinput, enum litest_device_type which, diff --git a/test/litest.h b/test/litest.h index a48daf43..676293be 100644 --- a/test/litest.h +++ b/test/litest.h @@ -92,6 +92,8 @@ struct litest_device { }; struct libinput *litest_create_context(void); +void litest_disable_log_handler(struct libinput *libinput); +void litest_restore_log_handler(struct libinput *libinput); void litest_add(const char *name, void *func, enum litest_device_feature required_feature, diff --git a/test/misc.c b/test/misc.c index 5b8191f2..db26d67e 100644 --- a/test/misc.c +++ b/test/misc.c @@ -126,9 +126,11 @@ START_TEST(event_conversion_device_notify) else if (type == LIBINPUT_EVENT_DEVICE_REMOVED) device_removed++; + litest_disable_log_handler(li); ck_assert(libinput_event_get_pointer_event(event) == NULL); ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); + litest_restore_log_handler(li); } libinput_event_destroy(event); @@ -178,9 +180,11 @@ START_TEST(event_conversion_pointer) else if (type == LIBINPUT_EVENT_POINTER_BUTTON) button++; + litest_disable_log_handler(li); ck_assert(libinput_event_get_device_notify_event(event) == NULL); ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); + litest_restore_log_handler(li); } libinput_event_destroy(event); } @@ -224,9 +228,11 @@ START_TEST(event_conversion_pointer_abs) else if (type == LIBINPUT_EVENT_POINTER_BUTTON) button++; + litest_disable_log_handler(li); ck_assert(libinput_event_get_device_notify_event(event) == NULL); ck_assert(libinput_event_get_keyboard_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); + litest_restore_log_handler(li); } libinput_event_destroy(event); } @@ -263,9 +269,11 @@ START_TEST(event_conversion_key) key++; + litest_disable_log_handler(li); ck_assert(libinput_event_get_device_notify_event(event) == NULL); ck_assert(libinput_event_get_pointer_event(event) == NULL); ck_assert(libinput_event_get_touch_event(event) == NULL); + litest_restore_log_handler(li); } libinput_event_destroy(event); } @@ -309,9 +317,11 @@ START_TEST(event_conversion_touch) touch++; + litest_disable_log_handler(li); ck_assert(libinput_event_get_device_notify_event(event) == NULL); ck_assert(libinput_event_get_pointer_event(event) == NULL); ck_assert(libinput_event_get_keyboard_event(event) == NULL); + litest_restore_log_handler(li); } libinput_event_destroy(event); } From eeac7106d53ffabc33ed6bbdb2908b41e3489565 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 10:07:53 +1000 Subject: [PATCH 09/33] Add event type checking to the various libinput_event_ functions Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 185 insertions(+), 6 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 4d88c46b..12317833 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -253,18 +253,33 @@ libinput_event_get_device_notify_event(struct libinput_event *event) LIBINPUT_EXPORT uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_KEYBOARD_KEY); + return event->time; } LIBINPUT_EXPORT uint32_t libinput_event_keyboard_get_key(struct libinput_event_keyboard *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_KEYBOARD_KEY); + return event->key; } LIBINPUT_EXPORT enum libinput_key_state libinput_event_keyboard_get_key_state(struct libinput_event_keyboard *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_KEYBOARD_KEY); + return event->state; } @@ -272,24 +287,47 @@ LIBINPUT_EXPORT uint32_t libinput_event_keyboard_get_seat_key_count( struct libinput_event_keyboard *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_KEYBOARD_KEY); + return event->seat_key_count; } LIBINPUT_EXPORT uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS); + return event->time; } LIBINPUT_EXPORT double libinput_event_pointer_get_dx(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION); + return event->x; } LIBINPUT_EXPORT double libinput_event_pointer_get_dy(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION); + return event->y; } @@ -297,6 +335,11 @@ LIBINPUT_EXPORT double libinput_event_pointer_get_dx_unaccelerated( struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION); + return event->dx_unaccel; } @@ -304,6 +347,11 @@ LIBINPUT_EXPORT double libinput_event_pointer_get_dy_unaccelerated( struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION); + return event->dy_unaccel; } @@ -313,6 +361,11 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); + return evdev_convert_to_mm(device->abs.absinfo_x, event->x); } @@ -322,6 +375,11 @@ libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); + return evdev_convert_to_mm(device->abs.absinfo_y, event->y); } @@ -333,6 +391,11 @@ libinput_event_pointer_get_absolute_x_transformed( struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); + return evdev_device_transform_x(device, event->x, width); } @@ -344,18 +407,33 @@ libinput_event_pointer_get_absolute_y_transformed( struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); + return evdev_device_transform_y(device, event->y, height); } LIBINPUT_EXPORT uint32_t libinput_event_pointer_get_button(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_BUTTON); + return event->button; } LIBINPUT_EXPORT enum libinput_button_state libinput_event_pointer_get_button_state(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_BUTTON); + return event->state; } @@ -363,6 +441,11 @@ LIBINPUT_EXPORT uint32_t libinput_event_pointer_get_seat_button_count( struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_BUTTON); + return event->seat_button_count; } @@ -370,13 +453,17 @@ LIBINPUT_EXPORT int libinput_event_pointer_has_axis(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { - if (event->base.type == LIBINPUT_EVENT_POINTER_AXIS) { - switch (axis) { - case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: - case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: - return !!(event->axes & AS_MASK(axis)); - } + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_AXIS); + + switch (axis) { + case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: + case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: + return !!(event->axes & AS_MASK(axis)); } + return 0; } @@ -387,6 +474,11 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, struct libinput *libinput = event->base.device->seat->libinput; double value = 0; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0.0, + LIBINPUT_EVENT_POINTER_AXIS); + if (!libinput_event_pointer_has_axis(event, axis)) { log_bug_client(libinput, "value requested for unset axis\n"); } else { @@ -410,6 +502,11 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev struct libinput *libinput = event->base.device->seat->libinput; double value = 0; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0.0, + LIBINPUT_EVENT_POINTER_AXIS); + if (!libinput_event_pointer_has_axis(event, axis)) { log_bug_client(libinput, "value requested for unset axis\n"); } else { @@ -428,24 +525,54 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev LIBINPUT_EXPORT enum libinput_pointer_axis_source libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_AXIS); + return event->source; } LIBINPUT_EXPORT uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL, + LIBINPUT_EVENT_TOUCH_FRAME); + return event->time; } LIBINPUT_EXPORT int32_t libinput_event_touch_get_slot(struct libinput_event_touch *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL); + return event->slot; } LIBINPUT_EXPORT int32_t libinput_event_touch_get_seat_slot(struct libinput_event_touch *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL); + return event->seat_slot; } @@ -455,6 +582,12 @@ libinput_event_touch_get_x(struct libinput_event_touch *event) struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_MOTION); + return evdev_convert_to_mm(device->abs.absinfo_x, event->x); } @@ -465,6 +598,12 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_MOTION); + return evdev_device_transform_x(device, event->x, width); } @@ -475,6 +614,12 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_MOTION); + return evdev_device_transform_y(device, event->y, height); } @@ -484,6 +629,12 @@ libinput_event_touch_get_y(struct libinput_event_touch *event) struct evdev_device *device = (struct evdev_device *) event->base.device; + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_MOTION); + return evdev_convert_to_mm(device->abs.absinfo_y, event->y); } @@ -1358,24 +1509,52 @@ libinput_device_pointer_has_button(struct libinput_device *device, uint32_t code LIBINPUT_EXPORT struct libinput_event * libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + NULL, + LIBINPUT_EVENT_DEVICE_ADDED, + LIBINPUT_EVENT_DEVICE_REMOVED); + return &event->base; } LIBINPUT_EXPORT struct libinput_event * libinput_event_keyboard_get_base_event(struct libinput_event_keyboard *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + NULL, + LIBINPUT_EVENT_KEYBOARD_KEY); + return &event->base; } LIBINPUT_EXPORT struct libinput_event * libinput_event_pointer_get_base_event(struct libinput_event_pointer *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + NULL, + LIBINPUT_EVENT_POINTER_MOTION, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS); + return &event->base; } LIBINPUT_EXPORT struct libinput_event * libinput_event_touch_get_base_event(struct libinput_event_touch *event) { + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + NULL, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL, + LIBINPUT_EVENT_TOUCH_FRAME); + return &event->base; } From abdd86a4c4b6a0e586f56ecfebe0f7852e57b20c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 09:22:59 +1000 Subject: [PATCH 10/33] cosmetic: rename touch to t for consistency Everywhere else in the touchpad code we use "t" for the struct tp_touch. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index a7936b61..a1839cbf 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -45,17 +45,17 @@ enum scroll_event { }; static uint32_t -tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *touch) +tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t) { uint32_t edge = EDGE_NONE; if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) return EDGE_NONE; - if (touch->x > tp->scroll.right_edge) + if (t->x > tp->scroll.right_edge) edge |= EDGE_RIGHT; - if (touch->y > tp->scroll.bottom_edge) + if (t->y > tp->scroll.bottom_edge) edge |= EDGE_BOTTOM; return edge; From 9f8edc5fd880e0a9c482b36e6b4120ccc056ee0b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 9 Mar 2015 15:51:12 +1000 Subject: [PATCH 11/33] evdev: add helper function to normalize delta coordinates No functional changes. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 70c60eea..645a36bf 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -224,6 +224,13 @@ evdev_device_transform_y(struct evdev_device *device, return scale_axis(device->abs.absinfo_y, y, height); } +static inline void +normalize_delta(struct evdev_device *device, double *dx, double *dy) +{ + *dx = *dx * (double)device->dpi / DEFAULT_MOUSE_DPI; + *dy = *dy * (double)device->dpi / DEFAULT_MOUSE_DPI; +} + static void evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { @@ -243,10 +250,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: - dx_unaccel = device->rel.dx / ((double) device->dpi / - DEFAULT_MOUSE_DPI); - dy_unaccel = device->rel.dy / ((double) device->dpi / - DEFAULT_MOUSE_DPI); + dx_unaccel = device->rel.dx; + dy_unaccel = device->rel.dy; + normalize_delta(device, &dx_unaccel, &dy_unaccel); device->rel.dx = 0; device->rel.dy = 0; From f5a0a381cb4137d7ff6ecc3cea9d3fb5cb3bcfb6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 08:35:38 +1000 Subject: [PATCH 12/33] evdev: start introducing some type-safety for device/normalized coordinates Make it clear where we're dealing with device coordinates and where we're dealing with DPI-normalized coordinates. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 88 +++++++++++++++++++++--------------------- src/evdev.h | 8 ++-- src/libinput-private.h | 10 +++++ 3 files changed, 57 insertions(+), 49 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 645a36bf..e1a1a971 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -193,12 +193,13 @@ evdev_device_led_update(struct evdev_device *device, enum libinput_led leds) } static void -transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y) +transform_absolute(struct evdev_device *device, + struct device_coords *point) { if (!device->abs.apply_calibration) return; - matrix_mult_vec(&device->abs.calibration, x, y); + matrix_mult_vec(&device->abs.calibration, &point->x, &point->y); } static inline double @@ -225,10 +226,12 @@ evdev_device_transform_y(struct evdev_device *device, } static inline void -normalize_delta(struct evdev_device *device, double *dx, double *dy) +normalize_delta(struct evdev_device *device, + const struct device_coords *delta, + struct normalized_coords *normalized) { - *dx = *dx * (double)device->dpi / DEFAULT_MOUSE_DPI; - *dy = *dy * (double)device->dpi / DEFAULT_MOUSE_DPI; + normalized->x = delta->x * (double)device->dpi / DEFAULT_MOUSE_DPI; + normalized->y = delta->y * (double)device->dpi / DEFAULT_MOUSE_DPI; } static void @@ -236,13 +239,13 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { struct libinput *libinput = device->base.seat->libinput; struct motion_params motion; - double dx_unaccel, dy_unaccel; - int32_t cx, cy; int32_t x, y; int slot; int seat_slot; struct libinput_device *base = &device->base; struct libinput_seat *seat = base->seat; + struct normalized_coords normalized; + struct device_coords point; slot = device->mt.slot; @@ -250,11 +253,9 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: - dx_unaccel = device->rel.dx; - dy_unaccel = device->rel.dy; - normalize_delta(device, &dx_unaccel, &dy_unaccel); - device->rel.dx = 0; - device->rel.dy = 0; + normalize_delta(device, &device->rel, &normalized); + device->rel.x = 0; + device->rel.y = 0; /* Use unaccelerated deltas for pointing stick scroll */ if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && @@ -262,23 +263,23 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) if (device->scroll.button_scroll_active) evdev_post_scroll(device, time, LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, - dx_unaccel, dy_unaccel); + normalized.x, normalized.y); break; } /* Apply pointer acceleration. */ - motion.dx = dx_unaccel; - motion.dy = dy_unaccel; + motion.dx = normalized.x; + motion.dy = normalized.y; filter_dispatch(device->pointer.filter, &motion, device, time); if (motion.dx == 0.0 && motion.dy == 0.0 && - dx_unaccel == 0.0 && dy_unaccel == 0.0) { + normalized.x == 0.0 && normalized.y == 0.0) { break; } pointer_notify_motion(base, time, motion.dx, motion.dy, - dx_unaccel, dy_unaccel); + normalized.x, normalized.x); break; case EVDEV_ABSOLUTE_MT_DOWN: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -299,25 +300,25 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) break; seat->slot_map |= 1 << seat_slot; - x = device->mt.slots[slot].x; - y = device->mt.slots[slot].y; - transform_absolute(device, &x, &y); + point = device->mt.slots[slot].point; + transform_absolute(device, &point); - touch_notify_touch_down(base, time, slot, seat_slot, x, y); + touch_notify_touch_down(base, time, slot, seat_slot, + point.x, point.y); break; case EVDEV_ABSOLUTE_MT_MOTION: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) break; seat_slot = device->mt.slots[slot].seat_slot; - x = device->mt.slots[slot].x; - y = device->mt.slots[slot].y; + point = device->mt.slots[slot].point; if (seat_slot == -1) break; - transform_absolute(device, &x, &y); - touch_notify_touch_motion(base, time, slot, seat_slot, x, y); + transform_absolute(device, &point); + touch_notify_touch_motion(base, time, slot, seat_slot, + point.x, point.y); break; case EVDEV_ABSOLUTE_MT_UP: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -353,18 +354,17 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) seat->slot_map |= 1 << seat_slot; - cx = device->abs.x; - cy = device->abs.y; - transform_absolute(device, &cx, &cy); + point = device->abs.point; + transform_absolute(device, &point); - touch_notify_touch_down(base, time, -1, seat_slot, cx, cy); + touch_notify_touch_down(base, time, -1, seat_slot, + point.x, point.y); break; case EVDEV_ABSOLUTE_MOTION: - cx = device->abs.x; - cy = device->abs.y; - transform_absolute(device, &cx, &cy); - x = cx; - y = cy; + point = device->abs.point; + transform_absolute(device, &point); + x = point.x; + y = point.y; if (device->seat_caps & EVDEV_DEVICE_TOUCH) { seat_slot = device->abs.seat_slot; @@ -553,12 +553,12 @@ evdev_process_touch(struct evdev_device *device, device->pending_event = EVDEV_ABSOLUTE_MT_UP; break; case ABS_MT_POSITION_X: - device->mt.slots[device->mt.slot].x = e->value; + device->mt.slots[device->mt.slot].point.x = e->value; if (device->pending_event == EVDEV_NONE) device->pending_event = EVDEV_ABSOLUTE_MT_MOTION; break; case ABS_MT_POSITION_Y: - device->mt.slots[device->mt.slot].y = e->value; + device->mt.slots[device->mt.slot].point.y = e->value; if (device->pending_event == EVDEV_NONE) device->pending_event = EVDEV_ABSOLUTE_MT_MOTION; break; @@ -571,12 +571,12 @@ evdev_process_absolute_motion(struct evdev_device *device, { switch (e->code) { case ABS_X: - device->abs.x = e->value; + device->abs.point.x = e->value; if (device->pending_event == EVDEV_NONE) device->pending_event = EVDEV_ABSOLUTE_MOTION; break; case ABS_Y: - device->abs.y = e->value; + device->abs.point.y = e->value; if (device->pending_event == EVDEV_NONE) device->pending_event = EVDEV_ABSOLUTE_MOTION; break; @@ -614,13 +614,13 @@ evdev_process_relative(struct evdev_device *device, case REL_X: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); - device->rel.dx += e->value; + device->rel.x += e->value; device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_Y: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); - device->rel.dy += e->value; + device->rel.y += e->value; device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: @@ -1507,8 +1507,8 @@ evdev_configure_device(struct evdev_device *device) for (slot = 0; slot < num_slots; ++slot) { slots[slot].seat_slot = -1; - slots[slot].x = 0; - slots[slot].y = 0; + slots[slot].point.x = 0; + slots[slot].point.y = 0; } device->mt.slots = slots; device->mt.slots_len = num_slots; @@ -1688,8 +1688,8 @@ evdev_device_create(struct libinput_seat *seat, device->is_mt = 0; device->mtdev = NULL; device->udev_device = udev_device_ref(udev_device); - device->rel.dx = 0; - device->rel.dy = 0; + device->rel.x = 0; + device->rel.y = 0; device->abs.seat_slot = -1; device->dispatch = NULL; device->fd = fd; diff --git a/src/evdev.h b/src/evdev.h index 9e8d6af0..a0a7f595 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -62,7 +62,7 @@ enum evdev_device_tags { struct mt_slot { int32_t seat_slot; - int32_t x, y; + struct device_coords point; }; struct evdev_device { @@ -81,7 +81,7 @@ struct evdev_device { const struct input_absinfo *absinfo_x, *absinfo_y; int fake_resolution; - int32_t x, y; + struct device_coords point; int32_t seat_slot; int apply_calibration; @@ -97,9 +97,7 @@ struct evdev_device { } mt; struct mtdev *mtdev; - struct { - int dx, dy; - } rel; + struct device_coords rel; struct { struct libinput_timer timer; diff --git a/src/libinput-private.h b/src/libinput-private.h index dbe15586..c15f7d8b 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -32,6 +32,16 @@ struct libinput_source; +/* A coordinate pair in device coordinates */ +struct device_coords { + int x, y; +}; + +/* A dpi-normalized coordinate pair */ +struct normalized_coords { + double x, y; +}; + struct libinput_interface_backend { int (*resume)(struct libinput *libinput); void (*suspend)(struct libinput *libinput); From dd3a2ea7d9fb1019ce1437e943ae9d39c1e5f4e1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 09:10:13 +1000 Subject: [PATCH 13/33] touchpad: change motion history to typesafe coords Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 2 +- src/evdev-mt-touchpad.h | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 88088503..ebe611ff 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -46,7 +46,7 @@ tp_hysteresis(int in, int center, int margin) return center + diff + margin; } -static inline struct tp_motion * +static inline struct device_coords * tp_motion_history_offset(struct tp_touch *t, int offset) { int offset_index = diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index aa6de69c..ec8c8b1c 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -122,11 +122,6 @@ enum tp_edge_scroll_touch_state { EDGE_SCROLL_TOUCH_STATE_AREA, }; -struct tp_motion { - int32_t x; - int32_t y; -}; - struct tp_touch { struct tp_dispatch *tp; enum touch_state state; @@ -137,7 +132,7 @@ struct tp_touch { uint64_t millis; struct { - struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH]; + struct device_coords samples[TOUCHPAD_HISTORY_LENGTH]; unsigned int index; unsigned int count; } history; From 614dc10fd1ac11fc0c0afcd8b6b5b6c885c9b0d7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 09:24:52 +1000 Subject: [PATCH 14/33] touchpad: switch touch point, hysteresis, initial coords to typesafe coords Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 14 +++---- src/evdev-mt-touchpad-edge-scroll.c | 11 +++-- src/evdev-mt-touchpad-tap.c | 7 ++-- src/evdev-mt-touchpad.c | 62 ++++++++++++++--------------- src/evdev-mt-touchpad.h | 24 ++++------- 5 files changed, 51 insertions(+), 67 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index fc79b0fc..3ca37b70 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -80,14 +80,14 @@ button_event_to_str(enum button_event event) { static inline bool is_inside_bottom_button_area(struct tp_dispatch *tp, struct tp_touch *t) { - return t->y >= tp->buttons.bottom_area.top_edge; + return t->point.y >= tp->buttons.bottom_area.top_edge; } static inline bool is_inside_bottom_right_area(struct tp_dispatch *tp, struct tp_touch *t) { return is_inside_bottom_button_area(tp, t) && - t->x > tp->buttons.bottom_area.rightbutton_left_edge; + t->point.x > tp->buttons.bottom_area.rightbutton_left_edge; } static inline bool @@ -100,29 +100,29 @@ is_inside_bottom_left_area(struct tp_dispatch *tp, struct tp_touch *t) static inline bool is_inside_top_button_area(struct tp_dispatch *tp, struct tp_touch *t) { - return t->y <= tp->buttons.top_area.bottom_edge; + return t->point.y <= tp->buttons.top_area.bottom_edge; } static inline bool is_inside_top_right_area(struct tp_dispatch *tp, struct tp_touch *t) { return is_inside_top_button_area(tp, t) && - t->x > tp->buttons.top_area.rightbutton_left_edge; + t->point.x > tp->buttons.top_area.rightbutton_left_edge; } static inline bool is_inside_top_left_area(struct tp_dispatch *tp, struct tp_touch *t) { return is_inside_top_button_area(tp, t) && - t->x < tp->buttons.top_area.leftbutton_right_edge; + t->point.x < tp->buttons.top_area.leftbutton_right_edge; } static inline bool is_inside_top_middle_area(struct tp_dispatch *tp, struct tp_touch *t) { return is_inside_top_button_area(tp, t) && - t->x >= tp->buttons.top_area.leftbutton_right_edge && - t->x <= tp->buttons.top_area.rightbutton_left_edge; + t->point.x >= tp->buttons.top_area.leftbutton_right_edge && + t->point.x <= tp->buttons.top_area.rightbutton_left_edge; } static void diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index a1839cbf..4504fe7a 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -52,10 +52,10 @@ tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t) if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) return EDGE_NONE; - if (t->x > tp->scroll.right_edge) + if (t->point.x > tp->scroll.right_edge) edge |= EDGE_RIGHT; - if (t->y > tp->scroll.bottom_edge) + if (t->point.y > tp->scroll.bottom_edge) edge |= EDGE_BOTTOM; return edge; @@ -76,8 +76,7 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp, break; case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW: t->scroll.edge = tp_touch_get_edge(tp, t); - t->scroll.initial_x = t->x; - t->scroll.initial_y = t->y; + t->scroll.initial = t->point; libinput_timer_set(&t->scroll.timer, t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT); break; @@ -359,8 +358,8 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) t->scroll.edge_state); break; case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW: - initial_dx = t->x - t->scroll.initial_x; - initial_dy = t->y - t->scroll.initial_y; + initial_dx = t->point.x - t->scroll.initial.x; + initial_dy = t->point.y - t->scroll.initial.y; tp_normalize_delta(tp, &initial_dx, &initial_dy); diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index c0475080..f706abcf 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -533,8 +533,8 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, int threshold = DEFAULT_TAP_MOVE_THRESHOLD; double dx, dy; - dx = abs(t->tap.initial_x - t->x); - dy = abs(t->tap.initial_y - t->y); + dx = abs(t->tap.initial.x - t->point.x); + dy = abs(t->tap.initial.y - t->point.y); tp_normalize_delta(tp, &dx, &dy); return dx * dx + dy * dy > threshold * threshold; @@ -571,8 +571,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) if (t->state == TOUCH_BEGIN) { t->tap.state = TAP_TOUCH_STATE_TOUCH; - t->tap.initial_x = t->x; - t->tap.initial_y = t->y; + t->tap.initial = t->point; tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time); } else if (t->state == TOUCH_END) { tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, time); diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ebe611ff..a3df0980 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -87,8 +87,7 @@ tp_motion_history_push(struct tp_touch *t) if (t->history.count < TOUCHPAD_HISTORY_LENGTH) t->history.count++; - t->history.samples[motion_index].x = t->x; - t->history.samples[motion_index].y = t->y; + t->history.samples[motion_index] = t->point; t->history.index = motion_index; } @@ -96,23 +95,22 @@ static inline void tp_motion_hysteresis(struct tp_dispatch *tp, struct tp_touch *t) { - int x = t->x, - y = t->y; + int x = t->point.x, + y = t->point.y; if (t->history.count == 0) { - t->hysteresis.center_x = t->x; - t->hysteresis.center_y = t->y; + t->hysteresis_center = t->point; } else { x = tp_hysteresis(x, - t->hysteresis.center_x, - tp->hysteresis.margin_x); + t->hysteresis_center.x, + tp->hysteresis_margin.x); y = tp_hysteresis(y, - t->hysteresis.center_y, - tp->hysteresis.margin_y); - t->hysteresis.center_x = x; - t->hysteresis.center_y = y; - t->x = x; - t->y = y; + t->hysteresis_center.y, + tp->hysteresis_margin.y); + t->hysteresis_center.x = x; + t->hysteresis_center.y = y; + t->point.x = x; + t->point.y = y; } } @@ -281,13 +279,13 @@ tp_process_absolute(struct tp_dispatch *tp, switch(e->code) { case ABS_MT_POSITION_X: - t->x = e->value; + t->point.x = e->value; t->millis = time; t->dirty = true; tp->queued |= TOUCHPAD_EVENT_MOTION; break; case ABS_MT_POSITION_Y: - t->y = e->value; + t->point.y = e->value; t->millis = time; t->dirty = true; tp->queued |= TOUCHPAD_EVENT_MOTION; @@ -312,13 +310,13 @@ tp_process_absolute_st(struct tp_dispatch *tp, switch(e->code) { case ABS_X: - t->x = e->value; + t->point.x = e->value; t->millis = time; t->dirty = true; tp->queued |= TOUCHPAD_EVENT_MOTION; break; case ABS_Y: - t->y = e->value; + t->point.y = e->value; t->millis = time; t->dirty = true; tp->queued |= TOUCHPAD_EVENT_MOTION; @@ -418,8 +416,8 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t) if (!t->pinned.is_pinned) return; - xdist = abs(t->x - t->pinned.center_x); - ydist = abs(t->y - t->pinned.center_y); + xdist = abs(t->point.x - t->pinned.center.x); + ydist = abs(t->point.y - t->pinned.center.y); if (xdist * xdist + ydist * ydist >= tp->buttons.motion_dist * tp->buttons.motion_dist) { @@ -428,8 +426,8 @@ tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t) } /* The finger may slowly drift, adjust the center */ - t->pinned.center_x = t->x + t->pinned.center_x / 2; - t->pinned.center_y = t->y + t->pinned.center_y / 2; + t->pinned.center.x = t->point.x + t->pinned.center.x / 2; + t->pinned.center.y = t->point.y + t->pinned.center.y / 2; } static void @@ -439,8 +437,7 @@ tp_pin_fingers(struct tp_dispatch *tp) tp_for_each_touch(tp, t) { t->pinned.is_pinned = true; - t->pinned.center_x = t->x; - t->pinned.center_y = t->y; + t->pinned.center = t->point; } } @@ -466,8 +463,9 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) */ if (t->palm.is_palm) { if (time < t->palm.time + PALM_TIMEOUT && - (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) { - int dirs = vector_get_direction(t->x - t->palm.x, t->y - t->palm.y); + (t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) { + int dirs = vector_get_direction(t->point.x - t->palm.first.x, + t->point.y - t->palm.first.y); if ((dirs & DIRECTIONS) && !(dirs & ~DIRECTIONS)) { t->palm.is_palm = false; } @@ -478,7 +476,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) /* palm must start in exclusion zone, it's ok to move into the zone without being a palm */ if (t->state != TOUCH_BEGIN || - (t->x > tp->palm.left_edge && t->x < tp->palm.right_edge)) + (t->point.x > tp->palm.left_edge && t->point.x < tp->palm.right_edge)) return; /* don't detect palm in software button areas, it's @@ -490,8 +488,7 @@ tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->palm.is_palm = true; t->palm.time = time; - t->palm.x = t->x; - t->palm.y = t->y; + t->palm.first = t->point; } static void @@ -566,8 +563,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) tp_motion_history_reset(t); if (i >= tp->real_touches && t->state != TOUCH_NONE) { - t->x = first->x; - t->y = first->y; + t->point = first->point; if (!t->dirty) t->dirty = first->dirty; } @@ -1155,9 +1151,9 @@ tp_init(struct tp_dispatch *tp, device->abs.absinfo_y->minimum); diagonal = sqrt(width*width + height*height); - tp->hysteresis.margin_x = + tp->hysteresis_margin.x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; - tp->hysteresis.margin_y = + tp->hysteresis_margin.y = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; if (tp_init_accel(tp, diagonal) != 0) diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index ec8c8b1c..e34b2ec3 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -127,8 +127,7 @@ struct tp_touch { enum touch_state state; bool has_ended; /* TRACKING_ID == -1 */ bool dirty; - int32_t x; /* in device coordinates */ - int32_t y; /* in device coordinates */ + struct device_coords point; uint64_t millis; struct { @@ -137,10 +136,7 @@ struct tp_touch { unsigned int count; } history; - struct { - int32_t center_x; /* in device coordinates */ - int32_t center_y; /* in device coordinates */ - } hysteresis; + struct device_coords hysteresis_center; /* A pinned touchpoint is the one that pressed the physical button * on a clickpad. After the release, it won't move until the center @@ -148,8 +144,7 @@ struct tp_touch { */ struct { bool is_pinned; - int32_t center_x; /* in device coordinates */ - int32_t center_y; /* in device coordinates */ + struct device_coords center; } pinned; /* Software-button state and timeout if applicable */ @@ -162,7 +157,7 @@ struct tp_touch { struct { enum tp_tap_touch_state state; - int32_t initial_x, initial_y; /* in device coordinates */ + struct device_coords initial; } tap; struct { @@ -170,14 +165,12 @@ struct tp_touch { uint32_t edge; int direction; struct libinput_timer timer; - int32_t initial_x; /* in device coordinates */ - int32_t initial_y; /* in device coordinates */ + struct device_coords initial; } scroll; struct { bool is_palm; - int32_t x, y; /* first coordinates if is_palm == true, - in device coordinates */ + struct device_coords first; /* first coordinates if is_palm == true */ uint32_t time; /* first timestamp if is_palm == true */ } palm; }; @@ -202,10 +195,7 @@ struct tp_dispatch { */ unsigned int fake_touches; - struct { - int32_t margin_x; /* in device coordiantes */ - int32_t margin_y; /* in device coordiantes */ - } hysteresis; + struct device_coords hysteresis_margin; struct { double x_scale_coeff; From 8101e4377439a5a710c53472652d63d92c2144fe Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 09:58:11 +1000 Subject: [PATCH 15/33] touchpad: switch delta handling to typesafe coordinates Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 26 ++++++------- src/evdev-mt-touchpad-gestures.c | 60 +++++++++++++++-------------- src/evdev-mt-touchpad-tap.c | 6 ++- src/evdev-mt-touchpad.c | 34 ++++++++-------- src/evdev-mt-touchpad.h | 12 +++--- 5 files changed, 73 insertions(+), 65 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 4504fe7a..92973e15 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -311,8 +311,9 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) struct libinput_device *device = &tp->device->base; struct tp_touch *t; enum libinput_pointer_axis axis; - double dx, dy, *delta; + double *delta; double initial_dx, initial_dy, *initial_delta; + struct normalized_coords normalized; if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) return 0; @@ -335,20 +336,21 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) continue; case EDGE_RIGHT: axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; - delta = &dy; + delta = &normalized.y; initial_delta = &initial_dy; break; case EDGE_BOTTOM: axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; - delta = &dx; + delta = &normalized.x; initial_delta = &initial_dx; break; default: /* EDGE_RIGHT | EDGE_BOTTOM */ continue; /* Don't know direction yet, skip */ } - tp_get_delta(t, &dx, &dy); - tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); + normalized = tp_get_delta(t); + tp_filter_motion(tp, &normalized.x, &normalized.y, + NULL, NULL, time); switch (t->scroll.edge_state) { case EDGE_SCROLL_TOUCH_STATE_NONE: @@ -361,14 +363,12 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) initial_dx = t->point.x - t->scroll.initial.x; initial_dy = t->point.y - t->scroll.initial.y; tp_normalize_delta(tp, - &initial_dx, - &initial_dy); + initial_dx, + initial_dy, + &normalized); if (fabs(*initial_delta) < DEFAULT_SCROLL_THRESHOLD) { - dx = 0.0; - dy = 0.0; - } else { - dx = initial_dx; - dy = initial_dy; + normalized.x = 0.0; + normalized.y = 0.0; } break; case EDGE_SCROLL_TOUCH_STATE_EDGE: @@ -381,7 +381,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) pointer_notify_axis(device, time, AS_MASK(axis), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - dx, dy, + normalized.x, normalized.y, 0, 0); t->scroll.direction = axis; diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index c1ed1c26..85b22ff1 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -31,45 +31,45 @@ #define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ -static void -tp_get_touches_delta(struct tp_dispatch *tp, double *dx, double *dy, bool average) +static struct normalized_coords +tp_get_touches_delta(struct tp_dispatch *tp, bool average) { struct tp_touch *t; unsigned int i, nchanged = 0; - double tmpx, tmpy; - - *dx = 0.0; - *dy = 0.0; + struct normalized_coords normalized; + struct normalized_coords delta = {0.0, 0.0}; for (i = 0; i < tp->real_touches; i++) { t = &tp->touches[i]; if (tp_touch_active(tp, t) && t->dirty) { nchanged++; - tp_get_delta(t, &tmpx, &tmpy); + normalized = tp_get_delta(t); - *dx += tmpx; - *dy += tmpy; + delta.x += normalized.x; + delta.y += normalized.y; } } if (!average || nchanged == 0) - return; + return delta; - *dx /= nchanged; - *dy /= nchanged; + delta.x /= nchanged; + delta.y /= nchanged; + + return delta; } -static inline void -tp_get_combined_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +static inline struct normalized_coords +tp_get_combined_touches_delta(struct tp_dispatch *tp) { - tp_get_touches_delta(tp, dx, dy, false); + return tp_get_touches_delta(tp, false); } -static inline void -tp_get_average_touches_delta(struct tp_dispatch *tp, double *dx, double *dy) +static inline struct normalized_coords +tp_get_average_touches_delta(struct tp_dispatch *tp) { - tp_get_touches_delta(tp, dx, dy, true); + return tp_get_touches_delta(tp, true); } static void @@ -89,39 +89,41 @@ tp_gesture_start(struct tp_dispatch *tp, uint64_t time) static void tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) { - double dx = 0.0, dy = 0.0; double dx_unaccel, dy_unaccel; + struct normalized_coords delta; /* When a clickpad is clicked, combine motion of all active touches */ if (tp->buttons.is_clickpad && tp->buttons.state) - tp_get_combined_touches_delta(tp, &dx, &dy); + delta = tp_get_combined_touches_delta(tp); else - tp_get_average_touches_delta(tp, &dx, &dy); + delta = tp_get_average_touches_delta(tp); - tp_filter_motion(tp, &dx, &dy, &dx_unaccel, &dy_unaccel, time); + tp_filter_motion(tp, &delta.x, &delta.y, &dx_unaccel, &dy_unaccel, time); - if (dx != 0.0 || dy != 0.0 || dx_unaccel != 0.0 || dy_unaccel != 0.0) { + if (delta.x != 0.0 || delta.y != 0.0 || + dx_unaccel != 0.0 || dy_unaccel != 0.0) { pointer_notify_motion(&tp->device->base, time, - dx, dy, dx_unaccel, dy_unaccel); + delta.x, delta.y, + dx_unaccel, dy_unaccel); } } static void tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) { - double dx = 0, dy =0; + struct normalized_coords delta; - tp_get_average_touches_delta(tp, &dx, &dy); - tp_filter_motion(tp, &dx, &dy, NULL, NULL, time); + delta = tp_get_average_touches_delta(tp); + tp_filter_motion(tp, &delta.x, &delta.y, NULL, NULL, time); - if (dx == 0.0 && dy == 0.0) + if (delta.x == 0.0 && delta.y == 0.0) return; tp_gesture_start(tp, time); evdev_post_scroll(tp->device, time, LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - dx, dy); + delta.x, delta.y); } void diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index f706abcf..6bd7c582 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -532,12 +532,14 @@ tp_tap_exceeds_motion_threshold(struct tp_dispatch *tp, { int threshold = DEFAULT_TAP_MOVE_THRESHOLD; double dx, dy; + struct normalized_coords normalized; dx = abs(t->tap.initial.x - t->point.x); dy = abs(t->tap.initial.y - t->point.y); - tp_normalize_delta(tp, &dx, &dy); + tp_normalize_delta(tp, dx, dy, &normalized); - return dx * dx + dy * dy > threshold * threshold; + return normalized.x * normalized.x + normalized.y * normalized.y + > threshold * threshold; } static bool diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a3df0980..a9322876 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -250,24 +250,26 @@ tp_estimate_delta(int x0, int x1, int x2, int x3) return (x0 + x1 - x2 - x3) / 4.0; } -void -tp_get_delta(struct tp_touch *t, double *dx, double *dy) +struct normalized_coords +tp_get_delta(struct tp_touch *t) { - if (t->history.count < TOUCHPAD_MIN_SAMPLES) { - *dx = 0; - *dy = 0; - return; - } + double dx, dy; /* in device coords */ + struct normalized_coords normalized = { 0.0, 0.0 }; - *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x, - tp_motion_history_offset(t, 1)->x, - tp_motion_history_offset(t, 2)->x, - tp_motion_history_offset(t, 3)->x); - *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y, - tp_motion_history_offset(t, 1)->y, - tp_motion_history_offset(t, 2)->y, - tp_motion_history_offset(t, 3)->y); - tp_normalize_delta(t->tp, dx, dy); + if (t->history.count < TOUCHPAD_MIN_SAMPLES) + return normalized; + + dx = tp_estimate_delta(tp_motion_history_offset(t, 0)->x, + tp_motion_history_offset(t, 1)->x, + tp_motion_history_offset(t, 2)->x, + tp_motion_history_offset(t, 3)->x); + dy = tp_estimate_delta(tp_motion_history_offset(t, 0)->y, + tp_motion_history_offset(t, 1)->y, + tp_motion_history_offset(t, 2)->y, + tp_motion_history_offset(t, 3)->y); + tp_normalize_delta(t->tp, dx, dy, &normalized); + + return normalized; } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index e34b2ec3..04acf214 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -277,14 +277,16 @@ struct tp_dispatch { for (unsigned int _i = 0; _i < (_tp)->ntouches && (_t = &(_tp)->touches[_i]); _i++) static inline void -tp_normalize_delta(struct tp_dispatch *tp, double *dx, double *dy) +tp_normalize_delta(struct tp_dispatch *tp, + double dx, double dy, + struct normalized_coords *normalized) { - *dx = *dx * tp->accel.x_scale_coeff; - *dy = *dy * tp->accel.y_scale_coeff; + normalized->x = dx * tp->accel.x_scale_coeff; + normalized->y = dy * tp->accel.y_scale_coeff; } -void -tp_get_delta(struct tp_touch *t, double *dx, double *dy); +struct normalized_coords +tp_get_delta(struct tp_touch *t); void tp_filter_motion(struct tp_dispatch *tp, From 47d7989682cd30a7633bd2365670baba3d07c72b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 10:36:44 +1000 Subject: [PATCH 16/33] Use typesafe coordinates for scrolling events Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 8 +-- src/evdev-mt-touchpad-gestures.c | 2 +- src/evdev.c | 81 ++++++++++++++++------------- src/evdev.h | 6 +-- src/libinput-private.h | 3 +- src/libinput.c | 6 +-- 6 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 92973e15..d33f4fd9 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -314,6 +314,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) double *delta; double initial_dx, initial_dy, *initial_delta; struct normalized_coords normalized; + const struct normalized_coords zero = { 0.0, 0.0 }; if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) return 0; @@ -329,7 +330,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) pointer_notify_axis(device, time, AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - 0.0, 0.0, + &zero, 0, 0); t->scroll.direction = -1; } @@ -381,7 +382,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) pointer_notify_axis(device, time, AS_MASK(axis), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - normalized.x, normalized.y, + &normalized, 0, 0); t->scroll.direction = axis; @@ -396,13 +397,14 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) { struct libinput_device *device = &tp->device->base; struct tp_touch *t; + const struct normalized_coords zero = { 0.0, 0.0 }; tp_for_each_touch(tp, t) { if (t->scroll.direction != -1) { pointer_notify_axis(device, time, AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - 0.0, 0.0, + &zero, 0.0, 0.0); t->scroll.direction = -1; } diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 85b22ff1..14567312 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -123,7 +123,7 @@ tp_gesture_post_twofinger_scroll(struct tp_dispatch *tp, uint64_t time) evdev_post_scroll(tp->device, time, LIBINPUT_POINTER_AXIS_SOURCE_FINGER, - delta.x, delta.y); + &delta); } void diff --git a/src/evdev.c b/src/evdev.c index e1a1a971..0a2f1f8f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -244,7 +244,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) int seat_slot; struct libinput_device *base = &device->base; struct libinput_seat *seat = base->seat; - struct normalized_coords normalized; + struct normalized_coords accel, unaccel; struct device_coords point; slot = device->mt.slot; @@ -253,7 +253,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: - normalize_delta(device, &device->rel, &normalized); + normalize_delta(device, &device->rel, &unaccel); device->rel.x = 0; device->rel.y = 0; @@ -263,23 +263,25 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) if (device->scroll.button_scroll_active) evdev_post_scroll(device, time, LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS, - normalized.x, normalized.y); + &unaccel); break; } /* Apply pointer acceleration. */ - motion.dx = normalized.x; - motion.dy = normalized.y; + motion.dx = unaccel.x; + motion.dy = unaccel.y; filter_dispatch(device->pointer.filter, &motion, device, time); + accel.x = motion.dx; + accel.y = motion.dy; - if (motion.dx == 0.0 && motion.dy == 0.0 && - normalized.x == 0.0 && normalized.y == 0.0) { + if (accel.x == 0.0 && accel.y == 0.0 && + unaccel.x == 0.0 && unaccel.y == 0.0) { break; } pointer_notify_motion(base, time, - motion.dx, motion.dy, - normalized.x, normalized.x); + accel.x, accel.y, + unaccel.x, unaccel.x); break; case EVDEV_ABSOLUTE_MT_DOWN: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -588,12 +590,14 @@ evdev_notify_axis(struct evdev_device *device, uint64_t time, uint32_t axes, enum libinput_pointer_axis_source source, - double x, double y, + const struct normalized_coords *delta_in, double x_discrete, double y_discrete) { + struct normalized_coords delta = *delta_in; + if (device->scroll.natural_scrolling_enabled) { - x *= -1; - y *= -1; + delta.x *= -1; + delta.y *= -1; x_discrete *= -1; y_discrete *= -1; } @@ -602,7 +606,7 @@ evdev_notify_axis(struct evdev_device *device, time, axes, source, - x, y, + &delta, x_discrete, y_discrete); } @@ -610,6 +614,8 @@ static inline void evdev_process_relative(struct evdev_device *device, struct input_event *e, uint64_t time) { + struct normalized_coords wheel_degrees = { 0.0, 0.0 }; + switch (e->code) { case REL_X: if (device->pending_event != EVDEV_RELATIVE_MOTION) @@ -625,25 +631,26 @@ evdev_process_relative(struct evdev_device *device, break; case REL_WHEEL: evdev_flush_pending_event(device, time); + wheel_degrees.y = -1 * e->value * + device->scroll.wheel_click_angle; evdev_notify_axis( device, time, AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, - 0.0, - -1 * e->value * device->scroll.wheel_click_angle, + &wheel_degrees, 0.0, -1 * e->value); break; case REL_HWHEEL: evdev_flush_pending_event(device, time); + wheel_degrees.x = e->value * device->scroll.wheel_click_angle; evdev_notify_axis( device, time, AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, - e->value * device->scroll.wheel_click_angle, - 0.0, + &wheel_degrees, e->value, 0.0); break; @@ -1922,20 +1929,19 @@ void evdev_post_scroll(struct evdev_device *device, uint64_t time, enum libinput_pointer_axis_source source, - double dx, - double dy) + const struct normalized_coords *delta) { - double trigger_horiz, trigger_vert; + const struct normalized_coords *trigger; + struct normalized_coords event; if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - device->scroll.buildup_vertical += dy; + device->scroll.buildup.y += delta->y; if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - device->scroll.buildup_horizontal += dx; + device->scroll.buildup.x += delta->x; - trigger_vert = device->scroll.buildup_vertical; - trigger_horiz = device->scroll.buildup_horizontal; + trigger = &device->scroll.buildup; /* If we're not scrolling yet, use a distance trigger: moving past a certain distance starts scrolling */ @@ -1943,42 +1949,45 @@ evdev_post_scroll(struct evdev_device *device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) && !evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - if (fabs(trigger_vert) >= device->scroll.threshold) + if (fabs(trigger->y) >= device->scroll.threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - if (fabs(trigger_horiz) >= device->scroll.threshold) + if (fabs(trigger->x) >= device->scroll.threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); /* We're already scrolling in one direction. Require some trigger speed to start scrolling in the other direction */ } else if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) { - if (fabs(dy) >= device->scroll.threshold) + if (fabs(delta->y) >= device->scroll.threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); } else if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) { - if (fabs(dx) >= device->scroll.threshold) + if (fabs(delta->x) >= device->scroll.threshold) evdev_start_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); } + event = *delta; + /* We use the trigger to enable, but the delta from this event for * the actual scroll movement. Otherwise we get a jump once * scrolling engages */ if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) - dy = 0.0; + event.y = 0.0; + if (!evdev_is_scrolling(device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) - dx = 0.0; + event.x = 0.0; - if (dx != 0.0 || dy != 0.0) + if (event.x != 0.0 || event.y != 0.0) evdev_notify_axis(device, time, device->scroll.direction, source, - dx, dy, + &event, 0.0, 0.0); } @@ -1987,17 +1996,19 @@ evdev_stop_scroll(struct evdev_device *device, uint64_t time, enum libinput_pointer_axis_source source) { + const struct normalized_coords zero = { 0.0, 0.0 }; + /* terminate scrolling with a zero scroll event */ if (device->scroll.direction != 0) pointer_notify_axis(&device->base, time, device->scroll.direction, source, - 0.0, 0.0, + &zero, 0.0, 0.0); - device->scroll.buildup_horizontal = 0; - device->scroll.buildup_vertical = 0; + device->scroll.buildup.x = 0; + device->scroll.buildup.y = 0; device->scroll.direction = 0; } diff --git a/src/evdev.h b/src/evdev.h index a0a7f595..caafd53a 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -114,8 +114,7 @@ struct evdev_device { bool button_scroll_active; double threshold; uint32_t direction; - double buildup_vertical; - double buildup_horizontal; + struct normalized_coords buildup; struct libinput_device_config_natural_scroll config_natural; /* set during device init if we want natural scrolling, @@ -304,8 +303,7 @@ void evdev_post_scroll(struct evdev_device *device, uint64_t time, enum libinput_pointer_axis_source source, - double dx, - double dy); + const struct normalized_coords *delta); void evdev_stop_scroll(struct evdev_device *device, diff --git a/src/libinput-private.h b/src/libinput-private.h index c15f7d8b..d5fb6965 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -312,8 +312,7 @@ pointer_notify_axis(struct libinput_device *device, uint64_t time, uint32_t axes, enum libinput_pointer_axis_source source, - double x, - double y, + const struct normalized_coords *delta, double x_discrete, double y_discrete); diff --git a/src/libinput.c b/src/libinput.c index 12317833..55b654df 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1179,7 +1179,7 @@ pointer_notify_axis(struct libinput_device *device, uint64_t time, uint32_t axes, enum libinput_pointer_axis_source source, - double x, double y, + const struct normalized_coords *delta, double x_discrete, double y_discrete) { struct libinput_event_pointer *axis_event; @@ -1190,8 +1190,8 @@ pointer_notify_axis(struct libinput_device *device, *axis_event = (struct libinput_event_pointer) { .time = time, - .x = x, - .y = y, + .x = delta->x, + .y = delta->y, .source = source, .axes = axes, .x_discrete = x_discrete, From 2d54b550b775352f230e24b4a86bd2c7f23d18b0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 10:43:18 +1000 Subject: [PATCH 17/33] Use typesafe coords in motion events Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 10 ++++------ src/evdev.c | 6 ++---- src/libinput-private.h | 9 +++------ src/libinput.c | 21 +++++++++------------ 4 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 14567312..f852ff5a 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -89,8 +89,7 @@ tp_gesture_start(struct tp_dispatch *tp, uint64_t time) static void tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) { - double dx_unaccel, dy_unaccel; - struct normalized_coords delta; + struct normalized_coords delta, unaccel; /* When a clickpad is clicked, combine motion of all active touches */ if (tp->buttons.is_clickpad && tp->buttons.state) @@ -98,13 +97,12 @@ tp_gesture_post_pointer_motion(struct tp_dispatch *tp, uint64_t time) else delta = tp_get_average_touches_delta(tp); - tp_filter_motion(tp, &delta.x, &delta.y, &dx_unaccel, &dy_unaccel, time); + tp_filter_motion(tp, &delta.x, &delta.y, &unaccel.x, &unaccel.y, time); if (delta.x != 0.0 || delta.y != 0.0 || - dx_unaccel != 0.0 || dy_unaccel != 0.0) { + unaccel.x != 0.0 || unaccel.y != 0.0) { pointer_notify_motion(&tp->device->base, time, - delta.x, delta.y, - dx_unaccel, dy_unaccel); + &delta, &unaccel); } } diff --git a/src/evdev.c b/src/evdev.c index 0a2f1f8f..d1b0504a 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -279,9 +279,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) break; } - pointer_notify_motion(base, time, - accel.x, accel.y, - unaccel.x, unaccel.x); + pointer_notify_motion(base, time, &accel, &unaccel); break; case EVDEV_ABSOLUTE_MT_DOWN: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -376,7 +374,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) touch_notify_touch_motion(base, time, -1, seat_slot, x, y); } else if (device->seat_caps & EVDEV_DEVICE_POINTER) { - pointer_notify_motion_absolute(base, time, x, y); + pointer_notify_motion_absolute(base, time, &point); } break; case EVDEV_ABSOLUTE_TOUCH_UP: diff --git a/src/libinput-private.h b/src/libinput-private.h index d5fb6965..a7e0b075 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -290,16 +290,13 @@ keyboard_notify_key(struct libinput_device *device, void pointer_notify_motion(struct libinput_device *device, uint64_t time, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel); + const struct normalized_coords *delta, + const struct normalized_coords *unaccel); void pointer_notify_motion_absolute(struct libinput_device *device, uint64_t time, - double x, - double y); + const struct device_coords *point); void pointer_notify_button(struct libinput_device *device, diff --git a/src/libinput.c b/src/libinput.c index 55b654df..a7956d60 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1098,10 +1098,8 @@ keyboard_notify_key(struct libinput_device *device, void pointer_notify_motion(struct libinput_device *device, uint64_t time, - double dx, - double dy, - double dx_unaccel, - double dy_unaccel) + const struct normalized_coords *delta, + const struct normalized_coords *unaccel) { struct libinput_event_pointer *motion_event; @@ -1111,10 +1109,10 @@ pointer_notify_motion(struct libinput_device *device, *motion_event = (struct libinput_event_pointer) { .time = time, - .x = dx, - .y = dy, - .dx_unaccel = dx_unaccel, - .dy_unaccel = dy_unaccel, + .x = delta->x, + .y = delta->y, + .dx_unaccel = unaccel->x, + .dy_unaccel = unaccel->y, }; post_device_event(device, time, @@ -1125,8 +1123,7 @@ pointer_notify_motion(struct libinput_device *device, void pointer_notify_motion_absolute(struct libinput_device *device, uint64_t time, - double x, - double y) + const struct device_coords *point) { struct libinput_event_pointer *motion_absolute_event; @@ -1136,8 +1133,8 @@ pointer_notify_motion_absolute(struct libinput_device *device, *motion_absolute_event = (struct libinput_event_pointer) { .time = time, - .x = x, - .y = y, + .x = point->x, + .y = point->y, }; post_device_event(device, time, From a3c8d7262589f2b3b3824e62be95c9e202639977 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 10:48:54 +1000 Subject: [PATCH 18/33] Use typesafe coordinates in touch events Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 13 +++++-------- src/libinput-private.h | 6 ++---- src/libinput.c | 23 +++++++++-------------- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index d1b0504a..cab7e856 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -239,7 +239,6 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { struct libinput *libinput = device->base.seat->libinput; struct motion_params motion; - int32_t x, y; int slot; int seat_slot; struct libinput_device *base = &device->base; @@ -304,7 +303,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) transform_absolute(device, &point); touch_notify_touch_down(base, time, slot, seat_slot, - point.x, point.y); + &point); break; case EVDEV_ABSOLUTE_MT_MOTION: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -318,7 +317,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) transform_absolute(device, &point); touch_notify_touch_motion(base, time, slot, seat_slot, - point.x, point.y); + &point); break; case EVDEV_ABSOLUTE_MT_UP: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) @@ -357,14 +356,11 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) point = device->abs.point; transform_absolute(device, &point); - touch_notify_touch_down(base, time, -1, seat_slot, - point.x, point.y); + touch_notify_touch_down(base, time, -1, seat_slot, &point); break; case EVDEV_ABSOLUTE_MOTION: point = device->abs.point; transform_absolute(device, &point); - x = point.x; - y = point.y; if (device->seat_caps & EVDEV_DEVICE_TOUCH) { seat_slot = device->abs.seat_slot; @@ -372,7 +368,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint64_t time) if (seat_slot == -1) break; - touch_notify_touch_motion(base, time, -1, seat_slot, x, y); + touch_notify_touch_motion(base, time, -1, seat_slot, + &point); } else if (device->seat_caps & EVDEV_DEVICE_POINTER) { pointer_notify_motion_absolute(base, time, &point); } diff --git a/src/libinput-private.h b/src/libinput-private.h index a7e0b075..91bfc379 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -318,16 +318,14 @@ touch_notify_touch_down(struct libinput_device *device, uint64_t time, int32_t slot, int32_t seat_slot, - double x, - double y); + const struct device_coords *point); void touch_notify_touch_motion(struct libinput_device *device, uint64_t time, int32_t slot, int32_t seat_slot, - double x, - double y); + const struct device_coords *point); void touch_notify_touch_up(struct libinput_device *device, diff --git a/src/libinput.c b/src/libinput.c index a7956d60..6dac12ba 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -111,8 +111,7 @@ struct libinput_event_touch { uint32_t time; int32_t slot; int32_t seat_slot; - double x; - double y; + struct device_coords point; }; static void @@ -588,7 +587,7 @@ libinput_event_touch_get_x(struct libinput_event_touch *event) LIBINPUT_EVENT_TOUCH_DOWN, LIBINPUT_EVENT_TOUCH_MOTION); - return evdev_convert_to_mm(device->abs.absinfo_x, event->x); + return evdev_convert_to_mm(device->abs.absinfo_x, event->point.x); } LIBINPUT_EXPORT double @@ -604,7 +603,7 @@ libinput_event_touch_get_x_transformed(struct libinput_event_touch *event, LIBINPUT_EVENT_TOUCH_DOWN, LIBINPUT_EVENT_TOUCH_MOTION); - return evdev_device_transform_x(device, event->x, width); + return evdev_device_transform_x(device, event->point.x, width); } LIBINPUT_EXPORT double @@ -620,7 +619,7 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, LIBINPUT_EVENT_TOUCH_DOWN, LIBINPUT_EVENT_TOUCH_MOTION); - return evdev_device_transform_y(device, event->y, height); + return evdev_device_transform_y(device, event->point.y, height); } LIBINPUT_EXPORT double @@ -635,7 +634,7 @@ libinput_event_touch_get_y(struct libinput_event_touch *event) LIBINPUT_EVENT_TOUCH_DOWN, LIBINPUT_EVENT_TOUCH_MOTION); - return evdev_convert_to_mm(device->abs.absinfo_y, event->y); + return evdev_convert_to_mm(device->abs.absinfo_y, event->point.y); } struct libinput_source * @@ -1205,8 +1204,7 @@ touch_notify_touch_down(struct libinput_device *device, uint64_t time, int32_t slot, int32_t seat_slot, - double x, - double y) + const struct device_coords *point) { struct libinput_event_touch *touch_event; @@ -1218,8 +1216,7 @@ touch_notify_touch_down(struct libinput_device *device, .time = time, .slot = slot, .seat_slot = seat_slot, - .x = x, - .y = y, + .point = *point, }; post_device_event(device, time, @@ -1232,8 +1229,7 @@ touch_notify_touch_motion(struct libinput_device *device, uint64_t time, int32_t slot, int32_t seat_slot, - double x, - double y) + const struct device_coords *point) { struct libinput_event_touch *touch_event; @@ -1245,8 +1241,7 @@ touch_notify_touch_motion(struct libinput_device *device, .time = time, .slot = slot, .seat_slot = seat_slot, - .x = x, - .y = y, + .point = *point, }; post_device_event(device, time, From 1b70842f9e277525f3aca12b9f8b535502312e5b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 11:19:24 +1000 Subject: [PATCH 19/33] Split deltas/absolute coords in pointer events to separate fields Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 6dac12ba..21a3777e 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -93,8 +93,8 @@ struct libinput_event_keyboard { struct libinput_event_pointer { struct libinput_event base; uint32_t time; - double x; - double y; + struct normalized_coords delta; + struct device_coords absolute; double x_discrete; double y_discrete; double dx_unaccel; @@ -316,7 +316,7 @@ libinput_event_pointer_get_dx(struct libinput_event_pointer *event) 0, LIBINPUT_EVENT_POINTER_MOTION); - return event->x; + return event->delta.x; } LIBINPUT_EXPORT double @@ -327,7 +327,7 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event) 0, LIBINPUT_EVENT_POINTER_MOTION); - return event->y; + return event->delta.y; } LIBINPUT_EXPORT double @@ -365,7 +365,7 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) 0, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); - return evdev_convert_to_mm(device->abs.absinfo_x, event->x); + return evdev_convert_to_mm(device->abs.absinfo_x, event->absolute.x); } LIBINPUT_EXPORT double @@ -379,7 +379,7 @@ libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) 0, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); - return evdev_convert_to_mm(device->abs.absinfo_y, event->y); + return evdev_convert_to_mm(device->abs.absinfo_y, event->absolute.y); } LIBINPUT_EXPORT double @@ -395,7 +395,7 @@ libinput_event_pointer_get_absolute_x_transformed( 0, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); - return evdev_device_transform_x(device, event->x, width); + return evdev_device_transform_x(device, event->absolute.x, width); } LIBINPUT_EXPORT double @@ -411,7 +411,7 @@ libinput_event_pointer_get_absolute_y_transformed( 0, LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE); - return evdev_device_transform_y(device, event->y, height); + return evdev_device_transform_y(device, event->absolute.y, height); } LIBINPUT_EXPORT uint32_t @@ -483,10 +483,10 @@ libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event, } else { switch (axis) { case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: - value = event->x; + value = event->delta.x; break; case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: - value = event->y; + value = event->delta.y; break; } } @@ -1108,8 +1108,7 @@ pointer_notify_motion(struct libinput_device *device, *motion_event = (struct libinput_event_pointer) { .time = time, - .x = delta->x, - .y = delta->y, + .delta = *delta, .dx_unaccel = unaccel->x, .dy_unaccel = unaccel->y, }; @@ -1132,8 +1131,7 @@ pointer_notify_motion_absolute(struct libinput_device *device, *motion_absolute_event = (struct libinput_event_pointer) { .time = time, - .x = point->x, - .y = point->y, + .absolute = *point, }; post_device_event(device, time, @@ -1186,8 +1184,7 @@ pointer_notify_axis(struct libinput_device *device, *axis_event = (struct libinput_event_pointer) { .time = time, - .x = delta->x, - .y = delta->y, + .delta = *delta, .source = source, .axes = axes, .x_discrete = x_discrete, From 1df0208f4f6d62927be7cf119854b412a8b7a95b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 11:30:02 +1000 Subject: [PATCH 20/33] Add another data type for discrete coordinates Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-edge-scroll.c | 8 +++++--- src/evdev.c | 27 ++++++++++++++++----------- src/libinput-private.h | 8 ++++++-- src/libinput.c | 12 +++++------- 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index d33f4fd9..6e248196 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -315,6 +315,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) double initial_dx, initial_dy, *initial_delta; struct normalized_coords normalized; const struct normalized_coords zero = { 0.0, 0.0 }; + const struct discrete_coords zero_discrete = { 0.0, 0.0 }; if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE) return 0; @@ -331,7 +332,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, &zero, - 0, 0); + &zero_discrete); t->scroll.direction = -1; } continue; @@ -383,7 +384,7 @@ tp_edge_scroll_post_events(struct tp_dispatch *tp, uint64_t time) AS_MASK(axis), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, &normalized, - 0, 0); + &zero_discrete); t->scroll.direction = axis; tp_edge_scroll_handle_event(tp, t, SCROLL_EVENT_POSTED); @@ -398,6 +399,7 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) struct libinput_device *device = &tp->device->base; struct tp_touch *t; const struct normalized_coords zero = { 0.0, 0.0 }; + const struct discrete_coords zero_discrete = { 0.0, 0.0 }; tp_for_each_touch(tp, t) { if (t->scroll.direction != -1) { @@ -405,7 +407,7 @@ tp_edge_scroll_stop_events(struct tp_dispatch *tp, uint64_t time) AS_MASK(t->scroll.direction), LIBINPUT_POINTER_AXIS_SOURCE_FINGER, &zero, - 0.0, 0.0); + &zero_discrete); t->scroll.direction = -1; } } diff --git a/src/evdev.c b/src/evdev.c index cab7e856..c661af99 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -586,15 +586,16 @@ evdev_notify_axis(struct evdev_device *device, uint32_t axes, enum libinput_pointer_axis_source source, const struct normalized_coords *delta_in, - double x_discrete, double y_discrete) + const struct discrete_coords *discrete_in) { struct normalized_coords delta = *delta_in; + struct discrete_coords discrete = *discrete_in; if (device->scroll.natural_scrolling_enabled) { delta.x *= -1; delta.y *= -1; - x_discrete *= -1; - y_discrete *= -1; + discrete.x *= -1; + discrete.y *= -1; } pointer_notify_axis(&device->base, @@ -602,7 +603,7 @@ evdev_notify_axis(struct evdev_device *device, axes, source, &delta, - x_discrete, y_discrete); + &discrete); } static inline void @@ -610,6 +611,7 @@ evdev_process_relative(struct evdev_device *device, struct input_event *e, uint64_t time) { struct normalized_coords wheel_degrees = { 0.0, 0.0 }; + struct discrete_coords discrete = { 0.0, 0.0 }; switch (e->code) { case REL_X: @@ -628,26 +630,26 @@ evdev_process_relative(struct evdev_device *device, evdev_flush_pending_event(device, time); wheel_degrees.y = -1 * e->value * device->scroll.wheel_click_angle; + discrete.y = -1 * e->value; evdev_notify_axis( device, time, AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, &wheel_degrees, - 0.0, - -1 * e->value); + &discrete); break; case REL_HWHEEL: evdev_flush_pending_event(device, time); wheel_degrees.x = e->value * device->scroll.wheel_click_angle; + discrete.x = e->value; evdev_notify_axis( device, time, AS_MASK(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL), LIBINPUT_POINTER_AXIS_SOURCE_WHEEL, &wheel_degrees, - e->value, - 0.0); + &discrete); break; } } @@ -1977,13 +1979,15 @@ evdev_post_scroll(struct evdev_device *device, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) event.x = 0.0; - if (event.x != 0.0 || event.y != 0.0) + if (event.x != 0.0 || event.y != 0.0) { + const struct discrete_coords zero_discrete = { 0.0, 0.0 }; evdev_notify_axis(device, time, device->scroll.direction, source, &event, - 0.0, 0.0); + &zero_discrete); + } } void @@ -1992,6 +1996,7 @@ evdev_stop_scroll(struct evdev_device *device, enum libinput_pointer_axis_source source) { const struct normalized_coords zero = { 0.0, 0.0 }; + const struct discrete_coords zero_discrete = { 0.0, 0.0 }; /* terminate scrolling with a zero scroll event */ if (device->scroll.direction != 0) @@ -2000,7 +2005,7 @@ evdev_stop_scroll(struct evdev_device *device, device->scroll.direction, source, &zero, - 0.0, 0.0); + &zero_discrete); device->scroll.buildup.x = 0; device->scroll.buildup.y = 0; diff --git a/src/libinput-private.h b/src/libinput-private.h index 91bfc379..e39ac5ea 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -42,6 +42,11 @@ struct normalized_coords { double x, y; }; +/* A discrete step pair (mouse wheels) */ +struct discrete_coords { + int x, y; +}; + struct libinput_interface_backend { int (*resume)(struct libinput *libinput); void (*suspend)(struct libinput *libinput); @@ -310,8 +315,7 @@ pointer_notify_axis(struct libinput_device *device, uint32_t axes, enum libinput_pointer_axis_source source, const struct normalized_coords *delta, - double x_discrete, - double y_discrete); + const struct discrete_coords *discrete); void touch_notify_touch_down(struct libinput_device *device, diff --git a/src/libinput.c b/src/libinput.c index 21a3777e..58881c95 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -95,8 +95,7 @@ struct libinput_event_pointer { uint32_t time; struct normalized_coords delta; struct device_coords absolute; - double x_discrete; - double y_discrete; + struct discrete_coords discrete; double dx_unaccel; double dy_unaccel; uint32_t button; @@ -511,10 +510,10 @@ libinput_event_pointer_get_axis_value_discrete(struct libinput_event_pointer *ev } else { switch (axis) { case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL: - value = event->x_discrete; + value = event->discrete.x; break; case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: - value = event->y_discrete; + value = event->discrete.y; break; } } @@ -1174,7 +1173,7 @@ pointer_notify_axis(struct libinput_device *device, uint32_t axes, enum libinput_pointer_axis_source source, const struct normalized_coords *delta, - double x_discrete, double y_discrete) + const struct discrete_coords *discrete) { struct libinput_event_pointer *axis_event; @@ -1187,8 +1186,7 @@ pointer_notify_axis(struct libinput_device *device, .delta = *delta, .source = source, .axes = axes, - .x_discrete = x_discrete, - .y_discrete = y_discrete, + .discrete = *discrete, }; post_device_event(device, time, From b2b5913a3598d0b7842e69f9f10d00e3e2e2915b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 11 Mar 2015 11:31:13 +1000 Subject: [PATCH 21/33] Store unaccelerated delta as normalized_coords Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/libinput.c b/src/libinput.c index 58881c95..80144571 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -94,10 +94,9 @@ struct libinput_event_pointer { struct libinput_event base; uint32_t time; struct normalized_coords delta; + struct normalized_coords delta_unaccel; struct device_coords absolute; struct discrete_coords discrete; - double dx_unaccel; - double dy_unaccel; uint32_t button; uint32_t seat_button_count; enum libinput_button_state state; @@ -338,7 +337,7 @@ libinput_event_pointer_get_dx_unaccelerated( 0, LIBINPUT_EVENT_POINTER_MOTION); - return event->dx_unaccel; + return event->delta_unaccel.x; } LIBINPUT_EXPORT double @@ -350,7 +349,7 @@ libinput_event_pointer_get_dy_unaccelerated( 0, LIBINPUT_EVENT_POINTER_MOTION); - return event->dy_unaccel; + return event->delta_unaccel.y; } LIBINPUT_EXPORT double @@ -1108,8 +1107,7 @@ pointer_notify_motion(struct libinput_device *device, *motion_event = (struct libinput_event_pointer) { .time = time, .delta = *delta, - .dx_unaccel = unaccel->x, - .dy_unaccel = unaccel->y, + .delta_unaccel = *unaccel, }; post_device_event(device, time, From a3a81d1dee78b699166ed1d947c9e3a0586b3613 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 16 Mar 2015 13:40:03 +1000 Subject: [PATCH 22/33] touchpad: add missing break in default: switch case Unneeded, but better for symmetry. Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad-edge-scroll.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 6e248196..26d6bbcf 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -255,6 +255,7 @@ tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device) */ edge_width = width * .04; edge_height = height * .054; + break; } tp->scroll.right_edge = device->abs.absinfo_x->maximum - edge_width; From 1884ee186e10e2c23b210b1f66e4bc1d262d74be Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 16 Mar 2015 13:49:52 +1000 Subject: [PATCH 23/33] touchpad: simplify resolution check The struct evdev_device's absinfo_x/y point to the right axis Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index a9322876..d0311a4c 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -961,17 +961,8 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) { int res_x, res_y; - if (tp->has_mt) { - res_x = libevdev_get_abs_resolution(tp->device->evdev, - ABS_MT_POSITION_X); - res_y = libevdev_get_abs_resolution(tp->device->evdev, - ABS_MT_POSITION_Y); - } else { - res_x = libevdev_get_abs_resolution(tp->device->evdev, - ABS_X); - res_y = libevdev_get_abs_resolution(tp->device->evdev, - ABS_Y); - } + res_x = tp->device->abs.absinfo_x->resolution; + res_y = tp->device->abs.absinfo_y->resolution; /* * Not all touchpads report the same amount of units/mm (resolution). From 9761db67201d12b93fb6e83f3eddebbd15041426 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 10:35:31 +1000 Subject: [PATCH 24/33] touchpad: check for the fake_resolution boolean instead of a res value Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 3ca37b70..18c32fda 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -513,7 +513,7 @@ tp_init_softbuttons(struct tp_dispatch *tp, /* button height: 10mm or 15% of the touchpad height, whichever is smaller */ - if (yres > 1 && (height * 0.15/yres) > 10) { + if (!device->abs.fake_resolution && (height * 0.15/yres) > 10) { tp->buttons.bottom_area.top_edge = absinfo_y->maximum - 10 * yres; } else { @@ -550,7 +550,7 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, double topsize_mm = 10 * topbutton_size_mult; double topsize_pct = .15 * topbutton_size_mult; - if (yres > 1) { + if (!device->abs.fake_resolution) { tp->buttons.top_area.bottom_edge = yoffset + topsize_mm * yres; } else { From dc1d9461701d409a6b81526c81d3a2fb8f567527 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 12:31:37 +1000 Subject: [PATCH 25/33] evdev: fix android MT devices These devices don't provide ABS_X/Y, but do have proper multitouch. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index c661af99..ea63356d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1396,6 +1396,25 @@ evdev_device_get_udev_tags(struct evdev_device *device, return tags; } +static inline void +evdev_fix_android_mt(struct evdev_device *device) +{ + struct libevdev *evdev = device->evdev; + + if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) || + libevdev_has_event_code(evdev, EV_ABS, ABS_Y)) + return; + + if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) || + !libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) + return; + + libevdev_set_abs_info(evdev, ABS_X, + libevdev_get_abs_info(evdev, ABS_MT_POSITION_X)); + libevdev_set_abs_info(evdev, ABS_Y, + libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y)); +} + static int evdev_configure_device(struct evdev_device *device) { @@ -1449,6 +1468,7 @@ evdev_configure_device(struct evdev_device *device) } if (libevdev_has_event_type(evdev, EV_ABS)) { + evdev_fix_android_mt(device); if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { if (evdev_fix_abs_resolution(evdev, From edd534807dfa34e5531a048dd81b5301e0aa2383 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 12:41:13 +1000 Subject: [PATCH 26/33] evdev: add evdev_reject_device to reject a couple of oddball devices We really don't need to deal with devices that have x but not y or vice versa. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 23 +++++++++++ test/device.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index ea63356d..3481b455 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1415,6 +1415,22 @@ evdev_fix_android_mt(struct evdev_device *device) libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y)); } +static int +evdev_reject_device(struct evdev_device *device) +{ + struct libevdev *evdev = device->evdev; + + if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) ^ + libevdev_has_event_code(evdev, EV_ABS, ABS_Y)) + return -1; + + if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) ^ + libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) + return -1; + + return 0; +} + static int evdev_configure_device(struct evdev_device *device) { @@ -1467,6 +1483,13 @@ evdev_configure_device(struct evdev_device *device) return -1; } + if (evdev_reject_device(device) == -1) { + log_info(libinput, + "input device '%s', %s was rejected.\n", + device->devname, devnode); + return -1; + } + if (libevdev_has_event_type(evdev, EV_ABS)) { evdev_fix_android_mt(device); diff --git a/test/device.c b/test/device.c index 04205330..a18ec82d 100644 --- a/test/device.c +++ b/test/device.c @@ -716,6 +716,104 @@ START_TEST(device_group_ref) } END_TEST +START_TEST(abs_device_no_absx) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + + uinput = litest_create_uinput_device("test device", NULL, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_ABS, ABS_Y, + -1); + li = litest_create_context(); + litest_disable_log_handler(li); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + litest_restore_log_handler(li); + ck_assert(device == NULL); + libinput_unref(li); + + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(abs_device_no_absy) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + + uinput = litest_create_uinput_device("test device", NULL, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_ABS, ABS_X, + -1); + li = litest_create_context(); + litest_disable_log_handler(li); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + litest_restore_log_handler(li); + ck_assert(device == NULL); + libinput_unref(li); + + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(abs_mt_device_no_absy) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + + uinput = litest_create_uinput_device("test device", NULL, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_ABS, ABS_X, + EV_ABS, ABS_Y, + EV_ABS, ABS_MT_SLOT, + EV_ABS, ABS_MT_POSITION_X, + -1); + li = litest_create_context(); + litest_disable_log_handler(li); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + litest_restore_log_handler(li); + ck_assert(device == NULL); + libinput_unref(li); + + libevdev_uinput_destroy(uinput); +} +END_TEST + +START_TEST(abs_mt_device_no_absx) +{ + struct libevdev_uinput *uinput; + struct libinput *li; + struct libinput_device *device; + + uinput = litest_create_uinput_device("test device", NULL, + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_ABS, ABS_X, + EV_ABS, ABS_Y, + EV_ABS, ABS_MT_SLOT, + EV_ABS, ABS_MT_POSITION_Y, + -1); + li = litest_create_context(); + litest_disable_log_handler(li); + device = libinput_path_add_device(li, + libevdev_uinput_get_devnode(uinput)); + litest_restore_log_handler(li); + ck_assert(device == NULL); + libinput_unref(li); + + libevdev_uinput_destroy(uinput); +} +END_TEST + int main (int argc, char **argv) { litest_add("device:sendevents", device_sendevents_config, LITEST_ANY, LITEST_TOUCHPAD); @@ -744,5 +842,10 @@ int main (int argc, char **argv) litest_add("device:group", device_group_get, LITEST_ANY, LITEST_ANY); litest_add_no_device("device:group", device_group_ref); + litest_add_no_device("device:invalid devices", abs_device_no_absx); + 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); + return litest_run(argc, argv); } From 99d0c743f4fa3149f6ae0ef38edc22067cde86b7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 14:25:01 +1000 Subject: [PATCH 27/33] evdev: don't try to fix abs devices without x/y Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 3481b455..570c4361 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1490,7 +1490,8 @@ evdev_configure_device(struct evdev_device *device) return -1; } - if (libevdev_has_event_type(evdev, EV_ABS)) { + if (libevdev_has_event_code(evdev, EV_ABS, ABS_X) || + libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) { evdev_fix_android_mt(device); if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { From 522a42e9b45164d6dcb1f7e2c9535e8f4349ecdf Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 13 Mar 2015 13:56:14 +1000 Subject: [PATCH 28/33] Push the touchpad magic slowdown to the touchpad accel code This way the unaccelerated deltas returned by libinput are correct. To maintain the current behavior we slow down the input speed by the magic factor and likewise the accelerated output speed. This produces virtually the same accelerated deltas as the previous code. The magic factor is applied to the default denominator for guessing a resolution based on the touchpad diagonal. We can't really get around this without having a resolution from the touchpad; meanwhile this produces virtually the same coordinates before/after. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 20 ++++++-------------- src/evdev-mt-touchpad.h | 4 +--- src/evdev.c | 11 ++++++----- src/evdev.h | 4 +++- src/filter.c | 21 +++++++++++++++++++++ src/filter.h | 5 +++++ 6 files changed, 42 insertions(+), 23 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d0311a4c..b7760c23 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -29,7 +29,9 @@ #include "evdev-mt-touchpad.h" -#define DEFAULT_ACCEL_NUMERATOR 1200.0 +/* Number found by trial-and error, seems to be 1200, divided by the + * TP_MAGIC_SLOWDOWN in filter.c */ +#define DEFAULT_ACCEL_NUMERATOR 3000.0 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0 #define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 500 /* ms */ @@ -974,18 +976,6 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) if (res_x > 1 && res_y > 1) { tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; - - /* FIXME: once normalized, touchpads see the same - acceleration as mice. that is technically correct but - subjectively wrong, we expect a touchpad to be a lot - slower than a mouse. - For now, apply a magic factor here until this is - fixed in the actual filter code. - */ - { - tp->accel.x_scale_coeff *= TP_MAGIC_SLOWDOWN; - tp->accel.y_scale_coeff *= TP_MAGIC_SLOWDOWN; - } } else { /* * For touchpads where the driver does not provide resolution, fall @@ -995,7 +985,9 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal; } - if (evdev_device_init_pointer_acceleration(tp->device) == -1) + if (evdev_device_init_pointer_acceleration( + tp->device, + touchpad_accel_profile_linear) == -1) return -1; return 0; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 04acf214..9980f900 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -34,10 +34,8 @@ #define VENDOR_ID_APPLE 0x5ac -/* Touchpad slowdown factor, see the FIXME in tp_init_accel() */ -#define TP_MAGIC_SLOWDOWN 0.4 /* Convert mm to a distance normalized to DEFAULT_MOUSE_DPI */ -#define TP_MM_TO_DPI_NORMALIZED(mm) (DEFAULT_MOUSE_DPI/25.4 * TP_MAGIC_SLOWDOWN * mm) +#define TP_MM_TO_DPI_NORMALIZED(mm) (DEFAULT_MOUSE_DPI/25.4 * mm) enum touchpad_event { TOUCHPAD_EVENT_NONE = 0, diff --git a/src/evdev.c b/src/evdev.c index 570c4361..ff7bc371 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1266,11 +1266,10 @@ evdev_accel_config_get_default_speed(struct libinput_device *device) } int -evdev_device_init_pointer_acceleration(struct evdev_device *device) +evdev_device_init_pointer_acceleration(struct evdev_device *device, + accel_profile_func_t profile) { - device->pointer.filter = - create_pointer_accelerator_filter( - pointer_accel_profile_linear); + device->pointer.filter = create_pointer_accelerator_filter(profile); if (!device->pointer.filter) return -1; @@ -1575,7 +1574,9 @@ evdev_configure_device(struct evdev_device *device) if (udev_tags & EVDEV_UDEV_TAG_MOUSE) { if (!libevdev_has_event_code(evdev, EV_ABS, ABS_X) && !libevdev_has_event_code(evdev, EV_ABS, ABS_Y) && - evdev_device_init_pointer_acceleration(device) == -1) + evdev_device_init_pointer_acceleration( + device, + pointer_accel_profile_linear) == -1) return -1; device->seat_caps |= EVDEV_DEVICE_POINTER; diff --git a/src/evdev.h b/src/evdev.h index caafd53a..ddaab9fc 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -32,6 +32,7 @@ #include "libinput-private.h" #include "timer.h" +#include "filter.h" /* The HW DPI rate we normalize to before calculating pointer acceleration */ #define DEFAULT_MOUSE_DPI 1000 @@ -212,7 +213,8 @@ evdev_device_create(struct libinput_seat *seat, struct udev_device *device); int -evdev_device_init_pointer_acceleration(struct evdev_device *device); +evdev_device_init_pointer_acceleration(struct evdev_device *device, + accel_profile_func_t profile); struct evdev_dispatch * evdev_touchpad_create(struct evdev_device *device); diff --git a/src/filter.c b/src/filter.c index 72ef7609..306a2fe6 100644 --- a/src/filter.c +++ b/src/filter.c @@ -327,3 +327,24 @@ pointer_accel_profile_linear(struct motion_filter *filter, return min(max_accel, s2 > 1 ? s2 : s1); } + +double +touchpad_accel_profile_linear(struct motion_filter *filter, + void *data, + double speed_in, + uint64_t time) +{ + /* Once normalized, touchpads see the same + acceleration as mice. that is technically correct but + subjectively wrong, we expect a touchpad to be a lot + slower than a mouse. Apply a magic factor here and proceed + as normal. */ + const double TP_MAGIC_SLOWDOWN = 0.4; + double speed_out; + + speed_in *= TP_MAGIC_SLOWDOWN; + + speed_out = pointer_accel_profile_linear(filter, data, speed_in, time); + + return speed_out * TP_MAGIC_SLOWDOWN; +} diff --git a/src/filter.h b/src/filter.h index 9e903303..f23b691b 100644 --- a/src/filter.h +++ b/src/filter.h @@ -64,4 +64,9 @@ pointer_accel_profile_linear(struct motion_filter *filter, void *data, double speed_in, uint64_t time); +double +touchpad_accel_profile_linear(struct motion_filter *filter, + void *data, + double speed_in, + uint64_t time); #endif /* FILTER_H */ From 1e4116beb9863ecb69253b159af1f6909354600a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 10:07:00 +1000 Subject: [PATCH 29/33] evdev: refactor fake resolution setting Make the helper function accessible from other places (will be needed in an upcoming patchset). This also now takes a custom resolution as argument instead of always setting it to 1, and allows overriding a fake resolution after the fact. And instead of a hardcoded 1 everywhere, use a define for the resolution. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 105 ++++++++++++++++++++++++++++++++++------------------ src/evdev.h | 9 +++++ 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index ff7bc371..d9860b15 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1350,23 +1350,66 @@ evdev_read_dpi_prop(struct evdev_device *device) return dpi; } -static inline int -evdev_fix_abs_resolution(struct libevdev *evdev, - unsigned int code, - const struct input_absinfo *absinfo) +/* Return 1 if the given resolutions have been set, or 0 otherwise */ +inline int +evdev_fix_abs_resolution(struct evdev_device *device, + unsigned int xcode, + unsigned int ycode, + int xresolution, + int yresolution) { + struct libinput *libinput = device->base.seat->libinput; + struct libevdev *evdev = device->evdev; + const struct input_absinfo *absx, *absy; struct input_absinfo fixed; + int rc = 0; - if (absinfo->resolution == 0) { - fixed = *absinfo; - fixed.resolution = 1; - /* libevdev_set_abs_info() changes the absinfo we already - have a pointer to, no need to fetch it again */ - libevdev_set_abs_info(evdev, code, &fixed); - return 1; - } else { + if (!(xcode == ABS_X && ycode == ABS_Y) && + !(xcode == ABS_MT_POSITION_X && ycode == ABS_MT_POSITION_Y)) { + log_bug_libinput(libinput, + "Invalid x/y code combination %d/%d\n", + xcode, ycode); return 0; } + + if (xresolution == 0 || yresolution == 0 || + (xresolution == EVDEV_FAKE_RESOLUTION && xresolution != yresolution) || + (yresolution == EVDEV_FAKE_RESOLUTION && xresolution != yresolution)) { + log_bug_libinput(libinput, + "Invalid x/y resolutions %d/%d\n", + xresolution, yresolution); + return 0; + } + + absx = libevdev_get_abs_info(evdev, xcode); + absy = libevdev_get_abs_info(evdev, ycode); + + if ((absx->resolution == 0 && absy->resolution != 0) || + (absx->resolution != 0 && absy->resolution == 0)) { + log_bug_kernel(libinput, + "Kernel has only x or y resolution, not both.\n"); + return 0; + } + + if (absx->resolution == 0 || absx->resolution == EVDEV_FAKE_RESOLUTION) { + fixed = *absx; + fixed.resolution = xresolution; + /* libevdev_set_abs_info() changes the absinfo we already + have a pointer to, no need to fetch it again */ + libevdev_set_abs_info(evdev, xcode, &fixed); + rc = 1; + } + + if (absy->resolution == 0 || absy->resolution == EVDEV_FAKE_RESOLUTION) { + fixed = *absy; + fixed.resolution = yresolution; + /* libevdev_set_abs_info() changes the absinfo we already + have a pointer to, no need to fetch it again */ + libevdev_set_abs_info(evdev, ycode, &fixed); + rc = 1; + } + + return rc; } static enum evdev_device_udev_tags @@ -1435,7 +1478,6 @@ evdev_configure_device(struct evdev_device *device) { struct libinput *libinput = device->base.seat->libinput; struct libevdev *evdev = device->evdev; - const struct input_absinfo *absinfo; struct mt_slot *slots; int num_slots; int active_slot; @@ -1493,20 +1535,14 @@ evdev_configure_device(struct evdev_device *device) libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X)) { evdev_fix_android_mt(device); - if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { - if (evdev_fix_abs_resolution(evdev, - ABS_X, - absinfo)) - device->abs.fake_resolution = 1; - device->abs.absinfo_x = absinfo; - } - if ((absinfo = libevdev_get_abs_info(evdev, ABS_Y))) { - if (evdev_fix_abs_resolution(evdev, - ABS_Y, - absinfo)) - device->abs.fake_resolution = 1; - device->abs.absinfo_y = absinfo; - } + if (evdev_fix_abs_resolution(device, + ABS_X, + ABS_Y, + EVDEV_FAKE_RESOLUTION, + EVDEV_FAKE_RESOLUTION)) + device->abs.fake_resolution = 1; + device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_X); + device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_Y); /* Fake MT devices have the ABS_MT_SLOT bit set because of the limited ABS_* range - they aren't MT devices, they @@ -1516,19 +1552,14 @@ evdev_configure_device(struct evdev_device *device) udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN; } else if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) && libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) { - absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); - if (evdev_fix_abs_resolution(evdev, + if (evdev_fix_abs_resolution(device, ABS_MT_POSITION_X, - absinfo)) - device->abs.fake_resolution = 1; - device->abs.absinfo_x = absinfo; - - absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); - if (evdev_fix_abs_resolution(evdev, ABS_MT_POSITION_Y, - absinfo)) + EVDEV_FAKE_RESOLUTION, + EVDEV_FAKE_RESOLUTION)) device->abs.fake_resolution = 1; - device->abs.absinfo_y = absinfo; + device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); + device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); device->is_mt = 1; /* We only handle the slotted Protocol B in libinput. diff --git a/src/evdev.h b/src/evdev.h index ddaab9fc..af09baa5 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -36,6 +36,8 @@ /* The HW DPI rate we normalize to before calculating pointer acceleration */ #define DEFAULT_MOUSE_DPI 1000 +/* The fake resolution value for abs devices without resolution */ +#define EVDEV_FAKE_RESOLUTION 1 enum evdev_event_type { EVDEV_NONE, @@ -212,6 +214,13 @@ struct evdev_device * evdev_device_create(struct libinput_seat *seat, struct udev_device *device); +int +evdev_fix_abs_resolution(struct evdev_device *device, + unsigned int xcode, + unsigned int ycode, + int yresolution, + int xresolution); + int evdev_device_init_pointer_acceleration(struct evdev_device *device, accel_profile_func_t profile); From 0e64837f30c310da878f28961a6db7c4bcd4f282 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 10:16:13 +1000 Subject: [PATCH 30/33] touchpad: parse the TOUCHPAD_RESOLUTION property Not all touchpad kernel drivers supply the x/y resolution. Let the udev hwdb fix this up where possible and read the value from it. This is intentionally only used on touchpads, touchscreen devices without resolution should be considered buggy and fixed in the kernel. 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 insertions(+) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index fc1c0af8..87e92e6e 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -57,6 +57,11 @@ 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 b7760c23..998249ff 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1117,6 +1117,32 @@ 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) @@ -1130,6 +1156,8 @@ 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 49e297af..cd3b18dc 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -201,3 +201,33 @@ 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 f76439f1..bd71a1ff 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -299,5 +299,8 @@ 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 db26d67e..414d7cb3 100644 --- a/test/misc.c +++ b/test/misc.c @@ -557,6 +557,54 @@ 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); @@ -572,6 +620,7 @@ 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 70f8ae5678ea1fe079e97e2d317d234a05407bbb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Mar 2015 12:15:22 +1000 Subject: [PATCH 31/33] evdev: factor out setting up the MT slots/mtdev No functional changes Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 100 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index d9860b15..284aa1fb 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1474,14 +1474,67 @@ evdev_reject_device(struct evdev_device *device) } static int -evdev_configure_device(struct evdev_device *device) +evdev_configure_mt_device(struct evdev_device *device) { - struct libinput *libinput = device->base.seat->libinput; struct libevdev *evdev = device->evdev; struct mt_slot *slots; int num_slots; int active_slot; int slot; + + if (!libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) || + !libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) + return 0; + + if (evdev_fix_abs_resolution(device, + ABS_MT_POSITION_X, + ABS_MT_POSITION_Y, + EVDEV_FAKE_RESOLUTION, + EVDEV_FAKE_RESOLUTION)) + device->abs.fake_resolution = 1; + + device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); + device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); + device->is_mt = 1; + + /* We only handle the slotted Protocol B in libinput. + Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT + require mtdev for conversion. */ + if (evdev_need_mtdev(device)) { + device->mtdev = mtdev_new_open(device->fd); + if (!device->mtdev) + return -1; + + /* pick 10 slots as default for type A + devices. */ + num_slots = 10; + active_slot = device->mtdev->caps.slot.value; + } else { + num_slots = libevdev_get_num_slots(device->evdev); + active_slot = libevdev_get_current_slot(evdev); + } + + slots = calloc(num_slots, sizeof(struct mt_slot)); + if (!slots) + return -1; + + for (slot = 0; slot < num_slots; ++slot) { + slots[slot].seat_slot = -1; + slots[slot].point.x = 0; + slots[slot].point.y = 0; + } + device->mt.slots = slots; + device->mt.slots_len = num_slots; + device->mt.slot = active_slot; + + return 0; +} + +static int +evdev_configure_device(struct evdev_device *device) +{ + struct libinput *libinput = device->base.seat->libinput; + struct libevdev *evdev = device->evdev; const char *devnode = udev_device_get_devnode(device->udev_device); enum evdev_device_udev_tags udev_tags; @@ -1550,47 +1603,8 @@ evdev_configure_device(struct evdev_device *device) if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_SLOT) && libevdev_get_num_slots(evdev) == -1) { udev_tags &= ~EVDEV_UDEV_TAG_TOUCHSCREEN; - } else if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) && - libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) { - if (evdev_fix_abs_resolution(device, - ABS_MT_POSITION_X, - ABS_MT_POSITION_Y, - EVDEV_FAKE_RESOLUTION, - EVDEV_FAKE_RESOLUTION)) - device->abs.fake_resolution = 1; - device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); - device->abs.absinfo_y = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); - device->is_mt = 1; - - /* We only handle the slotted Protocol B in libinput. - Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT - require mtdev for conversion. */ - if (evdev_need_mtdev(device)) { - device->mtdev = mtdev_new_open(device->fd); - if (!device->mtdev) - return -1; - - /* pick 10 slots as default for type A - devices. */ - num_slots = 10; - active_slot = device->mtdev->caps.slot.value; - } else { - num_slots = libevdev_get_num_slots(device->evdev); - active_slot = libevdev_get_current_slot(evdev); - } - - slots = calloc(num_slots, sizeof(struct mt_slot)); - if (!slots) - return -1; - - for (slot = 0; slot < num_slots; ++slot) { - slots[slot].seat_slot = -1; - slots[slot].point.x = 0; - slots[slot].point.y = 0; - } - device->mt.slots = slots; - device->mt.slots_len = num_slots; - device->mt.slot = active_slot; + } else if (evdev_configure_mt_device(device) == -1) { + return -1; } } From d101d43dd0f7516167ec5d9964268f838a03cff1 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 16 Mar 2015 14:13:43 +1000 Subject: [PATCH 32/33] touchpad: force a resolution onto the apple touchpads A large range of the Apple touchpads seem to have the same dimensions. Use that fact to force-set a resolution. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 998249ff..62d80195 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -966,6 +966,22 @@ 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 7506d69811fe2b97f6dc6a6ef054a2f5e60fd740 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 18 Mar 2015 10:01:03 +1000 Subject: [PATCH 33/33] tools: print available click methods on device notify Signed-off-by: Peter Hutterer --- tools/event-debug.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/event-debug.c b/tools/event-debug.c index 38a6e823..3629e745 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -124,7 +124,7 @@ print_device_notify(struct libinput_event *ev) struct libinput_seat *seat = libinput_device_get_seat(dev); struct libinput_device_group *group; double w, h; - uint32_t scroll_methods; + uint32_t scroll_methods, click_methods; static int next_group_id = 0; intptr_t group_id; @@ -175,6 +175,15 @@ print_device_notify(struct libinput_event *ev) printf("-button"); } + click_methods = libinput_device_config_click_get_methods(dev); + if (click_methods != LIBINPUT_CONFIG_CLICK_METHOD_NONE) { + printf(" click"); + if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) + printf("-buttonareas"); + if (click_methods & LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER) + printf("-clickfinger"); + } + printf("\n"); }