Skip to content

[macOS] IME preedit lost on focus change - #21601

Merged
Gillibald merged 5 commits into
AvaloniaUI:mainfrom
hyunq21:fix/macos-ime-preedit-lost-on-focus-change
Jul 28, 2026
Merged

[macOS] IME preedit lost on focus change#21601
Gillibald merged 5 commits into
AvaloniaUI:mainfrom
hyunq21:fix/macos-ime-preedit-lost-on-focus-change

Conversation

@hyunq21

@hyunq21 hyunq21 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

What does the pull request do?

Fixes two related macOS Korean IME issues where in-progress composition
(preedit) text was lost when focus moved away from a TextBox while
composing — e.g. while typing Korean and then clicking another control or
switching focus between text boxes.

What is the current behavior?

On macOS, when a Korean IME composition is active (marked/preedit text is
shown) and the user moves focus away — by clicking another control or
focusing a different TextBox — the composing text is silently discarded
instead of being committed. The half-composed characters are lost.

This happens because:

  • AvnTextInputMethod::Reset() was an empty no-op, so the native input
    context was never told to finalize/clear its marked text when the
    Avalonia input client changed.
  • A mouse press during an active composition was not forwarded to the
    NSTextInputContext, so the IME never got the chance to commit the
    composition before the click was handled.

What is the updated/expected behavior with this PR?

The active composition is committed (not dropped) when focus changes:

  • Clicking another control while composing commits the current preedit.
  • Switching focus between text boxes commits the preedit and clears the
    stale composition state.

To test:

  1. Run on macOS with the Korean IME (2-Set Hangul).
  2. Start composing text in a TextBox (leave it mid-composition, with the
    underlined preedit visible).
  3. Click another control / another TextBox.
  4. The composed text is now committed into the original TextBox instead
    of being lost.

How was the solution implemented (if it's not obvious)?

  • AvnView: on a mouse button-down while hasMarkedText is true, forward
    the event to [self inputContext] handleEvent: so the IME commits the
    in-progress composition before the click is processed.
  • AvnTextInputMethod::Reset() now calls a new resetInputMethod delegate
    method on the view, which clears the preedit on the Avalonia client,
    resets the marked range, and calls discardMarkedText on the input
    context so no stale composition state leaks across focus changes.
  • Added the resetInputMethod declaration to AvnTextInputMethodDelegate.

Checklist

Breaking changes

None.

Obsoletions / Deprecations

None.

Fixed issues

Fixes #19964
Fixes #15183

@hyunq21

hyunq21 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author
2026-06-17.3.42.19.mov

@cla-avalonia

cla-avalonia commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator
  • All contributors have signed the CLA.

@hyunq21

hyunq21 commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@cla-avalonia agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes macOS Korean IME composition (preedit) loss/misplacement when focus changes by ensuring the native NSTextInputContext gets a chance to commit an active composition on mouse-down, and by explicitly resetting native/managed preedit state on input-client changes.

Changes:

  • Forward mouse button-down events to NSTextInputContext when there is active marked text so the IME can commit before Avalonia processes the click.
  • Implement AvnTextInputMethod::Reset() to invoke a new delegate hook that clears preedit/marked state and discards marked text in the native input context.
  • Extend AvnTextInputMethodDelegate with resetInputMethod and implement it on AvnView.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
native/Avalonia.Native/src/OSX/AvnView.mm Forwards mouse-down to the input context during composition and adds a reset hook to clear marked/preedit state.
native/Avalonia.Native/src/OSX/AvnTextInputMethodDelegate.h Extends the delegate protocol with resetInputMethod used during client resets.
native/Avalonia.Native/src/OSX/AvnTextInputMethod.mm Implements Reset() to call the delegate and trigger native IME state cleanup on focus/client changes.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066569-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul MrJul added bug os-macos backport-candidate-12.0.x Consider this PR for backporting to 12.0 branch labels Jun 17, 2026
@hyunq21

hyunq21 commented Jun 21, 2026

Copy link
Copy Markdown
Contributor Author

#19636 also appears to be the same issue

@Gillibald Gillibald left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@hyunq21

hyunq21 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor Author

I missed something. Korean preedit is always a single character, but Japanese and Chinese preedit can span multiple characters, so we must not commit the preedit when the user clicks inside it. We should only commit it when a point outside the preedit is clicked.

@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.1.999-cibuild0066850-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@Gillibald

Copy link
Copy Markdown
Contributor

We do not need to fix this as part of this PR. I have a dedicated PR for a more complete NSTextInputContext implementation that covers this as well. That PR is based on this PR.

@MrJul MrJul added backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch and removed backport-candidate-12.0.x Consider this PR for backporting to 12.0 branch labels Jul 9, 2026
@MrJul
MrJul enabled auto-merge July 28, 2026 12:21
@avaloniaui-bot

Copy link
Copy Markdown

You can test this PR using the following package version. 12.2.999-cibuild0067857-alpha. (feed url: https://nuget-feed-all.avaloniaui.net/v3/index.json) [PRBUILDID]

@MrJul
MrJul added this pull request to the merge queue Jul 28, 2026
Gillibald added a commit to Gillibald/Avalonia that referenced this pull request Jul 28, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 28, 2026
@Gillibald
Gillibald added this pull request to the merge queue Jul 28, 2026
Merged via the queue into AvaloniaUI:main with commit dbb8af9 Jul 28, 2026
10 checks passed
Gillibald added a commit to Gillibald/Avalonia that referenced this pull request Jul 29, 2026
MrJul added a commit that referenced this pull request Jul 29, 2026
* fix(macOS): commit IME preedit when switching focus between textboxes

Fixes #19964

* remove comment

---------

Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
@MrJul MrJul added backported-12.1.x and removed backport-candidate-12.1.x Consider this PR for backporting to 12.1 branch labels Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Mac OS] IME Preedit text is lost or misplaced when switching focus between textboxes Changing focus removes "incomplete" Korean character on Mac.

6 participants