From 41aaafef77f8aa8a183c69a79d674167cbb0e34e Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 10 Sep 2021 15:46:33 +0200 Subject: [PATCH] Added unicode input for xfreerdp --- client/X11/xf_keyboard.c | 68 ++++++++++++++++++++++++++++------ client/X11/xf_keyboard.h | 2 +- client/common/cmdline.c | 9 +++++ client/common/cmdline.h | 3 ++ libfreerdp/core/capabilities.c | 21 ++++++++--- libfreerdp/core/settings.c | 5 ++- 6 files changed, 88 insertions(+), 20 deletions(-) diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index 0dd9738fe..45ae89221 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -43,6 +43,8 @@ #include #define TAG CLIENT_TAG("x11") +static void xf_keyboard_send_key(xfContext* xfc, BOOL down, const XKeyEvent* ev); + static BOOL xf_sync_kbd_state(xfContext* xfc) { const UINT32 syncFlags = xf_keyboard_get_toggle_keys_state(xfc); @@ -155,7 +157,7 @@ void xf_keyboard_key_press(xfContext* xfc, const XKeyEvent* event, KeySym keysym if (xf_keyboard_handle_special_keys(xfc, keysym)) return; - xf_keyboard_send_key(xfc, TRUE, event->keycode); + xf_keyboard_send_key(xfc, TRUE, event); } void xf_keyboard_key_release(xfContext* xfc, const XKeyEvent* event, KeySym keysym) @@ -168,7 +170,7 @@ void xf_keyboard_key_release(xfContext* xfc, const XKeyEvent* event, KeySym keys xfc->KeyboardState[event->keycode] = FALSE; xf_keyboard_handle_special_keys_release(xfc, keysym); - xf_keyboard_send_key(xfc, FALSE, event->keycode); + xf_keyboard_send_key(xfc, FALSE, event); } void xf_keyboard_release_all_keypress(xfContext* xfc) @@ -200,19 +202,20 @@ BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym) return xfc->KeyboardState[keycode]; } -void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode) +void xf_keyboard_send_key(xfContext* xfc, BOOL down, const XKeyEvent* event) { DWORD rdp_scancode; rdpInput* input; - input = xfc->context.input; - rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(keycode); - if (rdp_scancode == RDP_SCANCODE_UNKNOWN) - { - WLog_ERR(TAG, "Unknown key with X keycode 0x%02" PRIx8 "", keycode); - } - else if (rdp_scancode == RDP_SCANCODE_PAUSE && !xf_keyboard_key_pressed(xfc, XK_Control_L) && - !xf_keyboard_key_pressed(xfc, XK_Control_R)) + WINPR_ASSERT(xfc); + WINPR_ASSERT(event); + + input = xfc->context.input; + WINPR_ASSERT(input); + + rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(event->keycode); + if (rdp_scancode == RDP_SCANCODE_PAUSE && !xf_keyboard_key_pressed(xfc, XK_Control_L) && + !xf_keyboard_key_pressed(xfc, XK_Control_R)) { /* Pause without Ctrl has to be sent as a series of keycodes * in a single input PDU. Pause only happens on "press"; @@ -225,7 +228,48 @@ void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode) } else { - freerdp_input_send_keyboard_event_ex(input, down, rdp_scancode); + BOOL rc; + if (freerdp_settings_get_bool(xfc->context.settings, FreeRDP_UnicodeInput)) + { + wchar_t buffer[32] = { 0 }; + int rc = 0; + int xwc = -1; + + switch (rdp_scancode) + { + case RDP_SCANCODE_RETURN: + break; + default: + { + XIM xim = XOpenIM(xfc->display, 0, 0, 0); + XIC xic = + XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, NULL); + + KeySym ignore = { 0 }; + Status return_status; + XKeyEvent ev = *event; + ev.type = KeyPress; + xwc = XwcLookupString(xic, &ev, buffer, ARRAYSIZE(buffer), &ignore, + &return_status); + } + break; + } + + if (xwc < 1) + { + if (rdp_scancode == RDP_SCANCODE_UNKNOWN) + WLog_ERR(TAG, "Unknown key with X keycode 0x%02" PRIx8 "", event->keycode); + else + rc = freerdp_input_send_keyboard_event_ex(input, down, rdp_scancode); + } + else + rc = freerdp_input_send_unicode_keyboard_event(input, down ? KBD_FLAGS_RELEASE : 0, + buffer[0]); + } + else if (rdp_scancode == RDP_SCANCODE_UNKNOWN) + WLog_ERR(TAG, "Unknown key with X keycode 0x%02" PRIx8 "", event->keycode); + else + rc = freerdp_input_send_keyboard_event_ex(input, down, rdp_scancode); if ((rdp_scancode == RDP_SCANCODE_CAPSLOCK) && (down == FALSE)) { diff --git a/client/X11/xf_keyboard.h b/client/X11/xf_keyboard.h index 406d38a91..36b921b45 100644 --- a/client/X11/xf_keyboard.h +++ b/client/X11/xf_keyboard.h @@ -50,7 +50,7 @@ void xf_keyboard_key_release(xfContext* xfc, const XKeyEvent* event, KeySym keys void xf_keyboard_release_all_keypress(xfContext* xfc); BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym); -void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode); + int xf_keyboard_read_keyboard_state(xfContext* xfc); BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym); UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index cc9d0d994..2eaa94e4e 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1631,6 +1631,10 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, arg = largs; errno = 0; + /* Disable unicode input unless requested. */ + if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, FALSE)) + return COMMAND_LINE_ERROR_MEMORY; + do { BOOL enable = arg->Value ? TRUE : FALSE; @@ -2053,6 +2057,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->KeyboardType = (UINT32)val; } + CommandLineSwitchCase(arg, "kbd-unicode") + { + if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, enable)) + return COMMAND_LINE_ERROR_UNEXPECTED_VALUE; + } CommandLineSwitchCase(arg, "kbd-subtype") { LONGLONG val; diff --git a/client/common/cmdline.h b/client/common/cmdline.h index 02f2f0294..18825dd49 100644 --- a/client/common/cmdline.h +++ b/client/common/cmdline.h @@ -221,6 +221,9 @@ static const COMMAND_LINE_ARGUMENT_A args[] = { { "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard subtype" }, { "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Keyboard type" }, + { "kbd-unicode", COMMAND_LINE_VALUE_FLAG, "", NULL, NULL, -1, NULL, + "Send unicode symbols, e.g. use the local keyboard map. ATTENTION: Does not work with every " + "RDP server!" }, { "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Load balance info" }, { "log-filters", COMMAND_LINE_VALUE_REQUIRED, ":[,:[,...]]", NULL, NULL, diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 91381901e..ffad86f8e 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -1294,14 +1294,23 @@ static BOOL rdp_read_input_capability_set(wStream* s, rdpSettings* settings) settings->FastPathInput = FALSE; } - if (inputFlags & TS_INPUT_FLAG_MOUSE_HWHEEL) - settings->HasHorizontalWheel = TRUE; + if (settings->HasHorizontalWheel) + { + if (inputFlags & TS_INPUT_FLAG_MOUSE_HWHEEL) + settings->HasHorizontalWheel = TRUE; + } - if (inputFlags & INPUT_FLAG_UNICODE) - settings->UnicodeInput = TRUE; + if (settings->UnicodeInput) + { + if (inputFlags & INPUT_FLAG_UNICODE) + settings->UnicodeInput = TRUE; + } - if (inputFlags & INPUT_FLAG_MOUSEX) - settings->HasExtendedMouseEvent = TRUE; + if (settings->HasExtendedMouseEvent) + { + if (inputFlags & INPUT_FLAG_MOUSEX) + settings->HasExtendedMouseEvent = TRUE; + } } return TRUE; diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index 9c988de7b..0c86310c0 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -311,7 +311,10 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings) return NULL; - if (!freerdp_settings_set_bool(settings, FreeRDP_HiDefRemoteApp, FALSE) || + if (!freerdp_settings_set_bool(settings, FreeRDP_UnicodeInput, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_HasHorizontalWheel, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_HasExtendedMouseEvent, TRUE) || + !freerdp_settings_set_bool(settings, FreeRDP_HiDefRemoteApp, FALSE) || !freerdp_settings_set_uint32( settings, FreeRDP_RemoteApplicationSupportMask, RAIL_LEVEL_SUPPORTED | RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED |