1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22
23 /* General keyboard handling code for SDL */
24
25 #include "SDL_timer.h"
26 #include "SDL_events.h"
27 #include "SDL_events_c.h"
28 #include "SDL_assert.h"
29 #include "../video/SDL_sysvideo.h"
30
31
32 /* #define DEBUG_KEYBOARD */
33
34 /* Global keyboard information */
35
36 #define KEYBOARD_HARDWARE 0x01
37 #define KEYBOARD_AUTORELEASE 0x02
38
39 typedef struct SDL_Keyboard SDL_Keyboard;
40
41 struct SDL_Keyboard
42 {
43 /* Data common to all keyboards */
44 SDL_Window *focus;
45 Uint16 modstate;
46 Uint8 keysource[SDL_NUM_SCANCODES];
47 Uint8 keystate[SDL_NUM_SCANCODES];
48 SDL_Keycode keymap[SDL_NUM_SCANCODES];
49 SDL_bool autorelease_pending;
50 };
51
52 static SDL_Keyboard SDL_keyboard;
53
54 static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = {
55 0, 0, 0, 0,
56 'a',
57 'b',
58 'c',
59 'd',
60 'e',
61 'f',
62 'g',
63 'h',
64 'i',
65 'j',
66 'k',
67 'l',
68 'm',
69 'n',
70 'o',
71 'p',
72 'q',
73 'r',
74 's',
75 't',
76 'u',
77 'v',
78 'w',
79 'x',
80 'y',
81 'z',
82 '1',
83 '2',
84 '3',
85 '4',
86 '5',
87 '6',
88 '7',
89 '8',
90 '9',
91 '0',
92 SDLK_RETURN,
93 SDLK_ESCAPE,
94 SDLK_BACKSPACE,
95 SDLK_TAB,
96 SDLK_SPACE,
97 '-',
98 '=',
99 '[',
100 ']',
101 '\\',
102 '#',
103 ';',
104 '\'',
105 '`',
106 ',',
107 '.',
108 '/',
109 SDLK_CAPSLOCK,
110 SDLK_F1,
111 SDLK_F2,
112 SDLK_F3,
113 SDLK_F4,
114 SDLK_F5,
115 SDLK_F6,
116 SDLK_F7,
117 SDLK_F8,
118 SDLK_F9,
119 SDLK_F10,
120 SDLK_F11,
121 SDLK_F12,
122 SDLK_PRINTSCREEN,
123 SDLK_SCROLLLOCK,
124 SDLK_PAUSE,
125 SDLK_INSERT,
126 SDLK_HOME,
127 SDLK_PAGEUP,
128 SDLK_DELETE,
129 SDLK_END,
130 SDLK_PAGEDOWN,
131 SDLK_RIGHT,
132 SDLK_LEFT,
133 SDLK_DOWN,
134 SDLK_UP,
135 SDLK_NUMLOCKCLEAR,
136 SDLK_KP_DIVIDE,
137 SDLK_KP_MULTIPLY,
138 SDLK_KP_MINUS,
139 SDLK_KP_PLUS,
140 SDLK_KP_ENTER,
141 SDLK_KP_1,
142 SDLK_KP_2,
143 SDLK_KP_3,
144 SDLK_KP_4,
145 SDLK_KP_5,
146 SDLK_KP_6,
147 SDLK_KP_7,
148 SDLK_KP_8,
149 SDLK_KP_9,
150 SDLK_KP_0,
151 SDLK_KP_PERIOD,
152 0,
153 SDLK_APPLICATION,
154 SDLK_POWER,
155 SDLK_KP_EQUALS,
156 SDLK_F13,
157 SDLK_F14,
158 SDLK_F15,
159 SDLK_F16,
160 SDLK_F17,
161 SDLK_F18,
162 SDLK_F19,
163 SDLK_F20,
164 SDLK_F21,
165 SDLK_F22,
166 SDLK_F23,
167 SDLK_F24,
168 SDLK_EXECUTE,
169 SDLK_HELP,
170 SDLK_MENU,
171 SDLK_SELECT,
172 SDLK_STOP,
173 SDLK_AGAIN,
174 SDLK_UNDO,
175 SDLK_CUT,
176 SDLK_COPY,
177 SDLK_PASTE,
178 SDLK_FIND,
179 SDLK_MUTE,
180 SDLK_VOLUMEUP,
181 SDLK_VOLUMEDOWN,
182 0, 0, 0,
183 SDLK_KP_COMMA,
184 SDLK_KP_EQUALSAS400,
185 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186 SDLK_ALTERASE,
187 SDLK_SYSREQ,
188 SDLK_CANCEL,
189 SDLK_CLEAR,
190 SDLK_PRIOR,
191 SDLK_RETURN2,
192 SDLK_SEPARATOR,
193 SDLK_OUT,
194 SDLK_OPER,
195 SDLK_CLEARAGAIN,
196 SDLK_CRSEL,
197 SDLK_EXSEL,
198 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
199 SDLK_KP_00,
200 SDLK_KP_000,
201 SDLK_THOUSANDSSEPARATOR,
202 SDLK_DECIMALSEPARATOR,
203 SDLK_CURRENCYUNIT,
204 SDLK_CURRENCYSUBUNIT,
205 SDLK_KP_LEFTPAREN,
206 SDLK_KP_RIGHTPAREN,
207 SDLK_KP_LEFTBRACE,
208 SDLK_KP_RIGHTBRACE,
209 SDLK_KP_TAB,
210 SDLK_KP_BACKSPACE,
211 SDLK_KP_A,
212 SDLK_KP_B,
213 SDLK_KP_C,
214 SDLK_KP_D,
215 SDLK_KP_E,
216 SDLK_KP_F,
217 SDLK_KP_XOR,
218 SDLK_KP_POWER,
219 SDLK_KP_PERCENT,
220 SDLK_KP_LESS,
221 SDLK_KP_GREATER,
222 SDLK_KP_AMPERSAND,
223 SDLK_KP_DBLAMPERSAND,
224 SDLK_KP_VERTICALBAR,
225 SDLK_KP_DBLVERTICALBAR,
226 SDLK_KP_COLON,
227 SDLK_KP_HASH,
228 SDLK_KP_SPACE,
229 SDLK_KP_AT,
230 SDLK_KP_EXCLAM,
231 SDLK_KP_MEMSTORE,
232 SDLK_KP_MEMRECALL,
233 SDLK_KP_MEMCLEAR,
234 SDLK_KP_MEMADD,
235 SDLK_KP_MEMSUBTRACT,
236 SDLK_KP_MEMMULTIPLY,
237 SDLK_KP_MEMDIVIDE,
238 SDLK_KP_PLUSMINUS,
239 SDLK_KP_CLEAR,
240 SDLK_KP_CLEARENTRY,
241 SDLK_KP_BINARY,
242 SDLK_KP_OCTAL,
243 SDLK_KP_DECIMAL,
244 SDLK_KP_HEXADECIMAL,
245 0, 0,
246 SDLK_LCTRL,
247 SDLK_LSHIFT,
248 SDLK_LALT,
249 SDLK_LGUI,
250 SDLK_RCTRL,
251 SDLK_RSHIFT,
252 SDLK_RALT,
253 SDLK_RGUI,
254 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255 SDLK_MODE,
256 SDLK_AUDIONEXT,
257 SDLK_AUDIOPREV,
258 SDLK_AUDIOSTOP,
259 SDLK_AUDIOPLAY,
260 SDLK_AUDIOMUTE,
261 SDLK_MEDIASELECT,
262 SDLK_WWW,
263 SDLK_MAIL,
264 SDLK_CALCULATOR,
265 SDLK_COMPUTER,
266 SDLK_AC_SEARCH,
267 SDLK_AC_HOME,
268 SDLK_AC_BACK,
269 SDLK_AC_FORWARD,
270 SDLK_AC_STOP,
271 SDLK_AC_REFRESH,
272 SDLK_AC_BOOKMARKS,
273 SDLK_BRIGHTNESSDOWN,
274 SDLK_BRIGHTNESSUP,
275 SDLK_DISPLAYSWITCH,
276 SDLK_KBDILLUMTOGGLE,
277 SDLK_KBDILLUMDOWN,
278 SDLK_KBDILLUMUP,
279 SDLK_EJECT,
280 SDLK_SLEEP,
281 SDLK_APP1,
282 SDLK_APP2,
283 SDLK_AUDIOREWIND,
284 SDLK_AUDIOFASTFORWARD,
285 };
286
287 static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
288 NULL, NULL, NULL, NULL,
289 "A",
290 "B",
291 "C",
292 "D",
293 "E",
294 "F",
295 "G",
296 "H",
297 "I",
298 "J",
299 "K",
300 "L",
301 "M",
302 "N",
303 "O",
304 "P",
305 "Q",
306 "R",
307 "S",
308 "T",
309 "U",
310 "V",
311 "W",
312 "X",
313 "Y",
314 "Z",
315 "1",
316 "2",
317 "3",
318 "4",
319 "5",
320 "6",
321 "7",
322 "8",
323 "9",
324 "0",
325 "Return",
326 "Escape",
327 "Backspace",
328 "Tab",
329 "Space",
330 "-",
331 "=",
332 "[",
333 "]",
334 "\\",
335 "#",
336 ";",
337 "'",
338 "`",
339 ",",
340 ".",
341 "/",
342 "CapsLock",
343 "F1",
344 "F2",
345 "F3",
346 "F4",
347 "F5",
348 "F6",
349 "F7",
350 "F8",
351 "F9",
352 "F10",
353 "F11",
354 "F12",
355 "PrintScreen",
356 "ScrollLock",
357 "Pause",
358 "Insert",
359 "Home",
360 "PageUp",
361 "Delete",
362 "End",
363 "PageDown",
364 "Right",
365 "Left",
366 "Down",
367 "Up",
368 "Numlock",
369 "Keypad /",
370 "Keypad *",
371 "Keypad -",
372 "Keypad +",
373 "Keypad Enter",
374 "Keypad 1",
375 "Keypad 2",
376 "Keypad 3",
377 "Keypad 4",
378 "Keypad 5",
379 "Keypad 6",
380 "Keypad 7",
381 "Keypad 8",
382 "Keypad 9",
383 "Keypad 0",
384 "Keypad .",
385 NULL,
386 "Application",
387 "Power",
388 "Keypad =",
389 "F13",
390 "F14",
391 "F15",
392 "F16",
393 "F17",
394 "F18",
395 "F19",
396 "F20",
397 "F21",
398 "F22",
399 "F23",
400 "F24",
401 "Execute",
402 "Help",
403 "Menu",
404 "Select",
405 "Stop",
406 "Again",
407 "Undo",
408 "Cut",
409 "Copy",
410 "Paste",
411 "Find",
412 "Mute",
413 "VolumeUp",
414 "VolumeDown",
415 NULL, NULL, NULL,
416 "Keypad ,",
417 "Keypad = (AS400)",
418 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
419 NULL, NULL, NULL, NULL, NULL, NULL,
420 "AltErase",
421 "SysReq",
422 "Cancel",
423 "Clear",
424 "Prior",
425 "Return",
426 "Separator",
427 "Out",
428 "Oper",
429 "Clear / Again",
430 "CrSel",
431 "ExSel",
432 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
433 "Keypad 00",
434 "Keypad 000",
435 "ThousandsSeparator",
436 "DecimalSeparator",
437 "CurrencyUnit",
438 "CurrencySubUnit",
439 "Keypad (",
440 "Keypad )",
441 "Keypad {",
442 "Keypad }",
443 "Keypad Tab",
444 "Keypad Backspace",
445 "Keypad A",
446 "Keypad B",
447 "Keypad C",
448 "Keypad D",
449 "Keypad E",
450 "Keypad F",
451 "Keypad XOR",
452 "Keypad ^",
453 "Keypad %",
454 "Keypad <",
455 "Keypad >",
456 "Keypad &",
457 "Keypad &&",
458 "Keypad |",
459 "Keypad ||",
460 "Keypad :",
461 "Keypad #",
462 "Keypad Space",
463 "Keypad @",
464 "Keypad !",
465 "Keypad MemStore",
466 "Keypad MemRecall",
467 "Keypad MemClear",
468 "Keypad MemAdd",
469 "Keypad MemSubtract",
470 "Keypad MemMultiply",
471 "Keypad MemDivide",
472 "Keypad +/-",
473 "Keypad Clear",
474 "Keypad ClearEntry",
475 "Keypad Binary",
476 "Keypad Octal",
477 "Keypad Decimal",
478 "Keypad Hexadecimal",
479 NULL, NULL,
480 "Left Ctrl",
481 "Left Shift",
482 "Left Alt",
483 "Left GUI",
484 "Right Ctrl",
485 "Right Shift",
486 "Right Alt",
487 "Right GUI",
488 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
489 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
490 NULL,
491 "ModeSwitch",
492 "AudioNext",
493 "AudioPrev",
494 "AudioStop",
495 "AudioPlay",
496 "AudioMute",
497 "MediaSelect",
498 "WWW",
499 "Mail",
500 "Calculator",
501 "Computer",
502 "AC Search",
503 "AC Home",
504 "AC Back",
505 "AC Forward",
506 "AC Stop",
507 "AC Refresh",
508 "AC Bookmarks",
509 "BrightnessDown",
510 "BrightnessUp",
511 "DisplaySwitch",
512 "KBDIllumToggle",
513 "KBDIllumDown",
514 "KBDIllumUp",
515 "Eject",
516 "Sleep",
517 "App1",
518 "App2",
519 "AudioRewind",
520 "AudioFastForward",
521 };
522
523 /* Taken from SDL_iconv() */
524 char *
SDL_UCS4ToUTF8(Uint32 ch,char * dst)525 SDL_UCS4ToUTF8(Uint32 ch, char *dst)
526 {
527 Uint8 *p = (Uint8 *) dst;
528 if (ch <= 0x7F) {
529 *p = (Uint8) ch;
530 ++dst;
531 } else if (ch <= 0x7FF) {
532 p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
533 p[1] = 0x80 | (Uint8) (ch & 0x3F);
534 dst += 2;
535 } else if (ch <= 0xFFFF) {
536 p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
537 p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
538 p[2] = 0x80 | (Uint8) (ch & 0x3F);
539 dst += 3;
540 } else if (ch <= 0x1FFFFF) {
541 p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
542 p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
543 p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
544 p[3] = 0x80 | (Uint8) (ch & 0x3F);
545 dst += 4;
546 } else if (ch <= 0x3FFFFFF) {
547 p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
548 p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
549 p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
550 p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
551 p[4] = 0x80 | (Uint8) (ch & 0x3F);
552 dst += 5;
553 } else {
554 p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
555 p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
556 p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
557 p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
558 p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
559 p[5] = 0x80 | (Uint8) (ch & 0x3F);
560 dst += 6;
561 }
562 return dst;
563 }
564
565 /* Public functions */
566 int
SDL_KeyboardInit(void)567 SDL_KeyboardInit(void)
568 {
569 SDL_Keyboard *keyboard = &SDL_keyboard;
570
571 /* Set the default keymap */
572 SDL_memcpy(keyboard->keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
573 return (0);
574 }
575
576 void
SDL_ResetKeyboard(void)577 SDL_ResetKeyboard(void)
578 {
579 SDL_Keyboard *keyboard = &SDL_keyboard;
580 SDL_Scancode scancode;
581
582 #ifdef DEBUG_KEYBOARD
583 printf("Resetting keyboard\n");
584 #endif
585 for (scancode = (SDL_Scancode) 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
586 if (keyboard->keystate[scancode] == SDL_PRESSED) {
587 SDL_SendKeyboardKey(SDL_RELEASED, scancode);
588 }
589 }
590 }
591
592 void
SDL_GetDefaultKeymap(SDL_Keycode * keymap)593 SDL_GetDefaultKeymap(SDL_Keycode * keymap)
594 {
595 SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
596 }
597
598 void
SDL_SetKeymap(int start,SDL_Keycode * keys,int length)599 SDL_SetKeymap(int start, SDL_Keycode * keys, int length)
600 {
601 SDL_Keyboard *keyboard = &SDL_keyboard;
602 SDL_Scancode scancode;
603
604 if (start < 0 || start + length > SDL_NUM_SCANCODES) {
605 return;
606 }
607
608 SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
609
610 /* The number key scancodes always map to the number key keycodes.
611 * On AZERTY layouts these technically are symbols, but users (and games)
612 * always think of them and view them in UI as number keys.
613 */
614 keyboard->keymap[SDL_SCANCODE_0] = SDLK_0;
615 for (scancode = SDL_SCANCODE_1; scancode <= SDL_SCANCODE_9; ++scancode) {
616 keyboard->keymap[scancode] = SDLK_1 + (scancode - SDL_SCANCODE_1);
617 }
618 }
619
620 void
SDL_SetScancodeName(SDL_Scancode scancode,const char * name)621 SDL_SetScancodeName(SDL_Scancode scancode, const char *name)
622 {
623 SDL_scancode_names[scancode] = name;
624 }
625
626 SDL_Window *
SDL_GetKeyboardFocus(void)627 SDL_GetKeyboardFocus(void)
628 {
629 SDL_Keyboard *keyboard = &SDL_keyboard;
630
631 return keyboard->focus;
632 }
633
634 void
SDL_SetKeyboardFocus(SDL_Window * window)635 SDL_SetKeyboardFocus(SDL_Window * window)
636 {
637 SDL_Keyboard *keyboard = &SDL_keyboard;
638
639 if (keyboard->focus && !window) {
640 /* We won't get anymore keyboard messages, so reset keyboard state */
641 SDL_ResetKeyboard();
642 }
643
644 /* See if the current window has lost focus */
645 if (keyboard->focus && keyboard->focus != window) {
646
647 /* new window shouldn't think it has mouse captured. */
648 SDL_assert(!window || !(window->flags & SDL_WINDOW_MOUSE_CAPTURE));
649
650 /* old window must lose an existing mouse capture. */
651 if (keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE) {
652 SDL_CaptureMouse(SDL_FALSE); /* drop the capture. */
653 SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE));
654 }
655
656 SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
657 0, 0);
658
659 /* Ensures IME compositions are committed */
660 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
661 SDL_VideoDevice *video = SDL_GetVideoDevice();
662 if (video && video->StopTextInput) {
663 video->StopTextInput(video);
664 }
665 }
666 }
667
668 keyboard->focus = window;
669
670 if (keyboard->focus) {
671 SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
672 0, 0);
673
674 if (SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
675 SDL_VideoDevice *video = SDL_GetVideoDevice();
676 if (video && video->StartTextInput) {
677 video->StartTextInput(video);
678 }
679 }
680 }
681 }
682
683 static int
SDL_SendKeyboardKeyInternal(Uint8 source,Uint8 state,SDL_Scancode scancode)684 SDL_SendKeyboardKeyInternal(Uint8 source, Uint8 state, SDL_Scancode scancode)
685 {
686 SDL_Keyboard *keyboard = &SDL_keyboard;
687 int posted;
688 SDL_Keymod modifier;
689 SDL_Keycode keycode;
690 Uint32 type;
691 Uint8 repeat = SDL_FALSE;
692
693 if (scancode == SDL_SCANCODE_UNKNOWN) {
694 return 0;
695 }
696
697 #ifdef DEBUG_KEYBOARD
698 printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
699 state == SDL_PRESSED ? "pressed" : "released");
700 #endif
701
702 /* Figure out what type of event this is */
703 switch (state) {
704 case SDL_PRESSED:
705 type = SDL_KEYDOWN;
706 break;
707 case SDL_RELEASED:
708 type = SDL_KEYUP;
709 break;
710 default:
711 /* Invalid state -- bail */
712 return 0;
713 }
714
715 /* Drop events that don't change state */
716 if (state) {
717 if (keyboard->keystate[scancode]) {
718 if (!(keyboard->keysource[scancode] & source)) {
719 keyboard->keysource[scancode] |= source;
720 return 0;
721 }
722 repeat = SDL_TRUE;
723 }
724 keyboard->keysource[scancode] |= source;
725 } else {
726 if (!keyboard->keystate[scancode]) {
727 return 0;
728 }
729 keyboard->keysource[scancode] = 0;
730 }
731
732 /* Update internal keyboard state */
733 keyboard->keystate[scancode] = state;
734
735 keycode = keyboard->keymap[scancode];
736
737 if (source == KEYBOARD_AUTORELEASE) {
738 keyboard->autorelease_pending = SDL_TRUE;
739 }
740
741 /* Update modifiers state if applicable */
742 switch (keycode) {
743 case SDLK_LCTRL:
744 modifier = KMOD_LCTRL;
745 break;
746 case SDLK_RCTRL:
747 modifier = KMOD_RCTRL;
748 break;
749 case SDLK_LSHIFT:
750 modifier = KMOD_LSHIFT;
751 break;
752 case SDLK_RSHIFT:
753 modifier = KMOD_RSHIFT;
754 break;
755 case SDLK_LALT:
756 modifier = KMOD_LALT;
757 break;
758 case SDLK_RALT:
759 modifier = KMOD_RALT;
760 break;
761 case SDLK_LGUI:
762 modifier = KMOD_LGUI;
763 break;
764 case SDLK_RGUI:
765 modifier = KMOD_RGUI;
766 break;
767 case SDLK_MODE:
768 modifier = KMOD_MODE;
769 break;
770 default:
771 modifier = KMOD_NONE;
772 break;
773 }
774 if (SDL_KEYDOWN == type) {
775 switch (keycode) {
776 case SDLK_NUMLOCKCLEAR:
777 keyboard->modstate ^= KMOD_NUM;
778 break;
779 case SDLK_CAPSLOCK:
780 keyboard->modstate ^= KMOD_CAPS;
781 break;
782 default:
783 keyboard->modstate |= modifier;
784 break;
785 }
786 } else {
787 keyboard->modstate &= ~modifier;
788 }
789
790 /* Post the event, if desired */
791 posted = 0;
792 if (SDL_GetEventState(type) == SDL_ENABLE) {
793 SDL_Event event;
794 event.key.type = type;
795 event.key.state = state;
796 event.key.repeat = repeat;
797 event.key.keysym.scancode = scancode;
798 event.key.keysym.sym = keycode;
799 event.key.keysym.mod = keyboard->modstate;
800 event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
801 posted = (SDL_PushEvent(&event) > 0);
802 }
803 return (posted);
804 }
805
806 int
SDL_SendKeyboardKey(Uint8 state,SDL_Scancode scancode)807 SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
808 {
809 return SDL_SendKeyboardKeyInternal(KEYBOARD_HARDWARE, state, scancode);
810 }
811
812 int
SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode)813 SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode)
814 {
815 return SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_PRESSED, scancode);
816 }
817
818 void
SDL_ReleaseAutoReleaseKeys(void)819 SDL_ReleaseAutoReleaseKeys(void)
820 {
821 SDL_Keyboard *keyboard = &SDL_keyboard;
822 SDL_Scancode scancode;
823
824 if (keyboard->autorelease_pending) {
825 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
826 if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) {
827 SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_RELEASED, scancode);
828 }
829 }
830 keyboard->autorelease_pending = SDL_FALSE;
831 }
832 }
833
834 SDL_bool
SDL_HardwareKeyboardKeyPressed(void)835 SDL_HardwareKeyboardKeyPressed(void)
836 {
837 SDL_Keyboard *keyboard = &SDL_keyboard;
838 SDL_Scancode scancode;
839
840 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
841 if ((keyboard->keysource[scancode] & KEYBOARD_HARDWARE) != 0) {
842 return SDL_TRUE;
843 }
844 }
845 return SDL_FALSE;
846 }
847
848 int
SDL_SendKeyboardText(const char * text)849 SDL_SendKeyboardText(const char *text)
850 {
851 SDL_Keyboard *keyboard = &SDL_keyboard;
852 int posted;
853
854 /* Don't post text events for unprintable characters */
855 if ((unsigned char)*text < ' ' || *text == 127) {
856 return 0;
857 }
858
859 /* Post the event, if desired */
860 posted = 0;
861 if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) {
862 SDL_Event event;
863 event.text.type = SDL_TEXTINPUT;
864 event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
865 SDL_utf8strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
866 posted = (SDL_PushEvent(&event) > 0);
867 }
868 return (posted);
869 }
870
871 int
SDL_SendEditingText(const char * text,int start,int length)872 SDL_SendEditingText(const char *text, int start, int length)
873 {
874 SDL_Keyboard *keyboard = &SDL_keyboard;
875 int posted;
876
877 /* Post the event, if desired */
878 posted = 0;
879 if (SDL_GetEventState(SDL_TEXTEDITING) == SDL_ENABLE) {
880 SDL_Event event;
881 event.edit.type = SDL_TEXTEDITING;
882 event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
883 event.edit.start = start;
884 event.edit.length = length;
885 SDL_utf8strlcpy(event.edit.text, text, SDL_arraysize(event.edit.text));
886 posted = (SDL_PushEvent(&event) > 0);
887 }
888 return (posted);
889 }
890
891 void
SDL_KeyboardQuit(void)892 SDL_KeyboardQuit(void)
893 {
894 }
895
896 const Uint8 *
SDL_GetKeyboardState(int * numkeys)897 SDL_GetKeyboardState(int *numkeys)
898 {
899 SDL_Keyboard *keyboard = &SDL_keyboard;
900
901 if (numkeys != (int *) 0) {
902 *numkeys = SDL_NUM_SCANCODES;
903 }
904 return keyboard->keystate;
905 }
906
907 SDL_Keymod
SDL_GetModState(void)908 SDL_GetModState(void)
909 {
910 SDL_Keyboard *keyboard = &SDL_keyboard;
911
912 return (SDL_Keymod) keyboard->modstate;
913 }
914
915 void
SDL_SetModState(SDL_Keymod modstate)916 SDL_SetModState(SDL_Keymod modstate)
917 {
918 SDL_Keyboard *keyboard = &SDL_keyboard;
919
920 keyboard->modstate = modstate;
921 }
922
923 /* Note that SDL_ToggleModState() is not a public API. SDL_SetModState() is. */
924 void
SDL_ToggleModState(const SDL_Keymod modstate,const SDL_bool toggle)925 SDL_ToggleModState(const SDL_Keymod modstate, const SDL_bool toggle)
926 {
927 SDL_Keyboard *keyboard = &SDL_keyboard;
928 if (toggle) {
929 keyboard->modstate |= modstate;
930 } else {
931 keyboard->modstate &= ~modstate;
932 }
933 }
934
935
936 SDL_Keycode
SDL_GetKeyFromScancode(SDL_Scancode scancode)937 SDL_GetKeyFromScancode(SDL_Scancode scancode)
938 {
939 SDL_Keyboard *keyboard = &SDL_keyboard;
940
941 if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
942 SDL_InvalidParamError("scancode");
943 return 0;
944 }
945
946 return keyboard->keymap[scancode];
947 }
948
949 SDL_Scancode
SDL_GetScancodeFromKey(SDL_Keycode key)950 SDL_GetScancodeFromKey(SDL_Keycode key)
951 {
952 SDL_Keyboard *keyboard = &SDL_keyboard;
953 SDL_Scancode scancode;
954
955 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
956 ++scancode) {
957 if (keyboard->keymap[scancode] == key) {
958 return scancode;
959 }
960 }
961 return SDL_SCANCODE_UNKNOWN;
962 }
963
964 const char *
SDL_GetScancodeName(SDL_Scancode scancode)965 SDL_GetScancodeName(SDL_Scancode scancode)
966 {
967 const char *name;
968 if (((int)scancode) < SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
969 SDL_InvalidParamError("scancode");
970 return "";
971 }
972
973 name = SDL_scancode_names[scancode];
974 if (name)
975 return name;
976 else
977 return "";
978 }
979
SDL_GetScancodeFromName(const char * name)980 SDL_Scancode SDL_GetScancodeFromName(const char *name)
981 {
982 int i;
983
984 if (!name || !*name) {
985 SDL_InvalidParamError("name");
986 return SDL_SCANCODE_UNKNOWN;
987 }
988
989 for (i = 0; i < SDL_arraysize(SDL_scancode_names); ++i) {
990 if (!SDL_scancode_names[i]) {
991 continue;
992 }
993 if (SDL_strcasecmp(name, SDL_scancode_names[i]) == 0) {
994 return (SDL_Scancode)i;
995 }
996 }
997
998 SDL_InvalidParamError("name");
999 return SDL_SCANCODE_UNKNOWN;
1000 }
1001
1002 const char *
SDL_GetKeyName(SDL_Keycode key)1003 SDL_GetKeyName(SDL_Keycode key)
1004 {
1005 static char name[8];
1006 char *end;
1007
1008 if (key & SDLK_SCANCODE_MASK) {
1009 return
1010 SDL_GetScancodeName((SDL_Scancode) (key & ~SDLK_SCANCODE_MASK));
1011 }
1012
1013 switch (key) {
1014 case SDLK_RETURN:
1015 return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
1016 case SDLK_ESCAPE:
1017 return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
1018 case SDLK_BACKSPACE:
1019 return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
1020 case SDLK_TAB:
1021 return SDL_GetScancodeName(SDL_SCANCODE_TAB);
1022 case SDLK_SPACE:
1023 return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
1024 case SDLK_DELETE:
1025 return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
1026 default:
1027 /* Unaccented letter keys on latin keyboards are normally
1028 labeled in upper case (and probably on others like Greek or
1029 Cyrillic too, so if you happen to know for sure, please
1030 adapt this). */
1031 if (key >= 'a' && key <= 'z') {
1032 key -= 32;
1033 }
1034
1035 end = SDL_UCS4ToUTF8((Uint32) key, name);
1036 *end = '\0';
1037 return name;
1038 }
1039 }
1040
1041 SDL_Keycode
SDL_GetKeyFromName(const char * name)1042 SDL_GetKeyFromName(const char *name)
1043 {
1044 SDL_Keycode key;
1045
1046 /* Check input */
1047 if (name == NULL) {
1048 return SDLK_UNKNOWN;
1049 }
1050
1051 /* If it's a single UTF-8 character, then that's the keycode itself */
1052 key = *(const unsigned char *)name;
1053 if (key >= 0xF0) {
1054 if (SDL_strlen(name) == 4) {
1055 int i = 0;
1056 key = (Uint16)(name[i]&0x07) << 18;
1057 key |= (Uint16)(name[++i]&0x3F) << 12;
1058 key |= (Uint16)(name[++i]&0x3F) << 6;
1059 key |= (Uint16)(name[++i]&0x3F);
1060 return key;
1061 }
1062 return SDLK_UNKNOWN;
1063 } else if (key >= 0xE0) {
1064 if (SDL_strlen(name) == 3) {
1065 int i = 0;
1066 key = (Uint16)(name[i]&0x0F) << 12;
1067 key |= (Uint16)(name[++i]&0x3F) << 6;
1068 key |= (Uint16)(name[++i]&0x3F);
1069 return key;
1070 }
1071 return SDLK_UNKNOWN;
1072 } else if (key >= 0xC0) {
1073 if (SDL_strlen(name) == 2) {
1074 int i = 0;
1075 key = (Uint16)(name[i]&0x1F) << 6;
1076 key |= (Uint16)(name[++i]&0x3F);
1077 return key;
1078 }
1079 return SDLK_UNKNOWN;
1080 } else {
1081 if (SDL_strlen(name) == 1) {
1082 if (key >= 'A' && key <= 'Z') {
1083 key += 32;
1084 }
1085 return key;
1086 }
1087
1088 /* Get the scancode for this name, and the associated keycode */
1089 return SDL_default_keymap[SDL_GetScancodeFromName(name)];
1090 }
1091 }
1092
1093 /* vi: set ts=4 sw=4 expandtab: */
1094