Skip to content

Inject synthetic keyup events to recover from macOS swallowing them while a Meta key is held#7

Open
lxpollitt wants to merge 1 commit into
lanceewing:masterfrom
lxpollitt:pr1-synthetic-keyup
Open

Inject synthetic keyup events to recover from macOS swallowing them while a Meta key is held#7
lxpollitt wants to merge 1 commit into
lanceewing:masterfrom
lxpollitt:pr1-synthetic-keyup

Conversation

@lxpollitt
Copy link
Copy Markdown
Contributor

This PR addresses macOS swallowing keyup events while a Meta (CMD) key is held.

Problem

On macOS, the OS swallows keyup events for non-modifier keys whose keyup would land while a Meta (CMD) key is held. This is a long-standing macOS behaviour is inherited by Safari, Chrome, and Firefox. This results in the key becoming "stuck" down, until it is next pressed and released. So for example, if the user types CMD-X into the Oric BASIC command line, then X becomes stuck held down, generating auto-repeat X characters indefinitely until the user next presses and releases X. (And because of Oric's keyboard scanning behaviour, pressing any other key does not cancel the auto-repeat / stuck key. You have to press the X itself.)

Fix

Added a DOM-level keydown/keyup listener via JSNI to GwtKeyboardMatrix. It tracks which non-Meta keycodes have received a keydown but not yet a keyup. On the transition from CMD-held → CMD-released, it dispatches synthetic DOM keyup events for those tracked keys. The synthetic events flow through libGDX's normal listener path (it doesn't know they're synthetic) and clear the stuck pressedKeys[] entries.

Scope

  • GWT/web only. The lwjgl3 desktop backend already correctly translates GLFW_KEY_LEFT/RIGHT_SUPER to Keys.SYM, so I think it doesn't have the same pressedKeys[] gate problem. But note I've not been able to test this first hand because the desktop version doesn't currently run for me on my Mac. (I may investigate this problem another time.)
  • Listens with useCapture=true so it runs before libGDX's own listener (which uses useCapture=false).

Testing

I've confirmed the fix behaves as expected for me using both Safari and Chrome on macOS. I haven't been able to verity Windows and Linux behaves as expected as I don't have easy access to a Windows or Linux desktops. I think the code is pretty safe but it would be good to verify on at least one other OS to be sure before merging.

…hile a Meta key is held

macOS suppresses keyUp events for non-modifier keys whose keyUp would
occur while a Meta (CMD) key is held - an OS-level behaviour inherited
by Chrome, Safari and Firefox.

GwtKeyboardMatrix's UI-thread constructor now installs a DOM-level
keydown/keyup listener (capture phase, so it runs before libGDX's own
document-level bubble-phase listener). The listener tracks which non-
Meta keys have unreleased keydowns and, on Meta release, dispatches a
synthetic keyup event for each. The synthetic events flow through
libGDX's normal keyup handler and clear its internal pressedKeys[]
state.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant