A toucphad 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 <[email protected]>
---
 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 eb3dde3c..ad034429 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1635,6 +1635,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)
 {
@@ -1887,7 +1912,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:
@@ -1971,7 +1996,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 */
@@ -2004,19 +2028,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);
-- 
2.13.5

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to