Skip to content

Commit cbc3ae0

Browse files
authored
Fixes navigation between word boundaries (#348)
1 parent b8f5546 commit cbc3ae0

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

Sources/Runestone/TextView/Core/TextInputStringTokenizer.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import UIKit
33
final class TextInputStringTokenizer: UITextInputStringTokenizer {
44
var lineManager: LineManager
55
var stringView: StringView
6+
// Used to ensure we can workaround bug where multi-stage input, like when entering Korean text
7+
// does not work properly. If we do not treat navigation between word boundies as a special case then
8+
// navigating with Shift + Option + Arrow Keys followed by Shift + Arrow Keys will not work correctly.
9+
var didCallPositionFromPositionToWordBoundary = false
610

711
private let lineControllerStorage: LineControllerStorage
812
private var newlineCharacters: [Character] {
@@ -206,6 +210,7 @@ private extension TextInputStringTokenizer {
206210
guard let indexedPosition = position as? IndexedPosition else {
207211
return nil
208212
}
213+
didCallPositionFromPositionToWordBoundary = true
209214
let location = indexedPosition.index
210215
let alphanumerics = CharacterSet.alphanumerics
211216
if direction.isForward {

Sources/Runestone/TextView/Core/TextInputView.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ final class TextInputView: UIView, UITextInput {
4747
shouldNotifyInputDelegate = true
4848
didCallPositionFromPositionInDirectionWithOffset = false
4949
}
50+
// This is a consequence of our workaround that ensures multi-stage input, such as when entering Korean,
51+
// works correctly. The workaround causes bugs when selecting words using Shift + Option + Arrow Keys
52+
// followed by Shift + Arrow Keys if we do not treat it as a special case.
53+
// The consequence of not having this workaround is that Shift + Arrow Keys may adjust the wrong end of
54+
// the selected text when followed by navigating between word boundaries usign Shift + Option + Arrow Keys.
55+
if customTokenizer.didCallPositionFromPositionToWordBoundary && !didCallDeleteBackward {
56+
shouldNotifyInputDelegate = true
57+
customTokenizer.didCallPositionFromPositionToWordBoundary = false
58+
}
59+
didCallDeleteBackward = false
5060
notifyInputDelegateAboutSelectionChangeInLayoutSubviews = !shouldNotifyInputDelegate
5161
if shouldNotifyInputDelegate {
5262
inputDelegate?.selectionWillChange(self)
@@ -594,6 +604,7 @@ final class TextInputView: UIView, UITextInput {
594604
private var notifyInputDelegateAboutSelectionChangeInLayoutSubviews = false
595605
private var notifyDelegateAboutSelectionChangeInLayoutSubviews = false
596606
private var didCallPositionFromPositionInDirectionWithOffset = false
607+
private var didCallDeleteBackward = false
597608
private var hasDeletedTextWithPendingLayoutSubviews = false
598609
private var preserveUndoStackWhenSettingString = false
599610
private var cancellables: [AnyCancellable] = []
@@ -1116,6 +1127,7 @@ extension TextInputView {
11161127
}
11171128

11181129
func deleteBackward() {
1130+
didCallDeleteBackward = true
11191131
guard let selectedRange = markedRange ?? selectedRange, selectedRange.length > 0 else {
11201132
return
11211133
}

0 commit comments

Comments
 (0)