emscripten: dedupe keyboard event listeners across multiple windows#15511
Open
vittorioromeo wants to merge 1 commit intolibsdl-org:mainfrom
Open
emscripten: dedupe keyboard event listeners across multiple windows#15511vittorioromeo wants to merge 1 commit intolibsdl-org:mainfrom
vittorioromeo wants to merge 1 commit intolibsdl-org:mainfrom
Conversation
Contributor
Author
|
This is related to #12512 -- this PR shouldn't make the situation any worse than it is today. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DISCLAIMER: AI assistance was used to identify and understand the bug. The fix was hand-written.
Summary
On Emscripten, every browser
keydownproduces twoSDL_EVENT_KEY_DOWNevents per physical keypress when more than one SDL window has been created. The second event carriesrepeat=trueand shares the same timestamp as the first.The cause is a missing dedupe step in
Emscripten_RegisterEventHandlers: each SDL window stacks another listener on the same DOM target.Reproduction
MCVE: repro_emscripten_keyboard_dup.c
Compile with
emcc, linking against SDL3, and run withemrun. Press any key -- prior to this PR, you should see two log lines being printed out (with identical timestamps). After this fix, only one log line should be printed.Description
Emscripten_RegisterEventHandlersinsrc/video/emscripten/SDL_emscriptenevents.cis called once per SDL window. Each invocation does:These funnel into emscripten's
JSEvents.registerOrRemoveHandler(src/lib/libhtml5.js):When two SDL windows share the same keyboard target, the second
emscripten_set_keydown_callback(...)does not replace the first -- it appends anotheraddEventListenerand another entry inJSEvents.eventHandlers.Every browser
keydownthen fires the C-sideEmscripten_HandleKeytwice in the same JS task, which callsSDL_SendKeyboardKeyAndKeycodetwice in a row. InsideSDL_SendKeyboardKeyInternal(src/events/SDL_keyboard.c):The same stacking issue affects the JS-side document listener
sdlEventHandlerLockKeysCheck.Fix
Two changes to
Emscripten_RegisterEventHandlers, both insrc/video/emscripten/SDL_emscriptenevents.c:Before registering keyboard callbacks, call each setter with
NULLfirst to clear any prior handler on the same target.Before assigning a new
document.sdlEventHandlerLockKeysCheckclosure and adding it as akeydownlistener ondocument, remove the previous one if present.Testing
Manually tested on Chrome via
emrunwith the attached repro.Notes
I encountered this issue as part of the development of my VRSFML library, an opinionated C++23 fork of SFML that also targets Emscripten natively.
The fork maintains the same GL context model as upstream SFML: one hidden GL context (shared between all windows), and one GL context per window.
Having a shared GL context is actually nice because many resources such as textures or shaders can be reused between windows. Internally, I keep the same logic also for the Emscripten target, creating a hidden window:
The presence of this hidden window plus enabling repeated key presses led to the discovery of this bug.