Unverified Commit 715fcaac authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Can't drag the cursor with the mouse (#103002)

parent 8afaf7b5
......@@ -1208,12 +1208,28 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S
alignment: Alignment.topLeft,
width: interactiveRect.width,
height: interactiveRect.height,
child: GestureDetector(
child: RawGestureDetector(
behavior: HitTestBehavior.translucent,
dragStartBehavior: widget.dragStartBehavior,
onPanStart: widget.onSelectionHandleDragStart,
onPanUpdate: widget.onSelectionHandleDragUpdate,
onPanEnd: widget.onSelectionHandleDragEnd,
gestures: <Type, GestureRecognizerFactory>{
PanGestureRecognizer: GestureRecognizerFactoryWithHandlers<PanGestureRecognizer>(
() => PanGestureRecognizer(
debugOwner: this,
// Mouse events select the text and do not drag the cursor.
supportedDevices: <PointerDeviceKind>{
PointerDeviceKind.touch,
PointerDeviceKind.stylus,
PointerDeviceKind.unknown,
},
),
(PanGestureRecognizer instance) {
instance
..dragStartBehavior = widget.dragStartBehavior
..onStart = widget.onSelectionHandleDragStart
..onUpdate = widget.onSelectionHandleDragUpdate
..onEnd = widget.onSelectionHandleDragEnd;
},
),
},
child: Padding(
padding: EdgeInsets.only(
left: padding.left,
......
......@@ -2897,7 +2897,7 @@ void main() {
// The selection doesn't move beyond the left handle. There's always at
// least 1 char selected.
expect(controller.selection.extentOffset, 5);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Can select text by dragging with a mouse', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
......@@ -3571,7 +3571,7 @@ void main() {
expect(left.opacity.value, equals(1.0));
expect(right.opacity.value, equals(1.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('when CupertinoTextField would be blocked by keyboard, it is shown with enough space for the selection handle', (WidgetTester tester) async {
final ScrollController scrollController = ScrollController();
......
......@@ -9400,7 +9400,7 @@ void main() {
expect(left.opacity.value, equals(1.0));
expect(right.opacity.value, equals(1.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('iPad Scribble selection change shows selection handles', (WidgetTester tester) async {
const String testText = 'lorem ipsum';
......
......@@ -7825,7 +7825,7 @@ void main() {
// On web, we don't show the Flutter toolbar and instead rely on the browser
// toolbar. Until we change that, this test should remain skipped.
skip: kIsWeb, // [intended]
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS })
);
testWidgets("scrolling doesn't bounce", (WidgetTester tester) async {
......
......@@ -4279,7 +4279,7 @@ void main() {
expect(left.opacity.value, equals(1.0));
expect(right.opacity.value, equals(1.0));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
testWidgets('Long press shows handles and toolbar', (WidgetTester tester) async {
await tester.pumpWidget(
......
......@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'clipboard_utils.dart';
import 'editable_text_utils.dart';
void main() {
late int tapCount;
......@@ -628,7 +629,7 @@ void main() {
});
testWidgets('Mouse drag does not show handles nor toolbar', (WidgetTester tester) async {
// Regressing test for https://github.com/flutter/flutter/issues/69001
// Regression test for https://github.com/flutter/flutter/issues/69001
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
......@@ -652,6 +653,231 @@ void main() {
expect(editableText.selectionOverlay!.toolbarIsVisible, isFalse);
});
testWidgets('Mouse drag selects and cannot drag cursor', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/102928
final TextEditingController controller = TextEditingController(
text: 'I love flutter!',
);
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
editableTextKey: editableTextKey,
forcePressEnabled: false,
selectionEnabled: true,
);
final TextSelectionGestureDetectorBuilder provider =
TextSelectionGestureDetectorBuilder(delegate: delegate);
await tester.pumpWidget(
MaterialApp(
home: provider.buildGestureDetector(
behavior: HitTestBehavior.translucent,
child: EditableText(
key: editableTextKey,
controller: controller,
focusNode: FocusNode(),
backgroundCursorColor: Colors.white,
cursorColor: Colors.white,
style: const TextStyle(),
selectionControls: materialTextSelectionControls,
),
),
),
);
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, -1);
final Offset position = textOffsetToPosition(tester, 4);
await tester.tapAt(position);
await tester.pump();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 4);
final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.mouse);
addTearDown(gesture.removePointer);
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 7));
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 10));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(controller.selection.isCollapsed, isFalse);
expect(controller.selection.baseOffset, 4);
expect(controller.selection.extentOffset, 10);
});
testWidgets('Touch drag moves the cursor', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/102928
final TextEditingController controller = TextEditingController(
text: 'I love flutter!',
);
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
editableTextKey: editableTextKey,
forcePressEnabled: false,
selectionEnabled: true,
);
final TextSelectionGestureDetectorBuilder provider =
TextSelectionGestureDetectorBuilder(delegate: delegate);
await tester.pumpWidget(
MaterialApp(
home: provider.buildGestureDetector(
behavior: HitTestBehavior.translucent,
child: EditableText(
key: editableTextKey,
controller: controller,
focusNode: FocusNode(),
backgroundCursorColor: Colors.white,
cursorColor: Colors.white,
style: const TextStyle(),
selectionControls: materialTextSelectionControls,
),
),
),
);
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, -1);
final Offset position = textOffsetToPosition(tester, 4);
await tester.tapAt(position);
await tester.pump();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 4);
final TestGesture gesture = await tester.startGesture(position);
addTearDown(gesture.removePointer);
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 7));
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 10));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 10);
});
testWidgets('Stylus drag moves the cursor', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/102928
final TextEditingController controller = TextEditingController(
text: 'I love flutter!',
);
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
editableTextKey: editableTextKey,
forcePressEnabled: false,
selectionEnabled: true,
);
final TextSelectionGestureDetectorBuilder provider =
TextSelectionGestureDetectorBuilder(delegate: delegate);
await tester.pumpWidget(
MaterialApp(
home: provider.buildGestureDetector(
behavior: HitTestBehavior.translucent,
child: EditableText(
key: editableTextKey,
controller: controller,
focusNode: FocusNode(),
backgroundCursorColor: Colors.white,
cursorColor: Colors.white,
style: const TextStyle(),
selectionControls: materialTextSelectionControls,
),
),
),
);
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, -1);
final Offset position = textOffsetToPosition(tester, 4);
await tester.tapAt(position);
await tester.pump();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 4);
final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.stylus);
addTearDown(gesture.removePointer);
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 7));
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 10));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 10);
});
testWidgets('Drag of unknown type moves the cursor', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/102928
final TextEditingController controller = TextEditingController(
text: 'I love flutter!',
);
final GlobalKey<EditableTextState> editableTextKey = GlobalKey<EditableTextState>();
final FakeTextSelectionGestureDetectorBuilderDelegate delegate = FakeTextSelectionGestureDetectorBuilderDelegate(
editableTextKey: editableTextKey,
forcePressEnabled: false,
selectionEnabled: true,
);
final TextSelectionGestureDetectorBuilder provider =
TextSelectionGestureDetectorBuilder(delegate: delegate);
await tester.pumpWidget(
MaterialApp(
home: provider.buildGestureDetector(
behavior: HitTestBehavior.translucent,
child: EditableText(
key: editableTextKey,
controller: controller,
focusNode: FocusNode(),
backgroundCursorColor: Colors.white,
cursorColor: Colors.white,
style: const TextStyle(),
selectionControls: materialTextSelectionControls,
),
),
),
);
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, -1);
final Offset position = textOffsetToPosition(tester, 4);
await tester.tapAt(position);
await tester.pump();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 4);
final TestGesture gesture = await tester.startGesture(position, kind: PointerDeviceKind.unknown);
addTearDown(gesture.removePointer);
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 7));
await tester.pump();
await gesture.moveTo(textOffsetToPosition(tester, 10));
await tester.pump();
await gesture.up();
await tester.pumpAndSettle();
expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 10);
});
testWidgets('test TextSelectionGestureDetectorBuilder drag with RenderEditable viewport offset change', (WidgetTester tester) async {
await pumpTextSelectionGestureDetectorBuilder(tester);
final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable));
......@@ -767,7 +993,7 @@ void main() {
of: find.byType(CompositedTransformFollower),
matching: find.descendant(
of: find.byType(FadeTransition),
matching: find.byType(GestureDetector),
matching: find.byType(RawGestureDetector),
),
);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment