Unverified Commit 9e9ca698 authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Home/End key support for Linux (#87294)

Support for more desktop keyboard keys/shortcuts.
parent a17723d4
......@@ -346,14 +346,16 @@ 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): MoveSelectionRightByLineTextIntent(),
SingleActivator(LogicalKeyboardKey.home): MoveSelectionLeftByLineTextIntent(),
SingleActivator(LogicalKeyboardKey.end, shift: true): ExtendSelectionRightByLineTextIntent(),
SingleActivator(LogicalKeyboardKey.home, shift: true): ExtendSelectionLeftByLineTextIntent(),
SingleActivator(LogicalKeyboardKey.keyX, control: true): CutSelectionTextIntent(),
SingleActivator(LogicalKeyboardKey.keyC, control: true): CopySelectionTextIntent(),
SingleActivator(LogicalKeyboardKey.keyV, control: true): PasteTextIntent(),
SingleActivator(LogicalKeyboardKey.keyA, control: true): SelectAllTextIntent(),
// The following key combinations have no effect on text editing on this
// platform:
// * End
// * Home
// * Meta + X
// * Meta + C
// * Meta + V
......@@ -366,8 +368,6 @@ class DefaultTextEditingShortcuts extends Shortcuts {
// * Meta + shift + arrow left
// * Meta + shift + arrow right
// * Meta + shift + arrow up
// * Shift + end
// * Shift + home
// * Meta + delete
// * Meta + backspace
};
......
......@@ -5135,6 +5135,279 @@ void main() {
variant: TargetPlatformVariant.all(),
);
testWidgets('home/end keys', (WidgetTester tester) async {
final String targetPlatformString = defaultTargetPlatform.toString();
final String platform = targetPlatformString.substring(targetPlatformString.indexOf('.') + 1).toLowerCase();
final TextEditingController controller = TextEditingController(text: testText);
controller.selection = const TextSelection(
baseOffset: 0,
extentOffset: 0,
affinity: TextAffinity.upstream,
);
late TextSelection selection;
late SelectionChangedCause cause;
await tester.pumpWidget(MaterialApp(
home: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 400,
child: EditableText(
maxLines: 10,
controller: controller,
showSelectionHandles: true,
autofocus: true,
focusNode: FocusNode(),
style: Typography.material2018(platform: TargetPlatform.android).black.subtitle1!,
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
textAlign: TextAlign.right,
onSelectionChanged: (TextSelection newSelection, SelectionChangedCause? newCause) {
selection = newSelection;
cause = newCause!;
},
),
),
),
));
await tester.pump(); // Wait for autofocus to take effect.
// Move near the middle of the document.
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.arrowDown,
LogicalKeyboardKey.arrowRight,
LogicalKeyboardKey.arrowRight,
LogicalKeyboardKey.arrowRight,
],
targetPlatform: defaultTargetPlatform,
);
expect(cause, equals(SelectionChangedCause.keyboard), reason: 'on $platform');
expect(
selection,
equals(
const TextSelection.collapsed(
offset: 23,
affinity: TextAffinity.downstream,
),
),
reason: 'on $platform',
);
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.home,
],
targetPlatform: defaultTargetPlatform,
);
late final int afterHomeOffset;
late final int afterEndOffset;
late final TextAffinity afterEndAffinity;
switch (defaultTargetPlatform) {
// These platforms don't handle home/end at all.
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
case TargetPlatform.macOS:
afterHomeOffset = 23;
afterEndOffset = 23;
afterEndAffinity = TextAffinity.downstream;
break;
// These platforms go to the line start/end.
case TargetPlatform.linux:
case TargetPlatform.windows:
afterHomeOffset = 20;
afterEndOffset = 35;
afterEndAffinity = TextAffinity.upstream;
break;
}
expect(
selection,
equals(
TextSelection.collapsed(
offset: afterHomeOffset,
affinity: TextAffinity.downstream,
),
),
reason: 'on $platform',
);
expect(controller.text, equals(testText), reason: 'on $platform');
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.end,
],
targetPlatform: defaultTargetPlatform,
);
expect(
selection,
equals(
TextSelection.collapsed(
offset: afterEndOffset,
affinity: afterEndAffinity,
),
),
reason: 'on $platform',
);
expect(controller.text, equals(testText), reason: 'on $platform');
},
skip: kIsWeb,
variant: TargetPlatformVariant.all(),
);
testWidgets('shift + home/end keys', (WidgetTester tester) async {
final String targetPlatformString = defaultTargetPlatform.toString();
final String platform = targetPlatformString.substring(targetPlatformString.indexOf('.') + 1).toLowerCase();
final TextEditingController controller = TextEditingController(text: testText);
controller.selection = const TextSelection(
baseOffset: 0,
extentOffset: 0,
affinity: TextAffinity.upstream,
);
late TextSelection selection;
late SelectionChangedCause cause;
await tester.pumpWidget(MaterialApp(
home: Align(
alignment: Alignment.topLeft,
child: SizedBox(
width: 400,
child: EditableText(
maxLines: 10,
controller: controller,
showSelectionHandles: true,
autofocus: true,
focusNode: FocusNode(),
style: Typography.material2018(platform: TargetPlatform.android).black.subtitle1!,
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
textAlign: TextAlign.right,
onSelectionChanged: (TextSelection newSelection, SelectionChangedCause? newCause) {
selection = newSelection;
cause = newCause!;
},
),
),
),
));
await tester.pump();
// Move near the middle of the document.
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.arrowDown,
LogicalKeyboardKey.arrowRight,
LogicalKeyboardKey.arrowRight,
LogicalKeyboardKey.arrowRight,
],
targetPlatform: defaultTargetPlatform,
);
expect(cause, equals(SelectionChangedCause.keyboard), reason: 'on $platform');
expect(
selection,
equals(
const TextSelection.collapsed(
offset: 23,
affinity: TextAffinity.downstream,
),
),
reason: 'on $platform',
);
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.home,
],
shift: true,
targetPlatform: defaultTargetPlatform,
);
late final int afterHomeOffset;
late final int afterEndOffset;
switch (defaultTargetPlatform) {
// These platforms don't handle shift + home/end at all.
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
afterHomeOffset = 23;
afterEndOffset = 23;
break;
// These platforms go to the line start/end.
case TargetPlatform.linux:
case TargetPlatform.windows:
afterHomeOffset = 20;
afterEndOffset = 35;
break;
// Mac goes to the start/end of the document.
case TargetPlatform.macOS:
afterHomeOffset = 0;
afterEndOffset = 72;
break;
}
expect(
selection,
equals(
TextSelection(
baseOffset: 23,
extentOffset: afterHomeOffset,
affinity: TextAffinity.downstream,
),
),
reason: 'on $platform',
);
expect(controller.text, equals(testText), reason: 'on $platform');
// Move back to position 23.
controller.selection = const TextSelection.collapsed(
offset: 23,
affinity: TextAffinity.downstream,
);
await tester.pump();
await sendKeys(
tester,
<LogicalKeyboardKey>[
LogicalKeyboardKey.end,
],
shift: true,
targetPlatform: defaultTargetPlatform,
);
expect(
selection,
equals(
TextSelection(
baseOffset: 23,
extentOffset: afterEndOffset,
affinity: TextAffinity.downstream,
),
),
reason: 'on $platform',
);
expect(controller.text, equals(testText), reason: 'on $platform');
},
skip: kIsWeb,
variant: TargetPlatformVariant.all(),
);
// Regression test for https://github.com/flutter/flutter/issues/31287
testWidgets('text selection handle visibility', (WidgetTester tester) async {
// Text with two separate words to select.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment