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