Trackpad mode crash fix (#30475)
Fixes a crash that happened when attempting to select text in trackpad mode on iOS.
diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart
index d728cea..3b98b0e 100644
--- a/packages/flutter/lib/src/widgets/editable_text.dart
+++ b/packages/flutter/lib/src/widgets/editable_text.dart
@@ -914,6 +914,10 @@
void updateFloatingCursor(RawFloatingCursorPoint point) {
switch(point.state){
case FloatingCursorDragState.Start:
+ if (_floatingCursorResetController.isAnimating) {
+ _floatingCursorResetController.stop();
+ _onFloatingCursorResetTick();
+ }
final TextPosition currentTextPosition = TextPosition(offset: renderEditable.selection.baseOffset);
_startCaretRect = renderEditable.getLocalRectForCaret(currentTextPosition);
renderEditable.setFloatingCursor(point.state, _startCaretRect.center - _floatingCursorOffset, currentTextPosition);
diff --git a/packages/flutter/test/widgets/editable_text_cursor_test.dart b/packages/flutter/test/widgets/editable_text_cursor_test.dart
index 6e00f92..ba232dd 100644
--- a/packages/flutter/test/widgets/editable_text_cursor_test.dart
+++ b/packages/flutter/test/widgets/editable_text_cursor_test.dart
@@ -476,6 +476,72 @@
expect(controller.selection.baseOffset, 10);
});
+ // Regression test for https://github.com/flutter/flutter/pull/30475.
+ testWidgets('Trying to select with the floating cursor does not crash', (WidgetTester tester) async {
+ const String text = 'hello world this is fun and cool and awesome!';
+ controller.text = text;
+ final FocusNode focusNode = FocusNode();
+
+ await tester.pumpWidget(
+ MediaQuery(
+ data: const MediaQueryData(devicePixelRatio: 1),
+ child: Directionality(
+ textDirection: TextDirection.ltr,
+ child: FocusScope(
+ node: focusScopeNode,
+ autofocus: true,
+ child: EditableText(
+ backgroundCursorColor: Colors.grey,
+ controller: controller,
+ focusNode: focusNode,
+ style: textStyle,
+ cursorColor: cursorColor,
+ ),
+ ),
+ ),
+ ),
+ );
+
+ await tester.tap(find.byType(EditableText));
+ final RenderEditable renderEditable = findRenderEditable(tester);
+ renderEditable.selection = const TextSelection(baseOffset: 29, extentOffset: 29);
+
+ expect(controller.selection.baseOffset, 29);
+
+ final EditableTextState editableTextState = tester.firstState(find.byType(EditableText));
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
+
+ expect(controller.selection.baseOffset, 29);
+
+ // Sets the origin.
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
+ offset: const Offset(20, 20)));
+
+ expect(controller.selection.baseOffset, 29);
+
+ // Moves the cursor right a few characters.
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
+ offset: const Offset(-250, 20)));
+
+ // But we have not yet set the offset because the user is not done placing the cursor.
+ expect(controller.selection.baseOffset, 29);
+
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
+ // Immediately start a new floating cursor, in the same way as happens when
+ // the user tries to select text in trackpad mode.
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Start));
+ await tester.pumpAndSettle();
+
+ // Set and move the second cursor like a selection. Previously, the second
+ // Update here caused a crash.
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
+ offset: const Offset(20, 20)));
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.Update,
+ offset: const Offset(-250, 20)));
+ editableTextState.updateFloatingCursor(RawFloatingCursorPoint(state: FloatingCursorDragState.End));
+ await tester.pumpAndSettle();
+ });
+
testWidgets('autofocus sets cursor to the end of text', (WidgetTester tester) async {
const String text = 'hello world';
final FocusScopeNode focusScopeNode = FocusScopeNode();