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