From 9f1e8a032c0771b4b0c9a41484af1a2b8816ef5e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 27 Oct 2017 15:03:52 +1000 Subject: [PATCH] fallback: fix lid switch event listener being initialized twice Once the lid is closed, the keyboard event listener is set up to open the lid for us on keyboard events. With the right sequence, we can trigger the listener to be added to the list multiple times, triggering an assert in the list test code (or an infinite loop in the 1.8 branch). Conditions: * SW_LID value 1 - sets up the keyboard listener * keyboard event - sets lid_is_closed to false * SW_LID value 0 - is ignored because we're already open * SW_LID value 1 - sets up the keyboard listener again https://bugs.freedesktop.org/show_bug.cgi?id=103298 Signed-off-by: Peter Hutterer (cherry picked from commit 41a70bbe924c4867283bfdec67cd76012744afcb) --- src/evdev-lid.c | 12 ++++++------ test/test-lid.c | 33 +++++++++++++++++---------------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/evdev-lid.c b/src/evdev-lid.c index e410ecad..b12ca0af 100644 --- a/src/evdev-lid.c +++ b/src/evdev-lid.c @@ -105,6 +105,8 @@ lid_switch_toggle_keyboard_listener(struct lid_switch_dispatch *dispatch, if (!dispatch->keyboard.keyboard) return; + libinput_device_remove_event_listener(&dispatch->keyboard.listener); + if (is_closed) { libinput_device_add_event_listener( &dispatch->keyboard.keyboard->base, @@ -112,10 +114,7 @@ lid_switch_toggle_keyboard_listener(struct lid_switch_dispatch *dispatch, lid_switch_keyboard_event, dispatch); } else { - libinput_device_remove_event_listener( - &dispatch->keyboard.listener); - libinput_device_init_event_listener( - &dispatch->keyboard.listener); + libinput_device_init_event_listener(&dispatch->keyboard.listener); } } @@ -131,11 +130,12 @@ lid_switch_process_switch(struct lid_switch_dispatch *dispatch, case SW_LID: is_closed = !!e->value; - if (dispatch->lid_is_closed == is_closed) - return; lid_switch_toggle_keyboard_listener(dispatch, is_closed); + if (dispatch->lid_is_closed == is_closed) + return; + dispatch->lid_is_closed = is_closed; lid_switch_notify_toggle(dispatch, device, time); diff --git a/test/test-lid.c b/test/test-lid.c index 338c5447..d12f9b93 100644 --- a/test/test-lid.c +++ b/test/test-lid.c @@ -426,26 +426,27 @@ START_TEST(lid_open_on_key) keyboard = litest_add_device(li, LITEST_KEYBOARD); - litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); - litest_drain_events(li); + for (int i = 0; i < 3; i++) { + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON); + litest_drain_events(li); - litest_event(keyboard, EV_KEY, KEY_A, 1); - litest_event(keyboard, EV_SYN, SYN_REPORT, 0); - litest_event(keyboard, EV_KEY, KEY_A, 0); - litest_event(keyboard, EV_SYN, SYN_REPORT, 0); - libinput_dispatch(li); + litest_event(keyboard, EV_KEY, KEY_A, 1); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + litest_event(keyboard, EV_KEY, KEY_A, 0); + litest_event(keyboard, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); - event = libinput_get_event(li); - litest_is_switch_event(event, - LIBINPUT_SWITCH_LID, - LIBINPUT_SWITCH_STATE_OFF); + event = libinput_get_event(li); + litest_is_switch_event(event, + LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); - litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); + litest_assert_only_typed_events(li, LIBINPUT_EVENT_KEYBOARD_KEY); - litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); - litest_assert_empty_queue(li); - - libinput_event_destroy(event); + litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF); + litest_assert_empty_queue(li); + } litest_delete_device(keyboard); } END_TEST