From 3a08b46336cd123316a0339442f80d4f40dab8f7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 25 Jun 2015 11:49:48 -0700 Subject: [PATCH] Fixed bug 2834 - Patch to support dead keys on Windows Elise Maurer When inputting text, dead-keys are currently not handled correctly on Windows with the latest SDL2 tip as well as the 2.0.3 release. Using a French AZERTY keyboard, when I type the `^` key followed by `e` key to compose the `` character, I erroneously get two SDL_TEXTINPUT events, one with the `^` character and one with the `e` character. I've looked at the history for SDL_windowsevents.c and there's been some back-and-forth with several methods for handling text input: * r8142 removed any handling of WM_CHAR because keyboard input was being handled through WM_KEYDOWN along with ToUnicode since r7645. * But using ToUnicode actually breaks dead-keys (googling for "ToUnicode dead keys" reports many horror stories of people trying to work around that and failing). * It seems like r7645 introduced a double-fix: it fixed WM_CHAR to properly handle Unicode, and also (unnecessarily?) added text input handling to WM_KEYDOWN. Later, r8142 removed the WM_CHAR stuff instead of the WM_KEYDOWN stuff. The attached patch restores handling of text input through WM_CHAR and removes it from WM_KEYDOWN. I've tested it with French, English and Russian layouts and it seems to do its job. Obviously, with such matters, it's still a risky change. --- src/video/windows/SDL_windowsevents.c | 34 ++++++++++++--------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 7ade709727122..c787f25d0618b 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -295,7 +295,7 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data) data->mouse_button_flags = 0; } -SDL_FORCE_INLINE BOOL +BOOL WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text) { if (codepoint <= 0x7F) { @@ -568,21 +568,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) SDL_SendKeyboardKey(SDL_PRESSED, code); } } - if (msg == WM_KEYDOWN) { - BYTE keyboardState[256]; - char text[5]; - UINT32 utf32 = 0; - - GetKeyboardState(keyboardState); - if (ToUnicode(wParam, (lParam >> 16) & 0xff, keyboardState, (LPWSTR)&utf32, 1, 0) > 0) { - if (WIN_ConvertUTF32toUTF8(utf32, text)) { - WORD repetition; - for (repetition = lParam & 0xffff; repetition > 0; repetition--) { - SDL_SendKeyboardText(text); - } - } - } - } + returnCode = 0; break; @@ -604,9 +590,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_UNICHAR: - case WM_CHAR: - /* Ignore WM_CHAR messages that come from TranslateMessage(), since we handle WM_KEY* messages directly */ - returnCode = 0; + if ( wParam == UNICODE_NOCHAR ) { + returnCode = 1; + break; + } + /* otherwise fall through to below */ + case WM_CHAR: + { + char text[5]; + if ( WIN_ConvertUTF32toUTF8( wParam, text ) ) { + SDL_SendKeyboardText( text ); + } + } + returnCode = 0; break; #ifdef WM_INPUTLANGCHANGE