diff --git a/src/platform/linux/uhid_backend.cpp b/src/platform/linux/uhid_backend.cpp index d15fc83..67a40ab 100644 --- a/src/platform/linux/uhid_backend.cpp +++ b/src/platform/linux/uhid_backend.cpp @@ -649,8 +649,13 @@ namespace lvh::detail { return it->second; } + /** + * @brief Convert a virtual key to a Linux key code, including the ABNT2 extra slash key. + * @param key_code Windows virtual key or an extended editing key code. + * @return Linux key code, or -1 when the key is unsupported. + */ int key_code_to_linux(KeyboardKeyCode key_code) { - static constexpr std::array, 52> special_keys {{ + static constexpr std::array, 53> special_keys {{ {0x08, KEY_BACKSPACE}, {0x09, KEY_TAB}, {0x0D, KEY_ENTER}, @@ -694,6 +699,7 @@ namespace lvh::detail { {0xBE, KEY_DOT}, {0xBF, KEY_SLASH}, {0xC0, KEY_GRAVE}, + {0xC1, KEY_RO}, {0xDB, KEY_LEFTBRACE}, {0xDC, KEY_BACKSLASH}, {0xDD, KEY_RIGHTBRACE}, diff --git a/tests/unit/test_linux_backend.cpp b/tests/unit/test_linux_backend.cpp index ae06648..b2b2273 100644 --- a/tests/unit/test_linux_backend.cpp +++ b/tests/unit/test_linux_backend.cpp @@ -101,6 +101,7 @@ TEST_F(LinuxBackendTest, TranslatesKeyboardKeys) { EXPECT_EQ(lvh::detail::test::linux_key_code(0xBE), KEY_DOT); EXPECT_EQ(lvh::detail::test::linux_key_code(0xBF), KEY_SLASH); EXPECT_EQ(lvh::detail::test::linux_key_code(0xC0), KEY_GRAVE); + EXPECT_EQ(lvh::detail::test::linux_key_code(0xC1), KEY_RO); EXPECT_EQ(lvh::detail::test::linux_key_code(0xDB), KEY_LEFTBRACE); EXPECT_EQ(lvh::detail::test::linux_key_code(0xDC), KEY_BACKSLASH); EXPECT_EQ(lvh::detail::test::linux_key_code(0xDD), KEY_RIGHTBRACE); @@ -399,6 +400,19 @@ TEST_F(LinuxBackendTest, PipeBackedUinputKeyboardEmitsComposeKey) { } } +TEST_F(LinuxBackendTest, PipeBackedUinputKeyboardEmitsAbnt2SlashKey) { + for (const auto pressed : {true, false}) { + const auto result = lvh::detail::test::linux_uinput_keyboard_submit_pipe({.key_code = 0xC1, .pressed = pressed}); + ASSERT_TRUE(result.status.ok()) << result.status.message(); + ASSERT_EQ(result.events.size(), 2U); + EXPECT_EQ(result.events[0].type, EV_KEY); + EXPECT_EQ(result.events[0].code, KEY_RO); + EXPECT_EQ(result.events[0].value, pressed ? 1 : 0); + EXPECT_EQ(result.events[1].type, EV_SYN); + EXPECT_EQ(result.events[1].code, SYN_REPORT); + } +} + TEST_F(LinuxBackendTest, UinputKeyboardEmitsOnlySubmittedKeyTransitions) { const auto default_interval = lvh::CreateKeyboardOptions {}.auto_repeat_interval_ms; for (const auto interval_ms : {0U, 1U, default_interval}) { @@ -1270,7 +1284,7 @@ TEST_F(LinuxBackendTest, FakeUinputConstructionCoversCapabilitiesAndFailureBranc EXPECT_EQ(keyboard.name, lvh::profiles::keyboard().name); EXPECT_EQ(keyboard.bustype, BUS_USB); EXPECT_TRUE(has_type(keyboard, EV_KEY)); - for (const auto code : {KEY_A, KEY_ENTER, KEY_LEFTSHIFT, KEY_F1, KEY_VOLUMEUP, KEY_OK}) { + for (const auto code : {KEY_A, KEY_ENTER, KEY_LEFTSHIFT, KEY_RO, KEY_F1, KEY_VOLUMEUP, KEY_OK}) { EXPECT_NE(find_code(keyboard, EV_KEY, code), nullptr) << code; } for (const auto code : {BTN_LEFT, BTN_SOUTH, BTN_TOOL_PEN, BTN_TOUCH}) {