2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "SDL_config.h"
24 /* General keyboard handling code for SDL */
26 #include "SDL_timer.h"
27 #include "SDL_events.h"
28 #include "SDL_events_c.h"
29 #include "SDL_sysevents.h"
32 /* Global keyboard information */
33 static int SDL_num_keyboards;
34 static int SDL_current_keyboard;
35 static SDL_Keyboard **SDL_keyboards;
37 static const SDLKey SDL_default_keymap[SDL_NUM_SCANCODES] = {
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184 SDLK_THOUSANDSSEPARATOR,
185 SDLK_DECIMALSEPARATOR,
187 SDLK_CURRENCYSUBUNIT,
206 SDLK_KP_DBLAMPERSAND,
208 SDLK_KP_DBLVERTICALBAR,
237 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,
266 static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
267 NULL, NULL, NULL, NULL,
397 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
398 NULL, NULL, NULL, NULL, NULL, NULL,
411 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
414 "ThousandsSeparator",
448 "Keypad MemSubtract",
449 "Keypad MemMultiply",
457 "Keypad Hexadecimal",
467 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
468 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
498 /* Taken from SDL_iconv() */
500 SDL_UCS4ToUTF8(Uint32 ch, char *dst)
502 Uint8 *p = (Uint8 *) dst;
506 } else if (ch <= 0x7FF) {
507 p[0] = 0xC0 | (Uint8) ((ch >> 6) & 0x1F);
508 p[1] = 0x80 | (Uint8) (ch & 0x3F);
510 } else if (ch <= 0xFFFF) {
511 p[0] = 0xE0 | (Uint8) ((ch >> 12) & 0x0F);
512 p[1] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
513 p[2] = 0x80 | (Uint8) (ch & 0x3F);
515 } else if (ch <= 0x1FFFFF) {
516 p[0] = 0xF0 | (Uint8) ((ch >> 18) & 0x07);
517 p[1] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
518 p[2] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
519 p[3] = 0x80 | (Uint8) (ch & 0x3F);
521 } else if (ch <= 0x3FFFFFF) {
522 p[0] = 0xF8 | (Uint8) ((ch >> 24) & 0x03);
523 p[1] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
524 p[2] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
525 p[3] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
526 p[4] = 0x80 | (Uint8) (ch & 0x3F);
529 p[0] = 0xFC | (Uint8) ((ch >> 30) & 0x01);
530 p[1] = 0x80 | (Uint8) ((ch >> 24) & 0x3F);
531 p[2] = 0x80 | (Uint8) ((ch >> 18) & 0x3F);
532 p[3] = 0x80 | (Uint8) ((ch >> 12) & 0x3F);
533 p[4] = 0x80 | (Uint8) ((ch >> 6) & 0x3F);
534 p[5] = 0x80 | (Uint8) (ch & 0x3F);
540 /* Public functions */
542 SDL_KeyboardInit(void)
548 SDL_GetKeyboard(int index)
550 if (index < 0 || index >= SDL_num_keyboards) {
553 return SDL_keyboards[index];
557 SDL_AddKeyboard(const SDL_Keyboard * keyboard, int index)
559 SDL_Keyboard **keyboards;
561 /* Add the keyboard to the list of keyboards */
562 if (index < 0 || index >= SDL_num_keyboards || SDL_keyboards[index]) {
564 (SDL_Keyboard **) SDL_realloc(SDL_keyboards,
566 1) * sizeof(*keyboards));
572 SDL_keyboards = keyboards;
573 index = SDL_num_keyboards++;
575 SDL_keyboards[index] =
576 (SDL_Keyboard *) SDL_malloc(sizeof(*SDL_keyboards[index]));
577 if (!SDL_keyboards[index]) {
581 *SDL_keyboards[index] = *keyboard;
587 SDL_DelKeyboard(int index)
589 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
595 if (keyboard->FreeKeyboard) {
596 keyboard->FreeKeyboard(keyboard);
600 SDL_keyboards[index] = NULL;
604 SDL_ResetKeyboard(int index)
606 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
607 SDL_scancode scancode;
613 for (scancode = 0; scancode < SDL_NUM_SCANCODES; ++scancode) {
614 if (keyboard->keystate[scancode] == SDL_PRESSED) {
615 SDL_SendKeyboardKey(index, SDL_RELEASED, scancode);
621 SDL_GetDefaultKeymap(SDLKey * keymap)
623 SDL_memcpy(keymap, SDL_default_keymap, sizeof(SDL_default_keymap));
627 SDL_SetKeymap(int index, int start, SDLKey * keys, int length)
629 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
635 if (start < 0 || start + length > SDL_NUM_SCANCODES) {
639 SDL_memcpy(&keyboard->keymap[start], keys, sizeof(*keys) * length);
643 SDL_SetScancodeName(SDL_scancode scancode, const char *name)
645 SDL_scancode_names[scancode] = name;
649 SDL_SetKeyboardFocus(int index, SDL_WindowID windowID)
651 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
655 if (!keyboard || (keyboard->focus == windowID)) {
659 /* See if the current window has lost focus */
660 if (keyboard->focus) {
662 for (i = 0; i < SDL_num_keyboards; ++i) {
665 check = SDL_GetKeyboard(i);
666 if (check && check->focus == keyboard->focus) {
673 SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_LOST,
678 keyboard->focus = windowID;
680 if (keyboard->focus) {
682 for (i = 0; i < SDL_num_keyboards; ++i) {
685 check = SDL_GetKeyboard(i);
686 if (check && check->focus == keyboard->focus) {
693 SDL_SendWindowEvent(keyboard->focus, SDL_WINDOWEVENT_FOCUS_GAINED,
700 SDL_SendKeyboardKey(int index, Uint8 state, SDL_scancode scancode)
702 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
707 if (!keyboard || !scancode) {
711 printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
712 state == SDL_PRESSED ? "pressed" : "released");
714 if (state == SDL_PRESSED) {
715 modstate = keyboard->modstate;
717 case SDL_SCANCODE_NUMLOCKCLEAR:
718 keyboard->modstate ^= KMOD_NUM;
720 case SDL_SCANCODE_CAPSLOCK:
721 keyboard->modstate ^= KMOD_CAPS;
723 case SDL_SCANCODE_LCTRL:
724 keyboard->modstate |= KMOD_LCTRL;
726 case SDL_SCANCODE_RCTRL:
727 keyboard->modstate |= KMOD_RCTRL;
729 case SDL_SCANCODE_LSHIFT:
730 keyboard->modstate |= KMOD_LSHIFT;
732 case SDL_SCANCODE_RSHIFT:
733 keyboard->modstate |= KMOD_RSHIFT;
735 case SDL_SCANCODE_LALT:
736 keyboard->modstate |= KMOD_LALT;
738 case SDL_SCANCODE_RALT:
739 keyboard->modstate |= KMOD_RALT;
741 case SDL_SCANCODE_LGUI:
742 keyboard->modstate |= KMOD_LGUI;
744 case SDL_SCANCODE_RGUI:
745 keyboard->modstate |= KMOD_RGUI;
747 case SDL_SCANCODE_MODE:
748 keyboard->modstate |= KMOD_MODE;
755 case SDL_SCANCODE_NUMLOCKCLEAR:
756 case SDL_SCANCODE_CAPSLOCK:
758 case SDL_SCANCODE_LCTRL:
759 keyboard->modstate &= ~KMOD_LCTRL;
761 case SDL_SCANCODE_RCTRL:
762 keyboard->modstate &= ~KMOD_RCTRL;
764 case SDL_SCANCODE_LSHIFT:
765 keyboard->modstate &= ~KMOD_LSHIFT;
767 case SDL_SCANCODE_RSHIFT:
768 keyboard->modstate &= ~KMOD_RSHIFT;
770 case SDL_SCANCODE_LALT:
771 keyboard->modstate &= ~KMOD_LALT;
773 case SDL_SCANCODE_RALT:
774 keyboard->modstate &= ~KMOD_RALT;
776 case SDL_SCANCODE_LGUI:
777 keyboard->modstate &= ~KMOD_LGUI;
779 case SDL_SCANCODE_RGUI:
780 keyboard->modstate &= ~KMOD_RGUI;
782 case SDL_SCANCODE_MODE:
783 keyboard->modstate &= ~KMOD_MODE;
788 modstate = keyboard->modstate;
791 /* Figure out what type of event this is */
800 /* Invalid state -- bail */
804 /* Drop events that don't change state */
805 if (keyboard->keystate[scancode] == state) {
807 printf("Keyboard event didn't change state - dropped!\n");
812 /* Update internal keyboard state */
813 keyboard->keystate[scancode] = state;
815 /* Post the event, if desired */
817 if (SDL_ProcessEvents[type] == SDL_ENABLE) {
819 event.key.type = type;
820 event.key.which = (Uint8) index;
821 event.key.state = state;
822 event.key.keysym.scancode = scancode;
823 event.key.keysym.sym = keyboard->keymap[scancode];
824 event.key.keysym.mod = modstate;
825 event.key.keysym.unicode = 0;
826 event.key.windowID = keyboard->focus;
827 posted = (SDL_PushEvent(&event) > 0);
833 SDL_SendKeyboardText(int index, const char *text)
835 SDL_Keyboard *keyboard = SDL_GetKeyboard(index);
842 /* Post the event, if desired */
844 if (SDL_ProcessEvents[SDL_TEXTINPUT] == SDL_ENABLE) {
846 event.text.type = SDL_TEXTINPUT;
847 event.text.which = (Uint8) index;
848 SDL_strlcpy(event.text.text, text, SDL_arraysize(event.text.text));
849 event.text.windowID = keyboard->focus;
850 posted = (SDL_PushEvent(&event) > 0);
856 SDL_KeyboardQuit(void)
860 for (i = 0; i < SDL_num_keyboards; ++i) {
863 SDL_num_keyboards = 0;
864 SDL_current_keyboard = 0;
867 SDL_free(SDL_keyboards);
868 SDL_keyboards = NULL;
873 SDL_GetNumKeyboards(void)
875 return SDL_num_keyboards;
879 SDL_SelectKeyboard(int index)
881 if (index >= 0 && index < SDL_num_keyboards) {
882 SDL_current_keyboard = index;
884 return SDL_current_keyboard;
888 SDL_GetKeyboardState(int *numkeys)
890 SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
892 if (numkeys != (int *) 0) {
893 *numkeys = SDL_NUM_SCANCODES;
899 return keyboard->keystate;
903 SDL_GetModState(void)
905 SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
910 return keyboard->modstate;
914 SDL_SetModState(SDLMod modstate)
916 SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
921 keyboard->modstate = modstate;
925 SDL_GetKeyFromScancode(SDL_scancode scancode)
927 SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
932 return keyboard->keymap[scancode];
936 SDL_GetScancodeFromKey(SDLKey key)
938 SDL_Keyboard *keyboard = SDL_GetKeyboard(SDL_current_keyboard);
939 SDL_scancode scancode;
942 return SDL_SCANCODE_UNKNOWN;
945 for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES;
947 if (keyboard->keymap[scancode] == key) {
951 return SDL_SCANCODE_UNKNOWN;
955 SDL_GetScancodeName(SDL_scancode scancode)
957 const char *name = SDL_scancode_names[scancode];
966 SDL_GetKeyName(SDLKey key)
971 if (key & SDLK_SCANCODE_MASK) {
973 SDL_GetScancodeName((SDL_scancode) (key & ~SDLK_SCANCODE_MASK));
978 return SDL_GetScancodeName(SDL_SCANCODE_RETURN);
980 return SDL_GetScancodeName(SDL_SCANCODE_ESCAPE);
982 return SDL_GetScancodeName(SDL_SCANCODE_BACKSPACE);
984 return SDL_GetScancodeName(SDL_SCANCODE_TAB);
986 return SDL_GetScancodeName(SDL_SCANCODE_SPACE);
988 return SDL_GetScancodeName(SDL_SCANCODE_DELETE);
990 /* Unaccented letter keys on latin keyboards are normally
991 labeled in upper case (and probably on others like Greek or
992 Cyrillic too, so if you happen to know for sure, please
994 if (key >= 'a' && key <= 'z') {
998 end = SDL_UCS4ToUTF8((Uint32) key, name);
1004 /* vi: set ts=4 sw=4 expandtab: */