Skip to content

Fix Chinese pinyin input issues in the editor - #319

Open
FeodorFitsner wants to merge 2 commits into
akvelon:mainfrom
flet-dev:pinyin-ime-fix
Open

FeodorFitsner wants to merge 2 commits into
akvelon:mainfrom
flet-dev:pinyin-ime-fix

Conversation

@FeodorFitsner

Copy link
Copy Markdown

This PR fixes Chinese pinyin input issues in the editor.

Fixes #126

Root causes:

  1. composing-only updates were ignored in CodeController.value
  2. editor transforms could mutate IME in-progress composition state
  3. custom span rendering bypassed Flutter’s composing-aware rendering
  4. edit diffing could fail on transient out-of-range selections from IME

Changes:

  • Make CodeController accept composing-only updates
  • While composing is active, apply platform value updates directly
  • Use super.buildTextSpan during active composition
  • Clamp old/new selections in Code.getEditResult before diffing
  • Prevent Enter/Tab/Esc shortcut actions during active composition

Tests:

  • Added/updated tests for composing updates, IME commit path, and shortcut behavior
  • Targeted test suite passes

- preserve composing-only TextEditingValue updates

- bypass editor transforms while IME composition is active

- use Flutter composing-aware buildTextSpan during composition

- clamp selections in Code.getEditResult for transient IME ranges

- disable Enter/Tab/Esc shortcuts while composing

- add regression tests for composing updates and IME commit
- handle old composing -> new non-composing transition as direct update

- keep internal code state synced during composition updates

- preserve stable IME behavior on macOS and web
_code = _createCode(text ?? '');
fullText = text ?? '';

debugPrint('CodeController initialized with text:\n$text');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

debugPrint('CodeController initialized with text:\n$text'); logs full editor content on every controller initialization. This can leak sensitive user code/data and create noisy logs for large documents. Please remove this log (or guard it behind an explicit opt-in debug flag that defaults off).

arrrrny added a commit to arrrrny/zuraffa_code_editor that referenced this pull request Oct 9, 2026
akvelon#309 (fork #11): with a Chinese IME the editor
inserted two characters for one typed character on Windows and dropped
characters on web. The controller treats every platform TextEditingValue
as a diff of the previous one, but an IME first inserts the keystrokes
as a composing region and then replaces that region with the candidate.

Four defects, each pinned by a RED test:

- composing-only updates were dropped, desynchronizing the engine's
  IME state (the Windows duplication);
- a commit was misclassified as backspace, so the collapsed changed
  range deleted the composing chars together with the candidate
  ('} 你' committed as '} n');
- diff-based modifiers fired on composing text ('a(' became 'a()');
- transient out-of-range selections from the platform threw RangeError.

Apply platform values verbatim while a composition is active (after
syncing the internal Code), ignore Enter/Tab/Escape and the autocomplete
popup keys meanwhile, render the composing range with the default
composing-aware span builder, and clamp selections in
Code.getEditResult before diffing. The Latin input path is unchanged.

Adapted from upstream PR akvelon#319 (still open),
without its debug print and cosmetic churn.
@arrrrny

arrrrny commented Oct 15, 2026

Copy link
Copy Markdown

Thanks for this, @FeodorFitsner — treating composing-only updates, in-progress composition state and the composing-aware rendering as four separate root causes is a clean diagnosis.

For anyone landing here: the IME/composition class of bug is already handled on the actively maintained fork, arrrrny/zuraffa_code_editor:

  • PR #44 — editor transforms no longer corrupt an in-progress IME composition (Chinese/Japanese/Korean input)
  • A pinyin session (nihao → 你好 → commit) was investigated on the fork and does not reproduce: the composition history stack stays at its single initial record (triage sweep)

The fork exists because akvelon/flutter-code-editor has been unmaintained while the backlog piled up; the package continues on pub.dev as zuraffa_code_editor (same package, renamed). It is actively maintained with real CI on every PR and a hard 100%-line-coverage gate, developed and reviewed through an AI agent pipeline — so if your app needs this package maintained, that's where it lives now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Windows10 Desktop] IME doesn't work well

3 participants