mirror of
				https://github.com/Ryujinx/SDL.git
				synced 2025-11-04 15:34:58 +00:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									fd4bb4154b
								
							
						
					
					
						commit
						96a2a6b945
					
				| 
						 | 
					@ -153,45 +153,6 @@ static void SDL_EVDEV_dump_keymap(SDL_EVDEV_keyboard_state *kbd)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif /* DUMP_KEYMAP */
 | 
					#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 SDL_EVDEV_keyboard_state *kbd_cleanup_state = NULL;
 | 
				
			||||||
static int kbd_cleanup_sigactions_installed = 0;
 | 
					static int kbd_cleanup_sigactions_installed = 0;
 | 
				
			||||||
static int kbd_cleanup_atexit_installed = 0;
 | 
					static int kbd_cleanup_atexit_installed = 0;
 | 
				
			||||||
| 
						 | 
					@ -339,8 +300,8 @@ SDL_EVDEV_keyboard_state *
 | 
				
			||||||
SDL_EVDEV_kbd_init(void)
 | 
					SDL_EVDEV_kbd_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SDL_EVDEV_keyboard_state *kbd;
 | 
					    SDL_EVDEV_keyboard_state *kbd;
 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
    char flag_state;
 | 
					    char flag_state;
 | 
				
			||||||
 | 
					    char kbtype;
 | 
				
			||||||
    char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 };
 | 
					    char shift_state[sizeof(long)] = { TIOCL_GETSHIFTSTATE, 0 };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
 | 
					    kbd = (SDL_EVDEV_keyboard_state *)SDL_calloc(1, sizeof(*kbd));
 | 
				
			||||||
| 
						 | 
					@ -348,10 +309,14 @@ SDL_EVDEV_kbd_init(void)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kbd->npadch = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
 | 
					    /* 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);
 | 
					    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) {
 | 
					    if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
 | 
				
			||||||
        kbd->shift_state = *shift_state;
 | 
					        kbd->shift_state = *shift_state;
 | 
				
			||||||
| 
						 | 
					@ -362,48 +327,27 @@ SDL_EVDEV_kbd_init(void)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kbd->accents = &default_accents;
 | 
					    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;
 | 
					    kbd->key_maps = default_key_maps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
 | 
					    if (ioctl(kbd->console_fd, KDGKBMODE, &kbd->old_kbd_mode) == 0) {
 | 
				
			||||||
        /* Set the keyboard in UNICODE mode and load the keymaps */
 | 
					        /* Set the keyboard in UNICODE mode and load the keymaps */
 | 
				
			||||||
        ioctl(kbd->console_fd, KDSKBMODE, K_UNICODE);
 | 
					        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);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            /* 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
 | 
					    /* Allow inhibiting keyboard mute with env. variable for debugging etc. */
 | 
				
			||||||
    SDL_EVDEV_dump_accents(kbd);
 | 
					    if (SDL_getenv("SDL_INPUT_LINUX_KEEP_KBD") == NULL) {
 | 
				
			||||||
#endif
 | 
					        /* Mute the keyboard so keystrokes only generate evdev events
 | 
				
			||||||
#ifdef DUMP_KEYMAP
 | 
					         * and do not leak through to the console
 | 
				
			||||||
    SDL_EVDEV_dump_keymap(kbd);
 | 
					         */
 | 
				
			||||||
#endif
 | 
					        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);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return kbd;
 | 
					    return kbd;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -489,6 +433,11 @@ static unsigned int handle_diacr(SDL_EVDEV_keyboard_state *kbd, unsigned int ch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kbd->diacr = 0;
 | 
					    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++) {
 | 
					    for (i = 0; i < kbd->accents->kb_cnt; i++) {
 | 
				
			||||||
        if (kbd->accents->kbdiacr[i].diacr == d &&
 | 
					        if (kbd->accents->kbdiacr[i].diacr == d &&
 | 
				
			||||||
            kbd->accents->kbdiacr[i].base == ch) {
 | 
					            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) {
 | 
					    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 {
 | 
					    } else {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -814,9 +773,18 @@ void SDL_EVDEV_kbd_keycode(SDL_EVDEV_keyboard_state *state, unsigned int keycode
 | 
				
			||||||
            type = KT_LATIN;
 | 
					            type = KT_LATIN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (vc_kbd_led(state, K_CAPSLOCK)) {
 | 
					            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) {
 | 
					                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);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue