Fixed bug 3332 - Win32: reset deadkeys in StartTextInput/StopTextInput
authorSam Lantinga <slouken@libsdl.org>
Sat, 01 Oct 2016 11:54:02 -0700
changeset 10410e9dd9ecf3fe5
parent 10409 db023d8a1c8b
child 10411 9012ec687429
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
     1.1 --- a/src/video/windows/SDL_windowskeyboard.c	Sat Oct 01 11:48:15 2016 -0700
     1.2 +++ b/src/video/windows/SDL_windowskeyboard.c	Sat Oct 01 11:54:02 2016 -0700
     1.3 @@ -158,10 +158,50 @@
     1.4  }
     1.5  
     1.6  void
     1.7 +WIN_ResetDeadKeys()
     1.8 +{
     1.9 +    /*
    1.10 +    if a deadkey has been typed, but not the next character (which the deadkey might modify), 
    1.11 +    this tries to undo the effect pressing the deadkey.
    1.12 +    see: http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
    1.13 +    */
    1.14 +
    1.15 +    BYTE keyboardState[256];
    1.16 +    WCHAR buffer[16];
    1.17 +    int keycode, scancode, result, i;
    1.18 +
    1.19 +    GetKeyboardState(keyboardState);
    1.20 +
    1.21 +    keycode = VK_SPACE;
    1.22 +    scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC);
    1.23 +    if (scancode == 0)
    1.24 +    {
    1.25 +        /* the keyboard doesn't have this key */
    1.26 +        return;
    1.27 +    }
    1.28 +
    1.29 +    for (i = 0; i < 5; i++)
    1.30 +    {
    1.31 +        result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)buffer, 16, 0);
    1.32 +        if (result > 0)
    1.33 +        {
    1.34 +            /* success */
    1.35 +            return;
    1.36 +        }
    1.37 +    }
    1.38 +}
    1.39 +
    1.40 +void
    1.41  WIN_StartTextInput(_THIS)
    1.42  {
    1.43  #ifndef SDL_DISABLE_WINDOWS_IME
    1.44 -    SDL_Window *window = SDL_GetKeyboardFocus();
    1.45 +    SDL_Window *window;
    1.46 +#endif
    1.47 +
    1.48 +    WIN_ResetDeadKeys();
    1.49 +
    1.50 +#ifndef SDL_DISABLE_WINDOWS_IME
    1.51 +    window = SDL_GetKeyboardFocus();
    1.52      if (window) {
    1.53          HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    1.54          SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
    1.55 @@ -176,7 +216,13 @@
    1.56  WIN_StopTextInput(_THIS)
    1.57  {
    1.58  #ifndef SDL_DISABLE_WINDOWS_IME
    1.59 -    SDL_Window *window = SDL_GetKeyboardFocus();
    1.60 +    SDL_Window *window;
    1.61 +#endif
    1.62 +
    1.63 +    WIN_ResetDeadKeys();
    1.64 +
    1.65 +#ifndef SDL_DISABLE_WINDOWS_IME
    1.66 +    window = SDL_GetKeyboardFocus();
    1.67      if (window) {
    1.68          HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
    1.69          SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;