From 678a05217e02fbaf7baabebb4025d9ae8b20e8bc Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 11:17:02 -0800 Subject: [PATCH 1/9] Add XTest input fallback --- CMakeLists.txt | 2 + src/platform/linux/input.cpp | 362 +++++++++++++++++++++-------------- 2 files changed, 224 insertions(+), 140 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c9c03411f6..73f2da9a630 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,6 +296,8 @@ else() add_compile_definitions(SUNSHINE_BUILD_CUDA) endif() + list(APPEND PLATFORM_LIBRARIES Xtst) + if(LIBDRM_FOUND AND LIBCAP_FOUND) add_compile_definitions(SUNSHINE_BUILD_DRM) include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS}) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index c4585e1c8bc..b30e70228dd 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -4,6 +4,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -45,8 +49,7 @@ using mail_evdev_t = std::tuple init_keycodes() { std::array keycodes {}; -#define __CONVERT(wincode, linuxcode, scancode) \ +#define __CONVERT(wincode, linuxcode, scancode, keysym) \ static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ - keycodes[wincode] = keycode_t { linuxcode, scancode }; - - constexpr auto VK_NUMPAD = 0x60; - constexpr auto VK_F1 = 0x70; - constexpr auto VK_F13 = 0x7C; - constexpr auto VK_0 = 0x30; - - for(auto x = 0; x < 9; ++x) { - keycodes[x + VK_NUMPAD + 1] = keycode_t { (std::uint32_t)KEY_KP1 + x, (std::uint32_t)0x70059 + x }; - keycodes[x + VK_0 + 1] = keycode_t { (std::uint32_t)KEY_1 + x, (std::uint32_t)0x7001E + x }; - } - - for(auto x = 0; x < 10; ++x) { - keycodes[x + VK_F1] = keycode_t { (std::uint32_t)KEY_F1 + x, (std::uint32_t)0x70046 + x }; - } - - for(auto x = 0; x < 12; ++x) { - keycodes[x + VK_F13] = keycode_t { (std::uint32_t)KEY_F13 + x, (std::uint32_t)0x7003A + x }; - } - - __CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A); - __CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B); - __CONVERT(0x0C /* VKEY_CLEAR */, KEY_CLEAR, UNKNOWN); - __CONVERT(0x0D /* VKEY_RETURN */, KEY_ENTER, 0x70028); - __CONVERT(0x10 /* VKEY_SHIFT */, KEY_LEFTSHIFT, 0x700E1); - __CONVERT(0x11 /* VKEY_CONTROL */, KEY_LEFTCTRL, 0x700E0); - __CONVERT(0x12 /* VKEY_MENU */, KEY_LEFTALT, UNKNOWN); - __CONVERT(0x13 /* VKEY_PAUSE */, KEY_PAUSE, UNKNOWN); - __CONVERT(0x14 /* VKEY_CAPITAL */, KEY_CAPSLOCK, 0x70039); - __CONVERT(0x15 /* VKEY_KANA */, KEY_KATAKANAHIRAGANA, UNKNOWN); - __CONVERT(0x16 /* VKEY_HANGUL */, KEY_HANGEUL, UNKNOWN); - __CONVERT(0x17 /* VKEY_JUNJA */, KEY_HANJA, UNKNOWN); - __CONVERT(0x19 /* VKEY_KANJI */, KEY_KATAKANA, UNKNOWN); - __CONVERT(0x1B /* VKEY_ESCAPE */, KEY_ESC, 0x70029); - __CONVERT(0x20 /* VKEY_SPACE */, KEY_SPACE, 0x7002C); - __CONVERT(0x21 /* VKEY_PRIOR */, KEY_PAGEUP, 0x7004B); - __CONVERT(0x22 /* VKEY_NEXT */, KEY_PAGEDOWN, 0x7004E); - __CONVERT(0x23 /* VKEY_END */, KEY_END, 0x7004D); - __CONVERT(0x24 /* VKEY_HOME */, KEY_HOME, 0x7004A); - __CONVERT(0x25 /* VKEY_LEFT */, KEY_LEFT, 0x70050); - __CONVERT(0x26 /* VKEY_UP */, KEY_UP, 0x70052); - __CONVERT(0x27 /* VKEY_RIGHT */, KEY_RIGHT, 0x7004F); - __CONVERT(0x28 /* VKEY_DOWN */, KEY_DOWN, 0x70051); - __CONVERT(0x29 /* VKEY_SELECT */, KEY_SELECT, UNKNOWN); - __CONVERT(0x2A /* VKEY_PRINT */, KEY_PRINT, UNKNOWN); - __CONVERT(0x2C /* VKEY_SNAPSHOT */, KEY_SYSRQ, 0x70046); - __CONVERT(0x2D /* VKEY_INSERT */, KEY_INSERT, 0x70049); - __CONVERT(0x2E /* VKEY_DELETE */, KEY_DELETE, 0x7004C); - __CONVERT(0x2F /* VKEY_HELP */, KEY_HELP, UNKNOWN); - __CONVERT(0x30 /* VKEY_0 */, KEY_0, 0x70027); - __CONVERT(0x31 /* VKEY_1 */, KEY_1, 0x7001E); - __CONVERT(0x32 /* VKEY_2 */, KEY_2, 0x7001F); - __CONVERT(0x33 /* VKEY_3 */, KEY_3, 0x70020); - __CONVERT(0x34 /* VKEY_4 */, KEY_4, 0x70021); - __CONVERT(0x35 /* VKEY_5 */, KEY_5, 0x70022); - __CONVERT(0x36 /* VKEY_6 */, KEY_6, 0x70023); - __CONVERT(0x37 /* VKEY_7 */, KEY_7, 0x70024); - __CONVERT(0x38 /* VKEY_8 */, KEY_8, 0x70025); - __CONVERT(0x39 /* VKEY_9 */, KEY_9, 0x70026); - __CONVERT(0x41 /* VKEY_A */, KEY_A, 0x70004); - __CONVERT(0x42 /* VKEY_B */, KEY_B, 0x70005); - __CONVERT(0x43 /* VKEY_C */, KEY_C, 0x70006); - __CONVERT(0x44 /* VKEY_D */, KEY_D, 0x70007); - __CONVERT(0x45 /* VKEY_E */, KEY_E, 0x70008); - __CONVERT(0x46 /* VKEY_F */, KEY_F, 0x70009); - __CONVERT(0x47 /* VKEY_G */, KEY_G, 0x7000A); - __CONVERT(0x48 /* VKEY_H */, KEY_H, 0x7000B); - __CONVERT(0x49 /* VKEY_I */, KEY_I, 0x7000C); - __CONVERT(0x4A /* VKEY_J */, KEY_J, 0x7000D); - __CONVERT(0x4B /* VKEY_K */, KEY_K, 0x7000E); - __CONVERT(0x4C /* VKEY_L */, KEY_L, 0x7000F); - __CONVERT(0x4D /* VKEY_M */, KEY_M, 0x70010); - __CONVERT(0x4E /* VKEY_N */, KEY_N, 0x70011); - __CONVERT(0x4F /* VKEY_O */, KEY_O, 0x70012); - __CONVERT(0x50 /* VKEY_P */, KEY_P, 0x70013); - __CONVERT(0x51 /* VKEY_Q */, KEY_Q, 0x70014); - __CONVERT(0x52 /* VKEY_R */, KEY_R, 0x70015); - __CONVERT(0x53 /* VKEY_S */, KEY_S, 0x70016); - __CONVERT(0x54 /* VKEY_T */, KEY_T, 0x70017); - __CONVERT(0x55 /* VKEY_U */, KEY_U, 0x70018); - __CONVERT(0x56 /* VKEY_V */, KEY_V, 0x70019); - __CONVERT(0x57 /* VKEY_W */, KEY_W, 0x7001A); - __CONVERT(0x58 /* VKEY_X */, KEY_X, 0x7001B); - __CONVERT(0x59 /* VKEY_Y */, KEY_Y, 0x7001C); - __CONVERT(0x5A /* VKEY_Z */, KEY_Z, 0x7001D); - __CONVERT(0x5B /* VKEY_LWIN */, KEY_LEFTMETA, 0x700E3); - __CONVERT(0x5C /* VKEY_RWIN */, KEY_RIGHTMETA, 0x700E7); - __CONVERT(0x5F /* VKEY_SLEEP */, KEY_SLEEP, UNKNOWN); - __CONVERT(0x60 /* VKEY_NUMPAD0 */, KEY_KP0, 0x70062); - __CONVERT(0x61 /* VKEY_NUMPAD1 */, KEY_KP1, 0x70059); - __CONVERT(0x62 /* VKEY_NUMPAD2 */, KEY_KP2, 0x7005A); - __CONVERT(0x63 /* VKEY_NUMPAD3 */, KEY_KP3, 0x7005B); - __CONVERT(0x64 /* VKEY_NUMPAD4 */, KEY_KP4, 0x7005C); - __CONVERT(0x65 /* VKEY_NUMPAD5 */, KEY_KP5, 0x7005D); - __CONVERT(0x66 /* VKEY_NUMPAD6 */, KEY_KP6, 0x7005E); - __CONVERT(0x67 /* VKEY_NUMPAD7 */, KEY_KP7, 0x7005F); - __CONVERT(0x68 /* VKEY_NUMPAD8 */, KEY_KP8, 0x70060); - __CONVERT(0x69 /* VKEY_NUMPAD9 */, KEY_KP9, 0x70061); - __CONVERT(0x6A /* VKEY_MULTIPLY */, KEY_KPASTERISK, 0x70055); - __CONVERT(0x6B /* VKEY_ADD */, KEY_KPPLUS, 0x70057); - __CONVERT(0x6C /* VKEY_SEPARATOR */, KEY_KPCOMMA, UNKNOWN); - __CONVERT(0x6D /* VKEY_SUBTRACT */, KEY_KPMINUS, 0x70056); - __CONVERT(0x6E /* VKEY_DECIMAL */, KEY_KPDOT, 0x70063); - __CONVERT(0x6F /* VKEY_DIVIDE */, KEY_KPSLASH, 0x70054); - __CONVERT(0x7A /* VKEY_F11 */, KEY_F11, 70044); - __CONVERT(0x7B /* VKEY_F12 */, KEY_F12, 70045); - __CONVERT(0x90 /* VKEY_NUMLOCK */, KEY_NUMLOCK, 0x70053); - __CONVERT(0x91 /* VKEY_SCROLL */, KEY_SCROLLLOCK, 0x70047); - __CONVERT(0xA0 /* VKEY_LSHIFT */, KEY_LEFTSHIFT, 0x700E1); - __CONVERT(0xA1 /* VKEY_RSHIFT */, KEY_RIGHTSHIFT, 0x700E5); - __CONVERT(0xA2 /* VKEY_LCONTROL */, KEY_LEFTCTRL, 0x700E0); - __CONVERT(0xA3 /* VKEY_RCONTROL */, KEY_RIGHTCTRL, 0x700E4); - __CONVERT(0xA4 /* VKEY_LMENU */, KEY_LEFTALT, 0x7002E); - __CONVERT(0xA5 /* VKEY_RMENU */, KEY_RIGHTALT, 0x700E6); - __CONVERT(0xBA /* VKEY_OEM_1 */, KEY_SEMICOLON, 0x70033); - __CONVERT(0xBB /* VKEY_OEM_PLUS */, KEY_EQUAL, 0x7002E); - __CONVERT(0xBC /* VKEY_OEM_COMMA */, KEY_COMMA, 0x70036); - __CONVERT(0xBD /* VKEY_OEM_MINUS */, KEY_MINUS, 0x7002D); - __CONVERT(0xBE /* VKEY_OEM_PERIOD */, KEY_DOT, 0x70037); - __CONVERT(0xBF /* VKEY_OEM_2 */, KEY_SLASH, 0x70038); - __CONVERT(0xC0 /* VKEY_OEM_3 */, KEY_GRAVE, 0x70035); - __CONVERT(0xDB /* VKEY_OEM_4 */, KEY_LEFTBRACE, 0x7002F); - __CONVERT(0xDC /* VKEY_OEM_5 */, KEY_BACKSLASH, 0x70031); - __CONVERT(0xDD /* VKEY_OEM_6 */, KEY_RIGHTBRACE, 0x70030); - __CONVERT(0xDE /* VKEY_OEM_7 */, KEY_APOSTROPHE, 0x70034); - __CONVERT(0xE2 /* VKEY_NON_US_BACKSLASH */, KEY_102ND, 0x70064); + keycodes[wincode] = keycode_t { linuxcode, scancode, keysym }; + +__CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A, XK_BackSpace); +__CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B, XK_Tab); +__CONVERT(0x0C /* VKEY_CLEAR */, KEY_CLEAR, UNKNOWN, XK_Clear); +__CONVERT(0x0D /* VKEY_RETURN */, KEY_ENTER, 0x70028, XK_Return); +__CONVERT(0x10 /* VKEY_SHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); +__CONVERT(0x11 /* VKEY_CONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); +__CONVERT(0x12 /* VKEY_MENU */, KEY_LEFTALT, UNKNOWN, XK_Alt_L); +__CONVERT(0x13 /* VKEY_PAUSE */, KEY_PAUSE, UNKNOWN, XK_Pause); +__CONVERT(0x14 /* VKEY_CAPITAL */, KEY_CAPSLOCK, 0x70039, XK_Caps_Lock); +__CONVERT(0x15 /* VKEY_KANA */, KEY_KATAKANAHIRAGANA, UNKNOWN, XK_Kana_Shift); +__CONVERT(0x16 /* VKEY_HANGUL */, KEY_HANGEUL, UNKNOWN, XK_Hangul); +__CONVERT(0x17 /* VKEY_JUNJA */, KEY_HANJA, UNKNOWN, XK_Hangul_Jeonja); +__CONVERT(0x19 /* VKEY_KANJI */, KEY_KATAKANA, UNKNOWN, XK_Kanji); +__CONVERT(0x1B /* VKEY_ESCAPE */, KEY_ESC, 0x70029, XK_Escape); +__CONVERT(0x20 /* VKEY_SPACE */, KEY_SPACE, 0x7002C, XK_space); +__CONVERT(0x21 /* VKEY_PRIOR */, KEY_PAGEUP, 0x7004B, XK_Page_Up); +__CONVERT(0x22 /* VKEY_NEXT */, KEY_PAGEDOWN, 0x7004E, XK_Page_Down); +__CONVERT(0x23 /* VKEY_END */, KEY_END, 0x7004D, XK_End); +__CONVERT(0x24 /* VKEY_HOME */, KEY_HOME, 0x7004A, XK_Home); +__CONVERT(0x25 /* VKEY_LEFT */, KEY_LEFT, 0x70050, XK_Left); +__CONVERT(0x26 /* VKEY_UP */, KEY_UP, 0x70052, XK_Up); +__CONVERT(0x27 /* VKEY_RIGHT */, KEY_RIGHT, 0x7004F, XK_Right); +__CONVERT(0x28 /* VKEY_DOWN */, KEY_DOWN, 0x70051, XK_Down); +__CONVERT(0x29 /* VKEY_SELECT */, KEY_SELECT, UNKNOWN, XK_Select); +__CONVERT(0x2A /* VKEY_PRINT */, KEY_PRINT, UNKNOWN, XK_Print); +__CONVERT(0x2C /* VKEY_SNAPSHOT */, KEY_SYSRQ, 0x70046, XK_Sys_Req); +__CONVERT(0x2D /* VKEY_INSERT */, KEY_INSERT, 0x70049, XK_Insert); +__CONVERT(0x2E /* VKEY_DELETE */, KEY_DELETE, 0x7004C, XK_Delete); +__CONVERT(0x2F /* VKEY_HELP */, KEY_HELP, UNKNOWN, XK_Help); +__CONVERT(0x30 /* VKEY_0 */, KEY_0, 0x70027, XK_0); +__CONVERT(0x31 /* VKEY_1 */, KEY_1, 0x7001E, XK_1); +__CONVERT(0x32 /* VKEY_2 */, KEY_2, 0x7001F, XK_2); +__CONVERT(0x33 /* VKEY_3 */, KEY_3, 0x70020, XK_3); +__CONVERT(0x34 /* VKEY_4 */, KEY_4, 0x70021, XK_4); +__CONVERT(0x35 /* VKEY_5 */, KEY_5, 0x70022, XK_5); +__CONVERT(0x36 /* VKEY_6 */, KEY_6, 0x70023, XK_6); +__CONVERT(0x37 /* VKEY_7 */, KEY_7, 0x70024, XK_7); +__CONVERT(0x38 /* VKEY_8 */, KEY_8, 0x70025, XK_8); +__CONVERT(0x39 /* VKEY_9 */, KEY_9, 0x70026, XK_9); +__CONVERT(0x41 /* VKEY_A */, KEY_A, 0x70004, XK_A); +__CONVERT(0x42 /* VKEY_B */, KEY_B, 0x70005, XK_B); +__CONVERT(0x43 /* VKEY_C */, KEY_C, 0x70006, XK_C); +__CONVERT(0x44 /* VKEY_D */, KEY_D, 0x70007, XK_D); +__CONVERT(0x45 /* VKEY_E */, KEY_E, 0x70008, XK_E); +__CONVERT(0x46 /* VKEY_F */, KEY_F, 0x70009, XK_F); +__CONVERT(0x47 /* VKEY_G */, KEY_G, 0x7000A, XK_G); +__CONVERT(0x48 /* VKEY_H */, KEY_H, 0x7000B, XK_H); +__CONVERT(0x49 /* VKEY_I */, KEY_I, 0x7000C, XK_I); +__CONVERT(0x4A /* VKEY_J */, KEY_J, 0x7000D, XK_J); +__CONVERT(0x4B /* VKEY_K */, KEY_K, 0x7000E, XK_K); +__CONVERT(0x4C /* VKEY_L */, KEY_L, 0x7000F, XK_L); +__CONVERT(0x4D /* VKEY_M */, KEY_M, 0x70010, XK_M); +__CONVERT(0x4E /* VKEY_N */, KEY_N, 0x70011, XK_N); +__CONVERT(0x4F /* VKEY_O */, KEY_O, 0x70012, XK_O); +__CONVERT(0x50 /* VKEY_P */, KEY_P, 0x70013, XK_P); +__CONVERT(0x51 /* VKEY_Q */, KEY_Q, 0x70014, XK_Q); +__CONVERT(0x52 /* VKEY_R */, KEY_R, 0x70015, XK_R); +__CONVERT(0x53 /* VKEY_S */, KEY_S, 0x70016, XK_S); +__CONVERT(0x54 /* VKEY_T */, KEY_T, 0x70017, XK_T); +__CONVERT(0x55 /* VKEY_U */, KEY_U, 0x70018, XK_U); +__CONVERT(0x56 /* VKEY_V */, KEY_V, 0x70019, XK_V); +__CONVERT(0x57 /* VKEY_W */, KEY_W, 0x7001A, XK_W); +__CONVERT(0x58 /* VKEY_X */, KEY_X, 0x7001B, XK_X); +__CONVERT(0x59 /* VKEY_Y */, KEY_Y, 0x7001C, XK_Y); +__CONVERT(0x5A /* VKEY_Z */, KEY_Z, 0x7001D, XK_Z); +__CONVERT(0x5B /* VKEY_LWIN */, KEY_LEFTMETA, 0x700E3, XK_Meta_L); +__CONVERT(0x5C /* VKEY_RWIN */, KEY_RIGHTMETA, 0x700E7, XK_Meta_R); +__CONVERT(0x5F /* VKEY_SLEEP */, KEY_SLEEP, UNKNOWN, UNKNOWN); +__CONVERT(0x60 /* VKEY_NUMPAD0 */, KEY_KP0, 0x70062, XK_KP_0); +__CONVERT(0x61 /* VKEY_NUMPAD1 */, KEY_KP1, 0x70059, XK_KP_1); +__CONVERT(0x62 /* VKEY_NUMPAD2 */, KEY_KP2, 0x7005A, XK_KP_2); +__CONVERT(0x63 /* VKEY_NUMPAD3 */, KEY_KP3, 0x7005B, XK_KP_3); +__CONVERT(0x64 /* VKEY_NUMPAD4 */, KEY_KP4, 0x7005C, XK_KP_4); +__CONVERT(0x65 /* VKEY_NUMPAD5 */, KEY_KP5, 0x7005D, XK_KP_5); +__CONVERT(0x66 /* VKEY_NUMPAD6 */, KEY_KP6, 0x7005E, XK_KP_6); +__CONVERT(0x67 /* VKEY_NUMPAD7 */, KEY_KP7, 0x7005F, XK_KP_7); +__CONVERT(0x68 /* VKEY_NUMPAD8 */, KEY_KP8, 0x70060, XK_KP_8); +__CONVERT(0x69 /* VKEY_NUMPAD9 */, KEY_KP9, 0x70061, XK_KP_9); +__CONVERT(0x6A /* VKEY_MULTIPLY */, KEY_KPASTERISK, 0x70055, XK_KP_Multiply); +__CONVERT(0x6B /* VKEY_ADD */, KEY_KPPLUS, 0x70057, XK_KP_Add); +__CONVERT(0x6C /* VKEY_SEPARATOR */, KEY_KPCOMMA, UNKNOWN, XK_KP_Separator); +__CONVERT(0x6D /* VKEY_SUBTRACT */, KEY_KPMINUS, 0x70056, XK_KP_Subtract); +__CONVERT(0x6E /* VKEY_DECIMAL */, KEY_KPDOT, 0x70063, XK_KP_Decimal); +__CONVERT(0x6F /* VKEY_DIVIDE */, KEY_KPSLASH, 0x70054, XK_KP_Divide); +__CONVERT(0x70 /* VKEY_F1 */, KEY_F1, 0x70046, XK_F1); +__CONVERT(0x71 /* VKEY_F2 */, KEY_F2, 0x70047, XK_F2); +__CONVERT(0x72 /* VKEY_F3 */, KEY_F3, 0x70048, XK_F3); +__CONVERT(0x73 /* VKEY_F4 */, KEY_F4, 0x70049, XK_F4); +__CONVERT(0x74 /* VKEY_F5 */, KEY_F5, 0x7004a, XK_F5); +__CONVERT(0x75 /* VKEY_F6 */, KEY_F6, 0x7004b, XK_F6); +__CONVERT(0x76 /* VKEY_F7 */, KEY_F7, 0x7004c, XK_F7); +__CONVERT(0x77 /* VKEY_F8 */, KEY_F8, 0x7004d, XK_F8); +__CONVERT(0x78 /* VKEY_F9 */, KEY_F9, 0x7004e, XK_F9); +__CONVERT(0x79 /* VKEY_F10 */, KEY_F10, 0x70044, XK_F10); +__CONVERT(0x7A /* VKEY_F11 */, KEY_F11, 0x70044, XK_F11); +__CONVERT(0x7B /* VKEY_F12 */, KEY_F12, 0x70045, XK_F12); +__CONVERT(0x7C /* VKEY_F13 */, KEY_F13, 0x7003a, XK_F13); +__CONVERT(0x7D /* VKEY_F14 */, KEY_F14, 0x7003b, XK_F14); +__CONVERT(0x7E /* VKEY_F15 */, KEY_F15, 0x7003c, XK_F15); +__CONVERT(0x7F /* VKEY_F16 */, KEY_F16, 0x7003d, XK_F16); +__CONVERT(0x80 /* VKEY_F17 */, KEY_F17, 0x7003e, XK_F17); +__CONVERT(0x81 /* VKEY_F18 */, KEY_F18, 0x7003f, XK_F18); +__CONVERT(0x82 /* VKEY_F19 */, KEY_F19, 0x70040, XK_F19); +__CONVERT(0x83 /* VKEY_F20 */, KEY_F20, 0x70041, XK_F20); +__CONVERT(0x84 /* VKEY_F21 */, KEY_F21, 0x70042, XK_F21); +__CONVERT(0x85 /* VKEY_F22 */, KEY_F12, 0x70043, XK_F12); +__CONVERT(0x86 /* VKEY_F23 */, KEY_F23, 0x70044, XK_F23); +__CONVERT(0x87 /* VKEY_F24 */, KEY_F24, 0x70045, XK_F24); +__CONVERT(0x90 /* VKEY_NUMLOCK */, KEY_NUMLOCK, 0x70053, XK_Num_Lock); +__CONVERT(0x91 /* VKEY_SCROLL */, KEY_SCROLLLOCK, 0x70047, XK_Scroll_Lock); +__CONVERT(0xA0 /* VKEY_LSHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); +__CONVERT(0xA1 /* VKEY_RSHIFT */, KEY_RIGHTSHIFT, 0x700E5, XK_Shift_R); +__CONVERT(0xA2 /* VKEY_LCONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); +__CONVERT(0xA3 /* VKEY_RCONTROL */, KEY_RIGHTCTRL, 0x700E4, XK_Control_R); +__CONVERT(0xA4 /* VKEY_LMENU */, KEY_LEFTALT, 0x7002E, XK_Alt_L); +__CONVERT(0xA5 /* VKEY_RMENU */, KEY_RIGHTALT, 0x700E6, XK_Alt_R); +__CONVERT(0xBA /* VKEY_OEM_1 */, KEY_SEMICOLON, 0x70033, XK_semicolon); +__CONVERT(0xBB /* VKEY_OEM_PLUS */, KEY_EQUAL, 0x7002E, XK_equal); +__CONVERT(0xBC /* VKEY_OEM_COMMA */, KEY_COMMA, 0x70036, XK_comma); +__CONVERT(0xBD /* VKEY_OEM_MINUS */, KEY_MINUS, 0x7002D, XK_minus); +__CONVERT(0xBE /* VKEY_OEM_PERIOD */, KEY_DOT, 0x70037, XK_period); +__CONVERT(0xBF /* VKEY_OEM_2 */, KEY_SLASH, 0x70038, XK_slash); +__CONVERT(0xC0 /* VKEY_OEM_3 */, KEY_GRAVE, 0x70035, XK_grave); +__CONVERT(0xDB /* VKEY_OEM_4 */, KEY_LEFTBRACE, 0x7002F, XK_braceleft); +__CONVERT(0xDC /* VKEY_OEM_5 */, KEY_BACKSLASH, 0x70031, XK_backslash); +__CONVERT(0xDD /* VKEY_OEM_6 */, KEY_RIGHTBRACE, 0x70030, XK_braceright); +__CONVERT(0xDE /* VKEY_OEM_7 */, KEY_APOSTROPHE, 0x70034, XK_apostrophe); +__CONVERT(0xE2 /* VKEY_NON_US_BACKSLASH */, KEY_102ND, 0x70064, XK_backslash); #undef __CONVERT return keycodes; @@ -693,6 +700,8 @@ struct input_raw_t { evdev_t touch_dev; evdev_t mouse_dev; evdev_t keyboard_dev; + + Display *display; }; inline void rumbleIterate(std::vector &effects, std::vector &polls, std::chrono::milliseconds to) { @@ -899,10 +908,16 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { } } +static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { + Display *xdisplay = ((input_raw_t *)input.get())->display; + XTestFakeMotionEvent(xdisplay, -1, x, y, CurrentTime); + XFlush(xdisplay); +} void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); if(!touchscreen) { + x_abs_mouse(input, touch_port, x, y); return; } @@ -917,9 +932,16 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); } +static void x_move_mouse(input_t &input, int deltaX, int deltaY) { + Display *xdisplay = ((input_raw_t *)input.get())->display; + XTestFakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); + XFlush(xdisplay); +} + void move_mouse(input_t &input, int deltaX, int deltaY) { auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { + x_move_mouse(input, deltaX, deltaY); return; } @@ -934,7 +956,39 @@ void move_mouse(input_t &input, int deltaX, int deltaY) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +static void x_button_mouse(input_t &input, int button, bool release) { + unsigned int x_button = 0; + switch (button) { + case BUTTON_LEFT: + x_button = 1; + break; + case BUTTON_MIDDLE: + x_button = 2; + break; + case BUTTON_RIGHT: + x_button = 3; + break; + default: + x_button = (button - 4) + 8; // Button 4 (Moonlight) starts at index 8 (X11) + break; + } + + if (x_button < 1 || x_button > 31) { + return; + } + + Display *xdisplay = ((input_raw_t *)input.get())->display; + XTestFakeButtonEvent(xdisplay, x_button, !release, CurrentTime); + XFlush(xdisplay); +} + void button_mouse(input_t &input, int button, bool release) { + auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); + if(!mouse) { + x_button_mouse(input, button, release); + return; + } + int btn_type; int scan; @@ -959,21 +1013,27 @@ void button_mouse(input_t &input, int button, bool release) { scan = 90005; } - auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); - if(!mouse) { - return; - } - libevdev_uinput_write_event(mouse, EV_MSC, MSC_SCAN, scan); libevdev_uinput_write_event(mouse, EV_KEY, btn_type, release ? 0 : 1); libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { + const int button = distance > 0 ? button_pos : button_neg; + Display *xdisplay = ((input_raw_t *)input.get())->display; + for (int i = 0; i < abs(distance); i++) { + XTestFakeButtonEvent(xdisplay, button, true, CurrentTime); + XTestFakeButtonEvent(xdisplay, button, false, CurrentTime); + } + XFlush(xdisplay); +} + void scroll(input_t &input, int high_res_distance) { int distance = high_res_distance / 120; auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { + x_scroll(input, distance, 4, 5); return; } @@ -987,6 +1047,7 @@ void hscroll(input_t &input, int high_res_distance) { auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { + x_scroll(input, distance, 6, 7); return; } @@ -1003,9 +1064,27 @@ static keycode_t keysym(std::uint16_t modcode) { return {}; } +static void x_keyboard(input_t &input, uint16_t modcode, bool release) { + auto keycode = keysym(modcode); + if(keycode.keysym == UNKNOWN) { + return; + } + + Display *xdisplay = ((input_raw_t *)input.get())->display; + + const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); + if (keycode_x == 0) { + return; + } + + XTestFakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); + XFlush(xdisplay); +} + void keyboard(input_t &input, uint16_t modcode, bool release) { auto keyboard = ((input_raw_t *)input.get())->keyboard_input.get(); if(!keyboard) { + x_keyboard(input, modcode, release); return; } @@ -1014,14 +1093,12 @@ void keyboard(input_t &input, uint16_t modcode, bool release) { return; } - if(keycode.scancode != UNKNOWN && (release || !keycode.pressed)) { + if(keycode.scancode != UNKNOWN) { libevdev_uinput_write_event(keyboard, EV_MSC, MSC_SCAN, keycode.scancode); } - libevdev_uinput_write_event(keyboard, EV_KEY, keycode.keycode, release ? 0 : (1 + keycode.pressed)); + libevdev_uinput_write_event(keyboard, EV_KEY, keycode.keycode, release ? 0 : 1); libevdev_uinput_write_event(keyboard, EV_SYN, SYN_REPORT, 0); - - keycode.pressed = 1; } void unicode(input_t &input, char *utf8, int size) { @@ -1279,19 +1356,21 @@ input_t input() { gp.gamepads.resize(MAX_GAMEPADS); // Ensure starting from clean slate + XInitThreads(); gp.clear(); gp.keyboard_dev = keyboard(); gp.touch_dev = touchscreen(); gp.mouse_dev = mouse(); gp.gamepad_dev = x360(); + gp.display = XOpenDisplay(NULL); gp.create_mouse(); gp.create_touchscreen(); gp.create_keyboard(); - // If we do not have a keyboard, touchscreen, or mouse, no input is possible + // If we do not have a keyboard, touchscreen, or mouse, fall back to XTest if(!gp.mouse_input && !gp.touch_input && !gp.keyboard_input) { - BOOST_LOG(error) << "Unable to create any input devices! Are you a member of the 'input' group?"sv; + BOOST_LOG(error) << "Unable to create any input devices! Falling back to XTest! Are you a member of the 'input' group?"sv; } return result; @@ -1299,6 +1378,9 @@ input_t input() { void freeInput(void *p) { auto *input = (input_raw_t *)p; + if (input->display) { + XCloseDisplay(input->display); + } delete input; } From e4a5880db46b1b8e37567db77f6d3012466377ba Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 14:29:55 -0800 Subject: [PATCH 2/9] dynamically load x11 --- CMakeLists.txt | 2 - src/platform/linux/input.cpp | 108 ++++++++++++++++++++++++++++----- src/platform/linux/x11grab.cpp | 6 +- 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 73f2da9a630..3c9c03411f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,8 +296,6 @@ else() add_compile_definitions(SUNSHINE_BUILD_CUDA) endif() - list(APPEND PLATFORM_LIBRARIES Xtst) - if(LIBDRM_FOUND AND LIBCAP_FOUND) add_compile_definitions(SUNSHINE_BUILD_DRM) include_directories(${LIBDRM_INCLUDE_DIRS} ${LIBCAP_INCLUDE_DIRS}) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index b30e70228dd..e09cc2c5267 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -19,6 +19,8 @@ #include "src/platform/common.h" +#include "misc.h" + // Support older versions #ifndef REL_HWHEEL_HI_RES #define REL_HWHEEL_HI_RES 0x0c @@ -29,7 +31,82 @@ #endif using namespace std::literals; + namespace platf { +namespace x11 { +#define _FN(x, ret, args) \ + typedef ret(*x##_fn) args; \ + static x##_fn x + +_FN(OpenDisplay, Display *, (_Xconst char *display_name)); +_FN(CloseDisplay, int, (Display * display)); +_FN(InitThreads, Status, (void)); +_FN(Flush, int, (Display *)); + +namespace tst { +_FN(FakeMotionEvent, int, (Display * dpy, int screen_numer, int x, int y, unsigned long delay)); +_FN(FakeRelativeMotionEvent, int, (Display * dpy, int deltaX, int deltaY, unsigned long delay)); +_FN(FakeButtonEvent, int, (Display * dpy, unsigned int button, Bool is_press, unsigned long delay)); +_FN(FakeKeyEvent, int, (Display * dpy, unsigned int keycode, Bool is_press, unsigned long delay)); + +static int init() { + static void *handle { nullptr }; + static bool funcs_loaded = false; + + if(funcs_loaded) return 0; + + if(!handle) { + handle = dyn::handle({ "libXtst.so.6", "libXtst.so" }); + if(!handle) { + return -1; + } + } + + std::vector> funcs { + { (dyn::apiproc *)&FakeMotionEvent, "XTestFakeMotionEvent" }, + { (dyn::apiproc *)&FakeRelativeMotionEvent, "XTestFakeRelativeMotionEvent" }, + { (dyn::apiproc *)&FakeButtonEvent, "XTestFakeButtonEvent" }, + { (dyn::apiproc *)&FakeKeyEvent, "XTestFakeKeyEvent" }, + }; + + if(dyn::load(handle, funcs)) { + return -1; + } + + funcs_loaded = true; + return 0; +} +} // namespace tst + +static int init() { + static void *handle { nullptr }; + static bool funcs_loaded = false; + + if(funcs_loaded) return 0; + + if(!handle) { + handle = dyn::handle({ "libX11.so.6", "libX11.so" }); + if(!handle) { + return -1; + } + } + + std::vector> funcs { + { (dyn::apiproc *)&OpenDisplay, "XOpenDisplay" }, + { (dyn::apiproc *)&CloseDisplay, "XCloseDisplay" }, + { (dyn::apiproc *)&InitThreads, "XInitThreads" }, + { (dyn::apiproc *)&Flush, "XFlush" }, + }; + + if(dyn::load(handle, funcs)) { + return -1; + } + + funcs_loaded = true; + return 0; +} +} // namespace x11 + constexpr auto mail_evdev = "platf::evdev"sv; using evdev_t = util::safe_ptr; @@ -910,8 +987,8 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { Display *xdisplay = ((input_raw_t *)input.get())->display; - XTestFakeMotionEvent(xdisplay, -1, x, y, CurrentTime); - XFlush(xdisplay); + x11::tst::FakeMotionEvent(xdisplay, -1, x, y, CurrentTime); + x11::Flush(xdisplay); } void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { @@ -934,8 +1011,8 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) static void x_move_mouse(input_t &input, int deltaX, int deltaY) { Display *xdisplay = ((input_raw_t *)input.get())->display; - XTestFakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); - XFlush(xdisplay); + x11::tst::FakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); + x11::Flush(xdisplay); } void move_mouse(input_t &input, int deltaX, int deltaY) { @@ -978,8 +1055,8 @@ static void x_button_mouse(input_t &input, int button, bool release) { } Display *xdisplay = ((input_raw_t *)input.get())->display; - XTestFakeButtonEvent(xdisplay, x_button, !release, CurrentTime); - XFlush(xdisplay); + x11::tst::FakeButtonEvent(xdisplay, x_button, !release, CurrentTime); + x11::Flush(xdisplay); } void button_mouse(input_t &input, int button, bool release) { @@ -1022,10 +1099,10 @@ static void x_scroll(input_t &input, int distance, int button_pos, int button_ne const int button = distance > 0 ? button_pos : button_neg; Display *xdisplay = ((input_raw_t *)input.get())->display; for (int i = 0; i < abs(distance); i++) { - XTestFakeButtonEvent(xdisplay, button, true, CurrentTime); - XTestFakeButtonEvent(xdisplay, button, false, CurrentTime); + x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); + x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); } - XFlush(xdisplay); + x11::Flush(xdisplay); } void scroll(input_t &input, int high_res_distance) { @@ -1077,8 +1154,8 @@ static void x_keyboard(input_t &input, uint16_t modcode, bool release) { return; } - XTestFakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); - XFlush(xdisplay); + x11::tst::FakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); + x11::Flush(xdisplay); } void keyboard(input_t &input, uint16_t modcode, bool release) { @@ -1356,13 +1433,16 @@ input_t input() { gp.gamepads.resize(MAX_GAMEPADS); // Ensure starting from clean slate - XInitThreads(); + x11::init(); + x11::tst::init(); + + x11::InitThreads(); gp.clear(); gp.keyboard_dev = keyboard(); gp.touch_dev = touchscreen(); gp.mouse_dev = mouse(); gp.gamepad_dev = x360(); - gp.display = XOpenDisplay(NULL); + gp.display = x11::OpenDisplay(NULL); gp.create_mouse(); gp.create_touchscreen(); @@ -1379,7 +1459,7 @@ input_t input() { void freeInput(void *p) { auto *input = (input_raw_t *)p; if (input->display) { - XCloseDisplay(input->display); + x11::CloseDisplay(input->display); } delete input; } diff --git a/src/platform/linux/x11grab.cpp b/src/platform/linux/x11grab.cpp index e18de69d382..cf89328f2fa 100644 --- a/src/platform/linux/x11grab.cpp +++ b/src/platform/linux/x11grab.cpp @@ -66,7 +66,7 @@ _FN(FreeScreenResources, void, (XRRScreenResources * resources)); _FN(FreeOutputInfo, void, (XRROutputInfo * outputInfo)); _FN(FreeCrtcInfo, void, (XRRCrtcInfo * crtcInfo)); -int init() { +static int init() { static void *handle { nullptr }; static bool funcs_loaded = false; @@ -100,7 +100,7 @@ int init() { namespace fix { _FN(GetCursorImage, XFixesCursorImage *, (Display * dpy)); -int init() { +static int init() { static void *handle { nullptr }; static bool funcs_loaded = false; @@ -126,7 +126,7 @@ int init() { } } // namespace fix -int init() { +static int init() { static void *handle { nullptr }; static bool funcs_loaded = false; From 4683f174950b1ea3da6865a5b95f608c8293f14d Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 14:41:15 -0800 Subject: [PATCH 3/9] handle init issues --- src/platform/linux/input.cpp | 42 ++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index e09cc2c5267..f0f5623f51e 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -760,6 +760,10 @@ struct input_raw_t { for(int x = 0; x < gamepads.size(); ++x) { clear_gamepad(x); } + if (display) { + x11::CloseDisplay(display); + display = nullptr; + } } ~input_raw_t() { @@ -987,6 +991,9 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } x11::tst::FakeMotionEvent(xdisplay, -1, x, y, CurrentTime); x11::Flush(xdisplay); } @@ -1011,6 +1018,9 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) static void x_move_mouse(input_t &input, int deltaX, int deltaY) { Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } x11::tst::FakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); x11::Flush(xdisplay); } @@ -1055,6 +1065,9 @@ static void x_button_mouse(input_t &input, int button, bool release) { } Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } x11::tst::FakeButtonEvent(xdisplay, x_button, !release, CurrentTime); x11::Flush(xdisplay); } @@ -1096,8 +1109,12 @@ void button_mouse(input_t &input, int button, bool release) { } static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { - const int button = distance > 0 ? button_pos : button_neg; Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } + + const int button = distance > 0 ? button_pos : button_neg; for (int i = 0; i < abs(distance); i++) { x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); @@ -1148,6 +1165,9 @@ static void x_keyboard(input_t &input, uint16_t modcode, bool release) { } Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); if (keycode_x == 0) { @@ -1433,24 +1453,27 @@ input_t input() { gp.gamepads.resize(MAX_GAMEPADS); // Ensure starting from clean slate - x11::init(); - x11::tst::init(); - - x11::InitThreads(); gp.clear(); gp.keyboard_dev = keyboard(); gp.touch_dev = touchscreen(); gp.mouse_dev = mouse(); gp.gamepad_dev = x360(); - gp.display = x11::OpenDisplay(NULL); gp.create_mouse(); gp.create_touchscreen(); gp.create_keyboard(); // If we do not have a keyboard, touchscreen, or mouse, fall back to XTest - if(!gp.mouse_input && !gp.touch_input && !gp.keyboard_input) { - BOOST_LOG(error) << "Unable to create any input devices! Falling back to XTest! Are you a member of the 'input' group?"sv; + if(!gp.mouse_input || !gp.touch_input || !gp.keyboard_input) { + BOOST_LOG(error) << "Unable to create some input devices! Are you a member of the 'input' group?"sv; + + if (x11::init() || x11::tst::init()) { + BOOST_LOG(error) << "Unable to initialize X11 and/or XTest fallback"sv; + } else { + BOOST_LOG(info) << "Falling back to XTest"sv; + x11::InitThreads(); + gp.display = x11::OpenDisplay(NULL); + } } return result; @@ -1458,9 +1481,6 @@ input_t input() { void freeInput(void *p) { auto *input = (input_raw_t *)p; - if (input->display) { - x11::CloseDisplay(input->display); - } delete input; } From d293d96c92c7b5beceaa4be1c674b05641f91e50 Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 14:43:43 -0800 Subject: [PATCH 4/9] handle disabling x11 --- src/platform/linux/input.cpp | 153 +++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 70 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index f0f5623f51e..3365194b182 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -33,6 +33,7 @@ using namespace std::literals; namespace platf { +#ifdef SUNSHINE_BUILD_X11 namespace x11 { #define _FN(x, ret, args) \ typedef ret(*x##_fn) args; \ @@ -106,6 +107,7 @@ static int init() { return 0; } } // namespace x11 +#endif constexpr auto mail_evdev = "platf::evdev"sv; @@ -989,6 +991,8 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { } } + +#ifdef SUNSHINE_BUILD_X11 static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { Display *xdisplay = ((input_raw_t *)input.get())->display; if (!xdisplay) { @@ -998,24 +1002,6 @@ static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, x11::Flush(xdisplay); } -void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { - auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); - if(!touchscreen) { - x_abs_mouse(input, touch_port, x, y); - return; - } - - auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); - auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); - - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y); - libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); - libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); - - libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); -} - static void x_move_mouse(input_t &input, int deltaX, int deltaY) { Display *xdisplay = ((input_raw_t *)input.get())->display; if (!xdisplay) { @@ -1025,24 +1011,6 @@ static void x_move_mouse(input_t &input, int deltaX, int deltaY) { x11::Flush(xdisplay); } -void move_mouse(input_t &input, int deltaX, int deltaY) { - auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); - if(!mouse) { - x_move_mouse(input, deltaX, deltaY); - return; - } - - if(deltaX) { - libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX); - } - - if(deltaY) { - libevdev_uinput_write_event(mouse, EV_REL, REL_Y, deltaY); - } - - libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); -} - static void x_button_mouse(input_t &input, int button, bool release) { unsigned int x_button = 0; switch (button) { @@ -1072,6 +1040,83 @@ static void x_button_mouse(input_t &input, int button, bool release) { x11::Flush(xdisplay); } +static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { + Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } + + const int button = distance > 0 ? button_pos : button_neg; + for (int i = 0; i < abs(distance); i++) { + x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); + x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); + } + x11::Flush(xdisplay); +} + +static void x_keyboard(input_t &input, uint16_t modcode, bool release) { + auto keycode = keysym(modcode); + if(keycode.keysym == UNKNOWN) { + return; + } + + Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } + + const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); + if (keycode_x == 0) { + return; + } + + x11::tst::FakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); + x11::Flush(xdisplay); +} +#else +static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {} +static void x_move_mouse(input_t &input, int deltaX, int deltaY) {} +static void x_button_mouse(input_t &input, int button, bool release) {} +static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) {} +static void x_keyboard(input_t &input, uint16_t modcode, bool release) {} +#endif + +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { + auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); + if(!touchscreen) { + x_abs_mouse(input, touch_port, x, y); + return; + } + + auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); + auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); + + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x); + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y); + libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); + libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); + + libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); +} + +void move_mouse(input_t &input, int deltaX, int deltaY) { + auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); + if(!mouse) { + x_move_mouse(input, deltaX, deltaY); + return; + } + + if(deltaX) { + libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX); + } + + if(deltaY) { + libevdev_uinput_write_event(mouse, EV_REL, REL_Y, deltaY); + } + + libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); +} + void button_mouse(input_t &input, int button, bool release) { auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { @@ -1108,20 +1153,6 @@ void button_mouse(input_t &input, int button, bool release) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } -static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { - Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { - return; - } - - const int button = distance > 0 ? button_pos : button_neg; - for (int i = 0; i < abs(distance); i++) { - x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); - x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); - } - x11::Flush(xdisplay); -} - void scroll(input_t &input, int high_res_distance) { int distance = high_res_distance / 120; @@ -1158,26 +1189,6 @@ static keycode_t keysym(std::uint16_t modcode) { return {}; } -static void x_keyboard(input_t &input, uint16_t modcode, bool release) { - auto keycode = keysym(modcode); - if(keycode.keysym == UNKNOWN) { - return; - } - - Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { - return; - } - - const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); - if (keycode_x == 0) { - return; - } - - x11::tst::FakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); - x11::Flush(xdisplay); -} - void keyboard(input_t &input, uint16_t modcode, bool release) { auto keyboard = ((input_raw_t *)input.get())->keyboard_input.get(); if(!keyboard) { @@ -1467,6 +1478,7 @@ input_t input() { if(!gp.mouse_input || !gp.touch_input || !gp.keyboard_input) { BOOST_LOG(error) << "Unable to create some input devices! Are you a member of the 'input' group?"sv; +#ifdef SUNSHINE_BUILD_X11 if (x11::init() || x11::tst::init()) { BOOST_LOG(error) << "Unable to initialize X11 and/or XTest fallback"sv; } else { @@ -1474,6 +1486,7 @@ input_t input() { x11::InitThreads(); gp.display = x11::OpenDisplay(NULL); } +#endif } return result; From 0b142c7c2e93eb8ad16a122c49813016515cb2c5 Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 14:45:58 -0800 Subject: [PATCH 5/9] handle disabling x11 --- src/platform/linux/input.cpp | 156 ++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 77 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index 3365194b182..cf55b8b7586 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -992,26 +992,66 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { } -#ifdef SUNSHINE_BUILD_X11 static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { +#ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; if (!xdisplay) { return; } x11::tst::FakeMotionEvent(xdisplay, -1, x, y, CurrentTime); x11::Flush(xdisplay); +#endif +} + +void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { + auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); + if(!touchscreen) { + x_abs_mouse(input, touch_port, x, y); + return; + } + + auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); + auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); + + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x); + libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y); + libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); + libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); + + libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); } static void x_move_mouse(input_t &input, int deltaX, int deltaY) { +#ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; if (!xdisplay) { return; } x11::tst::FakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); x11::Flush(xdisplay); +#endif +} + +void move_mouse(input_t &input, int deltaX, int deltaY) { + auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); + if(!mouse) { + x_move_mouse(input, deltaX, deltaY); + return; + } + + if(deltaX) { + libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX); + } + + if(deltaY) { + libevdev_uinput_write_event(mouse, EV_REL, REL_Y, deltaY); + } + + libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } static void x_button_mouse(input_t &input, int button, bool release) { +#ifdef SUNSHINE_BUILD_X11 unsigned int x_button = 0; switch (button) { case BUTTON_LEFT: @@ -1038,83 +1078,7 @@ static void x_button_mouse(input_t &input, int button, bool release) { } x11::tst::FakeButtonEvent(xdisplay, x_button, !release, CurrentTime); x11::Flush(xdisplay); -} - -static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { - Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { - return; - } - - const int button = distance > 0 ? button_pos : button_neg; - for (int i = 0; i < abs(distance); i++) { - x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); - x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); - } - x11::Flush(xdisplay); -} - -static void x_keyboard(input_t &input, uint16_t modcode, bool release) { - auto keycode = keysym(modcode); - if(keycode.keysym == UNKNOWN) { - return; - } - - Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { - return; - } - - const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); - if (keycode_x == 0) { - return; - } - - x11::tst::FakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); - x11::Flush(xdisplay); -} -#else -static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {} -static void x_move_mouse(input_t &input, int deltaX, int deltaY) {} -static void x_button_mouse(input_t &input, int button, bool release) {} -static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) {} -static void x_keyboard(input_t &input, uint16_t modcode, bool release) {} #endif - -void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { - auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); - if(!touchscreen) { - x_abs_mouse(input, touch_port, x, y); - return; - } - - auto scaled_x = (int)std::lround((x + touch_port.offset_x) * ((float)target_touch_port.width / (float)touch_port.width)); - auto scaled_y = (int)std::lround((y + touch_port.offset_y) * ((float)target_touch_port.height / (float)touch_port.height)); - - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_X, scaled_x); - libevdev_uinput_write_event(touchscreen, EV_ABS, ABS_Y, scaled_y); - libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 1); - libevdev_uinput_write_event(touchscreen, EV_KEY, BTN_TOOL_FINGER, 0); - - libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); -} - -void move_mouse(input_t &input, int deltaX, int deltaY) { - auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); - if(!mouse) { - x_move_mouse(input, deltaX, deltaY); - return; - } - - if(deltaX) { - libevdev_uinput_write_event(mouse, EV_REL, REL_X, deltaX); - } - - if(deltaY) { - libevdev_uinput_write_event(mouse, EV_REL, REL_Y, deltaY); - } - - libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } void button_mouse(input_t &input, int button, bool release) { @@ -1153,6 +1117,22 @@ void button_mouse(input_t &input, int button, bool release) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { +#ifdef SUNSHINE_BUILD_X11 + Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } + + const int button = distance > 0 ? button_pos : button_neg; + for (int i = 0; i < abs(distance); i++) { + x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); + x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); + } + x11::Flush(xdisplay); +#endif +} + void scroll(input_t &input, int high_res_distance) { int distance = high_res_distance / 120; @@ -1189,6 +1169,28 @@ static keycode_t keysym(std::uint16_t modcode) { return {}; } +static void x_keyboard(input_t &input, uint16_t modcode, bool release) { +#ifdef SUNSHINE_BUILD_X11 + auto keycode = keysym(modcode); + if(keycode.keysym == UNKNOWN) { + return; + } + + Display *xdisplay = ((input_raw_t *)input.get())->display; + if (!xdisplay) { + return; + } + + const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); + if (keycode_x == 0) { + return; + } + + x11::tst::FakeKeyEvent(xdisplay, keycode_x, !release, CurrentTime); + x11::Flush(xdisplay); +#endif +} + void keyboard(input_t &input, uint16_t modcode, bool release) { auto keyboard = ((input_raw_t *)input.get())->keyboard_input.get(); if(!keyboard) { From af194d435d8322f901ac100678055ac2b7a66ce9 Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 15:04:23 -0800 Subject: [PATCH 6/9] disable x11 even more --- src/platform/linux/input.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index cf55b8b7586..680ef495b34 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -4,10 +4,13 @@ #include #include + +#ifdef SUNSHINE_BUILD_X11 #include #include #include #include +#endif #include #include @@ -128,7 +131,10 @@ using mail_evdev_t = std::tuple init_keycodes() { std::array keycodes {}; -#define __CONVERT(wincode, linuxcode, scancode, keysym) \ +#ifdef SUNSHINE_BUILD_X11 +#define __CONVERT(wincode, linuxcode, scancode, keysym) \ static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ keycodes[wincode] = keycode_t { linuxcode, scancode, keysym }; +#else +#define __CONVERT(wincode, linuxcode, scancode) \ + static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ + static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ + keycodes[wincode] = keycode_t { linuxcode, scancode }; +#endif __CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A, XK_BackSpace); __CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B, XK_Tab); @@ -762,10 +775,13 @@ struct input_raw_t { for(int x = 0; x < gamepads.size(); ++x) { clear_gamepad(x); } + +#ifdef SUNSHINE_BUILD_X11 if (display) { x11::CloseDisplay(display); display = nullptr; } +#endif } ~input_raw_t() { @@ -784,7 +800,9 @@ struct input_raw_t { evdev_t mouse_dev; evdev_t keyboard_dev; +#ifdef SUNSHINE_BUILD_X11 Display *display; +#endif }; inline void rumbleIterate(std::vector &effects, std::vector &polls, std::chrono::milliseconds to) { From 6b664dfad46fce6aee6c3de0d3a108f29e5dc60d Mon Sep 17 00:00:00 2001 From: Doridian Date: Sat, 4 Mar 2023 15:07:58 -0800 Subject: [PATCH 7/9] improve macro --- src/platform/linux/input.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index 680ef495b34..14a319e3880 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -143,17 +143,18 @@ static constexpr std::array init_keycodes() { std::array keycodes {}; #ifdef SUNSHINE_BUILD_X11 -#define __CONVERT(wincode, linuxcode, scancode, keysym) \ - static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ - static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ +#define __CONVERT_UNSAFE(wincode, linuxcode, scancode, keysym) \ keycodes[wincode] = keycode_t { linuxcode, scancode, keysym }; #else -#define __CONVERT(wincode, linuxcode, scancode) \ - static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ - static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ +#define __CONVERT_UNSAFE(wincode, linuxcode, scancode, keysym) \ keycodes[wincode] = keycode_t { linuxcode, scancode }; #endif +#define __CONVERT(wincode, linuxcode, scancode, keysym) \ + static_assert(wincode < keycodes.size(), "Keycode doesn't fit into keycode array"); \ + static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ + __CONVERT_UNSAFE(wincode, linuxcode, scancode, keysym) + __CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A, XK_BackSpace); __CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B, XK_Tab); __CONVERT(0x0C /* VKEY_CLEAR */, KEY_CLEAR, UNKNOWN, XK_Clear); @@ -283,6 +284,7 @@ __CONVERT(0xDD /* VKEY_OEM_6 */, KEY_RIGHTBRACE, 0x70030, XK_braceright); __CONVERT(0xDE /* VKEY_OEM_7 */, KEY_APOSTROPHE, 0x70034, XK_apostrophe); __CONVERT(0xE2 /* VKEY_NON_US_BACKSLASH */, KEY_102ND, 0x70064, XK_backslash); #undef __CONVERT +#undef __CONVERT_UNSAFE return keycodes; } From 3f5ab8790ea2037725d938765483ba0e347eb6e3 Mon Sep 17 00:00:00 2001 From: Doridian Date: Tue, 7 Mar 2023 15:02:10 -0800 Subject: [PATCH 8/9] clang format --- src/platform/linux/input.cpp | 307 ++++++++++++++++++----------------- 1 file changed, 154 insertions(+), 153 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index 14a319e3880..13def2f043c 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -6,8 +6,8 @@ #include #ifdef SUNSHINE_BUILD_X11 -#include #include +#include #include #include #endif @@ -155,134 +155,134 @@ static constexpr std::array init_keycodes() { static_assert(wincode >= 0, "Are you mad?, keycode needs to be greater than zero"); \ __CONVERT_UNSAFE(wincode, linuxcode, scancode, keysym) -__CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A, XK_BackSpace); -__CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B, XK_Tab); -__CONVERT(0x0C /* VKEY_CLEAR */, KEY_CLEAR, UNKNOWN, XK_Clear); -__CONVERT(0x0D /* VKEY_RETURN */, KEY_ENTER, 0x70028, XK_Return); -__CONVERT(0x10 /* VKEY_SHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); -__CONVERT(0x11 /* VKEY_CONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); -__CONVERT(0x12 /* VKEY_MENU */, KEY_LEFTALT, UNKNOWN, XK_Alt_L); -__CONVERT(0x13 /* VKEY_PAUSE */, KEY_PAUSE, UNKNOWN, XK_Pause); -__CONVERT(0x14 /* VKEY_CAPITAL */, KEY_CAPSLOCK, 0x70039, XK_Caps_Lock); -__CONVERT(0x15 /* VKEY_KANA */, KEY_KATAKANAHIRAGANA, UNKNOWN, XK_Kana_Shift); -__CONVERT(0x16 /* VKEY_HANGUL */, KEY_HANGEUL, UNKNOWN, XK_Hangul); -__CONVERT(0x17 /* VKEY_JUNJA */, KEY_HANJA, UNKNOWN, XK_Hangul_Jeonja); -__CONVERT(0x19 /* VKEY_KANJI */, KEY_KATAKANA, UNKNOWN, XK_Kanji); -__CONVERT(0x1B /* VKEY_ESCAPE */, KEY_ESC, 0x70029, XK_Escape); -__CONVERT(0x20 /* VKEY_SPACE */, KEY_SPACE, 0x7002C, XK_space); -__CONVERT(0x21 /* VKEY_PRIOR */, KEY_PAGEUP, 0x7004B, XK_Page_Up); -__CONVERT(0x22 /* VKEY_NEXT */, KEY_PAGEDOWN, 0x7004E, XK_Page_Down); -__CONVERT(0x23 /* VKEY_END */, KEY_END, 0x7004D, XK_End); -__CONVERT(0x24 /* VKEY_HOME */, KEY_HOME, 0x7004A, XK_Home); -__CONVERT(0x25 /* VKEY_LEFT */, KEY_LEFT, 0x70050, XK_Left); -__CONVERT(0x26 /* VKEY_UP */, KEY_UP, 0x70052, XK_Up); -__CONVERT(0x27 /* VKEY_RIGHT */, KEY_RIGHT, 0x7004F, XK_Right); -__CONVERT(0x28 /* VKEY_DOWN */, KEY_DOWN, 0x70051, XK_Down); -__CONVERT(0x29 /* VKEY_SELECT */, KEY_SELECT, UNKNOWN, XK_Select); -__CONVERT(0x2A /* VKEY_PRINT */, KEY_PRINT, UNKNOWN, XK_Print); -__CONVERT(0x2C /* VKEY_SNAPSHOT */, KEY_SYSRQ, 0x70046, XK_Sys_Req); -__CONVERT(0x2D /* VKEY_INSERT */, KEY_INSERT, 0x70049, XK_Insert); -__CONVERT(0x2E /* VKEY_DELETE */, KEY_DELETE, 0x7004C, XK_Delete); -__CONVERT(0x2F /* VKEY_HELP */, KEY_HELP, UNKNOWN, XK_Help); -__CONVERT(0x30 /* VKEY_0 */, KEY_0, 0x70027, XK_0); -__CONVERT(0x31 /* VKEY_1 */, KEY_1, 0x7001E, XK_1); -__CONVERT(0x32 /* VKEY_2 */, KEY_2, 0x7001F, XK_2); -__CONVERT(0x33 /* VKEY_3 */, KEY_3, 0x70020, XK_3); -__CONVERT(0x34 /* VKEY_4 */, KEY_4, 0x70021, XK_4); -__CONVERT(0x35 /* VKEY_5 */, KEY_5, 0x70022, XK_5); -__CONVERT(0x36 /* VKEY_6 */, KEY_6, 0x70023, XK_6); -__CONVERT(0x37 /* VKEY_7 */, KEY_7, 0x70024, XK_7); -__CONVERT(0x38 /* VKEY_8 */, KEY_8, 0x70025, XK_8); -__CONVERT(0x39 /* VKEY_9 */, KEY_9, 0x70026, XK_9); -__CONVERT(0x41 /* VKEY_A */, KEY_A, 0x70004, XK_A); -__CONVERT(0x42 /* VKEY_B */, KEY_B, 0x70005, XK_B); -__CONVERT(0x43 /* VKEY_C */, KEY_C, 0x70006, XK_C); -__CONVERT(0x44 /* VKEY_D */, KEY_D, 0x70007, XK_D); -__CONVERT(0x45 /* VKEY_E */, KEY_E, 0x70008, XK_E); -__CONVERT(0x46 /* VKEY_F */, KEY_F, 0x70009, XK_F); -__CONVERT(0x47 /* VKEY_G */, KEY_G, 0x7000A, XK_G); -__CONVERT(0x48 /* VKEY_H */, KEY_H, 0x7000B, XK_H); -__CONVERT(0x49 /* VKEY_I */, KEY_I, 0x7000C, XK_I); -__CONVERT(0x4A /* VKEY_J */, KEY_J, 0x7000D, XK_J); -__CONVERT(0x4B /* VKEY_K */, KEY_K, 0x7000E, XK_K); -__CONVERT(0x4C /* VKEY_L */, KEY_L, 0x7000F, XK_L); -__CONVERT(0x4D /* VKEY_M */, KEY_M, 0x70010, XK_M); -__CONVERT(0x4E /* VKEY_N */, KEY_N, 0x70011, XK_N); -__CONVERT(0x4F /* VKEY_O */, KEY_O, 0x70012, XK_O); -__CONVERT(0x50 /* VKEY_P */, KEY_P, 0x70013, XK_P); -__CONVERT(0x51 /* VKEY_Q */, KEY_Q, 0x70014, XK_Q); -__CONVERT(0x52 /* VKEY_R */, KEY_R, 0x70015, XK_R); -__CONVERT(0x53 /* VKEY_S */, KEY_S, 0x70016, XK_S); -__CONVERT(0x54 /* VKEY_T */, KEY_T, 0x70017, XK_T); -__CONVERT(0x55 /* VKEY_U */, KEY_U, 0x70018, XK_U); -__CONVERT(0x56 /* VKEY_V */, KEY_V, 0x70019, XK_V); -__CONVERT(0x57 /* VKEY_W */, KEY_W, 0x7001A, XK_W); -__CONVERT(0x58 /* VKEY_X */, KEY_X, 0x7001B, XK_X); -__CONVERT(0x59 /* VKEY_Y */, KEY_Y, 0x7001C, XK_Y); -__CONVERT(0x5A /* VKEY_Z */, KEY_Z, 0x7001D, XK_Z); -__CONVERT(0x5B /* VKEY_LWIN */, KEY_LEFTMETA, 0x700E3, XK_Meta_L); -__CONVERT(0x5C /* VKEY_RWIN */, KEY_RIGHTMETA, 0x700E7, XK_Meta_R); -__CONVERT(0x5F /* VKEY_SLEEP */, KEY_SLEEP, UNKNOWN, UNKNOWN); -__CONVERT(0x60 /* VKEY_NUMPAD0 */, KEY_KP0, 0x70062, XK_KP_0); -__CONVERT(0x61 /* VKEY_NUMPAD1 */, KEY_KP1, 0x70059, XK_KP_1); -__CONVERT(0x62 /* VKEY_NUMPAD2 */, KEY_KP2, 0x7005A, XK_KP_2); -__CONVERT(0x63 /* VKEY_NUMPAD3 */, KEY_KP3, 0x7005B, XK_KP_3); -__CONVERT(0x64 /* VKEY_NUMPAD4 */, KEY_KP4, 0x7005C, XK_KP_4); -__CONVERT(0x65 /* VKEY_NUMPAD5 */, KEY_KP5, 0x7005D, XK_KP_5); -__CONVERT(0x66 /* VKEY_NUMPAD6 */, KEY_KP6, 0x7005E, XK_KP_6); -__CONVERT(0x67 /* VKEY_NUMPAD7 */, KEY_KP7, 0x7005F, XK_KP_7); -__CONVERT(0x68 /* VKEY_NUMPAD8 */, KEY_KP8, 0x70060, XK_KP_8); -__CONVERT(0x69 /* VKEY_NUMPAD9 */, KEY_KP9, 0x70061, XK_KP_9); -__CONVERT(0x6A /* VKEY_MULTIPLY */, KEY_KPASTERISK, 0x70055, XK_KP_Multiply); -__CONVERT(0x6B /* VKEY_ADD */, KEY_KPPLUS, 0x70057, XK_KP_Add); -__CONVERT(0x6C /* VKEY_SEPARATOR */, KEY_KPCOMMA, UNKNOWN, XK_KP_Separator); -__CONVERT(0x6D /* VKEY_SUBTRACT */, KEY_KPMINUS, 0x70056, XK_KP_Subtract); -__CONVERT(0x6E /* VKEY_DECIMAL */, KEY_KPDOT, 0x70063, XK_KP_Decimal); -__CONVERT(0x6F /* VKEY_DIVIDE */, KEY_KPSLASH, 0x70054, XK_KP_Divide); -__CONVERT(0x70 /* VKEY_F1 */, KEY_F1, 0x70046, XK_F1); -__CONVERT(0x71 /* VKEY_F2 */, KEY_F2, 0x70047, XK_F2); -__CONVERT(0x72 /* VKEY_F3 */, KEY_F3, 0x70048, XK_F3); -__CONVERT(0x73 /* VKEY_F4 */, KEY_F4, 0x70049, XK_F4); -__CONVERT(0x74 /* VKEY_F5 */, KEY_F5, 0x7004a, XK_F5); -__CONVERT(0x75 /* VKEY_F6 */, KEY_F6, 0x7004b, XK_F6); -__CONVERT(0x76 /* VKEY_F7 */, KEY_F7, 0x7004c, XK_F7); -__CONVERT(0x77 /* VKEY_F8 */, KEY_F8, 0x7004d, XK_F8); -__CONVERT(0x78 /* VKEY_F9 */, KEY_F9, 0x7004e, XK_F9); -__CONVERT(0x79 /* VKEY_F10 */, KEY_F10, 0x70044, XK_F10); -__CONVERT(0x7A /* VKEY_F11 */, KEY_F11, 0x70044, XK_F11); -__CONVERT(0x7B /* VKEY_F12 */, KEY_F12, 0x70045, XK_F12); -__CONVERT(0x7C /* VKEY_F13 */, KEY_F13, 0x7003a, XK_F13); -__CONVERT(0x7D /* VKEY_F14 */, KEY_F14, 0x7003b, XK_F14); -__CONVERT(0x7E /* VKEY_F15 */, KEY_F15, 0x7003c, XK_F15); -__CONVERT(0x7F /* VKEY_F16 */, KEY_F16, 0x7003d, XK_F16); -__CONVERT(0x80 /* VKEY_F17 */, KEY_F17, 0x7003e, XK_F17); -__CONVERT(0x81 /* VKEY_F18 */, KEY_F18, 0x7003f, XK_F18); -__CONVERT(0x82 /* VKEY_F19 */, KEY_F19, 0x70040, XK_F19); -__CONVERT(0x83 /* VKEY_F20 */, KEY_F20, 0x70041, XK_F20); -__CONVERT(0x84 /* VKEY_F21 */, KEY_F21, 0x70042, XK_F21); -__CONVERT(0x85 /* VKEY_F22 */, KEY_F12, 0x70043, XK_F12); -__CONVERT(0x86 /* VKEY_F23 */, KEY_F23, 0x70044, XK_F23); -__CONVERT(0x87 /* VKEY_F24 */, KEY_F24, 0x70045, XK_F24); -__CONVERT(0x90 /* VKEY_NUMLOCK */, KEY_NUMLOCK, 0x70053, XK_Num_Lock); -__CONVERT(0x91 /* VKEY_SCROLL */, KEY_SCROLLLOCK, 0x70047, XK_Scroll_Lock); -__CONVERT(0xA0 /* VKEY_LSHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); -__CONVERT(0xA1 /* VKEY_RSHIFT */, KEY_RIGHTSHIFT, 0x700E5, XK_Shift_R); -__CONVERT(0xA2 /* VKEY_LCONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); -__CONVERT(0xA3 /* VKEY_RCONTROL */, KEY_RIGHTCTRL, 0x700E4, XK_Control_R); -__CONVERT(0xA4 /* VKEY_LMENU */, KEY_LEFTALT, 0x7002E, XK_Alt_L); -__CONVERT(0xA5 /* VKEY_RMENU */, KEY_RIGHTALT, 0x700E6, XK_Alt_R); -__CONVERT(0xBA /* VKEY_OEM_1 */, KEY_SEMICOLON, 0x70033, XK_semicolon); -__CONVERT(0xBB /* VKEY_OEM_PLUS */, KEY_EQUAL, 0x7002E, XK_equal); -__CONVERT(0xBC /* VKEY_OEM_COMMA */, KEY_COMMA, 0x70036, XK_comma); -__CONVERT(0xBD /* VKEY_OEM_MINUS */, KEY_MINUS, 0x7002D, XK_minus); -__CONVERT(0xBE /* VKEY_OEM_PERIOD */, KEY_DOT, 0x70037, XK_period); -__CONVERT(0xBF /* VKEY_OEM_2 */, KEY_SLASH, 0x70038, XK_slash); -__CONVERT(0xC0 /* VKEY_OEM_3 */, KEY_GRAVE, 0x70035, XK_grave); -__CONVERT(0xDB /* VKEY_OEM_4 */, KEY_LEFTBRACE, 0x7002F, XK_braceleft); -__CONVERT(0xDC /* VKEY_OEM_5 */, KEY_BACKSLASH, 0x70031, XK_backslash); -__CONVERT(0xDD /* VKEY_OEM_6 */, KEY_RIGHTBRACE, 0x70030, XK_braceright); -__CONVERT(0xDE /* VKEY_OEM_7 */, KEY_APOSTROPHE, 0x70034, XK_apostrophe); -__CONVERT(0xE2 /* VKEY_NON_US_BACKSLASH */, KEY_102ND, 0x70064, XK_backslash); + __CONVERT(0x08 /* VKEY_BACK */, KEY_BACKSPACE, 0x7002A, XK_BackSpace); + __CONVERT(0x09 /* VKEY_TAB */, KEY_TAB, 0x7002B, XK_Tab); + __CONVERT(0x0C /* VKEY_CLEAR */, KEY_CLEAR, UNKNOWN, XK_Clear); + __CONVERT(0x0D /* VKEY_RETURN */, KEY_ENTER, 0x70028, XK_Return); + __CONVERT(0x10 /* VKEY_SHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); + __CONVERT(0x11 /* VKEY_CONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); + __CONVERT(0x12 /* VKEY_MENU */, KEY_LEFTALT, UNKNOWN, XK_Alt_L); + __CONVERT(0x13 /* VKEY_PAUSE */, KEY_PAUSE, UNKNOWN, XK_Pause); + __CONVERT(0x14 /* VKEY_CAPITAL */, KEY_CAPSLOCK, 0x70039, XK_Caps_Lock); + __CONVERT(0x15 /* VKEY_KANA */, KEY_KATAKANAHIRAGANA, UNKNOWN, XK_Kana_Shift); + __CONVERT(0x16 /* VKEY_HANGUL */, KEY_HANGEUL, UNKNOWN, XK_Hangul); + __CONVERT(0x17 /* VKEY_JUNJA */, KEY_HANJA, UNKNOWN, XK_Hangul_Jeonja); + __CONVERT(0x19 /* VKEY_KANJI */, KEY_KATAKANA, UNKNOWN, XK_Kanji); + __CONVERT(0x1B /* VKEY_ESCAPE */, KEY_ESC, 0x70029, XK_Escape); + __CONVERT(0x20 /* VKEY_SPACE */, KEY_SPACE, 0x7002C, XK_space); + __CONVERT(0x21 /* VKEY_PRIOR */, KEY_PAGEUP, 0x7004B, XK_Page_Up); + __CONVERT(0x22 /* VKEY_NEXT */, KEY_PAGEDOWN, 0x7004E, XK_Page_Down); + __CONVERT(0x23 /* VKEY_END */, KEY_END, 0x7004D, XK_End); + __CONVERT(0x24 /* VKEY_HOME */, KEY_HOME, 0x7004A, XK_Home); + __CONVERT(0x25 /* VKEY_LEFT */, KEY_LEFT, 0x70050, XK_Left); + __CONVERT(0x26 /* VKEY_UP */, KEY_UP, 0x70052, XK_Up); + __CONVERT(0x27 /* VKEY_RIGHT */, KEY_RIGHT, 0x7004F, XK_Right); + __CONVERT(0x28 /* VKEY_DOWN */, KEY_DOWN, 0x70051, XK_Down); + __CONVERT(0x29 /* VKEY_SELECT */, KEY_SELECT, UNKNOWN, XK_Select); + __CONVERT(0x2A /* VKEY_PRINT */, KEY_PRINT, UNKNOWN, XK_Print); + __CONVERT(0x2C /* VKEY_SNAPSHOT */, KEY_SYSRQ, 0x70046, XK_Sys_Req); + __CONVERT(0x2D /* VKEY_INSERT */, KEY_INSERT, 0x70049, XK_Insert); + __CONVERT(0x2E /* VKEY_DELETE */, KEY_DELETE, 0x7004C, XK_Delete); + __CONVERT(0x2F /* VKEY_HELP */, KEY_HELP, UNKNOWN, XK_Help); + __CONVERT(0x30 /* VKEY_0 */, KEY_0, 0x70027, XK_0); + __CONVERT(0x31 /* VKEY_1 */, KEY_1, 0x7001E, XK_1); + __CONVERT(0x32 /* VKEY_2 */, KEY_2, 0x7001F, XK_2); + __CONVERT(0x33 /* VKEY_3 */, KEY_3, 0x70020, XK_3); + __CONVERT(0x34 /* VKEY_4 */, KEY_4, 0x70021, XK_4); + __CONVERT(0x35 /* VKEY_5 */, KEY_5, 0x70022, XK_5); + __CONVERT(0x36 /* VKEY_6 */, KEY_6, 0x70023, XK_6); + __CONVERT(0x37 /* VKEY_7 */, KEY_7, 0x70024, XK_7); + __CONVERT(0x38 /* VKEY_8 */, KEY_8, 0x70025, XK_8); + __CONVERT(0x39 /* VKEY_9 */, KEY_9, 0x70026, XK_9); + __CONVERT(0x41 /* VKEY_A */, KEY_A, 0x70004, XK_A); + __CONVERT(0x42 /* VKEY_B */, KEY_B, 0x70005, XK_B); + __CONVERT(0x43 /* VKEY_C */, KEY_C, 0x70006, XK_C); + __CONVERT(0x44 /* VKEY_D */, KEY_D, 0x70007, XK_D); + __CONVERT(0x45 /* VKEY_E */, KEY_E, 0x70008, XK_E); + __CONVERT(0x46 /* VKEY_F */, KEY_F, 0x70009, XK_F); + __CONVERT(0x47 /* VKEY_G */, KEY_G, 0x7000A, XK_G); + __CONVERT(0x48 /* VKEY_H */, KEY_H, 0x7000B, XK_H); + __CONVERT(0x49 /* VKEY_I */, KEY_I, 0x7000C, XK_I); + __CONVERT(0x4A /* VKEY_J */, KEY_J, 0x7000D, XK_J); + __CONVERT(0x4B /* VKEY_K */, KEY_K, 0x7000E, XK_K); + __CONVERT(0x4C /* VKEY_L */, KEY_L, 0x7000F, XK_L); + __CONVERT(0x4D /* VKEY_M */, KEY_M, 0x70010, XK_M); + __CONVERT(0x4E /* VKEY_N */, KEY_N, 0x70011, XK_N); + __CONVERT(0x4F /* VKEY_O */, KEY_O, 0x70012, XK_O); + __CONVERT(0x50 /* VKEY_P */, KEY_P, 0x70013, XK_P); + __CONVERT(0x51 /* VKEY_Q */, KEY_Q, 0x70014, XK_Q); + __CONVERT(0x52 /* VKEY_R */, KEY_R, 0x70015, XK_R); + __CONVERT(0x53 /* VKEY_S */, KEY_S, 0x70016, XK_S); + __CONVERT(0x54 /* VKEY_T */, KEY_T, 0x70017, XK_T); + __CONVERT(0x55 /* VKEY_U */, KEY_U, 0x70018, XK_U); + __CONVERT(0x56 /* VKEY_V */, KEY_V, 0x70019, XK_V); + __CONVERT(0x57 /* VKEY_W */, KEY_W, 0x7001A, XK_W); + __CONVERT(0x58 /* VKEY_X */, KEY_X, 0x7001B, XK_X); + __CONVERT(0x59 /* VKEY_Y */, KEY_Y, 0x7001C, XK_Y); + __CONVERT(0x5A /* VKEY_Z */, KEY_Z, 0x7001D, XK_Z); + __CONVERT(0x5B /* VKEY_LWIN */, KEY_LEFTMETA, 0x700E3, XK_Meta_L); + __CONVERT(0x5C /* VKEY_RWIN */, KEY_RIGHTMETA, 0x700E7, XK_Meta_R); + __CONVERT(0x5F /* VKEY_SLEEP */, KEY_SLEEP, UNKNOWN, UNKNOWN); + __CONVERT(0x60 /* VKEY_NUMPAD0 */, KEY_KP0, 0x70062, XK_KP_0); + __CONVERT(0x61 /* VKEY_NUMPAD1 */, KEY_KP1, 0x70059, XK_KP_1); + __CONVERT(0x62 /* VKEY_NUMPAD2 */, KEY_KP2, 0x7005A, XK_KP_2); + __CONVERT(0x63 /* VKEY_NUMPAD3 */, KEY_KP3, 0x7005B, XK_KP_3); + __CONVERT(0x64 /* VKEY_NUMPAD4 */, KEY_KP4, 0x7005C, XK_KP_4); + __CONVERT(0x65 /* VKEY_NUMPAD5 */, KEY_KP5, 0x7005D, XK_KP_5); + __CONVERT(0x66 /* VKEY_NUMPAD6 */, KEY_KP6, 0x7005E, XK_KP_6); + __CONVERT(0x67 /* VKEY_NUMPAD7 */, KEY_KP7, 0x7005F, XK_KP_7); + __CONVERT(0x68 /* VKEY_NUMPAD8 */, KEY_KP8, 0x70060, XK_KP_8); + __CONVERT(0x69 /* VKEY_NUMPAD9 */, KEY_KP9, 0x70061, XK_KP_9); + __CONVERT(0x6A /* VKEY_MULTIPLY */, KEY_KPASTERISK, 0x70055, XK_KP_Multiply); + __CONVERT(0x6B /* VKEY_ADD */, KEY_KPPLUS, 0x70057, XK_KP_Add); + __CONVERT(0x6C /* VKEY_SEPARATOR */, KEY_KPCOMMA, UNKNOWN, XK_KP_Separator); + __CONVERT(0x6D /* VKEY_SUBTRACT */, KEY_KPMINUS, 0x70056, XK_KP_Subtract); + __CONVERT(0x6E /* VKEY_DECIMAL */, KEY_KPDOT, 0x70063, XK_KP_Decimal); + __CONVERT(0x6F /* VKEY_DIVIDE */, KEY_KPSLASH, 0x70054, XK_KP_Divide); + __CONVERT(0x70 /* VKEY_F1 */, KEY_F1, 0x70046, XK_F1); + __CONVERT(0x71 /* VKEY_F2 */, KEY_F2, 0x70047, XK_F2); + __CONVERT(0x72 /* VKEY_F3 */, KEY_F3, 0x70048, XK_F3); + __CONVERT(0x73 /* VKEY_F4 */, KEY_F4, 0x70049, XK_F4); + __CONVERT(0x74 /* VKEY_F5 */, KEY_F5, 0x7004a, XK_F5); + __CONVERT(0x75 /* VKEY_F6 */, KEY_F6, 0x7004b, XK_F6); + __CONVERT(0x76 /* VKEY_F7 */, KEY_F7, 0x7004c, XK_F7); + __CONVERT(0x77 /* VKEY_F8 */, KEY_F8, 0x7004d, XK_F8); + __CONVERT(0x78 /* VKEY_F9 */, KEY_F9, 0x7004e, XK_F9); + __CONVERT(0x79 /* VKEY_F10 */, KEY_F10, 0x70044, XK_F10); + __CONVERT(0x7A /* VKEY_F11 */, KEY_F11, 0x70044, XK_F11); + __CONVERT(0x7B /* VKEY_F12 */, KEY_F12, 0x70045, XK_F12); + __CONVERT(0x7C /* VKEY_F13 */, KEY_F13, 0x7003a, XK_F13); + __CONVERT(0x7D /* VKEY_F14 */, KEY_F14, 0x7003b, XK_F14); + __CONVERT(0x7E /* VKEY_F15 */, KEY_F15, 0x7003c, XK_F15); + __CONVERT(0x7F /* VKEY_F16 */, KEY_F16, 0x7003d, XK_F16); + __CONVERT(0x80 /* VKEY_F17 */, KEY_F17, 0x7003e, XK_F17); + __CONVERT(0x81 /* VKEY_F18 */, KEY_F18, 0x7003f, XK_F18); + __CONVERT(0x82 /* VKEY_F19 */, KEY_F19, 0x70040, XK_F19); + __CONVERT(0x83 /* VKEY_F20 */, KEY_F20, 0x70041, XK_F20); + __CONVERT(0x84 /* VKEY_F21 */, KEY_F21, 0x70042, XK_F21); + __CONVERT(0x85 /* VKEY_F22 */, KEY_F12, 0x70043, XK_F12); + __CONVERT(0x86 /* VKEY_F23 */, KEY_F23, 0x70044, XK_F23); + __CONVERT(0x87 /* VKEY_F24 */, KEY_F24, 0x70045, XK_F24); + __CONVERT(0x90 /* VKEY_NUMLOCK */, KEY_NUMLOCK, 0x70053, XK_Num_Lock); + __CONVERT(0x91 /* VKEY_SCROLL */, KEY_SCROLLLOCK, 0x70047, XK_Scroll_Lock); + __CONVERT(0xA0 /* VKEY_LSHIFT */, KEY_LEFTSHIFT, 0x700E1, XK_Shift_L); + __CONVERT(0xA1 /* VKEY_RSHIFT */, KEY_RIGHTSHIFT, 0x700E5, XK_Shift_R); + __CONVERT(0xA2 /* VKEY_LCONTROL */, KEY_LEFTCTRL, 0x700E0, XK_Control_L); + __CONVERT(0xA3 /* VKEY_RCONTROL */, KEY_RIGHTCTRL, 0x700E4, XK_Control_R); + __CONVERT(0xA4 /* VKEY_LMENU */, KEY_LEFTALT, 0x7002E, XK_Alt_L); + __CONVERT(0xA5 /* VKEY_RMENU */, KEY_RIGHTALT, 0x700E6, XK_Alt_R); + __CONVERT(0xBA /* VKEY_OEM_1 */, KEY_SEMICOLON, 0x70033, XK_semicolon); + __CONVERT(0xBB /* VKEY_OEM_PLUS */, KEY_EQUAL, 0x7002E, XK_equal); + __CONVERT(0xBC /* VKEY_OEM_COMMA */, KEY_COMMA, 0x70036, XK_comma); + __CONVERT(0xBD /* VKEY_OEM_MINUS */, KEY_MINUS, 0x7002D, XK_minus); + __CONVERT(0xBE /* VKEY_OEM_PERIOD */, KEY_DOT, 0x70037, XK_period); + __CONVERT(0xBF /* VKEY_OEM_2 */, KEY_SLASH, 0x70038, XK_slash); + __CONVERT(0xC0 /* VKEY_OEM_3 */, KEY_GRAVE, 0x70035, XK_grave); + __CONVERT(0xDB /* VKEY_OEM_4 */, KEY_LEFTBRACE, 0x7002F, XK_braceleft); + __CONVERT(0xDC /* VKEY_OEM_5 */, KEY_BACKSLASH, 0x70031, XK_backslash); + __CONVERT(0xDD /* VKEY_OEM_6 */, KEY_RIGHTBRACE, 0x70030, XK_braceright); + __CONVERT(0xDE /* VKEY_OEM_7 */, KEY_APOSTROPHE, 0x70034, XK_apostrophe); + __CONVERT(0xE2 /* VKEY_NON_US_BACKSLASH */, KEY_102ND, 0x70064, XK_backslash); #undef __CONVERT #undef __CONVERT_UNSAFE @@ -779,7 +779,7 @@ struct input_raw_t { } #ifdef SUNSHINE_BUILD_X11 - if (display) { + if(display) { x11::CloseDisplay(display); display = nullptr; } @@ -1015,7 +1015,7 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { + if(!xdisplay) { return; } x11::tst::FakeMotionEvent(xdisplay, -1, x, y, CurrentTime); @@ -1044,7 +1044,7 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) static void x_move_mouse(input_t &input, int deltaX, int deltaY) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { + if(!xdisplay) { return; } x11::tst::FakeRelativeMotionEvent(xdisplay, deltaX, deltaY, CurrentTime); @@ -1073,27 +1073,27 @@ void move_mouse(input_t &input, int deltaX, int deltaY) { static void x_button_mouse(input_t &input, int button, bool release) { #ifdef SUNSHINE_BUILD_X11 unsigned int x_button = 0; - switch (button) { - case BUTTON_LEFT: - x_button = 1; - break; - case BUTTON_MIDDLE: - x_button = 2; - break; - case BUTTON_RIGHT: - x_button = 3; - break; - default: - x_button = (button - 4) + 8; // Button 4 (Moonlight) starts at index 8 (X11) - break; + switch(button) { + case BUTTON_LEFT: + x_button = 1; + break; + case BUTTON_MIDDLE: + x_button = 2; + break; + case BUTTON_RIGHT: + x_button = 3; + break; + default: + x_button = (button - 4) + 8; // Button 4 (Moonlight) starts at index 8 (X11) + break; } - if (x_button < 1 || x_button > 31) { + if(x_button < 1 || x_button > 31) { return; } Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { + if(!xdisplay) { return; } x11::tst::FakeButtonEvent(xdisplay, x_button, !release, CurrentTime); @@ -1140,12 +1140,12 @@ void button_mouse(input_t &input, int button, bool release) { static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { + if(!xdisplay) { return; } const int button = distance > 0 ? button_pos : button_neg; - for (int i = 0; i < abs(distance); i++) { + for(int i = 0; i < abs(distance); i++) { x11::tst::FakeButtonEvent(xdisplay, button, true, CurrentTime); x11::tst::FakeButtonEvent(xdisplay, button, false, CurrentTime); } @@ -1197,12 +1197,12 @@ static void x_keyboard(input_t &input, uint16_t modcode, bool release) { } Display *xdisplay = ((input_raw_t *)input.get())->display; - if (!xdisplay) { + if(!xdisplay) { return; } const auto keycode_x = XKeysymToKeycode(xdisplay, keycode.keysym); - if (keycode_x == 0) { + if(keycode_x == 0) { return; } @@ -1501,9 +1501,10 @@ input_t input() { BOOST_LOG(error) << "Unable to create some input devices! Are you a member of the 'input' group?"sv; #ifdef SUNSHINE_BUILD_X11 - if (x11::init() || x11::tst::init()) { + if(x11::init() || x11::tst::init()) { BOOST_LOG(error) << "Unable to initialize X11 and/or XTest fallback"sv; - } else { + } + else { BOOST_LOG(info) << "Falling back to XTest"sv; x11::InitThreads(); gp.display = x11::OpenDisplay(NULL); From f77cc6e1f1e18e152a7520dfaf6b7c6eddf8230b Mon Sep 17 00:00:00 2001 From: Doridian Date: Wed, 8 Mar 2023 00:45:18 -0800 Subject: [PATCH 9/9] doctag a lot of functions in input --- src/platform/linux/input.cpp | 170 ++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 3 deletions(-) diff --git a/src/platform/linux/input.cpp b/src/platform/linux/input.cpp index 13def2f043c..fbcb4710437 100644 --- a/src/platform/linux/input.cpp +++ b/src/platform/linux/input.cpp @@ -139,6 +139,10 @@ struct keycode_t { constexpr auto UNKNOWN = 0; +/** + * @brief Initializes the keycode constants for translating + * moonlight keycodes to linux/X11 keycodes + */ static constexpr std::array init_keycodes() { std::array keycodes {}; @@ -1011,8 +1015,18 @@ void broadcastRumble(safe::queue_t &rumble_queue_queue) { } } - -static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { +/** + * @brief XTest absolute mouse move. + * @param input The input_t instance to use. + * @param x Absolute x position. + * @param y Absolute y position. + * + * EXAMPLES: + * ```cpp + * x_abs_mouse(input, 0, 0); + * ``` + */ +static void x_abs_mouse(input_t &input, float x, float y) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; if(!xdisplay) { @@ -1023,10 +1037,22 @@ static void x_abs_mouse(input_t &input, const touch_port_t &touch_port, float x, #endif } +/** + * @brief Absolute mouse move. + * @param input The input_t instance to use. + * @param touch_port The touch_port instance to use. + * @param x Absolute x position. + * @param y Absolute y position. + * + * EXAMPLES: + * ```cpp + * abs_mouse(input, touch_port, 0, 0); + * ``` + */ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { auto touchscreen = ((input_raw_t *)input.get())->touch_input.get(); if(!touchscreen) { - x_abs_mouse(input, touch_port, x, y); + x_abs_mouse(input, x, y); return; } @@ -1041,6 +1067,17 @@ void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) libevdev_uinput_write_event(touchscreen, EV_SYN, SYN_REPORT, 0); } +/** + * @brief XTest relative mouse move. + * @param input The input_t instance to use. + * @param deltaX Relative x position. + * @param deltaY Relative y position. + * + * EXAMPLES: + * ```cpp + * x_move_mouse(input, 10, 10); // Move mouse 10 pixels down and right + * ``` + */ static void x_move_mouse(input_t &input, int deltaX, int deltaY) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; @@ -1052,6 +1089,17 @@ static void x_move_mouse(input_t &input, int deltaX, int deltaY) { #endif } +/** + * @brief Relative mouse move. + * @param input The input_t instance to use. + * @param deltaX Relative x position. + * @param deltaY Relative y position. + * + * EXAMPLES: + * ```cpp + * move_mouse(input, 10, 10); // Move mouse 10 pixels down and right + * ``` + */ void move_mouse(input_t &input, int deltaX, int deltaY) { auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { @@ -1070,6 +1118,17 @@ void move_mouse(input_t &input, int deltaX, int deltaY) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +/** + * @brief XTest mouse button press/release. + * @param input The input_t instance to use. + * @param button Which mouse button to emulate. + * @param release Whether the event was a press (false) or a release (true) + * + * EXAMPLES: + * ```cpp + * x_button_mouse(input, 1, false); // Press left mouse button + * ``` + */ static void x_button_mouse(input_t &input, int button, bool release) { #ifdef SUNSHINE_BUILD_X11 unsigned int x_button = 0; @@ -1101,6 +1160,17 @@ static void x_button_mouse(input_t &input, int button, bool release) { #endif } +/** + * @brief Mouse button press/release. + * @param input The input_t instance to use. + * @param button Which mouse button to emulate. + * @param release Whether the event was a press (false) or a release (true) + * + * EXAMPLES: + * ```cpp + * button_mouse(input, 1, false); // Press left mouse button + * ``` + */ void button_mouse(input_t &input, int button, bool release) { auto mouse = ((input_raw_t *)input.get())->mouse_input.get(); if(!mouse) { @@ -1137,6 +1207,18 @@ void button_mouse(input_t &input, int button, bool release) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +/** + * @brief XTest mouse scroll. + * @param input The input_t instance to use. + * @param distance How far to scroll + * @param button_pos Which mouse button to emulate for positive scroll. + * @param button_neg Which mouse button to emulate for negative scroll. + * + * EXAMPLES: + * ```cpp + * x_scroll(input, 10, 4, 5); + * ``` + */ static void x_scroll(input_t &input, int distance, int button_pos, int button_neg) { #ifdef SUNSHINE_BUILD_X11 Display *xdisplay = ((input_raw_t *)input.get())->display; @@ -1153,6 +1235,16 @@ static void x_scroll(input_t &input, int distance, int button_pos, int button_ne #endif } +/** + * @brief Vertical mouse scroll. + * @param input The input_t instance to use. + * @param high_res_distance How far to scroll + * + * EXAMPLES: + * ```cpp + * scroll(input, 1200); + * ``` + */ void scroll(input_t &input, int high_res_distance) { int distance = high_res_distance / 120; @@ -1167,6 +1259,16 @@ void scroll(input_t &input, int high_res_distance) { libevdev_uinput_write_event(mouse, EV_SYN, SYN_REPORT, 0); } +/** + * @brief Horizontal mouse scroll. + * @param input The input_t instance to use. + * @param high_res_distance How far to scroll + * + * EXAMPLES: + * ```cpp + * hscroll(input, 1200); + * ``` + */ void hscroll(input_t &input, int high_res_distance) { int distance = high_res_distance / 120; @@ -1189,6 +1291,17 @@ static keycode_t keysym(std::uint16_t modcode) { return {}; } +/** + * @brief XTest keyboard emulation. + * @param input The input_t instance to use. + * @param modcode The moonlight key code. + * @param release Whether the event was a press (false) or a release (true) + * + * EXAMPLES: + * ```cpp + * x_keyboard(input, 0x5A, false); // Press Z + * ``` + */ static void x_keyboard(input_t &input, uint16_t modcode, bool release) { #ifdef SUNSHINE_BUILD_X11 auto keycode = keysym(modcode); @@ -1211,6 +1324,17 @@ static void x_keyboard(input_t &input, uint16_t modcode, bool release) { #endif } +/** + * @brief Keyboard emulation. + * @param input The input_t instance to use. + * @param modcode The moonlight key code. + * @param release Whether the event was a press (false) or a release (true) + * + * EXAMPLES: + * ```cpp + * keyboard(input, 0x5A, false); // Press Z + * ``` + */ void keyboard(input_t &input, uint16_t modcode, bool release) { auto keyboard = ((input_raw_t *)input.get())->keyboard_input.get(); if(!keyboard) { @@ -1305,6 +1429,14 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) { libevdev_uinput_write_event(uinput.get(), EV_SYN, SYN_REPORT, 0); } +/** + * @brief Initalize a new keyboard and return it. + * + * EXAMPLES: + * ```cpp + * auto my_keyboard = keyboard(); + * ``` + */ evdev_t keyboard() { evdev_t dev { libevdev_new() }; @@ -1325,6 +1457,14 @@ evdev_t keyboard() { return dev; } +/** + * @brief Initalize a new uinput virtual mouse and return it. + * + * EXAMPLES: + * ```cpp + * auto my_mouse = mouse(); + * ``` + */ evdev_t mouse() { evdev_t dev { libevdev_new() }; @@ -1367,6 +1507,14 @@ evdev_t mouse() { return dev; } +/** + * @brief Initalize a new uinput virtual touchscreen and return it. + * + * EXAMPLES: + * ```cpp + * auto my_touchscreen = touchscreen(); + * ``` + */ evdev_t touchscreen() { evdev_t dev { libevdev_new() }; @@ -1409,6 +1557,14 @@ evdev_t touchscreen() { return dev; } +/** + * @brief Initalize a new uinput virtual X360 gamepad and return it. + * + * EXAMPLES: + * ```cpp + * auto my_x360 = x360(); + * ``` + */ evdev_t x360() { evdev_t dev { libevdev_new() }; @@ -1477,6 +1633,14 @@ evdev_t x360() { return dev; } +/** + * @brief Initalize the input system and return it. + * + * EXAMPLES: + * ```cpp + * auto my_input = input(); + * ``` + */ input_t input() { input_t result { new input_raw_t() }; auto &gp = *(input_raw_t *)result.get();