diff --git a/meson.build b/meson.build index 27581b81..170b7f72 100644 --- a/meson.build +++ b/meson.build @@ -842,6 +842,7 @@ if get_option('tests') 'test/litest-device-synaptics-st.c', 'test/litest-device-synaptics-t440.c', 'test/litest-device-synaptics-x1-carbon-3rd.c', + 'test/litest-device-tablet-mode-switch.c', 'test/litest-device-thinkpad-extrabuttons.c', 'test/litest-device-trackpoint.c', 'test/litest-device-touch-screen.c', diff --git a/src/evdev.c b/src/evdev.c index dae1284d..124b07a0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -1923,15 +1923,20 @@ evdev_configure_device(struct evdev_device *device) if (libevdev_has_event_code(evdev, EV_SW, SW_TABLET_MODE)) { if (evdev_device_has_model_quirk(device, - QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE)) + QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE)) { evdev_log_info(device, - "device is an unreliable tablet mode switch.\n"); - else + "device is an unreliable tablet mode switch, filtering events.\n"); + libevdev_disable_event_code(device->evdev, + EV_SW, + SW_TABLET_MODE); + } else { device->tags |= EVDEV_TAG_TABLET_MODE_SWITCH; - - device->seat_caps |= EVDEV_DEVICE_SWITCH; - evdev_log_info(device, "device is a switch device\n"); + device->seat_caps |= EVDEV_DEVICE_SWITCH; + } } + + if (device->seat_caps & EVDEV_DEVICE_SWITCH) + evdev_log_info(device, "device is a switch device\n"); } if (device->seat_caps & EVDEV_DEVICE_POINTER && diff --git a/test/litest-device-tablet-mode-switch.c b/test/litest-device-tablet-mode-switch.c new file mode 100644 index 00000000..e677ddf4 --- /dev/null +++ b/test/litest-device-tablet-mode-switch.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2020 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "config.h" + +#include "litest.h" +#include "litest-int.h" + +static struct input_id input_id = { + .bustype = 0x18, + .vendor = 0x123, + .product = 0x456, +}; + +static int events[] = { + /* buttons are needed - the unreliable quirk removes SW_TABLET_MODE + * so we'd end up with a device with no seat caps and that won't get + * added */ + EV_KEY, BTN_LEFT, + EV_KEY, BTN_RIGHT, + EV_SW, SW_TABLET_MODE, + -1, -1, +}; + +static const char quirk_file[] = +"[litest unreliable tablet mode switch]\n" +"MatchName=litest Unreliable Tablet Mode Switch device\n" +"ModelTabletModeSwitchUnreliable=1\n"; + +TEST_DEVICE("tablet-mode-switch-unreliable", + .type = LITEST_TABLET_MODE_UNRELIABLE, + .features = LITEST_SWITCH, + .interface = NULL, + + .name = "Unreliable Tablet Mode Switch device", + .id = &input_id, + .events = events, + .absinfo = NULL, + + .quirk_file = quirk_file, + .udev_properties = { + { "ID_INPUT_SWITCH", "1" }, + { NULL }, + } +) + diff --git a/test/litest.h b/test/litest.h index ff28a599..c32e58ac 100644 --- a/test/litest.h +++ b/test/litest.h @@ -303,6 +303,7 @@ enum litest_device_type { LITEST_ALPS_3FG, LITEST_ELAN_TABLET, LITEST_ABSINFO_OVERRIDE, + LITEST_TABLET_MODE_UNRELIABLE, }; #define LITEST_DEVICELESS -2 diff --git a/test/test-switch.c b/test/test-switch.c index 16838a86..339519eb 100644 --- a/test/test-switch.c +++ b/test/test-switch.c @@ -47,6 +47,14 @@ START_TEST(switch_has_cap) { struct litest_device *dev = litest_current_device(); + /* Need to check for this specific device here because the + * unreliable tablet mode switch removes the capability too */ + if (dev->which == LITEST_TABLET_MODE_UNRELIABLE) { + ck_assert(!libinput_device_has_capability(dev->libinput_device, + LIBINPUT_DEVICE_CAP_SWITCH)); + return; + } + ck_assert(libinput_device_has_capability(dev->libinput_device, LIBINPUT_DEVICE_CAP_SWITCH)); @@ -66,16 +74,33 @@ START_TEST(switch_has_lid_switch) } END_TEST +static bool +tablet_mode_switch_is_reliable(struct litest_device *dev) +{ + bool is_unreliable = false; + + quirks_get_bool(dev->quirks, + QUIRK_MODEL_TABLET_MODE_SWITCH_UNRELIABLE, + &is_unreliable); + + return !is_unreliable; +} + START_TEST(switch_has_tablet_mode_switch) { struct litest_device *dev = litest_current_device(); + int has_switch; 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); + has_switch = libinput_device_switch_has_switch(dev->libinput_device, + LIBINPUT_SWITCH_TABLET_MODE); + + if (!tablet_mode_switch_is_reliable(dev)) + ck_assert_int_ne(has_switch, 1); + else + ck_assert_int_eq(has_switch, 1); } END_TEST