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.
This commit is contained in:
Sam Lantinga 2015-06-25 11:49:48 -07:00
parent 82eec4b630
commit 3a08b46336
1 changed files with 15 additions and 19 deletions

View File

@ -295,7 +295,7 @@ WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
data->mouse_button_flags = 0; data->mouse_button_flags = 0;
} }
SDL_FORCE_INLINE BOOL BOOL
WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text) WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
{ {
if (codepoint <= 0x7F) { if (codepoint <= 0x7F) {
@ -568,21 +568,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
SDL_SendKeyboardKey(SDL_PRESSED, code); 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; returnCode = 0;
break; break;
@ -604,9 +590,19 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break; break;
case WM_UNICHAR: case WM_UNICHAR:
case WM_CHAR: if ( wParam == UNICODE_NOCHAR ) {
/* Ignore WM_CHAR messages that come from TranslateMessage(), since we handle WM_KEY* messages directly */ returnCode = 1;
returnCode = 0; break;
}
/* otherwise fall through to below */
case WM_CHAR:
{
char text[5];
if ( WIN_ConvertUTF32toUTF8( wParam, text ) ) {
SDL_SendKeyboardText( text );
}
}
returnCode = 0;
break; break;
#ifdef WM_INPUTLANGCHANGE #ifdef WM_INPUTLANGCHANGE