Quellcode durchsuchen

UWP: Add support for supplementary Unicode characters input

Characters outside Basic Multilingual Plane (BMP) are coded as so called "surrogate pair" in two separate UTF-16 character events.
Dimitriy Ryazantcev vor 1 Jahr
Ursprung
Commit
9faa7977bd

+ 1 - 1
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 <typename BackButtonEventArgs>

+ 1 - 1
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;

+ 1 - 1
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);

+ 28 - 13
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;
-
-    /* Setup src */
-    src_ucs2[0] = args->KeyCode;
-    src_ucs2[1] = L'\0';
-
-    /* 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);
+    if (!window) {
+        return;
+    }
+
+    SDL_WindowData *data = window->driverdata;
+
+    /* 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';
     }
 }
 

+ 1 - 0
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

+ 1 - 0
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