Allow selection in composing region (#140516)

Fixes https://github.com/flutter/flutter/issues/68547 for macOS. Needs https://github.com/flutter/engine/pull/49314
This commit is contained in:
LongCatIsLooong 2024-01-16 15:33:49 -08:00 committed by GitHub
parent 9775877d8a
commit 212d0a64c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 13 deletions

View file

@ -218,9 +218,9 @@ class TextEditingController extends ValueNotifier<TextEditingValue> {
/// actions, not during the build, layout, or paint phases.
///
/// This property can be set from a listener added to this
/// [TextEditingController]; however, one should not also set [selection]
/// [TextEditingController]; **however, one should not also set [selection]
/// in a separate statement. To change both the [text] and the [selection]
/// change the controller's [value].
/// change the controller's [value].**
set text(String newText) {
value = value.copyWith(
text: newText,
@ -285,16 +285,13 @@ class TextEditingController extends ValueNotifier<TextEditingValue> {
/// in a separate statement. To change both the [text] and the [selection]
/// change the controller's [value].
///
/// If the new selection is of non-zero length, or is outside the composing
/// range, the composing range is cleared.
/// If the new selection is outside the composing range, the composing range is
/// cleared.
set selection(TextSelection newSelection) {
if (!isSelectionWithinTextBounds(newSelection)) {
if (!_isSelectionWithinTextBounds(newSelection)) {
throw FlutterError('invalid text selection: $newSelection');
}
final TextRange newComposing =
newSelection.isCollapsed && _isSelectionWithinComposingRange(newSelection)
? value.composing
: TextRange.empty;
final TextRange newComposing = _isSelectionWithinComposingRange(newSelection) ? value.composing : TextRange.empty;
value = value.copyWith(selection: newSelection, composing: newComposing);
}
@ -326,7 +323,7 @@ class TextEditingController extends ValueNotifier<TextEditingValue> {
}
/// Check that the [selection] is inside of the bounds of [text].
bool isSelectionWithinTextBounds(TextSelection selection) {
bool _isSelectionWithinTextBounds(TextSelection selection) {
return selection.start <= text.length && selection.end <= text.length;
}
@ -3650,7 +3647,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
// We return early if the selection is not valid. This can happen when the
// text of [EditableText] is updated at the same time as the selection is
// changed by a gesture event.
if (!widget.controller.isSelectionWithinTextBounds(selection)) {
if (!widget.controller._isSelectionWithinTextBounds(selection)) {
return;
}

View file

@ -11185,14 +11185,15 @@ void main() {
));
expect(state.currentTextEditingValue.composing, const TextRange(start: 4, end: 12));
// Setting a selection within the composing range clears the composing range.
// Setting a selection within the composing range doesn't clear the composing range.
state.updateEditingValue(const TextEditingValue(
text: 'foo composing bar',
selection: TextSelection.collapsed(offset: 4),
composing: TextRange(start: 4, end: 12),
));
controller.selection = const TextSelection(baseOffset: 5, extentOffset: 7);
expect(state.currentTextEditingValue.composing, TextRange.empty);
expect(state.currentTextEditingValue.composing, const TextRange(start: 4, end: 12));
expect(state.currentTextEditingValue.selection, const TextSelection(baseOffset: 5, extentOffset: 7));
// Reset the composing range.
state.updateEditingValue(const TextEditingValue(