wayland: Fix keymap changed event spam with non-latin keyboard layouts

The function SDL_GetCurrentKeymap() would return null instead of the actual bound keymap for non-latin layouts if certain mapping options were set. Add a parameter to ignore the keymap options and always return the actual bound keymap, which is needed in the Wayland backend to avoid spamming keymap changed events on every keystroke with certain layouts.
This commit is contained in:
Frank Praznik
2025-05-21 11:21:39 -04:00
parent b8e055ce64
commit 20e8ac0075
4 changed files with 24 additions and 19 deletions

View File

@@ -239,20 +239,22 @@ void SDL_ResetKeyboard(void)
}
}
SDL_Keymap *SDL_GetCurrentKeymap(void)
SDL_Keymap *SDL_GetCurrentKeymap(bool ignore_options)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
SDL_Keymap *keymap = SDL_keyboard.keymap;
if (keymap && keymap->thai_keyboard) {
// Thai keyboards are QWERTY plus Thai characters, use the default QWERTY keymap
return NULL;
}
if (!ignore_options) {
if (keymap && keymap->thai_keyboard) {
// Thai keyboards are QWERTY plus Thai characters, use the default QWERTY keymap
return NULL;
}
if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) &&
keymap && !keymap->latin_letters) {
// We'll use the default QWERTY keymap
return NULL;
if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) &&
keymap && !keymap->latin_letters) {
// We'll use the default QWERTY keymap
return NULL;
}
}
return keyboard->keymap;
@@ -490,7 +492,7 @@ SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate, b
SDL_Keyboard *keyboard = &SDL_keyboard;
if (key_event) {
SDL_Keymap *keymap = SDL_GetCurrentKeymap();
SDL_Keymap *keymap = SDL_GetCurrentKeymap(false);
bool numlock = (modstate & SDL_KMOD_NUM) != 0;
SDL_Keycode keycode;

View File

@@ -1059,7 +1059,7 @@ const char *SDL_GetKeyName(SDL_Keycode key)
// but the key name is defined as the letter printed on that key,
// which is usually the shifted capital letter.
if (key > 0x7F || (key >= 'a' && key <= 'z')) {
SDL_Keymap *keymap = SDL_GetCurrentKeymap();
SDL_Keymap *keymap = SDL_GetCurrentKeymap(false);
SDL_Keymod modstate;
SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
if (scancode != SDL_SCANCODE_UNKNOWN && !(modstate & SDL_KMOD_SHIFT)) {
@@ -1127,7 +1127,7 @@ SDL_Keycode SDL_GetKeyFromName(const char *name)
// SDL_Keycode is defined as the unshifted key on the keyboard,
// but the key name is defined as the letter printed on that key,
// which is usually the shifted capital letter.
SDL_Keymap *keymap = SDL_GetCurrentKeymap();
SDL_Keymap *keymap = SDL_GetCurrentKeymap(false);
SDL_Keymod modstate;
SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & (SDL_KMOD_SHIFT | SDL_KMOD_CAPS))) {

View File

@@ -34,7 +34,10 @@ typedef struct SDL_Keymap
bool thai_keyboard;
} SDL_Keymap;
SDL_Keymap *SDL_GetCurrentKeymap(void);
/* This may return null even when a keymap is bound, depending on the current keyboard mapping options.
* Set 'ignore_options' to true to always return the keymap that is actually bound.
*/
SDL_Keymap *SDL_GetCurrentKeymap(bool ignore_options);
SDL_Keymap *SDL_CreateKeymap(bool auto_release);
void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate, SDL_Keycode keycode);
SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate);

View File

@@ -438,7 +438,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS)
// If key repeat is active, we'll need to cap our maximum wait time to handle repeats
wl_list_for_each (seat, &d->seat_list, link) {
if (keyboard_repeat_is_set(&seat->keyboard.repeat)) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap()) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap(true)) {
SDL_SetKeymap(seat->keyboard.sdl_keymap, true);
SDL_SetModState(seat->keyboard.pressed_modifiers | seat->keyboard.locked_modifiers);
}
@@ -477,7 +477,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS)
// If key repeat is active, we might have woken up to generate a key event
if (key_repeat_active) {
wl_list_for_each (seat, &d->seat_list, link) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap()) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap(true)) {
SDL_SetKeymap(seat->keyboard.sdl_keymap, true);
SDL_SetModState(seat->keyboard.pressed_modifiers | seat->keyboard.locked_modifiers);
}
@@ -548,7 +548,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this)
wl_list_for_each (seat, &d->seat_list, link) {
if (keyboard_repeat_is_set(&seat->keyboard.repeat)) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap()) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap(true)) {
SDL_SetKeymap(seat->keyboard.sdl_keymap, true);
SDL_SetModState(seat->keyboard.pressed_modifiers | seat->keyboard.locked_modifiers);
}
@@ -1820,7 +1820,7 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
Uint64 timestamp = SDL_GetTicksNS();
window->last_focus_event_time_ns = timestamp;
if (SDL_GetCurrentKeymap() != seat->keyboard.sdl_keymap) {
if (SDL_GetCurrentKeymap(true) != seat->keyboard.sdl_keymap) {
SDL_SetKeymap(seat->keyboard.sdl_keymap, true);
}
@@ -1970,7 +1970,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
Wayland_UpdateImplicitGrabSerial(seat, serial);
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap()) {
if (seat->keyboard.sdl_keymap != SDL_GetCurrentKeymap(true)) {
SDL_SetKeymap(seat->keyboard.sdl_keymap, true);
SDL_SetModState(seat->keyboard.pressed_modifiers | seat->keyboard.locked_modifiers);
}
@@ -2131,7 +2131,7 @@ static void Wayland_SeatDestroyKeyboard(SDL_WaylandSeat *seat, bool send_event)
SDL_RemoveKeyboard(seat->keyboard.sdl_id, send_event);
if (seat->keyboard.sdl_keymap) {
if (seat->keyboard.sdl_keymap == SDL_GetCurrentKeymap()) {
if (seat->keyboard.sdl_keymap == SDL_GetCurrentKeymap(true)) {
SDL_SetKeymap(NULL, false);
}
SDL_DestroyKeymap(seat->keyboard.sdl_keymap);