From 53d53dd18ef14484d632421027cd7b6130013cf0 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 5 Sep 2017 14:38:53 +1000 Subject: [PATCH] touchpad: don't resume a disabled touchpad A touchpad that was disabled by toggling the sendevents option would come back normally after a lid resume, despite still being nominally disabled. https://bugzilla.redhat.com/show_bug.cgi?id=1448962 Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 44 +++++++++++++-------- test/test-switch.c | 85 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 15 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ae74cb9b..c3e9e5a3 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -1758,6 +1758,31 @@ tp_resume(struct tp_dispatch *tp, struct evdev_device *device) tp_sync_slots(tp, 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) { @@ -2010,7 +2035,7 @@ tp_switch_event(uint64_t time, struct libinput_event *event, void *data) 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, "%s: resume touchpad\n", which); break; case LIBINPUT_SWITCH_STATE_ON: @@ -2094,7 +2119,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 */ @@ -2127,19 +2151,9 @@ tp_interface_device_removed(struct evdev_device *device, tp->tablet_mode_switch.tablet_mode_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-switch.c b/test/test-switch.c index 77ba5593..c2b72914 100644 --- a/test/test-switch.c +++ b/test/test-switch.c @@ -418,6 +418,89 @@ START_TEST(switch_disable_touchpad_already_open) } END_TEST +START_TEST(switch_dont_resume_disabled_touchpad) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad; + struct libinput *li = sw->libinput; + enum libinput_switch which = _i; /* ranged test */ + + if (!libinput_device_switch_has_switch(sw->libinput_device, which)) + return; + + touchpad = switch_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_switch_action(sw, which, 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 but but tp is still disabled */ + litest_switch_action(sw, which, 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(switch_dont_resume_disabled_touchpad_external_mouse) +{ + struct litest_device *sw = litest_current_device(); + struct litest_device *touchpad, *mouse; + struct libinput *li = sw->libinput; + enum libinput_switch which = _i; /* ranged test */ + + if (!libinput_device_switch_has_switch(sw->libinput_device, which)) + return; + + touchpad = switch_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_switch_action(sw, which, 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 but but tp is still disabled */ + litest_switch_action(sw, which, 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(); @@ -744,6 +827,8 @@ litest_setup_tests_lid(void) litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll, LITEST_SWITCH, LITEST_ANY, &switches); litest_add_ranged("switch:touchpad", switch_disable_touchpad_edge_scroll_interrupt, LITEST_SWITCH, LITEST_ANY, &switches); litest_add_ranged("switch:touchpad", switch_disable_touchpad_already_open, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged("switch:touchpad", switch_dont_resume_disabled_touchpad_external_mouse, LITEST_SWITCH, LITEST_ANY, &switches); litest_add_ranged_no_device("switch:keyboard", switch_suspend_with_keyboard, &switches); litest_add_ranged_no_device("switch:touchpad", switch_suspend_with_touchpad, &switches);