src/video/winrt/SDL_winrtkeyboard.cpp
author David Ludwig <dludwig@pobox.com>
Sat, 25 Oct 2014 08:54:23 -0400
changeset 9192 50b888469010
parent 9191 7a728256c5f5
child 9193 5ca521b8486d
permissions -rw-r--r--
WinRT: Fixed bug whereby key-detection code could call SDL_Log
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../../SDL_internal.h"
    22 
    23 #if SDL_VIDEO_DRIVER_WINRT
    24 
    25 /* Windows-specific includes */
    26 #include <Windows.h>
    27 #include <agile.h>
    28 
    29 
    30 /* SDL-specific includes */
    31 #include <SDL.h>
    32 #include "SDL_winrtevents_c.h"
    33 
    34 extern "C" {
    35 #include "../../events/scancodes_windows.h"
    36 #include "../../events/SDL_keyboard_c.h"
    37 }
    38 
    39 
    40 static SDL_Scancode WinRT_Official_Keycodes[] = {
    41     SDL_SCANCODE_UNKNOWN, // VirtualKey.None -- 0
    42     SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftButton -- 1
    43     SDL_SCANCODE_UNKNOWN, // VirtualKey.RightButton -- 2
    44     SDL_SCANCODE_CANCEL, // VirtualKey.Cancel -- 3
    45     SDL_SCANCODE_UNKNOWN, // VirtualKey.MiddleButton -- 4
    46     SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton1 -- 5
    47     SDL_SCANCODE_UNKNOWN, // VirtualKey.XButton2 -- 6
    48     SDL_SCANCODE_UNKNOWN, // -- 7
    49     SDL_SCANCODE_BACKSPACE, // VirtualKey.Back -- 8
    50     SDL_SCANCODE_TAB, // VirtualKey.Tab -- 9
    51     SDL_SCANCODE_UNKNOWN, // -- 10
    52     SDL_SCANCODE_UNKNOWN, // -- 11
    53     SDL_SCANCODE_CLEAR, // VirtualKey.Clear -- 12
    54     SDL_SCANCODE_RETURN, // VirtualKey.Enter -- 13
    55     SDL_SCANCODE_UNKNOWN, // -- 14
    56     SDL_SCANCODE_UNKNOWN, // -- 15
    57     SDL_SCANCODE_LSHIFT, // VirtualKey.Shift -- 16
    58     SDL_SCANCODE_LCTRL, // VirtualKey.Control -- 17
    59     SDL_SCANCODE_MENU, // VirtualKey.Menu -- 18
    60     SDL_SCANCODE_PAUSE, // VirtualKey.Pause -- 19
    61     SDL_SCANCODE_CAPSLOCK, // VirtualKey.CapitalLock -- 20
    62     SDL_SCANCODE_UNKNOWN, // VirtualKey.Kana or VirtualKey.Hangul -- 21
    63     SDL_SCANCODE_UNKNOWN, // -- 22
    64     SDL_SCANCODE_UNKNOWN, // VirtualKey.Junja -- 23
    65     SDL_SCANCODE_UNKNOWN, // VirtualKey.Final -- 24
    66     SDL_SCANCODE_UNKNOWN, // VirtualKey.Hanja or VirtualKey.Kanji -- 25
    67     SDL_SCANCODE_UNKNOWN, // -- 26
    68     SDL_SCANCODE_ESCAPE, // VirtualKey.Escape -- 27
    69     SDL_SCANCODE_UNKNOWN, // VirtualKey.Convert -- 28
    70     SDL_SCANCODE_UNKNOWN, // VirtualKey.NonConvert -- 29
    71     SDL_SCANCODE_UNKNOWN, // VirtualKey.Accept -- 30
    72     SDL_SCANCODE_UNKNOWN, // VirtualKey.ModeChange -- 31  (maybe SDL_SCANCODE_MODE ?)
    73     SDL_SCANCODE_SPACE, // VirtualKey.Space -- 32
    74     SDL_SCANCODE_PAGEUP, // VirtualKey.PageUp -- 33
    75     SDL_SCANCODE_PAGEDOWN, // VirtualKey.PageDown -- 34
    76     SDL_SCANCODE_END, // VirtualKey.End -- 35
    77     SDL_SCANCODE_HOME, // VirtualKey.Home -- 36
    78     SDL_SCANCODE_LEFT, // VirtualKey.Left -- 37
    79     SDL_SCANCODE_UP, // VirtualKey.Up -- 38
    80     SDL_SCANCODE_RIGHT, // VirtualKey.Right -- 39
    81     SDL_SCANCODE_DOWN, // VirtualKey.Down -- 40
    82     SDL_SCANCODE_SELECT, // VirtualKey.Select -- 41
    83     SDL_SCANCODE_UNKNOWN, // VirtualKey.Print -- 42  (maybe SDL_SCANCODE_PRINTSCREEN ?)
    84     SDL_SCANCODE_EXECUTE, // VirtualKey.Execute -- 43
    85     SDL_SCANCODE_UNKNOWN, // VirtualKey.Snapshot -- 44
    86     SDL_SCANCODE_INSERT, // VirtualKey.Insert -- 45
    87     SDL_SCANCODE_DELETE, // VirtualKey.Delete -- 46
    88     SDL_SCANCODE_HELP, // VirtualKey.Help -- 47
    89     SDL_SCANCODE_0, // VirtualKey.Number0 -- 48
    90     SDL_SCANCODE_1, // VirtualKey.Number1 -- 49
    91     SDL_SCANCODE_2, // VirtualKey.Number2 -- 50
    92     SDL_SCANCODE_3, // VirtualKey.Number3 -- 51
    93     SDL_SCANCODE_4, // VirtualKey.Number4 -- 52
    94     SDL_SCANCODE_5, // VirtualKey.Number5 -- 53
    95     SDL_SCANCODE_6, // VirtualKey.Number6 -- 54
    96     SDL_SCANCODE_7, // VirtualKey.Number7 -- 55
    97     SDL_SCANCODE_8, // VirtualKey.Number8 -- 56
    98     SDL_SCANCODE_9, // VirtualKey.Number9 -- 57
    99     SDL_SCANCODE_UNKNOWN, // -- 58
   100     SDL_SCANCODE_UNKNOWN, // -- 59
   101     SDL_SCANCODE_UNKNOWN, // -- 60
   102     SDL_SCANCODE_UNKNOWN, // -- 61
   103     SDL_SCANCODE_UNKNOWN, // -- 62
   104     SDL_SCANCODE_UNKNOWN, // -- 63
   105     SDL_SCANCODE_UNKNOWN, // -- 64
   106     SDL_SCANCODE_A, // VirtualKey.A -- 65
   107     SDL_SCANCODE_B, // VirtualKey.B -- 66
   108     SDL_SCANCODE_C, // VirtualKey.C -- 67
   109     SDL_SCANCODE_D, // VirtualKey.D -- 68
   110     SDL_SCANCODE_E, // VirtualKey.E -- 69
   111     SDL_SCANCODE_F, // VirtualKey.F -- 70
   112     SDL_SCANCODE_G, // VirtualKey.G -- 71
   113     SDL_SCANCODE_H, // VirtualKey.H -- 72
   114     SDL_SCANCODE_I, // VirtualKey.I -- 73
   115     SDL_SCANCODE_J, // VirtualKey.J -- 74
   116     SDL_SCANCODE_K, // VirtualKey.K -- 75
   117     SDL_SCANCODE_L, // VirtualKey.L -- 76
   118     SDL_SCANCODE_M, // VirtualKey.M -- 77
   119     SDL_SCANCODE_N, // VirtualKey.N -- 78
   120     SDL_SCANCODE_O, // VirtualKey.O -- 79
   121     SDL_SCANCODE_P, // VirtualKey.P -- 80
   122     SDL_SCANCODE_Q, // VirtualKey.Q -- 81
   123     SDL_SCANCODE_R, // VirtualKey.R -- 82
   124     SDL_SCANCODE_S, // VirtualKey.S -- 83
   125     SDL_SCANCODE_T, // VirtualKey.T -- 84
   126     SDL_SCANCODE_U, // VirtualKey.U -- 85
   127     SDL_SCANCODE_V, // VirtualKey.V -- 86
   128     SDL_SCANCODE_W, // VirtualKey.W -- 87
   129     SDL_SCANCODE_X, // VirtualKey.X -- 88
   130     SDL_SCANCODE_Y, // VirtualKey.Y -- 89
   131     SDL_SCANCODE_Z, // VirtualKey.Z -- 90
   132     SDL_SCANCODE_UNKNOWN, // VirtualKey.LeftWindows -- 91  (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_LGUI ?)
   133     SDL_SCANCODE_UNKNOWN, // VirtualKey.RightWindows -- 92  (maybe SDL_SCANCODE_APPLICATION or SDL_SCANCODE_RGUI ?)
   134     SDL_SCANCODE_APPLICATION, // VirtualKey.Application -- 93
   135     SDL_SCANCODE_UNKNOWN, // -- 94
   136     SDL_SCANCODE_SLEEP, // VirtualKey.Sleep -- 95
   137     SDL_SCANCODE_KP_0, // VirtualKey.NumberPad0 -- 96
   138     SDL_SCANCODE_KP_1, // VirtualKey.NumberPad1 -- 97
   139     SDL_SCANCODE_KP_2, // VirtualKey.NumberPad2 -- 98
   140     SDL_SCANCODE_KP_3, // VirtualKey.NumberPad3 -- 99
   141     SDL_SCANCODE_KP_4, // VirtualKey.NumberPad4 -- 100
   142     SDL_SCANCODE_KP_5, // VirtualKey.NumberPad5 -- 101
   143     SDL_SCANCODE_KP_6, // VirtualKey.NumberPad6 -- 102
   144     SDL_SCANCODE_KP_7, // VirtualKey.NumberPad7 -- 103
   145     SDL_SCANCODE_KP_8, // VirtualKey.NumberPad8 -- 104
   146     SDL_SCANCODE_KP_9, // VirtualKey.NumberPad9 -- 105
   147     SDL_SCANCODE_KP_MULTIPLY, // VirtualKey.Multiply -- 106
   148     SDL_SCANCODE_KP_PLUS, // VirtualKey.Add -- 107
   149     SDL_SCANCODE_UNKNOWN, // VirtualKey.Separator -- 108
   150     SDL_SCANCODE_KP_MINUS, // VirtualKey.Subtract -- 109
   151     SDL_SCANCODE_UNKNOWN, // VirtualKey.Decimal -- 110  (maybe SDL_SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_KP_DECIMAL, or SDL_SCANCODE_KP_PERIOD ?)
   152     SDL_SCANCODE_KP_DIVIDE, // VirtualKey.Divide -- 111
   153     SDL_SCANCODE_F1, // VirtualKey.F1 -- 112
   154     SDL_SCANCODE_F2, // VirtualKey.F2 -- 113
   155     SDL_SCANCODE_F3, // VirtualKey.F3 -- 114
   156     SDL_SCANCODE_F4, // VirtualKey.F4 -- 115
   157     SDL_SCANCODE_F5, // VirtualKey.F5 -- 116
   158     SDL_SCANCODE_F6, // VirtualKey.F6 -- 117
   159     SDL_SCANCODE_F7, // VirtualKey.F7 -- 118
   160     SDL_SCANCODE_F8, // VirtualKey.F8 -- 119
   161     SDL_SCANCODE_F9, // VirtualKey.F9 -- 120
   162     SDL_SCANCODE_F10, // VirtualKey.F10 -- 121
   163     SDL_SCANCODE_F11, // VirtualKey.F11 -- 122
   164     SDL_SCANCODE_F12, // VirtualKey.F12 -- 123
   165     SDL_SCANCODE_F13, // VirtualKey.F13 -- 124
   166     SDL_SCANCODE_F14, // VirtualKey.F14 -- 125
   167     SDL_SCANCODE_F15, // VirtualKey.F15 -- 126
   168     SDL_SCANCODE_F16, // VirtualKey.F16 -- 127
   169     SDL_SCANCODE_F17, // VirtualKey.F17 -- 128
   170     SDL_SCANCODE_F18, // VirtualKey.F18 -- 129
   171     SDL_SCANCODE_F19, // VirtualKey.F19 -- 130
   172     SDL_SCANCODE_F20, // VirtualKey.F20 -- 131
   173     SDL_SCANCODE_F21, // VirtualKey.F21 -- 132
   174     SDL_SCANCODE_F22, // VirtualKey.F22 -- 133
   175     SDL_SCANCODE_F23, // VirtualKey.F23 -- 134
   176     SDL_SCANCODE_F24, // VirtualKey.F24 -- 135
   177     SDL_SCANCODE_UNKNOWN, // -- 136
   178     SDL_SCANCODE_UNKNOWN, // -- 137
   179     SDL_SCANCODE_UNKNOWN, // -- 138
   180     SDL_SCANCODE_UNKNOWN, // -- 139
   181     SDL_SCANCODE_UNKNOWN, // -- 140
   182     SDL_SCANCODE_UNKNOWN, // -- 141
   183     SDL_SCANCODE_UNKNOWN, // -- 142
   184     SDL_SCANCODE_UNKNOWN, // -- 143
   185     SDL_SCANCODE_NUMLOCKCLEAR, // VirtualKey.NumberKeyLock -- 144
   186     SDL_SCANCODE_SCROLLLOCK, // VirtualKey.Scroll -- 145
   187     SDL_SCANCODE_UNKNOWN, // -- 146
   188     SDL_SCANCODE_UNKNOWN, // -- 147
   189     SDL_SCANCODE_UNKNOWN, // -- 148
   190     SDL_SCANCODE_UNKNOWN, // -- 149
   191     SDL_SCANCODE_UNKNOWN, // -- 150
   192     SDL_SCANCODE_UNKNOWN, // -- 151
   193     SDL_SCANCODE_UNKNOWN, // -- 152
   194     SDL_SCANCODE_UNKNOWN, // -- 153
   195     SDL_SCANCODE_UNKNOWN, // -- 154
   196     SDL_SCANCODE_UNKNOWN, // -- 155
   197     SDL_SCANCODE_UNKNOWN, // -- 156
   198     SDL_SCANCODE_UNKNOWN, // -- 157
   199     SDL_SCANCODE_UNKNOWN, // -- 158
   200     SDL_SCANCODE_UNKNOWN, // -- 159
   201     SDL_SCANCODE_LSHIFT, // VirtualKey.LeftShift -- 160
   202     SDL_SCANCODE_RSHIFT, // VirtualKey.RightShift -- 161
   203     SDL_SCANCODE_LCTRL, // VirtualKey.LeftControl -- 162
   204     SDL_SCANCODE_RCTRL, // VirtualKey.RightControl -- 163
   205     SDL_SCANCODE_MENU, // VirtualKey.LeftMenu -- 164
   206     SDL_SCANCODE_MENU, // VirtualKey.RightMenu -- 165
   207     SDL_SCANCODE_AC_BACK, // VirtualKey.GoBack -- 166 : The go back key.
   208     SDL_SCANCODE_AC_FORWARD, // VirtualKey.GoForward -- 167 : The go forward key.
   209     SDL_SCANCODE_AC_REFRESH, // VirtualKey.Refresh -- 168 : The refresh key.
   210     SDL_SCANCODE_AC_STOP, // VirtualKey.Stop -- 169 : The stop key.
   211     SDL_SCANCODE_AC_SEARCH, // VirtualKey.Search -- 170 : The search key.
   212     SDL_SCANCODE_AC_BOOKMARKS, // VirtualKey.Favorites -- 171 : The favorites key.
   213     SDL_SCANCODE_AC_HOME // VirtualKey.GoHome -- 172 : The go home key.
   214 };
   215 
   216 /* Attempt to translate a keycode that isn't listed in WinRT's VirtualKey enum.
   217  */
   218 static SDL_Scancode
   219 WINRT_TranslateUnofficialKeycode(int keycode)
   220 {
   221     switch (keycode) {
   222         case 173: return SDL_SCANCODE_MUTE;
   223         case 174: return SDL_SCANCODE_VOLUMEDOWN;
   224         case 175: return SDL_SCANCODE_VOLUMEUP;
   225         case 176: return SDL_SCANCODE_AUDIONEXT;
   226         case 177: return SDL_SCANCODE_AUDIOPREV;
   227         // case 178: return ;
   228         case 179: return SDL_SCANCODE_AUDIOPLAY;
   229         case 180: return SDL_SCANCODE_MAIL;
   230         case 181: return SDL_SCANCODE_MEDIASELECT;
   231         // case 182: return ;
   232         case 183: return SDL_SCANCODE_CALCULATOR;
   233         // case 184: return ;
   234         // case 185: return ;
   235         case 186: return SDL_SCANCODE_SEMICOLON;
   236         case 187: return SDL_SCANCODE_EQUALS;
   237         case 188: return SDL_SCANCODE_COMMA;
   238         case 189: return SDL_SCANCODE_MINUS;
   239         case 190: return SDL_SCANCODE_PERIOD;
   240         case 191: return SDL_SCANCODE_SLASH;
   241         case 192: return SDL_SCANCODE_GRAVE;
   242         // ?
   243         // ...
   244         // ?
   245         case 219: return SDL_SCANCODE_LEFTBRACKET;
   246         case 220: return SDL_SCANCODE_BACKSLASH;
   247         case 221: return SDL_SCANCODE_RIGHTBRACKET;
   248         case 222: return SDL_SCANCODE_APOSTROPHE;
   249         default: break;
   250     }
   251     return SDL_SCANCODE_UNKNOWN;
   252 }
   253 
   254 static SDL_Scancode
   255 TranslateKeycode(int keycode, unsigned int nativeScancode)
   256 {
   257     // TODO, WinRT: try filling out the WinRT keycode table as much as possible, using the Win32 table for interpretation hints
   258     //SDL_Log("WinRT TranslateKeycode, keycode=%d\n", (int)keycode);
   259     SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
   260 
   261     /* HACK ALERT: At least one VirtualKey constant (Shift) with a left/right
   262      * designation might not get reported with its correct handedness, however
   263      * its hardware scan code can fill in the gaps.  If this is detected,
   264      * use the hardware scan code to try telling if the left, or the right
   265      * side's key was used.
   266      *
   267      * If Microsoft ever allows MapVirtualKey or MapVirtualKeyEx to be used
   268      * in WinRT apps, or something similar to these (it doesn't appear to be,
   269      * at least not for Windows [Phone] 8/8.1, as of Oct 24, 2014), then this
   270      * hack might become deprecated, or obsolete.
   271      */
   272     if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
   273         switch (keycode) {
   274             case 16:    // VirtualKey.Shift
   275                 switch (windows_scancode_table[nativeScancode]) {
   276                     case SDL_SCANCODE_LSHIFT:
   277                     case SDL_SCANCODE_RSHIFT:
   278                         return windows_scancode_table[nativeScancode];
   279                 }
   280                 break;
   281             
   282             // Add others, as necessary.
   283             //
   284             // Unfortunately, this hack doesn't seem to work in determining
   285             // handedness with Control keys.
   286 
   287             default:
   288                 break;
   289         }
   290     }
   291 
   292     /* Try to get a documented, WinRT, 'VirtualKey' next (as documented at
   293        http://msdn.microsoft.com/en-us/library/windows/apps/windows.system.virtualkey.aspx ).
   294        If that fails, fall back to a Win32 virtual key.
   295        If that fails, attempt to fall back to a scancode-derived key.
   296     */
   297     if (keycode < SDL_arraysize(WinRT_Official_Keycodes)) {
   298         scancode = WinRT_Official_Keycodes[keycode];
   299     }
   300     if (scancode == SDL_SCANCODE_UNKNOWN) {
   301         scancode = WINRT_TranslateUnofficialKeycode(keycode);
   302     }
   303     if (scancode == SDL_SCANCODE_UNKNOWN) {
   304         if (nativeScancode < SDL_arraysize(windows_scancode_table)) {
   305             scancode = windows_scancode_table[nativeScancode];
   306         }
   307     }
   308     /*
   309     if (scancode == SDL_SCANCODE_UNKNOWN) {
   310         SDL_Log("WinRT TranslateKeycode, unknown keycode=%d\n", (int)keycode);
   311     }
   312     */
   313     return scancode;
   314 }
   315 
   316 void
   317 WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^args)
   318 {
   319     SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
   320 #if 0
   321     SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
   322     SDL_Log("key down, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
   323             "repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
   324             "sdl scan code=%d (%s), sdl key code=%d (%s)\n",
   325         (args->Handled ? "1" : "0"),
   326         (args->KeyStatus.IsExtendedKey ? "1" : "0"),
   327         (args->KeyStatus.IsKeyReleased ? "1" : "0"),
   328         (args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
   329         args->KeyStatus.RepeatCount,
   330         args->KeyStatus.ScanCode,
   331         (args->KeyStatus.WasKeyDown ? "1" : "0"),
   332         args->VirtualKey,
   333         sdlScancode,
   334         SDL_GetScancodeName(sdlScancode),
   335         keycode,
   336         SDL_GetKeyName(keycode));
   337     //args->Handled = true;
   338     //VirtualKey vkey = args->VirtualKey;
   339 #endif
   340     SDL_SendKeyboardKey(SDL_PRESSED, sdlScancode);
   341 }
   342 
   343 void
   344 WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^args)
   345 {
   346     SDL_Scancode sdlScancode = TranslateKeycode((int)args->VirtualKey, args->KeyStatus.ScanCode);
   347 #if 0
   348     SDL_Keycode keycode = SDL_GetKeyFromScancode(sdlScancode);
   349     SDL_Log("key up, handled=%s, ext?=%s, released?=%s, menu key down?=%s, "
   350             "repeat count=%d, native scan code=0x%x, was down?=%s, vkey=%d, "
   351             "sdl scan code=%d (%s), sdl key code=%d (%s)\n",
   352         (args->Handled ? "1" : "0"),
   353         (args->KeyStatus.IsExtendedKey ? "1" : "0"),
   354         (args->KeyStatus.IsKeyReleased ? "1" : "0"),
   355         (args->KeyStatus.IsMenuKeyDown ? "1" : "0"),
   356         args->KeyStatus.RepeatCount,
   357         args->KeyStatus.ScanCode,
   358         (args->KeyStatus.WasKeyDown ? "1" : "0"),
   359         args->VirtualKey,
   360         sdlScancode,
   361         SDL_GetScancodeName(sdlScancode),
   362         keycode,
   363         SDL_GetKeyName(keycode));
   364     //args->Handled = true;
   365 #endif
   366     SDL_SendKeyboardKey(SDL_RELEASED, sdlScancode);
   367 }
   368 
   369 #endif // SDL_VIDEO_DRIVER_WINRT