From c29e93f4b29137885ac86a69e2ef15e3dd7ea087 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Mon, 16 Dec 2024 18:13:27 +0100 Subject: [PATCH] [locale,keyboard] deprecate keyboard mapping * deprecate keyboard mapping functions: * not context sensitive bug app global * only work reliable with XKB files * expose functions to parse and remap RDP scancodes --- client/Wayland/wlf_input.c | 11 +- client/Wayland/wlfreerdp.c | 12 +- client/Wayland/wlfreerdp.h | 2 + include/freerdp/locale/keyboard.h | 480 ++++++++++++++++++------------ libfreerdp/locale/keyboard.c | 64 ++++ 5 files changed, 374 insertions(+), 195 deletions(-) diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index bfe490366..3f3c71d81 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -324,19 +324,20 @@ BOOL wlf_handle_pointer_source(freerdp* instance, const UwacPointerSourceEvent* BOOL wlf_handle_key(freerdp* instance, const UwacKeyEvent* ev) { - rdpInput* input = NULL; - DWORD rdp_scancode = 0; - if (!instance || !ev) return FALSE; WINPR_ASSERT(instance->context); + wlfContext* ctx = (wlfContext*)instance->context; if (freerdp_settings_get_bool(instance->context->settings, FreeRDP_GrabKeyboard) && ev->raw_key == KEY_RIGHTCTRL) wlf_handle_ungrab_key(instance, ev); - input = instance->context->input; - rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(ev->raw_key + 8); + rdpInput* input = instance->context->input; + + const DWORD vc = GetVirtualKeyCodeFromKeycode(ev->raw_key, WINPR_KEYCODE_TYPE_EVDEV); + const DWORD sc = GetVirtualScanCodeFromVirtualKeyCode(vc, WINPR_KBD_TYPE_IBM_ENHANCED); + const DWORD rdp_scancode = freerdp_keyboard_remap_key(ctx->remap_table, sc); if (rdp_scancode == RDP_SCANCODE_UNKNOWN) return TRUE; diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 428bd4fa8..fca06e365 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -284,12 +284,12 @@ static BOOL wl_post_connect(freerdp* instance) UwacWindowSetOpaqueRegion(context->window, 0, 0, w, h); instance->context->update->EndPaint = wl_end_paint; instance->context->update->DesktopResize = wl_resize_display; - UINT32 KeyboardLayout = - freerdp_settings_get_uint32(instance->context->settings, FreeRDP_KeyboardLayout); const char* KeyboardRemappingList = freerdp_settings_get_string(instance->context->settings, FreeRDP_KeyboardRemappingList); - freerdp_keyboard_init_ex(KeyboardLayout, KeyboardRemappingList); + context->remap_table = freerdp_keyboard_remap_string_to_list(KeyboardRemappingList); + if (!context->remap_table) + return FALSE; if (!(context->disp = wlf_disp_new(context))) return FALSE; @@ -304,21 +304,21 @@ static BOOL wl_post_connect(freerdp* instance) static void wl_post_disconnect(freerdp* instance) { - wlfContext* context = NULL; - if (!instance) return; if (!instance->context) return; - context = (wlfContext*)instance->context; + wlfContext* context = (wlfContext*)instance->context; gdi_free(instance); wlf_clipboard_free(context->clipboard); wlf_disp_free(context->disp); if (context->window) UwacDestroyWindow(&context->window); + freerdp_keyboard_remap_free(context->remap_table); + context->remap_table = NULL; } static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display) diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index e1a465076..b47243418 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,7 @@ typedef struct wLog* log; CRITICAL_SECTION critical; wArrayList* events; + FREERDP_REMAP_TABLE* remap_table; } wlfContext; BOOL wlf_scale_coordinates(rdpContext* context, UINT32* px, UINT32* py, BOOL fromLocalToRDP); diff --git a/include/freerdp/locale/keyboard.h b/include/freerdp/locale/keyboard.h index ee614522e..bb548af73 100644 --- a/include/freerdp/locale/keyboard.h +++ b/include/freerdp/locale/keyboard.h @@ -31,21 +31,26 @@ extern "C" { #endif -#define RDP_KEYBOARD_LAYOUT_TYPE_STANDARD 1 -#define RDP_KEYBOARD_LAYOUT_TYPE_VARIANT 2 -#define RDP_KEYBOARD_LAYOUT_TYPE_IME 4 + typedef struct rdp_remap_table FREERDP_REMAP_TABLE; -typedef struct -{ - UINT16 id; - UINT8 primaryId; - UINT8 subId; - char locale[512]; - char primaryLanguage[512]; - char primaryLanguageSymbol[512]; - char subLanguage[512]; - char subLanguageSymbol[512]; -} RDP_CODEPAGE; + typedef enum + { + RDP_KEYBOARD_LAYOUT_TYPE_STANDARD = 1, + RDP_KEYBOARD_LAYOUT_TYPE_VARIANT = 2, + RDP_KEYBOARD_LAYOUT_TYPE_IME = 4 + } FREERDP_KEYBOARD_LAYOUT_TYPES; + + typedef struct + { + UINT16 id; + UINT8 primaryId; + UINT8 subId; + char locale[512]; + char primaryLanguage[512]; + char primaryLanguageSymbol[512]; + char subLanguage[512]; + char subLanguageSymbol[512]; + } RDP_CODEPAGE; typedef struct { @@ -54,184 +59,291 @@ typedef struct } RDP_KEYBOARD_LAYOUT; /* Keyboard layout IDs */ - -#define KBD_ARABIC_101 0x00000401 -#define KBD_BULGARIAN 0x00000402 -#define KBD_CHINESE_TRADITIONAL_US 0x00000404 -#define KBD_CZECH 0x00000405 -#define KBD_DANISH 0x00000406 -#define KBD_GERMAN 0x00000407 -#define KBD_GREEK 0x00000408 -#define KBD_US 0x00000409 -#define KBD_SPANISH 0x0000040A -#define KBD_FINNISH 0x0000040B -#define KBD_FRENCH 0x0000040C -#define KBD_HEBREW 0x0000040D -#define KBD_HUNGARIAN 0x0000040E -#define KBD_ICELANDIC 0x0000040F -#define KBD_ITALIAN 0x00000410 -#define KBD_JAPANESE 0x00000411 -#define KBD_KOREAN 0x00000412 -#define KBD_DUTCH 0x00000413 -#define KBD_NORWEGIAN 0x00000414 -#define KBD_POLISH_PROGRAMMERS 0x00000415 -#define KBD_PORTUGUESE_BRAZILIAN_ABNT 0x00000416 -#define KBD_ROMANIAN 0x00000418 -#define KBD_RUSSIAN 0x00000419 -#define KBD_CROATIAN 0x0000041A -#define KBD_SLOVAK 0x0000041B -#define KBD_ALBANIAN 0x0000041C -#define KBD_SWEDISH 0x0000041D -#define KBD_THAI_KEDMANEE 0x0000041E -#define KBD_TURKISH_Q 0x0000041F -#define KBD_URDU 0x00000420 -#define KBD_UKRAINIAN 0x00000422 -#define KBD_BELARUSIAN 0x00000423 -#define KBD_SLOVENIAN 0x00000424 -#define KBD_ESTONIAN 0x00000425 -#define KBD_LATVIAN 0x00000426 -#define KBD_LITHUANIAN_IBM 0x00000427 -#define KBD_FARSI 0x00000429 -#define KBD_VIETNAMESE 0x0000042A -#define KBD_ARMENIAN_EASTERN 0x0000042B -#define KBD_AZERI_LATIN 0x0000042C -#define KBD_FYRO_MACEDONIAN 0x0000042F -#define KBD_GEORGIAN 0x00000437 -#define KBD_FAEROESE 0x00000438 -#define KBD_DEVANAGARI_INSCRIPT 0x00000439 -#define KBD_MALTESE_47_KEY 0x0000043A -#define KBD_NORWEGIAN_WITH_SAMI 0x0000043B -#define KBD_KAZAKH 0x0000043F -#define KBD_KYRGYZ_CYRILLIC 0x00000440 -#define KBD_TATAR 0x00000444 -#define KBD_BENGALI 0x00000445 -#define KBD_PUNJABI 0x00000446 -#define KBD_GUJARATI 0x00000447 -#define KBD_TAMIL 0x00000449 -#define KBD_TELUGU 0x0000044A -#define KBD_KANNADA 0x0000044B -#define KBD_MALAYALAM 0x0000044C -#define KBD_MARATHI 0x0000044E -#define KBD_MONGOLIAN_CYRILLIC 0x00000450 -#define KBD_UNITED_KINGDOM_EXTENDED 0x00000452 -#define KBD_SYRIAC 0x0000045A -#define KBD_NEPALI 0x00000461 -#define KBD_PASHTO 0x00000463 -#define KBD_DIVEHI_PHONETIC 0x00000465 -#define KBD_LUXEMBOURGISH 0x0000046E -#define KBD_MAORI 0x00000481 -#define KBD_CHINESE_SIMPLIFIED_US 0x00000804 -#define KBD_SWISS_GERMAN 0x00000807 -#define KBD_UNITED_KINGDOM 0x00000809 -#define KBD_LATIN_AMERICAN 0x0000080A -#define KBD_BELGIAN_FRENCH 0x0000080C -#define KBD_BELGIAN_PERIOD 0x00000813 -#define KBD_PORTUGUESE 0x00000816 -#define KBD_SERBIAN_LATIN 0x0000081A -#define KBD_AZERI_CYRILLIC 0x0000082C -#define KBD_SWEDISH_WITH_SAMI 0x0000083B -#define KBD_UZBEK_CYRILLIC 0x00000843 -#define KBD_INUKTITUT_LATIN 0x0000085D -#define KBD_CANADIAN_FRENCH_LEGACY 0x00000C0C -#define KBD_SERBIAN_CYRILLIC 0x00000C1A -#define KBD_CANADIAN_FRENCH 0x00001009 -#define KBD_SWISS_FRENCH 0x0000100C -#define KBD_BOSNIAN 0x0000141A -#define KBD_IRISH 0x00001809 -#define KBD_BOSNIAN_CYRILLIC 0x0000201A +typedef enum +{ + KBD_ARABIC_101 = 0x00000401, + KBD_BULGARIAN = 0x00000402, + KBD_CHINESE_TRADITIONAL_US = 0x00000404, + KBD_CZECH = 0x00000405, + KBD_DANISH = 0x00000406, + KBD_GERMAN = 0x00000407, + KBD_GREEK = 0x00000408, + KBD_US = 0x00000409, + KBD_SPANISH = 0x0000040A, + KBD_FINNISH = 0x0000040B, + KBD_FRENCH = 0x0000040C, + KBD_HEBREW = 0x0000040D, + KBD_HUNGARIAN = 0x0000040E, + KBD_ICELANDIC = 0x0000040F, + KBD_ITALIAN = 0x00000410, + KBD_JAPANESE = 0x00000411, + KBD_KOREAN = 0x00000412, + KBD_DUTCH = 0x00000413, + KBD_NORWEGIAN = 0x00000414, + KBD_POLISH_PROGRAMMERS = 0x00000415, + KBD_PORTUGUESE_BRAZILIAN_ABNT = 0x00000416, + KBD_ROMANIAN = 0x00000418, + KBD_RUSSIAN = 0x00000419, + KBD_CROATIAN = 0x0000041A, + KBD_SLOVAK = 0x0000041B, + KBD_ALBANIAN = 0x0000041C, + KBD_SWEDISH = 0x0000041D, + KBD_THAI_KEDMANEE = 0x0000041E, + KBD_TURKISH_Q = 0x0000041F, + KBD_URDU = 0x00000420, + KBD_UKRAINIAN = 0x00000422, + KBD_BELARUSIAN = 0x00000423, + KBD_SLOVENIAN = 0x00000424, + KBD_ESTONIAN = 0x00000425, + KBD_LATVIAN = 0x00000426, + KBD_LITHUANIAN_IBM = 0x00000427, + KBD_FARSI = 0x00000429, + KBD_VIETNAMESE = 0x0000042A, + KBD_ARMENIAN_EASTERN = 0x0000042B, + KBD_AZERI_LATIN = 0x0000042C, + KBD_FYRO_MACEDONIAN = 0x0000042F, + KBD_GEORGIAN = 0x00000437, + KBD_FAEROESE = 0x00000438, + KBD_DEVANAGARI_INSCRIPT = 0x00000439, + KBD_MALTESE_47_KEY = 0x0000043A, + KBD_NORWEGIAN_WITH_SAMI = 0x0000043B, + KBD_KAZAKH = 0x0000043F, + KBD_KYRGYZ_CYRILLIC = 0x00000440, + KBD_TATAR = 0x00000444, + KBD_BENGALI = 0x00000445, + KBD_PUNJABI = 0x00000446, + KBD_GUJARATI = 0x00000447, + KBD_TAMIL = 0x00000449, + KBD_TELUGU = 0x0000044A, + KBD_KANNADA = 0x0000044B, + KBD_MALAYALAM = 0x0000044C, + KBD_MARATHI = 0x0000044E, + KBD_MONGOLIAN_CYRILLIC = 0x00000450, + KBD_UNITED_KINGDOM_EXTENDED = 0x00000452, + KBD_SYRIAC = 0x0000045A, + KBD_NEPALI = 0x00000461, + KBD_PASHTO = 0x00000463, + KBD_DIVEHI_PHONETIC = 0x00000465, + KBD_LUXEMBOURGISH = 0x0000046E, + KBD_MAORI = 0x00000481, + KBD_CHINESE_SIMPLIFIED_US = 0x00000804, + KBD_SWISS_GERMAN = 0x00000807, + KBD_UNITED_KINGDOM = 0x00000809, + KBD_LATIN_AMERICAN = 0x0000080A, + KBD_BELGIAN_FRENCH = 0x0000080C, + KBD_BELGIAN_PERIOD = 0x00000813, + KBD_PORTUGUESE = 0x00000816, + KBD_SERBIAN_LATIN = 0x0000081A, + KBD_AZERI_CYRILLIC = 0x0000082C, + KBD_SWEDISH_WITH_SAMI = 0x0000083B, + KBD_UZBEK_CYRILLIC = 0x00000843, + KBD_INUKTITUT_LATIN = 0x0000085D, + KBD_CANADIAN_FRENCH_LEGACY = 0x00000C0C, + KBD_SERBIAN_CYRILLIC = 0x00000C1A, + KBD_CANADIAN_FRENCH = 0x00001009, + KBD_SWISS_FRENCH = 0x0000100C, + KBD_BOSNIAN = 0x0000141A, + KBD_IRISH = 0x00001809, + KBD_BOSNIAN_CYRILLIC = 0x0000201A +} FREERDP_KBD_LAYOUT_ID; /* Keyboard layout variant IDs */ - -#define KBD_ARABIC_102 0x00010401 -#define KBD_BULGARIAN_LATIN 0x00010402 -#define KBD_CZECH_QWERTY 0x00010405 -#define KBD_GERMAN_IBM 0x00010407 -#define KBD_GREEK_220 0x00010408 -#define KBD_UNITED_STATES_DVORAK 0x00010409 -#define KBD_SPANISH_VARIATION 0x0001040A -#define KBD_HUNGARIAN_101_KEY 0x0001040E -#define KBD_ITALIAN_142 0x00010410 -#define KBD_POLISH_214 0x00010415 -#define KBD_PORTUGUESE_BRAZILIAN_ABNT2 0x00010416 -#define KBD_ROMANIAN_STANDARD 0x00010418 -#define KBD_RUSSIAN_TYPEWRITER 0x00010419 -#define KBD_SLOVAK_QWERTY 0x0001041B -#define KBD_THAI_PATTACHOTE 0x0001041E -#define KBD_TURKISH_F 0x0001041F -#define KBD_LATVIAN_QWERTY 0x00010426 -#define KBD_LITHUANIAN 0x00010427 -#define KBD_ARMENIAN_WESTERN 0x0001042B -#define KBD_GEORGIAN_QUERTY 0x00010437 -#define KBD_HINDI_TRADITIONAL 0x00010439 -#define KBD_MALTESE_48_KEY 0x0001043A -#define KBD_SAMI_EXTENDED_NORWAY 0x0001043B -#define KBD_BENGALI_INSCRIPT 0x00010445 -#define KBD_KHMER 0x00010453 -#define KBD_SYRIAC_PHONETIC 0x0001045A -#define KBD_DIVEHI_TYPEWRITER 0x00010465 -#define KBD_BELGIAN_COMMA 0x0001080C -#define KBD_FINNISH_WITH_SAMI 0x0001083B -#define KBD_CANADIAN_MULTILINGUAL_STANDARD 0x00011009 -#define KBD_GAELIC 0x00011809 -#define KBD_ARABIC_102_AZERTY 0x00020401 -#define KBD_CZECH_PROGRAMMERS 0x00020405 -#define KBD_GREEK_319 0x00020408 -#define KBD_UNITED_STATES_INTERNATIONAL 0x00020409 -#define KBD_HEBREW_STANDARD 0x0002040D /** @since version 3.6.0 */ -#define KBD_RUSSIAN_PHONETIC 0x00020419 -#define KBD_THAI_KEDMANEE_NON_SHIFTLOCK 0x0002041E -#define KBD_BANGLA 0x00020445 -#define KBD_SAMI_EXTENDED_FINLAND_SWEDEN 0x0002083B -#define KBD_GREEK_220_LATIN 0x00030408 -#define KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND 0x00030409 -#define KBD_THAI_PATTACHOTE_NON_SHIFTLOCK 0x0003041E -#define KBD_BULGARIAN_PHONETIC 0x00040402 -#define KBD_GREEK_319_LATIN 0x00040408 -#define KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND 0x00040409 -#define KBD_UNITED_STATES_DVORAK_PROGRAMMER 0x19360409 -#define KBD_GREEK_LATIN 0x00050408 -#define KBD_PERSIAN 0x00050429 -#define KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L 0x00050409 -#define KBD_GREEK_POLYTONIC 0x00060408 -#define KBD_FRENCH_BEPO 0xa000040c -#define KBD_GERMAN_NEO 0xB0000407 +typedef enum +{ + KBD_ARABIC_102 = 0x00010401, + KBD_BULGARIAN_LATIN = 0x00010402, + KBD_CZECH_QWERTY = 0x00010405, + KBD_GERMAN_IBM = 0x00010407, + KBD_GREEK_220 = 0x00010408, + KBD_UNITED_STATES_DVORAK = 0x00010409, + KBD_SPANISH_VARIATION = 0x0001040A, + KBD_HUNGARIAN_101_KEY = 0x0001040E, + KBD_ITALIAN_142 = 0x00010410, + KBD_POLISH_214 = 0x00010415, + KBD_PORTUGUESE_BRAZILIAN_ABNT2 = 0x00010416, + KBD_ROMANIAN_STANDARD = 0x00010418, + KBD_RUSSIAN_TYPEWRITER = 0x00010419, + KBD_SLOVAK_QWERTY = 0x0001041B, + KBD_THAI_PATTACHOTE = 0x0001041E, + KBD_TURKISH_F = 0x0001041F, + KBD_LATVIAN_QWERTY = 0x00010426, + KBD_LITHUANIAN = 0x00010427, + KBD_ARMENIAN_WESTERN = 0x0001042B, + KBD_GEORGIAN_QUERTY = 0x00010437, + KBD_HINDI_TRADITIONAL = 0x00010439, + KBD_MALTESE_48_KEY = 0x0001043A, + KBD_SAMI_EXTENDED_NORWAY = 0x0001043B, + KBD_BENGALI_INSCRIPT = 0x00010445, + KBD_KHMER = 0x00010453, + KBD_SYRIAC_PHONETIC = 0x0001045A, + KBD_DIVEHI_TYPEWRITER = 0x00010465, + KBD_BELGIAN_COMMA = 0x0001080C, + KBD_FINNISH_WITH_SAMI = 0x0001083B, + KBD_CANADIAN_MULTILINGUAL_STANDARD = 0x00011009, + KBD_GAELIC = 0x00011809, + KBD_ARABIC_102_AZERTY = 0x00020401, + KBD_CZECH_PROGRAMMERS = 0x00020405, + KBD_GREEK_319 = 0x00020408, + KBD_UNITED_STATES_INTERNATIONAL = 0x00020409, + KBD_HEBREW_STANDARD = 0x0002040D, /** @since version 3.6.0 */ + KBD_RUSSIAN_PHONETIC = 0x00020419, + KBD_THAI_KEDMANEE_NON_SHIFTLOCK = 0x0002041E, + KBD_BANGLA = 0x00020445, + KBD_SAMI_EXTENDED_FINLAND_SWEDEN = 0x0002083B, + KBD_GREEK_220_LATIN = 0x00030408, + KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND = 0x00030409, + KBD_THAI_PATTACHOTE_NON_SHIFTLOCK = 0x0003041E, + KBD_BULGARIAN_PHONETIC = 0x00040402, + KBD_GREEK_319_LATIN = 0x00040408, + KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND = 0x00040409, + KBD_UNITED_STATES_DVORAK_PROGRAMMER = 0x19360409, + KBD_GREEK_LATIN = 0x00050408, + KBD_PERSIAN = 0x00050429, + KBD_US_ENGLISH_TABLE_FOR_IBM_ARABIC_238_L = 0x00050409, + KBD_GREEK_POLYTONIC = 0x00060408, + KBD_FRENCH_BEPO = 0xa000040c, + KBD_GERMAN_NEO = 0xB0000407 +} FREERDP_KBD_LAYPUT_VARIANT_ID; /* Global Input Method Editor (IME) IDs */ +typedef enum +{ + KBD_CHINESE_TRADITIONAL_PHONETIC = 0xE0010404, + KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 = 0xE0010411, + KBD_KOREAN_INPUT_SYSTEM_IME_2000 = 0xE0010412, + KBD_CHINESE_SIMPLIFIED_QUANPIN = 0xE0010804, + KBD_CHINESE_TRADITIONAL_CHANGJIE = 0xE0020404, + KBD_CHINESE_SIMPLIFIED_SHUANGPIN = 0xE0020804, + KBD_CHINESE_TRADITIONAL_QUICK = 0xE0030404, + KBD_CHINESE_SIMPLIFIED_ZHENGMA = 0xE0030804, + KBD_CHINESE_TRADITIONAL_BIG5_CODE = 0xE0040404, + KBD_CHINESE_TRADITIONAL_ARRAY = 0xE0050404, + KBD_CHINESE_SIMPLIFIED_NEIMA = 0xE0050804, + KBD_CHINESE_TRADITIONAL_DAYI = 0xE0060404, + KBD_CHINESE_TRADITIONAL_UNICODE = 0xE0070404, + KBD_CHINESE_TRADITIONAL_NEW_PHONETIC = 0xE0080404, + KBD_CHINESE_TRADITIONAL_NEW_CHANGJIE = 0xE0090404, + KBD_CHINESE_TRADITIONAL_MICROSOFT_PINYIN_IME_3 = 0xE00E0804, + KBD_CHINESE_TRADITIONAL_ALPHANUMERIC = 0xE00F0404 +} FREERDP_KBD_IME_ID; -#define KBD_CHINESE_TRADITIONAL_PHONETIC 0xE0010404 -#define KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002 0xE0010411 -#define KBD_KOREAN_INPUT_SYSTEM_IME_2000 0xE0010412 -#define KBD_CHINESE_SIMPLIFIED_QUANPIN 0xE0010804 -#define KBD_CHINESE_TRADITIONAL_CHANGJIE 0xE0020404 -#define KBD_CHINESE_SIMPLIFIED_SHUANGPIN 0xE0020804 -#define KBD_CHINESE_TRADITIONAL_QUICK 0xE0030404 -#define KBD_CHINESE_SIMPLIFIED_ZHENGMA 0xE0030804 -#define KBD_CHINESE_TRADITIONAL_BIG5_CODE 0xE0040404 -#define KBD_CHINESE_TRADITIONAL_ARRAY 0xE0050404 -#define KBD_CHINESE_SIMPLIFIED_NEIMA 0xE0050804 -#define KBD_CHINESE_TRADITIONAL_DAYI 0xE0060404 -#define KBD_CHINESE_TRADITIONAL_UNICODE 0xE0070404 -#define KBD_CHINESE_TRADITIONAL_NEW_PHONETIC 0xE0080404 -#define KBD_CHINESE_TRADITIONAL_NEW_CHANGJIE 0xE0090404 -#define KBD_CHINESE_TRADITIONAL_MICROSOFT_PINYIN_IME_3 0xE00E0804 -#define KBD_CHINESE_TRADITIONAL_ALPHANUMERIC 0xE00F0404 +/** @brief Deallocation function for a \b RDP_KEYBOARD_LAYOUT array of \b count size + * + * @param layouts An array allocated by \ref freerdp_keyboard_get_layouts + * @param count The number of \b RDP_KEYBOARD_LAYOUT members + * + */ +FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts, size_t count); - FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId); - FREERDP_API DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, - const char* keyboardRemappingList); - FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types, size_t* count); - FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts, size_t count); - FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId); - FREERDP_API DWORD freerdp_keyboard_get_layout_id_from_name(const char* name); - FREERDP_API DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode); - FREERDP_API DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode(DWORD scancode, - BOOL extended); +/** @brief Return an allocated array of available keyboard layouts + * + * @param types The types of layout queried. A mask of \b RDP_KEYBOARD_LAYOUT_TYPES + * @param count A pointer that will be set to the number of elements in the returned array + * + * @return An allocated array of keyboard layouts, free with \b freerdp_keyboard_layouts_free + */ +WINPR_ATTR_MALLOC(freerdp_keyboard_layouts_free, 1) +FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types, size_t* count); - FREERDP_API RDP_CODEPAGE* - freerdp_keyboard_get_matching_codepages(DWORD column, const char* filter, size_t* count); - FREERDP_API void freerdp_codepages_free(RDP_CODEPAGE*); +/** @brief Get a string representation of a keyboard layout. + * + * @param keyboardLayoutId The keyboard layout to get a string for + * + * @return The string representation of the layout or the string \b "unknown" in case there is + * none. + */ +FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId); - FREERDP_API const char* freerdp_keyboard_scancode_name(DWORD scancode); +/** @brief Get a keyboard layout id from a string + * + * @param name The string to convert to a layout id. Must not be \b NULL + * + * @return The keyboard layout id or \b 0 in case of no mapping + */ +FREERDP_API DWORD freerdp_keyboard_get_layout_id_from_name(const char* name); + +WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", + FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId)); + +WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", + FREERDP_API DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, + const char* keyboardRemappingList)); + +WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", + FREERDP_API DWORD + freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode)); + +WINPR_DEPRECATED_VAR("since 3.11.0, implement yourself in client", + FREERDP_API DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode( + DWORD scancode, BOOL extended)); + +/** @brief deallocate a \b FREERDP_REMAP_TABLE + * + * @param table The table to deallocate, may be \b NULL + * + * @since version 3.11.0 + */ +FREERDP_API void freerdp_keyboard_remap_free(FREERDP_REMAP_TABLE* table); + +/** @brief parses a key=value string and creates a RDP scancode remapping table from it. + * + * @param list A string containing the comma separated key=value pairs (e.g. + * 'key=val,key2=val2,...') + * + * @return An allocated array of values to remap. Must be deallocated by \ref + * freerdp_keyboard_remap_free + * + * @since version 3.11.0 + */ +WINPR_ATTR_MALLOC(freerdp_keyboard_remap_free, 1) +FREERDP_API FREERDP_REMAP_TABLE* freerdp_keyboard_remap_string_to_list(const char* list); + +/** @brief does remap a RDP scancode according to the remap table provided. + * + * @param remap_table The remapping table to use + * @param rdpScanCode the RDP scancode to remap + * + * @return The remapped RDP scancode (or the rdpScanCode if not remapped) or \b 0 in case of any + * failures + * + * @since version 3.11.0 + */ +FREERDP_API DWORD freerdp_keyboard_remap_key(const FREERDP_REMAP_TABLE* remap_table, + DWORD rdpScanCode); + +/** @brief deallocator for a \b RDP_CODEPAGE array allocated by \ref + * freerdp_keyboard_get_matching_codepages + * + * @param codepages The codepages to free, may be \b NULL + */ +FREERDP_API void freerdp_codepages_free(RDP_CODEPAGE* codepages); + +/** @brief return an allocated array of matching codepages + * + * @param column The column the filter is applied to: + * - 0 : RDP_CODEPAGE::locale + * - 1 : RDP_CODEPAGE::PrimaryLanguage + * - 2 : RDP_CODEPAGE::PrimaryLanguageSymbol + * - 3 : RDP_CODEPAGE::Sublanguage + * - 4 : RDP_CODEPAGE::SublanguageSymbol + * @param filter A filter pattern or \b NULL for no filtering. Simple string match, no expressions + * supported (e.g. \b strstr match) + * @param count A pointer that will be set to the number of codepages found, may be \b NULL + * + * @return An allocated array of \b RDP_CODEPAGE of size \b count or \b NULL if no match. Must be + * freed by \ref freerdp_codepages_free + */ +WINPR_ATTR_MALLOC(freerdp_codepages_free, 1) +FREERDP_API RDP_CODEPAGE* freerdp_keyboard_get_matching_codepages(DWORD column, const char* filter, + size_t* count); + +/** @brief get a string representation of a RDP scancode + * + * @param scancode The RDP scancode to get a string for + * + * @return A string describing the RDP scancode or \b NULL if it does not exist + */ +FREERDP_API const char* freerdp_keyboard_scancode_name(DWORD scancode); #ifdef __cplusplus } diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c index 4f00601a5..c938f7201 100644 --- a/libfreerdp/locale/keyboard.c +++ b/libfreerdp/locale/keyboard.c @@ -55,6 +55,11 @@ static DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2] = { 0 }; static DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256] = { 0 }; static DWORD REMAPPING_TABLE[0x10000] = { 0 }; +struct rdp_remap_table +{ + DWORD table[0x10000]; +}; + struct scancode_map_entry { DWORD scancode; @@ -342,6 +347,52 @@ DWORD freerdp_keyboard_init(DWORD keyboardLayoutId) return keyboardLayoutId; } +FREERDP_REMAP_TABLE* freerdp_keyboard_remap_string_to_list(const char* list) +{ + const size_t remap_table_size = 0x10000; + + FREERDP_REMAP_TABLE* remap_table = calloc(1, sizeof(FREERDP_REMAP_TABLE)); + if (!remap_table) + return NULL; + + for (size_t x = 0; x < ARRAYSIZE(remap_table->table); x++) + remap_table->table[x] = (UINT32)x; + + if (!list) + return remap_table; + + char* copy = _strdup(list); + if (!copy) + goto fail; + + BOOL success = FALSE; + char* context = NULL; + char* token = strtok_s(copy, ",", &context); + while (token) + { + DWORD key = 0; + DWORD value = 0; + if (!freerdp_extract_key_value(token, &key, &value)) + goto fail; + if (key >= remap_table_size) + goto fail; + remap_table->table[key] = value; + token = strtok_s(NULL, ",", &context); + } + + success = TRUE; + +fail: + free(copy); + + if (!success) + { + free(remap_table); + return NULL; + } + return remap_table; +} + DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, const char* keyboardRemappingList) { DWORD res = freerdp_keyboard_init(keyboardLayoutId); @@ -442,3 +493,16 @@ const char* freerdp_keyboard_scancode_name(DWORD scancode) return NULL; } + +DWORD freerdp_keyboard_remap_key(const FREERDP_REMAP_TABLE* remap_table, DWORD rdpScanCode) +{ + if (!remap_table || (ARRAYSIZE(remap_table->table) <= rdpScanCode)) + return 0; + + return remap_table->table[rdpScanCode]; +} + +void freerdp_keyboard_remap_free(FREERDP_REMAP_TABLE* table) +{ + free(table); +}