| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "../../SDL_internal.h"
- #include "SDL_evdev_kbd.h"
- #include "SDL_hints.h"
- #ifdef SDL_INPUT_LINUXKD
- /* This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source */
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/ioctl.h>
- #include <linux/kd.h>
- #include <linux/keyboard.h>
- #include <linux/vt.h>
- #include <linux/tiocl.h> /* for TIOCL_GETSHIFTSTATE */
- #include <signal.h>
- #include "../../events/SDL_events_c.h"
- #include "SDL_evdev_kbd_default_accents.h"
- #include "SDL_evdev_kbd_default_keymap.h"
- /* These are not defined in older Linux kernel headers */
- #ifndef K_UNICODE
- #define K_UNICODE 0x03
- #endif
- #ifndef K_OFF
- #define K_OFF 0x04
- #endif
- /*
- * Handler Tables.
- */
- #define K_HANDLERS \
- k_self, k_fn, k_spec, k_pad, \
- k_dead, k_cons, k_cur, k_shift, \
- k_meta, k_ascii, k_lock, k_lowercase, \
- k_slock, k_dead2, k_brl, k_ignore
- typedef void(k_handler_fn)(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag);
- static k_handler_fn K_HANDLERS;
- static k_handler_fn *k_handler[16] = { K_HANDLERS };
- typedef void(fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
- static void fn_enter(SDL_EVDEV_keyboard_state *kbd);
- static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd);
- static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd);
- static void fn_num(SDL_EVDEV_keyboard_state *kbd);
- static void fn_compose(SDL_EVDEV_keyboard_state *kbd);
- static fn_handler_fn *fn_handler[] = {
- NULL, fn_enter, NULL, NULL,
- NULL, NULL, NULL, fn_caps_toggle,
- fn_num, NULL, NULL, NULL,
- NULL, fn_caps_on, fn_compose, NULL,
- NULL, NULL, NULL, fn_num
- };
- /*
- * Keyboard State
- */
- struct SDL_EVDEV_keyboard_state
- {
- int console_fd;
- SDL_bool muted;
- int old_kbd_mode;
- unsigned short **key_maps;
- unsigned char shift_down[NR_SHIFT]; /* shift state counters.. */
- SDL_bool dead_key_next;
- int npadch; /* -1 or number assembled on pad */
- struct kbdiacrs *accents;
- unsigned int diacr;
- SDL_bool rep; /* flag telling character repeat */
- unsigned char lockstate;
- unsigned char slockstate;
- unsigned char ledflagstate;
- char shift_state;
- char text[128];
- unsigned int text_len;
- };
- #ifdef DUMP_ACCENTS
- static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd)
- {
- unsigned int i;
- printf("static struct kbdiacrs default_accents = {\n");
- printf(" %d,\n", kbd->accents->kb_cnt);
- printf(" {\n");
- for (i = 0; i < kbd->accents->kb_cnt; ++i) {
- struct kbdiacr *diacr = &kbd->accents->kbdiacr[i];
- printf(" { 0x%.2x, 0x%.2x, 0x%.2x },\n",
- diacr->diacr, diacr->base, diacr->result);
- }
- while (i < 256) {
- printf(" { 0x00, 0x00, 0x00 },\n");
- ++i;
- }
- printf(" }\n");
- printf("};\n");
- }
- #endif /* DUMP_ACCENTS */
- #ifdef DUMP_KEYMAP
- static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
- {
- int i, j;
- for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
- if (kbd->key_maps[i]) {
- printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
- for (j = 0; j < NR_KEYS; ++j) {
- if ((j % 8) == 0) {
- printf("\n ");
- }
- printf("0x%.4x, ", kbd->key_maps[i][j]);
- }
- printf("\n};\n");
- }
- }
- printf("\n");
- printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
- for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
- if (kbd->key_maps[i]) {
- printf(" default_key_map_%d,\n", i);
- } else {
- printf(" NULL,\n");
- }
- }
- printf("};\n");
- }
- #endif /* DUMP_KEYMAP */
- static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL;
- static int kbd_cleanup_sigactions_installed = 0;
- static int kbd_cleanup_atexit_installed = 0;
- static struct sigaction old_sigaction[NSIG];
- static int fatal_signals[] = {
- /* Handlers for SIGTERM and SIGINT are installed in SDL_QuitInit. */
- SIGHUP, SIGQUIT, SIGILL, SIGABRT,
- SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
- SIGSYS
- };
- static void kbd_cleanup(void)
- {
- SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state;
- if (kbd == NULL) {
- return;
- }
- kbd_cleanup_state = NULL;
- ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
- }
- static void SDL_EVDEV_kbd_reraise_signal(int sig)
- {
- (void)raise(sig);
- }
- siginfo_t *SDL_EVDEV_kdb_cleanup_siginfo = NULL;
- void *SDL_EVDEV_kdb_cleanup_ucontext = NULL;
- static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontext)
- {
- struct sigaction *old_action_p = &(old_sigaction[signum]);
- sigset_t sigset;
- /* Restore original signal handler before going any further. */
- sigaction(signum, old_action_p, NULL);
- /* Unmask current signal. */
- sigemptyset(&sigset);
- sigaddset(&sigset, signum);
- sigprocmask(SIG_UNBLOCK, &sigset, NULL);
- /* Save original signal info and context for archeologists. */
- SDL_EVDEV_kdb_cleanup_siginfo = info;
- SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
- /* Restore keyboard. */
- kbd_cleanup();
- /* Reraise signal. */
- SDL_EVDEV_kbd_reraise_signal(signum);
- }
- static void kbd_unregister_emerg_cleanup()
- {
- int tabidx, signum;
- kbd_cleanup_state = NULL;
- if (!kbd_cleanup_sigactions_installed) {
- return;
- }
- kbd_cleanup_sigactions_installed = 0;
- for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
- struct sigaction *old_action_p;
- struct sigaction cur_action;
- signum = fatal_signals[tabidx];
- old_action_p = &(old_sigaction[signum]);
- /* Examine current signal action */
- if (sigaction(signum, NULL, &cur_action)) {
- continue;
- }
- /* Check if action installed and not modifed */
- if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) {
- continue;
- }
- /* Restore original action */
- sigaction(signum, old_action_p, NULL);
- }
- }
- static void kbd_cleanup_atexit(void)
- {
- /* Restore keyboard. */
- kbd_cleanup();
- /* Try to restore signal handlers in case shared library is being unloaded */
- kbd_unregister_emerg_cleanup();
- }
- static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd)
- {
- int tabidx, signum;
- if (kbd_cleanup_state != NULL) {
- return;
- }
- kbd_cleanup_state = kbd;
- if (!kbd_cleanup_atexit_installed) {
- /* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish
- * functions that are called when the shared library is unloaded.
- * -- man atexit(3)
- */
- (void)atexit(kbd_cleanup_atexit);
- kbd_cleanup_atexit_installed = 1;
- }
- if (kbd_cleanup_sigactions_installed) {
- return;
- }
- kbd_cleanup_sigactions_installed = 1;
- for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
- struct sigaction *old_action_p;
- struct sigaction new_action;
- signum = fatal_signals[tabidx];
- old_action_p = &(old_sigaction[signum]);
- if (sigaction(signum, NULL, old_action_p)) {
- continue;
- }
- /* Skip SIGHUP and SIGPIPE if handler is already installed
- * - assume the handler will do the cleanup
- */
- if ((signum == SIGHUP || signum == SIGPIPE) && (old_action_p->sa_handler != SIG_DFL || (void (*)(int))old_action_p->sa_sigaction != SIG_DFL)) {
- continue;
- }
- new_action = *old_action_p;
- new_action.sa_flags |= SA_SIGINFO;
- new_action.sa_sigaction = &kbd_cleanup_signal_action;
- sigaction(signum, &new_action, NULL);
- }
- }
- SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
- {
- SDL_EVDEV_keyboard_state *kbd;
- char flag_state;
- char kbtype;
- char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 };
- kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
- if (kbd == NULL) {
- return NULL;
- }
- /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
- kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
- if (!((ioctl(kbd->console_fd, KDGKBTYPE, &kbtype) == 0) && ((kbtype == KB_101) || (kbtype == KB_84)))) {
- close(kbd->console_fd);
- kbd->console_fd = -1;
- }
- kbd->npadch = -1;
- if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
- kbd->shift_state = *shift_state;
- }
- if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
- kbd->ledflagstate = flag_state;
- }
- kbd->accents = &default_accents;
- kbd->key_maps = default_key_maps;
- if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
- /* Set the keyboard in UNICODE mode and load the keymaps */
- ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
- }
- return kbd;
- }
- void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
- {
- if (state == NULL) {
- return;
- }
- SDL_EVDEV_kbd_set_muted(state, SDL_FALSE);
- if (state->console_fd >= 0) {
- close(state->console_fd);
- state->console_fd = -1;
- }
- if (state->key_maps && state->key_maps != default_key_maps) {
- int i;
- for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
- if (state->key_maps[i]) {
- SDL_free(state->key_maps[i]);
- }
- }
- SDL_free(state->key_maps);
- }
- SDL_free(state);
- }
- void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted)
- {
- if (state == NULL) {
- return;
- }
- if (muted == state->muted) {
- return;
- }
- if (muted) {
- /* Allow inhibiting keyboard mute with env. variable for debugging etc. */
- if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
- /* Mute the keyboard so keystrokes only generate evdev events
- * and do not leak through to the console
- */
- ioctl(state->console_fd, KDSKBMODE, K_OFF);
- /* Make sure to restore keyboard if application fails to call
- * SDL_Quit before exit or fatal signal is raised.
- */
- if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
- kbd_register_emerg_cleanup(state);
- }
- }
- } else {
- kbd_unregister_emerg_cleanup();
- /* Restore the original keyboard mode */
- ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode);
- }
- state->muted = muted;
- }
- /*
- * Helper Functions.
- */
- static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c)
- {
- /* c is already part of a UTF-8 sequence and safe to add as a character */
- if (kbd->text_len < (sizeof(kbd->text) - 1)) {
- kbd->text[kbd->text_len++] = (char)c;
- }
- }
- static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c)
- {
- if (c < 0x80) {
- put_queue(kbd, c); /* 0******* */
- } else if (c < 0x800) {
- /* 110***** 10****** */
- put_queue(kbd, 0xc0 | (c >> 6));
- put_queue(kbd, 0x80 | (c & 0x3f));
- } else if (c < 0x10000) {
- if (c >= 0xD800 && c < 0xE000) {
- return;
- }
- if (c == 0xFFFF) {
- return;
- }
- /* 1110**** 10****** 10****** */
- put_queue(kbd, 0xe0 | (c >> 12));
- put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
- put_queue(kbd, 0x80 | (c & 0x3f));
- } else if (c < 0x110000) {
- /* 11110*** 10****** 10****** 10****** */
- put_queue(kbd, 0xf0 | (c >> 18));
- put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
- put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
- put_queue(kbd, 0x80 | (c & 0x3f));
- }
- }
- /*
- * We have a combining character DIACR here, followed by the character CH.
- * If the combination occurs in the table, return the corresponding value.
- * Otherwise, if CH is a space or equals DIACR, return DIACR.
- * Otherwise, conclude that DIACR was not combining after all,
- * queue it and return CH.
- */
- static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
- {
- unsigned int d = kbd->diacr;
- unsigned int i;
- kbd->diacr = 0;
- if (kbd->console_fd >= 0)
- if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
- /* No worries, we'll use the default accent table */
- }
- for (i = 0; i < kbd->accents->kb_cnt; i++) {
- if (kbd->accents->kbdiacr[i].diacr == d &&
- kbd->accents->kbdiacr[i].base == ch) {
- return kbd->accents->kbdiacr[i].result;
- }
- }
- if (ch == ' ' || ch == d) {
- return d;
- }
- put_utf8(kbd, d);
- return ch;
- }
- static int vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- return (kbd->ledflagstate & flag) != 0;
- }
- static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- kbd->ledflagstate |= flag;
- ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
- }
- static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- kbd->ledflagstate &= ~flag;
- ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
- }
- static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- kbd->lockstate ^= 1 << flag;
- }
- static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- kbd->slockstate ^= 1 << flag;
- }
- static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
- {
- kbd->ledflagstate ^= flag;
- ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
- }
- /*
- * Special function handlers
- */
- static void fn_enter(SDL_EVDEV_keyboard_state *kbd)
- {
- if (kbd->diacr) {
- put_utf8(kbd, kbd->diacr);
- kbd->diacr = 0;
- }
- }
- static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd)
- {
- if (kbd->rep) {
- return;
- }
- chg_vc_kbd_led(kbd, K_CAPSLOCK);
- }
- static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd)
- {
- if (kbd->rep) {
- return;
- }
- set_vc_kbd_led(kbd, K_CAPSLOCK);
- }
- static void fn_num(SDL_EVDEV_keyboard_state *kbd)
- {
- if (!kbd->rep) {
- chg_vc_kbd_led(kbd, K_NUMLOCK);
- }
- }
- static void fn_compose(SDL_EVDEV_keyboard_state *kbd)
- {
- kbd->dead_key_next = SDL_TRUE;
- }
- /*
- * Special key handlers
- */
- static void k_ignore(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_spec(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- if (up_flag) {
- return;
- }
- if (value >= SDL_arraysize(fn_handler)) {
- return;
- }
- if (fn_handler[value]) {
- fn_handler[value](kbd);
- }
- }
- static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- if (up_flag) {
- return; /* no action, if this is a key release */
- }
- if (kbd->diacr) {
- value = handle_diacr(kbd, value);
- }
- if (kbd->dead_key_next) {
- kbd->dead_key_next = SDL_FALSE;
- kbd->diacr = value;
- return;
- }
- put_utf8(kbd, value);
- }
- static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag)
- {
- if (up_flag) {
- return;
- }
- kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
- }
- static void k_dead(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- const unsigned char ret_diacr[NR_DEAD] = { '`', '\'', '^', '~', '"', ',' };
- k_deadunicode(kbd, ret_diacr[value], up_flag);
- }
- static void k_dead2(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- k_deadunicode(kbd, value, up_flag);
- }
- static void k_cons(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_fn(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_cur(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- static const char pad_chars[] = "0123456789+-*/\015,.?()#";
- if (up_flag) {
- return; /* no action, if this is a key release */
- }
- if (!vc_kbd_led(kbd, K_NUMLOCK)) {
- /* unprintable action */
- return;
- }
- put_queue(kbd, pad_chars[value]);
- }
- static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- int old_state = kbd->shift_state;
- if (kbd->rep) {
- return;
- }
- /*
- * Mimic typewriter:
- * a CapsShift key acts like Shift but undoes CapsLock
- */
- if (value == KVAL(K_CAPSSHIFT)) {
- value = KVAL(K_SHIFT);
- if (!up_flag) {
- clr_vc_kbd_led(kbd, K_CAPSLOCK);
- }
- }
- if (up_flag) {
- /*
- * handle the case that two shift or control
- * keys are depressed simultaneously
- */
- if (kbd->shift_down[value]) {
- kbd->shift_down[value]--;
- }
- } else {
- kbd->shift_down[value]++;
- }
- if (kbd->shift_down[value]) {
- kbd->shift_state |= (1 << value);
- } else {
- kbd->shift_state &= ~(1 << value);
- }
- /* kludge */
- if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
- put_utf8(kbd, kbd->npadch);
- kbd->npadch = -1;
- }
- }
- static void k_meta(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- int base;
- if (up_flag) {
- return;
- }
- if (value < 10) {
- /* decimal input of code, while Alt depressed */
- base = 10;
- } else {
- /* hexadecimal input of code, while AltGr depressed */
- value -= 10;
- base = 16;
- }
- if (kbd->npadch == -1) {
- kbd->npadch = value;
- } else {
- kbd->npadch = kbd->npadch * base + value;
- }
- }
- static void k_lock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- if (up_flag || kbd->rep) {
- return;
- }
- chg_vc_kbd_lock(kbd, value);
- }
- static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- k_shift(kbd, value, up_flag);
- if (up_flag || kbd->rep) {
- return;
- }
- chg_vc_kbd_slock(kbd, value);
- /* try to make Alt, oops, AltGr and such work */
- if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
- kbd->slockstate = 0;
- chg_vc_kbd_slock(kbd, value);
- }
- }
- static void k_brl(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
- {
- }
- void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
- {
- unsigned char shift_final;
- unsigned char type;
- unsigned short *key_map;
- unsigned short keysym;
- if (state == NULL) {
- return;
- }
- state->rep = (down == 2);
- shift_final = (state->shift_state | state->slockstate) ^ state->lockstate;
- key_map = state->key_maps[shift_final];
- if (key_map == NULL) {
- /* Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state */
- state->shift_state = 0;
- state->slockstate = 0;
- state->lockstate = 0;
- return;
- }
- if (keycode < NR_KEYS) {
- if (state->console_fd < 0) {
- keysym = key_map[keycode];
- } else {
- struct kbentry kbe;
- kbe.kb_table = shift_final;
- kbe.kb_index = keycode;
- if (ioctl(state->console_fd, KDGKBENT, &kbe) == 0)
- keysym = (kbe.kb_value ^ 0xf000);
- else
- return;
- }
- } else {
- return;
- }
- type = KTYP(keysym);
- if (type < 0xf0) {
- if (down) {
- put_utf8(state, keysym);
- }
- } else {
- type -= 0xf0;
- /* if type is KT_LETTER then it can be affected by Caps Lock */
- if (type == KT_LETTER) {
- type = KT_LATIN;
- if (vc_kbd_led(state, K_CAPSLOCK)) {
- shift_final = shift_final ^ (1 << KG_SHIFT);
- key_map = state->key_maps[shift_final];
- if (key_map) {
- if (state->console_fd < 0) {
- keysym = key_map[keycode];
- } else {
- struct kbentry kbe;
- kbe.kb_table = shift_final;
- kbe.kb_index = keycode;
- if (ioctl(state->console_fd, KDGKBENT, &kbe) == 0)
- keysym = (kbe.kb_value ^ 0xf000);
- }
- }
- }
- }
- (*k_handler[type])(state, keysym & 0xff, !down);
- if (type != KT_SLOCK) {
- state->slockstate = 0;
- }
- }
- if (state->text_len > 0) {
- state->text[state->text_len] = '\0';
- SDL_SendKeyboardText(state->text);
- state->text_len = 0;
- }
- }
- #elif !defined(SDL_INPUT_FBSDKBIO) /* !SDL_INPUT_LINUXKD */
- SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
- {
- return NULL;
- }
- void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, SDL_bool muted)
- {
- }
- void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
- {
- }
- void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
- {
- }
- #endif /* SDL_INPUT_LINUXKD */
- /* vi: set ts=4 sw=4 expandtab: */
|