re_editor syncs only the current line to the system IME via _buildTextEditingValue(). On mobile, many third-party keyboards (notably iFlytek / 讯飞输入法) expose document-level actions such as:
- 开头 (go to beginning)
- 末尾 (go to end)
- 全选 (select all)
- 选择 (selection mode) + 开头/末尾 (expand selection to document boundaries)
Because the IME only sees one line, these actions are interpreted at line scope instead of document scope, which diverges from mainstream apps (WeChat, system EditText, etc.).
Additionally, on Android, the zero-width prefix (\u200b) path treats selection.start == 0 as a backward delete, so “go to beginning” can delete the previous character instead of moving the cursor.
Expected behavior
Platforms
- Android and iOS (both use the
usePrefix IME bridge in _CodeInputController)
Cursor mode (no iFlytek “选择”)
| Action |
Expected |
| 开头 |
Move caret to document start |
| 末尾 |
Move caret to document end |
| 全选 |
Select all lines in the editor |
Selection mode (iFlytek “选择” + 开头/末尾)
When the user enters iFlytek’s selection mode and taps 开头/末尾, the IME typically sends a non-collapsed selection update. The editor should expand selection to document boundaries while preserving content (not delete the selection).
Example: double-tap to select word AB (A = anchor start, B = anchor end), then 选择 → 开头/末尾:
- 开头: document start
(0,0) → B
- 末尾: A → document end
- Repeated taps should be idempotent (same result each time)
- After the user drags selection handles to a new range (e.g. AC), the anchor should reset; the next 开头/末尾 uses the new range as the frozen anchor
Direct 开头/末尾 (without 选择) should still mean collapse selection + move caret, not expand.
Why this belongs in re_editor
IME callbacks (updateEditingValueWithDeltas, performPrivateCommand, performSelector, etc.) are handled inside private _CodeInputController. Host apps cannot intercept these before CodeLineEditingController applies edits, so fixes for third-party keyboard semantics need to live in the package.
Suggested approach (for discussion)
- Detect IME navigation intents (selection-only updates, private commands, selectors) before applying line-local
edit() / deleteBackward()
- Map 开头/末尾/全选 to
moveCursorToPageStart / moveCursorToPageEnd / selectAll at document level
- For iFlytek selection mode: freeze an anchor on first expand, apply start/end expansion from that anchor, reset on manual selection change / text edit / focus loss
- Sync a sensible IME editing state during selection sessions (IME currently only sees one line, which breaks follow-up 末尾 actions)
References
re_editorsyncs only the current line to the system IME via_buildTextEditingValue(). On mobile, many third-party keyboards (notably iFlytek / 讯飞输入法) expose document-level actions such as:Because the IME only sees one line, these actions are interpreted at line scope instead of document scope, which diverges from mainstream apps (WeChat, system
EditText, etc.).Additionally, on Android, the zero-width prefix (
\u200b) path treatsselection.start == 0as a backward delete, so “go to beginning” can delete the previous character instead of moving the cursor.Expected behavior
Platforms
usePrefixIME bridge in_CodeInputController)Cursor mode (no iFlytek “选择”)
Selection mode (iFlytek “选择” + 开头/末尾)
When the user enters iFlytek’s selection mode and taps 开头/末尾, the IME typically sends a non-collapsed selection update. The editor should expand selection to document boundaries while preserving content (not delete the selection).
Example: double-tap to select word AB (A = anchor start, B = anchor end), then 选择 → 开头/末尾:
(0,0)→ BDirect 开头/末尾 (without 选择) should still mean collapse selection + move caret, not expand.
Why this belongs in
re_editorIME callbacks (
updateEditingValueWithDeltas,performPrivateCommand,performSelector, etc.) are handled inside private_CodeInputController. Host apps cannot intercept these beforeCodeLineEditingControllerapplies edits, so fixes for third-party keyboard semantics need to live in the package.Suggested approach (for discussion)
edit()/deleteBackward()moveCursorToPageStart/moveCursorToPageEnd/selectAllat document levelReferences
PlatformException)lib/src/_code_input.dart(_CodeInputController,_buildTextEditingValue)