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

[ios]fix ios 16 auto correction highlight showing on top left corner #47279

Merged
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 @@ -1676,6 +1676,16 @@ - (CGRect)firstRectForRange:(UITextRange*)range {
}
}

// The iOS 16 system highlight does not repect the height returned by `firstRectForRange`
// API (unlike iOS 17). So we return CGRectZero to hide it (unless if scribble is enabled).
// To support scribble's advanced gestures (e.g. insert a space with a vertical bar),
// at least 1 character's width is required.
if (@available(iOS 17, *)) {
// No-op
} else if (![self isScribbleAvailable]) {
return CGRectZero;
}

NSUInteger first = start;
if (end < start) {
first = end;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1558,19 +1558,19 @@ - (void)testUpdateFirstRectForRange {
[inputView firstRectForRange:range]));
}

- (void)testFirstRectForRangeReturnsCorrectRectOnASingleLineLeftToRight {
- (void)testFirstRectForRangeReturnsNoneZeroRectWhenScribbleIsEnabled {
FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin];
[inputView setTextInputState:@{@"text" : @"COMPOSING"}];

FlutterTextInputView* mockInputView = OCMPartialMock(inputView);
OCMStub([mockInputView isScribbleAvailable]).andReturn(YES);

[inputView setSelectionRects:@[
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(0, 0, 100, 100) position:0U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(100, 0, 100, 100) position:1U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(200, 0, 100, 100) position:2U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(300, 0, 100, 100) position:3U],
]];
FlutterTextRange* singleRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 1)];
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));

FlutterTextRange* multiRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 3)];

Expand All @@ -1581,6 +1581,34 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnASingleLineLeftToRight {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
}
}

- (void)testFirstRectForRangeReturnsCorrectRectOnASingleLineLeftToRight {
FlutterTextInputView* inputView = [[FlutterTextInputView alloc] initWithOwner:textInputPlugin];
[inputView setTextInputState:@{@"text" : @"COMPOSING"}];

[inputView setSelectionRects:@[
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(0, 0, 100, 100) position:0U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(100, 0, 100, 100) position:1U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(200, 0, 100, 100) position:2U],
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(300, 0, 100, 100) position:3U],
]];
FlutterTextRange* singleRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 1)];
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:singleRectRange]));
}

FlutterTextRange* multiRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 3)];

if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}

[inputView setTextInputState:@{@"text" : @"COM"}];
FlutterTextRange* rangeOutsideBounds = [FlutterTextRange rangeWithNSRange:NSMakeRange(3, 1)];
Expand All @@ -1598,16 +1626,19 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnASingleLineRightToLeft {
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(0, 0, 100, 100) position:3U],
]];
FlutterTextRange* singleRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 1)];
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:singleRectRange]));
}

FlutterTextRange* multiRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 3)];
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(0, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}

[inputView setTextInputState:@{@"text" : @"COM"}];
Expand All @@ -1630,17 +1661,20 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnMultipleLinesLeftToRight {
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(300, 100, 100, 100) position:7U],
]];
FlutterTextRange* singleRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 1)];
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:singleRectRange]));
}

FlutterTextRange* multiRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 4)];

if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1659,16 +1693,19 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnMultipleLinesRightToLeft {
[FlutterTextSelectionRect selectionRectWithRect:CGRectMake(0, 100, 100, 100) position:7U],
]];
FlutterTextRange* singleRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 1)];
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:singleRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:singleRectRange]));
}

FlutterTextRange* multiRectRange = [FlutterTextRange rangeWithNSRange:NSMakeRange(1, 4)];
if (@available(iOS 17, *)) {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(0, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1691,8 +1728,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnSingleLineWithVaryingMinYAndMax
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, -10, 300, 120),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 10, 100, 80),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1715,8 +1751,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectOnSingleLineWithVaryingMinYAndMax
XCTAssertTrue(CGRectEqualToRect(CGRectMake(0, -10, 300, 120),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, -10, 100, 120),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1739,8 +1774,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectWithOverlappingRectsExceedingThre
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1763,8 +1797,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectWithOverlappingRectsExceedingThre
XCTAssertTrue(CGRectEqualToRect(CGRectMake(0, 0, 300, 100),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(200, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1787,8 +1820,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectWithOverlappingRectsWithinThresho
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 400, 140),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(100, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand All @@ -1811,8 +1843,7 @@ - (void)testFirstRectForRangeReturnsCorrectRectWithOverlappingRectsWithinThresho
XCTAssertTrue(CGRectEqualToRect(CGRectMake(0, 0, 400, 140),
[inputView firstRectForRange:multiRectRange]));
} else {
XCTAssertTrue(CGRectEqualToRect(CGRectMake(300, 0, 100, 100),
[inputView firstRectForRange:multiRectRange]));
XCTAssertTrue(CGRectEqualToRect(CGRectZero, [inputView firstRectForRange:multiRectRange]));
}
}

Expand Down