fix: handle insertReplacementText for Korean IME on WKWebView/Safari#5704
fix: handle insertReplacementText for Korean IME on WKWebView/Safari#5704minemos wants to merge 4 commits intoxtermjs:masterfrom
Conversation
WKWebView (used by Tauri, Capacitor, and Safari-based apps) does not fire
compositionstart/compositionupdate/compositionend events for Korean IME input.
Instead, it fires:
- insertText for initial jamo (e.g. 'ㅎ')
- insertReplacementText for composition updates (e.g. 'ㅎ' → '하' → '한')
Since _inputEvent only handles insertText, composed Korean syllables were
silently dropped, causing only raw jamo to reach the terminal.
This patch:
1. Buffers insertReplacementText data and shows composition preview
2. Intercepts Hangul insertText to buffer instead of sending immediately
3. Flushes the composed syllable on next non-IME keydown or new character
4. Adds wkImeComposing flag to CompositionHelper to suppress
_handleAnyTextareaChanges during synthetic WK composition
Tested with Korean (Hangul) IME in Tauri v2 (macOS WKWebView).
|
Thanks. This patch works fine for tauri 2.0. macos 26.3(25D125), safari, rust and tauri env. hope to merge this on later version xterm.js 6.x.x. |
| /** | ||
| * WKWebView IME workaround: holds the latest composed text from | ||
| * insertReplacementText events, flushed on next insertText or non-IME keydown. | ||
| */ | ||
| private _wkImeComposing: boolean = false; | ||
| private _wkImePending: string = ''; |
There was a problem hiding this comment.
I looked at how the events work Safari and it's unfortunate. How about instead of hardcoding this stuff into CoreBrowserTerminal, have a WkHangulCompositionEventEmulator that maps insertText/insertReplacementText events into compositionstart/update/end events? This class could then also be created only when it looks like webkit.
Apply changes from xtermjs/xterm.js#5704 as a pnpm patch. Adds WKWebView IME workaround that handles insertReplacementText events for Korean (Hangul) composition input, which WKWebView/Safari fires instead of standard composition events. Co-Authored-By: Claude Opus 4.6 <[email protected]>
|
For anyone looking for an external workaround while this PR is being reworked: I've published a standalone module that implements the same logic as an external interceptor (per Tyriar's recommendation to use a separate emulator class): Confirmed working with xterm.js 6.0.0 + Tauri v2 (WKWebView) on macOS. Three-layer approach:
No xterm.js fork needed — works as a drop-in module. |


Summary
WKWebView (used by Tauri, Capacitor, and Safari-based apps on macOS/iOS) does not fire
compositionstart/compositionupdate/compositionendevents for Korean IME input. Instead, it fires:insertTextwithinputType === 'insertText'for the initial jamo (e.g.ㅎ)insertReplacementTextfor composition updates (e.g.ㅎ→하→한)Since
_inputEvent()only handlesinputType === 'insertText', the composed Korean syllables frominsertReplacementTextwere silently dropped, causing only raw jamo to reach the terminal.Changes
CoreBrowserTerminal.ts(main fix):insertReplacementTextdata instead of dropping it, and show composition previewinsertText(before thecomposed/keyDownSeenguard) to buffer instead of sending immediately — WKWebView may setcomposed=trueon Hangul syllablesCompositionHelper.ts(minimal):wkImeComposingflag to suppress_handleAnyTextareaChanges()during synthetic WK composition (keyCode 229 would otherwise send individual jamo viasetTimeout)Types.ts/TestUtils.test.ts:wkImeComposingtoICompositionHelperinterface and mockHow it works
insertText "ㅎ"ㅎsent to PTYinsertReplacementText "하"하, preview updatedinsertReplacementText "한"한, preview updatedinsertText "..."한flushed to PTY, new buffer startedTesting
Tested with Korean (Hangul) IME in:
This fix is scoped to
insertReplacementTexthandling and Hangul detection, so it should not affect existing composition flows on Chrome/Firefox where standard composition events are fired.Fixes input for Korean IME users on Safari/WKWebView-based terminal applications.