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