From 817b4343ffa6e3db86e841f933e94230ccc2e112 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 5 Sep 2017 16:08:09 +1000 Subject: [PATCH] Don't try pinching when the finger number exceeds available slots Don't resume a disabled touchpad after a lid switch open (#1448962) --- ...on-t-try-to-pinch-for-nfingers-slots.patch | 282 ++++++++++++++++++ ...pad-don-t-resume-a-disabled-touchpad.patch | 186 ++++++++++++ libinput.spec | 9 +- 3 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 0001-gestures-don-t-try-to-pinch-for-nfingers-slots.patch create mode 100644 0001-touchpad-don-t-resume-a-disabled-touchpad.patch diff --git a/0001-gestures-don-t-try-to-pinch-for-nfingers-slots.patch b/0001-gestures-don-t-try-to-pinch-for-nfingers-slots.patch new file mode 100644 index 0000000..2a589dc --- /dev/null +++ b/0001-gestures-don-t-try-to-pinch-for-nfingers-slots.patch @@ -0,0 +1,282 @@ +From a7e79ed5a69556c71bb9dd2f0047e4833affa929 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Sat, 29 Jul 2017 13:59:40 +0100 +Subject: [PATCH libinput] gestures: don't try to pinch for nfingers > slots + +We don't know the position of the third finger on 2-slot touchpads, differing +between swipe and pinch is reliable. Simply disable 3-finger pinch and always +use swipe; 3fg pinch is uncommon anyway and it's better to have one of the +gestures working reliably than both unreliably. + +Signed-off-by: Peter Hutterer +Reviewed-by: Hans de Goede +--- + src/evdev-mt-touchpad-gestures.c | 7 +- + test/test-gestures.c | 211 --------------------------------------- + 2 files changed, 6 insertions(+), 212 deletions(-) + +diff --git a/src/evdev-mt-touchpad-gestures.c b/src/evdev-mt-touchpad-gestures.c +index a20b26d4..26bdef5a 100644 +--- a/src/evdev-mt-touchpad-gestures.c ++++ b/src/evdev-mt-touchpad-gestures.c +@@ -334,6 +334,10 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time) + if (tp->gesture.finger_count == 2) { + tp_gesture_set_scroll_buildup(tp); + return GESTURE_STATE_SCROLL; ++ /* more fingers than slots, don't bother with pinch, always ++ * assume swipe */ ++ } else if (tp->gesture.finger_count > tp->num_slots) { ++ return GESTURE_STATE_SWIPE; + } + + /* for 3+ finger gestures, check if one finger is > 20mm +@@ -356,7 +360,8 @@ tp_gesture_handle_state_unknown(struct tp_dispatch *tp, uint64_t time) + + /* If both touches are moving in the same direction assume + * scroll or swipe */ +- if (tp_gesture_same_directions(dir1, dir2)) { ++ if (tp->gesture.finger_count > tp->num_slots || ++ tp_gesture_same_directions(dir1, dir2)) { + if (tp->gesture.finger_count == 2) { + tp_gesture_set_scroll_buildup(tp); + return GESTURE_STATE_SCROLL; +diff --git a/test/test-gestures.c b/test/test-gestures.c +index ce1012d4..e95d1a01 100644 +--- a/test/test-gestures.c ++++ b/test/test-gestures.c +@@ -754,110 +754,6 @@ START_TEST(gestures_pinch_3fg) + } + END_TEST + +-START_TEST(gestures_pinch_3fg_btntool) +-{ +- struct litest_device *dev = litest_current_device(); +- struct libinput *li = dev->libinput; +- struct libinput_event *event; +- struct libinput_event_gesture *gevent; +- double dx, dy; +- int cardinal = _i; /* ranged test */ +- double dir_x, dir_y; +- int i; +- double scale, oldscale; +- double angle; +- int cardinals[8][2] = { +- { 0, 30 }, +- { 30, 30 }, +- { 30, 0 }, +- { 30, -30 }, +- { 0, -30 }, +- { -30, -30 }, +- { -30, 0 }, +- { -30, 30 }, +- }; +- +- if (libevdev_get_num_slots(dev->evdev) > 2 || +- !libinput_device_has_capability(dev->libinput_device, +- LIBINPUT_DEVICE_CAP_GESTURE)) +- return; +- +- dir_x = cardinals[cardinal][0]; +- dir_y = cardinals[cardinal][1]; +- +- litest_drain_events(li); +- +- litest_touch_down(dev, 0, 50 + dir_x, 50 + dir_y); +- litest_touch_down(dev, 1, 50 - dir_x, 50 - dir_y); +- 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); +- +- for (i = 0; i < 8; i++) { +- litest_push_event_frame(dev); +- if (dir_x > 0.0) +- dir_x -= 2; +- else if (dir_x < 0.0) +- dir_x += 2; +- if (dir_y > 0.0) +- dir_y -= 2; +- else if (dir_y < 0.0) +- dir_y += 2; +- litest_touch_move(dev, +- 0, +- 50 + dir_x, +- 50 + dir_y); +- litest_touch_move(dev, +- 1, +- 50 - dir_x, +- 50 - dir_y); +- litest_pop_event_frame(dev); +- libinput_dispatch(li); +- } +- +- event = libinput_get_event(li); +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_BEGIN, +- 3); +- dx = libinput_event_gesture_get_dx(gevent); +- dy = libinput_event_gesture_get_dy(gevent); +- scale = libinput_event_gesture_get_scale(gevent); +- ck_assert(dx == 0.0); +- ck_assert(dy == 0.0); +- ck_assert(scale == 1.0); +- +- libinput_event_destroy(event); +- +- while ((event = libinput_get_event(li)) != NULL) { +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_UPDATE, +- 3); +- +- oldscale = scale; +- scale = libinput_event_gesture_get_scale(gevent); +- +- ck_assert(scale < oldscale); +- +- angle = libinput_event_gesture_get_angle_delta(gevent); +- ck_assert_double_le(fabs(angle), 1.0); +- +- libinput_event_destroy(event); +- libinput_dispatch(li); +- } +- +- litest_touch_up(dev, 0); +- litest_touch_up(dev, 1); +- libinput_dispatch(li); +- event = libinput_get_event(li); +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_END, +- 3); +- ck_assert(!libinput_event_gesture_get_cancelled(gevent)); +- libinput_event_destroy(event); +-} +-END_TEST +- + START_TEST(gestures_pinch_4fg) + { + struct litest_device *dev = litest_current_device(); +@@ -969,111 +865,6 @@ START_TEST(gestures_pinch_4fg) + } + END_TEST + +-START_TEST(gestures_pinch_4fg_btntool) +-{ +- struct litest_device *dev = litest_current_device(); +- struct libinput *li = dev->libinput; +- struct libinput_event *event; +- struct libinput_event_gesture *gevent; +- double dx, dy; +- int cardinal = _i; /* ranged test */ +- double dir_x, dir_y; +- int i; +- double scale, oldscale; +- double angle; +- int cardinals[8][2] = { +- { 0, 30 }, +- { 30, 30 }, +- { 30, 0 }, +- { 30, -30 }, +- { 0, -30 }, +- { -30, -30 }, +- { -30, 0 }, +- { -30, 30 }, +- }; +- +- if (libevdev_get_num_slots(dev->evdev) > 2 || +- !libevdev_has_event_code(dev->evdev, EV_KEY, BTN_TOOL_QUADTAP) || +- !libinput_device_has_capability(dev->libinput_device, +- LIBINPUT_DEVICE_CAP_GESTURE)) +- return; +- +- dir_x = cardinals[cardinal][0]; +- dir_y = cardinals[cardinal][1]; +- +- litest_drain_events(li); +- +- litest_touch_down(dev, 0, 50 + dir_x, 50 + dir_y); +- litest_touch_down(dev, 1, 50 - dir_x, 50 - dir_y); +- litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0); +- litest_event(dev, EV_KEY, BTN_TOOL_QUADTAP, 1); +- litest_event(dev, EV_SYN, SYN_REPORT, 0); +- libinput_dispatch(li); +- +- for (i = 0; i < 8; i++) { +- litest_push_event_frame(dev); +- if (dir_x > 0.0) +- dir_x -= 3; +- else if (dir_x < 0.0) +- dir_x += 3; +- if (dir_y > 0.0) +- dir_y -= 3; +- else if (dir_y < 0.0) +- dir_y += 3; +- litest_touch_move(dev, +- 0, +- 50 + dir_x, +- 50 + dir_y); +- litest_touch_move(dev, +- 1, +- 50 - dir_x, +- 50 - dir_y); +- litest_pop_event_frame(dev); +- libinput_dispatch(li); +- } +- +- event = libinput_get_event(li); +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_BEGIN, +- 4); +- dx = libinput_event_gesture_get_dx(gevent); +- dy = libinput_event_gesture_get_dy(gevent); +- scale = libinput_event_gesture_get_scale(gevent); +- ck_assert(dx == 0.0); +- ck_assert(dy == 0.0); +- ck_assert(scale == 1.0); +- +- libinput_event_destroy(event); +- +- while ((event = libinput_get_event(li)) != NULL) { +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_UPDATE, +- 4); +- +- oldscale = scale; +- scale = libinput_event_gesture_get_scale(gevent); +- +- ck_assert(scale < oldscale); +- +- angle = libinput_event_gesture_get_angle_delta(gevent); +- ck_assert_double_le(fabs(angle), 1.5); +- +- libinput_event_destroy(event); +- libinput_dispatch(li); +- } +- +- litest_touch_up(dev, 0); +- litest_touch_up(dev, 1); +- libinput_dispatch(li); +- event = libinput_get_event(li); +- gevent = litest_is_gesture_event(event, +- LIBINPUT_EVENT_GESTURE_PINCH_END, +- 4); +- ck_assert(!libinput_event_gesture_get_cancelled(gevent)); +- libinput_event_destroy(event); +-} +-END_TEST +- + START_TEST(gestures_spread) + { + struct litest_device *dev = litest_current_device(); +@@ -1282,9 +1073,7 @@ litest_setup_tests_gestures(void) + litest_add_ranged("gestures:swipe", gestures_swipe_4fg_btntool, 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_pinch_3fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); +- litest_add_ranged("gestures:pinch", gestures_pinch_3fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged("gestures:pinch", gestures_pinch_4fg, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); +- litest_add_ranged("gestures:pinch", gestures_pinch_4fg_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged("gestures:pinch", gestures_spread, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &cardinals); + litest_add_ranged("gestures:pinch", gestures_pinch_vertical_positon, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH, &fingers); + +-- +2.13.5 + diff --git a/0001-touchpad-don-t-resume-a-disabled-touchpad.patch b/0001-touchpad-don-t-resume-a-disabled-touchpad.patch new file mode 100644 index 0000000..8158120 --- /dev/null +++ b/0001-touchpad-don-t-resume-a-disabled-touchpad.patch @@ -0,0 +1,186 @@ +From 03f13ce6e854b3ff5d4b8971405a97afd66eef8e Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 5 Sep 2017 14:38:53 +1000 +Subject: [PATCH libinput] touchpad: don't resume a disabled touchpad + +Signed-off-by: Peter Hutterer +--- + src/evdev-mt-touchpad.c | 44 ++++++++++++++++++---------- + test/test-lid.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 107 insertions(+), 15 deletions(-) + +diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c +index 5b8fb1ec..c0a78255 100644 +--- a/src/evdev-mt-touchpad.c ++++ b/src/evdev-mt-touchpad.c +@@ -1426,6 +1426,31 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device) + } + } + ++#define NO_EXCLUDED_DEVICE NULL ++static void ++tp_resume_conditional(struct tp_dispatch *tp, ++ struct evdev_device *device, ++ struct evdev_device *excluded_device) ++{ ++ if (tp->sendevents.current_mode == LIBINPUT_CONFIG_SEND_EVENTS_DISABLED) ++ return; ++ ++ if (tp->sendevents.current_mode == ++ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) { ++ struct libinput_device *dev; ++ ++ list_for_each(dev, &device->base.seat->devices_list, link) { ++ struct evdev_device *d = evdev_device(dev); ++ if (d != excluded_device && ++ (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) { ++ return; ++ } ++ } ++ } ++ ++ tp_resume(tp, device); ++} ++ + static void + tp_trackpoint_timeout(uint64_t now, void *data) + { +@@ -1667,7 +1692,7 @@ tp_lid_switch_event(uint64_t time, struct libinput_event *event, void *data) + swev = libinput_event_get_switch_event(event); + switch (libinput_event_switch_get_switch_state(swev)) { + case LIBINPUT_SWITCH_STATE_OFF: +- tp_resume(tp, tp->device); ++ tp_resume_conditional(tp, tp->device, NO_EXCLUDED_DEVICE); + evdev_log_debug(tp->device, "lid: resume touchpad\n"); + break; + case LIBINPUT_SWITCH_STATE_ON: +@@ -1722,7 +1747,6 @@ tp_interface_device_removed(struct evdev_device *device, + struct evdev_device *removed_device) + { + struct tp_dispatch *tp = (struct tp_dispatch*)device->dispatch; +- struct libinput_device *dev; + + if (removed_device == tp->buttons.trackpoint) { + /* Clear any pending releases for the trackpoint */ +@@ -1749,19 +1773,9 @@ tp_interface_device_removed(struct evdev_device *device, + tp->lid_switch.lid_switch = NULL; + } + +- if (tp->sendevents.current_mode != +- LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE) +- return; +- +- list_for_each(dev, &device->base.seat->devices_list, link) { +- struct evdev_device *d = evdev_device(dev); +- if (d != removed_device && +- (d->tags & EVDEV_TAG_EXTERNAL_MOUSE)) { +- return; +- } +- } +- +- tp_resume(tp, device); ++ /* removed_device is still in the device list at this point, so we ++ * need to exclude it from the tp_resume_conditional */ ++ tp_resume_conditional(tp, device, removed_device); + } + + static inline void +diff --git a/test/test-lid.c b/test/test-lid.c +index 4bf4c059..7e42f53d 100644 +--- a/test/test-lid.c ++++ b/test/test-lid.c +@@ -342,6 +342,81 @@ START_TEST(lid_disable_touchpad_already_open) + } + END_TEST + ++START_TEST(lid_dont_resume_disabled_touchpad) ++{ ++ struct litest_device *sw = litest_current_device(); ++ struct litest_device *touchpad; ++ struct libinput *li = sw->libinput; ++ ++ touchpad = lid_init_paired_touchpad(li); ++ litest_disable_tap(touchpad->libinput_device); ++ libinput_device_config_send_events_set_mode(touchpad->libinput_device, ++ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED); ++ litest_drain_events(li); ++ ++ /* switch is on - no events */ ++ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); ++ litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); ++ ++ litest_touch_down(touchpad, 0, 50, 50); ++ litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); ++ litest_touch_up(touchpad, 0); ++ litest_assert_empty_queue(li); ++ ++ /* switch is off - motion events */ ++ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); ++ litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); ++ ++ litest_touch_down(touchpad, 0, 50, 50); ++ litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); ++ litest_touch_up(touchpad, 0); ++ litest_assert_empty_queue(li); ++ ++ litest_delete_device(touchpad); ++} ++END_TEST ++ ++START_TEST(lid_dont_resume_disabled_touchpad_external_mouse) ++{ ++ struct litest_device *sw = litest_current_device(); ++ struct litest_device *touchpad, *mouse; ++ struct libinput *li = sw->libinput; ++ ++ touchpad = lid_init_paired_touchpad(li); ++ mouse = litest_add_device(li, LITEST_MOUSE); ++ litest_disable_tap(touchpad->libinput_device); ++ libinput_device_config_send_events_set_mode(touchpad->libinput_device, ++ LIBINPUT_CONFIG_SEND_EVENTS_DISABLED_ON_EXTERNAL_MOUSE); ++ litest_drain_events(li); ++ ++ litest_touch_down(touchpad, 0, 50, 50); ++ litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); ++ litest_touch_up(touchpad, 0); ++ litest_assert_empty_queue(li); ++ ++ /* switch is on - no events */ ++ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); ++ litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); ++ ++ litest_touch_down(touchpad, 0, 50, 50); ++ litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); ++ litest_touch_up(touchpad, 0); ++ litest_assert_empty_queue(li); ++ ++ /* switch is off - motion events */ ++ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); ++ litest_assert_only_typed_events(li, LIBINPUT_EVENT_SWITCH_TOGGLE); ++ ++ litest_touch_down(touchpad, 0, 50, 50); ++ litest_touch_move_to(touchpad, 0, 50, 50, 70, 50, 10, 1); ++ litest_touch_up(touchpad, 0); ++ litest_assert_empty_queue(li); ++ ++ litest_delete_device(touchpad); ++ litest_delete_device(mouse); ++} ++END_TEST ++ + START_TEST(lid_open_on_key) + { + struct litest_device *sw = litest_current_device(); +@@ -568,6 +643,9 @@ litest_setup_tests_lid(void) + litest_add("lid:disable_touchpad", lid_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:disable_touchpad", lid_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY); + ++ litest_add("switch:touchpad", lid_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY); ++ litest_add("switch:touchpad", lid_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY); ++ + litest_add("lid:keyboard", lid_open_on_key, LITEST_SWITCH, LITEST_ANY); + litest_add("lid:keyboard", lid_open_on_key_touchpad_enabled, LITEST_SWITCH, LITEST_ANY); + +-- +2.13.5 + diff --git a/libinput.spec b/libinput.spec index 82a7f77..b95ffd6 100644 --- a/libinput.spec +++ b/libinput.spec @@ -5,7 +5,7 @@ Name: libinput Version: 1.8.1 -Release: 3%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} +Release: 4%{?gitdate:.%{gitdate}git%{gitversion}}%{?dist} Summary: Input device library License: MIT @@ -18,6 +18,9 @@ Source2: commitid Source0: http://www.freedesktop.org/software/libinput/libinput-%{version}.tar.xz %endif +Patch01: 0001-gestures-don-t-try-to-pinch-for-nfingers-slots.patch +Patch02: 0001-touchpad-don-t-resume-a-disabled-touchpad.patch + BuildRequires: git-core BuildRequires: gcc BuildRequires: meson @@ -103,6 +106,10 @@ git am -p1 %{patches} < /dev/null %changelog +* Tue Sep 05 2017 Peter Hutterer 1.8.1-4 +- Don't try pinching when the finger number exceeds available slots +- Don't resume a disabled touchpad after a lid switch open (#1448962) + * Thu Aug 03 2017 Fedora Release Engineering - 1.8.1-3 - Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild