From 9cd79605be5286a3c2d5ce1ca39c80dba1a94956 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 23 Jun 2022 14:36:56 +0200 Subject: [PATCH 01/32] Initial implementation --- .../flutter/lib/src/rendering/editable.dart | 18 +++++ .../default_text_editing_shortcuts.dart | 10 +++ .../lib/src/widgets/editable_text.dart | 71 +++++++++++++++++++ .../lib/src/widgets/text_editing_intents.dart | 11 +++ 4 files changed, 110 insertions(+) diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 9cc430ef462cb..80051181aea92 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -200,6 +200,24 @@ class VerticalCaretMovementRun extends Iterator { _currentTextPosition = position.value; return true; } + + bool moveByOffset(double offset) { + final Offset initialOffset = _currentOffset; + if (offset >= 0.0) { + while (_currentOffset.dy < initialOffset.dy + offset) { + if (!moveNext()) { + break; + } + } + } else { + while (_currentOffset.dy > initialOffset.dy + offset) { + if (!movePrevious()) { + break; + } + } + } + return initialOffset != _currentOffset; + } } /// Displays some text in a scrollable container with a potentially blinking 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 2c426848307bb..8803234f1da1f 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -198,6 +198,11 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageUp): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.keyX, control: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard), const SingleActivator(LogicalKeyboardKey.keyC, control: true): CopySelectionTextIntent.copy, const SingleActivator(LogicalKeyboardKey.keyV, control: true): const PasteTextIntent(SelectionChangedCause.keyboard), @@ -299,6 +304,11 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageUp): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.keyT, control: true): const TransposeCharactersIntent(), const SingleActivator(LogicalKeyboardKey.home): const ScrollToDocumentBoundaryIntent(forward: false), diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index dc1cb337517c8..c6b75ef207c16 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -473,6 +473,7 @@ class _DiscreteKeyFrameSimulation extends Simulation { /// | [ExtendSelectionToNextWordBoundaryOrCaretLocationIntent](`collapseSelection: true`) | Collapses the selection to the word boundary before/after the selection's [TextSelection.extent] position, or [TextSelection.base], whichever is closest in the given direction | Moves the caret to the previous/next word boundary. | /// | [ExtendSelectionToLineBreakIntent](`collapseSelection: true`) | Collapses the selection to the start/end of the line at the selection's [TextSelection.extent] position | Moves the caret to the start/end of the current line .| /// | [ExtendSelectionVerticallyToAdjacentLineIntent](`collapseSelection: true`) | Collapses the selection to the position closest to the selection's [TextSelection.extent], on the previous/next adjacent line | Moves the caret to the closest position on the previous/next adjacent line. | +/// | [ExtendSelectionVerticallyToAdjacentPageIntent](`collapseSelection: true`) | Collapses the selection to the position closest to the selection's [TextSelection.extent], on the previous/next adjacent page | Moves the caret to the closest position on the previous/next adjacent page. | /// | [ExtendSelectionToDocumentBoundaryIntent](`collapseSelection: true`) | Collapses the selection to the start/end of the document | Moves the caret to the start/end of the document. | /// /// #### Intents for Extending the Selection @@ -484,6 +485,7 @@ class _DiscreteKeyFrameSimulation extends Simulation { /// | [ExtendSelectionToNextWordBoundaryOrCaretLocationIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the previous/next word boundary, or [TextSelection.base] whichever is closest in the given direction | Moves the selection's [TextSelection.extent] to the previous/next word boundary. | /// | [ExtendSelectionToLineBreakIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the start/end of the line | /// | [ExtendSelectionVerticallyToAdjacentLineIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the closest position on the previous/next adjacent line | +/// | [ExtendSelectionVerticallyToAdjacentPageIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the closest position on the previous/next adjacent page | /// | [ExtendSelectionToDocumentBoundaryIntent](`collapseSelection: false`) | Moves the selection's [TextSelection.extent] to the start/end of the document | /// | [SelectAllTextIntent] | Selects the entire document | /// @@ -3374,6 +3376,8 @@ class EditableTextState extends State with AutomaticKeepAliveClien late final _UpdateTextSelectionToAdjacentLineAction _adjacentLineAction = _UpdateTextSelectionToAdjacentLineAction(this); + late final _UpdateTextSelectionToAdjacentPageAction _adjacentPageAction = _UpdateTextSelectionToAdjacentPageAction(this); + void _expandSelectionToDocumentBoundary(ExpandSelectionToDocumentBoundaryIntent intent) { final _TextBoundary textBoundary = _documentBoundary(intent); _expandSelection(intent.forward, textBoundary, true); @@ -3435,6 +3439,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien ExpandSelectionToLineBreakIntent: _makeOverridable(CallbackAction(onInvoke: _expandSelectionToLinebreak)), ExpandSelectionToDocumentBoundaryIntent: _makeOverridable(CallbackAction(onInvoke: _expandSelectionToDocumentBoundary)), ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_adjacentLineAction), + ExtendSelectionVerticallyToAdjacentPageIntent: _makeOverridable(_adjacentPageAction), ExtendSelectionToDocumentBoundaryIntent: _makeOverridable(_UpdateTextSelectionAction(this, true, _documentBoundary)), ExtendSelectionToNextWordBoundaryOrCaretLocationIntent: _makeOverridable(_ExtendSelectionOrCaretPositionAction(this, _nextWordBoundary)), ScrollToDocumentBoundaryIntent: _makeOverridable(CallbackAction(onInvoke: _scrollToDocumentBoundary)), @@ -4477,6 +4482,72 @@ class _UpdateTextSelectionToAdjacentLineAction state._value.selection.isValid; } +class _UpdateTextSelectionToAdjacentPageAction extends ContextAction { + _UpdateTextSelectionToAdjacentPageAction(this.state); + + final EditableTextState state; + + VerticalCaretMovementRun? _verticalMovementRun; + TextSelection? _runSelection; + + void stopCurrentVerticalRunIfSelectionChanges() { + final TextSelection? runSelection = _runSelection; + if (runSelection == null) { + assert(_verticalMovementRun == null); + return; + } + _runSelection = state._value.selection; + final TextSelection currentSelection = state.widget.controller.selection; + final bool continueCurrentRun = currentSelection.isValid && currentSelection.isCollapsed + && currentSelection.baseOffset == runSelection.baseOffset + && currentSelection.extentOffset == runSelection.extentOffset; + if (!continueCurrentRun) { + _verticalMovementRun = null; + _runSelection = null; + } + } + + @override + void invoke(T intent, [BuildContext? context]) { + assert(state._value.selection.isValid); + + final bool collapseSelection = intent.collapseSelection || !state.widget.selectionEnabled; + final TextEditingValue value = state._textEditingValueforTextLayoutMetrics; + if (!value.selection.isValid) { + return; + } + + if (_verticalMovementRun?.isValid == false) { + _verticalMovementRun = null; + _runSelection = null; + } + + final VerticalCaretMovementRun currentRun = _verticalMovementRun + ?? state.renderEditable.startVerticalCaretMovement(state.renderEditable.selection!.extent); + + final bool shouldMove = currentRun.moveByOffset( + (intent.forward ? 1.0 : -1.0) * state.renderEditable.size.height); + final TextPosition newExtent = shouldMove + ? currentRun.current + : (intent.forward ? TextPosition(offset: state._value.text.length) : const TextPosition(offset: 0)); + final TextSelection newSelection = collapseSelection + ? TextSelection.fromPosition(newExtent) + : value.selection.extendTo(newExtent); + + Actions.invoke( + context!, + UpdateSelectionIntent(value, newSelection, SelectionChangedCause.keyboard), + ); + if (state._value.selection == newSelection) { + _verticalMovementRun = currentRun; + _runSelection = newSelection; + } + } + + @override + bool get isActionEnabled => state._value.selection.isValid; +} + class _SelectAllAction extends ContextAction { _SelectAllAction(this.state); diff --git a/packages/flutter/lib/src/widgets/text_editing_intents.dart b/packages/flutter/lib/src/widgets/text_editing_intents.dart index a7be37d704ccd..2f0343c6996b8 100644 --- a/packages/flutter/lib/src/widgets/text_editing_intents.dart +++ b/packages/flutter/lib/src/widgets/text_editing_intents.dart @@ -210,6 +210,17 @@ class ExtendSelectionVerticallyToAdjacentLineIntent extends DirectionalCaretMove }) : super(forward, collapseSelection); } +/// Expands, or moves the current selection from the current +/// [TextSelection.extent] position to the closest position on the adjacent +/// page. +class ExtendSelectionVerticallyToAdjacentPageIntent extends DirectionalCaretMovementIntent { + /// Creates an [ExtendSelectionVerticallyToAdjacentPageIntent]. + const ExtendSelectionVerticallyToAdjacentPageIntent({ + required bool forward, + required bool collapseSelection, + }) : super(forward, collapseSelection); +} + /// Extends, or moves the current selection from the current /// [TextSelection.extent] position to the start or the end of the document. /// From e45b2fb5db1d8041cb8198c17941683d39a93137 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 23 Jun 2022 14:59:12 +0200 Subject: [PATCH 02/32] Update comments --- packages/flutter/lib/src/rendering/editable.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 80051181aea92..5bd55c51eb3e5 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -108,10 +108,13 @@ class TextSelectionPoint { /// false. Similarly the [moveNext] method moves the caret to the next line, and /// returns false if the caret is already on the last line. /// +/// The [moveByOffset] takes a pixel offset from the current position to move +/// the caret up or down. +/// /// If the underlying paragraph's layout changes, [isValid] becomes false and /// the [VerticalCaretMovementRun] must not be used. The [isValid] property must -/// be checked before calling [movePrevious] and [moveNext], or accessing -/// [current]. +/// be checked before calling [movePrevious], [moveNext] and [moveByOffset], +/// or accessing [current]. class VerticalCaretMovementRun extends Iterator { VerticalCaretMovementRun._( this._editable, @@ -134,8 +137,8 @@ class VerticalCaretMovementRun extends Iterator { /// A [VerticalCaretMovementRun] run is valid if the underlying text layout /// hasn't changed. /// - /// The [current] value and the [movePrevious] and [moveNext] methods must not - /// be accessed when [isValid] is false. + /// The [current] value and the [movePrevious], [moveNext] and [moveByOffset] + /// methods must not be accessed when [isValid] is false. bool get isValid { if (!_isValid) { return false; From 79162a130667070bf00a2b34daa38adcba639661 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 7 Jul 2022 17:36:53 +0200 Subject: [PATCH 03/32] Document public method --- packages/flutter/lib/src/rendering/editable.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 5bd55c51eb3e5..fafec02e637f1 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -204,6 +204,11 @@ class VerticalCaretMovementRun extends Iterator { return true; } + /// Move forward or backward by a number of elements determined + /// by pixel [offset]. + /// + /// If [offset] is negative, move backward; otherwise move forward. + /// Returns true and updates [current] if successful. bool moveByOffset(double offset) { final Offset initialOffset = _currentOffset; if (offset >= 0.0) { From 75474d2fd0a391298cba10fad5eaeacbb422127e Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 7 Jul 2022 17:38:58 +0200 Subject: [PATCH 04/32] Use const intents --- .../widgets/default_text_editing_shortcuts.dart | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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 8803234f1da1f..675aaa4b44b20 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -198,10 +198,10 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: true, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageUp): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.keyX, control: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard), const SingleActivator(LogicalKeyboardKey.keyC, control: true): CopySelectionTextIntent.copy, @@ -304,10 +304,10 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: true, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageUp): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.keyT, control: true): const TransposeCharactersIntent(), From 2b167002c97792481d4f7877f07f668265471a68 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 7 Jul 2022 19:24:59 +0200 Subject: [PATCH 05/32] Remove macOS page up/down shortcuts --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 5 ----- 1 file changed, 5 deletions(-) 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 675aaa4b44b20..63a79e10c637a 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -304,11 +304,6 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true, meta: true): const ExtendSelectionToDocumentBoundaryIntent(forward: true, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.keyT, control: true): const TransposeCharactersIntent(), const SingleActivator(LogicalKeyboardKey.home): const ScrollToDocumentBoundaryIntent(forward: false), From 61d73c521c04e170e2c24329deb10acffb01c89e Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 14 Jul 2022 01:51:52 +0200 Subject: [PATCH 06/32] Add shortcuts tests --- .../widgets/editable_text_shortcuts_test.dart | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index 0661410a5b3e0..6631f1d183203 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -121,6 +121,8 @@ void main() { LogicalKeyboardKey.arrowRight, LogicalKeyboardKey.arrowUp, LogicalKeyboardKey.arrowDown, + LogicalKeyboardKey.pageUp, + LogicalKeyboardKey.pageDown, LogicalKeyboardKey.home, LogicalKeyboardKey.end, ]; @@ -1443,6 +1445,18 @@ void main() { reason: activator.toString(), ); } + + for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageUp)) { + await sendKeyCombination(tester, activator); + await tester.pump(); + + expect(controller.text, testText); + expect( + controller.selection, + const TextSelection.collapsed(offset: 0), + reason: activator.toString(), + ); + } }, variant: TargetPlatformVariant.all()); testWidgets('at end', (WidgetTester tester) async { @@ -1461,6 +1475,15 @@ void main() { expect(controller.selection.baseOffset, 72, reason: activator.toString()); expect(controller.selection.extentOffset, 72, reason: activator.toString()); } + + for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageDown)) { + await sendKeyCombination(tester, activator); + await tester.pump(); + + expect(controller.text, testText); + expect(controller.selection.baseOffset, 72, reason: activator.toString()); + expect(controller.selection.extentOffset, 72, reason: activator.toString()); + } }, variant: TargetPlatformVariant.all()); testWidgets('run', (WidgetTester tester) async { @@ -1549,6 +1572,41 @@ void main() { )); }, variant: TargetPlatformVariant.all()); + testWidgets('run with page down/up', (WidgetTester tester) async { + controller.text = + 'aa\n' // 3 + 'a\n' // 3 + 2 = 5 + 'aa\n' // 5 + 3 = 8 + 'aaa\n' // 8 + 4 = 12 + '${"aaa\n" * 50}' + 'aaaa'; + + controller.selection = const TextSelection.collapsed(offset: 2); + await tester.pumpWidget(buildEditableText()); + + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.arrowDown)); + await tester.pump(); + expect(controller.selection, const TextSelection.collapsed( + offset: 4, + affinity: TextAffinity.upstream, + )); + + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown)); + await tester.pump(); + expect(controller.selection, const TextSelection.collapsed(offset: 81)); + + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.arrowUp)); + await tester.pump(); + expect(controller.selection, const TextSelection.collapsed(offset: 77)); + + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp)); + await tester.pump(); + expect(controller.selection, const TextSelection.collapsed( + offset: 4, + affinity: TextAffinity.upstream, + )); + }, variant: TargetPlatformVariant.all()); + testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = 'aa\n' // 3 From 474ac7d3557f4679e68d42909bbeafadcbee4384 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 14 Jul 2022 01:52:27 +0200 Subject: [PATCH 07/32] Add page down/up in EditableText editing test --- .../test/widgets/editable_text_test.dart | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 55acff909ff5c..a6aed72256453 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5853,6 +5853,86 @@ void main() { reason: 'on $platform', ); + // Move down by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + targetPlatform: defaultTargetPlatform, + ); + + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 55, + ), + ), + reason: 'on $platform', + ); + + // Move up by page (to start). + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + targetPlatform: defaultTargetPlatform, + ); + + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, + ), + ), + reason: 'on $platform', + ); + + // Select towards end by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + + expect( + selection, + equals( + const TextSelection( + baseOffset: 0, + extentOffset: 55, + affinity: TextAffinity.upstream, + ), + ), + reason: 'on $platform', + ); + + // Change selection extent towards start by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); + + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, + ), + ), + reason: 'on $platform', + ); + // Jump forward three words. await sendKeys( tester, From af34a0fa992ba31a606507ff4db4c1bb9603b398 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 14 Jul 2022 02:00:35 +0200 Subject: [PATCH 08/32] Exclude Cupertino platforms from tests --- .../widgets/editable_text_shortcuts_test.dart | 31 +++- .../test/widgets/editable_text_test.dart | 141 +++++++++--------- 2 files changed, 102 insertions(+), 70 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index 6631f1d183203..1ed5ec579a2a0 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1445,6 +1445,15 @@ void main() { reason: activator.toString(), ); } + }, variant: TargetPlatformVariant.all()); + + testWidgets('at start with page up', (WidgetTester tester) async { + controller.text = testText; + controller.selection = const TextSelection.collapsed( + offset: 0, + ); + + await tester.pumpWidget(buildEditableText()); for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageUp)) { await sendKeyCombination(tester, activator); @@ -1457,7 +1466,7 @@ void main() { reason: activator.toString(), ); } - }, variant: TargetPlatformVariant.all()); + }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); testWidgets('at end', (WidgetTester tester) async { controller.text = testText; @@ -1486,6 +1495,24 @@ void main() { } }, variant: TargetPlatformVariant.all()); + testWidgets('at end with page down', (WidgetTester tester) async { + controller.text = testText; + controller.selection = const TextSelection.collapsed( + offset: 72, + ); + + await tester.pumpWidget(buildEditableText()); + + for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageDown)) { + await sendKeyCombination(tester, activator); + await tester.pump(); + + expect(controller.text, testText); + expect(controller.selection.baseOffset, 72, reason: activator.toString()); + expect(controller.selection.extentOffset, 72, reason: activator.toString()); + } + }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); + testWidgets('run', (WidgetTester tester) async { controller.text = 'aa\n' // 3 @@ -1605,7 +1632,7 @@ void main() { offset: 4, affinity: TextAffinity.upstream, )); - }, variant: TargetPlatformVariant.all()); + }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index a6aed72256453..3f72c1258df76 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5853,85 +5853,90 @@ void main() { reason: 'on $platform', ); - // Move down by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageDown, - ], - targetPlatform: defaultTargetPlatform, - ); + // Skip page down/up tests on Cupertino platforms as these keys don't + // move the caret. + if (defaultTargetPlatform != TargetPlatform.iOS + && defaultTargetPlatform != TargetPlatform.macOS) { + // Move down by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 55, + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 55, + ), ), - ), - reason: 'on $platform', - ); + reason: 'on $platform', + ); - // Move up by page (to start). - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageUp, - ], - targetPlatform: defaultTargetPlatform, - ); + // Move up by page (to start). + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 0, + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, + ), ), - ), - reason: 'on $platform', - ); + reason: 'on $platform', + ); - // Select towards end by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageDown, - ], - shift: true, - targetPlatform: defaultTargetPlatform, - ); + // Select towards end by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection( - baseOffset: 0, - extentOffset: 55, - affinity: TextAffinity.upstream, + expect( + selection, + equals( + const TextSelection( + baseOffset: 0, + extentOffset: 55, + affinity: TextAffinity.upstream, + ), ), - ), - reason: 'on $platform', - ); + reason: 'on $platform', + ); - // Change selection extent towards start by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageUp, - ], - shift: true, - targetPlatform: defaultTargetPlatform, - ); + // Change selection extent towards start by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + shift: true, + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 0, + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, + ), ), - ), - reason: 'on $platform', - ); + reason: 'on $platform', + ); + } // Jump forward three words. await sendKeys( From 0b779994d0ae9967299f4c8daa111bcab341fa41 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Thu, 14 Jul 2022 09:57:32 +0200 Subject: [PATCH 09/32] Update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index a3fcb825ea668..f15c9ef6ef523 100644 --- a/AUTHORS +++ b/AUTHORS @@ -94,3 +94,4 @@ Twin Sun, LLC Taskulu LDA Jonathan Joelson Elsabe Ros +Tomasz Gucio \ No newline at end of file From aae50b3523fbfe4c1408ed044269f7ed93df77b9 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Fri, 22 Jul 2022 16:51:51 +0200 Subject: [PATCH 10/32] Add _webDisablingTextShortcuts shortcuts --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 4 ++++ 1 file changed, 4 insertions(+) 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 63a79e10c637a..b427dae38057b 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -412,6 +412,10 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.home, shift: true): const DoNothingAndStopPropagationTextIntent(), const SingleActivator(LogicalKeyboardKey.end, control: true): const DoNothingAndStopPropagationTextIntent(), const SingleActivator(LogicalKeyboardKey.home, control: true): const DoNothingAndStopPropagationTextIntent(), + const SingleActivator(LogicalKeyboardKey.pageUp): const DoNothingAndStopPropagationTextIntent(), + const SingleActivator(LogicalKeyboardKey.pageDown): const DoNothingAndStopPropagationTextIntent(), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const DoNothingAndStopPropagationTextIntent(), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const DoNothingAndStopPropagationTextIntent(), const SingleActivator(LogicalKeyboardKey.space): const DoNothingAndStopPropagationTextIntent(), const SingleActivator(LogicalKeyboardKey.enter): const DoNothingAndStopPropagationTextIntent(), const SingleActivator(LogicalKeyboardKey.keyX, control: true): const DoNothingAndStopPropagationTextIntent(), From 4a2716b749e3db1f076f1f4d3cb60edaef0eefbf Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Fri, 22 Jul 2022 18:20:42 +0200 Subject: [PATCH 11/32] Enable caret move with Alt+PageUp/Down on Cupertino platforms --- .../default_text_editing_shortcuts.dart | 5 + .../widgets/editable_text_shortcuts_test.dart | 37 +---- .../test/widgets/editable_text_test.dart | 149 +++++++++--------- 3 files changed, 87 insertions(+), 104 deletions(-) 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 b427dae38057b..db2b3aed6d342 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -311,6 +311,11 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: false), const SingleActivator(LogicalKeyboardKey.end, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: true), + const SingleActivator(LogicalKeyboardKey.pageUp, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.keyX, meta: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard), const SingleActivator(LogicalKeyboardKey.keyC, meta: true): CopySelectionTextIntent.copy, const SingleActivator(LogicalKeyboardKey.keyV, meta: true): const PasteTextIntent(SelectionChangedCause.keyboard), diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index 1ed5ec579a2a0..5916eb8f0dc44 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1445,15 +1445,6 @@ void main() { reason: activator.toString(), ); } - }, variant: TargetPlatformVariant.all()); - - testWidgets('at start with page up', (WidgetTester tester) async { - controller.text = testText; - controller.selection = const TextSelection.collapsed( - offset: 0, - ); - - await tester.pumpWidget(buildEditableText()); for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageUp)) { await sendKeyCombination(tester, activator); @@ -1466,7 +1457,7 @@ void main() { reason: activator.toString(), ); } - }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); + }, variant: TargetPlatformVariant.all()); testWidgets('at end', (WidgetTester tester) async { controller.text = testText; @@ -1495,24 +1486,6 @@ void main() { } }, variant: TargetPlatformVariant.all()); - testWidgets('at end with page down', (WidgetTester tester) async { - controller.text = testText; - controller.selection = const TextSelection.collapsed( - offset: 72, - ); - - await tester.pumpWidget(buildEditableText()); - - for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.pageDown)) { - await sendKeyCombination(tester, activator); - await tester.pump(); - - expect(controller.text, testText); - expect(controller.selection.baseOffset, 72, reason: activator.toString()); - expect(controller.selection.extentOffset, 72, reason: activator.toString()); - } - }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); - testWidgets('run', (WidgetTester tester) async { controller.text = 'aa\n' // 3 @@ -1608,6 +1581,8 @@ void main() { '${"aaa\n" * 50}' 'aaaa'; + final bool isApple = defaultTargetPlatform == TargetPlatform.macOS || defaultTargetPlatform == TargetPlatform.iOS; + controller.selection = const TextSelection.collapsed(offset: 2); await tester.pumpWidget(buildEditableText()); @@ -1618,7 +1593,7 @@ void main() { affinity: TextAffinity.upstream, )); - await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown)); + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown, alt: isApple)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 81)); @@ -1626,13 +1601,13 @@ void main() { await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 77)); - await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp)); + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp, alt: isApple)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed( offset: 4, affinity: TextAffinity.upstream, )); - }, variant: TargetPlatformVariant.all(excluding: { TargetPlatform.iOS, TargetPlatform.macOS })); + }, variant: TargetPlatformVariant.all()); testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index af26936614010..98c4609b7e3ed 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5901,90 +5901,93 @@ void main() { reason: 'on $platform', ); - // Skip page down/up tests on Cupertino platforms as these keys don't - // move the caret. - if (defaultTargetPlatform != TargetPlatform.iOS - && defaultTargetPlatform != TargetPlatform.macOS) { - // Move down by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageDown, - ], - targetPlatform: defaultTargetPlatform, - ); + // On Cupertino platforms, caret moves by page with Alt + PageDown/Up. + final bool isCupertino = defaultTargetPlatform == TargetPlatform.macOS + || defaultTargetPlatform == TargetPlatform.iOS; - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 55, - ), + // Move down by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + wordModifier: isCupertino, + targetPlatform: defaultTargetPlatform, + ); + + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 55, ), - reason: 'on $platform', - ); + ), + reason: 'on $platform', + ); - // Move up by page (to start). - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageUp, - ], - targetPlatform: defaultTargetPlatform, - ); + // Move up by page (to start). + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + wordModifier: isCupertino, + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 0, - ), + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, ), - reason: 'on $platform', - ); + ), + reason: 'on $platform', + ); - // Select towards end by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageDown, - ], - shift: true, - targetPlatform: defaultTargetPlatform, - ); + // Select towards end by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageDown, + ], + shift: true, + wordModifier: isCupertino, + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection( - baseOffset: 0, - extentOffset: 55, - affinity: TextAffinity.upstream, - ), + expect( + selection, + equals( + const TextSelection( + baseOffset: 0, + extentOffset: 55, + affinity: TextAffinity.upstream, ), - reason: 'on $platform', - ); + ), + reason: 'on $platform', + ); - // Change selection extent towards start by page. - await sendKeys( - tester, - [ - LogicalKeyboardKey.pageUp, - ], - shift: true, - targetPlatform: defaultTargetPlatform, - ); + // Change selection extent towards start by page. + await sendKeys( + tester, + [ + LogicalKeyboardKey.pageUp, + ], + shift: true, + wordModifier: isCupertino, + targetPlatform: defaultTargetPlatform, + ); - expect( - selection, - equals( - const TextSelection.collapsed( - offset: 0, - ), + expect( + selection, + equals( + const TextSelection.collapsed( + offset: 0, ), - reason: 'on $platform', - ); - } + ), + reason: 'on $platform', + ); // Jump forward three words. await sendKeys( From 688e98cde4439b8d228e1d40d1c43b7f7be52903 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Sat, 23 Jul 2022 11:08:56 +0200 Subject: [PATCH 12/32] Fix tests --- .../flutter/test/widgets/editable_text_shortcuts_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index 5916eb8f0dc44..1e56b6f9db3dc 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1593,7 +1593,7 @@ void main() { affinity: TextAffinity.upstream, )); - await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown, alt: isApple)); + await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageDown, alt: isApple)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 81)); @@ -1601,7 +1601,7 @@ void main() { await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 77)); - await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp, alt: isApple)); + await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageUp, alt: isApple)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed( offset: 4, From 14d9b78d1940eedd7855567835234ce7d375a702 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 16:18:03 +0200 Subject: [PATCH 13/32] Fix macOS test --- .../flutter/test/widgets/editable_text_test.dart | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 7b53945da165f..fe46c085cd540 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5923,10 +5923,6 @@ void main() { reason: 'on $platform', ); - // On Cupertino platforms, caret moves by page with Alt + PageDown/Up. - final bool isCupertino = defaultTargetPlatform == TargetPlatform.macOS - || defaultTargetPlatform == TargetPlatform.iOS; - // Move down by page. await sendKeys( tester, @@ -5937,12 +5933,14 @@ void main() { targetPlatform: defaultTargetPlatform, ); + // On macOS platforms, there's no NSStandardKeyBindingResponding + // for move selection by page + collapse. expect( selection, equals( - const TextSelection.collapsed( - offset: 55, - ), + defaultTargetPlatform == TargetPlatform.macOS + ? const TextSelection.collapsed(offset: 55) + : const TextSelection.collapsed(offset: 0), ), reason: 'on $platform', ); @@ -5974,7 +5972,6 @@ void main() { LogicalKeyboardKey.pageDown, ], shift: true, - wordModifier: isCupertino, targetPlatform: defaultTargetPlatform, ); @@ -5997,7 +5994,6 @@ void main() { LogicalKeyboardKey.pageUp, ], shift: true, - wordModifier: isCupertino, targetPlatform: defaultTargetPlatform, ); From b49ca21c6fb123b0deacb5d623e837e2a1ecf1c2 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 16:18:44 +0200 Subject: [PATCH 14/32] Really fix this test --- packages/flutter/test/widgets/editable_text_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index fe46c085cd540..9d512a289fa60 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5939,8 +5939,8 @@ void main() { selection, equals( defaultTargetPlatform == TargetPlatform.macOS - ? const TextSelection.collapsed(offset: 55) - : const TextSelection.collapsed(offset: 0), + ? const TextSelection.collapsed(offset: 0) + : const TextSelection.collapsed(offset: 55), ), reason: 'on $platform', ); From ce80c8be87358e8084874649ab337d7a093cf87d Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 16:35:16 +0200 Subject: [PATCH 15/32] Fix the fix --- packages/flutter/test/widgets/editable_text_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 9d512a289fa60..16d9f5df402fc 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5929,7 +5929,6 @@ void main() { [ LogicalKeyboardKey.pageDown, ], - wordModifier: isCupertino, targetPlatform: defaultTargetPlatform, ); @@ -5951,7 +5950,6 @@ void main() { [ LogicalKeyboardKey.pageUp, ], - wordModifier: isCupertino, targetPlatform: defaultTargetPlatform, ); From ca70cde9e7107fb4115dbdf13999800feecab5f4 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 16:35:36 +0200 Subject: [PATCH 16/32] Fix the comment too --- packages/flutter/test/widgets/editable_text_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index 16d9f5df402fc..7eebacfc7115c 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -5932,7 +5932,7 @@ void main() { targetPlatform: defaultTargetPlatform, ); - // On macOS platforms, there's no NSStandardKeyBindingResponding + // On macOS, there's no NSStandardKeyBindingResponding // for move selection by page + collapse. expect( selection, From 489b4c461a402616abd27079d967f0716bd06533 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 19:17:25 +0200 Subject: [PATCH 17/32] Enable regular page down/up on iOS --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 8 ++++---- .../test/widgets/editable_text_shortcuts_test.dart | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) 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 30f2052732a9f..72740b4d29c56 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -340,10 +340,10 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: false), const SingleActivator(LogicalKeyboardKey.end, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: true), - const SingleActivator(LogicalKeyboardKey.pageUp, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageUp, shift: true, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageDown, shift: true, alt: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.keyX, meta: true): const CopySelectionTextIntent.cut(SelectionChangedCause.keyboard), const SingleActivator(LogicalKeyboardKey.keyC, meta: true): CopySelectionTextIntent.copy, diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index de9992e3591a5..c7b4b39bf0163 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1582,8 +1582,6 @@ void main() { '${"aaa\n" * 50}' 'aaaa'; - final bool isApple = defaultTargetPlatform == TargetPlatform.macOS || defaultTargetPlatform == TargetPlatform.iOS; - controller.selection = const TextSelection.collapsed(offset: 2); await tester.pumpWidget(buildEditableText()); @@ -1594,7 +1592,7 @@ void main() { affinity: TextAffinity.upstream, )); - await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageDown, alt: isApple)); + await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageDown)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 81)); @@ -1602,13 +1600,13 @@ void main() { await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 77)); - await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageUp, alt: isApple)); + await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageUp)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed( offset: 4, affinity: TextAffinity.upstream, )); - }, variant: TargetPlatformVariant.all()); + }, variant: TargetPlatformVariant.all(excluding: TargetPlatform.macOS)); // intended: on macOS Page Up/Down only scrolls testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = From 45d14567d17b6b7ffbcd7b71cd6d90ff9f76f98e Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 19:18:19 +0200 Subject: [PATCH 18/32] Update macOS intents --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 72740b4d29c56..ba2e9c506359e 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -554,8 +554,8 @@ Intent? intentForMacOSSelector(String selectorName) { // TODO(knopp): Page Up/Down intents are missing (https://github.com/flutter/flutter/pull/105497) 'scrollPageUp:': ScrollToDocumentBoundaryIntent(forward: false), 'scrollPageDown:': ScrollToDocumentBoundaryIntent(forward: true), - 'pageUpAndModifySelection': ExpandSelectionToDocumentBoundaryIntent(forward: false), - 'pageDownAndModifySelection:': ExpandSelectionToDocumentBoundaryIntent(forward: true), + 'pageUpAndModifySelection': ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + 'pageDownAndModifySelection:': ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), // Escape key when there's no IME selection popup. 'cancelOperation:': DismissIntent(), From 2d36a0ff5d102a28a4bd37ae18cc890cd6f8cb91 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 23:16:10 +0200 Subject: [PATCH 19/32] Fix test (again!) --- packages/flutter/test/widgets/editable_text_shortcuts_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index c7b4b39bf0163..fd28aaae5bdc3 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1606,7 +1606,7 @@ void main() { offset: 4, affinity: TextAffinity.upstream, )); - }, variant: TargetPlatformVariant.all(excluding: TargetPlatform.macOS)); // intended: on macOS Page Up/Down only scrolls + }, variant: TargetPlatformVariant.all(excluding: {TargetPlatform.macOS})); // intended: on macOS Page Up/Down only scrolls testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = From 2fe0e12b1a9e2bb4f66b3fa334e9ccc3c3820f25 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Wed, 10 Aug 2022 23:50:16 +0200 Subject: [PATCH 20/32] Lints --- .../flutter/test/widgets/editable_text_shortcuts_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index fd28aaae5bdc3..b275e34f01ee7 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1592,7 +1592,7 @@ void main() { affinity: TextAffinity.upstream, )); - await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageDown)); + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageDown)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 81)); @@ -1600,7 +1600,7 @@ void main() { await tester.pump(); expect(controller.selection, const TextSelection.collapsed(offset: 77)); - await sendKeyCombination(tester, SingleActivator(LogicalKeyboardKey.pageUp)); + await sendKeyCombination(tester, const SingleActivator(LogicalKeyboardKey.pageUp)); await tester.pump(); expect(controller.selection, const TextSelection.collapsed( offset: 4, From 55a6a41dbf3bd16da2eab8a677c7c3d6dc1ff090 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 01:27:59 +0200 Subject: [PATCH 21/32] Remove unnecessary consts --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 b86571c816c51..b5ef5fd8b3983 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -417,8 +417,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget { SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): DoNothingAndStopPropagationTextIntent(), - SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const DoNothingAndStopPropagationTextIntent(), - SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const DoNothingAndStopPropagationTextIntent(), + SingleActivator(LogicalKeyboardKey.pageUp, shift: true): DoNothingAndStopPropagationTextIntent(), + SingleActivator(LogicalKeyboardKey.pageDown, shift: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.end, shift: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.home, shift: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowDown): DoNothingAndStopPropagationTextIntent(), @@ -429,8 +429,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget { SingleActivator(LogicalKeyboardKey.arrowRight, control: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): DoNothingAndStopPropagationTextIntent(), - SingleActivator(LogicalKeyboardKey.pageUp): const DoNothingAndStopPropagationTextIntent(), - SingleActivator(LogicalKeyboardKey.pageDown): const DoNothingAndStopPropagationTextIntent(), + SingleActivator(LogicalKeyboardKey.pageUp): DoNothingAndStopPropagationTextIntent(), + SingleActivator(LogicalKeyboardKey.pageDown): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.end): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.home): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.end, control: true): DoNothingAndStopPropagationTextIntent(), From 8412c39e579e821d49b93040ae1ff87557dbef32 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 01:33:26 +0200 Subject: [PATCH 22/32] Update default_text_editing_shortcuts.dart --- .../lib/src/widgets/default_text_editing_shortcuts.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 b5ef5fd8b3983..c2067a06aeb53 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -263,10 +263,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // macOS document shortcuts: https://support.apple.com/en-us/HT201236. // The macOS shortcuts uses different word/line modifiers than most other // platforms. - static final Map _macShortcuts = _iOSShortcuts; - - // There is no complete documentation of iOS shortcuts. - static final Map _iOSShortcuts = { + static final Map _macShortcuts = { for (final bool pressShift in const [true, false]) ...{ SingleActivator(LogicalKeyboardKey.backspace, shift: pressShift): const DeleteCharacterIntent(forward: false), @@ -345,6 +342,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // * Control + shift? + Z }; + // There is no complete documentation of iOS shortcuts: use macOS ones. + static final Map _iOSShortcuts = _macShortcuts; // The following key combinations have no effect on text editing on this // platform: From d70df7283775b3fc1214b095ec7e8c9bcc1759ce Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 01:36:56 +0200 Subject: [PATCH 23/32] Exclude iOS from test --- packages/flutter/test/widgets/editable_text_shortcuts_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart index 550d3c8ba5c4c..24ec74e8453f8 100644 --- a/packages/flutter/test/widgets/editable_text_shortcuts_test.dart +++ b/packages/flutter/test/widgets/editable_text_shortcuts_test.dart @@ -1610,7 +1610,7 @@ void main() { offset: 4, affinity: TextAffinity.upstream, )); - }, variant: TargetPlatformVariant.all(excluding: {TargetPlatform.macOS})); // intended: on macOS Page Up/Down only scrolls + }, variant: TargetPlatformVariant.all(excluding: {TargetPlatform.iOS, TargetPlatform.macOS})); // intended: on macOS Page Up/Down only scrolls testWidgets('run can be interrupted by layout changes', (WidgetTester tester) async { controller.text = From c2a0fd049730308e50557ad51da48d753f43d57e Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 01:45:50 +0200 Subject: [PATCH 24/32] No page down/up on iOS --- packages/flutter/test/widgets/editable_text_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/test/widgets/editable_text_test.dart b/packages/flutter/test/widgets/editable_text_test.dart index a4a352411faf0..a4e6e8475a56c 100644 --- a/packages/flutter/test/widgets/editable_text_test.dart +++ b/packages/flutter/test/widgets/editable_text_test.dart @@ -6003,12 +6003,12 @@ void main() { targetPlatform: defaultTargetPlatform, ); - // On macOS, there's no NSStandardKeyBindingResponding - // for move selection by page + collapse. + // On macOS, pageDown/Up don't change selection. expect( selection, equals( defaultTargetPlatform == TargetPlatform.macOS + || defaultTargetPlatform == TargetPlatform.iOS ? const TextSelection.collapsed(offset: 0) : const TextSelection.collapsed(offset: 55), ), From 061f1fe93809dfdc77fe25372f0e695576ee9f61 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:23:11 +0200 Subject: [PATCH 25/32] Remove Page Down / Up shortcut for iOS --- .../default_text_editing_shortcuts.dart | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) 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 c2067a06aeb53..940cd96c37892 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -171,13 +171,13 @@ class DefaultTextEditingShortcuts extends StatelessWidget { SingleActivator(LogicalKeyboardKey.delete, alt: true, shift: pressShift): const DeleteToLineBreakIntent(forward: true), }, - // Arrow: Move Selection. + // Arrow: Move selection. const SingleActivator(LogicalKeyboardKey.arrowLeft): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.arrowRight): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.arrowUp): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.arrowDown): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: true, collapseSelection: true), - // Shift + Arrow: Extend Selection. + // Shift + Arrow: Extend selection. const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: false), @@ -199,8 +199,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: true, collapseSelection: false), - const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + // Shift + Page Up / Down: Extend selection by pge. const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), @@ -233,12 +232,18 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // * Shift + home // * Meta + shift? + delete // * Meta + shift? + backspace - static final Map _androidShortcuts = _commonShortcuts; + static final Map _androidShortcuts = { + ..._commonShortcuts, + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + }; static final Map _fuchsiaShortcuts = _androidShortcuts; static final Map _linuxShortcuts = { ..._commonShortcuts, + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.home): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.end): const ExtendSelectionToLineBreakIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: false), @@ -279,7 +284,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowUp): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.arrowDown): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: true, collapseSelection: true), - // Shift + Arrow: Extend Selection. + // Shift + Arrow: Extend selection. const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: false), @@ -359,6 +364,8 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // * Meta + backspace static final Map _windowsShortcuts = { ..._commonShortcuts, + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.home): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: true, continuesAtWrap: true), const SingleActivator(LogicalKeyboardKey.end): const ExtendSelectionToLineBreakIntent(forward: true, collapseSelection: true, continuesAtWrap: true), const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: false, continuesAtWrap: true), @@ -394,7 +401,6 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.keyA, meta: true): const DoNothingAndStopPropagationTextIntent(), }; - static const Map _commonDisablingTextShortcuts = { SingleActivator(LogicalKeyboardKey.arrowDown, alt: true): DoNothingAndStopPropagationTextIntent(), SingleActivator(LogicalKeyboardKey.arrowLeft, alt: true): DoNothingAndStopPropagationTextIntent(), From d1b772b19044ce7e6b82a1acd7e401b6a4ff837d Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 11:27:59 +0200 Subject: [PATCH 26/32] Fix macOS/iOS page up/down shortcut removal --- .../widgets/default_text_editing_shortcuts.dart | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) 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 940cd96c37892..f4956d4854040 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -199,7 +199,11 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, control: true): const ExtendSelectionToNextWordBoundaryIntent(forward: true, collapseSelection: false), - // Shift + Page Up / Down: Extend selection by pge. + // Page Up / Down: Move selection by page. + const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), + const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), + + // Shift + Page Up / Down: Extend selection by page. const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), @@ -232,18 +236,12 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // * Shift + home // * Meta + shift? + delete // * Meta + shift? + backspace - static final Map _androidShortcuts = { - ..._commonShortcuts, - const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - }; + static final Map _androidShortcuts = _commonShortcuts; static final Map _fuchsiaShortcuts = _androidShortcuts; static final Map _linuxShortcuts = { ..._commonShortcuts, - const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.home): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.end): const ExtendSelectionToLineBreakIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: false), @@ -317,8 +315,6 @@ class DefaultTextEditingShortcuts extends StatelessWidget { const SingleActivator(LogicalKeyboardKey.home, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: false), const SingleActivator(LogicalKeyboardKey.end, shift: true): const ExpandSelectionToDocumentBoundaryIntent(forward: true), - const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), - const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), From 31c707730f0e93168d6f2d1f59d5efa73241eccb Mon Sep 17 00:00:00 2001 From: Tomasz Gucio <72562119+tgucio@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:08:20 +0200 Subject: [PATCH 27/32] Trailing spaces --- .../flutter/lib/src/widgets/default_text_editing_shortcuts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f4956d4854040..5fad389344bf1 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -202,7 +202,7 @@ class DefaultTextEditingShortcuts extends StatelessWidget { // Page Up / Down: Move selection by page. const SingleActivator(LogicalKeyboardKey.pageUp): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: true), const SingleActivator(LogicalKeyboardKey.pageDown): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: true), - + // Shift + Page Up / Down: Extend selection by page. const SingleActivator(LogicalKeyboardKey.pageUp, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), const SingleActivator(LogicalKeyboardKey.pageDown, shift: true): const ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), From 1fcb315194a0e61f38f38c42e6e431bfaeae11fe Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Tue, 25 Oct 2022 15:38:51 +0200 Subject: [PATCH 28/32] Fix missing colon in selector name --- .../flutter/lib/src/widgets/default_text_editing_shortcuts.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5fad389344bf1..b8c9cb41f9532 100644 --- a/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart +++ b/packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart @@ -560,7 +560,7 @@ Intent? intentForMacOSSelector(String selectorName) { // TODO(knopp): Page Up/Down intents are missing (https://github.com/flutter/flutter/pull/105497) 'scrollPageUp:': ScrollToDocumentBoundaryIntent(forward: false), 'scrollPageDown:': ScrollToDocumentBoundaryIntent(forward: true), - 'pageUpAndModifySelection': ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), + 'pageUpAndModifySelection:': ExtendSelectionVerticallyToAdjacentPageIntent(forward: false, collapseSelection: false), 'pageDownAndModifySelection:': ExtendSelectionVerticallyToAdjacentPageIntent(forward: true, collapseSelection: false), // Escape key when there's no IME selection popup. From c8c8467b4f69598df33f50e1389d03438fffc73f Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Tue, 25 Oct 2022 15:48:45 +0200 Subject: [PATCH 29/32] Nits in comments --- packages/flutter/lib/src/rendering/editable.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/flutter/lib/src/rendering/editable.dart b/packages/flutter/lib/src/rendering/editable.dart index 2709b4dfb7389..08da752aa6e5e 100644 --- a/packages/flutter/lib/src/rendering/editable.dart +++ b/packages/flutter/lib/src/rendering/editable.dart @@ -108,7 +108,7 @@ class TextSelectionPoint { /// false. Similarly the [moveNext] method moves the caret to the next line, and /// returns false if the caret is already on the last line. /// -/// The [moveByOffset] takes a pixel offset from the current position to move +/// The [moveByOffset] method takes a pixel offset from the current position to move /// the caret up or down. /// /// If the underlying paragraph's layout changes, [isValid] becomes false and @@ -208,6 +208,7 @@ class VerticalCaretMovementRun extends Iterator { /// by pixel [offset]. /// /// If [offset] is negative, move backward; otherwise move forward. + /// /// Returns true and updates [current] if successful. bool moveByOffset(double offset) { final Offset initialOffset = _currentOffset; From a4282260971bf6150dff6fa7a85ebb569b1f2103 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Tue, 25 Oct 2022 15:57:26 +0200 Subject: [PATCH 30/32] Add missing call to _adjacentPageAction.stop...RunIfSelectionChanges() --- packages/flutter/lib/src/widgets/editable_text.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index b4072b17a9754..17b9f94bef763 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -3109,6 +3109,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien // to avoid this setState(). setState(() { /* We use widget.controller.value in build(). */ }); _adjacentLineAction.stopCurrentVerticalRunIfSelectionChanges(); + _adjacentPageAction.stopCurrentVerticalRunIfSelectionChanges(); } void _handleFocusChanged() { From b1295f46d0c1799e11f9f7caa479ba0aba8fe0a7 Mon Sep 17 00:00:00 2001 From: Tomasz Gucio Date: Tue, 25 Oct 2022 15:59:53 +0200 Subject: [PATCH 31/32] Remove perentheses in ternary --- packages/flutter/lib/src/widgets/editable_text.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 17b9f94bef763..33c0310d086fc 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -4656,7 +4656,7 @@ class _UpdateTextSelectionToAdjacentLineAction Date: Tue, 25 Oct 2022 16:25:25 +0200 Subject: [PATCH 32/32] Merge line and page actions --- .../lib/src/widgets/editable_text.dart | 86 +++---------------- .../widgets/editable_text_shortcuts_test.dart | 6 +- 2 files changed, 13 insertions(+), 79 deletions(-) diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 33c0310d086fc..8307aa7bc99e3 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -3108,8 +3108,7 @@ class EditableTextState extends State with AutomaticKeepAliveClien // TODO(abarth): Teach RenderEditable about ValueNotifier // to avoid this setState(). setState(() { /* We use widget.controller.value in build(). */ }); - _adjacentLineAction.stopCurrentVerticalRunIfSelectionChanges(); - _adjacentPageAction.stopCurrentVerticalRunIfSelectionChanges(); + _verticalSelectionUpdateAction.stopCurrentVerticalRunIfSelectionChanges(); } void _handleFocusChanged() { @@ -3592,9 +3591,8 @@ class EditableTextState extends State with AutomaticKeepAliveClien } late final Action _updateSelectionAction = CallbackAction(onInvoke: _updateSelection); - late final _UpdateTextSelectionToAdjacentLineAction _adjacentLineAction = _UpdateTextSelectionToAdjacentLineAction(this); - - late final _UpdateTextSelectionToAdjacentPageAction _adjacentPageAction = _UpdateTextSelectionToAdjacentPageAction(this); + late final _UpdateTextSelectionVerticallyAction _verticalSelectionUpdateAction = + _UpdateTextSelectionVerticallyAction(this); void _expandSelectionToDocumentBoundary(ExpandSelectionToDocumentBoundaryIntent intent) { final TextBoundary textBoundary = _documentBoundary(intent); @@ -3722,8 +3720,8 @@ class EditableTextState extends State with AutomaticKeepAliveClien ExtendSelectionToLineBreakIntent: _makeOverridable(_UpdateTextSelectionAction(this, true, _linebreak)), ExpandSelectionToLineBreakIntent: _makeOverridable(CallbackAction(onInvoke: _expandSelectionToLinebreak)), ExpandSelectionToDocumentBoundaryIntent: _makeOverridable(CallbackAction(onInvoke: _expandSelectionToDocumentBoundary)), - ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_adjacentLineAction), - ExtendSelectionVerticallyToAdjacentPageIntent: _makeOverridable(_adjacentPageAction), + ExtendSelectionVerticallyToAdjacentLineIntent: _makeOverridable(_verticalSelectionUpdateAction), + ExtendSelectionVerticallyToAdjacentPageIntent: _makeOverridable(_verticalSelectionUpdateAction), ExtendSelectionToDocumentBoundaryIntent: _makeOverridable(_UpdateTextSelectionAction(this, true, _documentBoundary)), ExtendSelectionToNextWordBoundaryOrCaretLocationIntent: _makeOverridable(_ExtendSelectionOrCaretPositionAction(this, _nextWordBoundary)), ScrollToDocumentBoundaryIntent: _makeOverridable(CallbackAction(onInvoke: _scrollToDocumentBoundary)), @@ -4610,73 +4608,8 @@ class _ExtendSelectionOrCaretPositionAction extends ContextAction state.widget.selectionEnabled && state._value.selection.isValid; } -class _UpdateTextSelectionToAdjacentLineAction extends ContextAction { - _UpdateTextSelectionToAdjacentLineAction(this.state); - - final EditableTextState state; - - VerticalCaretMovementRun? _verticalMovementRun; - TextSelection? _runSelection; - - void stopCurrentVerticalRunIfSelectionChanges() { - final TextSelection? runSelection = _runSelection; - if (runSelection == null) { - assert(_verticalMovementRun == null); - return; - } - _runSelection = state._value.selection; - final TextSelection currentSelection = state.widget.controller.selection; - final bool continueCurrentRun = currentSelection.isValid && currentSelection.isCollapsed - && currentSelection.baseOffset == runSelection.baseOffset - && currentSelection.extentOffset == runSelection.extentOffset; - if (!continueCurrentRun) { - _verticalMovementRun = null; - _runSelection = null; - } - } - - @override - void invoke(T intent, [BuildContext? context]) { - assert(state._value.selection.isValid); - - final bool collapseSelection = intent.collapseSelection || !state.widget.selectionEnabled; - final TextEditingValue value = state._textEditingValueforTextLayoutMetrics; - if (!value.selection.isValid) { - return; - } - - if (_verticalMovementRun?.isValid == false) { - _verticalMovementRun = null; - _runSelection = null; - } - - final VerticalCaretMovementRun currentRun = _verticalMovementRun - ?? state.renderEditable.startVerticalCaretMovement(state.renderEditable.selection!.extent); - - final bool shouldMove = intent.forward ? currentRun.moveNext() : currentRun.movePrevious(); - final TextPosition newExtent = shouldMove - ? currentRun.current - : intent.forward ? TextPosition(offset: state._value.text.length) : const TextPosition(offset: 0); - final TextSelection newSelection = collapseSelection - ? TextSelection.fromPosition(newExtent) - : value.selection.extendTo(newExtent); - - Actions.invoke( - context!, - UpdateSelectionIntent(value, newSelection, SelectionChangedCause.keyboard), - ); - if (state._value.selection == newSelection) { - _verticalMovementRun = currentRun; - _runSelection = newSelection; - } - } - - @override - bool get isActionEnabled => state._value.selection.isValid; -} - -class _UpdateTextSelectionToAdjacentPageAction extends ContextAction { - _UpdateTextSelectionToAdjacentPageAction(this.state); +class _UpdateTextSelectionVerticallyAction extends ContextAction { + _UpdateTextSelectionVerticallyAction(this.state); final EditableTextState state; @@ -4718,8 +4651,9 @@ class _UpdateTextSelectionToAdjacentPageAction{TargetPlatform.iOS, TargetPlatform.macOS})); // intended: on macOS Page Up/Down only scrolls