Skip to content

Fix #35: Fix Korean input composition and marked text handling#44

Open
nova286 wants to merge 3 commits into
masterfrom
fix/issue-35-korean-input
Open

Fix #35: Fix Korean input composition and marked text handling#44
nova286 wants to merge 3 commits into
masterfrom
fix/issue-35-korean-input

Conversation

@nova286

@nova286 nova286 commented May 12, 2026

Copy link
Copy Markdown
Owner

Summary

Fix Korean (Hangul) input not composing jamo into syllables. When typing Korean, individual jamo (ㅇㅏㄴ) now compose into syllables (안).

Root Cause

Three related bugs in BSTextView.swift:

  1. Dual markedTextRange properties: Two separate stored properties existed — the public markedTextRange: UITextRange? (written by setMarkedText) and the private _markedTextRange: TextRange? (never written, always nil). All 12 internal checks read _markedTextRange, so caret clamping, magnifier switching, and selection rendering during composition were all broken.

  2. markedTextStyle was nil: The property was declared but never had a default value and was unused in setMarkedText. Korean IME may check this property; if nil, it falls back to insertText per jamo instead of using setMarkedText for composition.

  3. insertText didn't handle active marked text: If IME commits via insertText while marked text is active, the composition state was left dangling.

Also fixed: Force-unwrap crash in setMarkedText/deleteBackward when _lastTypeRange is nil on first input.

Changes

File Change
BSText/BSTextView.swift Merge dual properties, default markedTextStyle, insertText guard, nil-safety fix
Framework/BSTextTests/BSTextTests.swift 10 unit tests covering Korean/Chinese/Japanese composition
Package.swift Add test target for SPM

Test plan

  • 18/18 tests pass (10 new + 8 existing)
  • Manual test: Korean keyboard input in BSTextView Demo app

Co-Authored-By: Claude Opus 4.7 noreply@anthropic.com

Developer and others added 3 commits May 12, 2026 18:29
- Merge dual markedTextRange properties into single source of truth
  (_markedTextRange was never written, causing all internal marked text
  checks to fail — caret clamping, magnifier switching, selection rendering)
- Set default markedTextStyle background color so IME recognizes marked
  text support and uses setMarkedText instead of insertText per jamo
- Guard insertText to unmark before inserting when marked text is active
- Fix force-unwrap crash in setMarkedText/deleteBackward when
  _lastTypeRange is nil on first input
- Add 10 unit tests covering Korean/Chinese/Japanese composition

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tWindow

- Line 426: mag.snapshot! -> mag.snapshot? with nil coalescing
- Line 477: mag.snapshot! -> mag.snapshot? with optional chaining

Prevents Fatal error: Unexpectedly found nil while unwrapping an Optional value
at TextEffectWindow.swift:477
Root cause: During Korean IME composition, setMarkedText called
_updateOuterProperties() which triggers KVO on attributedText. External
observers may respond by resetting text/attributedText, breaking the
composition state and causing jamo (ㅇㅏㄴ) to land as separate characters
instead of composing into a single syllable (안).

Fix: Skip _updateOuterProperties() in setMarkedText when markedTextRange
is not nil (i.e. during active IME composition). The outer properties
will be synced when unmarkText is called after composition completes.

Also includes:
- Added missing _inputDelegate notifications in unmarkText()
- Skip emoji fix in position(from:offset:) during IME composition
- Fixed tokenizer to use self instead of empty UITextView()

Fixes #35
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