From 98e22213dae7395cb2abc011c9dfceb732a74e02 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 13 Sep 2025 01:48:21 -0400 Subject: [PATCH] emscripten: Do a little better at tracking Caps/Num/Scroll Lock state. Fixes #5447. --- src/video/emscripten/SDL_emscriptenevents.c | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 5fbf2cf2cf..d0ec8aa5f4 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -1239,6 +1239,17 @@ void Emscripten_UnregisterGlobalEventHandlers(SDL_VideoDevice *device) emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, NULL, 0, NULL); } +EMSCRIPTEN_KEEPALIVE void Emscripten_HandleLockKeysCheck(SDL_WindowData *window_data, EM_BOOL capslock, EM_BOOL numlock, EM_BOOL scrolllock) +{ + const SDL_Keymod new_mods = (capslock ? SDL_KMOD_CAPS : 0) | (numlock ? SDL_KMOD_NUM : 0) | (scrolllock ? SDL_KMOD_SCROLL : 0); + SDL_Keymod modstate = SDL_GetModState(); + if ((modstate & (SDL_KMOD_CAPS|SDL_KMOD_NUM|SDL_KMOD_SCROLL)) != new_mods) { + modstate &= ~(SDL_KMOD_CAPS|SDL_KMOD_NUM|SDL_KMOD_SCROLL); + modstate |= new_mods; + SDL_SetModState(modstate); + } +} + void Emscripten_RegisterEventHandlers(SDL_WindowData *data) { const char *keyElement; @@ -1250,6 +1261,19 @@ void Emscripten_RegisterEventHandlers(SDL_WindowData *data) keyElement = Emscripten_GetKeyboardTargetElement(data->keyboard_element); if (keyElement) { + MAIN_THREAD_EM_ASM_INT({ + var data = $0; + // our keymod state can get confused in various ways (changed capslock when browser didn't have focus, etc), and you can't query the current + // state from the DOM, outside of a keyboard event, so catch keypresses globally and reset mod state if it's unexpectedly wrong. Best we can do. + // Note that this thing _only_ adjusts the lock keys if necessary; the real SDL keypress handling happens elsewhere. + document.sdlEventHandlerLockKeysCheck = function(event) { + // don't try to adjust the state on the actual lock key presses; the normal key handler will catch that and adjust. + if ((event.key != "CapsLock") && (event.key != "NumLock") && (event.key != "ScrollLock")) { + _Emscripten_HandleLockKeysCheck(data, event.getModifierState("CapsLock"), event.getModifierState("NumLock"), event.getModifierState("ScrollLock")); + } + }; + document.addEventListener("keydown", document.sdlEventHandlerLockKeysCheck); + }, data); emscripten_set_keydown_callback(keyElement, data, 0, Emscripten_HandleKey); emscripten_set_keyup_callback(keyElement, data, 0, Emscripten_HandleKey); emscripten_set_keypress_callback(keyElement, data, 0, Emscripten_HandleKeyPress); @@ -1288,6 +1312,9 @@ void Emscripten_UnregisterEventHandlers(SDL_WindowData *data) emscripten_set_keydown_callback(keyElement, NULL, 0, NULL); emscripten_set_keyup_callback(keyElement, NULL, 0, NULL); emscripten_set_keypress_callback(keyElement, NULL, 0, NULL); + MAIN_THREAD_EM_ASM_INT({ + document.removeEventListener("keydown", document.sdlEventHandlerLockKeysCheck); + }); } emscripten_set_visibilitychange_callback(NULL, 0, NULL);