8000 Korean IME (한글) input issues on Windows 11 · Issue #1 · amirlehmam/wmux · GitHub
[go: up one dir, main page]

Skip to content

Korean IME (한글) input issues on Windows 11 #1

Closed

Description

@babyfings

Environment

  • wmux version: 0.6.1
  • OS: Windows 11 Pro (10.0.26200)
  • IME: Windows default Korean IME (Microsoft 입력기)
  • Previously tried third-party Korean IME — same issue

Description

Korean (Hangul) composition input is unreliable. Characters sometimes get dropped, duplicated, or composed incorrectly during typing.

Root Cause Analysis

After inspecting the source (app.asar), wmux has no Korean-specific IME handling. It relies entirely on xterm.js (v5.5.0) CompositionHelper.

Potential issues found:

  1. _finalizeComposition() uses setTimeout(0) which may cause race conditions during Hangul composition
  2. conpty PTY layer may have character encoding issues with multi-byte Korean characters
  3. Electron's textarea composition events may not sync properly with Windows 11 IME

Steps to Reproduce

  1. Open wmux terminal on Windows 11
  2. Switch to Korean IME
  3. Type Korean characters — observe irregular composition behavior

Expected

Smooth Korean character composition, same as Windows Terminal or VS Code integrated terminal.

Activity

  1. amirlehmam c 8000 ommented on Apr 10, 2026

    @amirlehmam
    Owner

    Thanks for the excellent bug report — your root-cause analysis was spot on. Fixed in v0.6.3 (commit 5292107).

    Root cause

    Your point #1 was the actual bug. In CompositionHelper._finalizeComposition() (xterm.js 5.5, src/browser/input/CompositionHelper.ts), the compositionend path defers reading the textarea via setTimeout(0):

    this._isSendingComposition = true;
    setTimeout(() => {
      if (this._isSendingComposition) {
        // ... reads this._textarea.value.substring(currentCompositionPosition.start, ...)
        this._coreService.triggerDataEvent(input, true);
      }
    }, 0);

    With fast Hangul typing, a new compositionstart can fire before the deferred reader runs, which shifts _isComposing / _compositionPosition so the substring that finally reaches triggerDataEvent is wrong — manifesting as the dropped / duplicated / incorrectly composed characters you saw. xterm's own inline comment on that block literally names Korean as the counter-example:

    The last compositionupdate event's data property does not always accurately describe the character, a counter example being Korean where an ending consonant can move to the following character if the following input is a vowel.

    Your points #2 and #3 were the right things to check but weren't the primary cause — Chromium 130 (Electron 33) populates the textarea synchronously before compositionend fires, and node-pty write() is a clean UTF-8 passthrough to conpty.

    Fix

    src/renderer/hooks/useTerminal.ts — after terminal.open(), patch the _compositionHelper instance to replace _finalizeComposition with a synchronous implementation:

    const xtermCore: any = (terminal as any)._core;
    const compositionHelper: any = xtermCore?._compositionHelper;
    if (compositionHelper && xtermCore?.textarea) {
      compositionHelper._finalizeComposition = function (_wait: boolean): void {
        if (this._compositionView) {
          this._compositionView.classList.remove('active');
          this._compositionView.textContent = '';
        }
        this._isComposing = false;
        this._isSendingComposition = false;
        const start: number = this._compositionPosition?.start ?? 0;
        const ta: HTMLTextAreaElement = this._textarea;
        const value = ta.value;
        const input = value.substring(start);
        if (input.length > 0 && this._coreService) {
          this._coreService.triggerDataEvent(input, true);
        }
        ta.value = value.substring(0, start);
        this._compositionPosition = { start: 0, end: 0 };
        this._dataAlreadySent = '';
      };
    }

    Key properties:

    • No setTimeout → no race with a subsequent compositionstart.
    • Reads the textarea at event time (reliable in Chromium 130+).
    • Replaces the method on both call paths — compositionend and the sync finalize from CompositionHelper.keydown when a non-composition key (Enter, arrow keys) is pressed mid-composition.
    • Clears only the consumed portion of the textarea so the trailing input event (inputType: 'insertCompositionText') can't double-consume it.
    • Still routes through _coreService.triggerDataEvent(), so it integrates with xterm's normal onData → pty.write() pipeline.

    Bonus fix (belt and suspenders)

    Even with the composition race fixed, if conpty is running in a non-UTF-8 code page, Korean bytes can still get mangled between the renderer and the shell. So I also set UTF-8 I/O encoding in the shell integration scripts:

    src/shell-integration/wmux-powershell-integration.ps1:

    [Console]::InputEncoding = [System.Text.UTF8Encoding]::new()
    [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
    $OutputEncoding = [System.Text.UTF8Encoding]::new()

    src/shell-integration/wmux-cmd-integration.cmd:

    chcp 65001 >/dev/null 2>&1

    How to get the fix

    1. Download wmux-0.6.3-win-x64.zip
    2. Important — right-click the zip → Properties → Unblock (or powershell "Get-ChildItem -Recurse | Unblock-File" after extracting) to strip the Mark of the Web, otherwise SmartScreen will be unhappy
    3. Extract and run wmux.exe

    Please reopen this issue if you still see any composition weirdness after the update — especially with 종성 → 초성 migration (e.g. typing 간 + ㅏ which should re-compose to 가나). That edge case is the exact scenario the xterm code comment was worried about, and it's the one I'd most like independent confirmation on. 🙏

    감사합니다!

  2. babyfings commented on Apr 10, 2026

    @babyfings
    Author

    Thank you so much for the incredibly thorough and prompt fix! 🙏

    Your detailed root-cause analysis and the synchronous _finalizeComposition patch are truly impressive. The fact that you not only addressed the core setTimeout(0) race condition but also added the UTF-8 encoding fix as a belt-and-suspenders measure shows real attention to detail.

    I've updated to v0.6.3 and Korean input is now working flawlessly — including the 종성 → 초성 migration case (e.g., 간 + ㅏ → 가나) that you mentioned. No more dropped or duplicated characters.

    As a Korean user, having reliable Hangul input is absolutely essential, and this fix makes wmux a joy to use. Thank you for caring about international input support and for the incredibly fast turnaround.

    정말 감사합니다! 🎉

  3. added 2 commits that reference this issue on Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0