evdev_kbd: Use current keymap keymap can change over time, caching the keymap causes wrong keys returned when user changes keymap during runtime Signed-off-by: Michal Suchanek <msuchanek@suse.de>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c
index f7ccca7..6535fdf 100644
--- a/src/core/linux/SDL_evdev_kbd.c
+++ b/src/core/linux/SDL_evdev_kbd.c
@@ -153,45 +153,6 @@ static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
}
#endif /* DUMP_KEYMAP */
-static int SDL_EVDEV_kbd_load_keymaps(SDL_EVDEV_keyboard_state *kbd)
-{
- int i, j;
-
- kbd->key_maps = (unsigned short **)SDL_calloc(MAX_NR_KEYMAPS, sizeof(unsigned short *));
- if (!kbd->key_maps) {
- return -1;
- }
-
- for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
- struct kbentry kbe;
-
- kbe.kb_table = i;
- kbe.kb_index = 0;
- if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
- return -1;
- }
-
- if (kbe.kb_value == K_NOSUCHMAP) {
- continue;
- }
-
- kbd->key_maps[i] = (unsigned short *)SDL_malloc(NR_KEYS * sizeof(unsigned short));
- if (!kbd->key_maps[i]) {
- return -1;
- }
-
- for (j = 0; j < NR_KEYS; ++j) {
- kbe.kb_table = i;
- kbe.kb_index = j;
- if (ioctl(kbd->console_fd, KDGKBENT, &kbe) < 0) {
- return -1;
- }
- kbd->key_maps[i][j] = (kbe.kb_value ^ 0xf000);
- }
- }
- return 0;
-}
-
static SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL;
static int kbd_cleanup_sigactions_installed = 0;
static int kbd_cleanup_atexit_installed = 0;
@@ -339,8 +300,8 @@ SDL_EVDEV_keyboard_state *
SDL_EVDEV_kbd_init(void)
{
SDL_EVDEV_keyboard_state *kbd;
- int i;
char flag_state;
+ char kbtype;
char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 };
kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
@@ -348,10 +309,14 @@ SDL_EVDEV_kbd_init(void)
return NULL;
}
- kbd->npadch = -1;
-
/* 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;
@@ -362,48 +327,27 @@ SDL_EVDEV_kbd_init(void)
}
kbd->accents = &default_accents;
- if (ioctl(kbd->console_fd, KDGKBDIACR, kbd->accents) < 0) {
- /* No worries, we'll use the default accent table */
- }
-
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);
+ }
- if (SDL_EVDEV_kbd_load_keymaps(kbd) < 0) {
- for (i = 0; i < MAX_NR_KEYMAPS; ++i) {
- if (kbd->key_maps[i]) {
- SDL_free(kbd->key_maps[i]);
- }
- }
- SDL_free(kbd->key_maps);
-
- kbd->key_maps = default_key_maps;
- }
+ /* 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(kbd->console_fd, KDSKBMODE, K_OFF);
- /* 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(kbd->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(kbd);
- }
+ /* 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(kbd);
}
}
-
-#ifdef DUMP_ACCENTS
- SDL_EVDEV_dump_accents(kbd);
-#endif
-#ifdef DUMP_KEYMAP
- SDL_EVDEV_dump_keymap(kbd);
-#endif
return kbd;
}
@@ -489,6 +433,11 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
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) {
@@ -795,7 +744,17 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode
}
if (keycode < NR_KEYS) {
- keysym = key_map[keycode];
+ 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;
}
@@ -814,9 +773,18 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode
type = KT_LATIN;
if (vc_kbd_led(state, K_CAPSLOCK)) {
- key_map = state->key_maps[shift_final ^ (1 << KG_SHIFT)];
+ shift_final = shift_final ^ (1 << KG_SHIFT);
+ key_map = state->key_maps[shift_final];
if (key_map) {
- keysym = key_map[keycode];
+ 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);
+ }
}
}
}