fix(@wterm/dom): support IME composition (Japanese/Chinese/Korean input)#50
Open
sakaritoru wants to merge 3 commits into
Open
fix(@wterm/dom): support IME composition (Japanese/Chinese/Korean input)#50sakaritoru wants to merge 3 commits into
sakaritoru wants to merge 3 commits into
Conversation
IME first keystroke (e.g. typing 'k' to compose 'か') fires keydown with keyCode 229 before compositionstart. Without this guard, the raw latin key is sent to the PTY in addition to the eventual composed character, which breaks Japanese/Chinese/Korean input. Also bail when e.isComposing is true (defense in depth for browsers that surface it on keydown). Refs: w3c/uievents-key#23, xtermjs/xterm.js handles this similarly.
The hidden textarea sits at left:-9999px which means the OS IME inline preview (the candidate window's pre-edit text) is rendered off-screen. Users can compose Japanese/Chinese/Korean but can't see what they're typing until they commit. Mirror xterm.js's approach: keep the textarea at the cursor as an input antenna, and add a separate <span class="term-composition"> overlay that renders the candidate string with the terminal's font and background. The textarea stays opacity:0 so the OS caret never shows through. Lifecycle: compositionstart -> position textarea + show overlay compositionupdate -> overlay textContent = e.data compositionend -> hide overlay + send committed data once A MutationObserver re-positions the textarea when the cursor element moves so subsequent compositions land at the right column.
Full-screen TUIs (Claude Code, vim, less, tmux, etc.) routinely emit
\x1b[?25l to hide the cursor while drawing their own UI. The renderer
removes the .term-cursor element when the cursor is invisible, so
querySelector(".term-cursor") returns null and the composition overlay
ends up at the document origin instead of the prompt position.
Fall back to bridge.getCursor() and resolve a pixel position from the
matching .term-row plus a measured monospace character width. The probe
caches its result unconditionally — an unmeasurable layout (jsdom)
would otherwise re-probe on every observer fire and recurse forever.
|
@sakaritoru is attempting to deploy a commit to the Vercel Labs Team on Vercel. A member of the Team first needs to authorize it. |
nzinfo
added a commit
to coreseekdev/wterm
that referenced
this pull request
May 10, 2026
…panese/Chinese/Korean input)
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.
Summary
Adds IME (Input Method Editor) composition support to
@wterm/dom, fixing three independent issues that broke Japanese / Chinese / Korean text entry:keydown(which fires withkeyCode === 229beforecompositionstart) was forwarded to the PTY as a raw character, so commits like `こんにちは` produced `kこんにちは`.Changes
Three atomic commits, all scoped to `packages/@wterm/dom/src/input.ts` and its tests:
No API surface change. No new dependencies. No other packages touched.
Test plan
Notes