fix(terminal): stop losing fast IME-mode English input - #1276
Open
jt-wang wants to merge 2 commits into
Open
Conversation
With a Chinese IME active on macOS, Chromium reports every keydown with
keyCode 229 (keeping the real character in `key`) — including the IME's
ASCII/English mode. xterm routes 229 keydowns through CompositionHelper's
textarea-diff path, which batches pending input behind a single 0ms timer
over the shared helper textarea.
The forwarder still claimed ASCII/CJK punctuation among those keydowns and
cleared that same textarea after forwarding, destroying the pending diff
baseline. Fast typing then lost whole letter runs ("what's the next step"
-> "'s the next step"), and a clear landing on a non-empty baseline made
the diff emit a spurious DEL that deleted the just-forwarded character —
the "cannot type ?" symptom. Slow typing let the timer drain first, and
IME-committed CJK strings bypass the path entirely, which is why only
fast English typing appeared broken.
keyCode 229 keydowns now stay with xterm's IME machinery, whose diff
forwards the inserted text (including full-width punctuation) verbatim.
The claim remains for non-IME keydowns, where xterm would otherwise
synthesize the raw ASCII byte and miss the IME's replacement text.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Safari dispatches textInput/beforeinput/input BEFORE the corresponding
keydown while a macOS IME is active (including IME English modes), and
overlapping keystrokes keep the previous key held when the next key's
input event arrives. xterm's _inputEvent guarded on
(!ev.composed || !this._keyDownSeen), a Chromium-order heuristic, so
every input event landing between a keydown and the previous keyup was
silently dropped — reproduced byte-for-byte from a user-captured Safari
trace ("it doesn't work" -> "itdoen't wor", losing exactly the rollover
chars) in a bare patched xterm on both WebKit and Chromium.
The patch replaces the ordering heuristic with precise guards: accept
non-composed insertText (composition text still flows through
CompositionHelper), keep the existing _keyPressHandled dedupe, and
cancel CompositionHelper's pending 229 textarea-diff when the input
event delivers the text directly — Chromium IME streams now emit
per-character sends instead of batched diffs, with no double-send.
Verified: bare-xterm A/B on the captured trace (drops before, complete
after, both engines); full-stack replay through WS/PTY/pi; clean-typing
and IME-229 regression matrices; monorepo suite green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
@jt-wang is attempting to deploy a commit to the luokerenx4's Team Team on Vercel. A member of the Team first needs to authorize it. |
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.
Context — With a CJK IME enabled on macOS (even its ASCII/English mode), fast English typing in the workspace terminal silently drops characters:
what's the next step→'s the next step(Chromium);it doesn't work→itdoen't wor(Safari, reproduced byte-for-byte from a captured user trace). Slow typing is unaffected, and IME-committed CJK strings bypass the path entirely — which is why only fast English typing appears broken.Why — Two root causes in two layers, one commit each.
_inputEventguarded on(!ev.composed || !this._keyDownSeen)— a Chromium-order heuristic — so every input event landing between a keydown and the previous keyup was dropped. The bundled xterm patch replaces the ordering heuristic with precise guards: accept non-composed insertText (composition text still flows through CompositionHelper), keep the existing_keyPressHandleddedupe, and cancel the pending 229 textarea-diff when the input event delivers the text directly.Verified: bare-xterm A/B on the captured trace (drops before, complete after, on both WebKit and Chromium); full-stack replay through WS/PTY/pi; clean-typing and IME-229 regression matrices; new 7-test spec for the forwarder; monorepo suite green.
Reviewer action — Target
devper CONTRIBUTING.md. The two commits are independent and can land in either order. Quickest repro: macOS → enable a Chinese IME → switch to its English mode → type fast in the terminal.