Skip to content

Commit

Permalink
Some MacOS control key shortcuts (#103936)
Browse files Browse the repository at this point in the history
  • Loading branch information
justinmc authored May 18, 2022
1 parent 2038180 commit 8f7e41a
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
const SingleActivator(LogicalKeyboardKey.keyA, meta: true): const SelectAllTextIntent(SelectionChangedCause.keyboard),
const SingleActivator(LogicalKeyboardKey.keyZ, meta: true): const UndoTextIntent(SelectionChangedCause.keyboard),
const SingleActivator(LogicalKeyboardKey.keyZ, shift: true, meta: true): const RedoTextIntent(SelectionChangedCause.keyboard),
const SingleActivator(LogicalKeyboardKey.keyE, control: true): const ExtendSelectionToLineBreakIntent(forward: true, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.keyA, control: true): const ExtendSelectionToLineBreakIntent(forward: false, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.keyF, control: true): const ExtendSelectionByCharacterIntent(forward: true, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.keyB, control: true): const ExtendSelectionByCharacterIntent(forward: false, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.keyN, control: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: true, collapseSelection: true),
const SingleActivator(LogicalKeyboardKey.keyP, control: true): const ExtendSelectionVerticallyToAdjacentLineIntent(forward: false, collapseSelection: true),
// These keys should go to the IME when a field is focused, not to other
// Shortcuts.
const SingleActivator(LogicalKeyboardKey.space): const DoNothingAndStopPropagationTextIntent(),
Expand Down
215 changes: 215 additions & 0 deletions packages/flutter/test/widgets/editable_text_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11982,6 +11982,221 @@ void main() {
expect(tester.takeException(), null);
// On web, the text selection toolbar cut button is handled by the browser.
}, skip: kIsWeb); // [intended]

group('Mac document shortcuts', () {
testWidgets('ctrl-A/E', (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,
);
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().black.subtitle1!,
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
textAlign: TextAlign.right,
),
),
),
));

await tester.pump(); // Wait for autofocus to take effect.

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 0);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyE, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(
controller.selection,
equals(
const TextSelection.collapsed(
offset: 19,
affinity: TextAffinity.upstream,
),
),
reason: 'on $platform',
);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyA, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(
controller.selection,
equals(
const TextSelection.collapsed(
offset: 0,
),
),
reason: 'on $platform',
);
},
skip: kIsWeb, // [intended] on web these keys are handled by the browser.
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
);

testWidgets('ctrl-F/B', (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,
);
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().black.subtitle1!,
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
textAlign: TextAlign.right,
),
),
),
));

await tester.pump(); // Wait for autofocus to take effect.

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 0);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyF, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 1);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyB, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 0);
},
skip: kIsWeb, // [intended] on web these keys are handled by the browser.
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
);

testWidgets('ctrl-N/P', (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,
);
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().black.subtitle1!,
cursorColor: Colors.blue,
backgroundCursorColor: Colors.grey,
selectionControls: materialTextSelectionControls,
keyboardType: TextInputType.text,
textAlign: TextAlign.right,
),
),
),
));

await tester.pump(); // Wait for autofocus to take effect.

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 0);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyN, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 20);

await tester.sendKeyDownEvent(
LogicalKeyboardKey.controlLeft,
platform: platform,
);
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.keyP, platform: platform);
await tester.pump();
await tester.sendKeyUpEvent(LogicalKeyboardKey.controlLeft, platform: platform);
await tester.pump();

expect(controller.selection.isCollapsed, isTrue);
expect(controller.selection.baseOffset, 0);
},
skip: kIsWeb, // [intended] on web these keys are handled by the browser.
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
);
});
}

class UnsettableController extends TextEditingController {
Expand Down

0 comments on commit 8f7e41a

Please sign in to comment.