fix(osr): give the page e.key back — a zero character pair is FlagsChanged - #32
Merged
Conversation
…anged
Every printable keydown reached the page as `e.key === "Unidentified"`, so no
page-level keyboard shortcut worked in an OSR webview (⌘F, ⌘K, j/k navigation).
`e.code` was correct throughout, which made it look like a partial keyboard
rather than a broken one.
The cause is not a missing `dom_key`. CEF never sets `dom_key` on macOS at all —
`TranslateWebKeyEvent` builds a synthetic NSEvent and lets Chromium's
`NativeWebKeyboardEvent` derive it. But its first branch is:
if (key_event.character == 0 && key_event.unmodified_character == 0)
event_type = NSEventTypeFlagsChanged;
and `DomKeyFromNSEvent` answers a FlagsChanged event with
`DomKeyFromKeyCode()`, which maps only the modifier keys. We sent 0 for every
printable key — `kCefMacKeyChars` held editing/navigation keys only — so each
one was delivered as a modifier-state change carrying no modifier.
`DomCodeFromNSEvent` reads `keyCode` whatever the event type, which is exactly
why `e.code` survived and hid the shape of the bug.
So `cefMacCharForKey` now falls back to the key's own printable codepoint
(`LogicalKeyboardKey.keyId` is the lowercase Unicode value and follows the
active layout, so it is the character macOS would report), and the call site
prefers the typed character when there is one — a shifted key reports `A` like
a browser rather than the unshifted `a`. The function-row keys get their
NSEvent private-use codepoints for the same reason. Modifier keys stay 0:
FlagsChanged is the correct event for them, and it is the one case
`DomKeyFromKeyCode` does map.
Dart-side only — `main.mm` already forwards `character` into both CefKeyEvent
character fields, so no protocol change and no cef_host rebuild.
Follow-up, not needed for this fix: `unmodified_character` is currently a copy
of `character`, and `is_system_key` is never sent at all. Carrying both
properly needs two new wire fields and a host rebuild.
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.
Every printable keydown reached the page as
e.key === "Unidentified", so nopage-level keyboard shortcut worked in an OSR webview.
e.codewas correctthroughout, which made it look like a partial keyboard rather than a broken one.
Cause
Not a missing
dom_key— CEF never setsdom_keyon macOS at all.TranslateWebKeyEventbuilds a syntheticNSEventand lets Chromium'sNativeWebKeyboardEventderive it. But its first branch is:and
DomKeyFromNSEventanswers a FlagsChanged event withDomKeyFromKeyCode(),which maps only the modifier keys:
We sent
0for every printable key —kCefMacKeyCharsheld editing/navigationkeys only — so each one was delivered as a modifier-state change carrying no
modifier.
DomCodeFromNSEventreadskeyCodewhatever the event type, which isexactly why
e.codesurvived and hid the shape of the bug.Fix
cefMacCharForKeyfalls back to the key's own printable codepoint.LogicalKeyboardKey.keyIdis the lowercase Unicode value and follows the activelayout, so it is the character macOS would report. The call site prefers the
typed character when there is one, so a shifted key reports
Alike a browserrather than the unshifted
a. Function-row keys get their NSEvent private-usecodepoints for the same reason.
Modifier keys stay
0— FlagsChanged is the correct event for them, and it isthe one case
DomKeyFromKeyCodedoes map.Dart-side only:
main.mmalready forwardscharacterinto bothCefKeyEventcharacter fields, so no protocol change and no
cef_hostrebuild.Verification
Built the example app against a probe page with no JS shim. Confirmed live:
plain letters, Shift+letter, function keys, arrows, and ⌘ combos all report a
real
e.key.⌘A and ⌘F still do not reach the page, and that is unrelated to this bug — the
accelerator block claims ⌘C ⌘X ⌘V ⌘A ⌘Z ⌘⇧Z ⌘= ⌘- ⌘0 and returns
handledbefore
sendKey, plus ⌘F when the host wiresonFind. ⌘J confirms the ⌘ pathitself is fixed.
Full analyze clean; 173 tests pass. One existing test asserted
printable keys carry no override char (-> 0; they ride the IME)— it encodedthe bug, so it is replaced by its inverse plus a modifier-keys-stay-zero guard.
Known follow-ups (not in this PR)
unmodified_characteris a copy ofcharacter, so it is wrong for Shift andOption and for non-Latin layouts;
is_system_keyis never sent at all.Carrying both properly needs two new wire fields and a host rebuild.
preventDefault()on⌘A should suppress select-all. The nine accelerators above are currently
unconditional. CEF supports the browser behaviour via
OnPreKeyEventmarking the combo
is_keyboard_shortcut.