SDL_evdev_kbd.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. #include "SDL_evdev_kbd.h"
  20. #ifdef SDL_INPUT_LINUXKD
  21. // This logic is adapted from drivers/tty/vt/keyboard.c in the Linux kernel source
  22. #include <unistd.h>
  23. #include <fcntl.h>
  24. #include <sys/ioctl.h>
  25. #include <linux/kd.h>
  26. #include <linux/keyboard.h>
  27. #include <linux/vt.h>
  28. #include <linux/tiocl.h> // for TIOCL_GETSHIFTSTATE
  29. #include <signal.h>
  30. #include "../../events/SDL_events_c.h"
  31. #include "SDL_evdev_kbd_default_accents.h"
  32. #include "SDL_evdev_kbd_default_keymap.h"
  33. // These are not defined in older Linux kernel headers
  34. #ifndef K_UNICODE
  35. #define K_UNICODE 0x03
  36. #endif
  37. #ifndef K_OFF
  38. #define K_OFF 0x04
  39. #endif
  40. /*
  41. * Handler Tables.
  42. */
  43. #define K_HANDLERS \
  44. k_self, k_fn, k_spec, k_pad, \
  45. k_dead, k_cons, k_cur, k_shift, \
  46. k_meta, k_ascii, k_lock, k_lowercase, \
  47. k_slock, k_dead2, k_brl, k_ignore
  48. typedef void(k_handler_fn)(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag);
  49. static k_handler_fn K_HANDLERS;
  50. static k_handler_fn *k_handler[16] = { K_HANDLERS };
  51. typedef void(fn_handler_fn)(SDL_EVDEV_keyboard_state *kbd);
  52. static void fn_enter(SDL_EVDEV_keyboard_state *kbd);
  53. static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd);
  54. static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd);
  55. static void fn_num(SDL_EVDEV_keyboard_state *kbd);
  56. static void fn_compose(SDL_EVDEV_keyboard_state *kbd);
  57. static fn_handler_fn *fn_handler[] = {
  58. NULL, fn_enter, NULL, NULL,
  59. NULL, NULL, NULL, fn_caps_toggle,
  60. fn_num, NULL, NULL, NULL,
  61. NULL, fn_caps_on, fn_compose, NULL,
  62. NULL, NULL, NULL, fn_num
  63. };
  64. /*
  65. * Keyboard State
  66. */
  67. struct SDL_EVDEV_keyboard_state
  68. {
  69. int console_fd;
  70. bool muted;
  71. int old_kbd_mode;
  72. unsigned short **key_maps;
  73. unsigned char shift_down[NR_SHIFT]; // shift state counters..
  74. bool dead_key_next;
  75. int npadch; // -1 or number assembled on pad
  76. struct kbdiacrs *accents;
  77. unsigned int diacr;
  78. bool rep; // flag telling character repeat
  79. unsigned char lockstate;
  80. unsigned char slockstate;
  81. unsigned char ledflagstate;
  82. char shift_state;
  83. char text[128];
  84. unsigned int text_len;
  85. void (*vt_release_callback)(void *);
  86. void *vt_release_callback_data;
  87. void (*vt_acquire_callback)(void *);
  88. void *vt_acquire_callback_data;
  89. };
  90. #ifdef DUMP_ACCENTS
  91. static void SDL_EVDEV_dump_accents(SDL_EVDEV_keyboard_state *kbd)
  92. {
  93. unsigned int i;
  94. printf("static struct kbdiacrs default_accents = {\n");
  95. printf(" %d,\n", kbd->accents->kb_cnt);
  96. printf(" {\n");
  97. for (i = 0; i < kbd->accents->kb_cnt; ++i) {
  98. struct kbdiacr *diacr = &kbd->accents->kbdiacr[i];
  99. printf(" { 0x%.2x, 0x%.2x, 0x%.2x },\n",
  100. diacr->diacr, diacr->base, diacr->result);
  101. }
  102. while (i < 256) {
  103. printf(" { 0x00, 0x00, 0x00 },\n");
  104. ++i;
  105. }
  106. printf(" }\n");
  107. printf("};\n");
  108. }
  109. #endif // DUMP_ACCENTS
  110. #ifdef DUMP_KEYMAP
  111. static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
  112. {
  113. int i, j;
  114. for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
  115. if (kbd->key_maps[i]) {
  116. printf("static unsigned short default_key_map_%d[NR_KEYS] = {", i);
  117. for (j = 0; j < NR_KEYS; ++j) {
  118. if ((j % 8) == 0) {
  119. printf("\n ");
  120. }
  121. printf("0x%.4x, ", kbd->key_maps[i][j]);
  122. }
  123. printf("\n};\n");
  124. }
  125. }
  126. printf("\n");
  127. printf("static unsigned short *default_key_maps[MAX_NR_KEYMAPS] = {\n");
  128. for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
  129. if (kbd->key_maps[i]) {
  130. printf(" default_key_map_%d,\n", i);
  131. } else {
  132. printf(" NULL,\n");
  133. }
  134. }
  135. printf("};\n");
  136. }
  137. #endif // DUMP_KEYMAP
  138. static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL;
  139. static int kbd_cleanup_sigactions_installed = 0;
  140. static int kbd_cleanup_atexit_installed = 0;
  141. static struct sigaction old_sigaction[NSIG];
  142. static int fatal_signals[] = {
  143. // Handlers for SIGTERM and SIGINT are installed in SDL_InitQuit.
  144. SIGHUP, SIGQUIT, SIGILL, SIGABRT,
  145. SIGFPE, SIGSEGV, SIGPIPE, SIGBUS,
  146. SIGSYS
  147. };
  148. static void kbd_cleanup(void)
  149. {
  150. SDL_EVDEV_keyboard_state *kbd = kbd_cleanup_state;
  151. if (!kbd) {
  152. return;
  153. }
  154. kbd_cleanup_state = NULL;
  155. ioctl(kbd->console_fd, KDSKBMODE, kbd->old_kbd_mode);
  156. }
  157. static void SDL_EVDEV_kbd_reraise_signal(int sig)
  158. {
  159. (void)raise(sig);
  160. }
  161. static siginfo_t *SDL_EVDEV_kdb_cleanup_siginfo = NULL;
  162. static void *SDL_EVDEV_kdb_cleanup_ucontext = NULL;
  163. static void kbd_cleanup_signal_action(int signum, siginfo_t *info, void *ucontext)
  164. {
  165. struct sigaction *old_action_p = &(old_sigaction[signum]);
  166. sigset_t sigset;
  167. // Restore original signal handler before going any further.
  168. sigaction(signum, old_action_p, NULL);
  169. // Unmask current signal.
  170. sigemptyset(&sigset);
  171. sigaddset(&sigset, signum);
  172. sigprocmask(SIG_UNBLOCK, &sigset, NULL);
  173. // Save original signal info and context for archeologists.
  174. SDL_EVDEV_kdb_cleanup_siginfo = info;
  175. SDL_EVDEV_kdb_cleanup_ucontext = ucontext;
  176. // Restore keyboard.
  177. kbd_cleanup();
  178. // Reraise signal.
  179. SDL_EVDEV_kbd_reraise_signal(signum);
  180. }
  181. static void kbd_unregister_emerg_cleanup(void)
  182. {
  183. int tabidx;
  184. kbd_cleanup_state = NULL;
  185. if (!kbd_cleanup_sigactions_installed) {
  186. return;
  187. }
  188. kbd_cleanup_sigactions_installed = 0;
  189. for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
  190. struct sigaction *old_action_p;
  191. struct sigaction cur_action;
  192. int signum = fatal_signals[tabidx];
  193. old_action_p = &(old_sigaction[signum]);
  194. // Examine current signal action
  195. if (sigaction(signum, NULL, &cur_action)) {
  196. continue;
  197. }
  198. // Check if action installed and not modified
  199. if (!(cur_action.sa_flags & SA_SIGINFO) || cur_action.sa_sigaction != &kbd_cleanup_signal_action) {
  200. continue;
  201. }
  202. // Restore original action
  203. sigaction(signum, old_action_p, NULL);
  204. }
  205. }
  206. static void kbd_cleanup_atexit(void)
  207. {
  208. // Restore keyboard.
  209. kbd_cleanup();
  210. // Try to restore signal handlers in case shared library is being unloaded
  211. kbd_unregister_emerg_cleanup();
  212. }
  213. static void kbd_register_emerg_cleanup(SDL_EVDEV_keyboard_state *kbd)
  214. {
  215. int tabidx;
  216. if (kbd_cleanup_state) {
  217. return;
  218. }
  219. kbd_cleanup_state = kbd;
  220. if (!kbd_cleanup_atexit_installed) {
  221. /* Since glibc 2.2.3, atexit() (and on_exit(3)) can be used within a shared library to establish
  222. * functions that are called when the shared library is unloaded.
  223. * -- man atexit(3)
  224. */
  225. (void)atexit(kbd_cleanup_atexit);
  226. kbd_cleanup_atexit_installed = 1;
  227. }
  228. if (kbd_cleanup_sigactions_installed) {
  229. return;
  230. }
  231. kbd_cleanup_sigactions_installed = 1;
  232. for (tabidx = 0; tabidx < sizeof(fatal_signals) / sizeof(fatal_signals[0]); ++tabidx) {
  233. struct sigaction *old_action_p;
  234. struct sigaction new_action;
  235. int signum = fatal_signals[tabidx];
  236. old_action_p = &(old_sigaction[signum]);
  237. if (sigaction(signum, NULL, old_action_p)) {
  238. continue;
  239. }
  240. /* Skip SIGHUP and SIGPIPE if handler is already installed
  241. * - assume the handler will do the cleanup
  242. */
  243. if ((signum == SIGHUP || signum == SIGPIPE) && (old_action_p->sa_handler != SIG_DFL || (void (*)(int))old_action_p->sa_sigaction != SIG_DFL)) {
  244. continue;
  245. }
  246. new_action = *old_action_p;
  247. new_action.sa_flags |= SA_SIGINFO;
  248. new_action.sa_sigaction = &kbd_cleanup_signal_action;
  249. sigaction(signum, &new_action, NULL);
  250. }
  251. }
  252. enum {
  253. VT_SIGNAL_NONE,
  254. VT_SIGNAL_RELEASE,
  255. VT_SIGNAL_ACQUIRE,
  256. };
  257. static int vt_release_signal;
  258. static int vt_acquire_signal;
  259. static SDL_AtomicInt vt_signal_pending;
  260. typedef void (*signal_handler)(int signum);
  261. static void kbd_vt_release_signal_action(int signum)
  262. {
  263. SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_RELEASE);
  264. }
  265. static void kbd_vt_acquire_signal_action(int signum)
  266. {
  267. SDL_SetAtomicInt(&vt_signal_pending, VT_SIGNAL_ACQUIRE);
  268. }
  269. static bool setup_vt_signal(int signum, signal_handler handler)
  270. {
  271. struct sigaction *old_action_p;
  272. struct sigaction new_action;
  273. old_action_p = &(old_sigaction[signum]);
  274. SDL_zero(new_action);
  275. new_action.sa_handler = handler;
  276. new_action.sa_flags = SA_RESTART;
  277. if (sigaction(signum, &new_action, old_action_p) < 0) {
  278. return false;
  279. }
  280. if (old_action_p->sa_handler != SIG_DFL) {
  281. // This signal is already in use
  282. sigaction(signum, old_action_p, NULL);
  283. return false;
  284. }
  285. return true;
  286. }
  287. static int find_free_signal(signal_handler handler)
  288. {
  289. #ifdef SIGRTMIN
  290. int i;
  291. for (i = SIGRTMIN + 2; i <= SIGRTMAX; ++i) {
  292. if (setup_vt_signal(i, handler)) {
  293. return i;
  294. }
  295. }
  296. #endif
  297. if (setup_vt_signal(SIGUSR1, handler)) {
  298. return SIGUSR1;
  299. }
  300. if (setup_vt_signal(SIGUSR2, handler)) {
  301. return SIGUSR2;
  302. }
  303. return 0;
  304. }
  305. static void kbd_vt_quit(int console_fd)
  306. {
  307. struct vt_mode mode;
  308. if (vt_release_signal) {
  309. sigaction(vt_release_signal, &old_sigaction[vt_release_signal], NULL);
  310. vt_release_signal = 0;
  311. }
  312. if (vt_acquire_signal) {
  313. sigaction(vt_acquire_signal, &old_sigaction[vt_acquire_signal], NULL);
  314. vt_acquire_signal = 0;
  315. }
  316. SDL_zero(mode);
  317. mode.mode = VT_AUTO;
  318. ioctl(console_fd, VT_SETMODE, &mode);
  319. }
  320. static bool kbd_vt_init(int console_fd)
  321. {
  322. struct vt_mode mode;
  323. vt_release_signal = find_free_signal(kbd_vt_release_signal_action);
  324. vt_acquire_signal = find_free_signal(kbd_vt_acquire_signal_action);
  325. if (!vt_release_signal || !vt_acquire_signal ) {
  326. kbd_vt_quit(console_fd);
  327. return false;
  328. }
  329. SDL_zero(mode);
  330. mode.mode = VT_PROCESS;
  331. mode.relsig = vt_release_signal;
  332. mode.acqsig = vt_acquire_signal;
  333. mode.frsig = SIGIO;
  334. if (ioctl(console_fd, VT_SETMODE, &mode) < 0) {
  335. kbd_vt_quit(console_fd);
  336. return false;
  337. }
  338. return true;
  339. }
  340. static void kbd_vt_update(SDL_EVDEV_keyboard_state *state)
  341. {
  342. int signal_pending = SDL_GetAtomicInt(&vt_signal_pending);
  343. if (signal_pending != VT_SIGNAL_NONE) {
  344. if (signal_pending == VT_SIGNAL_RELEASE) {
  345. if (state->vt_release_callback) {
  346. state->vt_release_callback(state->vt_release_callback_data);
  347. }
  348. ioctl(state->console_fd, VT_RELDISP, 1);
  349. } else {
  350. if (state->vt_acquire_callback) {
  351. state->vt_acquire_callback(state->vt_acquire_callback_data);
  352. }
  353. ioctl(state->console_fd, VT_RELDISP, VT_ACKACQ);
  354. }
  355. SDL_CompareAndSwapAtomicInt(&vt_signal_pending, signal_pending, VT_SIGNAL_NONE);
  356. }
  357. }
  358. SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
  359. {
  360. SDL_EVDEV_keyboard_state *kbd;
  361. char flag_state;
  362. char kbtype;
  363. char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 };
  364. kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
  365. if (!kbd) {
  366. return NULL;
  367. }
  368. // This might fail if we're not connected to a tty (e.g. on the Steam Link)
  369. kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
  370. if (!((ioctl(kbd->console_fd, KDGKBTYPE, &kbtype) == 0) && ((kbtype == KB_101) || (kbtype == KB_84)))) {
  371. close(kbd->console_fd);
  372. kbd->console_fd = -1;
  373. }
  374. kbd->npadch = -1;
  375. if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
  376. kbd->shift_state = *shift_state;
  377. }
  378. if (ioctl(kbd->console_fd, KDGKBLED, &flag_state) == 0) {
  379. kbd->ledflagstate = flag_state;
  380. }
  381. kbd->accents = &default_accents;
  382. kbd->key_maps = default_key_maps;
  383. if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
  384. // Set the keyboard in UNICODE mode and load the keymaps
  385. ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
  386. }
  387. kbd_vt_init(kbd->console_fd);
  388. return kbd;
  389. }
  390. void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted)
  391. {
  392. if (!state) {
  393. return;
  394. }
  395. if (muted == state->muted) {
  396. return;
  397. }
  398. if (muted) {
  399. if (SDL_GetHintBoolean(SDL_HINT_MUTE_CONSOLE_KEYBOARD, true)) {
  400. /* Mute the keyboard so keystrokes only generate evdev events
  401. * and do not leak through to the console
  402. */
  403. ioctl(state->console_fd, KDSKBMODE, K_OFF);
  404. /* Make sure to restore keyboard if application fails to call
  405. * SDL_Quit before exit or fatal signal is raised.
  406. */
  407. if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, false)) {
  408. kbd_register_emerg_cleanup(state);
  409. }
  410. }
  411. } else {
  412. kbd_unregister_emerg_cleanup();
  413. // Restore the original keyboard mode
  414. ioctl(state->console_fd, KDSKBMODE, state->old_kbd_mode);
  415. }
  416. state->muted = muted;
  417. }
  418. void 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)
  419. {
  420. if (state == NULL) {
  421. return;
  422. }
  423. state->vt_release_callback = release_callback;
  424. state->vt_release_callback_data = release_callback_data;
  425. state->vt_acquire_callback = acquire_callback;
  426. state->vt_acquire_callback_data = acquire_callback_data;
  427. }
  428. void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state)
  429. {
  430. if (!state) {
  431. return;
  432. }
  433. kbd_vt_update(state);
  434. }
  435. void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
  436. {
  437. if (state == NULL) {
  438. return;
  439. }
  440. SDL_EVDEV_kbd_set_muted(state, false);
  441. kbd_vt_quit(state->console_fd);
  442. if (state->console_fd >= 0) {
  443. close(state->console_fd);
  444. state->console_fd = -1;
  445. }
  446. if (state->key_maps && state->key_maps != default_key_maps) {
  447. int i;
  448. for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
  449. if (state->key_maps[i]) {
  450. SDL_free(state->key_maps[i]);
  451. }
  452. }
  453. SDL_free(state->key_maps);
  454. }
  455. SDL_free(state);
  456. }
  457. /*
  458. * Helper Functions.
  459. */
  460. static void put_queue(SDL_EVDEV_keyboard_state *kbd, uint c)
  461. {
  462. // c is already part of a UTF-8 sequence and safe to add as a character
  463. if (kbd->text_len < (sizeof(kbd->text) - 1)) {
  464. kbd->text[kbd->text_len++] = (char)c;
  465. }
  466. }
  467. static void put_utf8(SDL_EVDEV_keyboard_state *kbd, uint c)
  468. {
  469. if (c < 0x80) {
  470. put_queue(kbd, c); /* 0******* */
  471. } else if (c < 0x800) {
  472. /* 110***** 10****** */
  473. put_queue(kbd, 0xc0 | (c >> 6));
  474. put_queue(kbd, 0x80 | (c & 0x3f));
  475. } else if (c < 0x10000) {
  476. if (c >= 0xD800 && c < 0xE000) {
  477. return;
  478. }
  479. if (c == 0xFFFF) {
  480. return;
  481. }
  482. /* 1110**** 10****** 10****** */
  483. put_queue(kbd, 0xe0 | (c >> 12));
  484. put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
  485. put_queue(kbd, 0x80 | (c & 0x3f));
  486. } else if (c < 0x110000) {
  487. /* 11110*** 10****** 10****** 10****** */
  488. put_queue(kbd, 0xf0 | (c >> 18));
  489. put_queue(kbd, 0x80 | ((c >> 12) & 0x3f));
  490. put_queue(kbd, 0x80 | ((c >> 6) & 0x3f));
  491. put_queue(kbd, 0x80 | (c & 0x3f));
  492. }
  493. }
  494. /*
  495. * We have a combining character DIACR here, followed by the character CH.
  496. * If the combination occurs in the table, return the corresponding value.
  497. * Otherwise, if CH is a space or equals DIACR, return DIACR.
  498. * Otherwise, conclude that DIACR was not combining after all,
  499. * queue it and return CH.
  500. */
  501. static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
  502. {
  503. unsigned int d = kbd->diacr;
  504. unsigned int i;
  505. kbd->diacr = 0;
  506. if (kbd->console_fd >= 0)
  507. if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
  508. // No worries, we'll use the default accent table
  509. }
  510. for (i = 0; i < kbd->accents->kb_cnt; i++) {
  511. if (kbd->accents->kbdiacr[i].diacr == d &&
  512. kbd->accents->kbdiacr[i].base == ch) {
  513. return kbd->accents->kbdiacr[i].result;
  514. }
  515. }
  516. if (ch == ' ' || ch == d) {
  517. return d;
  518. }
  519. put_utf8(kbd, d);
  520. return ch;
  521. }
  522. static bool vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
  523. {
  524. return (kbd->ledflagstate & flag) != 0;
  525. }
  526. static void set_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
  527. {
  528. kbd->ledflagstate |= flag;
  529. ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
  530. }
  531. static void clr_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
  532. {
  533. kbd->ledflagstate &= ~flag;
  534. ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
  535. }
  536. static void chg_vc_kbd_lock(SDL_EVDEV_keyboard_state *kbd, int flag)
  537. {
  538. kbd->lockstate ^= 1 << flag;
  539. }
  540. static void chg_vc_kbd_slock(SDL_EVDEV_keyboard_state *kbd, int flag)
  541. {
  542. kbd->slockstate ^= 1 << flag;
  543. }
  544. static void chg_vc_kbd_led(SDL_EVDEV_keyboard_state *kbd, int flag)
  545. {
  546. kbd->ledflagstate ^= flag;
  547. ioctl(kbd->console_fd, KDSETLED, (unsigned long)(kbd->ledflagstate));
  548. }
  549. /*
  550. * Special function handlers
  551. */
  552. static void fn_enter(SDL_EVDEV_keyboard_state *kbd)
  553. {
  554. if (kbd->diacr) {
  555. put_utf8(kbd, kbd->diacr);
  556. kbd->diacr = 0;
  557. }
  558. }
  559. static void fn_caps_toggle(SDL_EVDEV_keyboard_state *kbd)
  560. {
  561. if (kbd->rep) {
  562. return;
  563. }
  564. chg_vc_kbd_led(kbd, K_CAPSLOCK);
  565. }
  566. static void fn_caps_on(SDL_EVDEV_keyboard_state *kbd)
  567. {
  568. if (kbd->rep) {
  569. return;
  570. }
  571. set_vc_kbd_led(kbd, K_CAPSLOCK);
  572. }
  573. static void fn_num(SDL_EVDEV_keyboard_state *kbd)
  574. {
  575. if (!kbd->rep) {
  576. chg_vc_kbd_led(kbd, K_NUMLOCK);
  577. }
  578. }
  579. static void fn_compose(SDL_EVDEV_keyboard_state *kbd)
  580. {
  581. kbd->dead_key_next = true;
  582. }
  583. /*
  584. * Special key handlers
  585. */
  586. static void k_ignore(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  587. {
  588. }
  589. static void k_spec(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  590. {
  591. if (up_flag) {
  592. return;
  593. }
  594. if (value >= SDL_arraysize(fn_handler)) {
  595. return;
  596. }
  597. if (fn_handler[value]) {
  598. fn_handler[value](kbd);
  599. }
  600. }
  601. static void k_lowercase(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  602. {
  603. }
  604. static void k_self(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  605. {
  606. if (up_flag) {
  607. return; // no action, if this is a key release
  608. }
  609. if (kbd->diacr) {
  610. value = handle_diacr(kbd, value);
  611. }
  612. if (kbd->dead_key_next) {
  613. kbd->dead_key_next = false;
  614. kbd->diacr = value;
  615. return;
  616. }
  617. put_utf8(kbd, value);
  618. }
  619. static void k_deadunicode(SDL_EVDEV_keyboard_state *kbd, unsigned int value, char up_flag)
  620. {
  621. if (up_flag) {
  622. return;
  623. }
  624. kbd->diacr = (kbd->diacr ? handle_diacr(kbd, value) : value);
  625. }
  626. static void k_dead(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  627. {
  628. const unsigned char ret_diacr[NR_DEAD] = { '`', '\'', '^', '~', '"', ',' };
  629. k_deadunicode(kbd, ret_diacr[value], up_flag);
  630. }
  631. static void k_dead2(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  632. {
  633. k_deadunicode(kbd, value, up_flag);
  634. }
  635. static void k_cons(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  636. {
  637. }
  638. static void k_fn(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  639. {
  640. }
  641. static void k_cur(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  642. {
  643. }
  644. static void k_pad(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  645. {
  646. static const char pad_chars[] = "0123456789+-*/\015,.?()#";
  647. if (up_flag) {
  648. return; // no action, if this is a key release
  649. }
  650. if (!vc_kbd_led(kbd, K_NUMLOCK)) {
  651. // unprintable action
  652. return;
  653. }
  654. put_queue(kbd, pad_chars[value]);
  655. }
  656. static void k_shift(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  657. {
  658. int old_state = kbd->shift_state;
  659. if (kbd->rep) {
  660. return;
  661. }
  662. /*
  663. * Mimic typewriter:
  664. * a CapsShift key acts like Shift but undoes CapsLock
  665. */
  666. if (value == KVAL(K_CAPSSHIFT)) {
  667. value = KVAL(K_SHIFT);
  668. if (!up_flag) {
  669. clr_vc_kbd_led(kbd, K_CAPSLOCK);
  670. }
  671. }
  672. if (up_flag) {
  673. /*
  674. * handle the case that two shift or control
  675. * keys are depressed simultaneously
  676. */
  677. if (kbd->shift_down[value]) {
  678. kbd->shift_down[value]--;
  679. }
  680. } else {
  681. kbd->shift_down[value]++;
  682. }
  683. if (kbd->shift_down[value]) {
  684. kbd->shift_state |= (1 << value);
  685. } else {
  686. kbd->shift_state &= ~(1 << value);
  687. }
  688. // kludge
  689. if (up_flag && kbd->shift_state != old_state && kbd->npadch != -1) {
  690. put_utf8(kbd, kbd->npadch);
  691. kbd->npadch = -1;
  692. }
  693. }
  694. static void k_meta(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  695. {
  696. }
  697. static void k_ascii(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  698. {
  699. int base;
  700. if (up_flag) {
  701. return;
  702. }
  703. if (value < 10) {
  704. // decimal input of code, while Alt depressed
  705. base = 10;
  706. } else {
  707. // hexadecimal input of code, while AltGr depressed
  708. value -= 10;
  709. base = 16;
  710. }
  711. if (kbd->npadch == -1) {
  712. kbd->npadch = value;
  713. } else {
  714. kbd->npadch = kbd->npadch * base + value;
  715. }
  716. }
  717. static void k_lock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  718. {
  719. if (up_flag || kbd->rep) {
  720. return;
  721. }
  722. chg_vc_kbd_lock(kbd, value);
  723. }
  724. static void k_slock(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  725. {
  726. k_shift(kbd, value, up_flag);
  727. if (up_flag || kbd->rep) {
  728. return;
  729. }
  730. chg_vc_kbd_slock(kbd, value);
  731. // try to make Alt, oops, AltGr and such work
  732. if (!kbd->key_maps[kbd->lockstate ^ kbd->slockstate]) {
  733. kbd->slockstate = 0;
  734. chg_vc_kbd_slock(kbd, value);
  735. }
  736. }
  737. static void k_brl(SDL_EVDEV_keyboard_state *kbd, unsigned char value, char up_flag)
  738. {
  739. }
  740. void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
  741. {
  742. unsigned char shift_final;
  743. unsigned char type;
  744. unsigned short *key_map;
  745. unsigned short keysym;
  746. if (!state) {
  747. return;
  748. }
  749. state->rep = (down == 2);
  750. shift_final = (state->shift_state | state->slockstate) ^ state->lockstate;
  751. key_map = state->key_maps[shift_final];
  752. if (!key_map) {
  753. // Unsupported shift state (e.g. ctrl = 4, alt = 8), just reset to the default state
  754. state->shift_state = 0;
  755. state->slockstate = 0;
  756. state->lockstate = 0;
  757. return;
  758. }
  759. if (keycode < NR_KEYS) {
  760. if (state->console_fd < 0) {
  761. keysym = key_map[keycode];
  762. } else {
  763. struct kbentry kbe;
  764. kbe.kb_table = shift_final;
  765. kbe.kb_index = keycode;
  766. if (ioctl(state->console_fd, KDGKBENT, &kbe) == 0)
  767. keysym = (kbe.kb_value ^ 0xf000);
  768. else
  769. return;
  770. }
  771. } else {
  772. return;
  773. }
  774. type = KTYP(keysym);
  775. if (type < 0xf0) {
  776. if (down) {
  777. put_utf8(state, keysym);
  778. }
  779. } else {
  780. type -= 0xf0;
  781. // if type is KT_LETTER then it can be affected by Caps Lock
  782. if (type == KT_LETTER) {
  783. type = KT_LATIN;
  784. if (vc_kbd_led(state, K_CAPSLOCK)) {
  785. shift_final = shift_final ^ (1 << KG_SHIFT);
  786. key_map = state->key_maps[shift_final];
  787. if (key_map) {
  788. if (state->console_fd < 0) {
  789. keysym = key_map[keycode];
  790. } else {
  791. struct kbentry kbe;
  792. kbe.kb_table = shift_final;
  793. kbe.kb_index = keycode;
  794. if (ioctl(state->console_fd, KDGKBENT, &kbe) == 0)
  795. keysym = (kbe.kb_value ^ 0xf000);
  796. }
  797. }
  798. }
  799. }
  800. (*k_handler[type])(state, keysym & 0xff, !down);
  801. if (type != KT_SLOCK) {
  802. state->slockstate = 0;
  803. }
  804. }
  805. if (state->text_len > 0) {
  806. state->text[state->text_len] = '\0';
  807. SDL_SendKeyboardText(state->text);
  808. state->text_len = 0;
  809. }
  810. }
  811. #elif !defined(SDL_INPUT_FBSDKBIO) // !SDL_INPUT_LINUXKD
  812. SDL_EVDEV_keyboard_state *SDL_EVDEV_kbd_init(void)
  813. {
  814. return NULL;
  815. }
  816. void SDL_EVDEV_kbd_set_muted(SDL_EVDEV_keyboard_state *state, bool muted)
  817. {
  818. }
  819. void 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)
  820. {
  821. }
  822. void SDL_EVDEV_kbd_update(SDL_EVDEV_keyboard_state *state)
  823. {
  824. }
  825. void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode, int down)
  826. {
  827. }
  828. void SDL_EVDEV_kbd_quit(SDL_EVDEV_keyboard_state *state)
  829. {
  830. }
  831. #endif // SDL_INPUT_LINUXKD