Atlas - SDL_evdev_kbd_freebsd.c

Home / ext / SDL / src / core / freebsd Lines: 2 | Size: 22191 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 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 22#include "SDL_internal.h" 23 24#include "../linux/SDL_evdev_kbd.h" 25 26#ifdef SDL_INPUT_FBSDKBIO 27 28// This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source, slightly modified to work with FreeBSD 29 30#include <errno.h> 31#include <unistd.h> 32#include <fcntl.h> 33#include <sys/ioctl.h> 34#include <sys/kbio.h> 35#include <sys/consio.h> 36#include <termios.h> 37 38#include <signal.h> 39 40#include "../../events/SDL_events_c.h" 41#include "SDL_evdev_kbd_default_keyaccmap.h" 42 43#ifndef K_OFF 44#define K_OFF 0x04 45#endif 46 47typedef void(fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd); 48 49 50/* 51 * Keyboard State 52 */ 53 54struct SDL_EVDEV_keyboard_state 55{ 56 int console_fd; 57 int keyboard_fd; 58 bool muted; 59 unsigned long old_kbd_mode; 60 unsigned short **key_maps; 61 keymap_t *key_map; 62 keyboard_info_t *kbInfo; 63 unsigned char shift_down[4]; // shift state counters.. 64 bool dead_key_next; 65 int npadch; // -1 or number assembled on pad 66 accentmap_t *accents; 67 unsigned int diacr; 68 bool rep; // flag telling character repeat 69 unsigned char lockstate; 70 unsigned char ledflagstate; 71 char shift_state; 72 char text[128]; 73 unsigned int text_len; 74 void (*vt_release_callback)(void *); 75 void *vt_release_callback_data; 76 void (*vt_acquire_callback)(void *); 77 void *vt_acquire_callback_data; 78}; 79 80static bool SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd) 81{ 82 return ioctl(kbd->keyboard_fd, GIO_KEYMAP, kbd->key_map) >= 0; 83} 84 85static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL; 86static int kbd_cleanup_sigactions_installed = 0; 87static int kbd_cleanup_atexit_installed = 0; 88 89static struct sigaction old_sigaction[NSIG]; 90 91static int fatal_signals[] = { 92 // Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit. 93 SIGHUP, SIGQUIT, SIGILL, SIGABRT, 94 SIGFPE, SIGSEGV, SIGPIPE, SIGBUS, 95 SIGSYS 96}; 97 98static void vt_update_mouse(SDL_EVDEV_keyboard_state *kbd, int operation) 99{ 100 struct mouse_info mData; 101 102 SDL_zero(mData); 103 mData.operation = operation; 104 ioctl(kbd->console_fd, CONS_MOUSECTL, &mData); 105} 106 107static void kbd_cleanup(void) 108{ 109 SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state; 110 if (!kbd) { 111 return; 112 } 113 kbd_cleanup_state = NULL; 114 ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode); 115 if (kbd->keyboard_fd != kbd->console_fd) { 116 close(kbd->keyboard_fd); 117 } 118 ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index)); 119 vt_update_mouse(kbd, true); 120} 121 122void SDL_EVDEV_kbd_reraise_signal(int sig) 123{ 124 raise(sig); 125} 126 127siginfo_t *SDL_EVDEV_kdb_cleanup_siginfo = NULL; 128void *SDL_EVDEV_kdb_cleanup_ucontext = NULL; 129 130static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontext) 131{ 132 struct sigaction *old_action_p = &(old_sigaction[signum]); 133 sigset_t sigset; 134 135 // Restore original signal handler before going any further. 136 sigaction(signum, old_action_p, NULL); 137 138 // Unmask current signal. 139 sigemptyset(&sigset); 140 sigaddset(&sigset, signum); 141 sigprocmask(SIG_UNBLOCK, &sigset, NULL); 142 143 // Save original signal info and context for archeologists. 144 SDL_EVDEV_kdb_cleanup_siginfo = info; 145 SDL_EVDEV_kdb_cleanup_ucontext = ucontext; 146 147 // Restore keyboard. 148 kbd_cleanup(); 149 150 // Reraise signal. 151 SDL_EVDEV_kbd_reraise_signal(signum); 152} 153 154static void kbd_unregister_emerg_cleanup(void) 155{ 156 int tabidx; 157 158 kbd_cleanup_state = NULL; 159 160 if (!kbd_cleanup_sigactions_installed) { 161 return; 162 } 163 kbd_cleanup_sigactions_installed = 0; 164 165 for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) { 166 struct sigaction *old_action_p; 167 struct sigaction cur_action; 168 int signum = fatal_signals[tabidx]; 169 old_action_p = &(old_sigaction[signum]); 170 171 // Examine current signal action 172 if (sigaction(signum, NULL, &cur_action)) { 173 continue; 174 } 175 176 // Check if action installed and not modified 177 if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) { 178 continue; 179 } 180 181 // Restore original action 182 sigaction(signum, old_action_p, NULL); 183 } 184} 185 186static void kbd_cleanup_atexit(void) 187{ 188 // Restore keyboard. 189 kbd_cleanup(); 190 191 // Try to restore signal handlers in case shared library is being unloaded 192 kbd_unregister_emerg_cleanup(); 193} 194 195static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd) 196{ 197 int tabidx; 198 199 if (kbd_cleanup_state) { 200 return; 201 } 202 kbd_cleanup_state = kbd; 203 204 if (!kbd_cleanup_atexit_installed) { 205 /* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish 206 * functions that are called when the shared library is unloaded. 207 * -- man atexit(3) 208 */ 209 atexit(kbd_cleanup_atexit); 210 kbd_cleanup_atexit_installed = 1; 211 } 212 213 if (kbd_cleanup_sigactions_installed) { 214 return; 215 } 216 kbd_cleanup_sigactions_installed = 1; 217 218 for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) { 219 struct sigaction *old_action_p; 220 struct sigaction new_action; 221 int signum = fatal_signals[tabidx]; 222 old_action_p = &(old_sigaction[signum]); 223 if (sigaction(signum, NULL, old_action_p)) { 224 continue; 225 } 226 227 /* Skip SIGHUP and SIGPIPE if handler is already installed 228 * - assume the handler will do the cleanup 229 */ 230 if ((signum == SIGHUP || signum == SIGPIPE) && (old_action_p->sa_handler != SIG_DFL || (void (*)(int))old_action_p->sa_sigaction != SIG_DFL)) { 231 continue; 232 } 233 234 new_action = *old_action_p; 235 new_action.sa_flags |= SA_SIGINFO; 236 new_action.sa_sigaction = &kbd_cleanup_signal_action; 237 sigaction(signum, &new_action, NULL); 238 } 239} 240 241enum { 242 VT_SIGNAL_NONE, 243 VT_SIGNAL_RELEASE, 244 VT_SIGNAL_ACQUIRE, 245}; 246static int vt_release_signal; 247static int vt_acquire_signal; 248static SDL_AtomicInt vt_signal_pending; 249SDL_AtomicInt vt_current; 250 251typedef void (*signal_handler)(int signum); 252 253 254static void kbd_vt_release_signal_action(int signum) 255{ 256 SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_RELEASE); 257 SDL_SetAtomicInt(&vt_current, VT_THEIRS); 258} 259 260static void kbd_vt_acquire_signal_action(int signum) 261{ 262 SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_ACQUIRE); 263 SDL_SetAtomicInt(&vt_current, VT_OURS); 264} 265 266static bool setup_vt_signal(int signum, signal_handler handler) 267{ 268 struct sigaction *old_action_p; 269 struct sigaction new_action; 270 old_action_p = &(old_sigaction[signum]); 271 SDL_zero(new_action); 272 new_action.sa_handler = handler; 273 new_action.sa_flags = SA_RESTART; 274 if (sigaction(signum, &new_action, old_action_p) < 0) { 275 return false; 276 } 277 if (old_action_p->sa_handler != SIG_DFL) { 278 // This signal is already in use 279 if (signum == SIGUSR1 || signum == SIGUSR2) { 280 /* 281 * For the moment we have no other options in FreeBSD because 282 * the vt(4) will not accept signal numbers over 32. 283 */ 284 return true; 285 } 286 sigaction(signum, old_action_p, NULL); 287 return false; 288 } 289 return true; 290} 291 292static void kbd_vt_quit(int console_fd) 293{ 294 struct vt_mode mode; 295 296 if (vt_release_signal) { 297 sigaction(vt_release_signal, &old_sigaction[vt_release_signal], NULL); 298 vt_release_signal = 0; 299 } 300 if (vt_acquire_signal) { 301 sigaction(vt_acquire_signal, &old_sigaction[vt_acquire_signal], NULL); 302 vt_acquire_signal = 0; 303 } 304 305 SDL_zero(mode); 306 mode.mode = VT_AUTO; 307 ioctl(console_fd, VT_SETMODE, &mode); 308} 309 310static bool kbd_vt_init(int console_fd) 311{ 312 struct vt_mode mode; 313 314 if (setup_vt_signal(SIGUSR1, kbd_vt_release_signal_action)) { 315 vt_release_signal = SIGUSR1; 316 } 317 if (setup_vt_signal(SIGUSR2, kbd_vt_acquire_signal_action)) { 318 vt_acquire_signal = SIGUSR2; 319 } 320 if (!vt_release_signal || !vt_acquire_signal ) { 321 kbd_vt_quit(console_fd); 322 return false; 323 } 324 325 SDL_zero(mode); 326 mode.mode = VT_PROCESS; 327 mode.relsig = vt_release_signal; 328 mode.acqsig = vt_acquire_signal; 329 mode.frsig = SIGIO; 330 if (ioctl(console_fd, VT_SETMODE, &mode) < 0) { 331 SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Failed VT_SETMODE ioctl: %s", strerror(errno)); 332 kbd_vt_quit(console_fd); 333 return false; 334 } 335 return true; 336} 337 338SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void) 339{ 340 SDL_EVDEV_keyboard_state *kbd; 341 char flag_state; 342 343 kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(SDL_EVDEV_keyboard_state)); 344 if (!kbd) { 345 return NULL; 346 } 347 348 kbd->npadch = -1; 349 350 // This might fail if we're not connected to a tty (e.g. on the Steam Link) 351 kbd->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC); 352 353 kbd->shift_state = 0; 354 355 kbd->accents = SDL_calloc(1, sizeof(accentmap_t)); 356 kbd->key_map = SDL_calloc(1, sizeof(keymap_t)); 357 kbd->kbInfo = SDL_calloc(1, sizeof(keyboard_info_t)); 358 359 ioctl(kbd->console_fd, KDGKBINFO, kbd->kbInfo); 360 361 if (ioctl(kbd->console_fd, KDGKBSTATE, &flag_state) == 0) { 362 kbd->ledflagstate = flag_state; 363 } 364 365 if (ioctl(kbd->console_fd, GIO_DEADKEYMAP, kbd->accents) < 0) { 366 SDL_free(kbd->accents); 367 kbd->accents = &accentmap_default_us_acc; 368 } 369 370 if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) { 371 // Set the keyboard in XLATE mode and load the keymaps 372 ioctl(kbd->console_fd, KDSKBMODE, (unsigned long)(K_XLATE)); 373 if (!SDL_EVDEV_kbd_load_keymaps(kbd)) { 374 SDL_free(kbd->key_map); 375 kbd->key_map = &keymap_default_us_acc; 376 } 377 378 if (!kbd_vt_init(kbd->console_fd)) { 379 SDL_LogInfo(SDL_LOG_CATEGORY_INPUT, "kbd_vt_init failed"); 380 } 381 382 kbd->keyboard_fd = kbd->console_fd; 383 384 if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { 385 kbd_register_emerg_cleanup(kbd); 386 } 387 } 388 389 vt_update_mouse(kbd, MOUSE_HIDE); 390 391 return kbd; 392} 393 394void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *kbd) 395{ 396 if (!kbd) { 397 return; 398 } 399 400 kbd_vt_quit(kbd->console_fd); 401 402 vt_update_mouse(kbd, MOUSE_SHOW); 403 404 kbd_unregister_emerg_cleanup(); 405 406 if (kbd->keyboard_fd >= 0) { 407 // Restore the original keyboard mode 408 ioctl(kbd->keyboard_fd, KDSKBMODE, kbd->old_kbd_mode); 409 410 close(kbd->keyboard_fd); 411 if (kbd->console_fd != kbd->keyboard_fd && kbd->console_fd >= 0) { 412 // Give back keyboard. 413 ioctl(kbd->console_fd, CONS_SETKBD, (unsigned long)(kbd->kbInfo->kb_index)); 414 } 415 kbd->console_fd = kbd->keyboard_fd = -1; 416 } 417 418 SDL_free(kbd); 419} 420 421void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted) 422{ 423 struct termios tios; 424 425 SDL_zero(tios); 426 427 if (!state) { 428 return; 429 } 430 431 if (muted == state->muted) { 432 return; 433 } 434 435 if (tcgetattr(state->console_fd, &tios) == -1) { 436 SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Could not get terminal mode: %s", strerror(errno)); 437 return; 438 } 439 440 if (muted) { 441 if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) { 442 ioctl(state->console_fd, KDSKBMODE, K_OFF); 443 cfmakeraw(&tios); 444 445 if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) { 446 kbd_register_emerg_cleanup(state); 447 } 448 } 449 } else { 450 kbd_unregister_emerg_cleanup(); 451 452 cfmakesane(&tios); 453 ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode); 454 } 455 456 if (tcsetattr(state->console_fd, TCSAFLUSH, &tios) == -1) { 457 SDL_LogError(SDL_LOG_CATEGORY_INPUT, "Could not set terminal mode to %s: %s", muted ? "raw" : "sane", strerror(errno)); 458 return; 459 } 460 461 state->muted = muted; 462} 463 464void SDL_EVDEV_kbd_set_vt_switch_callbacks(SDL_EVDEV_keyboard_state *state, void (*release_callback)(void *), void *release_callback_data, void (*acquire_callback)(void *), void *acquire_callback_data) 465{ 466 if (state == NULL) { 467 return; 468 } 469 470 state->vt_release_callback = release_callback; 471 state->vt_release_callback_data = release_callback_data; 472 state->vt_acquire_callback = acquire_callback; 473 state->vt_acquire_callback_data = acquire_callback_data; 474} 475 476void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state) 477{ 478 if (!state) { 479 return; 480 } 481 482 int signal_pending = SDL_GetAtomicInt(&vt_signal_pending); 483 484 if (signal_pending != VT_SIGNAL_NONE) { 485 if (signal_pending == VT_SIGNAL_RELEASE) { 486 if (state->vt_release_callback) { 487 vt_update_mouse(state, MOUSE_SHOW); 488 state->vt_release_callback(state->vt_release_callback_data); 489 } 490 ioctl(state->console_fd, VT_RELDISP, 1); 491 } else { 492 if (state->vt_acquire_callback) { 493 state->vt_acquire_callback(state->vt_acquire_callback_data); 494 vt_update_mouse(state, MOUSE_HIDE); 495 } 496 ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ); 497 } 498 SDL_CompareAndSwapAtomicInt(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE); 499 } 500} 501 502/* 503 * Helper Functions. 504 */ 505static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c) 506{ 507 // c is already part of a UTF-8 sequence and safe to add as a character 508 if (kbd->text_len < (sizeof(kbd->text) - 1)) { 509 kbd->text[kbd->text_len++] = (char)c; 510 } 511} 512 513static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c) 514{ 515 if (c < 0x80) 516 /* 0******* */ 517 put_queue(kbd, c); 518 else if (c < 0x800) { 519 /* 110***** 10****** */ 520 put_queue(kbd, 0xc0 | (c >> 6)); 521 put_queue(kbd, 0x80 | (c & 0x3f)); 522 } else if (c < 0x10000) { 523 if (c >= 0xD800 && c < 0xE000) { 524 return; 525 } 526 if (c == 0xFFFF) { 527 return; 528 } 529 /* 1110**** 10****** 10****** */ 530 put_queue(kbd, 0xe0 | (c >> 12)); 531 put_queue(kbd, 0x80 | ((c >> 6) & 0x3f)); 532 put_queue(kbd, 0x80 | (c & 0x3f)); 533 } else if (c < 0x110000) { 534 /* 11110*** 10****** 10****** 10****** */ 535 put_queue(kbd, 0xf0 | (c >> 18)); 536 put_queue(kbd, 0x80 | ((c >> 12) & 0x3f)); 537 put_queue(kbd, 0x80 | ((c >> 6) & 0x3f)); 538 put_queue(kbd, 0x80 | (c & 0x3f)); 539 } 540} 541 542/* 543 * We have a combining character DIACR here, followed by the character CH. 544 * If the combination occurs in the table, return the corresponding value. 545 * Otherwise, if CH is a space or equals DIACR, return DIACR. 546 * Otherwise, conclude that DIACR was not combining after all, 547 * queue it and return CH. 548 */ 549static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch) 550{ 551 unsigned int d = kbd->diacr; 552 unsigned int i, j; 553 554 kbd->diacr = 0; 555 556 for (i = 0; i < kbd->accents->n_accs; i++) { 557 if (kbd->accents->acc[i].accchar == d) { 558 for (j = 0; j < NUM_ACCENTCHARS; ++j) { 559 if (kbd->accents->acc[i].map[j][0] == 0) { // end of table 560 break; 561 } 562 if (kbd->accents->acc[i].map[j][0] == ch) { 563 return kbd->accents->acc[i].map[j][1]; 564 } 565 } 566 } 567 } 568 569 if (ch == ' ' || ch == d) { 570 put_utf8(kbd, d); 571 return 0; 572 } 573 put_utf8(kbd, d); 574 575 return ch; 576} 577 578static bool vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) 579{ 580 return (kbd->ledflagstate & flag) != 0; 581} 582 583static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag) 584{ 585 kbd->ledflagstate ^= flag; 586 ioctl(kbd->keyboard_fd, KDSKBSTATE, (unsigned long)(kbd->ledflagstate)); 587} 588 589/* 590 * Special function handlers 591 */ 592 593static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag) 594{ 595 if (up_flag) { 596 return; // no action, if this is a key release 597 } 598 599 if (kbd->diacr) { 600 value = handle_diacr(kbd, value); 601 } 602 603 if (kbd->dead_key_next) { 604 kbd->dead_key_next = false; 605 kbd->diacr = value; 606 return; 607 } 608 put_utf8(kbd, value); 609} 610 611static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag) 612{ 613 if (up_flag) 614 return; 615 616 kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value); 617} 618 619static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag) 620{ 621 int old_state = kbd->shift_state; 622 623 if (kbd->rep) 624 return; 625 626 if (up_flag) { 627 /* 628 * handle the case that two shift or control 629 * keys are depressed simultaneously 630 */ 631 if (kbd->shift_down[value]) { 632 kbd->shift_down[value]--; 633 } 634 } else 635 kbd->shift_down[value]++; 636 637 if (kbd->shift_down[value]) 638 kbd->shift_state |= (1 << value); 639 else 640 kbd->shift_state &= ~(1 << value); 641 642 // kludge 643 if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) { 644 put_utf8(kbd, kbd->npadch); 645 kbd->npadch = -1; 646 } 647} 648 649void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *kbd, unsigned int keycode, int down) 650{ 651 keymap_t key_map; 652 struct keyent_t keysym; 653 unsigned int final_key_state; 654 unsigned int map_from_key_sym; 655 656 if (!kbd) { 657 return; 658 } 659 660 key_map = *kbd->key_map; 661 662 kbd->rep = (down == 2); 663 664 if (keycode < NUM_KEYS) { 665 if (keycode >= 89 && keycode <= 95) { 666 // These constitute unprintable language-related keys, so ignore them. 667 return; 668 } 669 if (keycode > 95) { 670 keycode -= 7; 671 } 672 if (vc_kbd_led(kbd, ALKED) || (kbd->shift_state & 0x8)) { 673 keycode += ALTGR_OFFSET; 674 } 675 keysym = key_map.key[keycode]; 676 } else { 677 return; 678 } 679 680 final_key_state = kbd->shift_state & 0x7; 681 if ((keysym.flgs & FLAG_LOCK_C) && vc_kbd_led(kbd, LED_CAP)) { 682 final_key_state ^= 0x1; 683 } 684 if ((keysym.flgs & FLAG_LOCK_N) && vc_kbd_led(kbd, LED_NUM)) { 685 final_key_state ^= 0x1; 686 } 687 688 map_from_key_sym = keysym.map[final_key_state]; 689 if ((keysym.spcl & (0x80 >> final_key_state)) || (map_from_key_sym & SPCLKEY)) { 690 // Special function. 691 if (map_from_key_sym == 0) 692 return; // Nothing to do. 693 if (map_from_key_sym & SPCLKEY) { 694 map_from_key_sym &= ~SPCLKEY; 695 } 696 if (map_from_key_sym >= F_ACC && map_from_key_sym <= L_ACC) { 697 // Accent function. 698 unsigned int accent_index = map_from_key_sym - F_ACC; 699 if (kbd->accents->acc[accent_index].accchar != 0) { 700 k_deadunicode(kbd, kbd->accents->acc[accent_index].accchar, !down); 701 } 702 } else { 703 switch (map_from_key_sym) { 704 case ASH: // alt/meta shift 705 k_shift(kbd, 3, down == 0); 706 break; 707 case LSHA: // left shift + alt lock 708 case RSHA: // right shift + alt lock 709 if (down == 0) { 710 chg_vc_kbd_led(kbd, ALKED); 711 } 712 SDL_FALLTHROUGH; 713 case LSH: // left shift 714 case RSH: // right shift 715 k_shift(kbd, 0, down == 0); 716 break; 717 case LCTRA: // left ctrl + alt lock 718 case RCTRA: // right ctrl + alt lock 719 if (down == 0) { 720 chg_vc_kbd_led(kbd, ALKED); 721 } 722 SDL_FALLTHROUGH; 723 case LCTR: // left ctrl 724 case RCTR: // right ctrl 725 k_shift(kbd, 1, down == 0); 726 break; 727 case LALTA: // left alt + alt lock 728 case RALTA: // right alt + alt lock 729 if (down == 0) { 730 chg_vc_kbd_led(kbd, ALKED); 731 } 732 SDL_FALLTHROUGH; 733 case LALT: // left alt 734 case RALT: // right alt 735 k_shift(kbd, 2, down == 0); 736 break; 737 case ALK: // alt lock 738 if (down == 1) { 739 chg_vc_kbd_led(kbd, ALKED); 740 } 741 break; 742 case CLK: // caps lock 743 if (down == 1) { 744 chg_vc_kbd_led(kbd, CLKED); 745 } 746 break; 747 case NLK: // num lock 748 if (down == 1) { 749 chg_vc_kbd_led(kbd, NLKED); 750 } 751 break; 752 case SLK: // scroll lock 753 if (down == 1) { 754 chg_vc_kbd_led(kbd, SLKED); 755 } 756 break; 757 default: 758 return; 759 } 760 } 761 } else { 762 if (map_from_key_sym == '\n' || map_from_key_sym == '\r') { 763 if (kbd->diacr) { 764 kbd->diacr = 0; 765 return; 766 } 767 } 768 if (map_from_key_sym >= ' ' && map_from_key_sym != 127) { 769 k_self(kbd, map_from_key_sym, !down); 770 } 771 } 772 773 if (kbd->text_len > 0) { 774 kbd->text[kbd->text_len] = '\0'; 775 SDL_SendKeyboardText(kbd->text); 776 kbd->text_len = 0; 777 } 778} 779 780#endif // SDL_INPUT_FBSDKBIO 781
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.