diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp index f451203e25..64572f33b2 100644 --- a/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -724,7 +724,7 @@ void SDL_WinRTApp::OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^ void SDL_WinRTApp::OnCharacterReceived(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args) { - WINRT_ProcessCharacterReceivedEvent(args); + WINRT_ProcessCharacterReceivedEvent(WINRT_GlobalSDLWindow, args); } template diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index dc56b0002b..8624b92dc9 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -855,7 +855,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_CHAR: /* Characters outside Unicode Basic Multilingual Plane (BMP) - * are coded as so called "surrogate pair" in two separate character events. + * are coded as so called "surrogate pair" in two separate UTF-16 character events. * Cache high surrogate until next character event. */ if (IS_HIGH_SURROGATE(wParam)) { data->high_surrogate = (WCHAR)wParam; diff --git a/src/video/winrt/SDL_winrtevents_c.h b/src/video/winrt/SDL_winrtevents_c.h index 7330c7442d..72de3bb8fd 100644 --- a/src/video/winrt/SDL_winrtevents_c.h +++ b/src/video/winrt/SDL_winrtevents_c.h @@ -64,7 +64,7 @@ extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::I /* Keyboard */ extern void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEventArgs ^ args); -extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args); +extern void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core::CharacterReceivedEventArgs ^ args); #if NTDDI_VERSION >= NTDDI_WIN10 extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this); diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index 0524db48f3..4a62b0186c 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -34,6 +34,8 @@ extern "C" { #include "../../events/SDL_keyboard_c.h" } +#include "SDL_winrtvideo_cpp.h" + static SDL_Scancode WINRT_TranslateKeycode(Windows::System::VirtualKey virtualKey, const Windows::UI::Core::CorePhysicalKeyStatus& keyStatus) { SDL_Scancode code; @@ -78,20 +80,33 @@ void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEvent SDL_SendKeyboardKey(0, state, code); } -void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^ args) +void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core::CharacterReceivedEventArgs ^ args) { - wchar_t src_ucs2[2]; - char dest_utf8[16]; - int result; + if (!window) { + return; + } - /* Setup src */ - src_ucs2[0] = args->KeyCode; - src_ucs2[1] = L'\0'; + SDL_WindowData *data = window->driverdata; - /* Convert the text, then send an SDL_EVENT_TEXT_INPUT event. */ - result = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&src_ucs2, -1, (LPSTR)dest_utf8, sizeof(dest_utf8), NULL, NULL); - if (result > 0) { - SDL_SendKeyboardText(dest_utf8); + /* Characters outside Unicode Basic Multilingual Plane (BMP) + * are coded as so called "surrogate pair" in two separate UTF-16 character events. + * Cache high surrogate until next character event. */ + if (IS_HIGH_SURROGATE(args->KeyCode)) { + data->high_surrogate = (WCHAR)args->KeyCode; + } else { + WCHAR utf16[] = { + data->high_surrogate ? data->high_surrogate : (WCHAR)args->KeyCode, + data->high_surrogate ? (WCHAR)args->KeyCode : L'\0', + L'\0' + }; + + char utf8[5]; + int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + if (result > 0) { + SDL_SendKeyboardText(utf8); + } + + data->high_surrogate = L'\0'; } } diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp index 1399738c7e..8f8cde7e5b 100644 --- a/src/video/winrt/SDL_winrtvideo.cpp +++ b/src/video/winrt/SDL_winrtvideo.cpp @@ -595,6 +595,7 @@ int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie } window->driverdata = data; data->sdlWindow = window; + data->high_surrogate = L'\0'; /* To note, when XAML support is enabled, access to the CoreWindow will not be possible, at least not via the SDL/XAML thread. Attempts to access it diff --git a/src/video/winrt/SDL_winrtvideo_cpp.h b/src/video/winrt/SDL_winrtvideo_cpp.h index 069fff4fb1..e8b8c3d476 100644 --- a/src/video/winrt/SDL_winrtvideo_cpp.h +++ b/src/video/winrt/SDL_winrtvideo_cpp.h @@ -100,6 +100,7 @@ struct SDL_WindowData #if SDL_WINRT_USE_APPLICATIONVIEW Windows::UI::ViewManagement::ApplicationView ^ appView; #endif + WCHAR high_surrogate; }; #endif // ifdef __cplusplus_winrt