diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index ce888fd3bd9..3cb02677581 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -743,8 +743,8 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin { } // Just place the collapsed selection at the end or beginning of the region - // if shift isn't down. - if (!shift) { + // if shift isn't down or selection isn't enabled. + if (!shift || !selectionEnabled) { // We want to put the cursor at the correct location depending on which // arrow is used while there is a selection. int newOffset = newSelection.extentOffset; diff --git a/packages/flutter/lib/src/widgets/text_selection.dart b/packages/flutter/lib/src/widgets/text_selection.dart index cce6c5d40f3..378e2f186d4 100644 --- a/packages/flutter/lib/src/widgets/text_selection.dart +++ b/packages/flutter/lib/src/widgets/text_selection.dart @@ -1084,6 +1084,8 @@ class TextSelectionGestureDetectorBuilder { /// this callback. @protected void onDragSelectionStart(DragStartDetails details) { + if (!delegate.selectionEnabled) + return; final PointerDeviceKind? kind = details.kind; _shouldShowSelectionToolbar = kind == null || kind == PointerDeviceKind.touch @@ -1106,6 +1108,8 @@ class TextSelectionGestureDetectorBuilder { /// this callback./lib/src/material/text_field.dart @protected void onDragSelectionUpdate(DragStartDetails startDetails, DragUpdateDetails updateDetails) { + if (!delegate.selectionEnabled) + return; renderEditable.selectPositionAt( from: startDetails.globalPosition, to: updateDetails.globalPosition, diff --git a/packages/flutter/test/rendering/editable_test.dart b/packages/flutter/test/rendering/editable_test.dart index 748c97be694..fd413a224ad 100644 --- a/packages/flutter/test/rendering/editable_test.dart +++ b/packages/flutter/test/rendering/editable_test.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io' show Platform; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -1081,6 +1083,73 @@ void main() { expect(currentSelection.extentOffset, 1); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/58068 + test('respects enableInteractiveSelection', () async { + final TextSelectionDelegate delegate = FakeEditableTextState(); + final ViewportOffset viewportOffset = ViewportOffset.zero(); + late TextSelection currentSelection; + final RenderEditable editable = RenderEditable( + backgroundCursorColor: Colors.grey, + selectionColor: Colors.black, + textDirection: TextDirection.ltr, + cursorColor: Colors.red, + offset: viewportOffset, + textSelectionDelegate: delegate, + onSelectionChanged: (TextSelection selection, RenderEditable renderObject, SelectionChangedCause cause) { + currentSelection = selection; + }, + startHandleLayerLink: LayerLink(), + endHandleLayerLink: LayerLink(), + text: const TextSpan( + text: '012345', // Thumbs up + style: TextStyle(height: 1.0, fontSize: 10.0, fontFamily: 'Ahem'), + ), + selection: const TextSelection.collapsed( + offset: 0, + ), + enableInteractiveSelection: false, + ); + + layout(editable); + editable.hasFocus = true; + + editable.selection = const TextSelection.collapsed(offset: 2); + pumpFrame(); + + await simulateKeyDownEvent(LogicalKeyboardKey.shift); + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight); + expect(currentSelection.isCollapsed, true); + expect(currentSelection.baseOffset, 3); + editable.selection = currentSelection; + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowLeft); + expect(currentSelection.isCollapsed, true); + expect(currentSelection.baseOffset, 2); + editable.selection = currentSelection; + + final LogicalKeyboardKey wordModifier = + Platform.isMacOS ? LogicalKeyboardKey.alt : LogicalKeyboardKey.control; + + await simulateKeyDownEvent(wordModifier); + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowRight); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowRight); + expect(currentSelection.isCollapsed, true); + expect(currentSelection.baseOffset, 6); + editable.selection = currentSelection; + + await simulateKeyDownEvent(LogicalKeyboardKey.arrowLeft); + await simulateKeyUpEvent(LogicalKeyboardKey.arrowLeft); + expect(currentSelection.isCollapsed, true); + expect(currentSelection.baseOffset, 0); + editable.selection = currentSelection; + + await simulateKeyUpEvent(wordModifier); + await simulateKeyUpEvent(LogicalKeyboardKey.shift); + }, skip: isBrowser); // https://github.com/flutter/flutter/issues/58068 + group('delete', () { test('handles selection', () async { final TextSelectionDelegate delegate = FakeEditableTextState() diff --git a/packages/flutter/test/widgets/text_selection_test.dart b/packages/flutter/test/widgets/text_selection_test.dart index 67f5067f648..18d4cd307cc 100644 --- a/packages/flutter/test/widgets/text_selection_test.dart +++ b/packages/flutter/test/widgets/text_selection_test.dart @@ -600,6 +600,23 @@ void main() { expect(renderEditable.selectWordsInRangeCalled, isFalse); }); + testWidgets('test TextSelectionGestureDetectorBuilder mouse drag disabled', (WidgetTester tester) async { + await pumpTextSelectionGestureDetectorBuilder(tester, selectionEnabled: false); + final TestGesture gesture = await tester.startGesture( + const Offset(0.0, 0.0), + kind: PointerDeviceKind.mouse, + ); + addTearDown(gesture.removePointer); + await tester.pump(); + await gesture.moveTo(const Offset(50.0, 0)); + await tester.pump(); + await gesture.up(); + await tester.pumpAndSettle(); + + final FakeRenderEditable renderEditable = tester.renderObject(find.byType(FakeEditable)); + expect(renderEditable.selectPositionAtCalled, isFalse); + }); + testWidgets('test TextSelectionGestureDetectorBuilder forcePress disabled', (WidgetTester tester) async { await pumpTextSelectionGestureDetectorBuilder(tester, forcePressEnabled: false); final TestGesture gesture = await tester.createGesture();