Skip to content

fix(macos): NSTextInputClient IME commit flow ( on master branch) - #4651

Open
gzm55 wants to merge 1 commit into
rust-windowing:masterfrom
gzm55:fix/macos-ime-insertText-vnext
Open

fix(macos): NSTextInputClient IME commit flow ( on master branch)#4651
gzm55 wants to merge 1 commit into
rust-windowing:masterfrom
gzm55:fix/macos-ime-insertText-vnext

Conversation

@gzm55

@gzm55 gzm55 commented Jul 30, 2026

Copy link
Copy Markdown

port #4650 to master.

Fixes #3925 — macOS insertText:replacementRange: incorrectly discards committed text when the IME calls unmarkText before insertText, and when the IME requires a non-empty validAttributesForMarkedText to enter composition.

Three targeted fixes in src/platform_impl/macos/view.rs:

1. validAttributesForMarkedText returns standard attributes

Some IMEs (e.g. 落格输入法 / LogInputMac3) require a non-empty return to enter composition mode. Apple's docs specify at minimum NSUnderlineStyleAttributeName and NSMarkedClauseSegmentAttributeName.

2. insertText: decouples marked-text clearing from commit

The old code required hasMarkedText() == true to commit, but some IMEs call unmarkText before insertText (clearing the marked text), which silently discarded all committed text. Apple's documentation for insertText:replacementRange: states that the provided string should be inserted regardless of whether there is marked text.

Commit is now gated on pending_commit && ime_enabled instead of has_marked && ime_enabled.

3. pending_commit flag distinguishes composition commits from regular typing

Simply removing the hasMarkedText check (as attempted in #4576) causes all insertText calls — including spaces and English characters during IME mode — to go through Ime::Commit. This loses KeyboardInput events and causes downstream visual artifacts (e.g. bracketed paste highlighting in Alacritty).

The pending_commit flag is set to true in setMarkedText: (only during actual composition) and checked + cleared in insertText:. This ensures:

Scenario pending_commit Path used
Composition → commit (any IME) true Ime::Commit
Space / English during IME mode false KeyboardInput
Punctuation without preedit false KeyboardInput (see notes)

Related PRs

Why pending_commit is necessary

kchibisov noted that removing the condition would lose KeyboardInput, and checking for ASCII is wrong since Russian layout shouldn't go through IME. The pending_commit flag ensures that only keystrokes that actually initiated a composition session result in Ime::Commit — everything else preserves the existing KeyboardInput path.

This matches how Kitty's IME handling works: query IME first, then decide whether the key was consumed by composition or should be forwarded as a key event.

Tested

IME Composition commit Punctuation English during IME Regression
落格输入法 (LogInputMac3)
搜狗拼音 (Sogou) No regression
Apple Pinyin No regression

Three fixes for NSTextInputClient protocol implementation:

1. validAttributesForMarkedText now returns standard attributes
   (NSUnderlineStyle, NSMarkedClauseSegment) instead of an empty
   array. Some IMEs (e.g. LogInputMac3) require non-empty return to
   enter composition mode.

2. insertText:replacementRange: no longer gates commit on
   hasMarkedText(). Some IMEs call unmarkText before insertText,
   which clears the marked text and caused all commits to be
   silently discarded.

3. Added pending_commit flag to distinguish genuine composition
   commits from regular typing during IME mode (spaces, English
   chars), which should go through keyboard input.
@gzm55
gzm55 requested a review from madsmtm as a code owner July 30, 2026 16:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

incorrectly handle insertText (macOS)

1 participant