1 /**
2  * Copyright (c) 2006-2019 LOVE Development Team
3  *
4  * This software is provided 'as-is', without any express or implied
5  * warranty.  In no event will the authors be held liable for any damages
6  * arising from the use of this software.
7  *
8  * Permission is granted to anyone to use this software for any purpose,
9  * including commercial applications, and to alter it and redistribute it
10  * freely, subject to the following restrictions:
11  *
12  * 1. The origin of this software must not be misrepresented; you must not
13  *    claim that you wrote the original software. If you use this software
14  *    in a product, an acknowledgment in the product documentation would be
15  *    appreciated but is not required.
16  * 2. Altered source versions must be plainly marked as such, and must not be
17  *    misrepresented as being the original software.
18  * 3. This notice may not be removed or altered from any source distribution.
19  **/
20 
21 #include "Keyboard.h"
22 #include "window/Window.h"
23 
24 namespace love
25 {
26 namespace keyboard
27 {
28 namespace sdl
29 {
30 
Keyboard()31 Keyboard::Keyboard()
32 	: key_repeat(false)
33 {
34 }
35 
getName() const36 const char *Keyboard::getName() const
37 {
38 	return "love.keyboard.sdl";
39 }
40 
setKeyRepeat(bool enable)41 void Keyboard::setKeyRepeat(bool enable)
42 {
43 	key_repeat = enable;
44 }
45 
hasKeyRepeat() const46 bool Keyboard::hasKeyRepeat() const
47 {
48 	return key_repeat;
49 }
50 
isDown(const std::vector<Key> & keylist) const51 bool Keyboard::isDown(const std::vector<Key> &keylist) const
52 {
53 	const Uint8 *state = SDL_GetKeyboardState(nullptr);
54 
55 	for (Key key : keylist)
56 	{
57 		SDL_Scancode scancode = SDL_GetScancodeFromKey(keymap[key]);
58 
59 		if (state[scancode])
60 			return true;
61 	}
62 
63 	return false;
64 }
65 
isScancodeDown(const std::vector<Scancode> & scancodelist) const66 bool Keyboard::isScancodeDown(const std::vector<Scancode> &scancodelist) const
67 {
68 	const Uint8 *state = SDL_GetKeyboardState(nullptr);
69 
70 	for (Scancode scancode : scancodelist)
71 	{
72 		SDL_Scancode sdlcode = SDL_SCANCODE_UNKNOWN;
73 
74 		if (scancodes.find(scancode, sdlcode) && state[sdlcode])
75 			return true;
76 	}
77 
78 	return false;
79 }
80 
getKeyFromScancode(Scancode scancode) const81 Keyboard::Key Keyboard::getKeyFromScancode(Scancode scancode) const
82 {
83 	SDL_Scancode sdlscancode = SDL_SCANCODE_UNKNOWN;
84 	scancodes.find(scancode, sdlscancode);
85 
86 	SDL_Keycode sdlkey = SDL_GetKeyFromScancode(sdlscancode);
87 
88 	for (int i = 0; i < KEY_MAX_ENUM; i++)
89 	{
90 		if (keymap[i] == sdlkey)
91 			return (Key) i;
92 	}
93 
94 	return KEY_UNKNOWN;
95 }
96 
getScancodeFromKey(Key key) const97 Keyboard::Scancode Keyboard::getScancodeFromKey(Key key) const
98 {
99 	Scancode scancode = SCANCODE_UNKNOWN;
100 
101 	if (key != KEY_MAX_ENUM)
102 	{
103 		SDL_Keycode sdlkey = keymap[key];
104 
105 		SDL_Scancode sdlscancode = SDL_GetScancodeFromKey(sdlkey);
106 		scancodes.find(sdlscancode, scancode);
107 	}
108 
109 	return scancode;
110 }
111 
setTextInput(bool enable)112 void Keyboard::setTextInput(bool enable)
113 {
114 	if (enable)
115 		SDL_StartTextInput();
116 	else
117 		SDL_StopTextInput();
118 }
119 
setTextInput(bool enable,double x,double y,double w,double h)120 void Keyboard::setTextInput(bool enable, double x, double y, double w, double h)
121 {
122 	// SDL_SetTextInputRect expects coordinates in window-space but setTextInput
123 	// takes pixels, so we should convert.
124 	auto window = Module::getInstance<window::Window>(M_WINDOW);
125 	if (window)
126 	{
127 		window->DPIToWindowCoords(&x, &y);
128 		window->DPIToWindowCoords(&w, &h);
129 	}
130 
131 	SDL_Rect rect = {(int) x, (int) y, (int) w, (int) h};
132 	SDL_SetTextInputRect(&rect);
133 
134 	setTextInput(enable);
135 }
136 
hasTextInput() const137 bool Keyboard::hasTextInput() const
138 {
139 	return SDL_IsTextInputActive() != SDL_FALSE;
140 }
141 
hasScreenKeyboard() const142 bool Keyboard::hasScreenKeyboard() const
143 {
144 	return SDL_HasScreenKeyboardSupport() != SDL_FALSE;
145 }
146 
getConstant(Scancode in,SDL_Scancode & out)147 bool Keyboard::getConstant(Scancode in, SDL_Scancode &out)
148 {
149 	return scancodes.find(in, out);
150 }
151 
getConstant(SDL_Scancode in,Scancode & out)152 bool Keyboard::getConstant(SDL_Scancode in, Scancode &out)
153 {
154 	return scancodes.find(in, out);
155 }
156 
createKeyMap()157 const SDL_Keycode *Keyboard::createKeyMap()
158 {
159 	// Array must be static so its lifetime continues once the function returns.
160 	static SDL_Keycode k[Keyboard::KEY_MAX_ENUM] = {SDLK_UNKNOWN};
161 
162 	k[Keyboard::KEY_UNKNOWN] = SDLK_UNKNOWN;
163 
164 	k[Keyboard::KEY_RETURN] = SDLK_RETURN;
165 	k[Keyboard::KEY_ESCAPE] = SDLK_ESCAPE;
166 	k[Keyboard::KEY_BACKSPACE] = SDLK_BACKSPACE;
167 	k[Keyboard::KEY_TAB] = SDLK_TAB;
168 	k[Keyboard::KEY_SPACE] = SDLK_SPACE;
169 	k[Keyboard::KEY_EXCLAIM] = SDLK_EXCLAIM;
170 	k[Keyboard::KEY_QUOTEDBL] = SDLK_QUOTEDBL;
171 	k[Keyboard::KEY_HASH] = SDLK_HASH;
172 	k[Keyboard::KEY_PERCENT] = SDLK_PERCENT;
173 	k[Keyboard::KEY_DOLLAR] = SDLK_DOLLAR;
174 	k[Keyboard::KEY_AMPERSAND] = SDLK_AMPERSAND;
175 	k[Keyboard::KEY_QUOTE] = SDLK_QUOTE;
176 	k[Keyboard::KEY_LEFTPAREN] = SDLK_LEFTPAREN;
177 	k[Keyboard::KEY_RIGHTPAREN] = SDLK_RIGHTPAREN;
178 	k[Keyboard::KEY_ASTERISK] = SDLK_ASTERISK;
179 	k[Keyboard::KEY_PLUS] = SDLK_PLUS;
180 	k[Keyboard::KEY_COMMA] = SDLK_COMMA;
181 	k[Keyboard::KEY_MINUS] = SDLK_MINUS;
182 	k[Keyboard::KEY_PERIOD] = SDLK_PERIOD;
183 	k[Keyboard::KEY_SLASH] = SDLK_SLASH;
184 	k[Keyboard::KEY_0] = SDLK_0;
185 	k[Keyboard::KEY_1] = SDLK_1;
186 	k[Keyboard::KEY_2] = SDLK_2;
187 	k[Keyboard::KEY_3] = SDLK_3;
188 	k[Keyboard::KEY_4] = SDLK_4;
189 	k[Keyboard::KEY_5] = SDLK_5;
190 	k[Keyboard::KEY_6] = SDLK_6;
191 	k[Keyboard::KEY_7] = SDLK_7;
192 	k[Keyboard::KEY_8] = SDLK_8;
193 	k[Keyboard::KEY_9] = SDLK_9;
194 	k[Keyboard::KEY_COLON] = SDLK_COLON;
195 	k[Keyboard::KEY_SEMICOLON] = SDLK_SEMICOLON;
196 	k[Keyboard::KEY_LESS] = SDLK_LESS;
197 	k[Keyboard::KEY_EQUALS] = SDLK_EQUALS;
198 	k[Keyboard::KEY_GREATER] = SDLK_GREATER;
199 	k[Keyboard::KEY_QUESTION] = SDLK_QUESTION;
200 	k[Keyboard::KEY_AT] = SDLK_AT;
201 
202 	k[Keyboard::KEY_LEFTBRACKET] = SDLK_LEFTBRACKET;
203 	k[Keyboard::KEY_BACKSLASH] = SDLK_BACKSLASH;
204 	k[Keyboard::KEY_RIGHTBRACKET] = SDLK_RIGHTBRACKET;
205 	k[Keyboard::KEY_CARET] = SDLK_CARET;
206 	k[Keyboard::KEY_UNDERSCORE] = SDLK_UNDERSCORE;
207 	k[Keyboard::KEY_BACKQUOTE] = SDLK_BACKQUOTE;
208 	k[Keyboard::KEY_A] = SDLK_a;
209 	k[Keyboard::KEY_B] = SDLK_b;
210 	k[Keyboard::KEY_C] = SDLK_c;
211 	k[Keyboard::KEY_D] = SDLK_d;
212 	k[Keyboard::KEY_E] = SDLK_e;
213 	k[Keyboard::KEY_F] = SDLK_f;
214 	k[Keyboard::KEY_G] = SDLK_g;
215 	k[Keyboard::KEY_H] = SDLK_h;
216 	k[Keyboard::KEY_I] = SDLK_i;
217 	k[Keyboard::KEY_J] = SDLK_j;
218 	k[Keyboard::KEY_K] = SDLK_k;
219 	k[Keyboard::KEY_L] = SDLK_l;
220 	k[Keyboard::KEY_M] = SDLK_m;
221 	k[Keyboard::KEY_N] = SDLK_n;
222 	k[Keyboard::KEY_O] = SDLK_o;
223 	k[Keyboard::KEY_P] = SDLK_p;
224 	k[Keyboard::KEY_Q] = SDLK_q;
225 	k[Keyboard::KEY_R] = SDLK_r;
226 	k[Keyboard::KEY_S] = SDLK_s;
227 	k[Keyboard::KEY_T] = SDLK_t;
228 	k[Keyboard::KEY_U] = SDLK_u;
229 	k[Keyboard::KEY_V] = SDLK_v;
230 	k[Keyboard::KEY_W] = SDLK_w;
231 	k[Keyboard::KEY_X] = SDLK_x;
232 	k[Keyboard::KEY_Y] = SDLK_y;
233 	k[Keyboard::KEY_Z] = SDLK_z;
234 
235 	k[Keyboard::KEY_CAPSLOCK] = SDLK_CAPSLOCK;
236 
237 	k[Keyboard::KEY_F1] = SDLK_F1;
238 	k[Keyboard::KEY_F2] = SDLK_F2;
239 	k[Keyboard::KEY_F3] = SDLK_F3;
240 	k[Keyboard::KEY_F4] = SDLK_F4;
241 	k[Keyboard::KEY_F5] = SDLK_F5;
242 	k[Keyboard::KEY_F6] = SDLK_F6;
243 	k[Keyboard::KEY_F7] = SDLK_F7;
244 	k[Keyboard::KEY_F8] = SDLK_F8;
245 	k[Keyboard::KEY_F9] = SDLK_F9;
246 	k[Keyboard::KEY_F10] = SDLK_F10;
247 	k[Keyboard::KEY_F11] = SDLK_F11;
248 	k[Keyboard::KEY_F12] = SDLK_F12;
249 
250 	k[Keyboard::KEY_PRINTSCREEN] = SDLK_PRINTSCREEN;
251 	k[Keyboard::KEY_SCROLLLOCK] = SDLK_SCROLLLOCK;
252 	k[Keyboard::KEY_PAUSE] = SDLK_PAUSE;
253 	k[Keyboard::KEY_INSERT] = SDLK_INSERT;
254 	k[Keyboard::KEY_HOME] = SDLK_HOME;
255 	k[Keyboard::KEY_PAGEUP] = SDLK_PAGEUP;
256 	k[Keyboard::KEY_DELETE] = SDLK_DELETE;
257 	k[Keyboard::KEY_END] = SDLK_END;
258 	k[Keyboard::KEY_PAGEDOWN] = SDLK_PAGEDOWN;
259 	k[Keyboard::KEY_RIGHT] = SDLK_RIGHT;
260 	k[Keyboard::KEY_LEFT] = SDLK_LEFT;
261 	k[Keyboard::KEY_DOWN] = SDLK_DOWN;
262 	k[Keyboard::KEY_UP] = SDLK_UP;
263 
264 	k[Keyboard::KEY_NUMLOCKCLEAR] = SDLK_NUMLOCKCLEAR;
265 	k[Keyboard::KEY_KP_DIVIDE] = SDLK_KP_DIVIDE;
266 	k[Keyboard::KEY_KP_MULTIPLY] = SDLK_KP_MULTIPLY;
267 	k[Keyboard::KEY_KP_MINUS] = SDLK_KP_MINUS;
268 	k[Keyboard::KEY_KP_PLUS] = SDLK_KP_PLUS;
269 	k[Keyboard::KEY_KP_ENTER] = SDLK_KP_ENTER;
270 	k[Keyboard::KEY_KP_0] = SDLK_KP_0;
271 	k[Keyboard::KEY_KP_1] = SDLK_KP_1;
272 	k[Keyboard::KEY_KP_2] = SDLK_KP_2;
273 	k[Keyboard::KEY_KP_3] = SDLK_KP_3;
274 	k[Keyboard::KEY_KP_4] = SDLK_KP_4;
275 	k[Keyboard::KEY_KP_5] = SDLK_KP_5;
276 	k[Keyboard::KEY_KP_6] = SDLK_KP_6;
277 	k[Keyboard::KEY_KP_7] = SDLK_KP_7;
278 	k[Keyboard::KEY_KP_8] = SDLK_KP_8;
279 	k[Keyboard::KEY_KP_9] = SDLK_KP_9;
280 	k[Keyboard::KEY_KP_PERIOD] = SDLK_KP_PERIOD;
281 	k[Keyboard::KEY_KP_COMMA] = SDLK_KP_COMMA;
282 	k[Keyboard::KEY_KP_EQUALS] = SDLK_KP_EQUALS;
283 
284 	k[Keyboard::KEY_APPLICATION] = SDLK_APPLICATION;
285 	k[Keyboard::KEY_POWER] = SDLK_POWER;
286 	k[Keyboard::KEY_F13] = SDLK_F13;
287 	k[Keyboard::KEY_F14] = SDLK_F14;
288 	k[Keyboard::KEY_F15] = SDLK_F15;
289 	k[Keyboard::KEY_F16] = SDLK_F16;
290 	k[Keyboard::KEY_F17] = SDLK_F17;
291 	k[Keyboard::KEY_F18] = SDLK_F18;
292 	k[Keyboard::KEY_F19] = SDLK_F19;
293 	k[Keyboard::KEY_F20] = SDLK_F20;
294 	k[Keyboard::KEY_F21] = SDLK_F21;
295 	k[Keyboard::KEY_F22] = SDLK_F22;
296 	k[Keyboard::KEY_F23] = SDLK_F23;
297 	k[Keyboard::KEY_F24] = SDLK_F24;
298 	k[Keyboard::KEY_EXECUTE] = SDLK_EXECUTE;
299 	k[Keyboard::KEY_HELP] = SDLK_HELP;
300 	k[Keyboard::KEY_MENU] = SDLK_MENU;
301 	k[Keyboard::KEY_SELECT] = SDLK_SELECT;
302 	k[Keyboard::KEY_STOP] = SDLK_STOP;
303 	k[Keyboard::KEY_AGAIN] = SDLK_AGAIN;
304 	k[Keyboard::KEY_UNDO] = SDLK_UNDO;
305 	k[Keyboard::KEY_CUT] = SDLK_CUT;
306 	k[Keyboard::KEY_COPY] = SDLK_COPY;
307 	k[Keyboard::KEY_PASTE] = SDLK_PASTE;
308 	k[Keyboard::KEY_FIND] = SDLK_FIND;
309 	k[Keyboard::KEY_MUTE] = SDLK_MUTE;
310 	k[Keyboard::KEY_VOLUMEUP] = SDLK_VOLUMEUP;
311 	k[Keyboard::KEY_VOLUMEDOWN] = SDLK_VOLUMEDOWN;
312 
313 	k[Keyboard::KEY_ALTERASE] = SDLK_ALTERASE;
314 	k[Keyboard::KEY_SYSREQ] = SDLK_SYSREQ;
315 	k[Keyboard::KEY_CANCEL] = SDLK_CANCEL;
316 	k[Keyboard::KEY_CLEAR] = SDLK_CLEAR;
317 	k[Keyboard::KEY_PRIOR] = SDLK_PRIOR;
318 	k[Keyboard::KEY_RETURN2] = SDLK_RETURN2;
319 	k[Keyboard::KEY_SEPARATOR] = SDLK_SEPARATOR;
320 	k[Keyboard::KEY_OUT] = SDLK_OUT;
321 	k[Keyboard::KEY_OPER] = SDLK_OPER;
322 	k[Keyboard::KEY_CLEARAGAIN] = SDLK_CLEARAGAIN;
323 
324 	k[Keyboard::KEY_THOUSANDSSEPARATOR] = SDLK_THOUSANDSSEPARATOR;
325 	k[Keyboard::KEY_DECIMALSEPARATOR] = SDLK_DECIMALSEPARATOR;
326 	k[Keyboard::KEY_CURRENCYUNIT] = SDLK_CURRENCYUNIT;
327 	k[Keyboard::KEY_CURRENCYSUBUNIT] = SDLK_CURRENCYSUBUNIT;
328 
329 	k[Keyboard::KEY_LCTRL] = SDLK_LCTRL;
330 	k[Keyboard::KEY_LSHIFT] = SDLK_LSHIFT;
331 	k[Keyboard::KEY_LALT] = SDLK_LALT;
332 	k[Keyboard::KEY_LGUI] = SDLK_LGUI;
333 	k[Keyboard::KEY_RCTRL] = SDLK_RCTRL;
334 	k[Keyboard::KEY_RSHIFT] = SDLK_RSHIFT;
335 	k[Keyboard::KEY_RALT] = SDLK_RALT;
336 	k[Keyboard::KEY_RGUI] = SDLK_RGUI;
337 
338 	k[Keyboard::KEY_MODE] = SDLK_MODE;
339 
340 	k[Keyboard::KEY_AUDIONEXT] = SDLK_AUDIONEXT;
341 	k[Keyboard::KEY_AUDIOPREV] = SDLK_AUDIOPREV;
342 	k[Keyboard::KEY_AUDIOSTOP] = SDLK_AUDIOSTOP;
343 	k[Keyboard::KEY_AUDIOPLAY] = SDLK_AUDIOPLAY;
344 	k[Keyboard::KEY_AUDIOMUTE] = SDLK_AUDIOMUTE;
345 	k[Keyboard::KEY_MEDIASELECT] = SDLK_MEDIASELECT;
346 	k[Keyboard::KEY_WWW] = SDLK_WWW;
347 	k[Keyboard::KEY_MAIL] = SDLK_MAIL;
348 	k[Keyboard::KEY_CALCULATOR] = SDLK_CALCULATOR;
349 	k[Keyboard::KEY_COMPUTER] = SDLK_COMPUTER;
350 	k[Keyboard::KEY_APP_SEARCH] = SDLK_AC_SEARCH;
351 	k[Keyboard::KEY_APP_HOME] = SDLK_AC_HOME;
352 	k[Keyboard::KEY_APP_BACK] = SDLK_AC_BACK;
353 	k[Keyboard::KEY_APP_FORWARD] = SDLK_AC_FORWARD;
354 	k[Keyboard::KEY_APP_STOP] = SDLK_AC_STOP;
355 	k[Keyboard::KEY_APP_REFRESH] = SDLK_AC_REFRESH;
356 	k[Keyboard::KEY_APP_BOOKMARKS] = SDLK_AC_BOOKMARKS;
357 
358 	k[Keyboard::KEY_BRIGHTNESSDOWN] = SDLK_BRIGHTNESSDOWN;
359 	k[Keyboard::KEY_BRIGHTNESSUP] = SDLK_BRIGHTNESSUP;
360 	k[Keyboard::KEY_DISPLAYSWITCH] = SDLK_DISPLAYSWITCH;
361 	k[Keyboard::KEY_KBDILLUMTOGGLE] = SDLK_KBDILLUMTOGGLE;
362 	k[Keyboard::KEY_KBDILLUMDOWN] = SDLK_KBDILLUMDOWN;
363 	k[Keyboard::KEY_KBDILLUMUP] = SDLK_KBDILLUMUP;
364 	k[Keyboard::KEY_EJECT] = SDLK_EJECT;
365 	k[Keyboard::KEY_SLEEP] = SDLK_SLEEP;
366 
367 	return k;
368 }
369 
370 const SDL_Keycode *Keyboard::keymap = Keyboard::createKeyMap();
371 
372 EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES>::Entry Keyboard::scancodeEntries[] =
373 {
374 	{SCANCODE_UNKNOWN, SDL_SCANCODE_UNKNOWN},
375 
376 	{SCANCODE_A, SDL_SCANCODE_A},
377 	{SCANCODE_B, SDL_SCANCODE_B},
378 	{SCANCODE_C, SDL_SCANCODE_C},
379 	{SCANCODE_D, SDL_SCANCODE_D},
380 	{SCANCODE_E, SDL_SCANCODE_E},
381 	{SCANCODE_F, SDL_SCANCODE_F},
382 	{SCANCODE_G, SDL_SCANCODE_G},
383 	{SCANCODE_H, SDL_SCANCODE_H},
384 	{SCANCODE_I, SDL_SCANCODE_I},
385 	{SCANCODE_J, SDL_SCANCODE_J},
386 	{SCANCODE_K, SDL_SCANCODE_K},
387 	{SCANCODE_L, SDL_SCANCODE_L},
388 	{SCANCODE_M, SDL_SCANCODE_M},
389 	{SCANCODE_N, SDL_SCANCODE_N},
390 	{SCANCODE_O, SDL_SCANCODE_O},
391 	{SCANCODE_P, SDL_SCANCODE_P},
392 	{SCANCODE_Q, SDL_SCANCODE_Q},
393 	{SCANCODE_R, SDL_SCANCODE_R},
394 	{SCANCODE_S, SDL_SCANCODE_S},
395 	{SCANCODE_T, SDL_SCANCODE_T},
396 	{SCANCODE_U, SDL_SCANCODE_U},
397 	{SCANCODE_V, SDL_SCANCODE_V},
398 	{SCANCODE_W, SDL_SCANCODE_W},
399 	{SCANCODE_X, SDL_SCANCODE_X},
400 	{SCANCODE_Y, SDL_SCANCODE_Y},
401 	{SCANCODE_Z, SDL_SCANCODE_Z},
402 
403 	{SCANCODE_1, SDL_SCANCODE_1},
404 	{SCANCODE_2, SDL_SCANCODE_2},
405 	{SCANCODE_3, SDL_SCANCODE_3},
406 	{SCANCODE_4, SDL_SCANCODE_4},
407 	{SCANCODE_5, SDL_SCANCODE_5},
408 	{SCANCODE_6, SDL_SCANCODE_6},
409 	{SCANCODE_7, SDL_SCANCODE_7},
410 	{SCANCODE_8, SDL_SCANCODE_8},
411 	{SCANCODE_9, SDL_SCANCODE_9},
412 	{SCANCODE_0, SDL_SCANCODE_0},
413 
414 	{SCANCODE_RETURN, SDL_SCANCODE_RETURN},
415 	{SCANCODE_ESCAPE, SDL_SCANCODE_ESCAPE},
416 	{SCANCODE_BACKSPACE, SDL_SCANCODE_BACKSPACE},
417 	{SCANCODE_TAB, SDL_SCANCODE_TAB},
418 	{SCANCODE_SPACE, SDL_SCANCODE_SPACE},
419 
420 	{SCANCODE_MINUS, SDL_SCANCODE_MINUS},
421 	{SCANCODE_EQUALS, SDL_SCANCODE_EQUALS},
422 	{SCANCODE_LEFTBRACKET, SDL_SCANCODE_LEFTBRACKET},
423 	{SCANCODE_RIGHTBRACKET, SDL_SCANCODE_RIGHTBRACKET},
424 	{SCANCODE_BACKSLASH, SDL_SCANCODE_BACKSLASH},
425 	{SCANCODE_NONUSHASH, SDL_SCANCODE_NONUSHASH},
426 	{SCANCODE_SEMICOLON, SDL_SCANCODE_SEMICOLON},
427 	{SCANCODE_APOSTROPHE, SDL_SCANCODE_APOSTROPHE},
428 	{SCANCODE_GRAVE, SDL_SCANCODE_GRAVE},
429 	{SCANCODE_COMMA, SDL_SCANCODE_COMMA},
430 	{SCANCODE_PERIOD, SDL_SCANCODE_PERIOD},
431 	{SCANCODE_SLASH, SDL_SCANCODE_SLASH},
432 
433 	{SCANCODE_CAPSLOCK, SDL_SCANCODE_CAPSLOCK},
434 
435 	{SCANCODE_F1, SDL_SCANCODE_F1},
436 	{SCANCODE_F2, SDL_SCANCODE_F2},
437 	{SCANCODE_F3, SDL_SCANCODE_F3},
438 	{SCANCODE_F4, SDL_SCANCODE_F4},
439 	{SCANCODE_F5, SDL_SCANCODE_F5},
440 	{SCANCODE_F6, SDL_SCANCODE_F6},
441 	{SCANCODE_F7, SDL_SCANCODE_F7},
442 	{SCANCODE_F8, SDL_SCANCODE_F8},
443 	{SCANCODE_F9, SDL_SCANCODE_F9},
444 	{SCANCODE_F10, SDL_SCANCODE_F10},
445 	{SCANCODE_F11, SDL_SCANCODE_F11},
446 	{SCANCODE_F12, SDL_SCANCODE_F12},
447 
448 	{SCANCODE_PRINTSCREEN, SDL_SCANCODE_PRINTSCREEN},
449 	{SCANCODE_SCROLLLOCK, SDL_SCANCODE_SCROLLLOCK},
450 	{SCANCODE_PAUSE, SDL_SCANCODE_PAUSE},
451 	{SCANCODE_INSERT, SDL_SCANCODE_INSERT},
452 	{SCANCODE_HOME, SDL_SCANCODE_HOME},
453 	{SCANCODE_PAGEUP, SDL_SCANCODE_PAGEUP},
454 	{SCANCODE_DELETE, SDL_SCANCODE_DELETE},
455 	{SCANCODE_END, SDL_SCANCODE_END},
456 	{SCANCODE_PAGEDOWN, SDL_SCANCODE_PAGEDOWN},
457 	{SCANCODE_RIGHT, SDL_SCANCODE_RIGHT},
458 	{SCANCODE_LEFT, SDL_SCANCODE_LEFT},
459 	{SCANCODE_DOWN, SDL_SCANCODE_DOWN},
460 	{SCANCODE_UP, SDL_SCANCODE_UP},
461 
462 	{SCANCODE_NUMLOCKCLEAR, SDL_SCANCODE_NUMLOCKCLEAR},
463 	{SCANCODE_KP_DIVIDE, SDL_SCANCODE_KP_DIVIDE},
464 	{SCANCODE_KP_MULTIPLY, SDL_SCANCODE_KP_MULTIPLY},
465 	{SCANCODE_KP_MINUS, SDL_SCANCODE_KP_MINUS},
466 	{SCANCODE_KP_PLUS, SDL_SCANCODE_KP_PLUS},
467 	{SCANCODE_KP_ENTER, SDL_SCANCODE_KP_ENTER},
468 	{SCANCODE_KP_1, SDL_SCANCODE_KP_1},
469 	{SCANCODE_KP_2, SDL_SCANCODE_KP_2},
470 	{SCANCODE_KP_3, SDL_SCANCODE_KP_3},
471 	{SCANCODE_KP_4, SDL_SCANCODE_KP_4},
472 	{SCANCODE_KP_5, SDL_SCANCODE_KP_5},
473 	{SCANCODE_KP_6, SDL_SCANCODE_KP_6},
474 	{SCANCODE_KP_7, SDL_SCANCODE_KP_7},
475 	{SCANCODE_KP_8, SDL_SCANCODE_KP_8},
476 	{SCANCODE_KP_9, SDL_SCANCODE_KP_9},
477 	{SCANCODE_KP_0, SDL_SCANCODE_KP_0},
478 	{SCANCODE_KP_PERIOD, SDL_SCANCODE_KP_PERIOD},
479 
480 	{SCANCODE_NONUSBACKSLASH, SDL_SCANCODE_NONUSBACKSLASH},
481 	{SCANCODE_APPLICATION, SDL_SCANCODE_APPLICATION},
482 	{SCANCODE_POWER, SDL_SCANCODE_POWER},
483 	{SCANCODE_KP_EQUALS, SDL_SCANCODE_KP_EQUALS},
484 	{SCANCODE_F13, SDL_SCANCODE_F13},
485 	{SCANCODE_F14, SDL_SCANCODE_F14},
486 	{SCANCODE_F15, SDL_SCANCODE_F15},
487 	{SCANCODE_F16, SDL_SCANCODE_F16},
488 	{SCANCODE_F17, SDL_SCANCODE_F17},
489 	{SCANCODE_F18, SDL_SCANCODE_F18},
490 	{SCANCODE_F19, SDL_SCANCODE_F19},
491 	{SCANCODE_F20, SDL_SCANCODE_F20},
492 	{SCANCODE_F21, SDL_SCANCODE_F21},
493 	{SCANCODE_F22, SDL_SCANCODE_F22},
494 	{SCANCODE_F23, SDL_SCANCODE_F23},
495 	{SCANCODE_F24, SDL_SCANCODE_F24},
496 	{SCANCODE_EXECUTE, SDL_SCANCODE_EXECUTE},
497 	{SCANCODE_HELP, SDL_SCANCODE_HELP},
498 	{SCANCODE_MENU, SDL_SCANCODE_MENU},
499 	{SCANCODE_SELECT, SDL_SCANCODE_SELECT},
500 	{SCANCODE_STOP, SDL_SCANCODE_STOP},
501 	{SCANCODE_AGAIN, SDL_SCANCODE_AGAIN},
502 	{SCANCODE_UNDO, SDL_SCANCODE_UNDO},
503 	{SCANCODE_CUT, SDL_SCANCODE_CUT},
504 	{SCANCODE_COPY, SDL_SCANCODE_COPY},
505 	{SCANCODE_PASTE, SDL_SCANCODE_PASTE},
506 	{SCANCODE_FIND, SDL_SCANCODE_FIND},
507 	{SCANCODE_MUTE, SDL_SCANCODE_MUTE},
508 	{SCANCODE_VOLUMEUP, SDL_SCANCODE_VOLUMEUP},
509 	{SCANCODE_VOLUMEDOWN, SDL_SCANCODE_VOLUMEDOWN},
510 	{SCANCODE_KP_COMMA, SDL_SCANCODE_KP_COMMA},
511 	{SCANCODE_KP_EQUALSAS400, SDL_SCANCODE_KP_EQUALSAS400},
512 
513 	{SCANCODE_INTERNATIONAL1, SDL_SCANCODE_INTERNATIONAL1},
514 	{SCANCODE_INTERNATIONAL2, SDL_SCANCODE_INTERNATIONAL2},
515 	{SCANCODE_INTERNATIONAL3, SDL_SCANCODE_INTERNATIONAL3},
516 	{SCANCODE_INTERNATIONAL4, SDL_SCANCODE_INTERNATIONAL4},
517 	{SCANCODE_INTERNATIONAL5, SDL_SCANCODE_INTERNATIONAL5},
518 	{SCANCODE_INTERNATIONAL6, SDL_SCANCODE_INTERNATIONAL6},
519 	{SCANCODE_INTERNATIONAL7, SDL_SCANCODE_INTERNATIONAL7},
520 	{SCANCODE_INTERNATIONAL8, SDL_SCANCODE_INTERNATIONAL8},
521 	{SCANCODE_INTERNATIONAL9, SDL_SCANCODE_INTERNATIONAL9},
522 	{SCANCODE_LANG1, SDL_SCANCODE_LANG1},
523 	{SCANCODE_LANG2, SDL_SCANCODE_LANG2},
524 	{SCANCODE_LANG3, SDL_SCANCODE_LANG3},
525 	{SCANCODE_LANG4, SDL_SCANCODE_LANG4},
526 	{SCANCODE_LANG5, SDL_SCANCODE_LANG5},
527 	{SCANCODE_LANG6, SDL_SCANCODE_LANG6},
528 	{SCANCODE_LANG7, SDL_SCANCODE_LANG7},
529 	{SCANCODE_LANG8, SDL_SCANCODE_LANG8},
530 	{SCANCODE_LANG9, SDL_SCANCODE_LANG9},
531 
532 	{SCANCODE_ALTERASE, SDL_SCANCODE_ALTERASE},
533 	{SCANCODE_SYSREQ, SDL_SCANCODE_SYSREQ},
534 	{SCANCODE_CANCEL, SDL_SCANCODE_CANCEL},
535 	{SCANCODE_CLEAR, SDL_SCANCODE_CLEAR},
536 	{SCANCODE_PRIOR, SDL_SCANCODE_PRIOR},
537 	{SCANCODE_RETURN2, SDL_SCANCODE_RETURN2},
538 	{SCANCODE_SEPARATOR, SDL_SCANCODE_SEPARATOR},
539 	{SCANCODE_OUT, SDL_SCANCODE_OUT},
540 	{SCANCODE_OPER, SDL_SCANCODE_OPER},
541 	{SCANCODE_CLEARAGAIN, SDL_SCANCODE_CLEARAGAIN},
542 	{SCANCODE_CRSEL, SDL_SCANCODE_CRSEL},
543 	{SCANCODE_EXSEL, SDL_SCANCODE_EXSEL},
544 
545 	{SCANCODE_KP_00, SDL_SCANCODE_KP_00},
546 	{SCANCODE_KP_000, SDL_SCANCODE_KP_000},
547 	{SCANCODE_THOUSANDSSEPARATOR, SDL_SCANCODE_THOUSANDSSEPARATOR},
548 	{SCANCODE_DECIMALSEPARATOR, SDL_SCANCODE_DECIMALSEPARATOR},
549 	{SCANCODE_CURRENCYUNIT, SDL_SCANCODE_CURRENCYUNIT},
550 	{SCANCODE_CURRENCYSUBUNIT, SDL_SCANCODE_CURRENCYSUBUNIT},
551 	{SCANCODE_KP_LEFTPAREN, SDL_SCANCODE_KP_LEFTPAREN},
552 	{SCANCODE_KP_RIGHTPAREN, SDL_SCANCODE_KP_RIGHTPAREN},
553 	{SCANCODE_KP_LEFTBRACE, SDL_SCANCODE_KP_LEFTBRACE},
554 	{SCANCODE_KP_RIGHTBRACE, SDL_SCANCODE_KP_RIGHTBRACE},
555 	{SCANCODE_KP_TAB, SDL_SCANCODE_KP_TAB},
556 	{SCANCODE_KP_BACKSPACE, SDL_SCANCODE_KP_BACKSPACE},
557 	{SCANCODE_KP_A, SDL_SCANCODE_KP_A},
558 	{SCANCODE_KP_B, SDL_SCANCODE_KP_B},
559 	{SCANCODE_KP_C, SDL_SCANCODE_KP_C},
560 	{SCANCODE_KP_D, SDL_SCANCODE_KP_D},
561 	{SCANCODE_KP_E, SDL_SCANCODE_KP_E},
562 	{SCANCODE_KP_F, SDL_SCANCODE_KP_F},
563 	{SCANCODE_KP_XOR, SDL_SCANCODE_KP_XOR},
564 	{SCANCODE_KP_POWER, SDL_SCANCODE_KP_POWER},
565 	{SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_PERCENT},
566 	{SCANCODE_KP_LESS, SDL_SCANCODE_KP_LESS},
567 	{SCANCODE_KP_GREATER, SDL_SCANCODE_KP_GREATER},
568 	{SCANCODE_KP_AMPERSAND, SDL_SCANCODE_KP_AMPERSAND},
569 	{SCANCODE_KP_DBLAMPERSAND, SDL_SCANCODE_KP_DBLAMPERSAND},
570 	{SCANCODE_KP_VERTICALBAR, SDL_SCANCODE_KP_VERTICALBAR},
571 	{SCANCODE_KP_DBLVERTICALBAR, SDL_SCANCODE_KP_DBLVERTICALBAR},
572 	{SCANCODE_KP_COLON, SDL_SCANCODE_KP_COLON},
573 	{SCANCODE_KP_HASH, SDL_SCANCODE_KP_HASH},
574 	{SCANCODE_KP_SPACE, SDL_SCANCODE_KP_SPACE},
575 	{SCANCODE_KP_AT, SDL_SCANCODE_KP_AT},
576 	{SCANCODE_KP_EXCLAM, SDL_SCANCODE_KP_EXCLAM},
577 	{SCANCODE_KP_MEMSTORE, SDL_SCANCODE_KP_MEMSTORE},
578 	{SCANCODE_KP_MEMRECALL, SDL_SCANCODE_KP_MEMRECALL},
579 	{SCANCODE_KP_MEMCLEAR, SDL_SCANCODE_KP_MEMCLEAR},
580 	{SCANCODE_KP_MEMADD, SDL_SCANCODE_KP_MEMADD},
581 	{SCANCODE_KP_MEMSUBTRACT, SDL_SCANCODE_KP_MEMSUBTRACT},
582 	{SCANCODE_KP_MEMMULTIPLY, SDL_SCANCODE_KP_MEMMULTIPLY},
583 	{SCANCODE_KP_MEMDIVIDE, SDL_SCANCODE_KP_MEMDIVIDE},
584 	{SCANCODE_KP_PLUSMINUS, SDL_SCANCODE_KP_PLUSMINUS},
585 	{SCANCODE_KP_CLEAR, SDL_SCANCODE_KP_CLEAR},
586 	{SCANCODE_KP_CLEARENTRY, SDL_SCANCODE_KP_CLEARENTRY},
587 	{SCANCODE_KP_BINARY, SDL_SCANCODE_KP_BINARY},
588 	{SCANCODE_KP_OCTAL, SDL_SCANCODE_KP_OCTAL},
589 	{SCANCODE_KP_DECIMAL, SDL_SCANCODE_KP_DECIMAL},
590 	{SCANCODE_KP_HEXADECIMAL, SDL_SCANCODE_KP_HEXADECIMAL},
591 
592 	{SCANCODE_LCTRL, SDL_SCANCODE_LCTRL},
593 	{SCANCODE_LSHIFT, SDL_SCANCODE_LSHIFT},
594 	{SCANCODE_LALT, SDL_SCANCODE_LALT},
595 	{SCANCODE_LGUI, SDL_SCANCODE_LGUI},
596 	{SCANCODE_RCTRL, SDL_SCANCODE_RCTRL},
597 	{SCANCODE_RSHIFT, SDL_SCANCODE_RSHIFT},
598 	{SCANCODE_RALT, SDL_SCANCODE_RALT},
599 	{SCANCODE_RGUI, SDL_SCANCODE_RGUI},
600 
601 	{SCANCODE_MODE, SDL_SCANCODE_MODE},
602 
603 	{SCANCODE_AUDIONEXT, SDL_SCANCODE_AUDIONEXT},
604 	{SCANCODE_AUDIOPREV, SDL_SCANCODE_AUDIOPREV},
605 	{SCANCODE_AUDIOSTOP, SDL_SCANCODE_AUDIOSTOP},
606 	{SCANCODE_AUDIOPLAY, SDL_SCANCODE_AUDIOPLAY},
607 	{SCANCODE_AUDIOMUTE, SDL_SCANCODE_AUDIOMUTE},
608 	{SCANCODE_MEDIASELECT, SDL_SCANCODE_MEDIASELECT},
609 	{SCANCODE_WWW, SDL_SCANCODE_WWW},
610 	{SCANCODE_MAIL, SDL_SCANCODE_MAIL},
611 	{SCANCODE_CALCULATOR, SDL_SCANCODE_CALCULATOR},
612 	{SCANCODE_COMPUTER, SDL_SCANCODE_COMPUTER},
613 	{SCANCODE_AC_SEARCH, SDL_SCANCODE_AC_SEARCH},
614 	{SCANCODE_AC_HOME, SDL_SCANCODE_AC_HOME},
615 	{SCANCODE_AC_BACK, SDL_SCANCODE_AC_BACK},
616 	{SCANCODE_AC_FORWARD, SDL_SCANCODE_AC_FORWARD},
617 	{SCANCODE_AC_STOP, SDL_SCANCODE_AC_STOP},
618 	{SCANCODE_AC_REFRESH, SDL_SCANCODE_AC_REFRESH},
619 	{SCANCODE_AC_BOOKMARKS, SDL_SCANCODE_AC_BOOKMARKS},
620 
621 	{SCANCODE_BRIGHTNESSDOWN, SDL_SCANCODE_BRIGHTNESSDOWN},
622 	{SCANCODE_BRIGHTNESSUP, SDL_SCANCODE_BRIGHTNESSUP},
623 	{SCANCODE_DISPLAYSWITCH, SDL_SCANCODE_DISPLAYSWITCH},
624 	{SCANCODE_KBDILLUMTOGGLE, SDL_SCANCODE_KBDILLUMTOGGLE},
625 	{SCANCODE_KBDILLUMDOWN, SDL_SCANCODE_KBDILLUMDOWN},
626 	{SCANCODE_KBDILLUMUP, SDL_SCANCODE_KBDILLUMUP},
627 	{SCANCODE_EJECT, SDL_SCANCODE_EJECT},
628 	{SCANCODE_SLEEP, SDL_SCANCODE_SLEEP},
629 
630 	{SCANCODE_APP1, SDL_SCANCODE_APP1},
631 	{SCANCODE_APP2, SDL_SCANCODE_APP2},
632 };
633 
634 EnumMap<Keyboard::Scancode, SDL_Scancode, SDL_NUM_SCANCODES> Keyboard::scancodes(Keyboard::scancodeEntries, sizeof(Keyboard::scancodeEntries));
635 
636 } // sdl
637 } // keyboard
638 } // love
639