Skip to content

fix(useMouse): Magic Remote clicks dead on Chrome <51 (LG webOS 3.x)#45

Merged
chiefcll merged 1 commit into
mainfrom
fix/webos-legacy-keyboard-event
Jul 20, 2026
Merged

fix(useMouse): Magic Remote clicks dead on Chrome <51 (LG webOS 3.x)#45
chiefcll merged 1 commit into
mainfrom
fix/webos-legacy-keyboard-event

Conversation

@chiefcll

Copy link
Copy Markdown
Contributor

What changed

useMouse routes pointer interactions through the focus manager by dispatching synthetic KeyboardEvents — Enter (13) on click, ArrowUp/ArrowDown (38/40) on scroll wheel. On Chrome < 51 (LG webOS 3.x ships Chrome 38) the KeyboardEvent constructor exists but ignores the key/keyCode/which members of KeyboardEventInit, so the events arrived with key: '' / keyCode: 0. The focus manager resolves keys via keyMapEntries[e.key] || keyMapEntries[e.keyCode], so they mapped to nothing and were silently dropped: every Magic Remote click and scroll-wheel tick did nothing on those devices. Hardware remote keys were unaffected (real events carry keyCode).

createKeyboardEvent now checks whether the constructor honored the init members and, only when it didn't, forces key/keyCode/which onto the event instance with Object.defineProperty getters.

Why this approach

  • Modern engines are untouched — the check fails and the event goes out exactly as before, no property overrides (asserted in a test via Object.getOwnPropertyDescriptor).
  • Avoids the deprecated initKeyboardEvent API.
  • A comment on the fallback branch documents the Chrome < 51 / webOS 3.x constraint so it doesn't get "simplified" away later.

Tests

New describe block in tests/useMouse.test.tsx:

  • Modern path: click dispatches Enter with key/keyCode/which intact and no own-property descriptors (pure constructor path).
  • Legacy path: a stubbed KeyboardEvent that drops init members (mimicking Chrome 38) — the click event still reports Enter/13/13, and with useFocusManager wired the element's onEnter fires, verifying dispatch → key mapping → handler end-to-end.
  • Legacy wheel: scroll produces ArrowDown/40 and ArrowUp/38 with forced values.

Reviewer notes

  • The new tests attach their keydown capture listener only after setup waits, because earlier tests in the file leave a 1ms-delayed synthetic Enter pending at dispose time that would otherwise leak into the capture.
  • Full suite (139 tests), npm run tsc, and lint all pass; no new lint warnings in touched files.

🤖 Generated with Claude Code

…webOS 3.x)

On Chrome < 51 (LG webOS 3.x runs Chrome 38) the KeyboardEvent
constructor ignores the key/keyCode/which init members, so the
synthetic Enter/ArrowUp/ArrowDown events dispatched by useMouse
arrived with key '' / keyCode 0 and the focusManager silently
dropped them — every Magic Remote click and scroll did nothing.

Detect when the constructor dropped the init members and force the
values onto the event instance with Object.defineProperty getters.
Modern engines keep the plain constructor path unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@chiefcll
chiefcll merged commit 9ac2ce0 into main Jul 20, 2026
1 check passed
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