1 | /**************************************************************************/ |
2 | /* keyboard.cpp */ |
3 | /**************************************************************************/ |
4 | /* This file is part of: */ |
5 | /* GODOT ENGINE */ |
6 | /* https://godotengine.org */ |
7 | /**************************************************************************/ |
8 | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ |
9 | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ |
10 | /* */ |
11 | /* Permission is hereby granted, free of charge, to any person obtaining */ |
12 | /* a copy of this software and associated documentation files (the */ |
13 | /* "Software"), to deal in the Software without restriction, including */ |
14 | /* without limitation the rights to use, copy, modify, merge, publish, */ |
15 | /* distribute, sublicense, and/or sell copies of the Software, and to */ |
16 | /* permit persons to whom the Software is furnished to do so, subject to */ |
17 | /* the following conditions: */ |
18 | /* */ |
19 | /* The above copyright notice and this permission notice shall be */ |
20 | /* included in all copies or substantial portions of the Software. */ |
21 | /* */ |
22 | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ |
23 | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ |
24 | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ |
25 | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ |
26 | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ |
27 | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ |
28 | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
29 | /**************************************************************************/ |
30 | |
31 | #include "keyboard.h" |
32 | |
33 | #include "core/os/os.h" |
34 | |
35 | struct _KeyCodeText { |
36 | Key code; |
37 | const char *text; |
38 | }; |
39 | |
40 | static const _KeyCodeText _keycodes[] = { |
41 | /* clang-format off */ |
42 | {Key::ESCAPE ,"Escape" }, |
43 | {Key::TAB ,"Tab" }, |
44 | {Key::BACKTAB ,"Backtab" }, |
45 | {Key::BACKSPACE ,"Backspace" }, |
46 | {Key::ENTER ,"Enter" }, |
47 | {Key::KP_ENTER ,"Kp Enter" }, |
48 | {Key::INSERT ,"Insert" }, |
49 | {Key::KEY_DELETE ,"Delete" }, |
50 | {Key::PAUSE ,"Pause" }, |
51 | {Key::PRINT ,"Print" }, |
52 | {Key::SYSREQ ,"SysReq" }, |
53 | {Key::CLEAR ,"Clear" }, |
54 | {Key::HOME ,"Home" }, |
55 | {Key::END ,"End" }, |
56 | {Key::LEFT ,"Left" }, |
57 | {Key::UP ,"Up" }, |
58 | {Key::RIGHT ,"Right" }, |
59 | {Key::DOWN ,"Down" }, |
60 | {Key::PAGEUP ,"PageUp" }, |
61 | {Key::PAGEDOWN ,"PageDown" }, |
62 | {Key::SHIFT ,"Shift" }, |
63 | {Key::CTRL ,"Ctrl" }, |
64 | #if defined(MACOS_ENABLED) |
65 | {Key::META ,"Command" }, |
66 | {Key::CMD_OR_CTRL ,"Command" }, |
67 | {Key::ALT ,"Option" }, |
68 | #elif defined(WINDOWS_ENABLED) |
69 | {Key::META ,"Windows" }, |
70 | {Key::CMD_OR_CTRL ,"Ctrl" }, |
71 | {Key::ALT ,"Alt" }, |
72 | #else |
73 | {Key::META ,"Meta" }, |
74 | {Key::CMD_OR_CTRL ,"Ctrl" }, |
75 | {Key::ALT ,"Alt" }, |
76 | #endif |
77 | {Key::CAPSLOCK ,"CapsLock" }, |
78 | {Key::NUMLOCK ,"NumLock" }, |
79 | {Key::SCROLLLOCK ,"ScrollLock" }, |
80 | {Key::F1 ,"F1" }, |
81 | {Key::F2 ,"F2" }, |
82 | {Key::F3 ,"F3" }, |
83 | {Key::F4 ,"F4" }, |
84 | {Key::F5 ,"F5" }, |
85 | {Key::F6 ,"F6" }, |
86 | {Key::F7 ,"F7" }, |
87 | {Key::F8 ,"F8" }, |
88 | {Key::F9 ,"F9" }, |
89 | {Key::F10 ,"F10" }, |
90 | {Key::F11 ,"F11" }, |
91 | {Key::F12 ,"F12" }, |
92 | {Key::F13 ,"F13" }, |
93 | {Key::F14 ,"F14" }, |
94 | {Key::F15 ,"F15" }, |
95 | {Key::F16 ,"F16" }, |
96 | {Key::F17 ,"F17" }, |
97 | {Key::F18 ,"F18" }, |
98 | {Key::F19 ,"F19" }, |
99 | {Key::F20 ,"F20" }, |
100 | {Key::F21 ,"F21" }, |
101 | {Key::F22 ,"F22" }, |
102 | {Key::F23 ,"F23" }, |
103 | {Key::F24 ,"F24" }, |
104 | {Key::F25 ,"F25" }, |
105 | {Key::F26 ,"F26" }, |
106 | {Key::F27 ,"F27" }, |
107 | {Key::F28 ,"F28" }, |
108 | {Key::F29 ,"F29" }, |
109 | {Key::F30 ,"F30" }, |
110 | {Key::F31 ,"F31" }, |
111 | {Key::F32 ,"F32" }, |
112 | {Key::F33 ,"F33" }, |
113 | {Key::F34 ,"F34" }, |
114 | {Key::F35 ,"F35" }, |
115 | {Key::KP_MULTIPLY ,"Kp Multiply" }, |
116 | {Key::KP_DIVIDE ,"Kp Divide" }, |
117 | {Key::KP_SUBTRACT ,"Kp Subtract" }, |
118 | {Key::KP_PERIOD ,"Kp Period" }, |
119 | {Key::KP_ADD ,"Kp Add" }, |
120 | {Key::KP_0 ,"Kp 0" }, |
121 | {Key::KP_1 ,"Kp 1" }, |
122 | {Key::KP_2 ,"Kp 2" }, |
123 | {Key::KP_3 ,"Kp 3" }, |
124 | {Key::KP_4 ,"Kp 4" }, |
125 | {Key::KP_5 ,"Kp 5" }, |
126 | {Key::KP_6 ,"Kp 6" }, |
127 | {Key::KP_7 ,"Kp 7" }, |
128 | {Key::KP_8 ,"Kp 8" }, |
129 | {Key::KP_9 ,"Kp 9" }, |
130 | {Key::MENU ,"Menu" }, |
131 | {Key::HYPER ,"Hyper" }, |
132 | {Key::HELP ,"Help" }, |
133 | {Key::BACK ,"Back" }, |
134 | {Key::FORWARD ,"Forward" }, |
135 | {Key::STOP ,"Stop" }, |
136 | {Key::REFRESH ,"Refresh" }, |
137 | {Key::VOLUMEDOWN ,"VolumeDown" }, |
138 | {Key::VOLUMEMUTE ,"VolumeMute" }, |
139 | {Key::VOLUMEUP ,"VolumeUp" }, |
140 | {Key::MEDIAPLAY ,"MediaPlay" }, |
141 | {Key::MEDIASTOP ,"MediaStop" }, |
142 | {Key::MEDIAPREVIOUS ,"MediaPrevious" }, |
143 | {Key::MEDIANEXT ,"MediaNext" }, |
144 | {Key::MEDIARECORD ,"MediaRecord" }, |
145 | {Key::HOMEPAGE ,"HomePage" }, |
146 | {Key::FAVORITES ,"Favorites" }, |
147 | {Key::SEARCH ,"Search" }, |
148 | {Key::STANDBY ,"StandBy" }, |
149 | {Key::OPENURL ,"OpenURL" }, |
150 | {Key::LAUNCHMAIL ,"LaunchMail" }, |
151 | {Key::LAUNCHMEDIA ,"LaunchMedia" }, |
152 | {Key::LAUNCH0 ,"Launch0" }, |
153 | {Key::LAUNCH1 ,"Launch1" }, |
154 | {Key::LAUNCH2 ,"Launch2" }, |
155 | {Key::LAUNCH3 ,"Launch3" }, |
156 | {Key::LAUNCH4 ,"Launch4" }, |
157 | {Key::LAUNCH5 ,"Launch5" }, |
158 | {Key::LAUNCH6 ,"Launch6" }, |
159 | {Key::LAUNCH7 ,"Launch7" }, |
160 | {Key::LAUNCH8 ,"Launch8" }, |
161 | {Key::LAUNCH9 ,"Launch9" }, |
162 | {Key::LAUNCHA ,"LaunchA" }, |
163 | {Key::LAUNCHB ,"LaunchB" }, |
164 | {Key::LAUNCHC ,"LaunchC" }, |
165 | {Key::LAUNCHD ,"LaunchD" }, |
166 | {Key::LAUNCHE ,"LaunchE" }, |
167 | {Key::LAUNCHF ,"LaunchF" }, |
168 | {Key::GLOBE ,"Globe" }, |
169 | {Key::KEYBOARD ,"On-screen keyboard" }, |
170 | {Key::JIS_EISU ,"JIS Eisu" }, |
171 | {Key::JIS_KANA ,"JIS Kana" }, |
172 | {Key::UNKNOWN ,"Unknown" }, |
173 | {Key::SPACE ,"Space" }, |
174 | {Key::EXCLAM ,"Exclam" }, |
175 | {Key::QUOTEDBL ,"QuoteDbl" }, |
176 | {Key::NUMBERSIGN ,"NumberSign" }, |
177 | {Key::DOLLAR ,"Dollar" }, |
178 | {Key::PERCENT ,"Percent" }, |
179 | {Key::AMPERSAND ,"Ampersand" }, |
180 | {Key::APOSTROPHE ,"Apostrophe" }, |
181 | {Key::PARENLEFT ,"ParenLeft" }, |
182 | {Key::PARENRIGHT ,"ParenRight" }, |
183 | {Key::ASTERISK ,"Asterisk" }, |
184 | {Key::PLUS ,"Plus" }, |
185 | {Key::COMMA ,"Comma" }, |
186 | {Key::MINUS ,"Minus" }, |
187 | {Key::PERIOD ,"Period" }, |
188 | {Key::SLASH ,"Slash" }, |
189 | {Key::KEY_0 ,"0" }, |
190 | {Key::KEY_1 ,"1" }, |
191 | {Key::KEY_2 ,"2" }, |
192 | {Key::KEY_3 ,"3" }, |
193 | {Key::KEY_4 ,"4" }, |
194 | {Key::KEY_5 ,"5" }, |
195 | {Key::KEY_6 ,"6" }, |
196 | {Key::KEY_7 ,"7" }, |
197 | {Key::KEY_8 ,"8" }, |
198 | {Key::KEY_9 ,"9" }, |
199 | {Key::COLON ,"Colon" }, |
200 | {Key::SEMICOLON ,"Semicolon" }, |
201 | {Key::LESS ,"Less" }, |
202 | {Key::EQUAL ,"Equal" }, |
203 | {Key::GREATER ,"Greater" }, |
204 | {Key::QUESTION ,"Question" }, |
205 | {Key::AT ,"At" }, |
206 | {Key::A ,"A" }, |
207 | {Key::B ,"B" }, |
208 | {Key::C ,"C" }, |
209 | {Key::D ,"D" }, |
210 | {Key::E ,"E" }, |
211 | {Key::F ,"F" }, |
212 | {Key::G ,"G" }, |
213 | {Key::H ,"H" }, |
214 | {Key::I ,"I" }, |
215 | {Key::J ,"J" }, |
216 | {Key::K ,"K" }, |
217 | {Key::L ,"L" }, |
218 | {Key::M ,"M" }, |
219 | {Key::N ,"N" }, |
220 | {Key::O ,"O" }, |
221 | {Key::P ,"P" }, |
222 | {Key::Q ,"Q" }, |
223 | {Key::R ,"R" }, |
224 | {Key::S ,"S" }, |
225 | {Key::T ,"T" }, |
226 | {Key::U ,"U" }, |
227 | {Key::V ,"V" }, |
228 | {Key::W ,"W" }, |
229 | {Key::X ,"X" }, |
230 | {Key::Y ,"Y" }, |
231 | {Key::Z ,"Z" }, |
232 | {Key::BRACKETLEFT ,"BracketLeft" }, |
233 | {Key::BACKSLASH ,"BackSlash" }, |
234 | {Key::BRACKETRIGHT ,"BracketRight" }, |
235 | {Key::ASCIICIRCUM ,"AsciiCircum" }, |
236 | {Key::UNDERSCORE ,"UnderScore" }, |
237 | {Key::QUOTELEFT ,"QuoteLeft" }, |
238 | {Key::BRACELEFT ,"BraceLeft" }, |
239 | {Key::BAR ,"Bar" }, |
240 | {Key::BRACERIGHT ,"BraceRight" }, |
241 | {Key::ASCIITILDE ,"AsciiTilde" }, |
242 | {Key::YEN ,"Yen" }, |
243 | {Key::SECTION ,"Section" }, |
244 | {Key::NONE ,nullptr} |
245 | /* clang-format on */ |
246 | }; |
247 | |
248 | bool keycode_has_unicode(Key p_keycode) { |
249 | switch (p_keycode) { |
250 | case Key::ESCAPE: |
251 | case Key::TAB: |
252 | case Key::BACKTAB: |
253 | case Key::BACKSPACE: |
254 | case Key::ENTER: |
255 | case Key::KP_ENTER: |
256 | case Key::INSERT: |
257 | case Key::KEY_DELETE: |
258 | case Key::PAUSE: |
259 | case Key::PRINT: |
260 | case Key::SYSREQ: |
261 | case Key::CLEAR: |
262 | case Key::HOME: |
263 | case Key::END: |
264 | case Key::LEFT: |
265 | case Key::UP: |
266 | case Key::RIGHT: |
267 | case Key::DOWN: |
268 | case Key::PAGEUP: |
269 | case Key::PAGEDOWN: |
270 | case Key::SHIFT: |
271 | case Key::CTRL: |
272 | case Key::META: |
273 | case Key::ALT: |
274 | case Key::CAPSLOCK: |
275 | case Key::NUMLOCK: |
276 | case Key::SCROLLLOCK: |
277 | case Key::F1: |
278 | case Key::F2: |
279 | case Key::F3: |
280 | case Key::F4: |
281 | case Key::F5: |
282 | case Key::F6: |
283 | case Key::F7: |
284 | case Key::F8: |
285 | case Key::F9: |
286 | case Key::F10: |
287 | case Key::F11: |
288 | case Key::F12: |
289 | case Key::F13: |
290 | case Key::F14: |
291 | case Key::F15: |
292 | case Key::F16: |
293 | case Key::F17: |
294 | case Key::F18: |
295 | case Key::F19: |
296 | case Key::F20: |
297 | case Key::F21: |
298 | case Key::F22: |
299 | case Key::F23: |
300 | case Key::F24: |
301 | case Key::F25: |
302 | case Key::F26: |
303 | case Key::F27: |
304 | case Key::F28: |
305 | case Key::F29: |
306 | case Key::F30: |
307 | case Key::F31: |
308 | case Key::F32: |
309 | case Key::F33: |
310 | case Key::F34: |
311 | case Key::F35: |
312 | case Key::MENU: |
313 | case Key::HYPER: |
314 | case Key::HELP: |
315 | case Key::BACK: |
316 | case Key::FORWARD: |
317 | case Key::STOP: |
318 | case Key::REFRESH: |
319 | case Key::VOLUMEDOWN: |
320 | case Key::VOLUMEMUTE: |
321 | case Key::VOLUMEUP: |
322 | case Key::MEDIAPLAY: |
323 | case Key::MEDIASTOP: |
324 | case Key::MEDIAPREVIOUS: |
325 | case Key::MEDIANEXT: |
326 | case Key::MEDIARECORD: |
327 | case Key::HOMEPAGE: |
328 | case Key::FAVORITES: |
329 | case Key::SEARCH: |
330 | case Key::STANDBY: |
331 | case Key::OPENURL: |
332 | case Key::LAUNCHMAIL: |
333 | case Key::LAUNCHMEDIA: |
334 | case Key::LAUNCH0: |
335 | case Key::LAUNCH1: |
336 | case Key::LAUNCH2: |
337 | case Key::LAUNCH3: |
338 | case Key::LAUNCH4: |
339 | case Key::LAUNCH5: |
340 | case Key::LAUNCH6: |
341 | case Key::LAUNCH7: |
342 | case Key::LAUNCH8: |
343 | case Key::LAUNCH9: |
344 | case Key::LAUNCHA: |
345 | case Key::LAUNCHB: |
346 | case Key::LAUNCHC: |
347 | case Key::LAUNCHD: |
348 | case Key::LAUNCHE: |
349 | case Key::LAUNCHF: |
350 | case Key::GLOBE: |
351 | case Key::KEYBOARD: |
352 | case Key::JIS_EISU: |
353 | case Key::JIS_KANA: |
354 | return false; |
355 | default: { |
356 | } |
357 | } |
358 | |
359 | return true; |
360 | } |
361 | |
362 | String keycode_get_string(Key p_code) { |
363 | String codestr; |
364 | if ((p_code & KeyModifierMask::SHIFT) != Key::NONE) { |
365 | codestr += find_keycode_name(Key::SHIFT); |
366 | codestr += "+" ; |
367 | } |
368 | if ((p_code & KeyModifierMask::ALT) != Key::NONE) { |
369 | codestr += find_keycode_name(Key::ALT); |
370 | codestr += "+" ; |
371 | } |
372 | if ((p_code & KeyModifierMask::CMD_OR_CTRL) != Key::NONE) { |
373 | if (OS::get_singleton()->has_feature("macos" ) || OS::get_singleton()->has_feature("web_macos" ) || OS::get_singleton()->has_feature("web_ios" )) { |
374 | codestr += find_keycode_name(Key::META); |
375 | } else { |
376 | codestr += find_keycode_name(Key::CTRL); |
377 | } |
378 | codestr += "+" ; |
379 | } |
380 | if ((p_code & KeyModifierMask::CTRL) != Key::NONE) { |
381 | codestr += find_keycode_name(Key::CTRL); |
382 | codestr += "+" ; |
383 | } |
384 | if ((p_code & KeyModifierMask::META) != Key::NONE) { |
385 | codestr += find_keycode_name(Key::META); |
386 | codestr += "+" ; |
387 | } |
388 | |
389 | p_code &= KeyModifierMask::CODE_MASK; |
390 | |
391 | const _KeyCodeText *kct = &_keycodes[0]; |
392 | |
393 | while (kct->text) { |
394 | if (kct->code == p_code) { |
395 | codestr += kct->text; |
396 | return codestr; |
397 | } |
398 | kct++; |
399 | } |
400 | |
401 | codestr += String::chr((char32_t)p_code); |
402 | |
403 | return codestr; |
404 | } |
405 | |
406 | Key find_keycode(const String &p_codestr) { |
407 | Key keycode = Key::NONE; |
408 | Vector<String> code_parts = p_codestr.split("+" ); |
409 | if (code_parts.size() < 1) { |
410 | return keycode; |
411 | } |
412 | |
413 | String last_part = code_parts[code_parts.size() - 1]; |
414 | const _KeyCodeText *kct = &_keycodes[0]; |
415 | |
416 | while (kct->text) { |
417 | if (last_part.nocasecmp_to(kct->text) == 0) { |
418 | keycode = kct->code; |
419 | break; |
420 | } |
421 | kct++; |
422 | } |
423 | |
424 | for (int part = 0; part < code_parts.size() - 1; part++) { |
425 | String code_part = code_parts[part]; |
426 | if (code_part.nocasecmp_to(find_keycode_name(Key::SHIFT)) == 0) { |
427 | keycode |= KeyModifierMask::SHIFT; |
428 | } else if (code_part.nocasecmp_to(find_keycode_name(Key::CTRL)) == 0) { |
429 | keycode |= KeyModifierMask::CTRL; |
430 | } else if (code_part.nocasecmp_to(find_keycode_name(Key::META)) == 0) { |
431 | keycode |= KeyModifierMask::META; |
432 | } else if (code_part.nocasecmp_to(find_keycode_name(Key::ALT)) == 0) { |
433 | keycode |= KeyModifierMask::ALT; |
434 | } |
435 | } |
436 | |
437 | return keycode; |
438 | } |
439 | |
440 | const char *find_keycode_name(Key p_keycode) { |
441 | const _KeyCodeText *kct = &_keycodes[0]; |
442 | |
443 | while (kct->text) { |
444 | if (kct->code == p_keycode) { |
445 | return kct->text; |
446 | } |
447 | kct++; |
448 | } |
449 | |
450 | return "" ; |
451 | } |
452 | |
453 | int keycode_get_count() { |
454 | const _KeyCodeText *kct = &_keycodes[0]; |
455 | |
456 | int count = 0; |
457 | while (kct->text) { |
458 | count++; |
459 | kct++; |
460 | } |
461 | return count; |
462 | } |
463 | |
464 | int keycode_get_value_by_index(int p_index) { |
465 | return (int)_keycodes[p_index].code; |
466 | } |
467 | |
468 | const char *keycode_get_name_by_index(int p_index) { |
469 | return _keycodes[p_index].text; |
470 | } |
471 | |
472 | char32_t fix_unicode(char32_t p_char) { |
473 | if (p_char >= 0x20 && p_char != 0x7F) { |
474 | return p_char; |
475 | } |
476 | return 0; |
477 | } |
478 | |
479 | Key fix_keycode(char32_t p_char, Key p_key) { |
480 | if (p_char >= 0x20 && p_char <= 0x7E) { |
481 | return (Key)String::char_uppercase(p_char); |
482 | } |
483 | return p_key; |
484 | } |
485 | |
486 | Key fix_key_label(char32_t p_char, Key p_key) { |
487 | if (p_char >= 0x20 && p_char != 0x7F) { |
488 | return (Key)String::char_uppercase(p_char); |
489 | } |
490 | return p_key; |
491 | } |
492 | |