diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 7f9a05c6d2..951bc87351 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -997,7 +997,7 @@ class RenderEditable extends RenderBox with RelayoutWhenSystemFontsChangeMixin, // // See also: // - // * _expandSelectionToEnd + // * _extendSelectionToEnd void _extendSelectionToStart(SelectionChangedCause cause) { if (selection!.extentOffset == 0) { return; diff --git a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart index 3343766069..d6564fe767 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -379,6 +379,8 @@ class DefaultTextEditingShortcuts extends Shortcuts { SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): ExtendSelectionLeftTextIntent(), SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): ExtendSelectionRightTextIntent(), SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): ExtendSelectionUpTextIntent(), + SingleActivator(LogicalKeyboardKey.end, shift: true): ExpandSelectionToEndTextIntent(), + SingleActivator(LogicalKeyboardKey.home, shift: true): ExpandSelectionToStartTextIntent(), SingleActivator(LogicalKeyboardKey.keyA, meta: true): SelectAllTextIntent(), // The following key combinations have no effect on text editing on this // platform: @@ -389,8 +391,6 @@ class DefaultTextEditingShortcuts extends Shortcuts { // * Control + shift + arrow right // * End // * Home - // * Shift + end - // * Shift + home // * Control + delete // * Control + backspace }; diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 9340a25e82..64259e1fa9 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -4135,8 +4135,10 @@ void main() { bool wordModifier = false, bool lineModifier = false, bool shortcutModifier = false, - required String platform, + required TargetPlatform targetPlatform, }) async { + final String targetPlatformString = targetPlatform.toString(); + final String platform = targetPlatformString.substring(targetPlatformString.indexOf('.') + 1).toLowerCase(); if (shift) { await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform); } @@ -4188,7 +4190,9 @@ void main() { } } - Future testTextEditing(WidgetTester tester, {required String platform}) async { + Future testTextEditing(WidgetTester tester, {required TargetPlatform targetPlatform}) async { + final String targetPlatformString = targetPlatform.toString(); + final String platform = targetPlatformString.substring(targetPlatformString.indexOf('.') + 1).toLowerCase(); final TextEditingController controller = TextEditingController(text: testText); controller.selection = const TextSelection( baseOffset: 0, @@ -4234,7 +4238,7 @@ void main() { LogicalKeyboardKey.arrowRight, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect(cause, equals(SelectionChangedCause.keyboard), reason: 'on $platform'); @@ -4259,7 +4263,7 @@ void main() { LogicalKeyboardKey.arrowLeft, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4281,7 +4285,7 @@ void main() { LogicalKeyboardKey.arrowLeft, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4305,7 +4309,7 @@ void main() { ], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4328,7 +4332,7 @@ void main() { ], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4350,7 +4354,7 @@ void main() { LogicalKeyboardKey.arrowDown, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4370,7 +4374,7 @@ void main() { [ LogicalKeyboardKey.arrowRight, ], - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4392,7 +4396,7 @@ void main() { LogicalKeyboardKey.arrowDown, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4417,7 +4421,7 @@ void main() { LogicalKeyboardKey.arrowDown, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4439,7 +4443,7 @@ void main() { LogicalKeyboardKey.arrowUp, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4462,7 +4466,7 @@ void main() { ], lineModifier: true, shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4485,7 +4489,7 @@ void main() { ], lineModifier: true, shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4507,7 +4511,7 @@ void main() { LogicalKeyboardKey.keyA, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4528,7 +4532,7 @@ void main() { [ LogicalKeyboardKey.arrowLeft, ], - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4551,7 +4555,7 @@ void main() { ], shift: false, lineModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4574,7 +4578,7 @@ void main() { ], shift: false, lineModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4599,7 +4603,7 @@ void main() { ], shift: false, lineModifier: false, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4621,7 +4625,7 @@ void main() { ], shift: true, lineModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4644,7 +4648,7 @@ void main() { ], shift: true, lineModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4667,7 +4671,7 @@ void main() { ], shift: false, lineModifier: false, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4690,7 +4694,7 @@ void main() { LogicalKeyboardKey.arrowRight, ], wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4714,7 +4718,7 @@ void main() { LogicalKeyboardKey.arrowLeft, ], shift: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4737,7 +4741,7 @@ void main() { ], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4760,7 +4764,7 @@ void main() { LogicalKeyboardKey.keyX, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4797,7 +4801,7 @@ void main() { LogicalKeyboardKey.keyV, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4821,7 +4825,7 @@ void main() { LogicalKeyboardKey.keyC, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4844,7 +4848,7 @@ void main() { [ LogicalKeyboardKey.delete, ], - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( selection, @@ -4861,9 +4865,7 @@ void main() { } testWidgets('keyboard text selection works', (WidgetTester tester) async { - final String targetPlatform = defaultTargetPlatform.toString(); - final String platform = targetPlatform.substring(targetPlatform.indexOf('.') + 1).toLowerCase(); - await testTextEditing(tester, platform: platform); + await testTextEditing(tester, targetPlatform: defaultTargetPlatform); // On web, using keyboard for selection is handled by the browser. }, skip: kIsWeb, variant: TargetPlatformVariant.all()); @@ -4914,7 +4916,7 @@ void main() { LogicalKeyboardKey.keyV, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect(selection, isNull, reason: 'on $platform'); @@ -4927,7 +4929,7 @@ void main() { LogicalKeyboardKey.keyA, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4950,7 +4952,7 @@ void main() { LogicalKeyboardKey.keyX, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -4978,7 +4980,7 @@ void main() { LogicalKeyboardKey.keyC, ], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( @@ -5005,7 +5007,7 @@ void main() { [ LogicalKeyboardKey.delete, ], - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( selection, @@ -5026,7 +5028,7 @@ void main() { [ LogicalKeyboardKey.backspace, ], - platform: platform, + targetPlatform: defaultTargetPlatform, ); expect( selection, @@ -7206,7 +7208,7 @@ void main() { [ LogicalKeyboardKey.delete, ], - platform: 'android', + targetPlatform: TargetPlatform.android, ); expect(tester.takeException(), null); @@ -7302,13 +7304,11 @@ void main() { expect(controller.selection.baseOffset, 0); // meta + A moves the cursor right instead of doing select all. - final String targetPlatform = defaultTargetPlatform.toString(); - final String platform = targetPlatform.substring(targetPlatform.indexOf('.') + 1).toLowerCase(); await sendKeys( tester, [LogicalKeyboardKey.keyA], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); await tester.pump(); expect(controller.selection.isCollapsed, isTrue); @@ -7317,7 +7317,7 @@ void main() { tester, [LogicalKeyboardKey.keyA], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); await tester.pump(); expect(controller.selection.isCollapsed, isTrue); @@ -7358,15 +7358,12 @@ void main() { expect(controller.selection.baseOffset, 7); expect(controller.selection.extentOffset, 9); - final String targetPlatform = defaultTargetPlatform.toString(); - final String platform = targetPlatform.substring(targetPlatform.indexOf('.') + 1).toLowerCase(); - await sendKeys( tester, [LogicalKeyboardKey.arrowRight], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); await tester.pump(); // word wo|rd word| @@ -7379,7 +7376,7 @@ void main() { [LogicalKeyboardKey.arrowLeft], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); // word wo|rd |word expect(controller.selection.isCollapsed, false); @@ -7391,9 +7388,9 @@ void main() { [LogicalKeyboardKey.arrowLeft], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); - if (platform == 'macos') { + if (defaultTargetPlatform == TargetPlatform.macOS) { // word wo|rd word expect(controller.selection.isCollapsed, true); expect(controller.selection.baseOffset, 7); @@ -7404,7 +7401,7 @@ void main() { [LogicalKeyboardKey.arrowLeft], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); } @@ -7418,7 +7415,7 @@ void main() { [LogicalKeyboardKey.arrowLeft], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); // |word wo|rd word expect(controller.selection.isCollapsed, false); @@ -7430,7 +7427,7 @@ void main() { [LogicalKeyboardKey.arrowRight], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); // word| wo|rd word expect(controller.selection.isCollapsed, false); @@ -7442,9 +7439,9 @@ void main() { [LogicalKeyboardKey.arrowRight], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); - if (platform == 'macos') { + if (defaultTargetPlatform == TargetPlatform.macOS) { // word wo|rd word expect(controller.selection.isCollapsed, true); expect(controller.selection.baseOffset, 7); @@ -7455,7 +7452,7 @@ void main() { [LogicalKeyboardKey.arrowRight], shift: true, wordModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); } @@ -7467,6 +7464,90 @@ void main() { // On web, using keyboard for selection is handled by the browser. }, skip: kIsWeb, variant: TargetPlatformVariant.all()); + testWidgets('expanding selection to start/end', (WidgetTester tester) async { + final TextEditingController controller = TextEditingController(text: 'word word word'); + // word wo|rd| word + controller.selection = const TextSelection( + baseOffset: 7, + extentOffset: 9, + affinity: TextAffinity.upstream, + ); + await tester.pumpWidget(MaterialApp( + home: Align( + alignment: Alignment.topLeft, + child: SizedBox( + width: 400, + child: EditableText( + maxLines: 10, + controller: controller, + autofocus: true, + focusNode: focusNode, + style: Typography.material2018(platform: TargetPlatform.android).black.subtitle1!, + cursorColor: Colors.blue, + backgroundCursorColor: Colors.grey, + keyboardType: TextInputType.text, + ), + ), + ), + )); + + await tester.pump(); // Wait for autofocus to take effect. + expect(controller.selection.isCollapsed, false); + expect(controller.selection.baseOffset, 7); + expect(controller.selection.extentOffset, 9); + + final String targetPlatform = defaultTargetPlatform.toString(); + final String platform = targetPlatform.substring(targetPlatform.indexOf('.') + 1).toLowerCase(); + + // Select to the start. + await sendKeys( + tester, + [ + LogicalKeyboardKey.home, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + + // |word word| word + expect( + controller.selection, + equals( + const TextSelection( + baseOffset: 9, + extentOffset: 0, + affinity: TextAffinity.downstream, + ), + ), + reason: 'on $platform', + ); + + // Select to the end. + await sendKeys( + tester, + [ + LogicalKeyboardKey.home, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + + // |word word word| + expect( + controller.selection, + equals( + const TextSelection( + baseOffset: 9, + extentOffset: 0, + affinity: TextAffinity.downstream, + ), + ), + reason: 'on $platform', + ); + + // On web, using keyboard for selection is handled by the browser. + }, skip: kIsWeb, variant: const TargetPlatformVariant({ TargetPlatform.macOS })); + testWidgets('can change behavior by overriding text editing actions', (WidgetTester tester) async { final TextEditingController controller = TextEditingController(text: testText); controller.selection = const TextSelection( @@ -7568,13 +7649,11 @@ void main() { expect(controller.selection.baseOffset, 0); // meta + A moves the cursor right instead of doing select all. - final String targetPlatform = defaultTargetPlatform.toString(); - final String platform = targetPlatform.substring(targetPlatform.indexOf('.') + 1).toLowerCase(); await sendKeys( tester, [LogicalKeyboardKey.keyA], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); await tester.pump(); expect(controller.selection.isCollapsed, isTrue); @@ -7584,7 +7663,7 @@ void main() { tester, [LogicalKeyboardKey.keyA], shortcutModifier: true, - platform: platform, + targetPlatform: defaultTargetPlatform, ); await tester.pump(); expect(controller.selection.isCollapsed, isTrue);