Skip to content

Commit 98e9032

Browse files
authored
[web] Allow shift + left/right keyboard shortcuts to be handled by framework on web (#117217)
* Remove DoNothing actions for shift + left/right keyboard shorcuts on web and add tests * Fix spacing * Add select all left/right cases + tests
1 parent 0604a0e commit 98e9032

File tree

2 files changed

+142
-22
lines changed

2 files changed

+142
-22
lines changed

packages/flutter/lib/src/widgets/default_text_editing_shortcuts.dart

+6-6
Original file line numberDiff line numberDiff line change
@@ -412,16 +412,10 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
412412
SingleActivator(LogicalKeyboardKey.arrowLeft, alt: true): DoNothingAndStopPropagationTextIntent(),
413413
SingleActivator(LogicalKeyboardKey.arrowRight, alt: true): DoNothingAndStopPropagationTextIntent(),
414414
SingleActivator(LogicalKeyboardKey.arrowUp, alt: true): DoNothingAndStopPropagationTextIntent(),
415-
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, alt: true): DoNothingAndStopPropagationTextIntent(),
416-
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, alt: true): DoNothingAndStopPropagationTextIntent(),
417415
SingleActivator(LogicalKeyboardKey.arrowDown, meta: true): DoNothingAndStopPropagationTextIntent(),
418416
SingleActivator(LogicalKeyboardKey.arrowLeft, meta: true): DoNothingAndStopPropagationTextIntent(),
419417
SingleActivator(LogicalKeyboardKey.arrowRight, meta: true): DoNothingAndStopPropagationTextIntent(),
420418
SingleActivator(LogicalKeyboardKey.arrowUp, meta: true): DoNothingAndStopPropagationTextIntent(),
421-
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, meta: true): DoNothingAndStopPropagationTextIntent(),
422-
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, meta: true): DoNothingAndStopPropagationTextIntent(),
423-
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): DoNothingAndStopPropagationTextIntent(),
424-
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): DoNothingAndStopPropagationTextIntent(),
425419
SingleActivator(LogicalKeyboardKey.pageUp, shift: true): DoNothingAndStopPropagationTextIntent(),
426420
SingleActivator(LogicalKeyboardKey.pageDown, shift: true): DoNothingAndStopPropagationTextIntent(),
427421
SingleActivator(LogicalKeyboardKey.end, shift: true): DoNothingAndStopPropagationTextIntent(),
@@ -452,6 +446,12 @@ class DefaultTextEditingShortcuts extends StatelessWidget {
452446
const SingleActivator(LogicalKeyboardKey.tab, shift: true): const DoNothingAndStopPropagationTextIntent(),
453447
const SingleActivator(LogicalKeyboardKey.arrowDown, shift: true, alt: true): const DoNothingAndStopPropagationTextIntent(),
454448
const SingleActivator(LogicalKeyboardKey.arrowUp, shift: true, alt: true): const DoNothingAndStopPropagationTextIntent(),
449+
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true): const DoNothingAndStopPropagationTextIntent(),
450+
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true): const DoNothingAndStopPropagationTextIntent(),
451+
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, alt: true): const DoNothingAndStopPropagationTextIntent(),
452+
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, alt: true): const DoNothingAndStopPropagationTextIntent(),
453+
const SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true, meta: true): const DoNothingAndStopPropagationTextIntent(),
454+
const SingleActivator(LogicalKeyboardKey.arrowRight, shift: true, meta: true): const DoNothingAndStopPropagationTextIntent(),
455455
};
456456

457457
// Hand backspace/delete events that do not depend on text layout (delete

packages/flutter/test/widgets/editable_text_shortcuts_test.dart

+136-16
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void main() {
5757
bool readOnly = false,
5858
bool obscured = false,
5959
TextStyle style = const TextStyle(fontSize: 10.0),
60+
bool enableInteractiveSelection = true
6061
}) {
6162
return MaterialApp(
6263
home: Align(
@@ -82,6 +83,7 @@ void main() {
8283
readOnly: readOnly,
8384
textAlign: textAlign,
8485
obscureText: obscured,
86+
enableInteractiveSelection: enableInteractiveSelection,
8587
),
8688
),
8789
),
@@ -2051,22 +2053,6 @@ void main() {
20512053
}
20522054
}, variant: TargetPlatformVariant.all());
20532055

2054-
testWidgets('horizontal movement', (WidgetTester tester) async {
2055-
controller.text = testText;
2056-
controller.selection = const TextSelection.collapsed(
2057-
offset: 0,
2058-
);
2059-
2060-
await tester.pumpWidget(buildEditableText());
2061-
2062-
for (final SingleActivator activator in allModifierVariants(LogicalKeyboardKey.arrowRight)) {
2063-
await sendKeyCombination(tester, activator);
2064-
await tester.pump();
2065-
2066-
expect(controller.selection, const TextSelection.collapsed(offset: 0));
2067-
}
2068-
}, variant: TargetPlatformVariant.all());
2069-
20702056
testWidgets('select all non apple', (WidgetTester tester) async {
20712057
controller.text = testText;
20722058
controller.selection = const TextSelection.collapsed(
@@ -2285,5 +2271,139 @@ void main() {
22852271
reason: selectAllDown.toString(),
22862272
);
22872273
}, variant: TargetPlatformVariant.desktop());
2274+
2275+
testWidgets('select left', (WidgetTester tester) async {
2276+
const SingleActivator selectLeft =
2277+
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true);
2278+
controller.text = 'testing';
2279+
controller.selection = const TextSelection.collapsed(
2280+
offset: 5,
2281+
);
2282+
2283+
await tester.pumpWidget(buildEditableText());
2284+
await sendKeyCombination(tester, selectLeft);
2285+
await tester.pump();
2286+
2287+
expect(controller.text, 'testing');
2288+
expect(
2289+
controller.selection,
2290+
const TextSelection(baseOffset: 5, extentOffset: 4),
2291+
reason: selectLeft.toString(),
2292+
);
2293+
}, variant: TargetPlatformVariant.desktop());
2294+
2295+
testWidgets('select right', (WidgetTester tester) async {
2296+
const SingleActivator selectRight =
2297+
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true);
2298+
controller.text = 'testing';
2299+
controller.selection = const TextSelection.collapsed(
2300+
offset: 5,
2301+
);
2302+
2303+
await tester.pumpWidget(buildEditableText());
2304+
await sendKeyCombination(tester, selectRight);
2305+
await tester.pump();
2306+
2307+
expect(controller.text, 'testing');
2308+
expect(
2309+
controller.selection,
2310+
const TextSelection(baseOffset: 5, extentOffset: 6),
2311+
reason: selectRight.toString(),
2312+
);
2313+
}, variant: TargetPlatformVariant.desktop());
2314+
2315+
testWidgets(
2316+
'select left should not expand selection if selection is disabled',
2317+
(WidgetTester tester) async {
2318+
const SingleActivator selectLeft =
2319+
SingleActivator(LogicalKeyboardKey.arrowLeft, shift: true);
2320+
controller.text = 'testing';
2321+
controller.selection = const TextSelection.collapsed(
2322+
offset: 5,
2323+
);
2324+
2325+
await tester
2326+
.pumpWidget(buildEditableText(enableInteractiveSelection: false));
2327+
await sendKeyCombination(tester, selectLeft);
2328+
await tester.pump();
2329+
2330+
expect(controller.text, 'testing');
2331+
expect(
2332+
controller.selection,
2333+
const TextSelection.collapsed(offset: 4), // should not expand selection
2334+
reason: selectLeft.toString(),
2335+
);
2336+
}, variant: TargetPlatformVariant.desktop());
2337+
2338+
testWidgets(
2339+
'select right should not expand selection if selection is disabled',
2340+
(WidgetTester tester) async {
2341+
const SingleActivator selectRight =
2342+
SingleActivator(LogicalKeyboardKey.arrowRight, shift: true);
2343+
controller.text = 'testing';
2344+
controller.selection = const TextSelection.collapsed(offset: 5);
2345+
2346+
await tester
2347+
.pumpWidget(buildEditableText(enableInteractiveSelection: false));
2348+
await sendKeyCombination(tester, selectRight);
2349+
await tester.pump();
2350+
2351+
expect(controller.text, 'testing');
2352+
expect(
2353+
controller.selection,
2354+
const TextSelection.collapsed(
2355+
offset: 6,
2356+
affinity: TextAffinity.upstream), // should not expand selection
2357+
reason: selectRight.toString(),
2358+
);
2359+
}, variant: TargetPlatformVariant.desktop());
2360+
2361+
testWidgets('select all left', (WidgetTester tester) async {
2362+
final bool isMacOS = defaultTargetPlatform == TargetPlatform.macOS;
2363+
final SingleActivator selectAllLeft = isMacOS
2364+
? const SingleActivator(LogicalKeyboardKey.arrowLeft,
2365+
shift: true, meta: true)
2366+
: const SingleActivator(LogicalKeyboardKey.arrowLeft,
2367+
shift: true, alt: true);
2368+
controller.text = 'testing';
2369+
controller.selection = const TextSelection.collapsed(
2370+
offset: 5,
2371+
);
2372+
2373+
await tester.pumpWidget(buildEditableText());
2374+
await sendKeyCombination(tester, selectAllLeft);
2375+
await tester.pump();
2376+
2377+
expect(controller.text, 'testing');
2378+
expect(
2379+
controller.selection,
2380+
const TextSelection(baseOffset: 5, extentOffset: 0),
2381+
reason: selectAllLeft.toString(),
2382+
);
2383+
}, variant: TargetPlatformVariant.desktop());
2384+
2385+
testWidgets('select all right', (WidgetTester tester) async {
2386+
final bool isMacOS = defaultTargetPlatform == TargetPlatform.macOS;
2387+
final SingleActivator selectAllRight = isMacOS
2388+
? const SingleActivator(LogicalKeyboardKey.arrowRight,
2389+
shift: true, meta: true)
2390+
: const SingleActivator(LogicalKeyboardKey.arrowRight,
2391+
shift: true, alt: true);
2392+
controller.text = 'testing';
2393+
controller.selection = const TextSelection.collapsed(
2394+
offset: 5,
2395+
);
2396+
2397+
await tester.pumpWidget(buildEditableText());
2398+
await sendKeyCombination(tester, selectAllRight);
2399+
await tester.pump();
2400+
2401+
expect(controller.text, 'testing');
2402+
expect(
2403+
controller.selection,
2404+
const TextSelection(baseOffset: 5, extentOffset: 7),
2405+
reason: selectAllRight.toString(),
2406+
);
2407+
}, variant: TargetPlatformVariant.desktop());
22882408
}, skip: !kIsWeb); // [intended] specific tests target web.
22892409
}

0 commit comments

Comments
 (0)