Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[CP] Fix crash with CJK keyboard with emoji at end of text field (#42540) #42945

Merged
merged 1 commit into from
Jun 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down