From 1e6e595484cc32aba4297546c042d4f4eb376822 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 1 Oct 2016 11:54:02 -0700 Subject: [PATCH] Fixed bug 3332 - Win32: reset deadkeys in StartTextInput/StopTextInput Eric Wasylishen The bug here is that a dead keys pressed before calling SDL_StartTextInput() carries over into future text input, so the next key pressed will have the deadkey applied to it. This in undesirable, imho, and doesn't occur on OS X (haven't check Linux or elsewhere). It's causing a problem for Quakespasm on German keyboard layouts, where we use the ^ deadkey to toggle the console (which enables/disables text input), and ^ characters are showing up in the TEXTINPUT events. --- src/video/windows/SDL_windowskeyboard.c | 50 ++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index d3e16c8bfc98a..de72ad7958309 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -157,11 +157,51 @@ WIN_QuitKeyboard(_THIS) #endif } +void +WIN_ResetDeadKeys() +{ + /* + if a deadkey has been typed, but not the next character (which the deadkey might modify), + this tries to undo the effect pressing the deadkey. + see: http://archives.miloush.net/michkap/archive/2006/09/10/748775.html + */ + + BYTE keyboardState[256]; + WCHAR buffer[16]; + int keycode, scancode, result, i; + + GetKeyboardState(keyboardState); + + keycode = VK_SPACE; + scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC); + if (scancode == 0) + { + /* the keyboard doesn't have this key */ + return; + } + + for (i = 0; i < 5; i++) + { + result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)buffer, 16, 0); + if (result > 0) + { + /* success */ + return; + } + } +} + void WIN_StartTextInput(_THIS) { #ifndef SDL_DISABLE_WINDOWS_IME - SDL_Window *window = SDL_GetKeyboardFocus(); + SDL_Window *window; +#endif + + WIN_ResetDeadKeys(); + +#ifndef SDL_DISABLE_WINDOWS_IME + window = SDL_GetKeyboardFocus(); if (window) { HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata; @@ -176,7 +216,13 @@ void WIN_StopTextInput(_THIS) { #ifndef SDL_DISABLE_WINDOWS_IME - SDL_Window *window = SDL_GetKeyboardFocus(); + SDL_Window *window; +#endif + + WIN_ResetDeadKeys(); + +#ifndef SDL_DISABLE_WINDOWS_IME + window = SDL_GetKeyboardFocus(); if (window) { HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;