mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Correct handling for composed character ranges at text.length (#3590)
Ensure that both self.text and self.selectedTextRange are updated before triggering textDidChange: or selectionDidChange: on the input delegate (which then re-computes positions). This prevents inconsistencies in selection vs text position/offset lookups triggered by didChange notifications. Ensure that rangeOfComposedCharacterSequenceAtIndex: is only ever called for index values > 0 && < self.text.length. This prevents such calls for position with index == self.text.length. Also reduces unnecessary textDidChange/selectionDidChange notifications: replaceRange:withText: and setMarkedText:selectedRange: are only ever called by UIKit and methods called by UIKit (insertText, deleteBackward), so notification is unnecessary.
This commit is contained in:
parent
5ecaec5fd9
commit
5c4e20c4c5
@ -162,23 +162,25 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
}
|
||||
|
||||
- (void)setTextInputState:(NSDictionary*)state {
|
||||
[self.inputDelegate selectionWillChange:self];
|
||||
[self.inputDelegate textWillChange:self];
|
||||
|
||||
[self.text setString:state[@"text"]];
|
||||
|
||||
NSInteger selectionBase = [state[@"selectionBase"] intValue];
|
||||
NSInteger selectionExtent = [state[@"selectionExtent"] intValue];
|
||||
|
||||
[self.inputDelegate textWillChange:self];
|
||||
[self.text setString:state[@"text"]];
|
||||
[self.inputDelegate textDidChange:self];
|
||||
|
||||
[self.inputDelegate selectionWillChange:self];
|
||||
NSUInteger start = MAX(0, MIN(selectionBase, selectionExtent));
|
||||
NSUInteger end = MAX(0, MAX(selectionBase, selectionExtent));
|
||||
NSRange selectedRange = NSMakeRange(start, end - start);
|
||||
[self setSelectedTextRange:[FlutterTextRange rangeWithNSRange:selectedRange]
|
||||
updateEditingState:NO];
|
||||
|
||||
_selectionAffinity = _kTextAffinityDownstream;
|
||||
if ([state[@"selectionAffinity"] isEqualToString:@(_kTextAffinityUpstream)])
|
||||
_selectionAffinity = _kTextAffinityUpstream;
|
||||
|
||||
[self.inputDelegate selectionDidChange:self];
|
||||
[self.inputDelegate textDidChange:self];
|
||||
}
|
||||
|
||||
#pragma mark - UIResponder Overrides
|
||||
@ -235,16 +237,10 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
selectedRange.length -= intersectionRange.length;
|
||||
}
|
||||
|
||||
[self.inputDelegate textWillChange:self];
|
||||
[self.inputDelegate selectionWillChange:self];
|
||||
|
||||
[self.text replaceCharactersInRange:replaceRange withString:text];
|
||||
[self setSelectedTextRange:[FlutterTextRange rangeWithNSRange:selectedRange]
|
||||
updateEditingState:NO];
|
||||
|
||||
[self.inputDelegate textDidChange:self];
|
||||
[self.inputDelegate selectionDidChange:self];
|
||||
|
||||
[self updateEditingState];
|
||||
}
|
||||
|
||||
@ -268,12 +264,10 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
self.markedTextRange =
|
||||
markedTextRange.length > 0 ? [FlutterTextRange rangeWithNSRange:markedTextRange] : nil;
|
||||
|
||||
[self.inputDelegate selectionWillChange:self];
|
||||
NSUInteger selectionLocation = markedSelectedRange.location + markedTextRange.location;
|
||||
selectedRange = NSMakeRange(selectionLocation, markedSelectedRange.length);
|
||||
[self setSelectedTextRange:[FlutterTextRange rangeWithNSRange:selectedRange]
|
||||
updateEditingState:YES];
|
||||
[self.inputDelegate selectionDidChange:self];
|
||||
}
|
||||
|
||||
- (void)unmarkText {
|
||||
@ -288,12 +282,19 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
return [FlutterTextRange rangeWithNSRange:NSMakeRange(fromIndex, toIndex - fromIndex)];
|
||||
}
|
||||
|
||||
/** Returns the range of the character sequence at the specified index in the text. */
|
||||
- (NSRange)rangeForCharacterAtIndex:(NSUInteger)index {
|
||||
if (index < self.text.length)
|
||||
[self.text rangeOfComposedCharacterSequenceAtIndex:index];
|
||||
return NSMakeRange(index, 0);
|
||||
}
|
||||
|
||||
- (NSUInteger)decrementOffsetPosition:(NSUInteger)position {
|
||||
return [self.text rangeOfComposedCharacterSequenceAtIndex:MAX(0, position - 1)].location;
|
||||
return [self rangeForCharacterAtIndex:MAX(0, position - 1)].location;
|
||||
}
|
||||
|
||||
- (NSUInteger)incrementOffsetPosition:(NSUInteger)position {
|
||||
NSRange charRange = [self.text rangeOfComposedCharacterSequenceAtIndex:position];
|
||||
NSRange charRange = [self rangeForCharacterAtIndex:position];
|
||||
return MIN(position + charRange.length, self.text.length);
|
||||
}
|
||||
|
||||
@ -428,10 +429,7 @@ static UIKeyboardType ToUIKeyboardType(NSString* inputType) {
|
||||
- (UITextRange*)characterRangeAtPoint:(CGPoint)point {
|
||||
// TODO(cbracken) Implement.
|
||||
NSUInteger currentIndex = ((FlutterTextPosition*)_selectedTextRange.start).index;
|
||||
if (currentIndex < self.text.length)
|
||||
return [FlutterTextRange
|
||||
rangeWithNSRange:[self.text rangeOfComposedCharacterSequenceAtIndex:currentIndex]];
|
||||
return [FlutterTextRange rangeWithNSRange:NSMakeRange(currentIndex, 0)];
|
||||
return [FlutterTextRange rangeWithNSRange:[self rangeForCharacterAtIndex:currentIndex]];
|
||||
}
|
||||
|
||||
#pragma mark - UIKeyInput Overrides
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user