1 //--------------------------------------------------------------------------------------
2 // File: Keyboard.h
3 //
4 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
6 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
7 // PARTICULAR PURPOSE.
8 //
9 // Copyright (c) Microsoft Corporation. All rights reserved.
10 //
11 // http://go.microsoft.com/fwlink/?LinkId=248929
12 //--------------------------------------------------------------------------------------
13 
14 #pragma once
15 
16 // VS 2010/2012 do not support =default =delete
17 #ifndef DIRECTX_CTOR_DEFAULT
18 #if defined(_MSC_VER) && (_MSC_VER < 1800)
19 #define DIRECTX_CTOR_DEFAULT {}
20 #define DIRECTX_CTOR_DELETE ;
21 #else
22 #define DIRECTX_CTOR_DEFAULT =default;
23 #define DIRECTX_CTOR_DELETE =delete;
24 #endif
25 #endif
26 
27 #pragma warning(push)
28 #pragma warning(disable : 4005)
29 #include <stdint.h>
30 #pragma warning(pop)
31 
32 #include <memory>
33 
34 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
35 namespace ABI { namespace Windows { namespace UI { namespace Core { struct ICoreWindow; } } } }
36 #endif
37 
38 
39 namespace DirectX
40 {
41     class Keyboard
42     {
43     public:
44         Keyboard();
45         Keyboard(Keyboard&& moveFrom);
46         Keyboard& operator= (Keyboard&& moveFrom);
47         virtual ~Keyboard();
48 
49         enum Keys
50         {
51             None                = 0,
52 
53             Back                = 0x8,
54             Tab                 = 0x9,
55 
56             Enter               = 0xd,
57 
58             Pause               = 0x13,
59             CapsLock            = 0x14,
60             Kana                = 0x15,
61 
62             Kanji               = 0x19,
63 
64             Escape              = 0x1b,
65             ImeConvert          = 0x1c,
66             ImeNoConvert        = 0x1d,
67 
68             Space               = 0x20,
69             PageUp              = 0x21,
70             PageDown            = 0x22,
71             End                 = 0x23,
72             Home                = 0x24,
73             Left                = 0x25,
74             Up                  = 0x26,
75             Right               = 0x27,
76             Down                = 0x28,
77             Select              = 0x29,
78             Print               = 0x2a,
79             Execute             = 0x2b,
80             PrintScreen         = 0x2c,
81             Insert              = 0x2d,
82             Delete              = 0x2e,
83             Help                = 0x2f,
84             D0                  = 0x30,
85             D1                  = 0x31,
86             D2                  = 0x32,
87             D3                  = 0x33,
88             D4                  = 0x34,
89             D5                  = 0x35,
90             D6                  = 0x36,
91             D7                  = 0x37,
92             D8                  = 0x38,
93             D9                  = 0x39,
94 
95             A                   = 0x41,
96             B                   = 0x42,
97             C                   = 0x43,
98             D                   = 0x44,
99             E                   = 0x45,
100             F                   = 0x46,
101             G                   = 0x47,
102             H                   = 0x48,
103             I                   = 0x49,
104             J                   = 0x4a,
105             K                   = 0x4b,
106             L                   = 0x4c,
107             M                   = 0x4d,
108             N                   = 0x4e,
109             O                   = 0x4f,
110             P                   = 0x50,
111             Q                   = 0x51,
112             R                   = 0x52,
113             S                   = 0x53,
114             T                   = 0x54,
115             U                   = 0x55,
116             V                   = 0x56,
117             W                   = 0x57,
118             X                   = 0x58,
119             Y                   = 0x59,
120             Z                   = 0x5a,
121             LeftWindows         = 0x5b,
122             RightWindows        = 0x5c,
123             Apps                = 0x5d,
124 
125             Sleep               = 0x5f,
126             NumPad0             = 0x60,
127             NumPad1             = 0x61,
128             NumPad2             = 0x62,
129             NumPad3             = 0x63,
130             NumPad4             = 0x64,
131             NumPad5             = 0x65,
132             NumPad6             = 0x66,
133             NumPad7             = 0x67,
134             NumPad8             = 0x68,
135             NumPad9             = 0x69,
136             Multiply            = 0x6a,
137             Add                 = 0x6b,
138             Separator           = 0x6c,
139             Subtract            = 0x6d,
140 
141             Decimal             = 0x6e,
142             Divide              = 0x6f,
143             F1                  = 0x70,
144             F2                  = 0x71,
145             F3                  = 0x72,
146             F4                  = 0x73,
147             F5                  = 0x74,
148             F6                  = 0x75,
149             F7                  = 0x76,
150             F8                  = 0x77,
151             F9                  = 0x78,
152             F10                 = 0x79,
153             F11                 = 0x7a,
154             F12                 = 0x7b,
155             F13                 = 0x7c,
156             F14                 = 0x7d,
157             F15                 = 0x7e,
158             F16                 = 0x7f,
159             F17                 = 0x80,
160             F18                 = 0x81,
161             F19                 = 0x82,
162             F20                 = 0x83,
163             F21                 = 0x84,
164             F22                 = 0x85,
165             F23                 = 0x86,
166             F24                 = 0x87,
167 
168             NumLock             = 0x90,
169             Scroll              = 0x91,
170 
171             LeftShift           = 0xa0,
172             RightShift          = 0xa1,
173             LeftControl         = 0xa2,
174             RightControl        = 0xa3,
175             LeftAlt             = 0xa4,
176             RightAlt            = 0xa5,
177             BrowserBack         = 0xa6,
178             BrowserForward      = 0xa7,
179             BrowserRefresh      = 0xa8,
180             BrowserStop         = 0xa9,
181             BrowserSearch       = 0xaa,
182             BrowserFavorites    = 0xab,
183             BrowserHome         = 0xac,
184             VolumeMute          = 0xad,
185             VolumeDown          = 0xae,
186             VolumeUp            = 0xaf,
187             MediaNextTrack      = 0xb0,
188             MediaPreviousTrack  = 0xb1,
189             MediaStop           = 0xb2,
190             MediaPlayPause      = 0xb3,
191             LaunchMail          = 0xb4,
192             SelectMedia         = 0xb5,
193             LaunchApplication1  = 0xb6,
194             LaunchApplication2  = 0xb7,
195 
196             OemSemicolon        = 0xba,
197             OemPlus             = 0xbb,
198             OemComma            = 0xbc,
199             OemMinus            = 0xbd,
200             OemPeriod           = 0xbe,
201             OemQuestion         = 0xbf,
202             OemTilde            = 0xc0,
203 
204             OemOpenBrackets     = 0xdb,
205             OemPipe             = 0xdc,
206             OemCloseBrackets    = 0xdd,
207             OemQuotes           = 0xde,
208             Oem8                = 0xdf,
209 
210             OemBackslash        = 0xe2,
211 
212             ProcessKey          = 0xe5,
213 
214             OemCopy             = 0xf2,
215             OemAuto             = 0xf3,
216             OemEnlW             = 0xf4,
217 
218             Attn                = 0xf6,
219             Crsel               = 0xf7,
220             Exsel               = 0xf8,
221             EraseEof            = 0xf9,
222             Play                = 0xfa,
223             Zoom                = 0xfb,
224 
225             Pa1                 = 0xfd,
226             OemClear            = 0xfe,
227         };
228 
229         struct State
230         {
231             bool Reserved0 : 8;
232             bool Back : 1;              // VK_BACK, 0x8
233             bool Tab : 1;               // VK_TAB, 0x9
234             bool Reserved1 : 3;
235             bool Enter : 1;             // VK_RETURN, 0xD
236             bool Reserved2 : 2;
237             bool Reserved3 : 3;
238             bool Pause : 1;             // VK_PAUSE, 0x13
239             bool CapsLock : 1;          // VK_CAPITAL, 0x14
240             bool Kana : 1;              // VK_KANA, 0x15
241             bool Reserved4 : 2;
242             bool Reserved5 : 1;
243             bool Kanji : 1;             // VK_KANJI, 0x19
244             bool Reserved6 : 1;
245             bool Escape : 1;            // VK_ESCAPE, 0x1B
246             bool ImeConvert : 1;        // VK_CONVERT, 0x1C
247             bool ImeNoConvert : 1;      // VK_NONCONVERT, 0x1D
248             bool Reserved7 : 2;
249             bool Space : 1;             // VK_SPACE, 0x20
250             bool PageUp : 1;            // VK_PRIOR, 0x21
251             bool PageDown : 1;          // VK_NEXT, 0x22
252             bool End : 1;               // VK_END, 0x23
253             bool Home : 1;              // VK_HOME, 0x24
254             bool Left : 1;              // VK_LEFT, 0x25
255             bool Up : 1;                // VK_UP, 0x26
256             bool Right : 1;             // VK_RIGHT, 0x27
257             bool Down : 1;              // VK_DOWN, 0x28
258             bool Select : 1;            // VK_SELECT, 0x29
259             bool Print : 1;             // VK_PRINT, 0x2A
260             bool Execute : 1;           // VK_EXECUTE, 0x2B
261             bool PrintScreen : 1;       // VK_SNAPSHOT, 0x2C
262             bool Insert : 1;            // VK_INSERT, 0x2D
263             bool Delete : 1;            // VK_DELETE, 0x2E
264             bool Help : 1;              // VK_HELP, 0x2F
265             bool D0 : 1;                // 0x30
266             bool D1 : 1;                // 0x31
267             bool D2 : 1;                // 0x32
268             bool D3 : 1;                // 0x33
269             bool D4 : 1;                // 0x34
270             bool D5 : 1;                // 0x35
271             bool D6 : 1;                // 0x36
272             bool D7 : 1;                // 0x37
273             bool D8 : 1;                // 0x38
274             bool D9 : 1;                // 0x39
275             bool Reserved8 : 6;
276             bool Reserved9 : 1;
277             bool A : 1;                 // 0x41
278             bool B : 1;                 // 0x42
279             bool C : 1;                 // 0x43
280             bool D : 1;                 // 0x44
281             bool E : 1;                 // 0x45
282             bool F : 1;                 // 0x46
283             bool G : 1;                 // 0x47
284             bool H : 1;                 // 0x48
285             bool I : 1;                 // 0x49
286             bool J : 1;                 // 0x4A
287             bool K : 1;                 // 0x4B
288             bool L : 1;                 // 0x4C
289             bool M : 1;                 // 0x4D
290             bool N : 1;                 // 0x4E
291             bool O : 1;                 // 0x4F
292             bool P : 1;                 // 0x50
293             bool Q : 1;                 // 0x51
294             bool R : 1;                 // 0x52
295             bool S : 1;                 // 0x53
296             bool T : 1;                 // 0x54
297             bool U : 1;                 // 0x55
298             bool V : 1;                 // 0x56
299             bool W : 1;                 // 0x57
300             bool X : 1;                 // 0x58
301             bool Y : 1;                 // 0x59
302             bool Z : 1;                 // 0x5A
303             bool LeftWindows : 1;       // VK_LWIN, 0x5B
304             bool RightWindows : 1;      // VK_RWIN, 0x5C
305             bool Apps : 1;              // VK_APPS, 0x5D
306             bool Reserved10 : 1;
307             bool Sleep : 1;             // VK_SLEEP, 0x5F
308             bool NumPad0 : 1;           // VK_NUMPAD0, 0x60
309             bool NumPad1 : 1;           // VK_NUMPAD1, 0x61
310             bool NumPad2 : 1;           // VK_NUMPAD2, 0x62
311             bool NumPad3 : 1;           // VK_NUMPAD3, 0x63
312             bool NumPad4 : 1;           // VK_NUMPAD4, 0x64
313             bool NumPad5 : 1;           // VK_NUMPAD5, 0x65
314             bool NumPad6 : 1;           // VK_NUMPAD6, 0x66
315             bool NumPad7 : 1;           // VK_NUMPAD7, 0x67
316             bool NumPad8 : 1;           // VK_NUMPAD8, 0x68
317             bool NumPad9 : 1;           // VK_NUMPAD9, 0x69
318             bool Multiply : 1;          // VK_MULTIPLY, 0x6A
319             bool Add : 1;               // VK_ADD, 0x6B
320             bool Separator : 1;         // VK_SEPARATOR, 0x6C
321             bool Subtract : 1;          // VK_SUBTRACT, 0x6D
322             bool Decimal : 1;           // VK_DECIMANL, 0x6E
323             bool Divide : 1;            // VK_DIVIDE, 0x6F
324             bool F1 : 1;                // VK_F1, 0x70
325             bool F2 : 1;                // VK_F2, 0x71
326             bool F3 : 1;                // VK_F3, 0x72
327             bool F4 : 1;                // VK_F4, 0x73
328             bool F5 : 1;                // VK_F5, 0x74
329             bool F6 : 1;                // VK_F6, 0x75
330             bool F7 : 1;                // VK_F7, 0x76
331             bool F8 : 1;                // VK_F8, 0x77
332             bool F9 : 1;                // VK_F9, 0x78
333             bool F10 : 1;               // VK_F10, 0x79
334             bool F11 : 1;               // VK_F11, 0x7A
335             bool F12 : 1;               // VK_F12, 0x7B
336             bool F13 : 1;               // VK_F13, 0x7C
337             bool F14 : 1;               // VK_F14, 0x7D
338             bool F15 : 1;               // VK_F15, 0x7E
339             bool F16 : 1;               // VK_F16, 0x7F
340             bool F17 : 1;               // VK_F17, 0x80
341             bool F18 : 1;               // VK_F18, 0x81
342             bool F19 : 1;               // VK_F19, 0x82
343             bool F20 : 1;               // VK_F20, 0x83
344             bool F21 : 1;               // VK_F21, 0x84
345             bool F22 : 1;               // VK_F22, 0x85
346             bool F23 : 1;               // VK_F23, 0x86
347             bool F24 : 1;               // VK_F24, 0x87
348             bool Reserved11 : 8;
349             bool NumLock : 1;           // VK_NUMLOCK, 0x90
350             bool Scroll : 1;            // VK_SCROLL, 0x91
351             bool Reserved12 : 6;
352             bool Reserved13 : 8;
353             bool LeftShift : 1;         // VK_LSHIFT, 0xA0
354             bool RightShift : 1;        // VK_RSHIFT, 0xA1
355             bool LeftControl : 1;       // VK_LCONTROL, 0xA2
356             bool RightControl : 1;      // VK_RCONTROL, 0xA3
357             bool LeftAlt : 1;           // VK_LMENU, 0xA4
358             bool RightAlt : 1;          // VK_RMENU, 0xA5
359             bool BrowserBack : 1;       // VK_BROWSER_BACK, 0xA6
360             bool BrowserForward : 1;    // VK_BROWSER_FORWARD, 0xA7
361             bool BrowserRefresh : 1;    // VK_BROWSER_REFRESH, 0xA8
362             bool BrowserStop : 1;       // VK_BROWSER_STOP, 0xA9
363             bool BrowserSearch : 1;     // VK_BROWSER_SEARCH, 0xAA
364             bool BrowserFavorites : 1;  // VK_BROWSER_FAVORITES, 0xAB
365             bool BrowserHome : 1;       // VK_BROWSER_HOME, 0xAC
366             bool VolumeMute : 1;        // VK_VOLUME_MUTE, 0xAD
367             bool VolumeDown : 1;        // VK_VOLUME_DOWN, 0xAE
368             bool VolumeUp : 1;          // VK_VOLUME_UP, 0xAF
369             bool MediaNextTrack : 1;    // VK_MEDIA_NEXT_TRACK, 0xB0
370             bool MediaPreviousTrack : 1;// VK_MEDIA_PREV_TRACK, 0xB1
371             bool MediaStop : 1;         // VK_MEDIA_STOP, 0xB2
372             bool MediaPlayPause : 1;    // VK_MEDIA_PLAY_PAUSE, 0xB3
373             bool LaunchMail : 1;        // VK_LAUNCH_MAIL, 0xB4
374             bool SelectMedia : 1;       // VK_LAUNCH_MEDIA_SELECT, 0xB5
375             bool LaunchApplication1 : 1;// VK_LAUNCH_APP1, 0xB6
376             bool LaunchApplication2 : 1;// VK_LAUNCH_APP2, 0xB7
377             bool Reserved14 : 2;
378             bool OemSemicolon : 1;      // VK_OEM_1, 0xBA
379             bool OemPlus : 1;           // VK_OEM_PLUS, 0xBB
380             bool OemComma : 1;          // VK_OEM_COMMA, 0xBC
381             bool OemMinus : 1;          // VK_OEM_MINUS, 0xBD
382             bool OemPeriod : 1;         // VK_OEM_PERIOD, 0xBE
383             bool OemQuestion : 1;       // VK_OEM_2, 0xBF
384             bool OemTilde : 1;          // VK_OEM_3, 0xC0
385             bool Reserved15 : 7;
386             bool Reserved16 : 8;
387             bool Reserved17 : 8;
388             bool Reserved18 : 3;
389             bool OemOpenBrackets : 1;   // VK_OEM_4, 0xDB
390             bool OemPipe : 1;           // VK_OEM_5, 0xDC
391             bool OemCloseBrackets : 1;  // VK_OEM_6, 0xDD
392             bool OemQuotes : 1;         // VK_OEM_7, 0xDE
393             bool Oem8 : 1;              // VK_OEM_8, 0xDF
394             bool Reserved19 : 2;
395             bool OemBackslash : 1;      // VK_OEM_102, 0xE2
396             bool Reserved20 : 2;
397             bool ProcessKey : 1;        // VK_PROCESSKEY, 0xE5
398             bool Reserved21 : 2;
399             bool Reserved22 : 8;
400             bool Reserved23 : 2;
401             bool OemCopy : 1;           // 0XF2
402             bool OemAuto : 1;           // 0xF3
403             bool OemEnlW : 1;           // 0xF4
404             bool Reserved24 : 1;
405             bool Attn : 1;              // VK_ATTN, 0xF6
406             bool Crsel : 1;             // VK_CRSEL, 0xF7
407             bool Exsel : 1;             // VK_EXSEL, 0xF8
408             bool EraseEof : 1;          // VK_EREOF, 0xF9
409             bool Play : 1;              // VK_PLAY, 0xFA
410             bool Zoom : 1;              // VK_ZOOM, 0xFB
411             bool Reserved25 : 1;
412             bool Pa1 : 1;               // VK_PA1, 0xFD
413             bool OemClear : 1;          // VK_OEM_CLEAR, 0xFE
414             bool Reserved26: 1;
415 
IsKeyDownState416             bool __cdecl IsKeyDown(Keys key) const
417             {
418                 if (key >= 0 && key <= 0xff)
419                 {
420                     auto ptr = reinterpret_cast<const uint32_t*>(this);
421                     unsigned int bf = 1u << (key & 0x1f);
422                     return (ptr[(key >> 5)] & bf) != 0;
423                 }
424                 return false;
425             }
426 
IsKeyUpState427             bool __cdecl IsKeyUp(Keys key) const
428             {
429                 if (key >= 0 && key <= 0xfe)
430                 {
431                     auto ptr = reinterpret_cast<const uint32_t*>(this);
432                     unsigned int bf = 1u << (key & 0x1f);
433                     return (ptr[(key >> 5)] & bf) == 0;
434                 }
435                 return false;
436             }
437         };
438 
439         class KeyboardStateTracker
440         {
441         public:
442             State released;
443             State pressed;
444 
KeyboardStateTracker()445             KeyboardStateTracker() { Reset(); }
446 
447             void __cdecl Update(const State& state);
448 
449             void __cdecl Reset();
450 
IsKeyPressed(Keys key)451             bool __cdecl IsKeyPressed(Keys key) const { return pressed.IsKeyDown(key); }
IsKeyReleased(Keys key)452             bool __cdecl IsKeyReleased(Keys key) const { return released.IsKeyDown(key); }
453 
454         public:
455             State lastState;
456         };
457 
458         // Retrieve the current state of the keyboard
459         State __cdecl GetState() const;
460 
461         // Reset the keyboard state
462         void __cdecl Reset();
463 
464 #if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) && defined(WM_USER)
465         static void __cdecl ProcessMessage(UINT message, WPARAM wParam, LPARAM lParam);
466 #endif
467 
468 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
469         void __cdecl SetWindow(ABI::Windows::UI::Core::ICoreWindow* window);
470 #ifdef __cplusplus_winrt
471         void __cdecl SetWindow(Windows::UI::Core::CoreWindow^ window)
472         {
473             // See https://msdn.microsoft.com/en-us/library/hh755802.aspx
474             SetWindow(reinterpret_cast<ABI::Windows::UI::Core::ICoreWindow*>(window));
475         }
476 #endif
477 #endif
478 
479         // Singleton
480         static Keyboard& __cdecl Get();
481 
482     private:
483         // Private implementation.
484         class Impl;
485 
486         std::unique_ptr<Impl> pImpl;
487 
488         // Prevent copying.
489         Keyboard(Keyboard const&) DIRECTX_CTOR_DELETE
490         Keyboard& operator=(Keyboard const&) DIRECTX_CTOR_DELETE
491     };
492 }
493