From be857f1e28e66c3bb13c91aa2de0b7438feb145a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Jul 2015 09:19:21 +1000 Subject: [PATCH 01/37] touchpad: don't log a bug for Apple's one-button touchpads Apple used to have a single-button touchpad that was not a clickpad. Skip logging an error for that one. Found in https://bugzilla.redhat.com/show_bug.cgi?id=1246651. Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad-buttons.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 1ee74cad..48726826 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -714,7 +714,8 @@ tp_init_buttons(struct tp_dispatch *tp, "%s: clickpad advertising right button\n", device->devname); } else if (libevdev_has_event_code(device->evdev, EV_KEY, BTN_LEFT) && - !tp->buttons.is_clickpad) { + !tp->buttons.is_clickpad && + libevdev_get_id_vendor(device->evdev) != VENDOR_ID_APPLE) { log_bug_kernel(libinput, "%s: non clickpad without right button?\n", device->devname); From f2aefb9942b94ab5b63768f78cd32b2d30302dd4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Jul 2015 10:24:32 +1000 Subject: [PATCH 02/37] test: filter out edge-scroll-only touchpads from 2fg scroll tests Signed-off-by: Peter Hutterer --- test/touchpad.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index b910d0ea..9af8da07 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -182,6 +182,9 @@ START_TEST(touchpad_2fg_scroll) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + if (!has_2fg_scroll(dev)) + return; + litest_drain_events(li); test_2fg_scroll(dev, 0.1, 40, 0); @@ -208,6 +211,9 @@ START_TEST(touchpad_2fg_scroll_slow_distance) const struct input_absinfo *y; double y_move; + if (!has_2fg_scroll(dev)) + return; + /* We want to move > 5 mm. */ y = libevdev_get_abs_info(dev->evdev, ABS_Y); if (y->resolution) { @@ -261,6 +267,9 @@ START_TEST(touchpad_2fg_scroll_source) struct libinput_event *event; struct libinput_event_pointer *ptrev; + if (!has_2fg_scroll(dev)) + return; + litest_drain_events(li); test_2fg_scroll(dev, 0, 30, 0); @@ -282,6 +291,9 @@ START_TEST(touchpad_2fg_scroll_semi_mt) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + if (!has_2fg_scroll(dev)) + return; + litest_drain_events(li); litest_touch_down(dev, 0, 20, 20); @@ -302,6 +314,9 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + if (!has_2fg_scroll(dev)) + return; + litest_drain_events(li); /* start with motion */ @@ -369,6 +384,9 @@ START_TEST(touchpad_scroll_natural) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; + if (!has_2fg_scroll(dev)) + return; + litest_drain_events(li); libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1); From a5e2e238705742c1ad7d10155084df22e73b2c63 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Jul 2015 10:32:28 +1000 Subject: [PATCH 03/37] test: enable 2fg scrolling before tests that rely on it Signed-off-by: Peter Hutterer --- test/touchpad.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index 9af8da07..cdb97f79 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -185,6 +185,7 @@ START_TEST(touchpad_2fg_scroll) if (!has_2fg_scroll(dev)) return; + enable_2fg_scroll(dev); litest_drain_events(li); test_2fg_scroll(dev, 0.1, 40, 0); @@ -223,6 +224,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance) y_move = 20.0; } + enable_2fg_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 49, 50); @@ -270,6 +272,7 @@ START_TEST(touchpad_2fg_scroll_source) if (!has_2fg_scroll(dev)) return; + enable_2fg_scroll(dev); litest_drain_events(li); test_2fg_scroll(dev, 0, 30, 0); @@ -294,6 +297,7 @@ START_TEST(touchpad_2fg_scroll_semi_mt) if (!has_2fg_scroll(dev)) return; + enable_2fg_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 20, 20); @@ -317,6 +321,7 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) if (!has_2fg_scroll(dev)) return; + enable_2fg_scroll(dev); litest_drain_events(li); /* start with motion */ @@ -387,6 +392,7 @@ START_TEST(touchpad_scroll_natural) if (!has_2fg_scroll(dev)) return; + enable_2fg_scroll(dev); litest_drain_events(li); libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1); From b4f27c43d930c5cfe7db20c08c366730ecc8e1ef Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Jul 2015 10:25:55 +1000 Subject: [PATCH 04/37] test: rename 2fg natural scroll test to be more obvious 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 cdb97f79..7fc8fdc5 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -384,7 +384,7 @@ START_TEST(touchpad_scroll_natural_enable_config) } END_TEST -START_TEST(touchpad_scroll_natural) +START_TEST(touchpad_scroll_natural_2fg) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; @@ -3458,7 +3458,7 @@ litest_setup_tests(void) litest_add("touchpad:scroll", touchpad_2fg_scroll_semi_mt, LITEST_SEMI_MT, LITEST_SINGLE_TOUCH); 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_scroll_natural_2fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); 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); From ed1aee6061e59b09f07875e6a4efaffcd279286d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 27 Jul 2015 10:54:36 +1000 Subject: [PATCH 05/37] test: don't leak the custom udev rule path for devices with custom creates Signed-off-by: Peter Hutterer --- test/litest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/litest.c b/test/litest.c index d2d82a18..d7769d5f 100644 --- a/test/litest.c +++ b/test/litest.c @@ -1049,6 +1049,7 @@ litest_create(enum litest_device_type which, litest_abort_msg("Custom create cannot be overridden"); } + d->udev_rule_file = udev_file; return d; } From 316f30d2f28b62f90efc2bdd9e6f3d83116070e7 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 23 Jul 2015 16:06:48 +1000 Subject: [PATCH 06/37] touchpad: don't check clickfinger distance for three fingers It's reasonable to expect a thumb (or the other hand's index finger) to click a button while a finger is down for movement. It's less reasonable to expect this when two fingers are interacting with the touchpad, or when two fingers click the touchpad (even on a large touchpad that's an awkward position). Simplify the clickfinger detection mechanism - if we have three touches down, it's always a three-finger click. Two fingers may be a right click or a index + thumb click. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-buttons.c | 25 +++------- test/touchpad-buttons.c | 82 +++++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 22 deletions(-) diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index 48726826..f16d1b87 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -858,14 +858,12 @@ tp_clickfinger_set_button(struct tp_dispatch *tp) unsigned int nfingers = tp->nfingers_down; struct tp_touch *t; struct tp_touch *first = NULL, - *second = NULL, - *third = NULL; - uint32_t close_touches = 0; + *second = NULL; - if (nfingers < 2 || nfingers > 3) + if (nfingers != 2) goto out; - /* two or three fingers down on the touchpad. Check for distance + /* two fingers down on the touchpad. Check for distance * between the fingers. */ tp_for_each_touch(tp, t) { if (t->state != TOUCH_BEGIN && t->state != TOUCH_UPDATE) @@ -878,10 +876,6 @@ tp_clickfinger_set_button(struct tp_dispatch *tp) first = t; else if (!second) second = t; - else if (!third) { - third = t; - break; - } } if (!first || !second) { @@ -889,15 +883,10 @@ tp_clickfinger_set_button(struct tp_dispatch *tp) goto out; } - close_touches |= tp_check_clickfinger_distance(tp, first, second) << 0; - close_touches |= tp_check_clickfinger_distance(tp, second, third) << 1; - close_touches |= tp_check_clickfinger_distance(tp, first, third) << 2; - - switch(__builtin_popcount(close_touches)) { - case 0: nfingers = 1; break; - case 1: nfingers = 2; break; - default: nfingers = 3; break; - } + if (tp_check_clickfinger_distance(tp, first, second)) + nfingers = 2; + else + nfingers = 1; out: switch (nfingers) { diff --git a/test/touchpad-buttons.c b/test/touchpad-buttons.c index 896b34b4..2cd8133e 100644 --- a/test/touchpad-buttons.c +++ b/test/touchpad-buttons.c @@ -482,6 +482,78 @@ START_TEST(touchpad_2fg_clickfinger_distance) } END_TEST +START_TEST(touchpad_3fg_clickfinger_distance) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + if (libevdev_get_num_slots(dev->evdev) < 3) + return; + + enable_clickfinger(dev); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 1, 10, 15); + litest_touch_down(dev, 2, 10, 15); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + 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_event(dev, EV_SYN, SYN_REPORT, 0); + litest_touch_up(dev, 0); + litest_touch_up(dev, 1); + litest_touch_up(dev, 2); + + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_RELEASED); +} +END_TEST + +START_TEST(touchpad_3fg_clickfinger_distance_btntool) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + + if (libevdev_get_num_slots(dev->evdev) > 2) + return; + + enable_clickfinger(dev); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 90, 90); + litest_touch_down(dev, 1, 10, 15); + libinput_dispatch(li); + litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + 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_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1); + litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 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_MIDDLE, + LIBINPUT_BUTTON_STATE_PRESSED); + litest_assert_button_event(li, + BTN_MIDDLE, + LIBINPUT_BUTTON_STATE_RELEASED); +} +END_TEST + START_TEST(touchpad_2fg_clickfinger_bottom) { struct litest_device *dev = litest_current_device(); @@ -728,8 +800,8 @@ START_TEST(touchpad_clickfinger_3fg_tool_position) enable_clickfinger(dev); litest_drain_events(li); - /* one in thumb area, one in normal area. spread is wide so the two - * real fingers don't count together. we expect a 2-finger click */ + /* one in thumb area, one in normal area + TRIPLETAP. spread is wide + * but any 3fg touch+click counts as middle */ litest_touch_down(dev, 0, 5, 99); litest_touch_down(dev, 1, 90, 15); litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); @@ -743,9 +815,9 @@ START_TEST(touchpad_clickfinger_3fg_tool_position) litest_event(dev, EV_SYN, SYN_REPORT, 0); libinput_dispatch(li); - litest_assert_button_event(li, BTN_RIGHT, + litest_assert_button_event(li, BTN_MIDDLE, LIBINPUT_BUTTON_STATE_PRESSED); - litest_assert_button_event(li, BTN_RIGHT, + litest_assert_button_event(li, BTN_MIDDLE, LIBINPUT_BUTTON_STATE_RELEASED); } END_TEST @@ -1513,6 +1585,8 @@ litest_setup_tests(void) litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_2slots, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_4fg_clickfinger_btntool_3slots, LITEST_CLICKPAD, LITEST_ANY); litest_add("touchpad:clickfinger", touchpad_2fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance, LITEST_CLICKPAD, LITEST_ANY); + litest_add("touchpad:clickfinger", touchpad_3fg_clickfinger_distance_btntool, 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", From eb146677eb5abb7951af4ead80874c992915b90d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 14 Jul 2015 10:27:46 +1000 Subject: [PATCH 07/37] touchpad: disable 2fg scrolling on Synaptics semi-mt touchpads These touchpads have a terrible resolution when two fingers are down, causing scrolling to jump around a lot. That then turns into bug reports that we can't do much about, the data is simply garbage. https://bugs.freedesktop.org/show_bug.cgi?id=91135 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- doc/scrolling.dox | 7 +++++ src/evdev-mt-touchpad.c | 38 ++++++++++++++++++++++------ src/evdev.c | 1 + src/evdev.h | 1 + test/litest-device-synaptics-hover.c | 10 ++++++++ test/touchpad.c | 21 ++++++++++++--- udev/libinput-model-quirks.c | 26 +++++++++++++++++++ 7 files changed, 93 insertions(+), 11 deletions(-) diff --git a/doc/scrolling.dox b/doc/scrolling.dox index 658fe4b6..0c03c98d 100644 --- a/doc/scrolling.dox +++ b/doc/scrolling.dox @@ -44,6 +44,13 @@ movements will translate into tiny scroll movements. Scrolling in both directions at once is possible by meeting the required distance thresholds to enable each direction separately. +Two-finger scrolling requires the touchpad to track both touch points with +reasonable precision. Unfortunately, some so-called "semi-mt" touchpads can +only track the bounding box of the two fingers rather than the actual +position of each finger. In addition, that bounding box usually suffers from +a low resolution, causing jumpy movement during two-finger scrolling. +libinput does not provide two-finger scrolling on those touchpads. + @section edge_scrolling Edge scrolling On some touchpads, edge scrolling is available, triggered by moving a single diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 6718b616..257af999 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1520,17 +1520,28 @@ tp_init_accel(struct tp_dispatch *tp, double diagonal) return 0; } +static uint32_t +tp_scroll_get_methods(struct tp_dispatch *tp) +{ + uint32_t methods = LIBINPUT_CONFIG_SCROLL_EDGE; + + /* some Synaptics semi-mt touchpads have a terrible 2fg resolution, + * causing scroll jumps. For all other 2fg touchpads, we enable 2fg + * scrolling */ + if (tp->ntouches >= 2 && + (tp->device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT) == 0) + methods |= LIBINPUT_CONFIG_SCROLL_2FG; + + return methods; +} + static uint32_t 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_EDGE; - if (tp->ntouches >= 2) - methods |= LIBINPUT_CONFIG_SCROLL_2FG; - - return methods; + return tp_scroll_get_methods(tp); } static enum libinput_config_status @@ -1564,10 +1575,21 @@ tp_scroll_config_scroll_method_get_method(struct libinput_device *device) static enum libinput_config_scroll_method tp_scroll_get_default_method(struct tp_dispatch *tp) { - if (tp->ntouches >= 2) - return LIBINPUT_CONFIG_SCROLL_2FG; + uint32_t methods; + enum libinput_config_scroll_method method; + + methods = tp_scroll_get_methods(tp); + + if (methods & LIBINPUT_CONFIG_SCROLL_2FG) + method = LIBINPUT_CONFIG_SCROLL_2FG; else - return LIBINPUT_CONFIG_SCROLL_EDGE; + method = LIBINPUT_CONFIG_SCROLL_EDGE; + + if ((methods & method) == 0) + log_bug_libinput(tp_libinput_context(tp), + "Invalid default scroll method %d\n", + method); + return method; } static enum libinput_config_scroll_method diff --git a/src/evdev.c b/src/evdev.c index 78d1f5df..0fc5a649 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1542,6 +1542,7 @@ evdev_read_model_flags(struct evdev_device *device) { "LIBINPUT_MODEL_WACOM_TOUCHPAD", EVDEV_MODEL_WACOM_TOUCHPAD }, { "LIBINPUT_MODEL_ALPS_TOUCHPAD", EVDEV_MODEL_ALPS_TOUCHPAD }, { "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD }, + { "LIBINPUT_MODEL_JUMPING_SEMI_MT", EVDEV_MODEL_JUMPING_SEMI_MT }, { NULL, EVDEV_MODEL_DEFAULT }, }; const struct model_map *m = model_map; diff --git a/src/evdev.h b/src/evdev.h index 36eac217..cc61c5fb 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -105,6 +105,7 @@ enum evdev_device_model { EVDEV_MODEL_WACOM_TOUCHPAD = (1 << 7), EVDEV_MODEL_ALPS_TOUCHPAD = (1 << 8), EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9), + EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10), }; struct mt_slot { diff --git a/test/litest-device-synaptics-hover.c b/test/litest-device-synaptics-hover.c index 2cc9b725..3c36affa 100644 --- a/test/litest-device-synaptics-hover.c +++ b/test/litest-device-synaptics-hover.c @@ -102,6 +102,15 @@ static struct input_absinfo absinfo[] = { { .value = -1 } }; +static const char udev_rule[] = +"ACTION==\"remove\", GOTO=\"synaptics_semi_mt_end\"\n" +"KERNEL!=\"event*\", GOTO=\"synaptics_semi_mt_end\"\n" +"\n" +"ATTRS{name}==\"SynPS/2 Synaptics TouchPad\",\n" +" ENV{LIBINPUT_MODEL_JUMPING_SEMI_MT}=\"1\"\n" +"\n" +"LABEL=\"synaptics_semi_mt_end\""; + struct litest_test_device litest_synaptics_hover_device = { .type = LITEST_SYNAPTICS_HOVER_SEMI_MT, .features = LITEST_TOUCHPAD | LITEST_SEMI_MT | LITEST_BUTTON, @@ -114,6 +123,7 @@ struct litest_test_device litest_synaptics_hover_device = { .id = &input_id, .events = events, .absinfo = absinfo, + .udev_rule = udev_rule, }; static void diff --git a/test/touchpad.c b/test/touchpad.c index 7fc8fdc5..5db79f8a 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -91,6 +91,16 @@ enable_buttonareas(struct litest_device *dev) litest_assert_int_eq(status, expected); } +static inline int +is_synaptics_semi_mt(struct litest_device *dev) +{ + struct libevdev *evdev = dev->evdev; + + return libevdev_has_property(evdev, INPUT_PROP_SEMI_MT) && + libevdev_get_id_vendor(evdev) == 0x2 && + libevdev_get_id_product(evdev) == 0x7; +} + START_TEST(touchpad_1fg_motion) { struct litest_device *dev = litest_current_device(); @@ -461,10 +471,14 @@ START_TEST(touchpad_scroll_defaults) method = libinput_device_config_scroll_get_methods(device); ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE); - if (libevdev_get_num_slots(evdev) > 1) + if (libevdev_get_num_slots(evdev) > 1 && + !is_synaptics_semi_mt(dev)) ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG); + else + ck_assert((method & LIBINPUT_CONFIG_SCROLL_2FG) == 0); - if (libevdev_get_num_slots(evdev) > 1) + if (libevdev_get_num_slots(evdev) > 1 && + !is_synaptics_semi_mt(dev)) expected = LIBINPUT_CONFIG_SCROLL_2FG; else expected = LIBINPUT_CONFIG_SCROLL_EDGE; @@ -480,7 +494,8 @@ START_TEST(touchpad_scroll_defaults) status = libinput_device_config_scroll_set_method(device, LIBINPUT_CONFIG_SCROLL_2FG); - if (libevdev_get_num_slots(evdev) > 1) + if (libevdev_get_num_slots(evdev) > 1 && + !is_synaptics_semi_mt(dev)) ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); else ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); diff --git a/udev/libinput-model-quirks.c b/udev/libinput-model-quirks.c index fc3dbe85..0e737a4b 100644 --- a/udev/libinput-model-quirks.c +++ b/udev/libinput-model-quirks.c @@ -68,6 +68,30 @@ handle_touchpad_alps(struct udev_device *device) printf("LIBINPUT_MODEL_FIRMWARE_VERSION=%d\n", pid); } +static void +handle_touchpad_synaptics(struct udev_device *device) +{ + const char *product, *props; + int bus, vid, pid, version; + int prop; + + product = prop_value(device, "PRODUCT"); + if (!product) + return; + + if (sscanf(product, "%x/%x/%x/%x", &bus, &vid, &pid, &version) != 4) + return; + + if (bus != BUS_I8042 || vid != 0x2 || pid != 0x7) + return; + + props = prop_value(device, "PROP"); + if (sscanf(props, "%x", &prop) != 1) + return; + if (prop & (1 << INPUT_PROP_SEMI_MT)) + printf("LIBINPUT_MODEL_JUMPING_SEMI_MT=1\n"); +} + static void handle_touchpad(struct udev_device *device) { @@ -79,6 +103,8 @@ handle_touchpad(struct udev_device *device) if (strstr(name, "AlpsPS/2 ALPS") != NULL) handle_touchpad_alps(device); + if (strstr(name, "Synaptics ") != NULL) + handle_touchpad_synaptics(device); } int main(int argc, char **argv) From 4bd1d5c6d1f4210a66cbfa50094134c30f8f2cbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 23 Jul 2015 15:23:30 +0800 Subject: [PATCH 08/37] test: Use ck_assert_double_ for checking doubles in some places MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- test/litest.c | 4 ++-- test/pointer.c | 36 +++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/test/litest.c b/test/litest.c index d7769d5f..2daf23ab 100644 --- a/test/litest.c +++ b/test/litest.c @@ -2223,9 +2223,9 @@ litest_assert_scroll(struct libinput *li, } } else { /* Last scroll event, must be 0 */ - litest_assert_int_eq( + ck_assert_double_eq( libinput_event_pointer_get_axis_value(ptrev, axis), - 0); + 0.0); } libinput_event_destroy(event); event = next_event; diff --git a/test/pointer.c b/test/pointer.c index c0a7392b..1de5dc92 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -897,15 +897,18 @@ START_TEST(pointer_accel_defaults) double speed; ck_assert(libinput_device_config_accel_is_available(device)); - ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0); - ck_assert(libinput_device_config_accel_get_speed(device) == 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device), + 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 0.0); for (speed = -2.0; speed < -1.0; speed += 0.2) { status = libinput_device_config_accel_set_speed(device, speed); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); - ck_assert(libinput_device_config_accel_get_speed(device) == 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 0.0); } for (speed = -1.0; speed <= 1.0; speed += 0.2) { @@ -913,7 +916,8 @@ START_TEST(pointer_accel_defaults) speed); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); - ck_assert(libinput_device_config_accel_get_speed(device) == speed); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + speed); } for (speed = 1.2; speed <= -2.0; speed += 0.2) { @@ -921,7 +925,8 @@ START_TEST(pointer_accel_defaults) speed); ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); - ck_assert(libinput_device_config_accel_get_speed(device) == 1.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 1.0); } } @@ -952,8 +957,10 @@ START_TEST(pointer_accel_defaults_absolute) double speed; ck_assert(!libinput_device_config_accel_is_available(device)); - ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0); - ck_assert(libinput_device_config_accel_get_speed(device) == 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device), + 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 0.0); for (speed = -2.0; speed <= 2.0; speed += 0.2) { status = libinput_device_config_accel_set_speed(device, @@ -964,7 +971,8 @@ START_TEST(pointer_accel_defaults_absolute) else ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_INVALID); - ck_assert(libinput_device_config_accel_get_speed(device) == 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 0.0); } } END_TEST @@ -975,8 +983,10 @@ START_TEST(pointer_accel_defaults_absolute_relative) struct libinput_device *device = dev->libinput_device; ck_assert(libinput_device_config_accel_is_available(device)); - ck_assert(libinput_device_config_accel_get_default_speed(device) == 0.0); - ck_assert(libinput_device_config_accel_get_speed(device) == 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_default_speed(device), + 0.0); + ck_assert_double_eq(libinput_device_config_accel_get_speed(device), + 0.0); } END_TEST @@ -1008,7 +1018,7 @@ START_TEST(pointer_accel_direction_change) pev = libinput_event_get_pointer_event(event); delta = libinput_event_pointer_get_dx(pev); - ck_assert(delta <= 0.0); + ck_assert_double_le(delta, 0.0); max_accel = delta; libinput_event_destroy(event); event = libinput_get_event(li); @@ -1016,8 +1026,8 @@ START_TEST(pointer_accel_direction_change) pev = libinput_event_get_pointer_event(event); delta = libinput_event_pointer_get_dx(pev); - ck_assert(delta > 0.0); - ck_assert(delta < -max_accel); + ck_assert_double_gt(delta, 0.0); + ck_assert_double_lt(delta, -max_accel); libinput_event_destroy(event); } END_TEST From 85f7bad759a8c2e51132f94f226c5e3cbebd8d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 11:52:44 +0800 Subject: [PATCH 09/37] Always use uint64_t for internal timestamp values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In most places we use 64 bit unsigned integers; lets be consistent and use it everywhere. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- src/evdev-mt-touchpad.h | 2 +- src/evdev.c | 6 +++--- src/evdev.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 6350a9f6..a7961e75 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -203,7 +203,7 @@ struct tp_touch { struct { enum touch_palm_state state; struct device_coords first; /* first coordinates if is_palm == true */ - uint32_t time; /* first timestamp if is_palm == true */ + uint64_t time; /* first timestamp if is_palm == true */ } palm; struct { diff --git a/src/evdev.c b/src/evdev.c index 0fc5a649..9af1841e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -129,7 +129,7 @@ update_key_down_count(struct evdev_device *device, int code, int pressed) void evdev_keyboard_notify_key(struct evdev_device *device, - uint32_t time, + uint64_t time, int key, enum libinput_key_state state) { @@ -144,7 +144,7 @@ evdev_keyboard_notify_key(struct evdev_device *device, void evdev_pointer_notify_physical_button(struct evdev_device *device, - uint32_t time, + uint64_t time, int button, enum libinput_button_state state) { @@ -159,7 +159,7 @@ evdev_pointer_notify_physical_button(struct evdev_device *device, void evdev_pointer_notify_button(struct evdev_device *device, - uint32_t time, + uint64_t time, int button, enum libinput_button_state state) { diff --git a/src/evdev.h b/src/evdev.h index cc61c5fb..c7017ba5 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -360,18 +360,18 @@ evdev_notify_resumed_device(struct evdev_device *device); void evdev_keyboard_notify_key(struct evdev_device *device, - uint32_t time, + uint64_t time, int key, enum libinput_key_state state); void evdev_pointer_notify_button(struct evdev_device *device, - uint32_t time, + uint64_t time, int button, enum libinput_button_state state); void evdev_pointer_notify_physical_button(struct evdev_device *device, - uint32_t time, + uint64_t time, int button, enum libinput_button_state state); From 6e26493272e0746caf0c5de8c672cde76449f749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 11:54:18 +0800 Subject: [PATCH 10/37] test/pointer: Don't rely on velocities in direction change test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently rely on an extra millisecond being added by the filter code to get a velocity that are small enough to not hit the max acceleration limit. If this arbitrary millisecond is changed (for example by changing the internal time measurment to microseconds and adding just a microsecond instead), the velocity may change so that the maximum or minimum acceleration is always hit. Adding a delay to the test won't work either since it would not only rely on ending up within the acceleration limits but there would also be an non-deterministic actual delay causing the velocity of the movement after the direction change to be potentially larger than the movement in the original direction due to the actual time delta in libinput will not always be 1ms. To fix the test to not rely on any artificial delays in the filter code nor any non-deterministic delays in the test, lets just test that the direction change of the hardware events resulted in a direction change of the libinput motion events. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- test/pointer.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/pointer.c b/test/pointer.c index 1de5dc92..10b9fdc4 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -998,7 +998,6 @@ START_TEST(pointer_accel_direction_change) struct libinput_event_pointer *pev; int i; double delta; - double max_accel; litest_drain_events(li); @@ -1019,7 +1018,6 @@ START_TEST(pointer_accel_direction_change) delta = libinput_event_pointer_get_dx(pev); ck_assert_double_le(delta, 0.0); - max_accel = delta; libinput_event_destroy(event); event = libinput_get_event(li); } while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE); @@ -1027,7 +1025,6 @@ START_TEST(pointer_accel_direction_change) pev = libinput_event_get_pointer_event(event); delta = libinput_event_pointer_get_dx(pev); ck_assert_double_gt(delta, 0.0); - ck_assert_double_lt(delta, -max_accel); libinput_event_destroy(event); } END_TEST From 98346f6a1aa690a8465d64107792b81c2b1cb7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 17:26:20 +0800 Subject: [PATCH 11/37] timer: Warn about negative timer offsets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Even if it may be caused by extreme stalls, warn if the timer was set to be triggered even before 'now' when it actually is triggered, as it is more likely a programming error. Part of the reason for this commit was not to convert the unsigned int to a signed int (which abs() does). Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- src/timer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/timer.c b/src/timer.c index 6a343dbf..a945f788 100644 --- a/src/timer.c +++ b/src/timer.c @@ -71,7 +71,10 @@ libinput_timer_set(struct libinput_timer *timer, uint64_t expire) { #ifndef NDEBUG uint64_t now = libinput_now(timer->libinput); - if (abs(expire - now) > 5000) + if (expire < now) + log_bug_libinput(timer->libinput, + "timer offset negative\n"); + else if ((expire - now) > 5000ULL) log_bug_libinput(timer->libinput, "timer offset more than 5s, now %" PRIu64 " expire %" PRIu64 "\n", From aa5f55149b23ef2a0ebea097ba5e480e39c57054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 17:51:52 +0800 Subject: [PATCH 12/37] Change to micro seconds for measuring time internally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to provide higher precision event time stamps, change the internal time measuring from milliseconds to microseconds. Microseconds are chosen because it is the most fine grained time stamp we can get from evdev. The API is extended with high precision getters whenever the given information is available. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- src/evdev-middle-button.c | 2 +- src/evdev-mt-touchpad-buttons.c | 8 ++-- src/evdev-mt-touchpad-edge-scroll.c | 2 +- src/evdev-mt-touchpad-gestures.c | 4 +- src/evdev-mt-touchpad-tap.c | 4 +- src/evdev-mt-touchpad.c | 8 ++-- src/evdev.c | 8 ++-- src/filter.c | 43 ++++++++++--------- src/libinput-private.h | 2 +- src/libinput-util.c | 12 +++--- src/libinput-util.h | 30 ++++++++++++++ src/libinput.c | 64 +++++++++++++++++++++++++++-- src/libinput.h | 32 +++++++++++++++ src/libinput.sym | 4 ++ src/timer.c | 6 +-- src/timer.h | 4 +- test/gestures.c | 37 +++++++++++++++++ test/keyboard.c | 30 ++++++++++++++ test/misc.c | 13 +++++- test/pointer.c | 28 +++++++++++++ test/touch.c | 23 +++++++++++ test/touchpad.c | 36 ++++++++++++++++ tools/ptraccel-debug.c | 10 +++-- 23 files changed, 349 insertions(+), 61 deletions(-) diff --git a/src/evdev-middle-button.c b/src/evdev-middle-button.c index 48330d39..397b699c 100644 --- a/src/evdev-middle-button.c +++ b/src/evdev-middle-button.c @@ -27,7 +27,7 @@ #include "evdev.h" -#define MIDDLEBUTTON_TIMEOUT 50 +#define MIDDLEBUTTON_TIMEOUT ms2us(50) /***************************************** * BEFORE YOU EDIT THIS FILE, look at the state diagram in diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index f16d1b87..8822e08c 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -32,8 +32,8 @@ #include "evdev-mt-touchpad.h" -#define DEFAULT_BUTTON_ENTER_TIMEOUT 100 /* ms */ -#define DEFAULT_BUTTON_LEAVE_TIMEOUT 300 /* ms */ +#define DEFAULT_BUTTON_ENTER_TIMEOUT ms2us(100) +#define DEFAULT_BUTTON_LEAVE_TIMEOUT ms2us(300) /***************************************** * BEFORE YOU EDIT THIS FILE, look at the state diagram in @@ -913,8 +913,8 @@ tp_notify_clickpadbutton(struct tp_dispatch *tp, struct evdev_dispatch *dispatch = tp->buttons.trackpoint->dispatch; struct input_event event; - event.time.tv_sec = time/1000; - event.time.tv_usec = (time % 1000) * 1000; + event.time.tv_sec = time / ms2us(1000); + event.time.tv_usec = time % ms2us(1000); event.type = EV_KEY; event.code = button; event.value = (state == LIBINPUT_BUTTON_STATE_PRESSED) ? 1 : 0; diff --git a/src/evdev-mt-touchpad-edge-scroll.c b/src/evdev-mt-touchpad-edge-scroll.c index 928f6029..49028087 100644 --- a/src/evdev-mt-touchpad-edge-scroll.c +++ b/src/evdev-mt-touchpad-edge-scroll.c @@ -93,7 +93,7 @@ static inline void tp_edge_scroll_set_timer(struct tp_dispatch *tp, struct tp_touch *t) { - const int DEFAULT_SCROLL_LOCK_TIMEOUT = 300; /* ms */ + const int DEFAULT_SCROLL_LOCK_TIMEOUT = ms2us(300); /* 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. diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 1acf1111..8bcdeb40 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -29,8 +29,8 @@ #include "evdev-mt-touchpad.h" -#define DEFAULT_GESTURE_SWITCH_TIMEOUT 100 /* ms */ -#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT 1000 /* ms */ +#define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100) +#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(1000) static inline const char* gesture_state_to_str(enum tp_gesture_2fg_state state) diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c index b2977545..de4945e6 100644 --- a/src/evdev-mt-touchpad-tap.c +++ b/src/evdev-mt-touchpad-tap.c @@ -35,8 +35,8 @@ #include "evdev-mt-touchpad.h" -#define DEFAULT_TAP_TIMEOUT_PERIOD 180 -#define DEFAULT_DRAG_TIMEOUT_PERIOD 300 +#define DEFAULT_TAP_TIMEOUT_PERIOD ms2us(180) +#define DEFAULT_DRAG_TIMEOUT_PERIOD ms2us(300) #define DEFAULT_TAP_MOVE_THRESHOLD TP_MM_TO_DPI_NORMALIZED(3) enum tap_event { diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 257af999..ebb8cee0 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -30,9 +30,9 @@ #include "evdev-mt-touchpad.h" -#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT 300 /* ms */ -#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 200 /* ms */ -#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 500 /* ms */ +#define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT ms2us(300) +#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 ms2us(200) +#define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 ms2us(500) #define FAKE_FINGER_OVERFLOW (1 << 7) static inline int @@ -588,7 +588,7 @@ tp_palm_detect_trackpoint(struct tp_dispatch *tp, static void tp_palm_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) { - const int PALM_TIMEOUT = 200; /* ms */ + const int PALM_TIMEOUT = ms2us(200); const int DIRECTIONS = NE|E|SE|SW|W|NW; struct device_float_coords delta; int dirs; diff --git a/src/evdev.c b/src/evdev.c index 9af1841e..ee904d31 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -44,7 +44,7 @@ #include "libinput-private.h" #define DEFAULT_WHEEL_CLICK_ANGLE 15 -#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT 200 +#define DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT ms2us(200) enum evdev_key_type { EVDEV_KEY_TYPE_NONE, @@ -457,7 +457,7 @@ evdev_button_scroll_button(struct evdev_device *device, { if (is_press) { libinput_timer_set(&device->scroll.timer, - time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT); + time + DEFAULT_MIDDLE_BUTTON_SCROLL_TIMEOUT); device->scroll.button_down_time = time; } else { libinput_timer_cancel(&device->scroll.timer); @@ -1270,7 +1270,7 @@ static inline void evdev_process_event(struct evdev_device *device, struct input_event *e) { struct evdev_dispatch *dispatch = device->dispatch; - uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000; + uint64_t time = s2us(e->time.tv_sec) + e->time.tv_usec; #if 0 if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT)) @@ -2153,7 +2153,7 @@ evdev_device_create(struct libinput_seat *seat, device->dpi = DEFAULT_MOUSE_DPI; /* at most 5 SYN_DROPPED log-messages per 30s */ - ratelimit_init(&device->syn_drop_limit, 30ULL * 1000, 5); + ratelimit_init(&device->syn_drop_limit, s2us(30), 5); matrix_init_identity(&device->abs.calibration); matrix_init_identity(&device->abs.usermatrix); diff --git a/src/filter.c b/src/filter.c index 35449f56..f8f94096 100644 --- a/src/filter.c +++ b/src/filter.c @@ -77,7 +77,7 @@ filter_get_speed(struct motion_filter *filter) * Default parameters for pointer acceleration profiles. */ -#define DEFAULT_THRESHOLD 0.4 /* in units/ms */ +#define DEFAULT_THRESHOLD 0.0004 /* in units/us */ #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ @@ -85,13 +85,13 @@ filter_get_speed(struct motion_filter *filter) * Pointer acceleration filter constants */ -#define MAX_VELOCITY_DIFF 1.0 /* units/ms */ -#define MOTION_TIMEOUT 1000 /* (ms) */ +#define MAX_VELOCITY_DIFF 0.001 /* units/us */ +#define MOTION_TIMEOUT ms2us(1000) #define NUM_POINTER_TRACKERS 16 struct pointer_tracker { struct normalized_coords delta; /* delta to most recent event */ - uint64_t time; /* ms */ + uint64_t time; /* us */ int dir; }; @@ -101,14 +101,14 @@ struct pointer_accelerator { accel_profile_func_t profile; - double velocity; /* units/ms */ - double last_velocity; /* units/ms */ + double velocity; /* units/us */ + double last_velocity; /* units/us */ struct normalized_coords last; struct pointer_tracker *trackers; int cur_tracker; - double threshold; /* units/ms */ + double threshold; /* units/us */ double accel; /* unitless factor */ double incline; /* incline of the function */ @@ -150,8 +150,7 @@ static double calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { double tdelta = time - tracker->time + 1; - - return normalized_length(tracker->delta) / tdelta; /* units/ms */ + return normalized_length(tracker->delta) / tdelta; /* units/us */ } static inline double @@ -221,7 +220,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time) } } - return result; /* units/ms */ + return result; /* units/us */ } static double @@ -261,7 +260,7 @@ accelerator_filter(struct motion_filter *filter, { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; - double velocity; /* units/ms */ + double velocity; /* units/us */ double accel_value; /* unitless factor */ struct normalized_coords accelerated; struct normalized_coords unnormalized; @@ -334,9 +333,9 @@ accelerator_set_speed(struct motion_filter *filter, assert(speed >= -1.0 && speed <= 1.0); /* delay when accel kicks in */ - accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4.0; - if (accel_filter->threshold < 0.2) - accel_filter->threshold = 0.2; + accel_filter->threshold = DEFAULT_THRESHOLD - speed / 4000.0; + if (accel_filter->threshold < 0.0002) + accel_filter->threshold = 0.0002; /* adjust max accel factor */ accel_filter->accel = DEFAULT_ACCELERATION + speed * 1.5; @@ -398,7 +397,7 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, double pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, void *data, - double speed_in, /* in device units */ + double speed_in, /* in device units (units/us) */ uint64_t time) { struct pointer_accelerator *accel_filter = @@ -406,15 +405,15 @@ pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, double s1, s2; double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/ms */ + const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; double dpi_factor = accel_filter->dpi_factor; max_accel /= dpi_factor; - s1 = min(1, 0.3 + speed_in * 10); - s2 = 1 + (speed_in - threshold * dpi_factor) * incline; + s1 = min(1, 0.3 + speed_in * 10000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -432,12 +431,12 @@ pointer_accel_profile_linear(struct motion_filter *filter, double s1, s2; const double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/ms */ + const double threshold = accel_filter->threshold; /* units/us */ const double incline = accel_filter->incline; double factor; - s1 = min(1, 0.3 + speed_in * 10); - s2 = 1 + (speed_in - threshold) * incline; + s1 = min(1, 0.3 + speed_in * 10 * 1000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -489,7 +488,7 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, const double max_accel = accel_filter->accel * TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */ const double threshold = accel_filter->threshold / - TP_MAGIC_LOW_RES_FACTOR; /* units/ms */ + TP_MAGIC_LOW_RES_FACTOR; /* units/us */ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR; speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; diff --git a/src/libinput-private.h b/src/libinput-private.h index 110955db..e0ba51b5 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -422,7 +422,7 @@ libinput_now(struct libinput *libinput) return 0; } - return ts.tv_sec * 1000ULL + ts.tv_nsec / 1000000; + return s2us(ts.tv_sec) + ns2us(ts.tv_nsec); } static inline struct device_float_coords diff --git a/src/libinput-util.c b/src/libinput-util.c index a383fa17..d35d7022 100644 --- a/src/libinput-util.c +++ b/src/libinput-util.c @@ -72,9 +72,9 @@ list_empty(const struct list *list) } void -ratelimit_init(struct ratelimit *r, uint64_t ival_ms, unsigned int burst) +ratelimit_init(struct ratelimit *r, uint64_t ival_us, unsigned int burst) { - r->interval = ival_ms; + r->interval = ival_us; r->begin = 0; r->burst = burst; r->num = 0; @@ -97,17 +97,17 @@ enum ratelimit_state ratelimit_test(struct ratelimit *r) { struct timespec ts; - uint64_t mtime; + uint64_t utime; if (r->interval <= 0 || r->burst <= 0) return RATELIMIT_PASS; clock_gettime(CLOCK_MONOTONIC, &ts); - mtime = ts.tv_sec * 1000 + ts.tv_nsec / 1000 / 1000; + utime = s2us(ts.tv_sec) + ns2us(ts.tv_nsec); - if (r->begin <= 0 || r->begin + r->interval < mtime) { + if (r->begin <= 0 || r->begin + r->interval < utime) { /* reset counter */ - r->begin = mtime; + r->begin = utime; r->num = 1; return RATELIMIT_PASS; } else if (r->num < r->burst) { diff --git a/src/libinput-util.h b/src/libinput-util.h index 3832b728..de9b98e1 100644 --- a/src/libinput-util.h +++ b/src/libinput-util.h @@ -303,4 +303,34 @@ 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 uint64_t +us(uint64_t us) +{ + return us; +} + +static inline uint64_t +ns2us(uint64_t ns) +{ + return us(ns / 1000); +} + +static inline uint64_t +ms2us(uint64_t ms) +{ + return us(ms * 1000); +} + +static inline uint64_t +s2us(uint64_t s) +{ + return ms2us(s * 1000); +} + +static inline uint32_t +us2ms(uint64_t us) +{ + return (uint32_t)(us / 1000); +} + #endif /* LIBINPUT_UTIL_H */ diff --git a/src/libinput.c b/src/libinput.c index cab6224a..69a6aef2 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -86,7 +86,7 @@ struct libinput_event_device_notify { struct libinput_event_keyboard { struct libinput_event base; - uint32_t time; + uint64_t time; uint32_t key; uint32_t seat_key_count; enum libinput_key_state state; @@ -94,7 +94,7 @@ struct libinput_event_keyboard { struct libinput_event_pointer { struct libinput_event base; - uint32_t time; + uint64_t time; struct normalized_coords delta; struct device_float_coords delta_raw; struct device_coords absolute; @@ -108,7 +108,7 @@ struct libinput_event_pointer { struct libinput_event_touch { struct libinput_event base; - uint32_t time; + uint64_t time; int32_t slot; int32_t seat_slot; struct device_coords point; @@ -116,7 +116,7 @@ struct libinput_event_touch { struct libinput_event_gesture { struct libinput_event base; - uint32_t time; + uint64_t time; int finger_count; int cancelled; struct normalized_coords delta; @@ -278,6 +278,17 @@ libinput_event_get_device_notify_event(struct libinput_event *event) LIBINPUT_EXPORT uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_KEYBOARD_KEY); + + return us2ms(event->time); +} + +LIBINPUT_EXPORT uint64_t +libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event) { require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -323,6 +334,20 @@ libinput_event_keyboard_get_seat_key_count( LIBINPUT_EXPORT uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_POINTER_MOTION, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS); + + return us2ms(event->time); +} + +LIBINPUT_EXPORT uint64_t +libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event) { require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -561,6 +586,21 @@ libinput_event_pointer_get_axis_source(struct libinput_event_pointer *event) LIBINPUT_EXPORT uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_TOUCH_DOWN, + LIBINPUT_EVENT_TOUCH_UP, + LIBINPUT_EVENT_TOUCH_MOTION, + LIBINPUT_EVENT_TOUCH_CANCEL, + LIBINPUT_EVENT_TOUCH_FRAME); + + return us2ms(event->time); +} + +LIBINPUT_EXPORT uint64_t +libinput_event_touch_get_time_usec(struct libinput_event_touch *event) { require_event_type(libinput_event_get_context(&event->base), event->base.type, @@ -666,6 +706,22 @@ libinput_event_touch_get_y(struct libinput_event_touch *event) LIBINPUT_EXPORT uint32_t libinput_event_gesture_get_time(struct libinput_event_gesture *event) +{ + require_event_type(libinput_event_get_context(&event->base), + event->base.type, + 0, + LIBINPUT_EVENT_GESTURE_PINCH_BEGIN, + LIBINPUT_EVENT_GESTURE_PINCH_UPDATE, + LIBINPUT_EVENT_GESTURE_PINCH_END, + LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN, + LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE, + LIBINPUT_EVENT_GESTURE_SWIPE_END); + + return us2ms(event->time); +} + +LIBINPUT_EXPORT uint64_t +libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event) { require_event_type(libinput_event_get_context(&event->base), event->base.type, diff --git a/src/libinput.h b/src/libinput.h index f9a7d681..f2b77b34 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -418,6 +418,14 @@ libinput_event_device_notify_get_base_event(struct libinput_event_device_notify uint32_t libinput_event_keyboard_get_time(struct libinput_event_keyboard *event); +/** + * @ingroup event_keyboard + * + * @return The event time for this event in microseconds + */ +uint64_t +libinput_event_keyboard_get_time_usec(struct libinput_event_keyboard *event); + /** * @ingroup event_keyboard * @@ -473,6 +481,14 @@ libinput_event_keyboard_get_seat_key_count( uint32_t libinput_event_pointer_get_time(struct libinput_event_pointer *event); +/** + * @ingroup event_pointer + * + * @return The event time for this event in microseconds + */ +uint64_t +libinput_event_pointer_get_time_usec(struct libinput_event_pointer *event); + /** * @ingroup event_pointer * @@ -815,6 +831,14 @@ libinput_event_pointer_get_base_event(struct libinput_event_pointer *event); uint32_t libinput_event_touch_get_time(struct libinput_event_touch *event); +/** + * @ingroup event_touch + * + * @return The event time for this event in microseconds + */ +uint64_t +libinput_event_touch_get_time_usec(struct libinput_event_touch *event); + /** * @ingroup event_touch * @@ -967,6 +991,14 @@ libinput_event_touch_get_base_event(struct libinput_event_touch *event); uint32_t libinput_event_gesture_get_time(struct libinput_event_gesture *event); +/** + * @ingroup event_gesture + * + * @return The event time for this event in microseconds + */ +uint64_t +libinput_event_gesture_get_time_usec(struct libinput_event_gesture *event); + /** * @ingroup event_gesture * diff --git a/src/libinput.sym b/src/libinput.sym index d7d12e40..7e0ef1c5 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -167,4 +167,8 @@ LIBINPUT_0.21.0 { libinput_device_config_dwt_set_enabled; libinput_device_config_dwt_get_enabled; libinput_device_config_dwt_get_default_enabled; + libinput_event_gesture_get_time_usec; + libinput_event_keyboard_get_time_usec; + libinput_event_pointer_get_time_usec; + libinput_event_touch_get_time_usec; } LIBINPUT_0.20.0; diff --git a/src/timer.c b/src/timer.c index a945f788..5ad23f31 100644 --- a/src/timer.c +++ b/src/timer.c @@ -57,8 +57,8 @@ libinput_timer_arm_timer_fd(struct libinput *libinput) } if (earliest_expire != UINT64_MAX) { - its.it_value.tv_sec = earliest_expire / 1000; - its.it_value.tv_nsec = (earliest_expire % 1000) * 1000 * 1000; + its.it_value.tv_sec = earliest_expire / ms2us(1000); + its.it_value.tv_nsec = (earliest_expire % ms2us(1000)) * 1000; } r = timerfd_settime(libinput->timer.fd, TFD_TIMER_ABSTIME, &its, NULL); @@ -74,7 +74,7 @@ libinput_timer_set(struct libinput_timer *timer, uint64_t expire) if (expire < now) log_bug_libinput(timer->libinput, "timer offset negative\n"); - else if ((expire - now) > 5000ULL) + else if ((expire - now) > ms2us(5000)) log_bug_libinput(timer->libinput, "timer offset more than 5s, now %" PRIu64 " expire %" PRIu64 "\n", diff --git a/src/timer.h b/src/timer.h index b005fbb8..f8315cfe 100644 --- a/src/timer.h +++ b/src/timer.h @@ -33,7 +33,7 @@ struct libinput; struct libinput_timer { struct libinput *libinput; struct list link; - uint64_t expire; /* in absolute ms CLOCK_MONOTONIC */ + uint64_t expire; /* in absolute us CLOCK_MONOTONIC */ void (*timer_func)(uint64_t now, void *timer_func_data); void *timer_func_data; }; @@ -43,7 +43,7 @@ libinput_timer_init(struct libinput_timer *timer, struct libinput *libinput, void (*timer_func)(uint64_t now, void *timer_func_data), void *timer_func_data); -/* Set timer expire time, in absolute ms CLOCK_MONOTONIC */ +/* Set timer expire time, in absolute us CLOCK_MONOTONIC */ void libinput_timer_set(struct libinput_timer *timer, uint64_t expire); diff --git a/test/gestures.c b/test/gestures.c index b9d73257..3b7ba7bf 100644 --- a/test/gestures.c +++ b/test/gestures.c @@ -349,6 +349,41 @@ START_TEST(gestures_spread) } END_TEST +START_TEST(gestures_time_usec) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_gesture *gevent; + + if (libevdev_get_num_slots(dev->evdev) < 3) + return; + + litest_drain_events(li); + + litest_touch_down(dev, 0, 40, 40); + litest_touch_down(dev, 1, 40, 50); + litest_touch_down(dev, 2, 40, 60); + libinput_dispatch(li); + litest_touch_move_three_touches(dev, + 40, 40, + 40, 50, + 40, 60, + 0, 30, + 4, 2); + + litest_wait_for_event(li); + + event = libinput_get_event(li); + gevent = litest_is_gesture_event(event, + LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN, + 3); + ck_assert_int_eq(libinput_event_gesture_get_time(gevent), + libinput_event_gesture_get_time_usec(gevent) / 1000); + libinput_event_destroy(event); +} +END_TEST + void litest_setup_tests(void) { @@ -361,4 +396,6 @@ litest_setup_tests(void) litest_add_ranged("gestures:swipe", gestures_swipe_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); litest_add_ranged("gestures:pinch", gestures_pinch, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + + litest_add("gesture:time", gestures_time_usec, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH); } diff --git a/test/keyboard.c b/test/keyboard.c index 204d57c4..e9f3bcb1 100644 --- a/test/keyboard.c +++ b/test/keyboard.c @@ -311,6 +311,35 @@ START_TEST(keyboard_keys_bad_device) } END_TEST +START_TEST(keyboard_time_usec) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event_keyboard *kev; + struct libinput_event *event; + + if (!libevdev_has_event_code(dev->evdev, EV_KEY, KEY_A)) + return; + + litest_drain_events(dev->libinput); + + litest_keyboard_key(dev, KEY_A, true); + + litest_wait_for_event(li); + + event = libinput_get_event(li); + kev = litest_is_keyboard_event(event, + KEY_A, + LIBINPUT_KEY_STATE_PRESSED); + + ck_assert_int_eq(libinput_event_keyboard_get_time(kev), + libinput_event_keyboard_get_time_usec(kev) / 1000); + + libinput_event_destroy(event); + litest_drain_events(dev->libinput); +} +END_TEST + void litest_setup_tests(void) { @@ -319,4 +348,5 @@ litest_setup_tests(void) litest_add_no_device("keyboard:key counting", keyboard_key_auto_release); litest_add("keyboard:keys", keyboard_has_key, LITEST_KEYS, LITEST_ANY); litest_add("keyboard:keys", keyboard_keys_bad_device, LITEST_ANY, LITEST_ANY); + litest_add("keyboard:time", keyboard_time_usec, LITEST_KEYS, LITEST_ANY); } diff --git a/test/misc.c b/test/misc.c index 6412b3b1..89edb145 100644 --- a/test/misc.c +++ b/test/misc.c @@ -507,7 +507,7 @@ START_TEST(ratelimit_helpers) unsigned int i, j; /* 10 attempts every 100ms */ - ratelimit_init(&rl, 100, 10); + ratelimit_init(&rl, ms2us(100), 10); for (j = 0; j < 3; ++j) { /* a burst of 9 attempts must succeed */ @@ -683,6 +683,16 @@ START_TEST(dimension_prop_parser) } END_TEST +START_TEST(time_conversion) +{ + ck_assert_int_eq(us(10), 10); + ck_assert_int_eq(ns2us(10000), 10); + ck_assert_int_eq(ms2us(10), 10000); + ck_assert_int_eq(s2us(1), 1000000); + ck_assert_int_eq(us2ms(10000), 10); +} +END_TEST + void litest_setup_tests(void) { @@ -703,4 +713,5 @@ litest_setup_tests(void) 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); + litest_add_no_device("misc:time", time_conversion); } diff --git a/test/pointer.c b/test/pointer.c index 10b9fdc4..f711d385 100644 --- a/test/pointer.c +++ b/test/pointer.c @@ -1419,6 +1419,32 @@ START_TEST(middlebutton_default_disabled) } END_TEST +START_TEST(pointer_time_usec) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event_pointer *ptrev; + struct libinput_event *event; + + litest_drain_events(dev->libinput); + + litest_event(dev, EV_REL, REL_X, 1); + litest_event(dev, EV_REL, REL_Y, 1); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + + litest_wait_for_event(li); + + event = libinput_get_event(li); + ptrev = litest_is_motion_event(event); + + ck_assert_int_eq(libinput_event_pointer_get_time(ptrev), + libinput_event_pointer_get_time_usec(ptrev) / 1000); + + libinput_event_destroy(event); + litest_drain_events(dev->libinput); +} +END_TEST + void litest_setup_tests(void) { @@ -1466,4 +1492,6 @@ litest_setup_tests(void) litest_add_for_device("pointer:middlebutton", middlebutton_default_alps, LITEST_ALPS_SEMI_MT); litest_add_ranged("pointer:state", pointer_absolute_initial_state, LITEST_ABSOLUTE, LITEST_ANY, &axis_range); + + litest_add("pointer:time", pointer_time_usec, LITEST_RELATIVE, LITEST_ANY); } diff --git a/test/touch.c b/test/touch.c index b519613d..eae8007c 100644 --- a/test/touch.c +++ b/test/touch.c @@ -652,6 +652,27 @@ START_TEST(touch_initial_state) } END_TEST +START_TEST(touch_time_usec) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_touch *tev; + + litest_drain_events(dev->libinput); + + litest_touch_down(dev, 0, 10, 10); + + litest_wait_for_event(li); + + event = libinput_get_event(li); + tev = litest_is_touch_event(event, LIBINPUT_EVENT_TOUCH_DOWN); + ck_assert_int_eq(libinput_event_touch_get_time(tev), + libinput_event_touch_get_time_usec(tev) / 1000); + libinput_event_destroy(event); +} +END_TEST + void litest_setup_tests(void) { @@ -678,4 +699,6 @@ litest_setup_tests(void) litest_add("touch:protocol a", touch_protocol_a_2fg_touch, LITEST_PROTOCOL_A, LITEST_ANY); litest_add_ranged("touch:state", touch_initial_state, LITEST_TOUCH, LITEST_PROTOCOL_A, &axes); + + litest_add("touch:time", touch_time_usec, LITEST_TOUCH, LITEST_TOUCHPAD); } diff --git a/test/touchpad.c b/test/touchpad.c index 5db79f8a..1935d19b 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3458,6 +3458,40 @@ START_TEST(touchpad_tool_tripletap_touch_count) } END_TEST +START_TEST(touchpad_time_usec) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_pointer *ptrev; + + litest_disable_tap(dev->libinput_device); + + litest_drain_events(li); + + litest_touch_down(dev, 0, 50, 50); + litest_touch_move_to(dev, 0, 50, 50, 80, 50, 5, 0); + litest_touch_up(dev, 0); + + libinput_dispatch(li); + + event = libinput_get_event(li); + ck_assert_notnull(event); + + while (event) { + uint64_t utime; + + ptrev = litest_is_motion_event(event); + utime = libinput_event_pointer_get_time_usec(ptrev); + + ck_assert_int_eq(libinput_event_pointer_get_time(ptrev), + utime / 1000); + libinput_event_destroy(event); + event = libinput_get_event(li); + } +} +END_TEST + void litest_setup_tests(void) { @@ -3562,4 +3596,6 @@ litest_setup_tests(void) litest_add("touchpad:thumb", touchpad_thumb_tap_hold_2ndfg_tap, LITEST_CLICKPAD, LITEST_SINGLE_TOUCH); litest_add_for_device("touchpad:bugs", touchpad_tool_tripletap_touch_count, LITEST_SYNAPTICS_TOPBUTTONPAD); + + litest_add("touchpad:time", touchpad_time_usec, LITEST_TOUCHPAD, LITEST_ANY); } diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index b2dd1f90..1496763b 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -26,12 +26,14 @@ #include #include #include -#include #include #include #include #include +#include +#include + static void print_ptraccel_deltas(struct motion_filter *filter, double step) { @@ -50,7 +52,7 @@ print_ptraccel_deltas(struct motion_filter *filter, double step) for (i = 0.0; i < 15.0; i += step) { motion.x = i; motion.y = 0; - time += 12; /* pretend 80Hz data */ + time += us(12500); /* pretend 80Hz data */ motion = filter_dispatch(filter, &motion, NULL, time); @@ -93,7 +95,7 @@ print_ptraccel_movement(struct motion_filter *filter, for (i = 0; i < nevents; i++) { motion.x = dx; motion.y = 0; - time += 12; /* pretend 80Hz data */ + time += us(12500); /* pretend 80Hz data */ motion = filter_dispatch(filter, &motion, NULL, time); @@ -127,7 +129,7 @@ print_ptraccel_sequence(struct motion_filter *filter, for (i = 0; i < nevents; i++, dx++) { motion.x = *dx; motion.y = 0; - time += 12; /* pretend 80Hz data */ + time += us(12500); /* pretend 80Hz data */ motion = filter_dispatch(filter, &motion, NULL, time); From 5cb1cb47f7313a4464f8a94b3fbfe90fe80488eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 15:53:53 +0800 Subject: [PATCH 13/37] test: Make udev path variables more explicitly named MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to make room for more types of rules files. Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- test/Makefile.am | 4 ++-- test/litest.c | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/test/Makefile.am b/test/Makefile.am index 1c2852e2..a9ddc85a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -45,8 +45,8 @@ 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_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \ - -DLIBINPUT_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" + -DLIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE="\"$(abs_top_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \ + -DLIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" if HAVE_LIBUNWIND liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS) diff --git a/test/litest.c b/test/litest.c index 2daf23ab..45dabaaf 100644 --- a/test/litest.c +++ b/test/litest.c @@ -53,8 +53,10 @@ #define UDEV_RULES_D "/run/udev/rules.d" #define UDEV_RULE_PREFIX "99-litest-" #define UDEV_HWDB_D "/etc/udev/hwdb.d" -#define UDEV_COMMON_RULE_FILE UDEV_RULES_D "/91-litest-model-quirks-REMOVEME.rules" -#define UDEV_COMMON_HWDB_FILE UDEV_HWDB_D "/91-litest-model-quirks-REMOVEME.hwdb" +#define UDEV_MODEL_QUIRKS_RULE_FILE UDEV_RULES_D \ + "/91-litest-model-quirks-REMOVEME.rules" +#define UDEV_MODEL_QUIRKS_HWDB_FILE UDEV_HWDB_D \ + "/91-litest-model-quirks-REMOVEME.hwdb" static int in_debugger = -1; static int verbose = 0; @@ -947,19 +949,19 @@ litest_install_model_quirks(void) "# running, remove this file and update your hwdb: \n" "# sudo udevadm hwdb --update\n" "#################################################################\n\n"; - litest_copy_file(UDEV_COMMON_RULE_FILE, - LIBINPUT_UDEV_RULES_FILE, + litest_copy_file(UDEV_MODEL_QUIRKS_RULE_FILE, + LIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE, warning); - litest_copy_file(UDEV_COMMON_HWDB_FILE, - LIBINPUT_UDEV_HWDB_FILE, + litest_copy_file(UDEV_MODEL_QUIRKS_HWDB_FILE, + LIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE, warning); } static inline void litest_remove_model_quirks(void) { - unlink(UDEV_COMMON_RULE_FILE); - unlink(UDEV_COMMON_HWDB_FILE); + unlink(UDEV_MODEL_QUIRKS_RULE_FILE); + unlink(UDEV_MODEL_QUIRKS_HWDB_FILE); } static void From 091206c907c7f7e31e2f4ce92346783131e7b7d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Jul 2015 16:08:04 +0800 Subject: [PATCH 14/37] Ignore test devices for libinput contexts not run from the test suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a LIBINPUT_TEST_DEVICE udev parameter to test devices created by the test suite. When an application tries to add such a device to the path backend or when the udev backend discovers such a device, it will be ignored. Only the context when run via the test suite will actually handle these devices. Doing this will enable a user to run the libinput test suite on a system running libinput without having the test suite devices interfering with the actual system. Note that X.org users running an input device driver that is not the libinput X input driver will still need to manually configure the X server to ignore such devices (see test/50-litest.conf). Signed-off-by: Jonas Ådahl Reviewed-by: Peter Hutterer --- src/libinput-private.h | 3 +++ src/libinput.c | 10 ++++++++++ src/path.c | 5 +++++ src/udev-seat.c | 3 +++ test/Makefile.am | 3 ++- test/litest.c | 7 +++++++ udev/.gitignore | 5 ++++- udev/80-libinput-test-device.rules | 1 + 8 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 udev/80-libinput-test-device.rules diff --git a/src/libinput-private.h b/src/libinput-private.h index e0ba51b5..5d0826d0 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -292,6 +292,9 @@ open_restricted(struct libinput *libinput, void close_restricted(struct libinput *libinput, int fd); +bool +ignore_litest_test_suite_device(struct udev_device *device); + void libinput_seat_init(struct libinput_seat *seat, struct libinput *libinput, diff --git a/src/libinput.c b/src/libinput.c index 69a6aef2..7d017e38 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1020,6 +1020,16 @@ close_restricted(struct libinput *libinput, int fd) return libinput->interface->close_restricted(fd, libinput->user_data); } +bool +ignore_litest_test_suite_device(struct udev_device *device) +{ + if (!getenv("LIBINPUT_RUNNING_TEST_SUITE") && + udev_device_get_property_value(device, "LIBINPUT_TEST_DEVICE")) + return true; + + return false; +} + void libinput_seat_init(struct libinput_seat *seat, struct libinput *libinput, diff --git a/src/path.c b/src/path.c index 04c703c1..b14d8b67 100644 --- a/src/path.c +++ b/src/path.c @@ -343,6 +343,11 @@ libinput_path_add_device(struct libinput *libinput, return NULL; } + if (ignore_litest_test_suite_device(udev_device)) { + udev_device_unref(udev_device); + return NULL; + } + device = path_create_device(libinput, udev_device, NULL); udev_device_unref(udev_device); return device; diff --git a/src/udev-seat.c b/src/udev-seat.c index 6b019da2..6bf85de9 100644 --- a/src/udev-seat.c +++ b/src/udev-seat.c @@ -62,6 +62,9 @@ device_added(struct udev_device *udev_device, if (!streq(device_seat, input->seat_id)) return 0; + if (ignore_litest_test_suite_device(udev_device)) + return 0; + devnode = udev_device_get_devnode(udev_device); /* Search for matching logical seat */ diff --git a/test/Makefile.am b/test/Makefile.am index a9ddc85a..cde93b36 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -46,7 +46,8 @@ liblitest_la_SOURCES = \ liblitest_la_LIBADD = $(top_builddir)/src/libinput-util.la liblitest_la_CFLAGS = $(AM_CFLAGS) \ -DLIBINPUT_MODEL_QUIRKS_UDEV_RULES_FILE="\"$(abs_top_builddir)/udev/90-libinput-model-quirks-litest.rules\"" \ - -DLIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" + -DLIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE="\"$(abs_top_srcdir)/udev/90-libinput-model-quirks.hwdb\"" \ + -DLIBINPUT_TEST_DEVICE_RULES_FILE="\"$(abs_top_srcdir)/udev/80-libinput-test-device.rules\"" if HAVE_LIBUNWIND liblitest_la_LIBADD += $(LIBUNWIND_LIBS) -ldl liblitest_la_CFLAGS += $(LIBUNWIND_CFLAGS) diff --git a/test/litest.c b/test/litest.c index 45dabaaf..676485ed 100644 --- a/test/litest.c +++ b/test/litest.c @@ -57,6 +57,8 @@ "/91-litest-model-quirks-REMOVEME.rules" #define UDEV_MODEL_QUIRKS_HWDB_FILE UDEV_HWDB_D \ "/91-litest-model-quirks-REMOVEME.hwdb" +#define UDEV_TEST_DEVICE_RULE_FILE UDEV_RULES_D \ + "/91-litest-test-device-REMOVEME.rules" static int in_debugger = -1; static int verbose = 0; @@ -955,6 +957,9 @@ litest_install_model_quirks(void) litest_copy_file(UDEV_MODEL_QUIRKS_HWDB_FILE, LIBINPUT_MODEL_QUIRKS_UDEV_HWDB_FILE, warning); + litest_copy_file(UDEV_TEST_DEVICE_RULE_FILE, + LIBINPUT_TEST_DEVICE_RULES_FILE, + warning); } static inline void @@ -962,6 +967,7 @@ litest_remove_model_quirks(void) { unlink(UDEV_MODEL_QUIRKS_RULE_FILE); unlink(UDEV_MODEL_QUIRKS_HWDB_FILE); + unlink(UDEV_TEST_DEVICE_RULE_FILE); } static void @@ -2551,6 +2557,7 @@ main(int argc, char **argv) list_init(&all_tests); setenv("CK_DEFAULT_TIMEOUT", "10", 0); + setenv("LIBINPUT_RUNNING_TEST_SUITE", "1", 1); mode = litest_parse_argv(argc, argv); if (mode == LITEST_MODE_ERROR) diff --git a/udev/.gitignore b/udev/.gitignore index 2fdaedcf..cad377a8 100644 --- a/udev/.gitignore +++ b/udev/.gitignore @@ -1,3 +1,6 @@ libinput-device-group libinput-model-quirks -*.rules +80-libinput-device-groups-litest.rules +80-libinput-device-groups.rules +90-libinput-model-quirks-litest.rules +90-libinput-model-quirks.rules diff --git a/udev/80-libinput-test-device.rules b/udev/80-libinput-test-device.rules new file mode 100644 index 00000000..d37b2abe --- /dev/null +++ b/udev/80-libinput-test-device.rules @@ -0,0 +1 @@ +KERNELS=="*input*", ATTRS{name}=="litest *", ENV{LIBINPUT_TEST_DEVICE}="1" From 42c25dcb89b9391fe73a60b111c77db6532db746 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 13:09:52 +1000 Subject: [PATCH 15/37] touchpad: log when thumb detection is enabled on a device Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ebb8cee0..668a4057 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1787,6 +1787,10 @@ tp_init_thumb(struct tp_dispatch *tp) tp->thumb.upper_thumb_line = ymax - yres * 15; tp->thumb.lower_thumb_line = ymax - yres * 8; + log_debug(tp_libinput_context(tp), + "thumb: enabled thumb detection on '%s'\n", + device->devname); + return 0; } From 5cec16eede70f6df44b1c39faae614a66594d774 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 09:52:28 +1000 Subject: [PATCH 16/37] test: add a bunch of libinput_dispatch() before timeout calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 98346f6a1aa added a warning about timeouts expiring before now. Those warnings are triggered by a bunch of tests where we have events, then a timeout, then a libinput_dispatch(). All these are bugs in the test, since we can't guarantee the order of fds (and thus which fd the events are pulled off first) it's just lucky that they worked. Insert the required libinput_dispatch() calls. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- test/touchpad.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index 1935d19b..84898618 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -3165,6 +3165,7 @@ START_TEST(touchpad_thumb_tap_begin) /* touch down is a thumb */ litest_touch_down_extended(dev, 0, 50, 99, axes); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_empty_queue(li); @@ -3172,6 +3173,7 @@ START_TEST(touchpad_thumb_tap_begin) /* make sure normal tap still works */ litest_touch_down(dev, 0, 50, 99); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); } @@ -3197,12 +3199,14 @@ START_TEST(touchpad_thumb_tap_touch) litest_touch_down(dev, 0, 50, 50); litest_touch_move_extended(dev, 0, 51, 99, axes); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_empty_queue(li); /* make sure normal tap still works */ litest_touch_down(dev, 0, 50, 99); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); } @@ -3226,6 +3230,7 @@ START_TEST(touchpad_thumb_tap_hold) /* event in state HOLD is thumb */ litest_touch_down(dev, 0, 50, 99); + libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); litest_touch_move_extended(dev, 0, 51, 99, axes); @@ -3235,6 +3240,7 @@ START_TEST(touchpad_thumb_tap_hold) /* make sure normal tap still works */ litest_touch_down(dev, 0, 50, 99); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); } @@ -3258,6 +3264,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg) /* event in state HOLD is thumb */ litest_touch_down(dev, 0, 50, 99); + libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); litest_touch_move_extended(dev, 0, 51, 99, axes); @@ -3273,6 +3280,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg) litest_assert_empty_queue(li); /* timeout -> into HOLD, no event on release */ + libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); litest_touch_up(dev, 1); @@ -3281,6 +3289,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg) /* make sure normal tap still works */ litest_touch_down(dev, 0, 50, 99); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); } @@ -3305,6 +3314,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap) /* event in state HOLD is thumb */ litest_touch_down(dev, 0, 50, 99); + libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); litest_touch_move_extended(dev, 0, 51, 99, axes); @@ -3328,6 +3338,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap) LIBINPUT_BUTTON_STATE_PRESSED); libinput_event_destroy(libinput_event_pointer_get_base_event(ptrev)); + libinput_dispatch(li); litest_timeout_tap(); libinput_dispatch(li); event = libinput_get_event(li); @@ -3339,6 +3350,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg_tap) /* make sure normal tap still works */ litest_touch_down(dev, 0, 50, 99); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tap(); litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_BUTTON); } From 3bf404da96c636e568e30dbfccef475c2403c705 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 11:00:17 +1000 Subject: [PATCH 17/37] =?UTF-8?q?touchpad:=20update=20the=20thumb=20move?= =?UTF-8?q?=20timeout=20to=20=C2=B5s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And add a #define for it so we stop hiding it. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/evdev-mt-touchpad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 668a4057..ee1612e4 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -33,6 +33,7 @@ #define DEFAULT_TRACKPOINT_ACTIVITY_TIMEOUT ms2us(300) #define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_1 ms2us(200) #define DEFAULT_KEYBOARD_ACTIVITY_TIMEOUT_2 ms2us(500) +#define THUMB_MOVE_TIMEOUT ms2us(300) #define FAKE_FINGER_OVERFLOW (1 << 7) static inline int @@ -700,7 +701,7 @@ tp_thumb_detect(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->thumb.state = THUMB_STATE_YES; else if (t->point.y > tp->thumb.lower_thumb_line && tp->scroll.method != LIBINPUT_CONFIG_SCROLL_EDGE && - t->thumb.first_touch_time + 300 < time) + t->thumb.first_touch_time + THUMB_MOVE_TIMEOUT < time) t->thumb.state = THUMB_STATE_YES; /* now what? we marked it as thumb, so: From dfb442be4e0e1dc7054502582052421269e81059 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 16:29:46 +1000 Subject: [PATCH 18/37] test: add missing libinput_dispatch() before timeouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit see 5cec16eede70. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- test/touchpad-tap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index c021f1dc..f6986e70 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -806,6 +806,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout) litest_assert_empty_queue(li); litest_touch_up(dev, 0); + libinput_dispatch(li); litest_timeout_tapndrag(); litest_assert_button_event(li, BTN_LEFT, From bae79eff3cebc59fc969c40ef2b9cf0bbbdd6468 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 16:06:20 +1000 Subject: [PATCH 19/37] test: abort if we trigger a libinput bug message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only abort on client or libinput bugs, skip over kernel bugs. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- test/litest.c | 4 ++++ test/path.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/test/litest.c b/test/litest.c index 676485ed..51085f19 100644 --- a/test/litest.c +++ b/test/litest.c @@ -777,6 +777,10 @@ litest_log_handler(struct libinput *libinput, fprintf(stderr, "litest %s: ", priority); vfprintf(stderr, format, args); + + if (strstr(format, "client bug: ") || + strstr(format, "libinput bug: ")) + litest_abort_msg("libinput bug triggered, aborting.\n"); } static int diff --git a/test/path.c b/test/path.c index 22db7ae5..0b04b196 100644 --- a/test/path.c +++ b/test/path.c @@ -331,7 +331,9 @@ START_TEST(path_add_invalid_path) li = litest_create_context(); + litest_disable_log_handler(li); device = libinput_path_add_device(li, "/tmp/"); + litest_restore_log_handler(li); ck_assert(device == NULL); libinput_dispatch(li); From 0d40aefecad44982cb90f9bfe3c3e33102c2bd27 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 29 Jul 2015 17:12:53 +1000 Subject: [PATCH 20/37] gestures: check ntouches, not just num_slots for the number of fingers We need to check fake fingers as well as real fingers, especially for two-finger scrolling on single-touch touchpads with BTN_TOOL_DOUBLETAP. https://bugzilla.redhat.com/show_bug.cgi?id=1246651 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 8bcdeb40..6b1a273c 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -157,7 +157,7 @@ tp_gesture_get_active_touches(struct tp_dispatch *tp, memset(touches, 0, count * sizeof(struct tp_touch *)); - for (i = 0; i < tp->num_slots; i++) { + for (i = 0; i < tp->ntouches; i++) { t = &tp->touches[i]; if (tp_touch_active(tp, t)) { touches[n++] = t; From 6b59b4273c38570258519d16357dd0953b650bc8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 12:54:16 +1000 Subject: [PATCH 21/37] touchpad: drop distance threshold to detect pinches This gives us too many false positives of 2fg scroll being detected as pinch gesture. Reporter in [1] uses index+ring finger and thus exceeds the distance easily (that's admittedly a special case). This is worsed by the lack of a client stack that handles the gestures. User's don't see that they're inadvertently performing a gesture, they just see 2fg scroll not working. Drop the distance for now, once we have a ubiquitous client stack we can revisit and bring it back. [1] https://bugzilla.redhat.com/show_bug.cgi?id=1246868 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 6b1a273c..3b1839e4 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -264,26 +264,11 @@ tp_gesture_twofinger_handle_state_none(struct tp_dispatch *tp, uint64_t time) static enum tp_gesture_2fg_state tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time) { - struct normalized_coords normalized; - struct device_float_coords delta; struct tp_touch *first = tp->gesture.touches[0], *second = tp->gesture.touches[1]; int dir1, dir2; - delta = device_delta(first->point, second->point); - normalized = tp_normalize_delta(tp, delta); - - /* If fingers are further than 3 cm apart assume pinch */ - if (normalized_length(normalized) > TP_MM_TO_DPI_NORMALIZED(30)) { - tp_gesture_get_pinch_info(tp, - &tp->gesture.initial_distance, - &tp->gesture.angle, - &tp->gesture.center); - tp->gesture.prev_scale = 1.0; - return GESTURE_2FG_STATE_PINCH; - } - - /* Elif fingers have been close together for a while, scroll */ + /* if fingers stay unmoving for a while, assume (slow) scroll */ if (time > (tp->gesture.initial_time + DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT)) { tp_gesture_set_scroll_buildup(tp); return GESTURE_2FG_STATE_SCROLL; From a12a39fb82fe116bc8477240b146b3528ded32a6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 11:11:12 +1000 Subject: [PATCH 22/37] doc: add a page on how to report bugs Signed-off-by: Peter Hutterer --- README.txt | 2 + doc/Makefile.am | 1 + doc/page-hierarchy.dox | 1 + doc/reporting-bugs.dox | 88 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100644 doc/reporting-bugs.dox diff --git a/README.txt b/README.txt index 0849e1d1..f557f69c 100644 --- a/README.txt +++ b/README.txt @@ -56,6 +56,8 @@ Where possible, please provide an [evemu](http://www.freedesktop.org/wiki/Evemu/) recording of the input device and/or the event sequence in question. +See @ref reporting_bugs for more info. + Documentation ------------- diff --git a/doc/Makefile.am b/doc/Makefile.am index ddda230b..01bcd1b5 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -18,6 +18,7 @@ header_files = \ $(srcdir)/normalization-of-relative-motion.dox \ $(srcdir)/palm-detection.dox \ $(srcdir)/page-hierarchy.dox \ + $(srcdir)/reporting-bugs.dox \ $(srcdir)/scrolling.dox \ $(srcdir)/seats.dox \ $(srcdir)/t440-support.dox \ diff --git a/doc/page-hierarchy.dox b/doc/page-hierarchy.dox index 78592fc2..1e82535f 100644 --- a/doc/page-hierarchy.dox +++ b/doc/page-hierarchy.dox @@ -25,6 +25,7 @@ - @subpage faq - @subpage tools +- @subpage reporting_bugs @page developers Developers diff --git a/doc/reporting-bugs.dox b/doc/reporting-bugs.dox new file mode 100644 index 00000000..0755a9ee --- /dev/null +++ b/doc/reporting-bugs.dox @@ -0,0 +1,88 @@ +/** +@page reporting_bugs Reporting bugs + +A new bug can be filed here: +https://bugs.freedesktop.org/enter_bug.cgi?product=Wayland&component=libinput + +When reporting bugs against libinput, please follow the instructions below +and provide the required data. This will speed up triage, resulting in a +quicker bugfix. + +First, try to identify the bugi by reproducing it reliably. The more +specific a bug description is, the easier it is to fix. The @ref +libinput-debug-events helper tool can help identify whether the bug is in +libinput at all. This tool is a direct hook to libinput without a desktop +stack in between and can thus help to identify whether a bug is in libinput +or in one of the higher layers. See the @ref libinput-debug-events section +for information on this tool. + +@section triage Required information for triage + +When you file a bug, please attach the following information: +- a virtual description of your input device, see @ref evemu. This is the + most important piece of information, do not forget it! +- the libinput version. Either the package version from your distribution + or, when running from git: git log -n 1 HEAD or git describe + HEAD. As a last resort: libinput-list-devices --version. +- the current libinput settings for the device. This is a bit harder to + obtain, for now we'll assume you are running X11. The current settings can + be obtained with xinput list-props "your device name". Use + xinput list to obtain the device name. +- if the device is a touchpad or a pointing stick, the vendor model number + of your laptop, and the content of /sys/class/dmi/id/modalias. +- if the device is a touchpad, the physical dimensions of your touchpad in + mm + +@section evemu Recording devices with evemu + +evemu records the +device capabilities together with the event stream from the kernel. On our +side, this allows us to recreate a virtual device identical to your device +and re-play the event sequence, hopefully triggering the same bug. + +evemu-record takes a /dev/input/eventX event node, but without arguments +it will simply show the list of devices and let you select: +@code +$ sudo evemu-record > scroll.evemu +Available devices: +/dev/input/event0: Lid Switch +/dev/input/event1: Sleep Button +/dev/input/event2: Power Button +/dev/input/event3: AT Translated Set 2 keyboard +/dev/input/event4: SynPS/2 Synaptics TouchPad +/dev/input/event5: Video Bus +/dev/input/event6: ELAN Touchscreen +/dev/input/event10: ThinkPad Extra Buttons +/dev/input/event11: HDA Intel HDMI HDMI/DP,pcm=3 +/dev/input/event12: HDA Intel HDMI HDMI/DP,pcm=7 +/dev/input/event13: HDA Intel HDMI HDMI/DP,pcm=8 +/dev/input/event14: HDA Intel PCH Dock Mic +/dev/input/event15: HDA Intel PCH Mic +/dev/input/event16: HDA Intel PCH Dock Headphone +/dev/input/event17: HDA Intel PCH Headphone +/dev/input/event18: Integrated Camera +/dev/input/event19: TPPS/2 IBM TrackPoint +Select the device event number [0-19]: +@endcode + +Select the device that triggers the issue, then reproduce the bug and Ctrl+C +the process. The resulting recording, ("scroll.evemu" in this example) will +contain the sequence required to reproduce the bug. If the bug fails to +reproduce during recording, simply Ctrl+C and restart evemu-record. +Always start the recording from a neutral state, i.e. without any buttons or +keys down, with the position of the device in the neutral position, without +touching the screen/touchpad. + +@note The longer the recording, the harder it is to identify the event +sequence triggering the bug. Please keep the event sequence as short as possible. + +To verify that the recording contains the bug, you can replay it on your +device. For example, to replay the sequence recorded in the example above: +@code +$ sudo evemu-play /dev/input/event4 < scroll.evemu +@endcode + +If the bug is triggered by replaying on your device, attach the recording to +the bug report. + +*/ From 2dd1b3ead0410149ccceed153dffdd5e83ef232b Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 14:48:12 +1000 Subject: [PATCH 23/37] test: move the helper functions to the litest.h file To avoid duplication Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- test/litest.h | 93 ++++++++++++++++++++++ test/touchpad-buttons.c | 72 ++++++----------- test/touchpad-tap.c | 40 ++-------- test/touchpad.c | 171 ++++++++++++---------------------------- 4 files changed, 176 insertions(+), 200 deletions(-) diff --git a/test/litest.h b/test/litest.h index b5d0f491..8a4b33d1 100644 --- a/test/litest.h +++ b/test/litest.h @@ -472,6 +472,99 @@ litest_disable_tap(struct libinput_device *device) litest_assert_int_eq(status, expected); } +static inline bool +litest_has_2fg_scroll(struct litest_device *dev) +{ + struct libinput_device *device = dev->libinput_device; + + return !!(libinput_device_config_scroll_get_methods(device) & + LIBINPUT_CONFIG_SCROLL_2FG); +} + +static inline void +litest_enable_2fg_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_2FG); + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + litest_assert_int_eq(status, expected); +} + +static inline void +litest_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); +} + +static inline void +litest_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 inline void +litest_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); +} + +static inline int +litest_is_synaptics_semi_mt(struct litest_device *dev) +{ + struct libevdev *evdev = dev->evdev; + + return libevdev_has_property(evdev, INPUT_PROP_SEMI_MT) && + libevdev_get_id_vendor(evdev) == 0x2 && + libevdev_get_id_product(evdev) == 0x7; +} + +static inline void +litest_enable_drag_lock(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); + + litest_assert_int_eq(status, expected); +} + +static inline void +litest_disable_drag_lock(struct libinput_device *device) +{ + enum libinput_config_status status, expected; + + expected = LIBINPUT_CONFIG_STATUS_SUCCESS; + status = libinput_device_config_tap_set_drag_lock_enabled(device, + LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); + + litest_assert_int_eq(status, expected); +} + #define CK_DOUBLE_EQ_EPSILON 1E-3 #define ck_assert_double_eq(X,Y) \ do { \ diff --git a/test/touchpad-buttons.c b/test/touchpad-buttons.c index 2cd8133e..064c29ef 100644 --- a/test/touchpad-buttons.c +++ b/test/touchpad-buttons.c @@ -32,30 +32,6 @@ #include "libinput-util.h" #include "litest.h" -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_click_defaults_clickfinger) { struct litest_device *dev = litest_current_device(); @@ -141,7 +117,7 @@ START_TEST(touchpad_1fg_clickfinger) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -166,7 +142,7 @@ START_TEST(touchpad_1fg_clickfinger_no_touch) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -189,7 +165,7 @@ START_TEST(touchpad_2fg_clickfinger) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -219,7 +195,7 @@ START_TEST(touchpad_3fg_clickfinger) if (libevdev_get_num_slots(dev->evdev) < 3) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -254,7 +230,7 @@ START_TEST(touchpad_3fg_clickfinger_btntool) !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP)) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -293,7 +269,7 @@ START_TEST(touchpad_4fg_clickfinger) if (libevdev_get_num_slots(dev->evdev) < 4) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -338,7 +314,7 @@ START_TEST(touchpad_4fg_clickfinger_btntool_2slots) !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_QUADTAP)) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -384,7 +360,7 @@ START_TEST(touchpad_4fg_clickfinger_btntool_3slots) !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_TRIPLETAP)) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -435,7 +411,7 @@ START_TEST(touchpad_2fg_clickfinger_distance) h < 50.0) small_touchpad = true; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -490,7 +466,7 @@ START_TEST(touchpad_3fg_clickfinger_distance) if (libevdev_get_num_slots(dev->evdev) < 3) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -524,7 +500,7 @@ START_TEST(touchpad_3fg_clickfinger_distance_btntool) if (libevdev_get_num_slots(dev->evdev) > 2) return; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -628,7 +604,7 @@ START_TEST(touchpad_clickfinger_to_area_method) litest_drain_events(li); - enable_buttonareas(dev); + litest_enable_buttonareas(dev); litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -643,7 +619,7 @@ START_TEST(touchpad_clickfinger_to_area_method) litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_RELEASED); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -671,7 +647,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down) litest_drain_events(li); - enable_buttonareas(dev); + litest_enable_buttonareas(dev); litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -680,7 +656,7 @@ START_TEST(touchpad_clickfinger_to_area_method_while_down) litest_assert_button_event(li, BTN_RIGHT, LIBINPUT_BUTTON_STATE_PRESSED); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_event(dev, EV_KEY, BTN_LEFT, 0); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -714,7 +690,7 @@ START_TEST(touchpad_area_to_clickfinger_method) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -732,7 +708,7 @@ START_TEST(touchpad_area_to_clickfinger_method) litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_RELEASED); - enable_buttonareas(dev); + litest_enable_buttonareas(dev); litest_touch_down(dev, 0, 95, 95); litest_event(dev, EV_KEY, BTN_LEFT, 1); @@ -755,7 +731,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -766,7 +742,7 @@ START_TEST(touchpad_area_to_clickfinger_method_while_down) litest_assert_button_event(li, BTN_LEFT, LIBINPUT_BUTTON_STATE_PRESSED); - enable_buttonareas(dev); + litest_enable_buttonareas(dev); litest_event(dev, EV_KEY, BTN_LEFT, 0); litest_event(dev, EV_SYN, SYN_REPORT, 0); @@ -797,7 +773,7 @@ START_TEST(touchpad_clickfinger_3fg_tool_position) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); /* one in thumb area, one in normal area + TRIPLETAP. spread is wide @@ -827,7 +803,7 @@ START_TEST(touchpad_clickfinger_4fg_tool_position) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); litest_touch_down(dev, 0, 5, 99); @@ -878,7 +854,7 @@ START_TEST(clickpad_btn_left) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_buttonareas(dev); + litest_enable_buttonareas(dev); litest_drain_events(li); @@ -1487,7 +1463,7 @@ START_TEST(clickpad_topsoftbuttons_clickfinger) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); @@ -1534,7 +1510,7 @@ START_TEST(clickpad_topsoftbuttons_clickfinger_dev_disabled) libinput_device_config_send_events_set_mode(dev->libinput_device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); litest_touch_down(dev, 0, 90, 5); diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index f6986e70..00afcdbe 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -32,30 +32,6 @@ #include "libinput-util.h" #include "litest.h" -static inline void -enable_drag_lock(struct libinput_device *device) -{ - enum libinput_config_status status, expected; - - expected = LIBINPUT_CONFIG_STATUS_SUCCESS; - status = libinput_device_config_tap_set_drag_lock_enabled(device, - LIBINPUT_CONFIG_DRAG_LOCK_ENABLED); - - litest_assert_int_eq(status, expected); -} - -static inline void -disable_drag_lock(struct libinput_device *device) -{ - enum libinput_config_status status, expected; - - expected = LIBINPUT_CONFIG_STATUS_SUCCESS; - status = libinput_device_config_tap_set_drag_lock_enabled(device, - LIBINPUT_CONFIG_DRAG_LOCK_DISABLED); - - litest_assert_int_eq(status, expected); -} - START_TEST(touchpad_1fg_tap) { struct litest_device *dev = litest_current_device(); @@ -467,7 +443,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap) ntaps; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -540,7 +516,7 @@ START_TEST(touchpad_1fg_multitap_n_drag_tap_click) ntaps; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -621,7 +597,7 @@ START_TEST(touchpad_1fg_tap_n_drag) struct libinput_event_pointer *ptrev __attribute__((unused)); litest_enable_tap(dev->libinput_device); - disable_drag_lock(dev->libinput_device); + litest_disable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -663,7 +639,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock) struct libinput *li = dev->libinput; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -704,7 +680,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_tap) struct libinput *li = dev->libinput; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -746,7 +722,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_tap_click) struct libinput *li = dev->libinput; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -791,7 +767,7 @@ START_TEST(touchpad_1fg_tap_n_drag_draglock_timeout) struct libinput *li = dev->libinput; litest_enable_tap(dev->libinput_device); - enable_drag_lock(dev->libinput_device); + litest_enable_drag_lock(dev->libinput_device); litest_drain_events(li); @@ -822,7 +798,7 @@ START_TEST(touchpad_2fg_tap_n_drag) struct libinput *li = dev->libinput; litest_enable_tap(dev->libinput_device); - disable_drag_lock(dev->libinput_device); + litest_disable_drag_lock(dev->libinput_device); litest_drain_events(li); diff --git a/test/touchpad.c b/test/touchpad.c index 84898618..a6989e79 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -32,75 +32,6 @@ #include "libinput-util.h" #include "litest.h" -static bool -has_2fg_scroll(struct litest_device *dev) -{ - struct libinput_device *device = dev->libinput_device; - - return !!(libinput_device_config_scroll_get_methods(device) & - LIBINPUT_CONFIG_SCROLL_2FG); -} - -static void -enable_2fg_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_2FG); - - expected = LIBINPUT_CONFIG_STATUS_SUCCESS; - litest_assert_int_eq(status, expected); -} - -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); -} - -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); -} - -static inline int -is_synaptics_semi_mt(struct litest_device *dev) -{ - struct libevdev *evdev = dev->evdev; - - return libevdev_has_property(evdev, INPUT_PROP_SEMI_MT) && - libevdev_get_id_vendor(evdev) == 0x2 && - libevdev_get_id_product(evdev) == 0x7; -} - START_TEST(touchpad_1fg_motion) { struct litest_device *dev = litest_current_device(); @@ -192,10 +123,10 @@ START_TEST(touchpad_2fg_scroll) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); test_2fg_scroll(dev, 0.1, 40, 0); @@ -222,7 +153,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance) const struct input_absinfo *y; double y_move; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; /* We want to move > 5 mm. */ @@ -234,7 +165,7 @@ START_TEST(touchpad_2fg_scroll_slow_distance) y_move = 20.0; } - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 49, 50); @@ -279,10 +210,10 @@ START_TEST(touchpad_2fg_scroll_source) struct libinput_event *event; struct libinput_event_pointer *ptrev; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); test_2fg_scroll(dev, 0, 30, 0); @@ -304,10 +235,10 @@ START_TEST(touchpad_2fg_scroll_semi_mt) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 20, 20); @@ -328,10 +259,10 @@ START_TEST(touchpad_2fg_scroll_return_to_motion) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); /* start with motion */ @@ -399,10 +330,10 @@ START_TEST(touchpad_scroll_natural_2fg) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - if (!has_2fg_scroll(dev)) + if (!litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_drain_events(li); libinput_device_config_scroll_set_natural_scroll_enabled(dev->libinput_device, 1); @@ -425,7 +356,7 @@ START_TEST(touchpad_edge_scroll) struct libinput *li = dev->libinput; litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_touch_down(dev, 0, 99, 20); litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0); @@ -472,13 +403,13 @@ START_TEST(touchpad_scroll_defaults) method = libinput_device_config_scroll_get_methods(device); ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE); if (libevdev_get_num_slots(evdev) > 1 && - !is_synaptics_semi_mt(dev)) + !litest_is_synaptics_semi_mt(dev)) ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG); else ck_assert((method & LIBINPUT_CONFIG_SCROLL_2FG) == 0); if (libevdev_get_num_slots(evdev) > 1 && - !is_synaptics_semi_mt(dev)) + !litest_is_synaptics_semi_mt(dev)) expected = LIBINPUT_CONFIG_SCROLL_2FG; else expected = LIBINPUT_CONFIG_SCROLL_EDGE; @@ -495,7 +426,7 @@ START_TEST(touchpad_scroll_defaults) LIBINPUT_CONFIG_SCROLL_2FG); if (libevdev_get_num_slots(evdev) > 1 && - !is_synaptics_semi_mt(dev)) + !litest_is_synaptics_semi_mt(dev)) ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_SUCCESS); else ck_assert_int_eq(status, LIBINPUT_CONFIG_STATUS_UNSUPPORTED); @@ -522,7 +453,7 @@ START_TEST(touchpad_edge_scroll_timeout) } litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_touch_down(dev, 0, 99, 20); libinput_dispatch(li); @@ -568,7 +499,7 @@ START_TEST(touchpad_edge_scroll_no_motion) struct libinput *li = dev->libinput; litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_touch_down(dev, 0, 99, 10); litest_touch_move_to(dev, 0, 99, 10, 99, 70, 10, 0); @@ -590,7 +521,7 @@ START_TEST(touchpad_edge_scroll_no_edge_after_motion) struct libinput *li = dev->libinput; litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); /* moving into the edge zone must not trigger scroll events */ litest_touch_down(dev, 0, 20, 20); @@ -612,7 +543,7 @@ START_TEST(touchpad_edge_scroll_source) struct libinput_event_pointer *ptrev; litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_touch_down(dev, 0, 99, 20); litest_touch_move_to(dev, 0, 99, 20, 99, 80, 10, 0); @@ -637,7 +568,7 @@ START_TEST(touchpad_edge_scroll_no_2fg) struct libinput *li = dev->libinput; litest_drain_events(li); - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_touch_down(dev, 0, 49, 50); litest_touch_down(dev, 1, 51, 50); @@ -656,8 +587,8 @@ 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_enable_buttonareas(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 99, 40); @@ -682,8 +613,8 @@ 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_enable_buttonareas(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 20, 99); @@ -710,8 +641,8 @@ START_TEST(touchpad_edge_scroll_buttonareas_click_stops_scroll) struct libinput_event_pointer *ptrev; double val; - enable_buttonareas(dev); - enable_edge_scroll(dev); + litest_enable_buttonareas(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 20, 95); @@ -757,8 +688,8 @@ START_TEST(touchpad_edge_scroll_clickfinger_click_stops_scroll) struct libinput_event_pointer *ptrev; double val; - enable_clickfinger(dev); - enable_edge_scroll(dev); + litest_enable_clickfinger(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); litest_touch_down(dev, 0, 20, 95); @@ -802,7 +733,7 @@ START_TEST(touchpad_edge_scroll_into_area) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); /* move into area, move vertically, move back to edge */ @@ -846,10 +777,10 @@ START_TEST(touchpad_palm_detect_at_edge) struct libinput *li = dev->libinput; if (!touchpad_has_palm_detect_size(dev) || - !has_2fg_scroll(dev)) + !litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_disable_tap(dev->libinput_device); @@ -875,7 +806,7 @@ START_TEST(touchpad_no_palm_detect_at_edge_for_edge_scrolling) if (!touchpad_has_palm_detect_size(dev)) return; - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_drain_events(li); @@ -893,10 +824,10 @@ START_TEST(touchpad_palm_detect_at_bottom_corners) struct libinput *li = dev->libinput; if (!touchpad_has_palm_detect_size(dev) || - !has_2fg_scroll(dev)) + !litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_disable_tap(dev->libinput_device); @@ -922,10 +853,10 @@ START_TEST(touchpad_palm_detect_at_top_corners) struct libinput *li = dev->libinput; if (!touchpad_has_palm_detect_size(dev) || - !has_2fg_scroll(dev)) + !litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_disable_tap(dev->libinput_device); @@ -951,10 +882,10 @@ START_TEST(touchpad_palm_detect_palm_stays_palm) struct libinput *li = dev->libinput; if (!touchpad_has_palm_detect_size(dev) || - !has_2fg_scroll(dev)) + !litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_disable_tap(dev->libinput_device); @@ -973,10 +904,10 @@ START_TEST(touchpad_palm_detect_palm_becomes_pointer) struct libinput *li = dev->libinput; if (!touchpad_has_palm_detect_size(dev) || - !has_2fg_scroll(dev)) + !litest_has_2fg_scroll(dev)) return; - enable_2fg_scroll(dev); + litest_enable_2fg_scroll(dev); litest_disable_tap(dev->libinput_device); @@ -2571,7 +2502,7 @@ START_TEST(touchpad_dwt_edge_scroll) if (!has_disable_while_typing(touchpad)) return; - enable_edge_scroll(touchpad); + litest_enable_edge_scroll(touchpad); keyboard = litest_add_device(li, LITEST_KEYBOARD); litest_drain_events(li); @@ -2618,7 +2549,7 @@ START_TEST(touchpad_dwt_edge_scroll_interrupt) if (!has_disable_while_typing(touchpad)) return; - enable_edge_scroll(touchpad); + litest_enable_edge_scroll(touchpad); keyboard = litest_add_device(li, LITEST_KEYBOARD); litest_drain_events(li); @@ -2977,7 +2908,7 @@ START_TEST(touchpad_thumb_update_no_motion) }; litest_disable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); if (!has_thumb_detect(dev)) return; @@ -3003,7 +2934,7 @@ START_TEST(touchpad_thumb_moving) }; litest_disable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); if (!has_thumb_detect(dev)) return; @@ -3127,7 +3058,7 @@ START_TEST(touchpad_thumb_edgescroll) if (!has_thumb_detect(dev)) return; - enable_edge_scroll(dev); + litest_enable_edge_scroll(dev); litest_disable_tap(dev->libinput_device); litest_drain_events(li); @@ -3159,7 +3090,7 @@ START_TEST(touchpad_thumb_tap_begin) return; litest_enable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); /* touch down is a thumb */ @@ -3192,7 +3123,7 @@ START_TEST(touchpad_thumb_tap_touch) return; litest_enable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); /* event after touch down is thumb */ @@ -3225,7 +3156,7 @@ START_TEST(touchpad_thumb_tap_hold) return; litest_enable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); /* event in state HOLD is thumb */ @@ -3259,7 +3190,7 @@ START_TEST(touchpad_thumb_tap_hold_2ndfg) return; litest_enable_tap(dev->libinput_device); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); litest_drain_events(li); /* event in state HOLD is thumb */ @@ -3368,7 +3299,7 @@ START_TEST(touchpad_tool_tripletap_touch_count) * https://bugs.freedesktop.org/show_bug.cgi?id=91352 */ litest_drain_events(li); - enable_clickfinger(dev); + litest_enable_clickfinger(dev); /* touch 1 down */ litest_event(dev, EV_ABS, ABS_MT_SLOT, 0); From 7b6bd641c7dcd03ff13ced94827b971bf2df9290 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 10:43:30 +1000 Subject: [PATCH 24/37] touchpad: move CAP_GESTURE assignment to the touchpad code That's where we set the pointer cap too. No functional changes. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 1 + src/evdev.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ee1612e4..e110b9ae 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1918,6 +1918,7 @@ tp_init(struct tp_dispatch *tp, return -1; device->seat_caps |= EVDEV_DEVICE_POINTER; + device->seat_caps |= EVDEV_DEVICE_GESTURE; return 0; } diff --git a/src/evdev.c b/src/evdev.c index ee904d31..aba124be 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1950,7 +1950,6 @@ evdev_configure_device(struct evdev_device *device) if (udev_tags & EVDEV_UDEV_TAG_TOUCHPAD) { device->dispatch = evdev_mt_touchpad_create(device); - device->seat_caps |= EVDEV_DEVICE_GESTURE; log_info(libinput, "input device '%s', %s is a touchpad\n", device->devname, devnode); From 424a172b1b075d1a2cf713bba3e412a64caad1f8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Jul 2015 12:41:12 +1000 Subject: [PATCH 25/37] tools: fix the velocity range for printing the ptraccel profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now using µs. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- tools/ptraccel-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index 1496763b..b0867db3 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -147,12 +147,12 @@ print_accel_func(struct motion_filter *filter) printf("# set ylabel \"raw accel factor\"\n"); printf("# set style data lines\n"); printf("# plot \"gnuplot.data\" using 1:2\n"); - for (vel = 0.0; vel < 3.0; vel += .0001) { + for (vel = 0.0; vel < 0.003; vel += 0.0000001) { double result = pointer_accel_profile_linear(filter, NULL, vel, 0 /* time */); - printf("%.4f\t%.4f\n", vel, result); + printf("%.8f\t%.4f\n", vel, result); } } From 26c8f2c442ac476027111ce7429c1a7897732d20 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Jul 2015 14:49:30 +1000 Subject: [PATCH 26/37] =?UTF-8?q?filter:=20fix=20x230=20acceleration=20fun?= =?UTF-8?q?ction=20for=20the=20ms=E2=86=92us=20change?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filter.c b/src/filter.c index f8f94096..54ae3978 100644 --- a/src/filter.c +++ b/src/filter.c @@ -493,8 +493,8 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; - s1 = min(1, speed_in * 5); - s2 = 1 + (speed_in - threshold) * incline; + s1 = min(1, speed_in * 5 * 1000.0); + s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; speed_out = min(max_accel, s2 > 1 ? s2 : s1); From 8a6825f1602aa9d9c4b29a83d296f55f68b316e0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Jul 2015 14:52:56 +1000 Subject: [PATCH 27/37] filter: move the pointer acceleration profiles back to units/ms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need here to use µs since we're just handling speeds/thresholds, not actual events where a ms granularity can be too high. Moving back to ms lets us drop a bunch of zeroes that clutter up the code, and since the acceleration functions are a bit magic anyway, having the various 1000.0 factors in there makes it even less obvious. Signed-off-by: Peter Hutterer Reviewed-by: Jonas Ådahl --- src/filter.c | 50 +++++++++++++++++++++--------------------- tools/ptraccel-debug.c | 4 ++-- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/filter.c b/src/filter.c index 54ae3978..2506ee27 100644 --- a/src/filter.c +++ b/src/filter.c @@ -77,7 +77,7 @@ filter_get_speed(struct motion_filter *filter) * Default parameters for pointer acceleration profiles. */ -#define DEFAULT_THRESHOLD 0.0004 /* in units/us */ +#define DEFAULT_THRESHOLD 0.4 /* in units/ms */ #define DEFAULT_ACCELERATION 2.0 /* unitless factor */ #define DEFAULT_INCLINE 1.1 /* unitless factor */ @@ -85,7 +85,7 @@ filter_get_speed(struct motion_filter *filter) * Pointer acceleration filter constants */ -#define MAX_VELOCITY_DIFF 0.001 /* units/us */ +#define MAX_VELOCITY_DIFF 1 /* units/ms */ #define MOTION_TIMEOUT ms2us(1000) #define NUM_POINTER_TRACKERS 16 @@ -101,14 +101,14 @@ struct pointer_accelerator { accel_profile_func_t profile; - double velocity; /* units/us */ - double last_velocity; /* units/us */ + double velocity; /* units/ms */ + double last_velocity; /* units/ms */ struct normalized_coords last; struct pointer_tracker *trackers; int cur_tracker; - double threshold; /* units/us */ + double threshold; /* units/ms */ double accel; /* unitless factor */ double incline; /* incline of the function */ @@ -150,7 +150,7 @@ static double calculate_tracker_velocity(struct pointer_tracker *tracker, uint64_t time) { double tdelta = time - tracker->time + 1; - return normalized_length(tracker->delta) / tdelta; /* units/us */ + return normalized_length(tracker->delta) / tdelta * 1000.0; /* units/ms */ } static inline double @@ -220,7 +220,7 @@ calculate_velocity(struct pointer_accelerator *accel, uint64_t time) } } - return result; /* units/us */ + return result; /* units/ms */ } static double @@ -256,11 +256,11 @@ calculate_acceleration(struct pointer_accelerator *accel, static struct normalized_coords accelerator_filter(struct motion_filter *filter, const struct normalized_coords *unaccelerated, - void *data, uint64_t time) + void *data, uint64_t time /* in us */) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; - double velocity; /* units/us */ + double velocity; /* units/ms */ double accel_value; /* unitless factor */ struct normalized_coords accelerated; struct normalized_coords unnormalized; @@ -397,23 +397,23 @@ create_pointer_accelerator_filter(accel_profile_func_t profile, double pointer_accel_profile_linear_low_dpi(struct motion_filter *filter, void *data, - double speed_in, /* in device units (units/us) */ - uint64_t time) + double speed_in, /* in device units (units/ms) */ + uint64_t time /* in us */) { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; double s1, s2; double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/us */ + const double threshold = accel_filter->threshold; /* units/ms */ const double incline = accel_filter->incline; double factor; double dpi_factor = accel_filter->dpi_factor; max_accel /= dpi_factor; - s1 = min(1, 0.3 + speed_in * 10000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * dpi_factor * 1000.0) * incline; + s1 = min(1, 0.3 + speed_in * 10.0); + s2 = 1 + (speed_in - threshold * dpi_factor) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -424,19 +424,19 @@ double pointer_accel_profile_linear(struct motion_filter *filter, void *data, double speed_in, /* 1000-dpi normalized */ - uint64_t time) + uint64_t time /* in us */) { struct pointer_accelerator *accel_filter = (struct pointer_accelerator *)filter; double s1, s2; const double max_accel = accel_filter->accel; /* unitless factor */ - const double threshold = accel_filter->threshold; /* units/us */ + const double threshold = accel_filter->threshold; /* units/ms */ const double incline = accel_filter->incline; double factor; - s1 = min(1, 0.3 + speed_in * 10 * 1000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + s1 = min(1, 0.3 + speed_in * 10); + s2 = 1 + (speed_in - threshold) * incline; factor = min(max_accel, s2 > 1 ? s2 : s1); @@ -445,9 +445,9 @@ pointer_accel_profile_linear(struct motion_filter *filter, double touchpad_accel_profile_linear(struct motion_filter *filter, - void *data, - double speed_in, - uint64_t time) + void *data, + double speed_in, + uint64_t time /* in us */) { /* Once normalized, touchpads see the same acceleration as mice. that is technically correct but @@ -468,7 +468,7 @@ double touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, void *data, double speed_in, - uint64_t time) + uint64_t time /* in us */) { /* Keep the magic factor from touchpad_accel_profile_linear. */ const double TP_MAGIC_SLOWDOWN = 0.4; @@ -488,13 +488,13 @@ touchpad_lenovo_x230_accel_profile(struct motion_filter *filter, const double max_accel = accel_filter->accel * TP_MAGIC_LOW_RES_FACTOR; /* unitless factor */ const double threshold = accel_filter->threshold / - TP_MAGIC_LOW_RES_FACTOR; /* units/us */ + TP_MAGIC_LOW_RES_FACTOR; /* units/ms */ const double incline = accel_filter->incline * TP_MAGIC_LOW_RES_FACTOR; speed_in *= TP_MAGIC_SLOWDOWN / TP_MAGIC_LOW_RES_FACTOR; - s1 = min(1, speed_in * 5 * 1000.0); - s2 = 1 + (speed_in * 1000.0 - threshold * 1000.0) * incline; + s1 = min(1, speed_in * 5); + s2 = 1 + (speed_in - threshold) * incline; speed_out = min(max_accel, s2 > 1 ? s2 : s1); diff --git a/tools/ptraccel-debug.c b/tools/ptraccel-debug.c index b0867db3..1496763b 100644 --- a/tools/ptraccel-debug.c +++ b/tools/ptraccel-debug.c @@ -147,12 +147,12 @@ print_accel_func(struct motion_filter *filter) printf("# set ylabel \"raw accel factor\"\n"); printf("# set style data lines\n"); printf("# plot \"gnuplot.data\" using 1:2\n"); - for (vel = 0.0; vel < 0.003; vel += 0.0000001) { + for (vel = 0.0; vel < 3.0; vel += .0001) { double result = pointer_accel_profile_linear(filter, NULL, vel, 0 /* time */); - printf("%.8f\t%.4f\n", vel, result); + printf("%.4f\t%.4f\n", vel, result); } } From cbc0b20793382652b54df2b6d0e73529efcfda68 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 31 Jul 2015 16:50:02 +1000 Subject: [PATCH 28/37] test: fix test case failure caused by belated timer See 5cec16eede70f6df44b1c39faae614a66594d774 Signed-off-by: Peter Hutterer --- test/touchpad.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/touchpad.c b/test/touchpad.c index 84898618..6d5d5c83 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -2215,6 +2215,8 @@ START_TEST(touchpad_initial_state) litest_touch_down(dev, 0, x, y); litest_touch_move_to(dev, 0, x, y, 80, 80, 10, 1); litest_touch_up(dev, 0); + libinput_dispatch(libinput1); + libinput_dispatch(libinput2); litest_wait_for_event(libinput1); litest_wait_for_event(libinput2); From 6295118c8e1bd65e2ba562547cbdd2a080fb8e3f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 10:48:39 +1000 Subject: [PATCH 29/37] touchpad: make gestures optional Not all multi-finger touchpads are able to reliably produce gestures, so make it optional. This patch just adds a boolean (currently always true) that gets set on touchpad init time, i.e. it is not run-time configurable. Three and four-finger gestures are filtered out in gesture_notify(), if the cap isn't set the event is discarded. For two-finger gestures we prevent a transition to PINCH, so we don't inadvertently detect a pinch gesture and then not send events. This way, a 2fg gesture is always scroll. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 5 ++++- src/evdev-mt-touchpad.c | 3 ++- src/evdev-mt-touchpad.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 3b1839e4..da03c262 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -295,7 +295,7 @@ tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time) ((dir2 & 0x80) && (dir1 & 0x01))) { tp_gesture_set_scroll_buildup(tp); return GESTURE_2FG_STATE_SCROLL; - } else { + } else if (tp->gesture.enabled) { tp_gesture_get_pinch_info(tp, &tp->gesture.initial_distance, &tp->gesture.angle, @@ -303,6 +303,8 @@ tp_gesture_twofinger_handle_state_unknown(struct tp_dispatch *tp, uint64_t time) tp->gesture.prev_scale = 1.0; return GESTURE_2FG_STATE_PINCH; } + + return GESTURE_2FG_STATE_UNKNOWN; } static enum tp_gesture_2fg_state @@ -563,6 +565,7 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time) int tp_init_gesture(struct tp_dispatch *tp) { + tp->gesture.enabled = true; tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE; libinput_timer_init(&tp->gesture.finger_count_switch_timer, diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index e110b9ae..af1cd47a 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1918,7 +1918,8 @@ tp_init(struct tp_dispatch *tp, return -1; device->seat_caps |= EVDEV_DEVICE_POINTER; - device->seat_caps |= EVDEV_DEVICE_GESTURE; + if (tp->gesture.enabled) + device->seat_caps |= EVDEV_DEVICE_GESTURE; return 0; } diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index a7961e75..3bd84258 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -246,6 +246,7 @@ struct tp_dispatch { } accel; struct { + bool enabled; bool started; unsigned int finger_count; unsigned int finger_count_pending; From 96d0e06f13099f7107c3177e1e6ba8f702e86b83 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 11:07:58 +1000 Subject: [PATCH 30/37] touchpad: disable gestures on Synaptics semi-mt touchpads Follow-up to eb146677e, if we disable 2fg scrolling on those touchpads we should also disable gestures. The data doesn't magically become more useful. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 6 +++++- test/gestures.c | 8 ++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index da03c262..14821362 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -565,7 +565,11 @@ tp_gesture_handle_state(struct tp_dispatch *tp, uint64_t time) int tp_init_gesture(struct tp_dispatch *tp) { - tp->gesture.enabled = true; + if (tp->device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT) + tp->gesture.enabled = false; + else + tp->gesture.enabled = true; + tp->gesture.twofinger_state = GESTURE_2FG_STATE_NONE; libinput_timer_init(&tp->gesture.finger_count_switch_timer, diff --git a/test/gestures.c b/test/gestures.c index 3b7ba7bf..9e447248 100644 --- a/test/gestures.c +++ b/test/gestures.c @@ -34,8 +34,12 @@ START_TEST(gestures_cap) struct litest_device *dev = litest_current_device(); struct libinput_device *device = dev->libinput_device; - ck_assert(libinput_device_has_capability(device, - LIBINPUT_DEVICE_CAP_GESTURE)); + if (litest_is_synaptics_semi_mt(dev)) + ck_assert(!libinput_device_has_capability(device, + LIBINPUT_DEVICE_CAP_GESTURE)); + else + ck_assert(libinput_device_has_capability(device, + LIBINPUT_DEVICE_CAP_GESTURE)); } END_TEST From 6933062dab0fa65d131e44bab2f7ace3563d9731 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 11:46:13 +1000 Subject: [PATCH 31/37] touchpad: elantech touchpads can use a 2mm gesture motion threshold Unlike ALPS and Synaptics semi-mt touchpads, the Elantech touchpads appear to be precise enough to allow a smaller motion threshold before we decide on the type of gesture (pinch vs scroll). https://bugs.freedesktop.org/show_bug.cgi?id=91475 Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 4 +++- src/evdev.c | 1 + src/evdev.h | 1 + udev/90-libinput-model-quirks.hwdb | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 14821362..60174168 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -189,8 +189,10 @@ tp_gesture_get_direction(struct tp_dispatch *tp, struct tp_touch *touch) /* * Semi-mt touchpads have somewhat inaccurate coordinates when * 2 fingers are down, so use a slightly larger threshold. + * Elantech semi-mt touchpads are accurate enough though. */ - if (tp->semi_mt) + if (tp->semi_mt && + (tp->device->model_flags & EVDEV_MODEL_ELANTECH_TOUCHPAD) == 0) move_threshold = TP_MM_TO_DPI_NORMALIZED(4); else move_threshold = TP_MM_TO_DPI_NORMALIZED(2); diff --git a/src/evdev.c b/src/evdev.c index aba124be..17c26043 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1543,6 +1543,7 @@ evdev_read_model_flags(struct evdev_device *device) { "LIBINPUT_MODEL_ALPS_TOUCHPAD", EVDEV_MODEL_ALPS_TOUCHPAD }, { "LIBINPUT_MODEL_SYNAPTICS_SERIAL_TOUCHPAD", EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD }, { "LIBINPUT_MODEL_JUMPING_SEMI_MT", EVDEV_MODEL_JUMPING_SEMI_MT }, + { "LIBINPUT_MODEL_ELANTECH_TOUCHPAD", EVDEV_MODEL_ELANTECH_TOUCHPAD }, { NULL, EVDEV_MODEL_DEFAULT }, }; const struct model_map *m = model_map; diff --git a/src/evdev.h b/src/evdev.h index c7017ba5..be5df0d0 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -106,6 +106,7 @@ enum evdev_device_model { EVDEV_MODEL_ALPS_TOUCHPAD = (1 << 8), EVDEV_MODEL_SYNAPTICS_SERIAL_TOUCHPAD = (1 << 9), EVDEV_MODEL_JUMPING_SEMI_MT = (1 << 10), + EVDEV_MODEL_ELANTECH_TOUCHPAD = (1 << 11), }; struct mt_slot { diff --git a/udev/90-libinput-model-quirks.hwdb b/udev/90-libinput-model-quirks.hwdb index a34b8f17..cf4fbfaa 100644 --- a/udev/90-libinput-model-quirks.hwdb +++ b/udev/90-libinput-model-quirks.hwdb @@ -39,6 +39,7 @@ libinput:touchpad:input:b0005v05ACp* ########################################## libinput:name:*ETPS/2 Elantech Touchpad*:dmi:* LIBINPUT_ATTR_RESOLUTION_HINT=31x31 + LIBINPUT_MODEL_ELANTECH_TOUCHPAD=1 ########################################## # Google From 7013a20f8b6a441a5f80b84aa261c32dd8011f95 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 30 Jul 2015 11:54:38 +1000 Subject: [PATCH 32/37] touchpad: pretend the jumpy semi-mt touchpad is a single-touch touchpad The first finger is accurate, it's just the second finger that is imprecise, so we can't handle it as a true touch. Instead, revert the device back to being a single-touch touchpad and use the fake touch bits for second finger handling. Two-finger scrolling thus becomes usable though we will lose out on other features like thumb detection. Useful scrolling trumps that though. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 21 ++++++++++++++++----- test/touchpad-tap.c | 3 +++ test/touchpad.c | 9 +++------ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index af1cd47a..64ec4466 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1465,6 +1465,21 @@ tp_init_slots(struct tp_dispatch *tp, tp->semi_mt = libevdev_has_property(device->evdev, INPUT_PROP_SEMI_MT); + /* This device has a terrible resolution when two fingers are down, + * causing scroll jumps. The single-touch emulation ABS_X/Y is + * accurate but the ABS_MT_POSITION touchpoints report the bounding + * box and that causes jumps. So we simply pretend it's a single + * touch touchpad with the BTN_TOOL bits. + * See https://bugzilla.redhat.com/show_bug.cgi?id=1235175 for an + * explanation. + */ + if (tp->semi_mt && + (device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT)) { + tp->num_slots = 1; + tp->slot = 0; + tp->has_mt = false; + } + ARRAY_FOR_EACH(max_touches, m) { if (libevdev_has_event_code(device->evdev, EV_KEY, @@ -1526,11 +1541,7 @@ tp_scroll_get_methods(struct tp_dispatch *tp) { uint32_t methods = LIBINPUT_CONFIG_SCROLL_EDGE; - /* some Synaptics semi-mt touchpads have a terrible 2fg resolution, - * causing scroll jumps. For all other 2fg touchpads, we enable 2fg - * scrolling */ - if (tp->ntouches >= 2 && - (tp->device->model_flags & EVDEV_MODEL_JUMPING_SEMI_MT) == 0) + if (tp->ntouches >= 2) methods |= LIBINPUT_CONFIG_SCROLL_2FG; return methods; diff --git a/test/touchpad-tap.c b/test/touchpad-tap.c index 00afcdbe..62c7a5c3 100644 --- a/test/touchpad-tap.c +++ b/test/touchpad-tap.c @@ -241,6 +241,9 @@ START_TEST(touchpad_1fg_multitap_n_drag_2fg) int range = _i, ntaps; + if (litest_is_synaptics_semi_mt(dev)) + return; + litest_enable_tap(dev->libinput_device); litest_drain_events(li); diff --git a/test/touchpad.c b/test/touchpad.c index a6989e79..77c1d2d1 100644 --- a/test/touchpad.c +++ b/test/touchpad.c @@ -402,14 +402,12 @@ START_TEST(touchpad_scroll_defaults) method = libinput_device_config_scroll_get_methods(device); ck_assert(method & LIBINPUT_CONFIG_SCROLL_EDGE); - if (libevdev_get_num_slots(evdev) > 1 && - !litest_is_synaptics_semi_mt(dev)) + if (libevdev_get_num_slots(evdev) > 1) ck_assert(method & LIBINPUT_CONFIG_SCROLL_2FG); else ck_assert((method & LIBINPUT_CONFIG_SCROLL_2FG) == 0); - if (libevdev_get_num_slots(evdev) > 1 && - !litest_is_synaptics_semi_mt(dev)) + if (libevdev_get_num_slots(evdev) > 1) expected = LIBINPUT_CONFIG_SCROLL_2FG; else expected = LIBINPUT_CONFIG_SCROLL_EDGE; @@ -425,8 +423,7 @@ START_TEST(touchpad_scroll_defaults) status = libinput_device_config_scroll_set_method(device, LIBINPUT_CONFIG_SCROLL_2FG); - if (libevdev_get_num_slots(evdev) > 1 && - !litest_is_synaptics_semi_mt(dev)) + 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); From 441db3afb1c5be794e7431f77f3ffbde9440767e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 3 Aug 2015 14:28:43 +1000 Subject: [PATCH 33/37] doc: add a page about touchpads Signed-off-by: Peter Hutterer --- doc/Makefile.am | 3 +- doc/touchpads.dox | 162 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 doc/touchpads.dox diff --git a/doc/Makefile.am b/doc/Makefile.am index 01bcd1b5..c9dccfda 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -24,7 +24,8 @@ header_files = \ $(srcdir)/t440-support.dox \ $(srcdir)/tapping.dox \ $(srcdir)/test-suite.dox \ - $(srcdir)/tools.dox + $(srcdir)/tools.dox \ + $(srcdir)/touchpads.dox diagram_files = \ $(srcdir)/dot/seats-sketch.gv \ diff --git a/doc/touchpads.dox b/doc/touchpads.dox new file mode 100644 index 00000000..fa509bc6 --- /dev/null +++ b/doc/touchpads.dox @@ -0,0 +1,162 @@ +/** +@page touchpads Touchpads + +This page provides an outline of touchpad devices. Touchpads aren't simply +categorised into a single type, instead they have a set of properties, a +combination of number of physical buttons, multitouch support abilities and +other properties. + +@section touchpads_buttons Number of buttons + +@subsection touchapds_buttons_phys Physically separate buttons + +Touchpads with physical buttons usually provide two buttons, left and right. +A few touchpads with three buttons exist, and Apple used to have touchpads +with a single physical buttons until ca 2008. Touchpads with only two +buttons require the software stack to emulate a middle button. libinput does +this when both buttons are pressed simultaneously. + +Note that many Lenovo laptops provide a pointing stick above the touchpad. +This pointing stick has a set of physical buttons just above the touchpad. +While many users use those as substitute touchpad buttons, they logically +belong to the pointing stick. The *40 and *50 series are an exception here, +the former had no physical buttons on the touchpad and required the top +section of the pad to emulate pointing stick buttons, the *50 series has +physical buttons but they are wired to the touchpads. The kernel re-routes +those buttons through the trackstick device. See @ref t440_support for more +information. + +@subsection touchpads_buttons_clickpads Clickpads + +Clickpads are the most common type of touchpads these days. A Clickpad has +no separate physical buttons, instead the touchpad itself is clickable as a +whole, i.e. a user presses down on the touch area and triggers a physical +click. Clickpads thus only provide a single button, everything else needs to +be software-emulated. See @ref clickpad_softbuttons for more information. + +Clickpads are labelled by the kernel with the @c INPUT_PROP_BUTTONPAD input +property. + +@subsection touchpads_buttons_forcepads Forcepads + +Forcepads are Clickpads without a physical button underneath the hardware. +They provide pressure and may have a vibration element that is +software-controlled. This element can simulate the feel of a physical +click or be co-opted for other tasks. + + +@section touchpads_touch Touch capabilities + +Virtually all touchpads available now can detect multiple fingers on +the touchpad, i.e. provide information on how many fingers are on the +touchpad. The touch capabilities described here specify how many fingers a +device can track, i.e. provide reliable positional information for. +In the kernel each finger is tracked in a so-called "slot", the number of +slots thus equals the number of simultaneous touches a device can track. + +@subsection touchapds_touch_st Single-touch touchpads + +Single-finger touchpads can track a single touchpoint. Most single-touch +touchpads can also detect three fingers on the touchpad, but no positional +information is provided for those. In libinput, these touches are termed +"fake touches". The kernel sends @c BTN_TOOL_DOUBLETAP, @c +BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events when +multiple fingers are detected. + +@subsection touchpads_touch_mt Pure multi-touch touchpads + +Pure multi-touch touchpads are those that can track, i.e. identify the +location of all fingers on the touchpad. Apple's touchpads support 16 +touches, others support 5 touches like the Synaptics touchpads when using +SMBus. + +These touchpads usually also provide extra information. Apple touchpads +provide an ellipsis and the orientation of the ellipsis for each touch point. +Other touchpads provide a pressure value for each touch point (see @ref +touchpads_pressure_handling). + +Note that the kernel sends @c BTN_TOOL_DOUBLETAP, @c +BTN_TOOL_TRIPLETAP, @c BTN_TOOL_QUADTAP and @c BTN_TOOL_QUINTTAP events for +all touches for backwards compatibility. libinput ignores these events if +the touchpad can track touches correctly. + +@subsection touchpads_touch_partial_mt Partial multi-touch touchpads + +The vast majority of touchpads fall into this category, the half-way +point between single-touch and pure multi-touch. These devices can track N +fingers, but detect more than N. For example, when using the serial +protocol, Synaptics touchpads can track two fingers but may detect up to +five. + +The number of slots may limit which features are available in libinput. +Any device with two slots can support two-finger scrolling, but @ref +thumb-detection or @ref palm_detection may be limited if only two slots are +available. + +@subsection touchpads_touch_semi_mt Semi-mt touchpads + +A sub-class of partial multi-touch touchpads. These touchpads can +technically detect two fingers but the location of both is limited to the +bounding box, i.e. the first touch is always the top-left one and the second +touch is the bottom-right one. Coordinates jump around as fingers move past +each other. + +Many semi-mt touchpads also have a lower resolution for the second touch, or +both touches. This may limit some features such as @ref gestures or +@ref scrolling. + +Semi-mt are labelled by the kernel with the @c INPUT_PROP_SEMI_MT input +property. + +@section touchpads_mis Other touchpad properties + +@subsection touchpads_external External touchpads + +External touchpads are USB or Bluetooth touchpads not in a laptop chassis, +e.g. Apple Magic Trackpad or the Logitech T650. These are usually @ref +touchpads_buttons_clickpads the biggest difference is that they can be +removed or added at runtime. + +One interaction method that is only possible on external touchpads is a +thumb resting on the very edge/immediately next to the touchpad. On the far +edge, touchpads don't always detect the finger location so clicking with a +thumb barely touching the edge makes it hard or impossible to figure out +which software button area the finger is on. + +These touchpads also don't need @ref palm_detection - since they're not +located underneath the keyboard, accidental palm touches are a non-issue. + +@subsection touchpads_pressure_handling Touchpads pressure handling + +Pressure is usually directly related to contact area. Human fingers flatten +out as the pressure on the pad increases, resulting in a bigger contact area +and the firmware then calculates that back into a ressure reading. + +libinput uses pressure to detect accidental palm contact and thumbs, though +pressure data is often device-specific and unreliable. + +@subsection touchpads_circular Circular touchpads + +Only listed for completeness, circular touchpads have not been used in +laptops for a number of years. These touchpad shaped in an ellipsis or +straight. + +@subsection touchpads_tablets Graphics tablets + +Touch-capable graphics tablets are effectively external touchpads, with two +differentiators: they are larger than normal touchpads and they have no +regular touchpad buttons. They either work like a @ref +touchpads_buttons_forcepads Forcepad, or rely on interaction methods that +don't require buttons (like @ref tapping). Since the physical device is +shared with the pen input, some touch arbitration is required to avoid touch +input interfering when the pen is in use. + +@subsection touchpads_edge_zone Dedicated edge scroll area + +Before @ref twofinger_scrolling became the default scroll method, some +touchpads provided a marking on the touch area that designates the +edge to be used for scrolling. A finger movement in that edge zone should +trigger vertical motions. Some touchpads had markers for a horizontal +scroll area too at the bottom of the touchpad. +*/ + From d823a3da0ad74f68e89ef5a0e8660c99b7eaf348 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 3 Aug 2015 15:08:57 +1000 Subject: [PATCH 34/37] gestures: reduce 2fg scroll timeout to 500ms Holding the fingers in place without moving for 500ms is long enough to lock in a scroll gesture, especially while we're still waiting for the rest of the stack to expose pinch gestures. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad-gestures.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c index 60174168..d82a6fb9 100644 --- a/src/evdev-mt-touchpad-gestures.c +++ b/src/evdev-mt-touchpad-gestures.c @@ -30,7 +30,7 @@ #include "evdev-mt-touchpad.h" #define DEFAULT_GESTURE_SWITCH_TIMEOUT ms2us(100) -#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(1000) +#define DEFAULT_GESTURE_2FG_SCROLL_TIMEOUT ms2us(500) static inline const char* gesture_state_to_str(enum tp_gesture_2fg_state state) From f03f447590d12f1a9bcc52065a3e476df67479d6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 28 Jul 2015 13:25:45 +1000 Subject: [PATCH 35/37] touchpad: always enable the bottom-most area for thumb detection If the touchpad is higher than 50mm, enable bottom area thumb detection. This only applies to the bottom-most 8mm and only if the touch remains unmoving in that area. Signed-off-by: Peter Hutterer Reviewed-by: Hans de Goede --- src/evdev-mt-touchpad.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 64ec4466..a683d9a4 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1765,13 +1765,6 @@ tp_init_thumb(struct tp_dispatch *tp) if (!tp->buttons.is_clickpad) return 0; - abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE); - if (!abs) - return 0; - - if (abs->maximum - abs->minimum < 255) - return 0; - /* if the touchpad is less than 50mm high, skip thumb detection. * it's too small to meaningfully interact with a thumb on the * touchpad */ @@ -1779,6 +1772,23 @@ tp_init_thumb(struct tp_dispatch *tp) if (h < 50) return 0; + tp->thumb.detect_thumbs = true; + tp->thumb.threshold = INT_MAX; + + /* detect thumbs by pressure in the bottom 15mm, detect thumbs by + * lingering in the bottom 8mm */ + ymax = tp->device->abs.absinfo_y->maximum; + yres = tp->device->abs.absinfo_y->resolution; + tp->thumb.upper_thumb_line = ymax - yres * 15; + tp->thumb.lower_thumb_line = ymax - yres * 8; + + abs = libevdev_get_abs_info(device->evdev, ABS_MT_PRESSURE); + if (!abs) + goto out; + + if (abs->maximum - abs->minimum < 255) + goto out; + /* Our reference touchpad is the T440s with 42x42 resolution. * Higher-res touchpads exhibit higher pressure for the same * interaction. On the T440s, the threshold value is 100, you don't @@ -1790,17 +1800,11 @@ tp_init_thumb(struct tp_dispatch *tp) yres = tp->device->abs.absinfo_y->resolution; threshold = 100.0 * hypot(xres, yres)/hypot(42, 42); tp->thumb.threshold = max(100, threshold); - tp->thumb.detect_thumbs = true; - - /* detect thumbs by pressure in the bottom 15mm, detect thumbs by - * lingering in the bottom 8mm */ - ymax = tp->device->abs.absinfo_y->maximum; - yres = tp->device->abs.absinfo_y->resolution; - tp->thumb.upper_thumb_line = ymax - yres * 15; - tp->thumb.lower_thumb_line = ymax - yres * 8; +out: log_debug(tp_libinput_context(tp), - "thumb: enabled thumb detection on '%s'\n", + "thumb: enabled thumb detection%s on '%s'\n", + tp->thumb.threshold != INT_MAX ? " (+pressure)" : "", device->devname); return 0; From e625d2d24ba393601c36283e52fcf4abb6b14b99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 10:25:47 +1000 Subject: [PATCH 36/37] udev: include new udev rule in EXTRA_DIST Fixes distcheck Signed-off-by: Peter Hutterer --- udev/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/udev/Makefile.am b/udev/Makefile.am index 975f5370..cfb854e1 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -33,3 +33,4 @@ CLEANFILES = $(litest_rules) DISTCLEANFILES = \ 80-libinput-device-groups.rules \ 90-libinput-model-quirks.rules +EXTRA_DIST = 80-libinput-test-device.rules From 603ac39e3b76fff453410995d7f11c9ace504ec6 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 4 Aug 2015 10:09:43 +1000 Subject: [PATCH 37/37] configure.ac: libinput 0.21.0 Signed-off-by: Peter Hutterer --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index e186d4e8..0d5d486c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ AC_PREREQ([2.64]) m4_define([libinput_major_version], [0]) -m4_define([libinput_minor_version], [20]) +m4_define([libinput_minor_version], [21]) m4_define([libinput_micro_version], [0]) m4_define([libinput_version], [libinput_major_version.libinput_minor_version.libinput_micro_version]) @@ -31,7 +31,7 @@ AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) # b) If interfaces have been changed or added, but binary compatibility has # been preserved, change to C+1:0:A+1 # c) If the interface is the same as the previous version, change to C:R+1:A -LIBINPUT_LT_VERSION=14:0:4 +LIBINPUT_LT_VERSION=15:0:5 AC_SUBST(LIBINPUT_LT_VERSION) AM_SILENT_RULES([yes])