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.
This commit is contained in:
Dimitriy Ryazantcev
2023-11-27 17:23:17 +02:00
committed by Sam Lantinga
parent 7b628ea4d5
commit 9faa7977bd
6 changed files with 31 additions and 14 deletions

View File

@@ -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) 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> template <typename BackButtonEventArgs>

View File

@@ -855,7 +855,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_CHAR: case WM_CHAR:
/* Characters outside Unicode Basic Multilingual Plane (BMP) /* 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. */ * Cache high surrogate until next character event. */
if (IS_HIGH_SURROGATE(wParam)) { if (IS_HIGH_SURROGATE(wParam)) {
data->high_surrogate = (WCHAR)wParam; data->high_surrogate = (WCHAR)wParam;

View File

@@ -64,7 +64,7 @@ extern void WINRT_ProcessMouseMovedEvent(SDL_Window *window, Windows::Devices::I
/* Keyboard */ /* Keyboard */
extern void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEventArgs ^ args); 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 #if NTDDI_VERSION >= NTDDI_WIN10
extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this); extern void WINTRT_InitialiseInputPaneEvents(SDL_VideoDevice *_this);

View File

@@ -34,6 +34,8 @@ extern "C" {
#include "../../events/SDL_keyboard_c.h" #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) static SDL_Scancode WINRT_TranslateKeycode(Windows::System::VirtualKey virtualKey, const Windows::UI::Core::CorePhysicalKeyStatus& keyStatus)
{ {
SDL_Scancode code; SDL_Scancode code;
@@ -78,20 +80,33 @@ void WINRT_ProcessAcceleratorKeyActivated(Windows::UI::Core::AcceleratorKeyEvent
SDL_SendKeyboardKey(0, state, code); 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]; if (!window) {
char dest_utf8[16]; return;
int result; }
/* Setup src */ SDL_WindowData *data = window->driverdata;
src_ucs2[0] = args->KeyCode;
src_ucs2[1] = L'\0';
/* Convert the text, then send an SDL_EVENT_TEXT_INPUT event. */ /* Characters outside Unicode Basic Multilingual Plane (BMP)
result = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)&src_ucs2, -1, (LPSTR)dest_utf8, sizeof(dest_utf8), NULL, NULL); * are coded as so called "surrogate pair" in two separate UTF-16 character events.
if (result > 0) { * Cache high surrogate until next character event. */
SDL_SendKeyboardText(dest_utf8); 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';
} }
} }

View File

@@ -595,6 +595,7 @@ int WINRT_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Propertie
} }
window->driverdata = data; window->driverdata = data;
data->sdlWindow = window; data->sdlWindow = window;
data->high_surrogate = L'\0';
/* To note, when XAML support is enabled, access to the CoreWindow will not /* 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 be possible, at least not via the SDL/XAML thread. Attempts to access it

View File

@@ -100,6 +100,7 @@ struct SDL_WindowData
#if SDL_WINRT_USE_APPLICATIONVIEW #if SDL_WINRT_USE_APPLICATIONVIEW
Windows::UI::ViewManagement::ApplicationView ^ appView; Windows::UI::ViewManagement::ApplicationView ^ appView;
#endif #endif
WCHAR high_surrogate;
}; };
#endif // ifdef __cplusplus_winrt #endif // ifdef __cplusplus_winrt