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