}
static void
+lid_switch_update_kernel_state(struct lid_switch_dispatch *dispatch,
+ uint64_t time)
+{
+ int fd;
+ const struct input_event ev[2] = {
+ {{ 0, 0 }, EV_SW, SW_LID, 0 },
+ {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 },
+ };
+
+ if (dispatch->reliability != RELIABILITY_WRITE_OPEN)
+ return;
+
+ fd = libevdev_get_fd(dispatch->device->evdev);
+ (void)write(fd, ev, sizeof(ev));
+}
+
+static void
lid_switch_keyboard_event(uint64_t time,
struct libinput_event *event,
void *data)
if (event->type != LIBINPUT_EVENT_KEYBOARD_KEY)
return;
- if (dispatch->reliability == RELIABILITY_WRITE_OPEN) {
- int fd = libevdev_get_fd(dispatch->device->evdev);
- struct input_event ev[2] = {
- {{ 0, 0 }, EV_SW, SW_LID, 0 },
- {{ 0, 0 }, EV_SYN, SYN_REPORT, 0 },
- };
-
- (void)write(fd, ev, sizeof(ev));
- /* In case write() fails, we sync the lid state manually
- * regardless. */
- }
+ lid_switch_update_kernel_state(dispatch, time);
/* Posting the event here means we preempt the keyboard events that
* caused us to wake up, so the lid event is always passed on before
struct lid_switch_dispatch *dispatch = lid_dispatch(device->dispatch);
if (removed_device == dispatch->keyboard.keyboard) {
+ uint64_t time;
+
libinput_device_remove_event_listener(
&dispatch->keyboard.listener);
libinput_device_init_event_listener(
&dispatch->keyboard.listener);
dispatch->keyboard.keyboard = NULL;
+
+ time = libinput_now(evdev_libinput_context(device));
+ lid_switch_update_kernel_state(dispatch, time);
}
}
}
END_TEST
+START_TEST(lid_force_open_if_no_keyboard)
+{
+ struct litest_device *sw = litest_current_device();
+ struct libinput *li;
+ struct litest_device *keyboard;
+
+ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_ON);
+ keyboard = litest_add_device(sw->libinput, LITEST_KEYBOARD);
+
+ /* separate context for the right state on init */
+ li = litest_create_context();
+ libinput_path_add_device(li,
+ libevdev_uinput_get_devnode(sw->uinput));
+
+ /* We only have the switch device in this context, not the keyboard.
+ * So don't expect any switch event to be in the pipe and don't
+ * expect the event to change if we type or toggle the state
+ */
+ while (libinput_next_event_type(li) != LIBINPUT_EVENT_NONE) {
+ ck_assert_int_ne(libinput_next_event_type(li),
+ LIBINPUT_EVENT_SWITCH_TOGGLE);
+ libinput_event_destroy(libinput_get_event(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);
+ litest_lid_action(sw, LIBINPUT_SWITCH_STATE_OFF);
+ litest_assert_empty_queue(li);
+
+ libinput_unref(li);
+ litest_delete_device(keyboard);
+}
+END_TEST
void
litest_setup_tests_lid(void)
{
litest_add_for_device("lid:buggy", lid_update_hw_on_key, LITEST_LID_SWITCH_SURFACE3);
litest_add_for_device("lid:buggy", lid_update_hw_on_key_closed_on_init, LITEST_LID_SWITCH_SURFACE3);
+ litest_add_for_device("lid:buggy", lid_force_open_if_no_keyboard, LITEST_LID_SWITCH_SURFACE3);
}