openMSX
Keys.cc
Go to the documentation of this file.
1#include "Keys.hh"
2#include "StringOp.hh"
3#include "ranges.hh"
4#include <array>
5
6using std::string_view;
7
8namespace openmsx::Keys {
9
10// can be std::pair in C++20
11struct P {
12 constexpr P(string_view s, KeyCode k)
13 : first(s), second(k) {}
14
15 string_view first;
17};
18
19struct CmpKeys {
20 // for std::sort
21 [[nodiscard]] constexpr bool operator()(const P& x, const P& y) const {
22 return x.first < y.first; // shortcut: no need to ignore case
23 }
24
25 // for lower_bound()
26 [[nodiscard]] bool operator()(const P& x, string_view y) const {
28 return cmp(x.first, y);
29 }
30 [[nodiscard]] bool operator()(string_view x, const P& y) const {
32 return cmp(x, y.first);
33 }
34};
35
36#ifdef _MSC_VER
37// Require a new enough visual studio version:
38// https://developercommunity.visualstudio.com/content/problem/429980/wrong-code-with-constexpr-on-msvc-1916.html
39static_assert(_MSC_VER >= 1923, "visual studio version too old");
40#endif
41static constexpr auto getSortedKeys()
42{
43 auto keys = std::array{
44 P("BACKSPACE", K_BACKSPACE),
45 P("TAB", K_TAB),
46 P("CLEAR", K_CLEAR),
47 P("RETURN", K_RETURN),
48 P("PAUSE", K_PAUSE),
49 P("ESCAPE", K_ESCAPE),
50 P("SPACE", K_SPACE),
51 P("EXCLAIM", K_EXCLAIM),
52 P("QUOTEDBL", K_QUOTEDBL),
53 P("HASH", K_HASH),
54 P("DOLLAR", K_DOLLAR),
55 P("AMPERSAND", K_AMPERSAND),
56 P("QUOTE", K_QUOTE),
57 P("LEFTPAREN", K_LEFTPAREN),
58 P("RIGHTPAREN", K_RIGHTPAREN),
59 P("ASTERISK", K_ASTERISK),
60 P("PLUS", K_PLUS),
61 P("COMMA", K_COMMA),
62 P("MINUS", K_MINUS),
63 P("PERIOD", K_PERIOD),
64 P("SLASH", K_SLASH),
65 P("0", K_0),
66 P("1", K_1),
67 P("2", K_2),
68 P("3", K_3),
69 P("4", K_4),
70 P("5", K_5),
71 P("6", K_6),
72 P("7", K_7),
73 P("8", K_8),
74 P("9", K_9),
75 P("COLON", K_COLON),
76 P("SEMICOLON", K_SEMICOLON),
77 P("LESS", K_LESS),
78 P("EQUALS", K_EQUALS),
79 P("GREATER", K_GREATER),
80 P("QUESTION", K_QUESTION),
81 P("AT", K_AT),
82
83 P("LEFTBRACKET",K_LEFTBRACKET),
84 P("BACKSLASH", K_BACKSLASH),
85 P("RIGHTBRACKET",K_RIGHTBRACKET),
86 P("CARET", K_CARET),
87 P("UNDERSCORE", K_UNDERSCORE),
88 P("BACKQUOTE", K_BACKQUOTE),
89 P("A", K_A),
90 P("B", K_B),
91 P("C", K_C),
92 P("D", K_D),
93 P("E", K_E),
94 P("F", K_F),
95 P("G", K_G),
96 P("H", K_H),
97 P("I", K_I),
98 P("J", K_J),
99 P("K", K_K),
100 P("L", K_L),
101 P("M", K_M),
102 P("N", K_N),
103 P("O", K_O),
104 P("P", K_P),
105 P("Q", K_Q),
106 P("R", K_R),
107 P("S", K_S),
108 P("T", K_T),
109 P("U", K_U),
110 P("V", K_V),
111 P("W", K_W),
112 P("X", K_X),
113 P("Y", K_Y),
114 P("Z", K_Z),
115 P("DELETE", K_DELETE),
116
117/*
118 P("WORLD_0", K_WORLD_0),
119 P("WORLD_1", K_WORLD_1),
120 P("WORLD_2", K_WORLD_2),
121 P("WORLD_3", K_WORLD_3),
122 P("WORLD_4", K_WORLD_4),
123 P("WORLD_5", K_WORLD_5),
124 P("WORLD_6", K_WORLD_6),
125 P("WORLD_7", K_WORLD_7),
126 P("WORLD_8", K_WORLD_8),
127 P("WORLD_9", K_WORLD_9),
128 P("WORLD_10", K_WORLD_10),
129 P("WORLD_11", K_WORLD_11),
130 P("WORLD_12", K_WORLD_12),
131 P("WORLD_13", K_WORLD_13),
132 P("WORLD_14", K_WORLD_14),
133 P("WORLD_15", K_WORLD_15),
134 P("WORLD_16", K_WORLD_16),
135 P("WORLD_17", K_WORLD_17),
136 P("WORLD_18", K_WORLD_18),
137 P("WORLD_19", K_WORLD_19),
138 P("WORLD_20", K_WORLD_20),
139 P("WORLD_21", K_WORLD_21),
140 P("WORLD_22", K_WORLD_22),
141 P("WORLD_23", K_WORLD_23),
142 P("WORLD_24", K_WORLD_24),
143 P("WORLD_25", K_WORLD_25),
144 P("WORLD_26", K_WORLD_26),
145 P("WORLD_27", K_WORLD_27),
146 P("WORLD_28", K_WORLD_28),
147 P("WORLD_29", K_WORLD_29),
148 P("WORLD_30", K_WORLD_30),
149 P("WORLD_31", K_WORLD_31),
150 P("WORLD_32", K_WORLD_32),
151 P("WORLD_33", K_WORLD_33),
152 P("WORLD_34", K_WORLD_34),
153 P("WORLD_35", K_WORLD_35),
154 P("WORLD_36", K_WORLD_36),
155 P("WORLD_37", K_WORLD_37),
156 P("WORLD_38", K_WORLD_38),
157 P("WORLD_39", K_WORLD_39),
158 P("WORLD_40", K_WORLD_40),
159 P("WORLD_41", K_WORLD_41),
160 P("WORLD_42", K_WORLD_42),
161 P("WORLD_43", K_WORLD_43),
162 P("WORLD_44", K_WORLD_44),
163 P("WORLD_45", K_WORLD_45),
164 P("WORLD_46", K_WORLD_46),
165 P("WORLD_47", K_WORLD_47),
166 P("WORLD_48", K_WORLD_48),
167 P("WORLD_49", K_WORLD_49),
168 P("WORLD_50", K_WORLD_50),
169 P("WORLD_51", K_WORLD_51),
170 P("WORLD_52", K_WORLD_52),
171 P("WORLD_53", K_WORLD_53),
172 P("WORLD_54", K_WORLD_54),
173 P("WORLD_55", K_WORLD_55),
174 P("WORLD_56", K_WORLD_56),
175 P("WORLD_57", K_WORLD_57),
176 P("WORLD_58", K_WORLD_58),
177 P("WORLD_59", K_WORLD_59),
178 P("WORLD_60", K_WORLD_60),
179 P("WORLD_61", K_WORLD_61),
180 P("WORLD_62", K_WORLD_62),
181 P("WORLD_63", K_WORLD_63),
182 P("WORLD_64", K_WORLD_64),
183 P("WORLD_65", K_WORLD_65),
184 P("WORLD_66", K_WORLD_66),
185 P("WORLD_67", K_WORLD_67),
186 P("WORLD_68", K_WORLD_68),
187 P("WORLD_69", K_WORLD_69),
188 P("WORLD_70", K_WORLD_70),
189 P("WORLD_71", K_WORLD_71),
190 P("WORLD_72", K_WORLD_72),
191 P("WORLD_73", K_WORLD_73),
192 P("WORLD_74", K_WORLD_74),
193 P("WORLD_75", K_WORLD_75),
194 P("WORLD_76", K_WORLD_76),
195 P("WORLD_77", K_WORLD_77),
196 P("WORLD_78", K_WORLD_78),
197 P("WORLD_79", K_WORLD_79),
198 P("WORLD_80", K_WORLD_80),
199 P("WORLD_81", K_WORLD_81),
200 P("WORLD_82", K_WORLD_82),
201 P("WORLD_83", K_WORLD_83),
202 P("WORLD_84", K_WORLD_84),
203 P("WORLD_85", K_WORLD_85),
204 P("WORLD_86", K_WORLD_86),
205 P("WORLD_87", K_WORLD_87),
206 P("WORLD_88", K_WORLD_88),
207 P("WORLD_89", K_WORLD_89),
208 P("WORLD_90", K_WORLD_90),
209 P("WORLD_91", K_WORLD_91),
210 P("WORLD_92", K_WORLD_92),
211 P("WORLD_93", K_WORLD_93),
212 P("WORLD_94", K_WORLD_94),
213 P("WORLD_95", K_WORLD_95),
214*/
215
216 // Numeric keypad
217 P("KP0", K_KP0),
218 P("KP1", K_KP1),
219 P("KP2", K_KP2),
220 P("KP3", K_KP3),
221 P("KP4", K_KP4),
222 P("KP5", K_KP5),
223 P("KP6", K_KP6),
224 P("KP7", K_KP7),
225 P("KP8", K_KP8),
226 P("KP9", K_KP9),
227 P("KP_PERIOD", K_KP_PERIOD),
228 P("KP_DIVIDE", K_KP_DIVIDE),
229 P("KP_MULTIPLY",K_KP_MULTIPLY),
230 P("KP_MINUS", K_KP_MINUS),
231 P("KP_PLUS", K_KP_PLUS),
232 P("KP_ENTER", K_KP_ENTER),
233 P("KP_EQUALS", K_KP_EQUALS),
234
235 // Arrows + Home/End pad
236 P("UP", K_UP),
237 P("DOWN", K_DOWN),
238 P("RIGHT", K_RIGHT),
239 P("LEFT", K_LEFT),
240 P("INSERT", K_INSERT),
241 P("HOME", K_HOME),
242 P("END", K_END),
243 P("PAGEUP", K_PAGEUP),
244 P("PAGEDOWN", K_PAGEDOWN),
245
246 // Function keys
247 P("F1", K_F1),
248 P("F2", K_F2),
249 P("F3", K_F3),
250 P("F4", K_F4),
251 P("F5", K_F5),
252 P("F6", K_F6),
253 P("F7", K_F7),
254 P("F8", K_F8),
255 P("F9", K_F9),
256 P("F10", K_F10),
257 P("F11", K_F11),
258 P("F12", K_F12),
259 P("F13", K_F13),
260 P("F14", K_F14),
261 P("F15", K_F15),
262 P("F16", K_F16),
263 P("F17", K_F17),
264 P("F18", K_F18),
265 P("F19", K_F19),
266 P("F20", K_F20),
267 P("F21", K_F21),
268 P("F22", K_F22),
269 P("F23", K_F23),
270 P("F24", K_F24),
271
272 // Key state modifier keys
273 P("NUMLOCK", K_NUMLOCK),
274 P("CAPSLOCK", K_CAPSLOCK),
275 // Note: Older openMSX releases duplicated the SDL 1.2 spelling mistake
276 // in the scroll lock key symbol. Since the wrong spelling comes
277 // alphabetically after the right one, our to-string conversion
278 // will pick the right one.
279 P("SCROLLLOCK", K_SCROLLLOCK),
280 P("SCROLLOCK", K_SCROLLLOCK), // backwards compat
281 P("RSHIFT", K_RSHIFT),
282 P("LSHIFT", K_LSHIFT),
283 P("RCTRL", K_RCTRL),
284 P("LCTRL", K_LCTRL),
285 P("RALT", K_RALT),
286 P("LALT", K_LALT),
287// P("RMETA", K_RMETA),
288// P("LMETA", K_LMETA),
289 P("LSUPER", K_LSUPER), // Left "Windows" key
290 P("RSUPER", K_RSUPER), // Right "Windows" key
291 P("RMODE", K_MODE), // "Alt Gr" key
292// P("COMPOSE", K_COMPOSE), // Multi-key compose key
293
294 // Miscellaneous function keys
295 P("HELP", K_HELP),
296 P("PRINT", K_PRINT),
297 P("SYSREQ", K_SYSREQ),
298// P("BREAK", K_BREAK),
299 P("MENU", K_MENU),
300 P("POWER", K_POWER), // Power Macintosh power key
301// P("EURO", K_EURO), // Some european keyboards
302 P("UNDO", K_UNDO),
303
304 // Application Control keys
305 P("BACK", K_BACK),
306
307 // Japanese keyboard special keys
308 P("ZENKAKU_HENKAKU", K_ZENKAKU_HENKAKU),
309 P("MUHENKAN", K_MUHENKAN),
310 P("HENKAN_MODE", K_HENKAN_MODE),
311 P("HIRAGANA_KATAKANA", K_HIRAGANA_KATAKANA),
312
313 // Modifiers
314 P("SHIFT", KM_SHIFT),
315 P("CTRL", KM_CTRL),
316 P("ALT", KM_ALT),
317 P("META", KM_META),
318 P("MODE", KM_MODE),
319
320 // Direction modifiers
321 P("PRESS", KD_PRESS),
322 P("RELEASE", KD_RELEASE)
323 };
324 ranges::sort(keys, CmpKeys());
325 return keys;
326}
327
328static constexpr auto keys = getSortedKeys();
329
330KeyCode getCode(string_view name)
331{
332 auto result = static_cast<KeyCode>(0);
333 string_view::size_type lastPos = 0;
334 while (lastPos != string_view::npos) {
335 auto pos = name.substr(lastPos).find_first_of(",+/");
336 auto part = (pos != string_view::npos)
337 ? name.substr(lastPos, pos)
338 : name.substr(lastPos);
339 auto k = binary_find(keys, part, CmpKeys{});
340 if (!k) {
341 return K_NONE;
342 }
343 KeyCode partCode = k->second;
344 if ((partCode & K_MASK) && (result & K_MASK)) {
345 // more than one non-modifier component
346 // is not allowed
347 return K_NONE;
348 }
349 result = static_cast<KeyCode>(result | partCode);
350 lastPos = (pos != string_view::npos)
351 ? lastPos + pos + 1
352 : string_view::npos;
353 }
354 return result;
355}
356
357std::pair<KeyCode, KeyCode> getCodes(SDL_Keycode sdlKeyCode, Uint16 mod, SDL_Scancode sdlScanCode, bool release)
358{
359 KeyCode key = [&] {
360 switch (sdlKeyCode) {
361 case SDLK_BACKSPACE: return K_BACKSPACE;
362 case SDLK_TAB: return K_TAB;
363 case SDLK_CLEAR: return K_CLEAR;
364 case SDLK_RETURN: return K_RETURN;
365 case SDLK_PAUSE: return K_PAUSE;
366 case SDLK_ESCAPE: return K_ESCAPE;
367 case SDLK_SPACE: return K_SPACE;
368 case SDLK_EXCLAIM: return K_EXCLAIM;
369 case SDLK_QUOTEDBL: return K_QUOTEDBL;
370 case SDLK_HASH: return K_HASH;
371 case SDLK_DOLLAR: return K_DOLLAR;
372 case SDLK_AMPERSAND: return K_AMPERSAND;
373 case SDLK_QUOTE: return K_QUOTE;
374 case SDLK_LEFTPAREN: return K_LEFTPAREN;
375 case SDLK_RIGHTPAREN: return K_RIGHTPAREN;
376 case SDLK_ASTERISK: return K_ASTERISK;
377 case SDLK_PLUS: return K_PLUS;
378 case SDLK_COMMA: return K_COMMA;
379 case SDLK_MINUS: return K_MINUS;
380 case SDLK_PERIOD: return K_PERIOD;
381 case SDLK_SLASH: return K_SLASH;
382 case SDLK_0: return K_0;
383 case SDLK_1: return K_1;
384 case SDLK_2: return K_2;
385 case SDLK_3: return K_3;
386 case SDLK_4: return K_4;
387 case SDLK_5: return K_5;
388 case SDLK_6: return K_6;
389 case SDLK_7: return K_7;
390 case SDLK_8: return K_8;
391 case SDLK_9: return K_9;
392 case SDLK_COLON: return K_COLON;
393 case SDLK_SEMICOLON: return K_SEMICOLON;
394 case SDLK_LESS: return K_LESS;
395 case SDLK_EQUALS: return K_EQUALS;
396 case SDLK_GREATER: return K_GREATER;
397 case SDLK_QUESTION: return K_QUESTION;
398 case SDLK_AT: return K_AT;
399
400 case SDLK_LEFTBRACKET: return K_LEFTBRACKET;
401 case SDLK_BACKSLASH: return K_BACKSLASH;
402 case SDLK_RIGHTBRACKET: return K_RIGHTBRACKET;
403 case SDLK_CARET: return K_CARET;
404 case SDLK_UNDERSCORE: return K_UNDERSCORE;
405 case SDLK_BACKQUOTE: return K_BACKQUOTE;
406 case SDLK_a: return K_A;
407 case SDLK_b: return K_B;
408 case SDLK_c: return K_C;
409 case SDLK_d: return K_D;
410 case SDLK_e: return K_E;
411 case SDLK_f: return K_F;
412 case SDLK_g: return K_G;
413 case SDLK_h: return K_H;
414 case SDLK_i: return K_I;
415 case SDLK_j: return K_J;
416 case SDLK_k: return K_K;
417 case SDLK_l: return K_L;
418 case SDLK_m: return K_M;
419 case SDLK_n: return K_N;
420 case SDLK_o: return K_O;
421 case SDLK_p: return K_P;
422 case SDLK_q: return K_Q;
423 case SDLK_r: return K_R;
424 case SDLK_s: return K_S;
425 case SDLK_t: return K_T;
426 case SDLK_u: return K_U;
427 case SDLK_v: return K_V;
428 case SDLK_w: return K_W;
429 case SDLK_x: return K_X;
430 case SDLK_y: return K_Y;
431 case SDLK_z: return K_Z;
432 case SDLK_DELETE: return K_DELETE;
433
434 // Numeric keypad
435 case SDLK_KP_0: return K_KP0;
436 case SDLK_KP_1: return K_KP1;
437 case SDLK_KP_2: return K_KP2;
438 case SDLK_KP_3: return K_KP3;
439 case SDLK_KP_4: return K_KP4;
440 case SDLK_KP_5: return K_KP5;
441 case SDLK_KP_6: return K_KP6;
442 case SDLK_KP_7: return K_KP7;
443 case SDLK_KP_8: return K_KP8;
444 case SDLK_KP_9: return K_KP9;
445 case SDLK_KP_PERIOD: return K_KP_PERIOD;
446 case SDLK_KP_DIVIDE: return K_KP_DIVIDE;
447 case SDLK_KP_MULTIPLY: return K_KP_MULTIPLY;
448 case SDLK_KP_MINUS: return K_KP_MINUS;
449 case SDLK_KP_PLUS: return K_KP_PLUS;
450 case SDLK_KP_ENTER: return K_KP_ENTER;
451 case SDLK_KP_EQUALS: return K_KP_EQUALS;
452
453 // Arrows + Home/End pad
454 case SDLK_UP: return K_UP;
455 case SDLK_DOWN: return K_DOWN;
456 case SDLK_RIGHT: return K_RIGHT;
457 case SDLK_LEFT: return K_LEFT;
458 case SDLK_INSERT: return K_INSERT;
459 case SDLK_HOME: return K_HOME;
460 case SDLK_END: return K_END;
461 case SDLK_PAGEUP: return K_PAGEUP;
462 case SDLK_PAGEDOWN: return K_PAGEDOWN;
463
464 // Function keys
465 case SDLK_F1: return K_F1;
466 case SDLK_F2: return K_F2;
467 case SDLK_F3: return K_F3;
468 case SDLK_F4: return K_F4;
469 case SDLK_F5: return K_F5;
470 case SDLK_F6: return K_F6;
471 case SDLK_F7: return K_F7;
472 case SDLK_F8: return K_F8;
473 case SDLK_F9: return K_F9;
474 case SDLK_F10: return K_F10;
475 case SDLK_F11: return K_F11;
476 case SDLK_F12: return K_F12;
477 case SDLK_F13: return K_F13;
478 case SDLK_F14: return K_F14;
479 case SDLK_F15: return K_F15;
480 case SDLK_F16: return K_F16;
481 case SDLK_F17: return K_F17;
482 case SDLK_F18: return K_F18;
483 case SDLK_F19: return K_F19;
484 case SDLK_F20: return K_F20;
485 case SDLK_F21: return K_F21;
486 case SDLK_F22: return K_F22;
487 case SDLK_F23: return K_F23;
488 case SDLK_F24: return K_F24;
489
490 // Key state modifier keys
491 case SDLK_NUMLOCKCLEAR: return K_NUMLOCK;
492 case SDLK_CAPSLOCK: return K_CAPSLOCK;
493 case SDLK_SCROLLLOCK: return K_SCROLLLOCK;
494 case SDLK_RSHIFT: return K_RSHIFT;
495 case SDLK_LSHIFT: return K_LSHIFT;
496 case SDLK_RCTRL: return K_RCTRL;
497 case SDLK_LCTRL: return K_LCTRL;
498 case SDLK_RALT: return K_RALT;
499 case SDLK_LALT: return K_LALT;
500 // case SDLK_RMETA: return K_RMETA;
501 // case SDLK_LMETA: return K_LMETA;
502 case SDLK_LGUI: return K_LSUPER; // Left "Windows" key
503 case SDLK_RGUI: return K_RSUPER; // Right "Windows" key
504 case SDLK_MODE: return K_MODE; // "Alt Gr" key
505 // case SDLK_COMPOSE: return K_COMPOSE; // Multi-key compose key
506
507 // Miscellaneous function keys
508 case SDLK_HELP: return K_HELP;
509 case SDLK_PRINTSCREEN: return K_PRINT;
510 case SDLK_SYSREQ: return K_SYSREQ;
511 // case SDLK_BREAK: return K_BREAK;
512 case SDLK_APPLICATION: return K_MENU;
513 case SDLK_MENU: return K_MENU;
514 case SDLK_POWER: return K_POWER; // Power Macintosh power key
515 // case SDLK_EURO: return K_EURO; // Some european keyboards
516 case SDLK_UNDO: return K_UNDO;
517
518 // Application Control keys
519 case SDLK_AC_BACK: return K_BACK;
520
521 default: return K_UNKNOWN;
522 }
523 }();
524
525 KeyCode scan = [&] {
526 switch (sdlScanCode) {
527 case SDL_SCANCODE_BACKSPACE: return K_BACKSPACE;
528 case SDL_SCANCODE_TAB: return K_TAB;
529 case SDL_SCANCODE_CLEAR: return K_CLEAR;
530 case SDL_SCANCODE_RETURN: return K_RETURN;
531 case SDL_SCANCODE_PAUSE: return K_PAUSE;
532 case SDL_SCANCODE_ESCAPE: return K_ESCAPE;
533 case SDL_SCANCODE_SPACE: return K_SPACE;
534 case SDL_SCANCODE_APOSTROPHE: return K_QUOTE;
535 case SDL_SCANCODE_COMMA: return K_COMMA;
536 case SDL_SCANCODE_MINUS: return K_MINUS;
537 case SDL_SCANCODE_PERIOD: return K_PERIOD;
538 case SDL_SCANCODE_SLASH: return K_SLASH;
539 case SDL_SCANCODE_0: return K_0;
540 case SDL_SCANCODE_1: return K_1;
541 case SDL_SCANCODE_2: return K_2;
542 case SDL_SCANCODE_3: return K_3;
543 case SDL_SCANCODE_4: return K_4;
544 case SDL_SCANCODE_5: return K_5;
545 case SDL_SCANCODE_6: return K_6;
546 case SDL_SCANCODE_7: return K_7;
547 case SDL_SCANCODE_8: return K_8;
548 case SDL_SCANCODE_9: return K_9;
549 case SDL_SCANCODE_SEMICOLON: return K_SEMICOLON;
550 case SDL_SCANCODE_EQUALS: return K_EQUALS;
551
552 case SDL_SCANCODE_LEFTBRACKET: return K_LEFTBRACKET;
553 case SDL_SCANCODE_BACKSLASH: return K_BACKSLASH;
554 case SDL_SCANCODE_RIGHTBRACKET: return K_RIGHTBRACKET;
555 case SDL_SCANCODE_GRAVE: return K_BACKQUOTE;
556 case SDL_SCANCODE_A: return K_A;
557 case SDL_SCANCODE_B: return K_B;
558 case SDL_SCANCODE_C: return K_C;
559 case SDL_SCANCODE_D: return K_D;
560 case SDL_SCANCODE_E: return K_E;
561 case SDL_SCANCODE_F: return K_F;
562 case SDL_SCANCODE_G: return K_G;
563 case SDL_SCANCODE_H: return K_H;
564 case SDL_SCANCODE_I: return K_I;
565 case SDL_SCANCODE_J: return K_J;
566 case SDL_SCANCODE_K: return K_K;
567 case SDL_SCANCODE_L: return K_L;
568 case SDL_SCANCODE_M: return K_M;
569 case SDL_SCANCODE_N: return K_N;
570 case SDL_SCANCODE_O: return K_O;
571 case SDL_SCANCODE_P: return K_P;
572 case SDL_SCANCODE_Q: return K_Q;
573 case SDL_SCANCODE_R: return K_R;
574 case SDL_SCANCODE_S: return K_S;
575 case SDL_SCANCODE_T: return K_T;
576 case SDL_SCANCODE_U: return K_U;
577 case SDL_SCANCODE_V: return K_V;
578 case SDL_SCANCODE_W: return K_W;
579 case SDL_SCANCODE_X: return K_X;
580 case SDL_SCANCODE_Y: return K_Y;
581 case SDL_SCANCODE_Z: return K_Z;
582 case SDL_SCANCODE_DELETE: return K_DELETE;
583
584 // Numeric keypad
585 case SDL_SCANCODE_KP_0: return K_KP0;
586 case SDL_SCANCODE_KP_1: return K_KP1;
587 case SDL_SCANCODE_KP_2: return K_KP2;
588 case SDL_SCANCODE_KP_3: return K_KP3;
589 case SDL_SCANCODE_KP_4: return K_KP4;
590 case SDL_SCANCODE_KP_5: return K_KP5;
591 case SDL_SCANCODE_KP_6: return K_KP6;
592 case SDL_SCANCODE_KP_7: return K_KP7;
593 case SDL_SCANCODE_KP_8: return K_KP8;
594 case SDL_SCANCODE_KP_9: return K_KP9;
595 case SDL_SCANCODE_KP_PERIOD: return K_KP_PERIOD;
596 case SDL_SCANCODE_KP_DIVIDE: return K_KP_DIVIDE;
597 case SDL_SCANCODE_KP_MULTIPLY: return K_KP_MULTIPLY;
598 case SDL_SCANCODE_KP_MINUS: return K_KP_MINUS;
599 case SDL_SCANCODE_KP_PLUS: return K_KP_PLUS;
600 case SDL_SCANCODE_KP_ENTER: return K_KP_ENTER;
601 case SDL_SCANCODE_KP_EQUALS: return K_KP_EQUALS;
602
603 // Arrows + Home/End pad
604 case SDL_SCANCODE_UP: return K_UP;
605 case SDL_SCANCODE_DOWN: return K_DOWN;
606 case SDL_SCANCODE_RIGHT: return K_RIGHT;
607 case SDL_SCANCODE_LEFT: return K_LEFT;
608 case SDL_SCANCODE_INSERT: return K_INSERT;
609 case SDL_SCANCODE_HOME: return K_HOME;
610 case SDL_SCANCODE_END: return K_END;
611 case SDL_SCANCODE_PAGEUP: return K_PAGEUP;
612 case SDL_SCANCODE_PAGEDOWN: return K_PAGEDOWN;
613
614 // Function keys
615 case SDL_SCANCODE_F1: return K_F1;
616 case SDL_SCANCODE_F2: return K_F2;
617 case SDL_SCANCODE_F3: return K_F3;
618 case SDL_SCANCODE_F4: return K_F4;
619 case SDL_SCANCODE_F5: return K_F5;
620 case SDL_SCANCODE_F6: return K_F6;
621 case SDL_SCANCODE_F7: return K_F7;
622 case SDL_SCANCODE_F8: return K_F8;
623 case SDL_SCANCODE_F9: return K_F9;
624 case SDL_SCANCODE_F10: return K_F10;
625 case SDL_SCANCODE_F11: return K_F11;
626 case SDL_SCANCODE_F12: return K_F12;
627 case SDL_SCANCODE_F13: return K_F13;
628 case SDL_SCANCODE_F14: return K_F14;
629 case SDL_SCANCODE_F15: return K_F15;
630 case SDL_SCANCODE_F16: return K_F16;
631 case SDL_SCANCODE_F17: return K_F17;
632 case SDL_SCANCODE_F18: return K_F18;
633 case SDL_SCANCODE_F19: return K_F19;
634 case SDL_SCANCODE_F20: return K_F20;
635 case SDL_SCANCODE_F21: return K_F21;
636 case SDL_SCANCODE_F22: return K_F22;
637 case SDL_SCANCODE_F23: return K_F23;
638 case SDL_SCANCODE_F24: return K_F24;
639
640 // Key state modifier keys
641 case SDL_SCANCODE_NUMLOCKCLEAR: return K_NUMLOCK;
642 case SDL_SCANCODE_CAPSLOCK: return K_CAPSLOCK;
643 case SDL_SCANCODE_SCROLLLOCK: return K_SCROLLLOCK;
644 case SDL_SCANCODE_RSHIFT: return K_RSHIFT;
645 case SDL_SCANCODE_LSHIFT: return K_LSHIFT;
646 case SDL_SCANCODE_RCTRL: return K_RCTRL;
647 case SDL_SCANCODE_LCTRL: return K_LCTRL;
648 case SDL_SCANCODE_RALT: return K_RALT;
649 case SDL_SCANCODE_LALT: return K_LALT;
650 case SDL_SCANCODE_LGUI: return K_LSUPER; // Left "Windows" key
651 case SDL_SCANCODE_RGUI: return K_RSUPER; // Right "Windows" key
652 case SDL_SCANCODE_MODE: return K_MODE; // "Alt Gr" key
653
654 // Miscellaneous function keys
655 case SDL_SCANCODE_HELP: return K_HELP;
656 case SDL_SCANCODE_PRINTSCREEN: return K_PRINT;
657 case SDL_SCANCODE_SYSREQ: return K_SYSREQ;
658 case SDL_SCANCODE_APPLICATION: return K_MENU;
659 case SDL_SCANCODE_MENU: return K_MENU;
660 case SDL_SCANCODE_POWER: return K_POWER; // Power Macintosh power key
661 case SDL_SCANCODE_UNDO: return K_UNDO;
662
663 // Application Control keys
664 case SDL_SCANCODE_AC_BACK: return K_BACK;
665
666 default: return K_UNKNOWN;
667 }
668 }();
669
670 // Handle keys that don't have a key code but do have a scan code.
671 if (key == K_UNKNOWN) {
672 // Assume it is a Japanese keyboard and check
673 // scancode to recognize a few japanese
674 // specific keys for which SDL does not have an
675 // SDL_Keycode keysym definition.
676 switch (sdlScanCode) {
677 // Keys found on Japanese keyboards:
678 case 49:
679 key = K_ZENKAKU_HENKAKU;
680 break;
681 case 129:
682 key = K_HENKAN_MODE;
683 break;
684 //case 131:
685 // key = K_MUHENKAN;
686 // break;
687 case 208:
689 break;
690 // Keys found on Korean keyboards:
691 case 56:
692 // On Korean keyboard this code is used for R-ALT key but SDL does
693 // not seem to recognize it, as reported by Miso Kim.
694 key = K_RALT;
695 break;
696 default:
697 break; // nothing, silence compiler warning
698 }
699 }
700
701 // Apply modifiers.
702 if (mod & KMOD_CTRL) {
703 key = combine(key, KM_CTRL);
704 scan = combine(scan, KM_CTRL);
705 }
706 if (mod & KMOD_SHIFT) {
707 key = combine(key, KM_SHIFT);
708 scan = combine(scan, KM_SHIFT);
709 }
710 if (mod & KMOD_ALT) {
711 key = combine(key, KM_ALT);
712 scan = combine(scan, KM_ALT);
713 }
714 if (mod & KMOD_GUI) {
715 key = combine(key, KM_META);
716 scan = combine(scan, KM_META);
717 }
718 if (mod & KMOD_MODE) {
719 key = combine(key, KM_MODE);
720 scan = combine(scan, KM_MODE);
721 }
722
723 if (release) {
724 key = combine(key, KD_RELEASE);
725 scan = combine(scan, KD_RELEASE);
726 }
727 return {key, scan};
728}
729
730std::string getName(KeyCode keyCode)
731{
732 std::string result;
733 for (const auto& [name, code] : keys) {
734 if (code == (keyCode & K_MASK)) {
735 result = name;
736 break;
737 }
738 }
739 if (result.empty()) {
740 return "unknown";
741 }
742 if (keyCode & KM_CTRL) {
743 result += "+CTRL";
744 }
745 if (keyCode & KM_SHIFT) {
746 result += "+SHIFT";
747 }
748 if (keyCode & KM_ALT) {
749 result += "+ALT";
750 }
751 if (keyCode & KM_META) {
752 result += "+META";
753 }
754 if (keyCode & KM_MODE) {
755 result += "+MODE";
756 }
757 if (keyCode & KD_RELEASE) {
758 result += ",RELEASE";
759 }
760 return result;
761}
762
763} // namespace openmsx::Keys
KeyCode combine(KeyCode key, KeyCode modifier)
Convenience method to create key combinations (hides ugly casts).
Definition: Keys.hh:234
KeyCode
Constants that identify keys and key modifiers.
Definition: Keys.hh:26
@ K_QUESTION
Definition: Keys.hh:67
@ K_UNDERSCORE
Definition: Keys.hh:74
@ K_HIRAGANA_KATAKANA
Definition: Keys.hh:201
@ K_BACKQUOTE
Definition: Keys.hh:75
@ K_MUHENKAN
Definition: Keys.hh:199
@ K_ESCAPE
Definition: Keys.hh:36
@ K_KP_EQUALS
Definition: Keys.hh:121
@ K_HENKAN_MODE
Definition: Keys.hh:200
@ K_EXCLAIM
Definition: Keys.hh:38
@ K_KP_MULTIPLY
Definition: Keys.hh:117
@ K_BACKSPACE
Definition: Keys.hh:31
@ K_RIGHTBRACKET
Definition: Keys.hh:72
@ K_EQUALS
Definition: Keys.hh:65
@ KD_RELEASE
Definition: Keys.hh:212
@ K_KP_ENTER
Definition: Keys.hh:120
@ K_KP_PERIOD
Definition: Keys.hh:115
@ K_UNKNOWN
Definition: Keys.hh:30
@ K_PERIOD
Definition: Keys.hh:50
@ K_SEMICOLON
Definition: Keys.hh:63
@ K_DOLLAR
Definition: Keys.hh:41
@ K_ZENKAKU_HENKAKU
Definition: Keys.hh:198
@ K_KP_DIVIDE
Definition: Keys.hh:116
@ K_CAPSLOCK
Definition: Keys.hh:162
@ K_GREATER
Definition: Keys.hh:66
@ K_QUOTEDBL
Definition: Keys.hh:39
@ K_RIGHTPAREN
Definition: Keys.hh:45
@ K_BACKSLASH
Definition: Keys.hh:71
@ K_SCROLLLOCK
Definition: Keys.hh:163
@ K_RETURN
Definition: Keys.hh:34
@ K_PAGEDOWN
Definition: Keys.hh:132
@ K_KP_MINUS
Definition: Keys.hh:118
@ K_LEFTPAREN
Definition: Keys.hh:44
@ K_AMPERSAND
Definition: Keys.hh:42
@ K_LEFTBRACKET
Definition: Keys.hh:70
@ K_ASTERISK
Definition: Keys.hh:46
std::pair< KeyCode, KeyCode > getCodes(SDL_Keycode sdlKeyCode, Uint16 mod, SDL_Scancode sdlScanCode, bool release)
Translate SDL_Keycode/SDL_Scancode into openMSX key/scan Keycode's.
Definition: Keys.cc:357
KeyCode getCode(string_view name)
Translate key name to key code.
Definition: Keys.cc:330
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:730
constexpr void sort(RandomAccessRange &&range)
Definition: ranges.hh:49
auto * binary_find(ForwardRange &&range, const T &value, Compare comp={}, Proj proj={})
Definition: ranges.hh:413
bool operator()(const P &x, string_view y) const
Definition: Keys.cc:26
constexpr bool operator()(const P &x, const P &y) const
Definition: Keys.cc:21
bool operator()(string_view x, const P &y) const
Definition: Keys.cc:30
KeyCode second
Definition: Keys.cc:16
constexpr P(string_view s, KeyCode k)
Definition: Keys.cc:12
string_view first
Definition: Keys.cc:15