Skip to content

CJK (Korean/Chinese/Japanese) character rendering and IME input support #3

Description

@BikiBikiBik

Summary

cmux-windows does not properly handle CJK (Chinese, Japanese, Korean) characters. There are two distinct issues:

1. Display: CJK characters rendered incorrectly (character width)

CJK characters occupy 2 terminal cells, but TerminalCell.Width is always set to 1 in WriteChar() and SetChar(). This causes overlapping and garbled output for all CJK text.

Root cause: No Unicode East Asian Width (UAX #11) implementation.

Affected files:

  • TerminalBuffer.cs: WriteChar() and SetChar() hardcode Width = 1
  • TerminalControl.cs: Rendering assumes x = col * _cellWidth without width compensation
  • FlushTextRun(): runWidth = _textRunBuffer.Length * _cellWidth (assumes 1 cell per char)
  • Mouse position, selection, URL detection all assume uniform 1-cell width

Fix needed: Implement wcwidth() equivalent, set Width = 2 for wide characters, mark next cell as continuation (Width = 0), and adjust rendering/mouse/selection accordingly.

2. Input: Korean IME composition fails — jamo appear decomposed

When typing Korean, individual jamo (ㅋ, ㅡ, ㄹ) appear instead of composed syllables (클). The final consonant (batchim) consistently separates: "전" appears as "저" + "ㄴ".

Root cause: TerminalControl extends FrameworkElement, which lacks TSF (Text Services Framework) integration. Without TSF, the Windows IME cannot maintain composition state — it falls back to committing each consonant+vowel pair immediately without waiting for a possible final consonant.

Approaches tried (all insufficient):

  • Key.ImeProcessed check in OnKeyDown — partial improvement
  • InputMethod.SetIsInputMethodEnabled — no effect
  • Win32 IMM32 API hooks (ImmGetContext, WM_IME_COMPOSITION) — WPF uses TSF, not IMM32
  • Hidden TextBox as IME proxy with TextChanged — fires during composition, not just on commit
  • Hidden TextBox with TextCompositionManager.TextInput — focus routing breaks

Fix needed: Either rebase TerminalControl on a control with TSF support (e.g., wrap a TextBox), or implement custom TSF integration for proper IME composition handling.

Environment

  • Windows 11 Pro
  • cmux-windows v1.0.6
  • Korean (두벌식) keyboard layout
  • .NET 10 SDK

Screenshots

Korean output garbled (before any fix):

  • Characters overlap and mix due to width=1 for all characters

Korean input decomposed:

  • Typing "클로드코드" produces "클르ㄴㄷ—ㅋㄴㄷ" (batchim separated)

Related

This is a common challenge for Windows terminal emulators. References:

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