From ffb19421a3ed68f2f70c59c5f12f33bedfd0d9ec Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 9 Jul 2015 09:32:40 +1000 Subject: [PATCH 01/29] touchpad: fix a misaligned { Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index e90bd1e4..3461dc5b 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -496,8 +496,7 @@ tp_palm_detect_dwt(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) return 1; } else if (!tp->dwt.keyboard_active && t->state == TOUCH_UPDATE && - t->palm.state == PALM_TYPING) - { + t->palm.state == PALM_TYPING) { /* If a touch has started before the first or after the last key press, release it on timeout. Benefit: a palm rested while typing on the touchpad will be ignored, but a touch From 9a8238836e261e614836d389ea8e2c516514999a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 3 Jul 2015 15:17:33 +1000 Subject: [PATCH 02/29] test: move enable_edge_scroll up No functional changes, just so we can group those helpers together. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 1f11cfa6..082312ca 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -32,6 +32,19 @@ #include "libinput-util.h" #include "litest.h" +static void +enable_edge_scroll(struct litest_device *dev) +{ + enum libinput_config_status status, expected; + struct libinput_device *device = dev->libinput_device; + + status = libinput_device_config_scroll_set_method(device, + LIBINPUT_CONFIG_SCROLL_EDGE); + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + litest_assert_int_eq(status, expected); +} + START_TEST(touchpad_1fg_motion) { struct litest_device *dev = litest_current_device(); @@ -1442,19 +1455,6 @@ START_TEST(touchpad_scroll_natural) } END_TEST -static void -enable_edge_scroll(struct litest_device *dev) -{ - enum libinput_config_status status, expected; - struct libinput_device *device = dev->libinput_device; - - status = libinput_device_config_scroll_set_method(device, - LIBINPUT_CONFIG_SCROLL_EDGE); - - expected = LIBINPUT_CONFIG_STATUS_SUCCESS; - litest_assert_int_eq(status, expected); -} - START_TEST(touchpad_edge_scroll) { struct litest_device *dev = litest_current_device(); From 77aca3c194eb651b52f3c35241f0f2ff7c176ca4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 3 Jul 2015 15:23:41 +1000 Subject: [PATCH 03/29] test: add helper function for enabling click methods Makes the test code easier to read. In tests where we explicitly check the API the real calls were left in place. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 89 +++++++++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 082312ca..8f11362a 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -45,6 +45,30 @@ enable_edge_scroll(struct litest_device *dev) litest_assert_int_eq(status, expected); } +static void +enable_clickfinger(struct litest_device *dev) +{ + enum libinput_config_status status, expected; + struct libinput_device *device = dev->libinput_device; + + status = libinput_device_config_click_set_method(device, + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + litest_assert_int_eq(status, expected); +} + +static void +enable_buttonareas(struct litest_device *dev) +{ + enum libinput_config_status status, expected; + struct libinput_device *device = dev->libinput_device; + + status = libinput_device_config_click_set_method(device, + LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + litest_assert_int_eq(status, expected); +} + START_TEST(touchpad_1fg_motion) { struct litest_device *dev = litest_current_device(); @@ -192,11 +216,8 @@ START_TEST(touchpad_1fg_clickfinger) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enum libinput_config_status status; - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -220,11 +241,8 @@ START_TEST(touchpad_1fg_clickfinger_no_touch) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enum libinput_config_status status; - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -246,11 +264,8 @@ START_TEST(touchpad_2fg_clickfinger) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enum libinput_config_status status; - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -277,8 +292,8 @@ START_TEST(touchpad_2fg_clickfinger_distance) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + enable_clickfinger(dev); + litest_drain_events(li); litest_touch_down(dev, 0, 90, 50); @@ -320,14 +335,11 @@ END_TEST START_TEST(touchpad_clickfinger_to_area_method) { struct litest_device *dev = litest_current_device(); - enum libinput_config_status status; struct libinput *li = dev->libinput; litest_drain_events(li); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_buttonareas(dev); litest_touch_down(dev, 0, 90, 90); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -342,9 +354,7 @@ START_TEST(touchpad_clickfinger_to_area_method) litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -368,14 +378,11 @@ END_TEST START_TEST(touchpad_clickfinger_to_area_method_while_down) { struct litest_device *dev = litest_current_device(); - enum libinput_config_status status; struct libinput *li = dev->libinput; litest_drain_events(li); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_buttonareas(dev); litest_touch_down(dev, 0, 90, 90); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -384,9 +391,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down) litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_event(dev, EV_KEY, BTN_LEFT, 0); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -418,12 +423,9 @@ END_TEST START_TEST(touchpad_area_to_clickfinger_method) { struct litest_device *dev = litest_current_device(); - enum libinput_config_status status; struct libinput *li = dev->libinput; - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -441,9 +443,7 @@ START_TEST(touchpad_area_to_clickfinger_method) litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_buttonareas(dev); litest_touch_down(dev, 0, 90, 90); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -464,12 +464,9 @@ END_TEST START_TEST(touchpad_area_to_clickfinger_method_while_down) { struct litest_device *dev = litest_current_device(); - enum libinput_config_status status; struct libinput *li = dev->libinput; - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_clickfinger(dev); litest_drain_events(li); @@ -480,9 +477,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down) litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED); - status = libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); - ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + enable_buttonareas(dev); litest_event(dev, EV_KEY, BTN_LEFT, 0); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -534,8 +529,7 @@ START_TEST(clickpad_btn_left) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + enable_buttonareas(dev); litest_drain_events(li); @@ -1137,8 +1131,8 @@ START_TEST(clickpad_topsoftbuttons_clickfinger) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + enable_clickfinger(dev); + litest_drain_events(li); litest_touch_down(dev, 0, 90, 5); @@ -1182,10 +1176,9 @@ START_TEST(clickpad_topsoftbuttons_clickfinger_dev_disabled) struct litest_device *trackpoint = litest_add_device(li, LITEST_TRACKPOINT); - libinput_device_config_click_set_method(dev->libinput_device, - LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); libinput_device_config_send_events_set_mode(dev->libinput_device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); + enable_clickfinger(dev); litest_drain_events(li); litest_touch_down(dev, 0, 90, 5); From abff4a1c24830931f1cbd5e54d5b1a4621eab863 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 3 Jul 2015 14:33:41 +1000 Subject: [PATCH 04/29] touchpad: allow edge scrolling on clickpads Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/scrolling.dox | 6 +- src/evdev-mt-touchpad-buttons.c | 4 + src/evdev-mt-touchpad-edge-scroll.c | 21 ++- src/evdev-mt-touchpad.c | 5 +- test/touchpad.c | 211 +++++++++++++++++++++++++++- 5 files changed, 230 insertions(+), 17 deletions(-) diff --git a/doc/scrolling.dox b/doc/scrolling.dox index 1ecd0333..658fe4b6 100644 --- a/doc/scrolling.dox +++ b/doc/scrolling.dox @@ -55,10 +55,8 @@ scroll). Due to the layout of the edges, diagonal scrolling is not possible. The behavior of edge scrolling using both edges at the same time is undefined. -Edge scrolling conflicts with @ref clickpad_softbuttons and is -not usually available on clickpads. See -http://who-t.blogspot.com.au/2015/03/why-libinput-doesnt-support-edge.html -for details. +Edge scrolling overlaps with @ref clickpad_softbuttons. A physical click on +a clickpad ends scrolling. @section button_scrolling On-Button scrolling diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index f0857747..3352c667 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -941,6 +941,10 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp, if (tp->device->suspended) return 0; + /* A button click always terminates edge scrolling, even if we + * don't end up sending a button event. */ + tp_edge_scroll_stop_events(tp, time); + /* * If the user has requested clickfinger replace the button chosen * by the softbutton code with one based on the number of fingers. diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 9a9d3b84..4d5f47af 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -34,7 +34,6 @@ #define CASE_RETURN_STRING(a) case a: return #a -#define DEFAULT_SCROLL_LOCK_TIMEOUT 300 /* ms */ /* Use a reasonably large threshold until locked into scrolling mode, to avoid accidentally locking in scrolling mode when trying to use the entire touchpad to move the pointer. The user can wait for the timeout to trigger @@ -92,6 +91,23 @@ tp_touch_get_edge(struct tp_dispatch *tp, struct tp_touch *t) return edge; } +static inline void +tp_edge_scroll_set_timer(struct tp_dispatch *tp, + struct tp_touch *t) +{ + const int DEFAULT_SCROLL_LOCK_TIMEOUT = 300; /* ms */ + /* if we use software buttons, we disable timeout-based + * edge scrolling. A finger resting on the button areas is + * likely there to trigger a button event. + */ + if (tp->buttons.click_method == + LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS) + return; + + libinput_timer_set(&t->scroll.timer, + t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT); +} + static void tp_edge_scroll_set_state(struct tp_dispatch *tp, struct tp_touch *t, @@ -108,8 +124,7 @@ tp_edge_scroll_set_state(struct tp_dispatch *tp, case EDGE_SCROLL_TOUCH_STATE_EDGE_NEW: t->scroll.edge = tp_touch_get_edge(tp, t); t->scroll.initial = t->point; - libinput_timer_set(&t->scroll.timer, - t->millis + DEFAULT_SCROLL_LOCK_TIMEOUT); + tp_edge_scroll_set_timer(tp, t); break; case EDGE_SCROLL_TOUCH_STATE_EDGE: break; diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 3461dc5b..d3bb6434 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1349,14 +1349,11 @@ tp_scroll_config_scroll_method_get_methods(struct libinput_device *device) { struct evdev_device *evdev = (struct evdev_device*)device; struct tp_dispatch *tp = (struct tp_dispatch*)evdev->dispatch; - uint32_t methods = LIBINPUT_CONFIG_SCROLL_NO_SCROLL; + uint32_t methods = LIBINPUT_CONFIG_SCROLL_EDGE; if (tp->ntouches >= 2) methods |= LIBINPUT_CONFIG_SCROLL_2FG; - if (!tp->buttons.is_clickpad) - methods |= LIBINPUT_CONFIG_SCROLL_EDGE; - return methods; } diff --git a/test/touchpad.c b/test/touchpad.c index 8f11362a..a9e9e4e9 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1490,6 +1490,42 @@ START_TEST(touchpad_edge_scroll) } END_TEST +START_TEST(touchpad_scroll_defaults) +{ + struct litest_device *dev = litest_current_device(); + struct libinput_device *device = dev->libinput_device; + struct libevdev *evdev = dev->evdev; + enum libinput_config_scroll_method method, expected; + enum libinput_config_status status; + + method = libinput_device_config_scroll_get_methods(device); + ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE); + if (libevdev_get_num_slots(evdev) > 1) + ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG); + + if (libevdev_get_num_slots(evdev) > 1) + expected = LIBINPUT_CONFIG_SCROLL_2FG; + else + expected = LIBINPUT_CONFIG_SCROLL_EDGE; + + method = libinput_device_config_scroll_get_method(device); + ck_assert_int_eq(method, expected); + method = libinput_device_config_scroll_get_default_method(device); + ck_assert_int_eq(method, expected); + + status = libinput_device_config_scroll_set_method(device, + LIBINPUT_CONFIG_SCROLL_EDGE); + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + status = libinput_device_config_scroll_set_method(device, + LIBINPUT_CONFIG_SCROLL_2FG); + + if (libevdev_get_num_slots(evdev) > 1) + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); + else + ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); +} +END_TEST + START_TEST(touchpad_edge_scroll_timeout) { struct litest_device *dev = litest_current_device(); @@ -1639,6 +1675,164 @@ START_TEST(touchpad_edge_scroll_no_2fg) } END_TEST +START_TEST(touchpad_edge_scroll_into_buttonareas) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + enable_buttonareas(dev); + enable_edge_scroll(dev); + litest_drain_events(li); + + litest_touch_down(dev, 0, 99, 40); + litest_touch_move_to(dev, 0, 99, 40, 99, 95, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + /* in the button zone now, make sure we still get events */ + litest_touch_move_to(dev, 0, 99, 95, 99, 100, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + /* and out of the zone again */ + litest_touch_move_to(dev, 0, 99, 100, 99, 70, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + /* still out of the zone */ + litest_touch_move_to(dev, 0, 99, 70, 99, 50, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); +} +END_TEST + +START_TEST(touchpad_edge_scroll_within_buttonareas) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + enable_buttonareas(dev); + enable_edge_scroll(dev); + litest_drain_events(li); + + litest_touch_down(dev, 0, 20, 99); + + /* within left button */ + litest_touch_move_to(dev, 0, 20, 99, 40, 99, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + /* over to right button */ + litest_touch_move_to(dev, 0, 40, 99, 60, 99, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + /* within right button */ + litest_touch_move_to(dev, 0, 60, 99, 80, 99, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); +} +END_TEST + +START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + double val; + + enable_buttonareas(dev); + enable_edge_scroll(dev); + litest_drain_events(li); + + litest_touch_down(dev, 0, 20, 95); + litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + litest_button_click(dev, BTN_LEFT, true); + libinput_dispatch(li); + + event = libinput_get_event(li); + ptrev = litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + val = libinput_event_pointer_get_axis_value(ptrev, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + ck_assert(val == 0.0); + libinput_event_destroy(event); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_PRESSED); + + libinput_event_destroy(event); + + /* within button areas -> no movement */ + litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0); + litest_assert_empty_queue(li); + + litest_button_click(dev, BTN_LEFT, false); + + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_BUTTON); + + litest_touch_up(dev, 0); +} +END_TEST + +START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + double val; + + enable_clickfinger(dev); + enable_edge_scroll(dev); + litest_drain_events(li); + + litest_touch_down(dev, 0, 20, 95); + litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_AXIS); + + litest_button_click(dev, BTN_LEFT, true); + libinput_dispatch(li); + + event = libinput_get_event(li); + ptrev = litest_is_axis_event(event, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + LIBINPUT_POINTER_AXIS_SOURCE_FINGER); + val = libinput_event_pointer_get_axis_value(ptrev, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + ck_assert(val == 0.0); + libinput_event_destroy(event); + + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + + libinput_event_destroy(event); + + /* clickfinger releases pointer -> expect movement */ + litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0); + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_empty_queue(li); + + litest_button_click(dev, BTN_LEFT, false); + + litest_assert_only_typed_events(li, + LIBINPUT_EVENT_POINTER_BUTTON); + + litest_touch_up(dev, 0); +} +END_TEST + static int touchpad_has_palm_detect_size(struct litest_device *dev) { @@ -3522,12 +3716,17 @@ litest_setup_tests(void) litest_add("touchpad:scroll", touchpad_scroll_natural_defaults, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:scroll", touchpad_scroll_natural_enable_config, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:scroll", touchpad_scroll_natural, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); - litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_CLICKPAD); - litest_add("touchpad:scroll", touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_CLICKPAD); + litest_add("touchpad:scroll", touchpad_scroll_defaults, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_no_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_no_edge_after_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_timeout, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_source, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_no_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:scroll", touchpad_edge_scroll_into_buttonareas, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_within_buttonareas, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_buttonareas_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:scroll", touchpad_edge_scroll_clickfinger_click_stops_scroll, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:palm", touchpad_palm_detect_at_edge, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:palm", touchpad_palm_detect_at_bottom_corners, LITEST_TOUCHPAD, LITEST_CLICKPAD); From 7d314738fb7cb351d08b9860158bfb41975fb6c0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 3 Jul 2015 10:30:06 +1000 Subject: [PATCH 05/29] touchpad: be smarter about clickfinger thumb detection Watching a colleague try clickfinger right-click after enabling it the first time showed that the vertical distance is too small. Increase it to 30mm instead. Increase the allowed spread between fingers to 40x30mm, but check if one of the fingers is in the bottom-most 20mm of the touchpad. If that's the case, and the touchpad is large enough to be feasable for resting a thumb on it, discard the finger for clickfinger count. If both fingers are in that area or one finger is in the area and they're really close together, the fingers count separately and are not regarded as thumb. https://bugs.freedesktop.org/show_bug.cgi?id=91046 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 50 +++++++++++++++----- test/touchpad.c | 82 +++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 3352c667..771d71de 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -825,6 +825,9 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp, struct tp_touch *t2) { double x, y; + int within_distance = 0; + int xres, yres; + int bottom_threshold; if (!t1 || !t2) return 0; @@ -839,19 +842,44 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp, w = tp->device->abs.dimensions.x; h = tp->device->abs.dimensions.y; - return (x < w * 0.3 && y < h * 0.3) ? 1 : 0; - } else { - /* maximum spread is 40mm horiz, 20mm vert. Anything wider than that - * is probably a gesture. The y spread is small so we ignore clicks - * with thumbs at the bottom of the touchpad while the pointer - * moving finger is still on the pad */ - - x /= tp->device->abs.absinfo_x->resolution; - y /= tp->device->abs.absinfo_y->resolution; - - return (x < 40 && y < 20) ? 1 : 0; + within_distance = (x < w * 0.3 && y < h * 0.3) ? 1 : 0; + goto out; } + xres = tp->device->abs.absinfo_x->resolution; + yres = tp->device->abs.absinfo_y->resolution; + x /= xres; + y /= yres; + + /* maximum horiz spread is 40mm horiz, 30mm vert, anything wider + * than that is probably a gesture. */ + if (x > 40 || y > 30) + goto out; + + within_distance = 1; + + /* if y spread is <= 20mm, they're definitely together. */ + if (y <= 20) + goto out; + + /* if they're vertically spread between 20-40mm, they're not + * together if: + * - the touchpad's vertical size is >50mm, anything smaller is + * unlikely to have a thumb resting on it + * - and one of the touches is in the bottom 20mm of the touchpad + * and the other one isn't + */ + + if (tp->device->abs.dimensions.y/yres < 50) + goto out; + + bottom_threshold = tp->device->abs.absinfo_y->maximum - 20 * yres; + if ((t1->point.y > bottom_threshold) != + (t2->point.y > bottom_threshold)) + within_distance = 0; + +out: + return within_distance; } static uint32_t diff --git a/test/touchpad.c b/test/touchpad.c index a9e9e4e9..4aa9f4e6 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -291,6 +291,13 @@ START_TEST(touchpad_2fg_clickfinger_distance) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + double w, h; + bool small_touchpad = false; + unsigned int expected_button; + + if (libinput_device_get_size(dev->libinput_device, &w, &h) == 0 && + h < 50.0) + small_touchpad = true; enable_clickfinger(dev); @@ -323,12 +330,86 @@ START_TEST(touchpad_2fg_clickfinger_distance) litest_touch_up(dev, 0); litest_touch_up(dev, 1); + /* if the touchpad is small enough, we expect all fingers to count + * for clickfinger */ + if (small_touchpad) + expected_button = BTN_RIGHT; + else + expected_button = BTN_LEFT; + + litest_assert_button_event(li, + expected_button, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + expected_button, + LIBINPUT_BUTTON_STATE_RELEASED); +} +END_TEST + +START_TEST(touchpad_2fg_clickfinger_bottom) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + /* this test is run for the T440s touchpad only, makes getting the + * mm correct easier */ + + libinput_device_config_click_set_method(dev->libinput_device, + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + litest_drain_events(li); + + /* one above, one below the magic line, vert spread ca 27mm */ + litest_touch_down(dev, 0, 40, 60); + litest_touch_down(dev, 1, 60, 100); + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED); litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); + + litest_assert_empty_queue(li); + + /* both below the magic line */ + litest_touch_down(dev, 0, 40, 100); + litest_touch_down(dev, 1, 60, 95); + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + + litest_assert_button_event(li, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_RELEASED); + + /* one above, one below the magic line, vert spread 17mm */ + litest_touch_down(dev, 0, 50, 75); + litest_touch_down(dev, 1, 55, 100); + litest_event(dev, EV_KEY, BTN_LEFT, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_event(dev, EV_KEY, BTN_LEFT, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + + litest_assert_button_event(li, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -3676,6 +3757,7 @@ litest_setup_tests(void) litest_add("touchpad:clickfinger", touchpad_1fg_clickfinger_no_touch, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); + litest_add_for_device("touchpad:clickfinger", touchpad_2fg_clickfinger_bottom, LITEST_SYNAPTICS_TOPBUTTONPAD); litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_clickfinger_to_area_method_while_down, LITEST_CLICKPAD, LITEST_ANY); From 4a3288dc59e2f1211c8f69dca3eb4b9ea4059482 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 6 Jul 2015 16:26:21 +1000 Subject: [PATCH 06/29] test: allow for a default value on LITEST_AUTO_ASSIGNS The touchpads currently all send a default value of 30 for ABS_PRESSURE. For some tests we want to have a custom pressure but changing all tests isn't sensible. So hook each device up to send a default value of 30 if it isn't overridden in the test itself. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/litest-bcm5974.c | 19 ++++++++++++++++++- test/litest-int.h | 6 ++++++ test/litest-synaptics-t440.c | 19 ++++++++++++++++++- test/litest-synaptics-x1-carbon-3rd.c | 19 ++++++++++++++++++- test/litest-synaptics.c | 19 ++++++++++++++++++- test/litest.c | 22 +++++++++++++++------- 6 files changed, 93 insertions(+), 11 deletions(-) diff --git a/test/litest-bcm5974.c b/test/litest-bcm5974.c index f84d1d00..cbf2a74c 100644 --- a/test/litest-bcm5974.c +++ b/test/litest-bcm5974.c @@ -37,11 +37,12 @@ static void litest_bcm5974_setup(void) static struct input_event down[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -50,15 +51,31 @@ static struct input_event move[] = { { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 30; + return 0; + } + return 1; +} + static struct litest_device_interface interface = { .touch_down_events = down, .touch_move_events = move, + + .get_axis_default = get_axis_default, }; static struct input_absinfo absinfo[] = { diff --git a/test/litest-int.h b/test/litest-int.h index 666c5ff9..ab611a56 100644 --- a/test/litest-int.h +++ b/test/litest-int.h @@ -79,6 +79,12 @@ struct litest_device_interface { void (*touch_move)(struct litest_device *d, unsigned int slot, double x, double y); void (*touch_up)(struct litest_device *d, unsigned int slot); + /** + * Default value for the given EV_ABS axis. + * @return 0 on success, nonzero otherwise + */ + int (*get_axis_default)(struct litest_device *d, unsigned int code, int32_t *value); + /** * Set of of events to execute on touch down, terminated by a .type * and .code value of -1. If the event value is LITEST_AUTO_ASSIGN, diff --git a/test/litest-synaptics-t440.c b/test/litest-synaptics-t440.c index 4247a0ce..fa561858 100644 --- a/test/litest-synaptics-t440.c +++ b/test/litest-synaptics-t440.c @@ -38,11 +38,12 @@ litest_synaptics_t440_setup(void) static struct input_event down[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -51,15 +52,31 @@ static struct input_event move[] = { { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 30; + return 0; + } + return 1; +} + static struct litest_device_interface interface = { .touch_down_events = down, .touch_move_events = move, + + .get_axis_default = get_axis_default, }; static struct input_id input_id = { diff --git a/test/litest-synaptics-x1-carbon-3rd.c b/test/litest-synaptics-x1-carbon-3rd.c index bb50f4a1..2005c8c4 100644 --- a/test/litest-synaptics-x1-carbon-3rd.c +++ b/test/litest-synaptics-x1-carbon-3rd.c @@ -38,11 +38,12 @@ litest_synaptics_carbon3rd_setup(void) static struct input_event down[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -51,15 +52,31 @@ static struct input_event move[] = { { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 30; + return 0; + } + return 1; +} + static struct litest_device_interface interface = { .touch_down_events = down, .touch_move_events = move, + + .get_axis_default = get_axis_default, }; static struct input_id input_id = { diff --git a/test/litest-synaptics.c b/test/litest-synaptics.c index c35ad3d5..4dcdebfd 100644 --- a/test/litest-synaptics.c +++ b/test/litest-synaptics.c @@ -38,11 +38,12 @@ litest_synaptics_clickpad_setup(void) static struct input_event down[] = { { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, - { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30 }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; @@ -51,15 +52,31 @@ static struct input_event move[] = { { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_PRESSURE, .value = LITEST_AUTO_ASSIGN }, { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, { .type = -1, .code = -1 }, }; +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 30; + return 0; + } + return 1; +} + static struct litest_device_interface interface = { .touch_down_events = down, .touch_move_events = move, + + .get_axis_default = get_axis_default, }; static struct input_id input_id = { diff --git a/test/litest.c b/test/litest.c index 86079c2a..8cde52fe 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1212,19 +1212,22 @@ litest_event(struct litest_device *d, unsigned int type, litest_assert_int_eq(ret, 0); } -static int32_t +static bool axis_replacement_value(struct axis_replacement *axes, - int32_t evcode) + int32_t evcode, + int32_t *value) { struct axis_replacement *axis = axes; while (axis->evcode != -1) { - if (axis->evcode == evcode) - return axis->value; + if (axis->evcode == evcode) { + *value = axis->value; + return true; + } axis++; } - return -1; + return false; } int @@ -1259,8 +1262,13 @@ litest_auto_assign_value(struct litest_device *d, value = touching ? 0 : 1; break; default: - if (axes) - value = axis_replacement_value(axes, ev->code); + value = -1; + if (!axes) + break; + + if (!axis_replacement_value(axes, ev->code, &value) && + d->interface->get_axis_default) + d->interface->get_axis_default(d, ev->code, &value); break; } From 3dcf28b919ae598506852b408829a6627168e803 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 27 May 2015 18:25:49 +1000 Subject: [PATCH 07/29] touchpad: add pressure-based thumb-detection All touchpad recordings seen so far show that a value above 100 is definitely a thumb or a palm. Values below are harder to discern, and the same isn't true for touchpads supporting ABS_PRESSURE instead of ABS_MT_PRESSURE. The handling of a touch is as outlined in tp_thumb_detect: * thumbs are ignored for pointer motion * thumbs cancel gestures * thumbs are ignored for clickfinger count * edge scrolling doesn't care either way * software buttons don't care either way * tap: only if thumb on begin The handling of thumbs while tapping is the simplest approach only, more to come in follow-up patches. Note that "thumb" is the synonym for "this touch is too big to be a fingertip". Which means that a light thumb touch will still be counted as a finger. The side-effect here is that thumbs resting a the bottom edge of the touchpad will almost certainly not trigger the pressure threshold because most of the thumb is off the touchpad. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 3 ++ src/evdev-mt-touchpad-gestures.c | 25 ++++++++++++- src/evdev-mt-touchpad-tap.c | 13 +++++++ src/evdev-mt-touchpad.c | 61 ++++++++++++++++++++++++++++++++ src/evdev-mt-touchpad.h | 9 +++++ 5 files changed, 110 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 771d71de..9542d874 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -832,6 +832,9 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp, if (!t1 || !t2) return 0; + if (t1->is_thumb || t2->is_thumb) + return 0; + x = abs(t1->point.x - t2->point.x); y = abs(t1->point.y - t2->point.y); diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index cd853ecf..81bbd4d7 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -525,11 +525,34 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time) { unsigned int active_touches = 0; struct tp_touch *t; + uint32_t old_thumb_mask, thumb_mask = 0; + int i = 0; - tp_for_each_touch(tp, t) + tp_for_each_touch(tp, t) { if (tp_touch_active(tp, t)) active_touches++; + if (t->is_thumb) + thumb_mask |= 1 << i; + i++; + } + + old_thumb_mask = tp->gesture.thumb_mask; + tp->gesture.thumb_mask = thumb_mask; + + /* active touches does not include thumb touches, need to count those + * separately, in a bitmask. + * then, if the finger count changes and/or the thumb count changes + * -> cancel gesture. + */ + if (thumb_mask != old_thumb_mask) { + /* if a thumb is detected during a gesture, that gesture is + * cancelled and the user effectively needs to restart. we + * could be smarter, but the complexity isn't worth it */ + tp_gesture_cancel(tp, time); + return; + } + if (active_touches != tp->gesture.finger_count) { /* If all fingers are lifted immediately end the gesture */ if (active_touches == 0) { diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index 7f241de5..a43e235e 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -691,7 +691,20 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) tp->queued & TOUCHPAD_EVENT_BUTTON_PRESS) t->tap.state = TAP_TOUCH_STATE_DEAD; + /* If a touch was considered thumb for tapping once, we + * ignore it for the rest of lifetime */ + if (t->tap.is_thumb) + continue; + if (t->state == TOUCH_BEGIN) { + /* The simple version: if a touch is a thumb on + * begin we ignore it. All other thumb touches + * follow the normal tap state for now */ + if (t->is_thumb) { + t->tap.is_thumb = true; + continue; + } + t->tap.state = TAP_TOUCH_STATE_TOUCH; t->tap.initial = t->point; tp_tap_handle_event(tp, t, TAP_EVENT_TOUCH, time); diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index d3bb6434..3f5dabac 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -212,6 +212,8 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->millis = time; tp->nfingers_down++; t->palm.time = time; + t->is_thumb = false; + t->tap.is_thumb = false; assert(tp->nfingers_down >= 1); } @@ -314,6 +316,9 @@ tp_process_absolute(struct tp_dispatch *tp, else tp_end_sequence(tp, t, time); break; + case ABS_MT_PRESSURE: + t->pressure = e->value; + break; } } @@ -461,6 +466,7 @@ tp_touch_active(struct tp_dispatch *tp, struct tp_touch *t) return (t->state == TOUCH_BEGIN || t->state == TOUCH_UPDATE) && t->palm.state == PALM_NONE && !t->pinned.is_pinned && + !t->is_thumb && tp_button_touch_active(tp, t) && tp_edge_scroll_touch_active(tp, t); } @@ -602,6 +608,33 @@ out: t->palm.state == PALM_TYPING ? "typing" : "trackpoint"); } +static void +tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t) +{ + /* once a thumb, always a thumb */ + if (!tp->thumb.detect_thumbs || t->is_thumb) + return; + + /* Note: a thumb at the edge of the touchpad won't trigger the + * threshold, the surface areas is usually too small. + */ + if (t->pressure < tp->thumb.threshold) + return; + + t->is_thumb = true; + + /* now what? we marked it as thumb, so: + * + * - pointer motion must ignore this touch + * - clickfinger must ignore this touch for finger count + * - software buttons are unaffected + * - edge scrolling unaffected + * - gestures: cancel + * - tapping: honour thumb on begin, ignore it otherwise for now, + * this gets a tad complicated otherwise + */ +} + static void tp_unhover_abs_distance(struct tp_dispatch *tp, uint64_t time) { @@ -720,6 +753,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) if (!t->dirty) continue; + tp_thumb_detect(tp, t); tp_palm_detect(tp, t, time); tp_motion_hysteresis(tp, t); @@ -1476,6 +1510,30 @@ tp_init_sendevents(struct tp_dispatch *tp, return 0; } +static int +tp_init_thumb(struct tp_dispatch *tp) +{ + struct evdev_device *device = tp->device; + const struct input_absinfo *abs; + + abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE); + if (!abs) + return 0; + + if (abs->maximum - abs->minimum < 255) + return 0; + + /* The touchpads we looked at so far have a clear thumb threshold of + * ~100, you don't reach that with a normal finger interaction. + * Note: "thumb" means massive touch that should not interact, not + * "using the tip of my thumb for a pinch gestures". + */ + tp->thumb.threshold = 100; + tp->thumb.detect_thumbs = true; + + return 0; +} + static int tp_sanity_check(struct tp_dispatch *tp, struct evdev_device *device) @@ -1558,6 +1616,9 @@ tp_init(struct tp_dispatch *tp, if (tp_init_gesture(tp) != 0) return -1; + if (tp_init_thumb(tp) != 0) + return -1; + device->seat_caps |= EVDEV_DEVICE_POINTER; return 0; diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index df8be94f..eda17a99 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -141,9 +141,11 @@ struct tp_touch { enum touch_state state; bool has_ended; /* TRACKING_ID == -1 */ bool dirty; + bool is_thumb; struct device_coords point; uint64_t millis; int distance; /* distance == 0 means touch */ + int pressure; struct { struct device_coords samples[TOUCHPAD_HISTORY_LENGTH]; @@ -173,6 +175,7 @@ struct tp_touch { struct { enum tp_tap_touch_state state; struct device_coords initial; + bool is_thumb; } tap; struct { @@ -234,6 +237,7 @@ struct tp_dispatch { double prev_scale; double angle; struct device_float_coords center; + uint32_t thumb_mask; } gesture; struct { @@ -317,6 +321,11 @@ struct tp_dispatch { uint64_t keyboard_last_press_time; } dwt; + + struct { + bool detect_thumbs; + int threshold; + } thumb; }; #define tp_for_each_touch(_tp, _t) \ From 4a463ca70228eaf0d3b676b6d7392b3cd5eb8f00 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 6 Jul 2015 15:22:45 +1000 Subject: [PATCH 08/29] touchpad: work thumb detection into the tap state machine Most thumbs are detected a few events into the sequence. Work this into parts of the tapping state machine. Only the most common use-case is handled here - if the first finger ends up being marked as a thumb, we return to the idle state and ignore that touch sequence. At any other state, we handle thumbs like any other finger. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/touchpad-tap-state-machine.svg | 18 ++++++++++++ src/evdev-mt-touchpad-tap.c | 47 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/doc/touchpad-tap-state-machine.svg b/doc/touchpad-tap-state-machine.svg index 89c34fa0..b1c5995b 100644 --- a/doc/touchpad-tap-state-machine.svg +++ b/doc/touchpad-tap-state-machine.svg @@ -1179,5 +1179,23 @@ [Not supported by viewer] + + + + thumb + + + + + + + TOUCH_DEAD + + + + + + + diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index a43e235e..9bbf6b88 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -47,6 +47,7 @@ enum tap_event { TAP_EVENT_RELEASE, TAP_EVENT_BUTTON, TAP_EVENT_TIMEOUT, + TAP_EVENT_THUMB, }; /***************************************** @@ -93,6 +94,7 @@ tap_event_to_str(enum tap_event event) CASE_RETURN_STRING(TAP_EVENT_RELEASE); CASE_RETURN_STRING(TAP_EVENT_TIMEOUT); CASE_RETURN_STRING(TAP_EVENT_BUTTON); + CASE_RETURN_STRING(TAP_EVENT_THUMB); } return NULL; } @@ -166,6 +168,10 @@ tp_tap_idle_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + log_bug_libinput(libinput, + "invalid tap event, no fingers down, no thumb\n"); + break; } } @@ -193,6 +199,12 @@ tp_tap_touch_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + tp->tap.state = TAP_STATE_IDLE; + t->tap.is_thumb = true; + t->tap.state = TAP_TOUCH_STATE_DEAD; + tp_tap_clear_timer(tp); + break; } } @@ -216,6 +228,11 @@ tp_tap_hold_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + tp->tap.state = TAP_STATE_IDLE; + t->tap.is_thumb = true; + t->tap.state = TAP_TOUCH_STATE_DEAD; + break; } } @@ -244,6 +261,8 @@ tp_tap_tapped_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -275,6 +294,8 @@ tp_tap_touch2_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + break; } } @@ -299,6 +320,8 @@ tp_tap_touch2_hold_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + break; } } @@ -328,6 +351,8 @@ tp_tap_touch3_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + break; } } @@ -351,6 +376,8 @@ tp_tap_touch3_hold_handle_event(struct tp_dispatch *tp, case TAP_EVENT_BUTTON: tp->tap.state = TAP_STATE_DEAD; break; + case TAP_EVENT_THUMB: + break; } } @@ -375,6 +402,8 @@ tp_tap_dragging_or_doubletap_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -408,6 +437,8 @@ tp_tap_dragging_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -433,6 +464,8 @@ tp_tap_dragging_wait_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -459,6 +492,8 @@ tp_tap_dragging_tap_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -484,6 +519,8 @@ tp_tap_dragging2_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_DEAD; tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); break; + case TAP_EVENT_THUMB: + break; } } @@ -518,6 +555,8 @@ tp_tap_multitap_handle_event(struct tp_dispatch *tp, tp->tap.state = TAP_STATE_IDLE; tp_tap_clear_timer(tp); break; + case TAP_EVENT_THUMB: + break; } } @@ -556,6 +595,8 @@ tp_tap_multitap_down_handle_event(struct tp_dispatch *tp, tp_tap_notify(tp, time, 1, LIBINPUT_BUTTON_STATE_RELEASED); tp_tap_clear_timer(tp); break; + case TAP_EVENT_THUMB: + break; } } @@ -576,6 +617,8 @@ tp_tap_dead_handle_event(struct tp_dispatch *tp, case TAP_EVENT_TIMEOUT: case TAP_EVENT_BUTTON: break; + case TAP_EVENT_THUMB: + break; } } @@ -731,6 +774,10 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time) } tp_tap_handle_event(tp, t, TAP_EVENT_MOTION, time); + } else if (tp->tap.state != TAP_STATE_IDLE && + t->is_thumb && + !t->tap.is_thumb) { + tp_tap_handle_event(tp, t, TAP_EVENT_THUMB, time); } } From cc59c8986f5d561c40c9edf746403cc69da66913 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 6 Jul 2015 16:41:41 +1000 Subject: [PATCH 09/29] test: add touchpad thumb detection tests Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/touchpad.c | 389 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index 4aa9f4e6..0b7b718b 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3745,6 +3745,384 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt) } END_TEST +static int +has_thumb_detect(struct litest_device *dev) +{ + return libevdev_has_event_code(dev->evdev, EV_ABS, ABS_MT_PRESSURE); +} + +START_TEST(touchpad_thumb_begin_no_motion) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_disable_tap(dev->libinput_device); + + litest_drain_events(li); + + litest_touch_down_extended(dev, 0, 50, 50, axes); + litest_touch_move_to(dev, 0, 50, 50, 80, 50, 10, 0); + litest_touch_up(dev, 0); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_thumb_update_no_motion) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + litest_disable_tap(dev->libinput_device); + + if (!has_thumb_detect(dev)) + return; + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 60, 50, 10, 0); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); + + litest_touch_move_extended(dev, 0, 65, 50, axes); + litest_touch_move_to(dev, 0, 65, 50, 80, 50, 10, 0); + litest_touch_up(dev, 0); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_thumb_clickfinger) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_disable_tap(dev->libinput_device); + + libinput_device_config_click_set_method(dev->libinput_device, + LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 60, 50); + litest_touch_move_extended(dev, 0, 55, 50, axes); + litest_button_click(dev, BTN_LEFT, true); + + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + + litest_assert_empty_queue(li); + + litest_button_click(dev, BTN_LEFT, false); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_down(dev, 1, 60, 50); + litest_touch_move_extended(dev, 1, 65, 50, axes); + litest_button_click(dev, BTN_LEFT, true); + + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_thumb_btnarea) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_disable_tap(dev->libinput_device); + + libinput_device_config_click_set_method(dev->libinput_device, + LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 90, 95); + litest_touch_move_extended(dev, 0, 95, 95, axes); + litest_button_click(dev, BTN_LEFT, true); + + /* button areas work as usual with a thumb */ + + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_RIGHT, + LIBINPUT_BUTTON_STATE_PRESSED); + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + + litest_assert_empty_queue(li); +} +END_TEST + +START_TEST(touchpad_thumb_edgescroll) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + enable_edge_scroll(dev); + litest_disable_tap(dev->libinput_device); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 99, 30); + litest_touch_move_to(dev, 0, 99, 30, 99, 50, 10, 0); + litest_drain_events(li); + + litest_touch_move_extended(dev, 0, 99, 55, axes); + libinput_dispatch(li); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); + + litest_touch_move_to(dev, 0, 99, 55, 99, 70, 10, 0); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); +} +END_TEST + +START_TEST(touchpad_thumb_tap_begin) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_drain_events(li); + + /* touch down is a thumb */ + litest_touch_down_extended(dev, 0, 50, 50, axes); + litest_touch_up(dev, 0); + litest_timeout_tap(); + + litest_assert_empty_queue(li); + + /* make sure normal tap still works */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); +} +END_TEST + +START_TEST(touchpad_thumb_tap_touch) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_drain_events(li); + + /* event after touch down is thumb */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_extended(dev, 0, 51, 50, axes); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_empty_queue(li); + + /* make sure normal tap still works */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); +} +END_TEST + +START_TEST(touchpad_thumb_tap_hold) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_drain_events(li); + + /* event in state HOLD is thumb */ + litest_touch_down(dev, 0, 50, 50); + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_move_extended(dev, 0, 51, 50, axes); + litest_touch_up(dev, 0); + litest_assert_empty_queue(li); + + /* make sure normal tap still works */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); +} +END_TEST + +START_TEST(touchpad_thumb_tap_hold_2ndfg) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_drain_events(li); + + /* event in state HOLD is thumb */ + litest_touch_down(dev, 0, 50, 50); + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_move_extended(dev, 0, 51, 50, axes); + + litest_assert_empty_queue(li); + + /* one finger is a thumb, now get second finger down */ + litest_touch_down(dev, 1, 60, 50); + litest_assert_empty_queue(li); + + /* release thumb */ + litest_touch_up(dev, 0); + litest_assert_empty_queue(li); + + /* timeout -> into HOLD, no event on release */ + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_up(dev, 1); + litest_assert_empty_queue(li); + + /* make sure normal tap still works */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); +} +END_TEST + +START_TEST(touchpad_thumb_tap_hold_2ndfg_tap) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + struct axis_replacement axes[] = { + { ABS_MT_PRESSURE, 100 }, + { -1, 0 } + }; + + if (!has_thumb_detect(dev)) + return; + + litest_enable_tap(dev->libinput_device); + litest_drain_events(li); + + /* event in state HOLD is thumb */ + litest_touch_down(dev, 0, 50, 50); + litest_timeout_tap(); + libinput_dispatch(li); + litest_touch_move_extended(dev, 0, 51, 50, axes); + + litest_assert_empty_queue(li); + + /* one finger is a thumb, now get second finger down */ + litest_touch_down(dev, 1, 60, 50); + litest_assert_empty_queue(li); + + /* release thumb */ + litest_touch_up(dev, 0); + litest_assert_empty_queue(li); + + /* release second finger, within timeout, ergo event */ + litest_touch_up(dev, 1); + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_PRESSED); + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + + litest_timeout_tap(); + libinput_dispatch(li); + event = libinput_get_event(li); + ptrev = litest_is_button_event(event, + BTN_LEFT, + LIBINPUT_BUTTON_STATE_RELEASED); + libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + + /* make sure normal tap still works */ + litest_touch_down(dev, 0, 50, 50); + litest_touch_up(dev, 0); + litest_timeout_tap(); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); +} +END_TEST + void litest_setup_tests(void) { @@ -3863,4 +4241,15 @@ litest_setup_tests(void) litest_add("touchpad:dwt", touchpad_dwt_click, LITEST_TOUCHPAD, LITEST_ANY); litest_add("touchpad:dwt", touchpad_dwt_edge_scroll, LITEST_TOUCHPAD, LITEST_CLICKPAD); litest_add("touchpad:dwt", touchpad_dwt_edge_scroll_interrupt, LITEST_TOUCHPAD, LITEST_CLICKPAD); + + litest_add("touchpad:thumb", touchpad_thumb_begin_no_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_update_no_motion, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_clickfinger, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_btnarea, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_edgescroll, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_tap_begin, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_tap_touch, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_tap_hold, LITEST_TOUCHPAD, LITEST_ANY); + litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); + litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); } From 4e3944375779e7fb0fc960d6079d186b09540fca Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 1 Jul 2015 10:17:48 +1000 Subject: [PATCH 10/29] udev: make sure the udev callout path is valid for a test run udev requires callout binaries to sit in /lib/udev or otherwise provide an absolute path. The test suite should work without installing everything first, so create two rule files - one to install, one with the path to the $builddir/test Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- configure.ac | 10 +++++++++- test/Makefile.am | 2 +- udev/.gitignore | 1 + ...oups.rules => 80-libinput-device-groups.rules.in} | 2 +- ...uirks.rules => 90-libinput-model-quirks.rules.in} | 0 udev/Makefile.am | 12 ++++++++++++ 6 files changed, 24 insertions(+), 3 deletions(-) rename udev/{80-libinput-device-groups.rules => 80-libinput-device-groups.rules.in} (77%) rename udev/{90-libinput-model-quirks.rules => 90-libinput-model-quirks.rules.in} (100%) diff --git a/configure.ac b/configure.ac index 978bbeaf..9b425840 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,12 @@ AM_CONDITIONAL(HAVE_VALGRIND, [test "x$VALGRIND" != "x"]) AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes"]) AM_CONDITIONAL(BUILD_DOCS, [test "x$build_documentation" = "xyes"]) +# Used by the udev rules so we can use callouts during testing without +# installing everything first. Default is the empty string so the installed +# rule will use udev's default path. Override is in udev/Makefile.am +AC_SUBST(UDEV_TEST_PATH, "") +AC_PATH_PROG(SED, [sed]) + AC_CONFIG_FILES([Makefile doc/Makefile doc/libinput.doxygen @@ -192,7 +198,9 @@ AC_CONFIG_FILES([Makefile src/libinput-version.h test/Makefile tools/Makefile - udev/Makefile]) + udev/Makefile + udev/80-libinput-device-groups.rules + udev/90-libinput-model-quirks.rules]) AC_CONFIG_FILES([test/symbols-leak-test], [chmod +x test/symbols-leak-test]) AC_OUTPUT diff --git a/test/Makefile.am b/test/Makefile.am index 3580e8aa..457c2971 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -43,7 +43,7 @@ liblitest_la_SOURCES = \ litest.c liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la liblitest_la_CFLAGS = $(AM_CFLAGS) \ - -DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.rules\"" \ + -DLIBINPUT_UDEV_RULES_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks-litest.rules\"" \ -DLIBINPUT_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" if HAVE_LIBUNWIND liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl diff --git a/udev/.gitignore b/udev/.gitignore index d8e1456b..72c77a0f 100644 --- a/udev/.gitignore +++ b/udev/.gitignore @@ -1 +1,2 @@ libinput-device-group +*.rules diff --git a/udev/80-libinput-device-groups.rules b/udev/80-libinput-device-groups.rules.in similarity index 77% rename from udev/80-libinput-device-groups.rules rename to udev/80-libinput-device-groups.rules.in index f826bec6..c2af0ce7 100644 --- a/udev/80-libinput-device-groups.rules +++ b/udev/80-libinput-device-groups.rules.in @@ -2,7 +2,7 @@ ACTION!="add|change", GOTO="libinput_device_group_end" KERNEL!="event[0-9]*", GOTO="libinput_device_group_end" ATTRS{phys}=="?*", \ - PROGRAM="libinput-device-group %S%p", \ + PROGRAM="@UDEV_TEST_PATH@libinput-device-group %S%p", \ ENV{LIBINPUT_DEVICE_GROUP}="%c" LABEL="libinput_device_group_end" diff --git a/udev/90-libinput-model-quirks.rules b/udev/90-libinput-model-quirks.rules.in similarity index 100% rename from udev/90-libinput-model-quirks.rules rename to udev/90-libinput-model-quirks.rules.in diff --git a/udev/Makefile.am b/udev/Makefile.am index 7d19809d..e5cf95c4 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -1,6 +1,10 @@ udevdir=$(UDEV_DIR) udev_PROGRAMS = libinput-device-group +litest_rules = 80-libinput-device-groups-litest.rules \ + 90-libinput-model-quirks-litest.rules +udev_SCRIPTS = $(litest_rules) + libinput_device_group_SOURCES = libinput-device-group.c libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS) libinput_device_group_LDADD = $(LIBUDEV_LIBS) @@ -13,3 +17,11 @@ dist_udev_rules_DATA = \ udev_hwdbdir=$(UDEV_DIR)/hwdb.d dist_udev_hwdb_DATA = \ 90-libinput-model-quirks.hwdb + +%-litest.rules: %.rules.in + $(SED) -e "s|\@UDEV_TEST_PATH\@|$(abs_builddir)/|" < $^ > $@ + +CLEANFILES = $(litest_rules) +DISTCLEANFILES = \ + 80-libinput-device-groups.rules \ + 90-libinput-model-quirks.rules From 6e8dc031ba9a0a3c71b29c5bca82fde2fc839857 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 12:07:16 +1000 Subject: [PATCH 11/29] evdev: simplify setting a fake resolution The only two callers passed in the fake resolution anyway, so we don't need extra parameters here. We don't allow devices with only x or y resolution set, either both or none. And we can use libevdev_set_abs_resolution() rather than handling absinfo structs. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev.c | 55 ++++++++++++----------------------------------------- 1 file changed, 12 insertions(+), 43 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 12617245..29bed728 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1551,19 +1551,16 @@ evdev_read_model(struct evdev_device *device) return m->model; } -/* Return 1 if the given resolutions have been set, or 0 otherwise */ +/* Return 1 if the device is set to the fake resolution or 0 otherwise */ static inline int evdev_fix_abs_resolution(struct evdev_device *device, unsigned int xcode, - unsigned int ycode, - int xresolution, - int yresolution) + unsigned int ycode) { 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; + int xres = EVDEV_FAKE_RESOLUTION, + yres = EVDEV_FAKE_RESOLUTION; if (!(xcode == ABS_X && ycode == ABS_Y) && !(xcode == ABS_MT_POSITION_X && ycode == ABS_MT_POSITION_Y)) { @@ -1573,37 +1570,15 @@ evdev_fix_abs_resolution(struct evdev_device *device, 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); + if (libevdev_get_abs_resolution(evdev, xcode) != 0) return 0; - } - absx = libevdev_get_abs_info(evdev, xcode); - absy = libevdev_get_abs_info(evdev, ycode); + /* libevdev_set_abs_resolution() changes the absinfo we already + have a pointer to, no need to fetch it again */ + libevdev_set_abs_resolution(evdev, xcode, xres); + libevdev_set_abs_resolution(evdev, ycode, yres); - 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; + return 1; } static enum evdev_device_udev_tags @@ -1774,9 +1749,7 @@ evdev_configure_mt_device(struct evdev_device *device) if (evdev_fix_abs_resolution(device, ABS_MT_POSITION_X, - ABS_MT_POSITION_Y, - EVDEV_FAKE_RESOLUTION, - EVDEV_FAKE_RESOLUTION)) + ABS_MT_POSITION_Y)) device->abs.fake_resolution = 1; device->abs.absinfo_x = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); @@ -1900,11 +1873,7 @@ evdev_configure_device(struct evdev_device *device) evdev_fix_android_mt(device); if (libevdev_has_event_code(evdev, EV_ABS, ABS_X)) { - if (evdev_fix_abs_resolution(device, - ABS_X, - ABS_Y, - EVDEV_FAKE_RESOLUTION, - EVDEV_FAKE_RESOLUTION)) + if (evdev_fix_abs_resolution(device, ABS_X, ABS_Y)) 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); From cc46e00e8192bdc95c16e2636d3073b39bdd2c37 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 9 Jul 2015 16:46:00 +1000 Subject: [PATCH 12/29] test: fix memleak in the udev_device_sysname() test If a device sends other events at startup, those events weren't freed. This can happen on tablet devices that send proximity events immediately after DEVICE_ADDED. Signed-off-by: Peter Hutterer --- test/udev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/udev.c b/test/udev.c index b077311a..30ae1180 100644 --- a/test/udev.c +++ b/test/udev.c @@ -413,8 +413,11 @@ START_TEST(udev_device_sysname) libinput_dispatch(li); while ((ev = libinput_get_event(li))) { - if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED) + if (libinput_event_get_type(ev) != + LIBINPUT_EVENT_DEVICE_ADDED) { + libinput_event_destroy(ev); continue; + } device = libinput_event_get_device(ev); sysname = libinput_device_get_sysname(device); From 3734a67eefcf7c6e40b7edfe14f85e91315bc7a3 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 11:26:18 +1000 Subject: [PATCH 13/29] test: slow down 2fg slow scroll movement To avoid test case failures when we switch to forced resolutions. Signed-off-by: Peter Hutterer --- test/touchpad.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 0b7b718b..80490c21 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1365,7 +1365,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance) 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_move_two_touches(dev, 49, 50, 51, 50, 0, y_move, 100, 10); litest_touch_up(dev, 1); litest_touch_up(dev, 0); libinput_dispatch(li); @@ -1634,7 +1634,7 @@ START_TEST(touchpad_edge_scroll_timeout) litest_timeout_edgescroll(); libinput_dispatch(li); - litest_touch_move_to(dev, 0, 99, 20, 99, 20 + y_movement, 60, 10); + litest_touch_move_to(dev, 0, 99, 20, 99, 20 + y_movement, 100, 10); litest_touch_up(dev, 0); libinput_dispatch(li); From 3b419fb17e32d97c92be78083883334063b09482 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 13:08:38 +1000 Subject: [PATCH 14/29] test: replace hardcoded wacom ID with the #define Signed-off-by: Peter Hutterer --- test/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/device.c b/test/device.c index 3f61f08c..24d59590 100644 --- a/test/device.c +++ b/test/device.c @@ -89,7 +89,7 @@ START_TEST(device_sendevents_config_touchpad_superset) uint32_t modes; /* The wacom devices in the test suite are external */ - if (libevdev_get_id_vendor(dev->evdev) == 0x56a) /* wacom */ + if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM) return; device = dev->libinput_device; From fa67be9e3cb46cb896f750ce80acdd99091073b6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 12:39:35 +1000 Subject: [PATCH 15/29] test: reduce movement of finger while pinned Otherwise the test fails on large touchpads with resolution (magic trackpad). Signed-off-by: Peter Hutterer --- test/touchpad.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 80490c21..96254119 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -685,9 +685,9 @@ START_TEST(clickpad_finger_pin) litest_button_click(dev, BTN_LEFT, true); litest_drain_events(li); - litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1); - litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1); - litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1); + litest_touch_move_to(dev, 0, 50, 50, 51, 51, 10, 1); + litest_touch_move_to(dev, 0, 51, 51, 49, 49, 10, 1); + litest_touch_move_to(dev, 0, 49, 49, 50, 50, 10, 1); litest_assert_empty_queue(li); @@ -695,9 +695,9 @@ START_TEST(clickpad_finger_pin) litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); /* still pinned after release */ - litest_touch_move_to(dev, 0, 50, 50, 52, 52, 10, 1); - litest_touch_move_to(dev, 0, 52, 52, 48, 48, 10, 1); - litest_touch_move_to(dev, 0, 48, 48, 50, 50, 10, 1); + litest_touch_move_to(dev, 0, 50, 50, 51, 51, 10, 1); + litest_touch_move_to(dev, 0, 51, 51, 49, 49, 10, 1); + litest_touch_move_to(dev, 0, 49, 49, 50, 50, 10, 1); litest_assert_empty_queue(li); From 74a8d6546ea3b0fa31d263bbdfe86a105532e9a2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 12:41:59 +1000 Subject: [PATCH 16/29] test: move finger position to test for right button down On large touchpads with resolution, 90% of the touchpad may be north of the button. Signed-off-by: Peter Hutterer --- test/touchpad.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 96254119..d3452118 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -422,7 +422,7 @@ START_TEST(touchpad_clickfinger_to_area_method) enable_buttonareas(dev); - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); @@ -440,7 +440,7 @@ START_TEST(touchpad_clickfinger_to_area_method) litest_drain_events(li); /* use bottom right corner to catch accidental softbutton right */ - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); @@ -465,7 +465,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down) enable_buttonareas(dev); - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); @@ -485,7 +485,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down) litest_drain_events(li); /* use bottom right corner to catch accidental softbutton right */ - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); @@ -511,7 +511,7 @@ START_TEST(touchpad_area_to_clickfinger_method) litest_drain_events(li); /* use bottom right corner to catch accidental softbutton right */ - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); @@ -526,7 +526,7 @@ START_TEST(touchpad_area_to_clickfinger_method) enable_buttonareas(dev); - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); @@ -552,7 +552,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down) litest_drain_events(li); /* use bottom right corner to catch accidental softbutton right */ - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_assert_button_event(li, BTN_LEFT, @@ -568,7 +568,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down) litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); - litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); litest_event(dev, EV_SYN, SYN_REPORT, 0); litest_event(dev, EV_KEY, BTN_LEFT, 0); From 55435a707f1f252539cd17ecf497dce6bd72a94c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 12:01:15 +1000 Subject: [PATCH 17/29] test: add an Apple Magic Trackpad test device Signed-off-by: Peter Hutterer --- test/Makefile.am | 1 + test/device.c | 6 +- test/litest-magic-trackpad.c | 110 +++++++++++++++++++++++++++++++++++ test/litest.c | 2 + test/litest.h | 1 + test/touchpad.c | 2 + 6 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 test/litest-magic-trackpad.c diff --git a/test/Makefile.am b/test/Makefile.am index 457c2971..d3c573a4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -22,6 +22,7 @@ liblitest_la_SOURCES = \ litest-keyboard-razer-blackwidow.c \ litest-logitech-trackball.c \ litest-nexus4-touch-screen.c \ + litest-magic-trackpad.c \ litest-mouse.c \ litest-mouse-roccat.c \ litest-mouse-low-dpi.c \ diff --git a/test/device.c b/test/device.c index 24d59590..f43228c6 100644 --- a/test/device.c +++ b/test/device.c @@ -70,7 +70,8 @@ START_TEST(device_sendevents_config_touchpad) expected = LIBINPUT_CONFIG_SEND_EVENTS_DISABLED; /* The wacom devices in the test suite are external */ - if (libevdev_get_id_vendor(dev->evdev) != VENDOR_ID_WACOM) + if (libevdev_get_id_vendor(dev->evdev) != VENDOR_ID_WACOM && + libevdev_get_id_bustype(dev->evdev) != BUS_BLUETOOTH) expected |= LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE; @@ -89,7 +90,8 @@ START_TEST(device_sendevents_config_touchpad_superset) uint32_t modes; /* The wacom devices in the test suite are external */ - if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM) + if (libevdev_get_id_vendor(dev->evdev) == VENDOR_ID_WACOM || + libevdev_get_id_bustype(dev->evdev) == BUS_BLUETOOTH) return; device = dev->libinput_device; diff --git a/test/litest-magic-trackpad.c b/test/litest-magic-trackpad.c new file mode 100644 index 00000000..588d6f5a --- /dev/null +++ b/test/litest-magic-trackpad.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "litest.h" +#include "litest-int.h" + +static void litest_magicpad_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_MAGIC_TRACKPAD); + litest_set_current_device(d); +} + +static struct input_event down[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 272 }, + { .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 400 }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct input_event move[] = { + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TOUCH_MAJOR, .value = 272 }, + { .type = EV_ABS, .code = ABS_MT_TOUCH_MINOR, .value = 400 }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct litest_device_interface interface = { + .touch_down_events = down, + .touch_move_events = move, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, -2909, 3167, 4, 0, 46 }, + { ABS_Y, -2456, 2565, 4, 0, 45 }, + { ABS_MT_SLOT, 0, 15, 0, 0, 0 }, + { ABS_MT_POSITION_X, -2909, 3167, 4, 0, 46 }, + { ABS_MT_POSITION_Y, -2456, 2565, 4, 0, 45 }, + { ABS_MT_ORIENTATION, -31, 32, 1, 0, 0 }, + { ABS_MT_TOUCH_MAJOR, 0, 1020, 4, 0, 0 }, + { ABS_MT_TOUCH_MINOR, 0, 1020, 4, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 }, + { .value = -1 }, +}; + +static struct input_id input_id = { + .bustype = 0x5, + .vendor = 0x5ac, + .product = 0x30e, +}; + +static int events[] = { + EV_KEY, BTN_LEFT, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOOL_QUINTTAP, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_TOOL_DOUBLETAP, + EV_KEY, BTN_TOOL_TRIPLETAP, + EV_KEY, BTN_TOOL_QUADTAP, + INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD, + -1, -1 +}; + +struct litest_test_device litest_magicpad_device = { + .type = LITEST_MAGIC_TRACKPAD, + .features = LITEST_TOUCHPAD | LITEST_CLICKPAD | + LITEST_BUTTON | LITEST_APPLE_CLICKPAD, + .shortname = "magic trackpad", + .setup = litest_magicpad_setup, + .interface = &interface, + + .name = "Apple Wireless Trackpad", + .id = &input_id, + .events = events, + .absinfo = absinfo, +}; diff --git a/test/litest.c b/test/litest.c index 8cde52fe..8d63d64d 100644 --- a/test/litest.c +++ b/test/litest.c @@ -356,6 +356,7 @@ extern struct litest_test_device litest_alps_dualpoint_device; extern struct litest_test_device litest_mouse_low_dpi_device; extern struct litest_test_device litest_generic_multitouch_screen_device; extern struct litest_test_device litest_nexus4_device; +extern struct litest_test_device litest_magicpad_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -385,6 +386,7 @@ struct litest_test_device* devices[] = { &litest_mouse_low_dpi_device, &litest_generic_multitouch_screen_device, &litest_nexus4_device, + &litest_magicpad_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 8981f13d..6c69090e 100644 --- a/test/litest.h +++ b/test/litest.h @@ -140,6 +140,7 @@ enum litest_device_type { LITEST_MOUSE_LOW_DPI = -26, LITEST_GENERIC_MULTITOUCH_SCREEN = -27, LITEST_NEXUS4_TOUCH_SCREEN = -28, + LITEST_MAGIC_TRACKPAD = -29, }; enum litest_device_feature { diff --git a/test/touchpad.c b/test/touchpad.c index d3452118..78c084e1 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3331,6 +3331,8 @@ has_disable_while_typing(struct litest_device *device) { if (libevdev_get_id_vendor(device->evdev) == VENDOR_ID_WACOM) return false; + if (libevdev_get_id_bustype(device->evdev) == BUS_BLUETOOTH) + return false; return true; } From 5c76e6f47fbcea0bfb9c194595ffb831c8f0b2fb Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 14:06:11 +1000 Subject: [PATCH 18/29] test: prefix all test device files with litest-device Signed-off-by: Peter Hutterer --- test/Makefile.am | 56 +++++++++---------- ...point.c => litest-device-alps-dualpoint.c} | 0 ...semi-mt.c => litest-device-alps-semi-mt.c} | 0 ...el-hover.c => litest-device-atmel-hover.c} | 0 ...test-bcm5974.c => litest-device-bcm5974.c} | 0 ....c => litest-device-generic-singletouch.c} | 0 ...litest-device-keyboard-razer-blackwidow.c} | 0 ...st-keyboard.c => litest-device-keyboard.c} | 0 ...l.c => litest-device-logitech-trackball.c} | 0 ...ckpad.c => litest-device-magic-trackpad.c} | 0 ...ow-dpi.c => litest-device-mouse-low-dpi.c} | 0 ...-roccat.c => litest-device-mouse-roccat.c} | 0 .../{litest-mouse.c => litest-device-mouse.c} | 0 ...ver.c => litest-device-ms-surface-cover.c} | 0 ....c => litest-device-nexus4-touch-screen.c} | 0 ...> litest-device-protocol-a-touch-screen.c} | 0 ...blet.c => litest-device-qemu-usb-tablet.c} | 0 ...over.c => litest-device-synaptics-hover.c} | 0 ...tics-st.c => litest-device-synaptics-st.c} | 0 ...-t440.c => litest-device-synaptics-t440.c} | 0 ...> litest-device-synaptics-x1-carbon-3rd.c} | 0 ...-synaptics.c => litest-device-synaptics.c} | 0 ...-screen.c => litest-device-touch-screen.c} | 0 ...rackpoint.c => litest-device-trackpoint.c} | 0 ... litest-device-vmware-virtual-usb-mouse.c} | 0 ....c => litest-device-wacom-intuos-finger.c} | 0 ...om-touch.c => litest-device-wacom-touch.c} | 0 ...heel-only.c => litest-device-wheel-only.c} | 0 ....c => litest-device-xen-virtual-pointer.c} | 0 29 files changed, 28 insertions(+), 28 deletions(-) rename test/{litest-alps-dualpoint.c => litest-device-alps-dualpoint.c} (100%) rename test/{litest-alps-semi-mt.c => litest-device-alps-semi-mt.c} (100%) rename test/{litest-atmel-hover.c => litest-device-atmel-hover.c} (100%) rename test/{litest-bcm5974.c => litest-device-bcm5974.c} (100%) rename test/{litest-generic-singletouch.c => litest-device-generic-singletouch.c} (100%) rename test/{litest-keyboard-razer-blackwidow.c => litest-device-keyboard-razer-blackwidow.c} (100%) rename test/{litest-keyboard.c => litest-device-keyboard.c} (100%) rename test/{litest-logitech-trackball.c => litest-device-logitech-trackball.c} (100%) rename test/{litest-magic-trackpad.c => litest-device-magic-trackpad.c} (100%) rename test/{litest-mouse-low-dpi.c => litest-device-mouse-low-dpi.c} (100%) rename test/{litest-mouse-roccat.c => litest-device-mouse-roccat.c} (100%) rename test/{litest-mouse.c => litest-device-mouse.c} (100%) rename test/{litest-ms-surface-cover.c => litest-device-ms-surface-cover.c} (100%) rename test/{litest-nexus4-touch-screen.c => litest-device-nexus4-touch-screen.c} (100%) rename test/{litest-protocol-a-touch-screen.c => litest-device-protocol-a-touch-screen.c} (100%) rename test/{litest-qemu-usb-tablet.c => litest-device-qemu-usb-tablet.c} (100%) rename test/{litest-synaptics-hover.c => litest-device-synaptics-hover.c} (100%) rename test/{litest-synaptics-st.c => litest-device-synaptics-st.c} (100%) rename test/{litest-synaptics-t440.c => litest-device-synaptics-t440.c} (100%) rename test/{litest-synaptics-x1-carbon-3rd.c => litest-device-synaptics-x1-carbon-3rd.c} (100%) rename test/{litest-synaptics.c => litest-device-synaptics.c} (100%) rename test/{litest-touch-screen.c => litest-device-touch-screen.c} (100%) rename test/{litest-trackpoint.c => litest-device-trackpoint.c} (100%) rename test/{litest-vmware-virtual-usb-mouse.c => litest-device-vmware-virtual-usb-mouse.c} (100%) rename test/{litest-wacom-intuos-finger.c => litest-device-wacom-intuos-finger.c} (100%) rename test/{litest-wacom-touch.c => litest-device-wacom-touch.c} (100%) rename test/{litest-wheel-only.c => litest-device-wheel-only.c} (100%) rename test/{litest-xen-virtual-pointer.c => litest-device-xen-virtual-pointer.c} (100%) diff --git a/test/Makefile.am b/test/Makefile.am index d3c573a4..df62a172 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,34 +13,34 @@ noinst_LTLIBRARIES = liblitest.la liblitest_la_SOURCES = \ litest.h \ litest-int.h \ - litest-alps-semi-mt.c \ - litest-alps-dualpoint.c \ - litest-atmel-hover.c \ - litest-bcm5974.c \ - litest-generic-singletouch.c \ - litest-keyboard.c \ - litest-keyboard-razer-blackwidow.c \ - litest-logitech-trackball.c \ - litest-nexus4-touch-screen.c \ - litest-magic-trackpad.c \ - litest-mouse.c \ - litest-mouse-roccat.c \ - litest-mouse-low-dpi.c \ - litest-ms-surface-cover.c \ - litest-protocol-a-touch-screen.c \ - litest-qemu-usb-tablet.c \ - litest-synaptics.c \ - litest-synaptics-hover.c \ - litest-synaptics-st.c \ - litest-synaptics-t440.c \ - litest-synaptics-x1-carbon-3rd.c \ - litest-trackpoint.c \ - litest-touch-screen.c \ - litest-wacom-touch.c \ - litest-wacom-intuos-finger.c \ - litest-wheel-only.c \ - litest-xen-virtual-pointer.c \ - litest-vmware-virtual-usb-mouse.c \ + litest-device-alps-semi-mt.c \ + litest-device-alps-dualpoint.c \ + litest-device-atmel-hover.c \ + litest-device-bcm5974.c \ + litest-device-generic-singletouch.c \ + litest-device-keyboard.c \ + litest-device-keyboard-razer-blackwidow.c \ + litest-device-logitech-trackball.c \ + litest-device-nexus4-touch-screen.c \ + litest-device-magic-trackpad.c \ + litest-device-mouse.c \ + litest-device-mouse-roccat.c \ + litest-device-mouse-low-dpi.c \ + litest-device-ms-surface-cover.c \ + litest-device-protocol-a-touch-screen.c \ + litest-device-qemu-usb-tablet.c \ + litest-device-synaptics.c \ + litest-device-synaptics-hover.c \ + litest-device-synaptics-st.c \ + litest-device-synaptics-t440.c \ + litest-device-synaptics-x1-carbon-3rd.c \ + litest-device-trackpoint.c \ + litest-device-touch-screen.c \ + litest-device-wacom-touch.c \ + litest-device-wacom-intuos-finger.c \ + litest-device-wheel-only.c \ + litest-device-xen-virtual-pointer.c \ + litest-device-vmware-virtual-usb-mouse.c \ litest.c liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la liblitest_la_CFLAGS = $(AM_CFLAGS) \ diff --git a/test/litest-alps-dualpoint.c b/test/litest-device-alps-dualpoint.c similarity index 100% rename from test/litest-alps-dualpoint.c rename to test/litest-device-alps-dualpoint.c diff --git a/test/litest-alps-semi-mt.c b/test/litest-device-alps-semi-mt.c similarity index 100% rename from test/litest-alps-semi-mt.c rename to test/litest-device-alps-semi-mt.c diff --git a/test/litest-atmel-hover.c b/test/litest-device-atmel-hover.c similarity index 100% rename from test/litest-atmel-hover.c rename to test/litest-device-atmel-hover.c diff --git a/test/litest-bcm5974.c b/test/litest-device-bcm5974.c similarity index 100% rename from test/litest-bcm5974.c rename to test/litest-device-bcm5974.c diff --git a/test/litest-generic-singletouch.c b/test/litest-device-generic-singletouch.c similarity index 100% rename from test/litest-generic-singletouch.c rename to test/litest-device-generic-singletouch.c diff --git a/test/litest-keyboard-razer-blackwidow.c b/test/litest-device-keyboard-razer-blackwidow.c similarity index 100% rename from test/litest-keyboard-razer-blackwidow.c rename to test/litest-device-keyboard-razer-blackwidow.c diff --git a/test/litest-keyboard.c b/test/litest-device-keyboard.c similarity index 100% rename from test/litest-keyboard.c rename to test/litest-device-keyboard.c diff --git a/test/litest-logitech-trackball.c b/test/litest-device-logitech-trackball.c similarity index 100% rename from test/litest-logitech-trackball.c rename to test/litest-device-logitech-trackball.c diff --git a/test/litest-magic-trackpad.c b/test/litest-device-magic-trackpad.c similarity index 100% rename from test/litest-magic-trackpad.c rename to test/litest-device-magic-trackpad.c diff --git a/test/litest-mouse-low-dpi.c b/test/litest-device-mouse-low-dpi.c similarity index 100% rename from test/litest-mouse-low-dpi.c rename to test/litest-device-mouse-low-dpi.c diff --git a/test/litest-mouse-roccat.c b/test/litest-device-mouse-roccat.c similarity index 100% rename from test/litest-mouse-roccat.c rename to test/litest-device-mouse-roccat.c diff --git a/test/litest-mouse.c b/test/litest-device-mouse.c similarity index 100% rename from test/litest-mouse.c rename to test/litest-device-mouse.c diff --git a/test/litest-ms-surface-cover.c b/test/litest-device-ms-surface-cover.c similarity index 100% rename from test/litest-ms-surface-cover.c rename to test/litest-device-ms-surface-cover.c diff --git a/test/litest-nexus4-touch-screen.c b/test/litest-device-nexus4-touch-screen.c similarity index 100% rename from test/litest-nexus4-touch-screen.c rename to test/litest-device-nexus4-touch-screen.c diff --git a/test/litest-protocol-a-touch-screen.c b/test/litest-device-protocol-a-touch-screen.c similarity index 100% rename from test/litest-protocol-a-touch-screen.c rename to test/litest-device-protocol-a-touch-screen.c diff --git a/test/litest-qemu-usb-tablet.c b/test/litest-device-qemu-usb-tablet.c similarity index 100% rename from test/litest-qemu-usb-tablet.c rename to test/litest-device-qemu-usb-tablet.c diff --git a/test/litest-synaptics-hover.c b/test/litest-device-synaptics-hover.c similarity index 100% rename from test/litest-synaptics-hover.c rename to test/litest-device-synaptics-hover.c diff --git a/test/litest-synaptics-st.c b/test/litest-device-synaptics-st.c similarity index 100% rename from test/litest-synaptics-st.c rename to test/litest-device-synaptics-st.c diff --git a/test/litest-synaptics-t440.c b/test/litest-device-synaptics-t440.c similarity index 100% rename from test/litest-synaptics-t440.c rename to test/litest-device-synaptics-t440.c diff --git a/test/litest-synaptics-x1-carbon-3rd.c b/test/litest-device-synaptics-x1-carbon-3rd.c similarity index 100% rename from test/litest-synaptics-x1-carbon-3rd.c rename to test/litest-device-synaptics-x1-carbon-3rd.c diff --git a/test/litest-synaptics.c b/test/litest-device-synaptics.c similarity index 100% rename from test/litest-synaptics.c rename to test/litest-device-synaptics.c diff --git a/test/litest-touch-screen.c b/test/litest-device-touch-screen.c similarity index 100% rename from test/litest-touch-screen.c rename to test/litest-device-touch-screen.c diff --git a/test/litest-trackpoint.c b/test/litest-device-trackpoint.c similarity index 100% rename from test/litest-trackpoint.c rename to test/litest-device-trackpoint.c diff --git a/test/litest-vmware-virtual-usb-mouse.c b/test/litest-device-vmware-virtual-usb-mouse.c similarity index 100% rename from test/litest-vmware-virtual-usb-mouse.c rename to test/litest-device-vmware-virtual-usb-mouse.c diff --git a/test/litest-wacom-intuos-finger.c b/test/litest-device-wacom-intuos-finger.c similarity index 100% rename from test/litest-wacom-intuos-finger.c rename to test/litest-device-wacom-intuos-finger.c diff --git a/test/litest-wacom-touch.c b/test/litest-device-wacom-touch.c similarity index 100% rename from test/litest-wacom-touch.c rename to test/litest-device-wacom-touch.c diff --git a/test/litest-wheel-only.c b/test/litest-device-wheel-only.c similarity index 100% rename from test/litest-wheel-only.c rename to test/litest-device-wheel-only.c diff --git a/test/litest-xen-virtual-pointer.c b/test/litest-device-xen-virtual-pointer.c similarity index 100% rename from test/litest-xen-virtual-pointer.c rename to test/litest-device-xen-virtual-pointer.c From cbaa79cfdbeb5d52bb96311d87e549cdafd50a93 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 14:11:11 +1000 Subject: [PATCH 19/29] test: add an Elantech touchpad device This is an old recording and predates properties. It's not a clickpad, we assume INPUT_PROP_POINTER is set. From: https://bugs.freedesktop.org/attachment.cgi?id=57154 Signed-off-by: Peter Hutterer --- test/Makefile.am | 1 + test/litest-device-elantech-touchpad.c | 121 +++++++++++++++++++++++++ test/litest.c | 2 + test/litest.h | 1 + 4 files changed, 125 insertions(+) create mode 100644 test/litest-device-elantech-touchpad.c diff --git a/test/Makefile.am b/test/Makefile.am index df62a172..49b3b021 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -17,6 +17,7 @@ liblitest_la_SOURCES = \ litest-device-alps-dualpoint.c \ litest-device-atmel-hover.c \ litest-device-bcm5974.c \ + litest-device-elantech-touchpad.c \ litest-device-generic-singletouch.c \ litest-device-keyboard.c \ litest-device-keyboard-razer-blackwidow.c \ diff --git a/test/litest-device-elantech-touchpad.c b/test/litest-device-elantech-touchpad.c new file mode 100644 index 00000000..abf58d1c --- /dev/null +++ b/test/litest-device-elantech-touchpad.c @@ -0,0 +1,121 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "litest.h" +#include "litest-int.h" + +static void +litest_elantech_touchpad_setup(void) +{ + struct litest_device *d = litest_create_device(LITEST_ELANTECH_TOUCHPAD); + litest_set_current_device(d); +} + +static struct input_event down[] = { + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static struct input_event move[] = { + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_PRESSURE, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = LITEST_AUTO_ASSIGN }, + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 }, + { .type = -1, .code = -1 }, +}; + +static int +get_axis_default(struct litest_device *d, unsigned int evcode, int32_t *value) +{ + switch (evcode) { + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + *value = 30; + return 0; + } + return 1; +} + +static struct litest_device_interface interface = { + .touch_down_events = down, + .touch_move_events = move, + + .get_axis_default = get_axis_default, +}; + +static struct input_id input_id = { + .bustype = 0x11, + .vendor = 0x2, + .product = 0xe, +}; + +static int events[] = { + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_KEY, BTN_TOOL_FINGER, + EV_KEY, BTN_TOUCH, + EV_KEY, BTN_TOOL_DOUBLETAP, + EV_KEY, BTN_TOOL_TRIPLETAP, + EV_KEY, BTN_TOOL_QUADTAP, + INPUT_PROP_MAX, INPUT_PROP_POINTER, + -1, -1, +}; + +static struct input_absinfo absinfo[] = { + { ABS_X, 0, 1280, 0, 0, 0 }, + { ABS_Y, 0, 704, 0, 0, 0 }, + { ABS_PRESSURE, 0, 255, 0, 0, 0 }, + { ABS_TOOL_WIDTH, 0, 15, 0, 0, 0 }, + { ABS_MT_SLOT, 0, 1, 0, 0, 0 }, + { ABS_MT_POSITION_X, 0, 1280, 0, 0, 0 }, + { ABS_MT_POSITION_Y, 0, 704, 0, 0, 0 }, + { ABS_MT_TRACKING_ID, 0, 65535, 0, 0, 0 }, + { .value = -1 } +}; + +struct litest_test_device litest_elantech_touchpad_device = { + .type = LITEST_ELANTECH_TOUCHPAD, + .features = LITEST_TOUCHPAD | LITEST_BUTTON, + .shortname = "elantech", + .setup = litest_elantech_touchpad_setup, + .interface = &interface, + + .name = "ETPS/2 Elantech Touchpad", + .id = &input_id, + .events = events, + .absinfo = absinfo, +}; diff --git a/test/litest.c b/test/litest.c index 8d63d64d..4dbe7817 100644 --- a/test/litest.c +++ b/test/litest.c @@ -357,6 +357,7 @@ extern struct litest_test_device litest_mouse_low_dpi_device; extern struct litest_test_device litest_generic_multitouch_screen_device; extern struct litest_test_device litest_nexus4_device; extern struct litest_test_device litest_magicpad_device; +extern struct litest_test_device litest_elantech_touchpad_device; struct litest_test_device* devices[] = { &litest_synaptics_clickpad_device, @@ -387,6 +388,7 @@ struct litest_test_device* devices[] = { &litest_generic_multitouch_screen_device, &litest_nexus4_device, &litest_magicpad_device, + &litest_elantech_touchpad_device, NULL, }; diff --git a/test/litest.h b/test/litest.h index 6c69090e..d557b5dc 100644 --- a/test/litest.h +++ b/test/litest.h @@ -141,6 +141,7 @@ enum litest_device_type { LITEST_GENERIC_MULTITOUCH_SCREEN = -27, LITEST_NEXUS4_TOUCH_SCREEN = -28, LITEST_MAGIC_TRACKPAD = -29, + LITEST_ELANTECH_TOUCHPAD = -30, }; enum litest_device_feature { From aab4ccac5c517542ff53807a9c23fb2d62aa9188 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 10 Jul 2015 15:03:42 +1000 Subject: [PATCH 20/29] touchpad: add gesture state debug helper Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad-gestures.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 81bbd4d7..768d3ec3 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -32,6 +32,20 @@ #define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ #define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT 1000 /* ms */ +#define CASE_RETURN_STRING(a) case a: return #a + +static inline const char* +gesture_state_to_str(enum tp_gesture_2fg_state state) +{ + switch (state) { + CASE_RETURN_STRING(GESTURE_2FG_STATE_NONE); + CASE_RETURN_STRING(GESTURE_2FG_STATE_UNKNOWN); + CASE_RETURN_STRING(GESTURE_2FG_STATE_SCROLL); + CASE_RETURN_STRING(GESTURE_2FG_STATE_PINCH); + } + return NULL; +} + static struct normalized_coords tp_get_touches_delta(struct tp_dispatch *tp, bool average) { @@ -380,6 +394,8 @@ tp_gesture_twofinger_handle_state_pinch(struct tp_dispatch *tp, uint64_t time) static void tp_gesture_post_twofinger(struct tp_dispatch *tp, uint64_t time) { + enum tp_gesture_2fg_state oldstate = tp->gesture.twofinger_state; + if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_NONE) tp->gesture.twofinger_state = tp_gesture_twofinger_handle_state_none(tp, time); @@ -395,6 +411,11 @@ tp_gesture_post_twofinger(struct tp_dispatch *tp, uint64_t time) if (tp->gesture.twofinger_state == GESTURE_2FG_STATE_PINCH) tp->gesture.twofinger_state = tp_gesture_twofinger_handle_state_pinch(tp, time); + + log_debug(tp_libinput_context(tp), + "gesture state: %s → %s\n", + gesture_state_to_str(oldstate), + gesture_state_to_str(tp->gesture.twofinger_state)); } static void From c7498a969856bea8ef944e4e8697cf3bde1e31a2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 13 Jul 2015 11:06:05 +1000 Subject: [PATCH 21/29] touchpad: drop obsolete comment Comment is obsolete now that we have edge scrolling on clickpads, see abff4a1c24830931f1cbd5e54d5b1a4621eab863 Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad-edge-scroll.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 4d5f47af..ade55e03 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -305,8 +305,7 @@ tp_edge_scroll_init(struct tp_dispatch *tp, struct evdev_device *device) default: /* For elantech and synaptics, note for lenovo #40 series, * e.g. the T440s min/max are the absolute edges, not the - * recommended ones as usual with synaptics. But these are - * clickpads, so N/A. + * recommended ones as usual with synaptics. */ edge_width = width * .04; edge_height = height * .054; From 35fb5412c5a481f6c045f628241d34c5c970f052 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 13 Jul 2015 15:39:13 +1000 Subject: [PATCH 22/29] test: remove some excessive linebreaks Signed-off-by: Peter Hutterer --- test/touchpad.c | 60 +++++++++++++++++-------------------------------- 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/test/touchpad.c b/test/touchpad.c index 78c084e1..12bceea3 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -1767,22 +1767,18 @@ START_TEST(touchpad_edge_scroll_into_buttonareas) litest_touch_down(dev, 0, 99, 40); litest_touch_move_to(dev, 0, 99, 40, 99, 95, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* in the button zone now, make sure we still get events */ litest_touch_move_to(dev, 0, 99, 95, 99, 100, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* and out of the zone again */ litest_touch_move_to(dev, 0, 99, 100, 99, 70, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* still out of the zone */ litest_touch_move_to(dev, 0, 99, 70, 99, 50, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); } END_TEST @@ -1799,18 +1795,15 @@ START_TEST(touchpad_edge_scroll_within_buttonareas) /* within left button */ litest_touch_move_to(dev, 0, 20, 99, 40, 99, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* over to right button */ litest_touch_move_to(dev, 0, 40, 99, 60, 99, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); /* within right button */ litest_touch_move_to(dev, 0, 60, 99, 80, 99, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); } END_TEST @@ -1828,8 +1821,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) litest_touch_down(dev, 0, 20, 95); litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_button_click(dev, BTN_LEFT, true); libinput_dispatch(li); @@ -1856,8 +1848,7 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) litest_button_click(dev, BTN_LEFT, false); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_BUTTON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); litest_touch_up(dev, 0); } @@ -1877,8 +1868,7 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) litest_touch_down(dev, 0, 20, 95); litest_touch_move_to(dev, 0, 20, 95, 70, 95, 10, 5); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_button_click(dev, BTN_LEFT, true); libinput_dispatch(li); @@ -1901,14 +1891,12 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) /* clickfinger releases pointer -> expect movement */ litest_touch_move_to(dev, 0, 70, 95, 90, 95, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); litest_assert_empty_queue(li); litest_button_click(dev, BTN_LEFT, false); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_BUTTON); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); litest_touch_up(dev, 0); } @@ -2715,8 +2703,7 @@ START_TEST(touchpad_semi_mt_hover_down_up) y -= 100; } - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); litest_event(dev, EV_ABS, ABS_MT_SLOT, 0); litest_event(dev, EV_ABS, ABS_MT_TRACKING_ID, -1); @@ -2855,8 +2842,7 @@ START_TEST(touchpad_hover_down) libinput_dispatch(li); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); /* go back to hover */ litest_hover_move_to(dev, 0, 50, 50, 70, 70, 10, 10); @@ -2899,8 +2885,7 @@ START_TEST(touchpad_hover_down_hover_down) litest_touch_move_to(dev, 0, 50, 50, 70, 70, 10, 10); litest_touch_up(dev, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); } END_TEST @@ -2934,8 +2919,7 @@ START_TEST(touchpad_hover_down_up) litest_touch_up(dev, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); } END_TEST @@ -2989,8 +2973,7 @@ START_TEST(touchpad_hover_2fg_1fg_down) litest_touch_up(dev, 1); litest_pop_event_frame(dev);; - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_MOTION); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_MOTION); } END_TEST @@ -3074,8 +3057,7 @@ START_TEST(touchpad_trackpoint_mb_scroll) litest_event(trackpoint, EV_SYN, SYN_REPORT, 0); litest_button_click(touchpad, BTN_2, false); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_delete_device(trackpoint); } @@ -3204,8 +3186,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) litest_touch_move_to(touchpad, 0, 40, 30, 40, 70, 10, 0); litest_touch_move_to(touchpad, 1, 60, 30, 60, 70, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); while ((e = libinput_get_event(li))) { ck_assert_int_eq(libinput_event_get_type(e), @@ -3230,8 +3211,7 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll) */ litest_touch_move_to(touchpad, 0, 40, 70, 40, 60, 10, 0); litest_touch_move_to(touchpad, 1, 60, 70, 60, 60, 10, 0); - litest_assert_only_typed_events(li, - LIBINPUT_EVENT_POINTER_AXIS); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); litest_touch_move_to(touchpad, 0, 40, 60, 40, 30, 10, 0); litest_touch_move_to(touchpad, 1, 60, 60, 60, 30, 10, 0); From 5bebd4aea487203dedca985e7c8333261bdb677f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 12:00:53 +1000 Subject: [PATCH 23/29] util: add a helper function to parse a "WIDTHxHEIGHT" property Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/libinput-util.c | 30 +++++++++++++++++++++++++++++ src/libinput-util.h | 2 ++ test/misc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/src/libinput-util.c b/src/libinput-util.c index 3a9c8db5..a383fa17 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -234,3 +234,33 @@ parse_trackpoint_accel_property(const char *prop) return accel; } + +/** + * Parses a simple dimension string in the form of "10x40". The two + * numbers must be positive integers in decimal notation. + * On success, the two numbers are stored in w and h. On failure, w and h + * are unmodified. + * + * @param prop The value of the property + * @param w Returns the first component of the dimension + * @param h Returns the second component of the dimension + * @return true on success, false otherwise + */ +bool +parse_dimension_property(const char *prop, size_t *w, size_t *h) +{ + int x, y; + + if (!prop) + return false; + + if (sscanf(prop, "%dx%d", &x, &y) != 2) + return false; + + if (x < 0 || y < 0) + return false; + + *w = (size_t)x; + *h = (size_t)y; + return true; +} diff --git a/src/libinput-util.h b/src/libinput-util.h index 00c93fe0..f27bcfd4 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -296,6 +297,7 @@ 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); double parse_trackpoint_accel_property(const char *prop); +bool parse_dimension_property(const char *prop, size_t *width, size_t *height); static inline double vector_length(double x, double y) diff --git a/test/misc.c b/test/misc.c index 0cffa227..2a2a63a8 100644 --- a/test/misc.c +++ b/test/misc.c @@ -584,6 +584,52 @@ START_TEST(trackpoint_accel_parser) } END_TEST +struct parser_test_dimension { + char *tag; + bool success; + int x, y; +}; + +START_TEST(dimension_prop_parser) +{ + struct parser_test_dimension tests[] = { + { "10x10", true, 10, 10 }, + { "1x20", true, 1, 20 }, + { "1x8000", true, 1, 8000 }, + { "238492x428210", true, 238492, 428210 }, + { "0x0", true, 0, 0 }, + { "-10x10", false, 0, 0 }, + { "-1", false, 0, 0 }, + { "1x-99", false, 0, 0 }, + { "0", false, 0, 0 }, + { "100", false, 0, 0 }, + { "", false, 0, 0 }, + { "abd", false, 0, 0 }, + { "xabd", false, 0, 0 }, + { "0xaf", false, 0, 0 }, + { "0x0x", true, 0, 0 }, + { "x10", false, 0, 0 }, + { NULL, false, 0, 0 } + }; + int i; + size_t x, y; + bool success; + + for (i = 0; tests[i].tag != NULL; i++) { + x = y = 0xad; + success = parse_dimension_property(tests[i].tag, &x, &y); + ck_assert(success == tests[i].success); + if (success) { + ck_assert_int_eq(x, tests[i].x); + ck_assert_int_eq(y, tests[i].y); + } else { + ck_assert_int_eq(x, 0xad); + ck_assert_int_eq(y, 0xad); + } + } +} +END_TEST + void litest_setup_tests(void) { @@ -602,4 +648,5 @@ litest_setup_tests(void) litest_add_no_device("misc:parser", dpi_parser); litest_add_no_device("misc:parser", wheel_click_parser); litest_add_no_device("misc:parser", trackpoint_accel_parser); + litest_add_no_device("misc:parser", dimension_prop_parser); } From a4f5abd18e4e6c98d4c467016bbe9b13a8a8b05d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 12:15:12 +1000 Subject: [PATCH 24/29] evdev: use LIBINPUT_ATTR_SIZE_HINT for resolutions Touchpads, notably Elantech, ALPS and bcm5974 don't provide x/y resolution until recent generations. Add a new property, LIBINPUT_ATTR_SIZE_HINT, that provides size information to libinput. Note that this property *does not* override true resolution values, it is only used when the resolution is missing. It is used merely as an approximate size hint. If the resolution for a specific device is known it should be added to the udev hwdb so it can be set globally. See the bcm5974 entries here: http://cgit.freedesktop.org/systemd/systemd/tree/hwdb/60-evdev.hwdb. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/device-configuration-via-udev.dox | 14 +++++++---- src/evdev.c | 36 +++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/doc/device-configuration-via-udev.dox b/doc/device-configuration-via-udev.dox index e38b93f6..85c5c9c9 100644 --- a/doc/device-configuration-via-udev.dox +++ b/doc/device-configuration-via-udev.dox @@ -67,6 +67,10 @@ to normalize them.
This prefix is reserved as private API, do not use.. See @ref model_specific_configuration for details.
+
LIBINPUT_ATTR_*
+
This prefix is reserved as private API, do not use.. See @ref +model_specific_configuration for details. +
Below is an example udev rule to assign "seat1" to a device from vendor @@ -103,13 +107,13 @@ ENV{ID_MODEL_ID}=="034b", ENV{ID_INPUT_TOUCHPAD}="", ENV{ID_INPUT_TABLET}="1" @section model_specific_configuration Model-specific configuration -libinput reserves the property prefix LIBINPUT_MODEL_ for -model-specific configuration. This prefix is reserved as private API, do -not use. +libinput reserves the property prefixes LIBINPUT_MODEL_ and +LIBINPUT_ATTR_* for model-specific configuration. These prefixes +are reserved as private API, do not use. -The effect of this property may be to enable or disable certain +The effect of these properties may be to enable or disable certain features on a specific device or set of devices, to change configuration -defaults or any other reason. The effects of setting this property, the +defaults or any other reason. The effects of setting these properties, the format of the property and the value of the property are subject to change at any time. diff --git a/src/evdev.c b/src/evdev.c index 29bed728..3d19ee73 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1551,6 +1551,23 @@ evdev_read_model(struct evdev_device *device) return m->model; } +static inline int +evdev_read_attr_size_prop(struct evdev_device *device, + size_t *size_x, + size_t *size_y) +{ + struct udev_device *udev; + const char *size_prop; + + udev = device->udev_device; + size_prop = udev_device_get_property_value(udev, + "LIBINPUT_ATTR_SIZE_HINT"); + if (!size_prop) + return false; + + return parse_dimension_property(size_prop, size_x, size_y); +} + /* Return 1 if the device is set to the fake resolution or 0 otherwise */ static inline int evdev_fix_abs_resolution(struct evdev_device *device, @@ -1559,6 +1576,8 @@ evdev_fix_abs_resolution(struct evdev_device *device, { struct libinput *libinput = device->base.seat->libinput; struct libevdev *evdev = device->evdev; + const struct input_absinfo *absx, *absy; + size_t widthmm = 0, heightmm = 0; int xres = EVDEV_FAKE_RESOLUTION, yres = EVDEV_FAKE_RESOLUTION; @@ -1570,15 +1589,28 @@ evdev_fix_abs_resolution(struct evdev_device *device, return 0; } - if (libevdev_get_abs_resolution(evdev, xcode) != 0) + absx = libevdev_get_abs_info(evdev, xcode); + absy = libevdev_get_abs_info(evdev, ycode); + + if (absx->resolution != 0 || absy->resolution != 0) return 0; + /* Note: we *do not* override resolutions if provided by the kernel. + * If a device needs this, add it to 60-evdev.hwdb. The libinput + * property is only for general size hints where we can make + * educated guesses but don't know better. + */ + if (evdev_read_attr_size_prop(device, &widthmm, &heightmm)) { + xres = (absx->maximum - absx->minimum)/widthmm; + yres = (absy->maximum - absy->minimum)/heightmm; + } + /* libevdev_set_abs_resolution() changes the absinfo we already have a pointer to, no need to fetch it again */ libevdev_set_abs_resolution(evdev, xcode, xres); libevdev_set_abs_resolution(evdev, ycode, yres); - return 1; + return xres == EVDEV_FAKE_RESOLUTION; } static enum evdev_device_udev_tags From b06a1be01322f17e98b69a3633f0efc7b862e429 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 9 Jul 2015 13:47:52 +1000 Subject: [PATCH 25/29] udev: add a model-quirks callout Some model-specific information isn't available through udev properties. This callout is used to query the device directly and set a property that we can then match on for the hwdb entries. This is geared for Elantech and ALPS touchpads where the firmware version is the interesting bit. The udev rule is added already to match on that, note that the callout doesn't do anything at this point. The various touchpad-related things will be added separately. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- udev/.gitignore | 1 + udev/90-libinput-model-quirks.hwdb | 2 +- udev/90-libinput-model-quirks.rules.in | 14 ++++ udev/Makefile.am | 10 ++- udev/libinput-model-quirks.c | 90 ++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 udev/libinput-model-quirks.c diff --git a/udev/.gitignore b/udev/.gitignore index 72c77a0f..2fdaedcf 100644 --- a/udev/.gitignore +++ b/udev/.gitignore @@ -1,2 +1,3 @@ libinput-device-group +libinput-model-quirks *.rules diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index cf57e9c9..fd9efa81 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -11,7 +11,7 @@ # Match string formats: # libinput: # libinput:name::dmi: - +# libinput:name::fwversion: # # Sort by brand, model diff --git a/udev/90-libinput-model-quirks.rules.in b/udev/90-libinput-model-quirks.rules.in index 43674f55..d8341558 100644 --- a/udev/90-libinput-model-quirks.rules.in +++ b/udev/90-libinput-model-quirks.rules.in @@ -11,6 +11,20 @@ ACTION!="add|change", GOTO="libinput_model_quirks_end" KERNEL!="event*", GOTO="libinput_model_quirks_end" +# Touchpad firmware detection, two-stage process. +# First, run the program and import the LIBINPUT_MODEL_FIRMWARE_VERSION +# environment (if any) +KERNELS=="*input*", \ + ENV{ID_INPUT_TOUCHPAD}=="1", \ + IMPORT{program}="@UDEV_TEST_PATH@libinput-model-quirks %S%p" + +# Second, match on anything with that env set and import from the hwdb +KERNELS=="*input*", \ + ENV{ID_INPUT_TOUCHPAD}=="1", \ + ENV{LIBINPUT_MODEL_FIRMWARE_VERSION}!="", \ + IMPORT{builtin}="hwdb 'libinput:name:$attr{name}:fwversion:$env{LIBINPUT_MODEL_FIRMWARE_VERSION}'" +# End of touchpad firmware detection + # Matches below are exclusive, if one matches we skip the rest # hwdb matches: # diff --git a/udev/Makefile.am b/udev/Makefile.am index e5cf95c4..e850e09c 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -1,5 +1,6 @@ udevdir=$(UDEV_DIR) -udev_PROGRAMS = libinput-device-group +udev_PROGRAMS = libinput-device-group \ + libinput-model-quirks litest_rules = 80-libinput-device-groups-litest.rules \ 90-libinput-model-quirks-litest.rules @@ -9,6 +10,13 @@ libinput_device_group_SOURCES = libinput-device-group.c libinput_device_group_CFLAGS = $(LIBUDEV_CFLAGS) $(GCC_CFLAGS) libinput_device_group_LDADD = $(LIBUDEV_LIBS) +libinput_model_quirks_SOURCES = libinput-model-quirks.c +libinput_model_quirks_CFLAGS = \ + -I$(top_srcdir)/src \ + $(LIBUDEV_CFLAGS) \ + $(GCC_CFLAGS) +libinput_model_quirks_LDADD = $(LIBUDEV_LIBS) + udev_rulesdir=$(UDEV_DIR)/rules.d dist_udev_rules_DATA = \ 80-libinput-device-groups.rules \ diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c new file mode 100644 index 00000000..3c51a378 --- /dev/null +++ b/udev/libinput-model-quirks.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2015 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "libinput-util.h" + +static inline const char * +prop_value(struct udev_device *device, + const char *prop_name) +{ + struct udev_device *parent; + const char *prop_value = NULL; + + parent = device; + while (parent && !prop_value) { + prop_value = udev_device_get_property_value(parent, prop_name); + parent = udev_device_get_parent(parent); + } + + return prop_value; +} + +static void +handle_touchpad(struct udev_device *device) +{ +} + +int main(int argc, char **argv) +{ + int rc = 1; + struct udev *udev = NULL; + struct udev_device *device = NULL; + const char *syspath; + + if (argc != 2) + return 1; + + syspath = argv[1]; + + udev = udev_new(); + if (!udev) + goto out; + + device = udev_device_new_from_syspath(udev, syspath); + if (!device) + goto out; + + if (udev_device_get_property_value(device, "ID_INPUT_TOUCHPAD")) + handle_touchpad(device); + + rc = 0; + +out: + if (device) + udev_device_unref(device); + if (udev) + udev_unref(udev); + + return rc; +} From a74dcf965a86251aed75420a0308b337e2fdbd7f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 13:00:10 +1000 Subject: [PATCH 26/29] udev: add ALPS firmware detection and size properties Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- udev/90-libinput-model-quirks.hwdb | 4 ++++ udev/libinput-model-quirks.c | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index fd9efa81..129f567f 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -22,6 +22,10 @@ libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:dmi:* libinput:name:*AlpsPS/2 ALPS GlidePoint:dmi:* LIBINPUT_MODEL_ALPS_TOUCHPAD=1 +libinput:name:*AlpsPS/2 ALPS DualPoint TouchPad:fwversion:8 +libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:8 + LIBINPUT_ATTR_SIZE_HINT=100x55 + ########################################## # Apple ########################################## diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c index 3c51a378..fc3dbe85 100644 --- a/udev/libinput-model-quirks.c +++ b/udev/libinput-model-quirks.c @@ -50,9 +50,35 @@ prop_value(struct udev_device *device, return prop_value; } +static void +handle_touchpad_alps(struct udev_device *device) +{ + const char *product; + int bus, vid, pid, version; + + product = prop_value(device, "PRODUCT"); + if (!product) + return; + + if (sscanf(product, "%x/%x/%x/%x", &bus, &vid, &pid, &version) != 4) + return; + + /* ALPS' firmware version is the PID */ + if (pid) + printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%d\n", pid); +} + static void handle_touchpad(struct udev_device *device) { + const char *name = NULL; + + name = prop_value(device, "NAME"); + if (!name) + return; + + if (strstr(name, "AlpsPS/2 ALPS") != NULL) + handle_touchpad_alps(device); } int main(int argc, char **argv) From fcd7af86e214a4a3054f2ba930203ea3a323e947 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 13:03:56 +1000 Subject: [PATCH 27/29] udev: add size hint for apple touchpads Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- udev/90-libinput-model-quirks.hwdb | 1 + 1 file changed, 1 insertion(+) diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index 129f567f..730b115a 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -32,6 +32,7 @@ libinput:name:*AlpsPS/2 ALPS GlidePoint:fwversion:8 libinput:touchpad:input:b0003v05ACp* libinput:touchpad:input:b0005v05ACp* LIBINPUT_MODEL_APPLE_TOUCHPAD=1 + LIBINPUT_ATTR_SIZE_HINT=104x75 ########################################## # Google From 3bbcffe488b0095c711cab6025da5fa0d826fd94 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 14:26:11 +1000 Subject: [PATCH 28/29] touchpad: default to a 69x50mm sized touchpad The previous approach of using the axis ranges and approximating parameters based on the x/y axis range clutters up the code and is generally unreliable. If we look at Synaptics touchpads, the resolution ranges from 42 to 130 while the axes stay the same axis range. Other touchpads likely have a similar variation across the various models. Let's make this simpler in code: unless we know otherwise, simply assume a default-sized touchpad. Anything that deviates from that can be fixed with the new hwdb entries to provide a more correct setting. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 3f5dabac..11fc03b8 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1558,6 +1558,43 @@ error: return -1; } +static int +tp_init_default_resolution(struct tp_dispatch *tp, + struct evdev_device *device) +{ + const int touchpad_width_mm = 69, /* 1 under palm detection */ + touchpad_height_mm = 50; + int xres, yres; + + if (!device->abs.fake_resolution) + return 0 ; + + /* we only get here if + * - the touchpad provides no resolution + * - the udev hwdb didn't override the resoluion + * - no ATTR_SIZE_HINT is set + * + * The majority of touchpads that triggers all these conditions + * are old ones, so let's assume a small touchpad size and assume + * that. + */ + log_info(tp_libinput_context(tp), + "%s: no resolution or size hints, assuming a size of %dx%dmm\n", + device->devname, + touchpad_width_mm, + touchpad_height_mm); + + xres = device->abs.dimensions.x/touchpad_width_mm; + yres = device->abs.dimensions.y/touchpad_height_mm; + libevdev_set_abs_resolution(device->evdev, ABS_X, xres); + libevdev_set_abs_resolution(device->evdev, ABS_Y, yres); + libevdev_set_abs_resolution(device->evdev, ABS_MT_POSITION_X, xres); + libevdev_set_abs_resolution(device->evdev, ABS_MT_POSITION_Y, yres); + device->abs.fake_resolution = 0; + + return 0; +} + static int tp_init(struct tp_dispatch *tp, struct evdev_device *device) @@ -1571,6 +1608,9 @@ tp_init(struct tp_dispatch *tp, if (tp_sanity_check(tp, device) != 0) return -1; + if (tp_init_default_resolution(tp, device) != 0) + return -1; + if (tp_init_slots(tp, device) != 0) return -1; From 8658ff159d416b6a567acb2aaf72b27887ad8576 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 30 Jun 2015 20:56:03 +1000 Subject: [PATCH 29/29] touchpad: drop fake resolution handling Now that we have all devices init a fixed resolution we don't need code to handle custom cases anymore. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 49 ++++++--------------------------- src/evdev-mt-touchpad.c | 30 +++++--------------- 2 files changed, 16 insertions(+), 63 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 9542d874..d9c469a4 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -525,20 +525,19 @@ tp_init_softbuttons(struct tp_dispatch *tp, absinfo_y = device->abs.absinfo_y; xoffset = absinfo_x->minimum, - yoffset = absinfo_y->minimum; + yoffset = absinfo_y->minimum, yres = absinfo_y->resolution; width = device->abs.dimensions.x; height = device->abs.dimensions.y; - /* button height: 10mm or 15% of the touchpad height, + /* button height: 10mm or 15% orf the touchpad height, whichever is smaller */ - if (!device->abs.fake_resolution && (height * 0.15/yres) > 10) { + if ((height * 0.15)/yres > 10) { tp->buttons.bottom_area.top_edge = - absinfo_y->maximum - 10 * yres; + absinfo_y->maximum - 10 * yres; } else { tp->buttons.bottom_area.top_edge = height * .85 + yoffset; } - tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset; } @@ -547,7 +546,7 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, struct evdev_device *device, double topbutton_size_mult) { - int width, height; + int width; const struct input_absinfo *absinfo_x, *absinfo_y; int xoffset, yoffset; int yres; @@ -559,7 +558,6 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, yoffset = absinfo_y->minimum; yres = absinfo_y->resolution; width = device->abs.dimensions.x; - height = device->abs.dimensions.y; if (tp->buttons.has_topbuttons) { /* T440s has the top button line 5mm from the top, event @@ -567,14 +565,8 @@ tp_init_top_softbuttons(struct tp_dispatch *tp, top - which maps to 15%. We allow the caller to enlarge the area using a multiplier for the touchpad disabled case. */ double topsize_mm = 10 * topbutton_size_mult; - double topsize_pct = .15 * topbutton_size_mult; - if (!device->abs.fake_resolution) { - tp->buttons.top_area.bottom_edge = - yoffset + topsize_mm * yres; - } else { - tp->buttons.top_area.bottom_edge = height * topsize_pct + yoffset; - } + tp->buttons.top_area.bottom_edge = yoffset + topsize_mm * yres; tp->buttons.top_area.rightbutton_left_edge = width * .58 + xoffset; tp->buttons.top_area.leftbutton_right_edge = width * .42 + xoffset; } else { @@ -713,8 +705,6 @@ tp_init_buttons(struct tp_dispatch *tp, { struct libinput *libinput = tp_libinput_context(tp); struct tp_touch *t; - int width, height; - double diagonal; const struct input_absinfo *absinfo_x, *absinfo_y; tp->buttons.is_clickpad = libevdev_has_property(device->evdev, @@ -738,19 +728,9 @@ tp_init_buttons(struct tp_dispatch *tp, absinfo_x = device->abs.absinfo_x; absinfo_y = device->abs.absinfo_y; - /* pinned-finger motion threshold, see tp_unpin_finger. - The MAGIC for resolution-less touchpads ends up as 2% of the diagonal */ - if (device->abs.fake_resolution) { - const double BUTTON_MOTION_MAGIC = 0.007; - width = device->abs.dimensions.x; - height = device->abs.dimensions.y; - diagonal = sqrt(width*width + height*height); - tp->buttons.motion_dist.x_scale_coeff = diagonal * BUTTON_MOTION_MAGIC; - tp->buttons.motion_dist.y_scale_coeff = diagonal * BUTTON_MOTION_MAGIC; - } else { - tp->buttons.motion_dist.x_scale_coeff = 1.0/absinfo_x->resolution; - tp->buttons.motion_dist.y_scale_coeff = 1.0/absinfo_y->resolution; - } + /* pinned-finger motion threshold, see tp_unpin_finger. */ + tp->buttons.motion_dist.x_scale_coeff = 1.0/absinfo_x->resolution; + tp->buttons.motion_dist.y_scale_coeff = 1.0/absinfo_y->resolution; tp->buttons.config_method.get_methods = tp_button_config_click_get_methods; tp->buttons.config_method.set_method = tp_button_config_click_set_method; @@ -838,17 +818,6 @@ tp_check_clickfinger_distance(struct tp_dispatch *tp, x = abs(t1->point.x - t2->point.x); y = abs(t1->point.y - t2->point.y); - /* no resolution, so let's assume they're close enough together if - they're within 30% of the touchpad width or height */ - if (tp->device->abs.fake_resolution) { - int w, h; - w = tp->device->abs.dimensions.x; - h = tp->device->abs.dimensions.y; - - within_distance = (x < w * 0.3 && y < h * 0.3) ? 1 : 0; - goto out; - } - xres = tp->device->abs.absinfo_x->resolution; yres = tp->device->abs.absinfo_y->resolution; x /= xres; diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 11fc03b8..bbba6657 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1351,17 +1351,8 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) * and y resolution, so that a circle on the * touchpad does not turn into an elipse on the screen. */ - if (!tp->device->abs.fake_resolution) { - tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; - tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; - } else { - /* - * For touchpads where the driver does not provide resolution, fall - * back to scaling motion events based on the diagonal size in units. - */ - tp->accel.x_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal; - tp->accel.y_scale_coeff = DEFAULT_ACCEL_NUMERATOR / diagonal; - } + tp->accel.x_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_x; + tp->accel.y_scale_coeff = (DEFAULT_MOUSE_DPI/25.4) / res_y; switch (tp->device->model) { case EVDEV_MODEL_LENOVO_X230: @@ -1601,6 +1592,7 @@ tp_init(struct tp_dispatch *tp, { int width, height; double diagonal; + int res_x, res_y; tp->base.interface = &tp_interface; tp->device = device; @@ -1614,6 +1606,8 @@ tp_init(struct tp_dispatch *tp, if (tp_init_slots(tp, device) != 0) return -1; + res_x = tp->device->abs.absinfo_x->resolution; + res_y = tp->device->abs.absinfo_y->resolution; width = device->abs.dimensions.x; height = device->abs.dimensions.y; diagonal = sqrt(width*width + height*height); @@ -1622,18 +1616,8 @@ tp_init(struct tp_dispatch *tp, EV_ABS, ABS_MT_DISTANCE); - if (device->abs.fake_resolution) { - tp->hysteresis_margin.x = - diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; - tp->hysteresis_margin.y = - diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; - } else { - int res_x = tp->device->abs.absinfo_x->resolution, - res_y = tp->device->abs.absinfo_y->resolution; - - tp->hysteresis_margin.x = res_x/2; - tp->hysteresis_margin.y = res_y/2; - } + tp->hysteresis_margin.x = res_x/2; + tp->hysteresis_margin.y = res_y/2; if (tp_init_accel(tp, diagonal) != 0) return -1;