https://bugs.freedesktop.org/show_bug.cgi?id=101008
Signed-off-by: Peter Hutterer <[email protected]> --- This builds on top of the patch series here https://lists.freedesktop.org/archives/wayland-devel/2017-April/033942.html since rebased and available here: https://github.com/whot/libinput/tree/wip/sw-tablet-mode src/evdev.c | 48 ++++++++++++--- src/evdev.h | 1 + src/libinput.h | 16 +++++ test/litest-device-thinkpad-extrabuttons.c | 1 + test/litest.c | 3 + test/test-switch.c | 95 +++++++++++++++--------------- 6 files changed, 108 insertions(+), 56 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 1b4ec934..8cc8a2cc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -958,6 +958,20 @@ fallback_process_switch(struct fallback_dispatch *dispatch, LIBINPUT_SWITCH_RF_DISABLED, state); break; + case SW_TABLET_MODE: + if (dispatch->sw.tablet_mode_state == e->value) + return; + + dispatch->sw.tablet_mode_state = e->value; + if (e->value) + state = LIBINPUT_SWITCH_STATE_ON; + else + state = LIBINPUT_SWITCH_STATE_OFF; + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_TABLET_MODE, + state); + break; } } @@ -1288,14 +1302,21 @@ fallback_sync_initial_state(struct evdev_device *device, struct evdev_dispatch *evdev_dispatch) { struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); + uint64_t time = libinput_now(evdev_libinput_context(device)); if (dispatch->sw.rfkill_all_state) { - uint64_t time = libinput_now(evdev_libinput_context(device)); switch_notify_toggle(&device->base, time, LIBINPUT_SWITCH_RF_DISABLED, LIBINPUT_SWITCH_STATE_ON); } + + if (dispatch->sw.tablet_mode_state) { + switch_notify_toggle(&device->base, + time, + LIBINPUT_SWITCH_TABLET_MODE, + LIBINPUT_SWITCH_STATE_ON); + } } static void @@ -1845,13 +1866,23 @@ static inline void fallback_dispatch_init_switch(struct fallback_dispatch *dispatch, struct evdev_device *device) { - if (!libevdev_has_event_code(device->evdev, EV_SW, SW_RFKILL_ALL)) - return; + int val; - dispatch->sw.rfkill_all_state = libevdev_get_event_value(device->evdev, - EV_SW, - SW_RFKILL_ALL); - device->seat_caps |= EVDEV_DEVICE_SWITCH; + if (libevdev_has_event_code(device->evdev, EV_SW, SW_RFKILL_ALL)) { + val = libevdev_get_event_value(device->evdev, + EV_SW, + SW_RFKILL_ALL); + dispatch->sw.rfkill_all_state = val; + device->seat_caps |= EVDEV_DEVICE_SWITCH; + } + + if (libevdev_has_event_code(device->evdev, EV_SW, SW_TABLET_MODE)) { + val = libevdev_get_event_value(device->evdev, + EV_SW, + SW_TABLET_MODE); + dispatch->sw.tablet_mode_state = val; + device->seat_caps |= EVDEV_DEVICE_SWITCH; + } } static struct evdev_dispatch * @@ -3214,6 +3245,9 @@ evdev_device_has_switch(struct evdev_device *device, case LIBINPUT_SWITCH_RF_DISABLED: code = SW_RFKILL_ALL; break; + case LIBINPUT_SWITCH_TABLET_MODE: + code = SW_TABLET_MODE; + break; default: return -1; } diff --git a/src/evdev.h b/src/evdev.h index 02c14e65..0587740d 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -359,6 +359,7 @@ struct fallback_dispatch { struct { int rfkill_all_state; + int tablet_mode_state; } sw; /* Bitmask of pressed keys used to ignore initial release events from diff --git a/src/libinput.h b/src/libinput.h index 38abae8e..316f210a 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -639,6 +639,22 @@ enum libinput_switch { * c) toggle the state to match the switch state (if required) */ LIBINPUT_SWITCH_RF_DISABLED, + + /** + * This switch indicates whether the device is in normal laptop mode + * or behaves like a tablet-like device where the primary + * interaction is usually a touch screen. When in tablet mode, the + * keyboard and touchpad are usually inaccessible. + * + * If the switch is in state @ref LIBINPUT_SWITCH_STATE_OFF, the + * device is in laptop mode. If the switch is in state @ref + * LIBINPUT_SWITCH_STATE_ON, the device is in tablet mode and the + * keyboard or touchpad may not be accessible. + * + * It is up to the caller to identify which devices are inaccessible + * in tablet mode. + */ + LIBINPUT_SWITCH_TABLET_MODE, }; /** diff --git a/test/litest-device-thinkpad-extrabuttons.c b/test/litest-device-thinkpad-extrabuttons.c index d5ff4303..84541493 100644 --- a/test/litest-device-thinkpad-extrabuttons.c +++ b/test/litest-device-thinkpad-extrabuttons.c @@ -71,6 +71,7 @@ static int events[] = { EV_KEY, KEY_BRIGHTNESS_MIN, EV_SW, SW_RFKILL_ALL, + EV_SW, SW_TABLET_MODE, -1, -1, }; diff --git a/test/litest.c b/test/litest.c index d0704bec..14eb2722 100644 --- a/test/litest.c +++ b/test/litest.c @@ -2178,6 +2178,9 @@ litest_switch_action(struct litest_device *dev, case LIBINPUT_SWITCH_RF_DISABLED: code = SW_RFKILL_ALL; break; + case LIBINPUT_SWITCH_TABLET_MODE: + code = SW_TABLET_MODE; + break; default: litest_abort_msg("Invalid switch %d", sw); break; diff --git a/test/test-switch.c b/test/test-switch.c index af184607..1fcf61d4 100644 --- a/test/test-switch.c +++ b/test/test-switch.c @@ -36,13 +36,6 @@ switch_has_lid(struct litest_device *dev) LIBINPUT_SWITCH_LID); } -static inline bool -switch_has_rfkill(struct litest_device *dev) -{ - return libinput_device_switch_has_switch(dev->libinput_device, - LIBINPUT_SWITCH_RF_DISABLED); -} - START_TEST(switch_has_lid_switch) { struct litest_device *dev = litest_current_device(); @@ -79,35 +72,47 @@ START_TEST(switch_has_rfkill_switch) } END_TEST +START_TEST(switch_has_tablet_mode_switch) +{ + struct litest_device *dev = litest_current_device(); + + if (!libevdev_has_event_code(dev->evdev, EV_SW, SW_TABLET_MODE)) + return; + + ck_assert_int_eq(libinput_device_switch_has_switch(dev->libinput_device, + LIBINPUT_SWITCH_TABLET_MODE), + 1); +} +END_TEST + START_TEST(switch_toggle) { struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; - enum libinput_switch sw; - - if (switch_has_lid(dev)) - sw = LIBINPUT_SWITCH_LID; - else if (switch_has_rfkill(dev)) - sw = LIBINPUT_SWITCH_RF_DISABLED; - else - litest_abort_msg("Missing switch for test"); + enum libinput_switch sw = _i; /* ranged test */ litest_drain_events(li); litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON); libinput_dispatch(li); - event = libinput_get_event(li); - litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON); - libinput_event_destroy(event); + if (libinput_device_switch_has_switch(dev->libinput_device, sw)) { + event = libinput_get_event(li); + litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_ON); + libinput_event_destroy(event); + } else { + litest_assert_empty_queue(li); + } litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_OFF); libinput_dispatch(li); - event = libinput_get_event(li); - litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF); - libinput_event_destroy(event); + if (libinput_device_switch_has_switch(dev->libinput_device, sw)) { + event = libinput_get_event(li); + litest_is_switch_event(event, sw, LIBINPUT_SWITCH_STATE_OFF); + libinput_event_destroy(event); + } litest_assert_empty_queue(li); } @@ -118,14 +123,10 @@ START_TEST(switch_toggle_double) struct litest_device *dev = litest_current_device(); struct libinput *li = dev->libinput; struct libinput_event *event; - enum libinput_switch sw; + enum libinput_switch sw = _i; /* ranged test */ - if (switch_has_lid(dev)) - sw = LIBINPUT_SWITCH_LID; - else if (switch_has_rfkill(dev)) - sw = LIBINPUT_SWITCH_RF_DISABLED; - else - litest_abort_msg("Missing switch for test"); + if (!libinput_device_switch_has_switch(dev->libinput_device, sw)) + return; litest_drain_events(li); @@ -167,17 +168,13 @@ START_TEST(switch_down_on_init) struct litest_device *dev = litest_current_device(); struct libinput *li; struct libinput_event *event; - enum libinput_switch sw = LIBINPUT_SWITCH_LID; + enum libinput_switch sw = _i; /* ranged test */ - if (switch_has_lid(dev)) { - sw = LIBINPUT_SWITCH_LID; - if (!lid_switch_is_reliable(dev)) - return; - } else if (switch_has_rfkill(dev)) { - sw = LIBINPUT_SWITCH_RF_DISABLED; - } else { - litest_abort_msg("Missing switch for test"); - } + if (!libinput_device_switch_has_switch(dev->libinput_device, sw)) + return; + + if (sw == LIBINPUT_SWITCH_LID && !lid_switch_is_reliable(dev)) + return; litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON); @@ -217,15 +214,11 @@ START_TEST(switch_not_down_on_init) struct libinput_event *event; enum libinput_switch sw = LIBINPUT_SWITCH_LID; - if (switch_has_lid(dev)) { - sw = LIBINPUT_SWITCH_LID; - if (lid_switch_is_reliable(dev)) - return; - } else if (switch_has_rfkill(dev)) { + if (!libinput_device_switch_has_switch(dev->libinput_device, sw)) + return; + + if (sw == LIBINPUT_SWITCH_LID && lid_switch_is_reliable(dev)) return; - } else { - litest_abort_msg("Missing switch for test"); - } litest_switch_action(dev, sw, LIBINPUT_SWITCH_STATE_ON); @@ -627,12 +620,16 @@ END_TEST void litest_setup_tests_lid(void) { + struct range switches = { LIBINPUT_SWITCH_LID, + LIBINPUT_SWITCH_TABLET_MODE + 1}; + litest_add("switch:has", switch_has_lid_switch, LITEST_SWITCH, LITEST_ANY); litest_add("switch:has", switch_has_rfkill_switch, LITEST_SWITCH, LITEST_ANY); + litest_add("switch:has", switch_has_tablet_mode_switch, LITEST_SWITCH, LITEST_ANY); litest_add("switch:has", switch_has_cap, LITEST_SWITCH, LITEST_ANY); - litest_add("switch:toggle", switch_toggle, LITEST_SWITCH, LITEST_ANY); - litest_add("switch:toggle", switch_toggle_double, LITEST_SWITCH, LITEST_ANY); - litest_add("switch:toggle", switch_down_on_init, LITEST_SWITCH, LITEST_ANY); + litest_add_ranged("switch:toggle", switch_toggle, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged("switch:toggle", switch_toggle_double, LITEST_SWITCH, LITEST_ANY, &switches); + litest_add_ranged("switch:toggle", switch_down_on_init, LITEST_SWITCH, LITEST_ANY, &switches); litest_add("switch:toggle", switch_not_down_on_init, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad, LITEST_SWITCH, LITEST_ANY); litest_add("lid:disable_touchpad", lid_disable_touchpad_during_touch, LITEST_SWITCH, LITEST_ANY); -- 2.12.2 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
