From 9faa7977bd9966793cf5ebb5a0c6d646468d8cb6 Mon Sep 17 00:00:00 2001
From: Dimitriy Ryazantcev <[EMAIL REDACTED]>
Date: Mon, 27 Nov 2023 17:23:17 +0200
Subject: [PATCH] =?UTF-8?q?=EF=BB=BFUWP:=20Add=20support=20for=20supplemen?=
=?UTF-8?q?tary=20Unicode=20characters=20input?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Characters outside Basic Multilingual Plane (BMP) are coded as so called "surrogate pair" in two separate UTF-16 character events.
---
src/core/winrt/SDL_winrtapp_direct3d.cpp | 2 +-
src/video/windows/SDL_windowsevents.c | 2 +-
src/video/winrt/SDL_winrtevents_c.h | 2 +-
src/video/winrt/SDL_winrtkeyboard.cpp | 41 ++++++++++++++++--------
src/video/winrt/SDL_winrtvideo.cpp | 1 +
src/video/winrt/SDL_winrtvideo_cpp.h | 1 +
6 files changed, 33 insertions(+), 16 deletions(-)
diff --git a/src/core/winrt/SDL_winrtapp_direct3d.cpp b/src/core/winrt/SDL_winrtapp_direct3d.cpp
index f451203e25b5..64572f33b2bb 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 <typename BackButtonEventArgs>
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index dc56b0002b39..8624b92dc9d5 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 7330c7442dc7..72de3bb8fd2a 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 0524db48f35a..4a62b0186ce1 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;
-
- /* 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';
}
}
diff --git a/src/video/winrt/SDL_winrtvideo.cpp b/src/video/winrt/SDL_winrtvideo.cpp
index 1399738c7e2b..8f8cde7e5b1e 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 069fff4fb19f..e8b8c3d47613 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