Skip to content

Fix iOS word selection for CJK text - #3377

Open
Kyle (Kyle-Ye) wants to merge 1 commit into
JetBrains:jb-mainfrom
Kyle-Ye:codex/cmp-10706-cjk-word-selection
Open

Fix iOS word selection for CJK text#3377
Kyle (Kyle-Ye) wants to merge 1 commit into
JetBrains:jb-mainfrom
Kyle-Ye:codex/cmp-10706-cjk-word-selection

Conversation

@Kyle-Ye

Copy link
Copy Markdown

Summary

On iOS, double-tap word selection uses Compose's layout word boundary, which can treat each
CJK ideograph as a separate word. This differs from UIKit's linguistic word selection.

This change:

  • adds an iOS word-selection adjustment backed by NLTokenizer
  • uses it for both legacy and state-based text fields
  • falls back to TextLayoutResult.getWordBoundary when the platform tokenizer returns no word,
    preserving the existing behavior for whitespace and unsupported text
  • preserves the existing selection behavior on other Skiko platforms

Fixes https://youtrack.jetbrains.com/issue/CMP-10706

Platform scope

The common source-set change only widens the visibility of the existing BoundaryFunction and
adjustToBoundaries helpers from private to internal, allowing the iOS source set to reuse the
established boundary-adjustment logic.

No common selection semantics are changed. The NLTokenizer-backed adjustment is injected and
consumed only by the iOS text-field paths. Other Skiko platforms continue using the existing
SelectionAdjustment.Word behavior.

Design rationale

An alternative would be to change TextLayoutResult.getWordBoundary so that it returns
NLTokenizer boundaries on iOS. This was intentionally not chosen because
TextLayoutResult.getWordBoundary is a public text-layout API whose contract is based on Unicode
word boundaries. It is also used by behavior beyond repeated-tap TextField selection, including
general text selection, word navigation and deletion, selection containers, and native text-input
integration.

Changing that API would therefore alter word-boundary semantics across a substantially broader
surface. It would also require introducing a platform-specific boundary provider below the shared
non-Android Skiko paragraph implementation. This change instead keeps the existing layout boundary
contract intact and applies UIKit-compatible linguistic tokenization only to the iOS TextField
interaction that requires it.

Testing

  • Added iOS tests covering Chinese and Japanese linguistic word boundaries.
  • Added coverage for UTF-16 offsets following an emoji.
  • Verified that Latin word selection remains unchanged.
  • Verified that whitespace falls back to the layout word boundary.
  • Compared the results with native UIKit word selection.
  • Manually verified the standalone Example on an iPhone 14 simulator running iOS 26.0.

AI assistance disclosure

This contribution was developed with AI assistance. The implementation, tests, and behavior were
reviewed, corrected, and validated by the author.

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.

1 participant