diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm index 4f92e456e5fad..4af9ac6ec835b 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm @@ -1658,25 +1658,6 @@ - (CGRect)firstRectForRange:(UITextRange*)range { return CGRectZero; } -- (BOOL)isRTLAtPosition:(NSUInteger)position { - // _selectionRects is sorted by position already. - // We can use binary search. - NSInteger min = 0; - NSInteger max = [_selectionRects count]; - while (min <= max) { - const NSUInteger mid = min + (max - min) / 2; - FlutterTextSelectionRect* rect = _selectionRects[mid]; - if (rect.position > position) { - max = mid - 1; - } else if (rect.position == position) { - return rect.isRTL; - } else { - min = mid + 1; - } - } - return NO; -} - - (CGRect)caretRectForPosition:(UITextPosition*)position { NSInteger index = ((FlutterTextPosition*)position).index; UITextStorageDirection affinity = ((FlutterTextPosition*)position).affinity; @@ -1699,7 +1680,8 @@ - (CGRect)caretRectForPosition:(UITextPosition*)position { CGRect characterAfterCaret = rects[0].rect; // Return a zero-width rectangle along the upstream edge of the character after the caret // position. - if ([self isRTLAtPosition:index]) { + if ([rects[0] isKindOfClass:[FlutterTextSelectionRect class]] && + ((FlutterTextSelectionRect*)rects[0]).isRTL) { return CGRectMake(characterAfterCaret.origin.x + characterAfterCaret.size.width, characterAfterCaret.origin.y, 0, characterAfterCaret.size.height); } else { @@ -1712,7 +1694,8 @@ - (CGRect)caretRectForPosition:(UITextPosition*)position { CGRect characterAfterCaret = rects[1].rect; // Return a zero-width rectangle along the upstream edge of the character after the caret // position. - if ([self isRTLAtPosition:index]) { + if ([rects[1] isKindOfClass:[FlutterTextSelectionRect class]] && + ((FlutterTextSelectionRect*)rects[1]).isRTL) { return CGRectMake(characterAfterCaret.origin.x + characterAfterCaret.size.width, characterAfterCaret.origin.y, 0, characterAfterCaret.size.height); } else { @@ -1727,7 +1710,8 @@ - (CGRect)caretRectForPosition:(UITextPosition*)position { // For both cases, return a zero-width rectangle along the downstream edge of the character // before the caret position. CGRect characterBeforeCaret = rects[0].rect; - if ([self isRTLAtPosition:index - 1]) { + if ([rects[0] isKindOfClass:[FlutterTextSelectionRect class]] && + ((FlutterTextSelectionRect*)rects[0]).isRTL) { return CGRectMake(characterBeforeCaret.origin.x, characterBeforeCaret.origin.y, 0, characterBeforeCaret.size.height); } else { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm index 04452ed9c3246..b1ee7274f36fe 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm @@ -1535,6 +1535,29 @@ - (void)testClosestPositionToPointWithinRange { ((FlutterTextPosition*)[inputView closestPositionToPoint:point withinRange:range]).affinity); } +- (void)testClosestPositionToPointWithPartialSelectionRects { + FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin]; + [inputView setTextInputState:@{@"text" : @"COMPOSING"}]; + + [inputView setSelectionRects:@[ [FlutterTextSelectionRect + selectionRectWithRect:CGRectMake(0, 0, 100, 100) + position:0U] ]]; + // Asking with a position at the end of selection rects should give you the trailing edge of + // the last rect. + XCTAssertTrue(CGRectEqualToRect( + [inputView caretRectForPosition:[FlutterTextPosition + positionWithIndex:1 + affinity:UITextStorageDirectionForward]], + CGRectMake(100, 0, 0, 100))); + // Asking with a position beyond the end of selection rects should return CGRectZero without + // crashing. + XCTAssertTrue(CGRectEqualToRect( + [inputView caretRectForPosition:[FlutterTextPosition + positionWithIndex:2 + affinity:UITextStorageDirectionForward]], + CGRectZero)); +} + #pragma mark - Floating Cursor - Tests - (void)testFloatingCursorDoesNotThrow {