From dd700e6d7cbfda540095b26be92cf628288647b3 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Tue, 4 Jun 2024 17:42:59 -0700 Subject: [PATCH] Request focus if `SemanticsAction.focus` is sent to a focusable widget (#142942) ## Description This causes the `Focus` widget to request focus on its focus node if the accessibility system (screen reader) focuses a widget via the `SemanticsAction.focus` action. ## Related Issues - https://github.com/flutter/flutter/issues/83809 ## Tests - Added a test to make sure that focus is requested when `SemanticsAction.focus` is sent by the engine. --- .../test/demo/material/chip_demo_test.dart | 2 + .../flutter/lib/src/widgets/focus_scope.dart | 8 ++++ .../flutter/test/cupertino/checkbox_test.dart | 10 +++-- .../flutter/test/cupertino/radio_test.dart | 4 ++ .../flutter/test/cupertino/route_test.dart | 2 +- .../test/cupertino/text_field_test.dart | 2 +- .../test/material/back_button_test.dart | 2 + .../material/bottom_navigation_bar_test.dart | 14 ++++++- .../material/calendar_date_picker_test.dart | 33 +++++++++++++++ packages/flutter/test/material/card_test.dart | 1 + .../material/checkbox_list_tile_test.dart | 1 + .../flutter/test/material/checkbox_test.dart | 11 +++-- packages/flutter/test/material/chip_test.dart | 10 ++--- .../test/material/date_picker_test.dart | 7 ++++ .../test/material/date_range_picker_test.dart | 1 + .../test/material/drawer_button_test.dart | 2 + .../flutter/test/material/drawer_test.dart | 2 +- .../flutter/test/material/dropdown_test.dart | 10 +++-- .../test/material/elevated_button_test.dart | 1 + .../test/material/expand_icon_test.dart | 4 ++ .../test/material/expansion_panel_test.dart | 8 ++++ .../test/material/expansion_tile_test.dart | 2 + .../test/material/filled_button_test.dart | 1 + .../material/floating_action_button_test.dart | 3 ++ .../test/material/icon_button_test.dart | 3 ++ .../flutter/test/material/ink_well_test.dart | 6 ++- .../flutter/test/material/list_tile_test.dart | 2 +- .../test/material/material_button_test.dart | 2 + .../test/material/menu_anchor_test.dart | 7 ++-- .../test/material/navigation_bar_test.dart | 8 ++++ .../test/material/navigation_drawer_test.dart | 4 ++ .../test/material/navigation_rail_test.dart | 8 ++-- .../test/material/outlined_button_test.dart | 1 + .../test/material/popup_menu_test.dart | 20 ++++----- .../test/material/radio_list_tile_test.dart | 5 ++- .../flutter/test/material/radio_test.dart | 4 ++ .../material/raw_material_button_test.dart | 1 + .../test/material/reorderable_list_test.dart | 1 + .../flutter/test/material/search_test.dart | 8 ++-- .../test/material/segmented_button_test.dart | 4 ++ .../flutter/test/material/slider_test.dart | 11 +++-- .../test/material/switch_list_tile_test.dart | 6 +-- packages/flutter/test/material/tabs_test.dart | 12 +++--- .../test/material/text_button_test.dart | 1 + .../test/material/text_field_test.dart | 4 +- .../test/material/time_picker_test.dart | 4 +- .../test/material/toggle_buttons_test.dart | 5 +++ .../user_accounts_drawer_header_test.dart | 1 + .../test/widgets/absorb_pointer_test.dart | 1 + .../flutter/test/widgets/actions_test.dart | 5 +++ packages/flutter/test/widgets/basic_test.dart | 1 + .../flutter/test/widgets/drawer_test.dart | 2 +- .../test/widgets/focus_scope_test.dart | 41 +++++++++++++++++++ .../test/widgets/focus_traversal_test.dart | 3 ++ .../gesture_detector_semantics_test.dart | 2 +- .../test/widgets/selectable_region_test.dart | 2 +- packages/flutter_test/lib/src/matchers.dart | 22 +++++++--- packages/flutter_test/test/matchers_test.dart | 3 ++ 58 files changed, 281 insertions(+), 70 deletions(-) diff --git a/dev/integration_tests/flutter_gallery/test/demo/material/chip_demo_test.dart b/dev/integration_tests/flutter_gallery/test/demo/material/chip_demo_test.dart index 9d769f7337fd..1b11c4d833ca 100644 --- a/dev/integration_tests/flutter_gallery/test/demo/material/chip_demo_test.dart +++ b/dev/integration_tests/flutter_gallery/test/demo/material/chip_demo_test.dart @@ -20,6 +20,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, label: 'Update border shape', )); @@ -29,6 +30,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, label: 'Reset chips', )); diff --git a/packages/flutter/lib/src/widgets/focus_scope.dart b/packages/flutter/lib/src/widgets/focus_scope.dart index acd9b04f1bfd..7b9743bb9662 100644 --- a/packages/flutter/lib/src/widgets/focus_scope.dart +++ b/packages/flutter/lib/src/widgets/focus_scope.dart @@ -671,6 +671,14 @@ class _FocusState extends State { Widget child = widget.child; if (widget.includeSemantics) { child = Semantics( + // Automatically request the focus for a focusable widget when it + // receives an input focus action from the semantics. Nothing is needed + // for losing the focus because if focus is lost, that means another + // node will gain focus and take focus from this widget. + onFocus: + _couldRequestFocus + ? focusNode.requestFocus + : null, focusable: _couldRequestFocus, focused: _hadPrimaryFocus, child: widget.child, diff --git a/packages/flutter/test/cupertino/checkbox_test.dart b/packages/flutter/test/cupertino/checkbox_test.dart index 601aef991d88..b6bdaf6baf25 100644 --- a/packages/flutter/test/cupertino/checkbox_test.dart +++ b/packages/flutter/test/cupertino/checkbox_test.dart @@ -34,6 +34,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -54,6 +55,7 @@ void main() { isChecked: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -73,6 +75,7 @@ void main() { hasEnabledState: true, // isFocusable is delayed by 1 frame. isFocusable: true, + hasFocusAction: true, )); await tester.pump(); @@ -178,6 +181,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -247,7 +251,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isCheckStateMixed, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); await tester.pumpWidget( @@ -268,7 +272,7 @@ void main() { SemanticsFlag.isChecked, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); await tester.pumpWidget( @@ -288,7 +292,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); semantics.dispose(); diff --git a/packages/flutter/test/cupertino/radio_test.dart b/packages/flutter/test/cupertino/radio_test.dart index c1eb4e6b52e7..9f7c3f2cee90 100644 --- a/packages/flutter/test/cupertino/radio_test.dart +++ b/packages/flutter/test/cupertino/radio_test.dart @@ -147,6 +147,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ); @@ -171,6 +172,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, isInMutuallyExclusiveGroup: true, )); @@ -190,6 +192,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, isInMutuallyExclusiveGroup: true, isChecked: true, @@ -210,6 +213,7 @@ void main() { hasEnabledState: true, isFocusable: true, isInMutuallyExclusiveGroup: true, + hasFocusAction: true, )); await tester.pump(); diff --git a/packages/flutter/test/cupertino/route_test.dart b/packages/flutter/test/cupertino/route_test.dart index 2ca816975ef5..649efb25a55a 100644 --- a/packages/flutter/test/cupertino/route_test.dart +++ b/packages/flutter/test/cupertino/route_test.dart @@ -1945,7 +1945,7 @@ void main() { await tester.pumpAndSettle(); expect(semantics, isNot(includesNodeWith( - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Dismiss', ))); debugDefaultTargetPlatformOverride = null; diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart index c46651ab159f..7407eccea10a 100644 --- a/packages/flutter/test/cupertino/text_field_test.dart +++ b/packages/flutter/test/cupertino/text_field_test.dart @@ -2621,7 +2621,7 @@ void main() { ), ); - expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap]))); + expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap, SemanticsAction.focus]))); semantics.dispose(); }); diff --git a/packages/flutter/test/material/back_button_test.dart b/packages/flutter/test/material/back_button_test.dart index afdba078a123..682dc4b2325d 100644 --- a/packages/flutter/test/material/back_button_test.dart +++ b/packages/flutter/test/material/back_button_test.dart @@ -215,6 +215,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -258,6 +259,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); diff --git a/packages/flutter/test/material/bottom_navigation_bar_test.dart b/packages/flutter/test/material/bottom_navigation_bar_test.dart index c74f893e6e71..f0e65837bb76 100644 --- a/packages/flutter/test/material/bottom_navigation_bar_test.dart +++ b/packages/flutter/test/material/bottom_navigation_bar_test.dart @@ -2111,6 +2111,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2120,6 +2121,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2129,6 +2131,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); }); @@ -2165,6 +2168,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2174,6 +2178,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2183,6 +2188,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); }); @@ -2515,6 +2521,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2524,6 +2531,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); }); @@ -2558,6 +2566,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -2567,6 +2576,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); }); @@ -2747,13 +2757,13 @@ void main() { SemanticsFlag.isSelected, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'A\nTab 1 of 2', textDirection: TextDirection.ltr, ), TestSemantics( flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'B\nTab 2 of 2', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter/test/material/calendar_date_picker_test.dart b/packages/flutter/test/material/calendar_date_picker_test.dart index ed7c1aa20541..b6eb7c577acf 100644 --- a/packages/flutter/test/material/calendar_date_picker_test.dart +++ b/packages/flutter/test/material/calendar_date_picker_test.dart @@ -864,6 +864,7 @@ void main() { tooltip: 'Previous month', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -872,6 +873,7 @@ void main() { tooltip: 'Next month', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -882,90 +884,105 @@ void main() { label: '1, Friday, January 1, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('2')), matchesSemantics( label: '2, Saturday, January 2, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('3')), matchesSemantics( label: '3, Sunday, January 3, 2016, Today', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('4')), matchesSemantics( label: '4, Monday, January 4, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('5')), matchesSemantics( label: '5, Tuesday, January 5, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('6')), matchesSemantics( label: '6, Wednesday, January 6, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('7')), matchesSemantics( label: '7, Thursday, January 7, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('8')), matchesSemantics( label: '8, Friday, January 8, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('9')), matchesSemantics( label: '9, Saturday, January 9, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('10')), matchesSemantics( label: '10, Sunday, January 10, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('11')), matchesSemantics( label: '11, Monday, January 11, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('12')), matchesSemantics( label: '12, Tuesday, January 12, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('13')), matchesSemantics( label: '13, Wednesday, January 13, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('14')), matchesSemantics( label: '14, Thursday, January 14, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('15')), matchesSemantics( label: '15, Friday, January 15, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isSelected: true, isFocusable: true, )); @@ -973,90 +990,105 @@ void main() { label: '16, Saturday, January 16, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('17')), matchesSemantics( label: '17, Sunday, January 17, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('18')), matchesSemantics( label: '18, Monday, January 18, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('19')), matchesSemantics( label: '19, Tuesday, January 19, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('20')), matchesSemantics( label: '20, Wednesday, January 20, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('21')), matchesSemantics( label: '21, Thursday, January 21, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('22')), matchesSemantics( label: '22, Friday, January 22, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('23')), matchesSemantics( label: '23, Saturday, January 23, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('24')), matchesSemantics( label: '24, Sunday, January 24, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('25')), matchesSemantics( label: '25, Monday, January 25, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('26')), matchesSemantics( label: '26, Tuesday, January 26, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('27')), matchesSemantics( label: '27, Wednesday, January 27, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('28')), matchesSemantics( label: '28, Thursday, January 28, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('29')), matchesSemantics( label: '29, Friday, January 29, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); expect(tester.getSemantics(find.text('30')), matchesSemantics( label: '30, Saturday, January 30, 2016', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); semantics.dispose(); @@ -1081,6 +1113,7 @@ void main() { expect(tester.getSemantics(find.text('$year')), matchesSemantics( label: '$year', hasTapAction: true, + hasFocusAction: true, isSelected: year == 2016, isFocusable: true, isButton: true, diff --git a/packages/flutter/test/material/card_test.dart b/packages/flutter/test/material/card_test.dart index c8a5815e4414..5e9003a1bf57 100644 --- a/packages/flutter/test/material/card_test.dart +++ b/packages/flutter/test/material/card_test.dart @@ -130,6 +130,7 @@ void main() { textDirection: TextDirection.ltr, actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], flags: [ SemanticsFlag.hasEnabledState, diff --git a/packages/flutter/test/material/checkbox_list_tile_test.dart b/packages/flutter/test/material/checkbox_list_tile_test.dart index b91628a16c17..81acbc9a6056 100644 --- a/packages/flutter/test/material/checkbox_list_tile_test.dart +++ b/packages/flutter/test/material/checkbox_list_tile_test.dart @@ -1189,6 +1189,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, label: 'Hello\nthere', )); diff --git a/packages/flutter/test/material/checkbox_test.dart b/packages/flutter/test/material/checkbox_test.dart index 636456d96202..56cbf37d9772 100644 --- a/packages/flutter/test/material/checkbox_test.dart +++ b/packages/flutter/test/material/checkbox_test.dart @@ -78,6 +78,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -97,6 +98,7 @@ void main() { isChecked: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -115,6 +117,7 @@ void main() { hasEnabledState: true, // isFocusable is delayed by 1 frame. isFocusable: true, + hasFocusAction: true, )); await tester.pump(); @@ -213,6 +216,7 @@ void main() { isChecked: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -242,6 +246,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -317,7 +322,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isCheckStateMixed, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); await tester.pumpWidget( @@ -341,7 +346,7 @@ void main() { SemanticsFlag.isChecked, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); await tester.pumpWidget( @@ -364,7 +369,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), hasLength(1)); semantics.dispose(); diff --git a/packages/flutter/test/material/chip_test.dart b/packages/flutter/test/material/chip_test.dart index 0a398a1dad70..d86147d09915 100644 --- a/packages/flutter/test/material/chip_test.dart +++ b/packages/flutter/test/material/chip_test.dart @@ -2971,7 +2971,7 @@ void main() { children: [ TestSemantics( tooltip: 'Delete', - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], textDirection: TextDirection.ltr, flags: [ SemanticsFlag.isButton, @@ -3030,7 +3030,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), @@ -3088,7 +3088,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), @@ -3141,7 +3141,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isSelected, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), @@ -3295,7 +3295,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), diff --git a/packages/flutter/test/material/date_picker_test.dart b/packages/flutter/test/material/date_picker_test.dart index df83154d4df5..8ba368cbea18 100644 --- a/packages/flutter/test/material/date_picker_test.dart +++ b/packages/flutter/test/material/date_picker_test.dart @@ -1545,6 +1545,7 @@ void main() { label: '3, Sunday, January 3, 2016, Today', isButton: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -1553,6 +1554,7 @@ void main() { tooltip: 'Switch to input', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -1565,6 +1567,7 @@ void main() { label: 'OK', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -1573,6 +1576,7 @@ void main() { label: 'CANCEL', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -1603,6 +1607,7 @@ void main() { tooltip: 'Switch to calendar', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -1630,6 +1635,7 @@ void main() { label: 'OK', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, @@ -1638,6 +1644,7 @@ void main() { label: 'CANCEL', isButton: true, hasTapAction: true, + hasFocusAction: true, isEnabled: true, hasEnabledState: true, isFocusable: true, diff --git a/packages/flutter/test/material/date_range_picker_test.dart b/packages/flutter/test/material/date_range_picker_test.dart index 353e35d47aa9..dbe3cdd4ee9b 100644 --- a/packages/flutter/test/material/date_range_picker_test.dart +++ b/packages/flutter/test/material/date_range_picker_test.dart @@ -1319,6 +1319,7 @@ void main() { matchesSemantics( label: '30, Saturday, January 30, 2016, Today', hasTapAction: true, + hasFocusAction: true, isFocusable: true, ), ); diff --git a/packages/flutter/test/material/drawer_button_test.dart b/packages/flutter/test/material/drawer_button_test.dart index bb565c8c7533..e1fe73532385 100644 --- a/packages/flutter/test/material/drawer_button_test.dart +++ b/packages/flutter/test/material/drawer_button_test.dart @@ -182,6 +182,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -239,6 +240,7 @@ void main() { hasEnabledState: true, isEnabled: true, hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); diff --git a/packages/flutter/test/material/drawer_test.dart b/packages/flutter/test/material/drawer_test.dart index 36b9ae2ff501..1562be4b6552 100644 --- a/packages/flutter/test/material/drawer_test.dart +++ b/packages/flutter/test/material/drawer_test.dart @@ -147,7 +147,7 @@ void main() { expect(semantics, isNot(includesNodeWith( label: const DefaultMaterialLocalizations().modalBarrierDismissLabel, - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ))); semantics.dispose(); diff --git a/packages/flutter/test/material/dropdown_test.dart b/packages/flutter/test/material/dropdown_test.dart index 5ec084aa05e5..c04ae2b1aa47 100644 --- a/packages/flutter/test/material/dropdown_test.dart +++ b/packages/flutter/test/material/dropdown_test.dart @@ -1300,6 +1300,7 @@ void main() { isButton: true, label: 'test', hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); @@ -1315,6 +1316,7 @@ void main() { isButton: true, label: 'three', hasTapAction: true, + hasFocusAction: true, isFocusable: true, )); handle.dispose(); @@ -1360,28 +1362,28 @@ void main() { SemanticsFlag.isFocusable, ], tags: [const SemanticsTag('RenderViewport.twoPane')], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), TestSemantics( label: 'two', textDirection: TextDirection.ltr, flags: [SemanticsFlag.isFocusable], tags: [const SemanticsTag('RenderViewport.twoPane')], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), TestSemantics( label: 'three', textDirection: TextDirection.ltr, flags: [SemanticsFlag.isFocusable], tags: [const SemanticsTag('RenderViewport.twoPane')], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), TestSemantics( label: 'four', textDirection: TextDirection.ltr, flags: [SemanticsFlag.isFocusable], tags: [const SemanticsTag('RenderViewport.twoPane')], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), diff --git a/packages/flutter/test/material/elevated_button_test.dart b/packages/flutter/test/material/elevated_button_test.dart index 2e9d958bebf9..d6627b5d9440 100644 --- a/packages/flutter/test/material/elevated_button_test.dart +++ b/packages/flutter/test/material/elevated_button_test.dart @@ -819,6 +819,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), diff --git a/packages/flutter/test/material/expand_icon_test.dart b/packages/flutter/test/material/expand_icon_test.dart index 7ec1338fa447..7ff43ab84fdc 100644 --- a/packages/flutter/test/material/expand_icon_test.dart +++ b/packages/flutter/test/material/expand_icon_test.dart @@ -217,6 +217,7 @@ void main() { expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocusable: true, @@ -233,6 +234,7 @@ void main() { expect(tester.getSemantics(find.byType(ExpandIcon)), matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocusable: true, @@ -258,6 +260,7 @@ void main() { children: [ matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocusable: true, @@ -277,6 +280,7 @@ void main() { children: [ matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocusable: true, diff --git a/packages/flutter/test/material/expansion_panel_test.dart b/packages/flutter/test/material/expansion_panel_test.dart index feab74d92d20..8df161448fee 100644 --- a/packages/flutter/test/material/expansion_panel_test.dart +++ b/packages/flutter/test/material/expansion_panel_test.dart @@ -211,6 +211,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, )); // Check custom header widget semantics is preserved. @@ -261,6 +262,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ], )); @@ -1099,6 +1101,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, onTapHint: localizations.expandedIconTapHint, )); @@ -1123,6 +1126,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, onTapHint: localizations.collapsedIconTapHint, )); @@ -1187,6 +1191,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ], )); @@ -1215,6 +1220,7 @@ void main() { isEnabled: true, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ], )); @@ -1268,6 +1274,7 @@ void main() { isFocusable: true, hasEnabledState: true, hasTapAction: true, + hasFocusAction: true, )); expect(tester.getSemantics(find.byKey(collapsedKey)), matchesSemantics( @@ -1276,6 +1283,7 @@ void main() { isFocusable: true, hasEnabledState: true, hasTapAction: true, + hasFocusAction: true, )); handle.dispose(); diff --git a/packages/flutter/test/material/expansion_tile_test.dart b/packages/flutter/test/material/expansion_tile_test.dart index 70daebbb82fe..c6de9c673ecc 100644 --- a/packages/flutter/test/material/expansion_tile_test.dart +++ b/packages/flutter/test/material/expansion_tile_test.dart @@ -728,6 +728,7 @@ void main() { tester.getSemantics(find.byType(ListTile).first), matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocused: true, @@ -742,6 +743,7 @@ void main() { tester.getSemantics(find.byType(ListTile).last), matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isEnabled: true, isFocusable: true, diff --git a/packages/flutter/test/material/filled_button_test.dart b/packages/flutter/test/material/filled_button_test.dart index e0dcc9f26b58..ad7f766e191e 100644 --- a/packages/flutter/test/material/filled_button_test.dart +++ b/packages/flutter/test/material/filled_button_test.dart @@ -1004,6 +1004,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), diff --git a/packages/flutter/test/material/floating_action_button_test.dart b/packages/flutter/test/material/floating_action_button_test.dart index e5cfc6b3f5bd..5a9f0148ced4 100644 --- a/packages/flutter/test/material/floating_action_button_test.dart +++ b/packages/flutter/test/material/floating_action_button_test.dart @@ -631,6 +631,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ], @@ -699,6 +700,7 @@ void main() { tooltip: 'Add Photo', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], flags: [ SemanticsFlag.hasEnabledState, @@ -922,6 +924,7 @@ void main() { tester.getSemantics(find.byType(FloatingActionButton)), matchesSemantics( hasTapAction: true, + hasFocusAction: true, hasEnabledState: true, isButton: true, isEnabled: true, diff --git a/packages/flutter/test/material/icon_button_test.dart b/packages/flutter/test/material/icon_button_test.dart index 7814043b7762..cdae2a943185 100644 --- a/packages/flutter/test/material/icon_button_test.dart +++ b/packages/flutter/test/material/icon_button_test.dart @@ -616,6 +616,7 @@ void main() { rect: const Rect.fromLTRB(0.0, 0.0, 48.0, 48.0), actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], flags: [ SemanticsFlag.hasEnabledState, @@ -690,6 +691,7 @@ void main() { TestSemantics( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], flags: [ SemanticsFlag.hasEnabledState, @@ -2177,6 +2179,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), transform: Matrix4.translationValues(356.0, 276.0, 0.0), diff --git a/packages/flutter/test/material/ink_well_test.dart b/packages/flutter/test/material/ink_well_test.dart index d90aded12e3e..3cc961ccc10a 100644 --- a/packages/flutter/test/material/ink_well_test.dart +++ b/packages/flutter/test/material/ink_well_test.dart @@ -1178,7 +1178,7 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async { ), ), )); - expect(semantics, includesNodeWith(label: 'Button', actions: [SemanticsAction.tap])); + expect(semantics, includesNodeWith(label: 'Button', actions: [SemanticsAction.tap, SemanticsAction.focus])); await tester.pumpWidget(Directionality( textDirection: TextDirection.ltr, @@ -1190,7 +1190,7 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async { ), ), )); - expect(semantics, isNot(includesNodeWith(label: 'Button', actions: [SemanticsAction.tap]))); + expect(semantics, isNot(includesNodeWith(label: 'Button', actions: [SemanticsAction.tap, SemanticsAction.focus]))); semantics.dispose(); }); @@ -1983,6 +1983,7 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async { label: 'Foo', hasLongPressAction: true, isFocusable: true, + hasFocusAction: true, textDirection: TextDirection.ltr, )); @@ -2003,6 +2004,7 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async { expect(tester.getSemantics(find.bySemanticsLabel('Foo')), matchesSemantics( label: 'Foo', hasTapAction: true, + hasFocusAction: true, hasLongPressAction: true, isFocusable: true, textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/material/list_tile_test.dart b/packages/flutter/test/material/list_tile_test.dart index 4860309ce34f..97d8ea6abe75 100644 --- a/packages/flutter/test/material/list_tile_test.dart +++ b/packages/flutter/test/material/list_tile_test.dart @@ -308,7 +308,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'two', ), TestSemantics.rootChild( diff --git a/packages/flutter/test/material/material_button_test.dart b/packages/flutter/test/material/material_button_test.dart index 482812fdd899..4f1612bfa1c4 100644 --- a/packages/flutter/test/material/material_button_test.dart +++ b/packages/flutter/test/material/material_button_test.dart @@ -620,6 +620,7 @@ void main() { label: 'Button', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], flags: [ SemanticsFlag.hasEnabledState, @@ -661,6 +662,7 @@ void main() { SemanticsFlag.isButton, SemanticsFlag.isFocusable, ], + actions: [SemanticsAction.focus], ), ], ), diff --git a/packages/flutter/test/material/menu_anchor_test.dart b/packages/flutter/test/material/menu_anchor_test.dart index 3759ccf1915e..85676da18347 100644 --- a/packages/flutter/test/material/menu_anchor_test.dart +++ b/packages/flutter/test/material/menu_anchor_test.dart @@ -3421,6 +3421,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), @@ -3551,7 +3552,7 @@ void main() { SemanticsFlag.hasExpandedState, SemanticsFlag.isExpanded, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), ), @@ -3573,7 +3574,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), ], ), @@ -3621,7 +3622,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), ), diff --git a/packages/flutter/test/material/navigation_bar_test.dart b/packages/flutter/test/material/navigation_bar_test.dart index f4676d597f6f..01ff1cb19f42 100644 --- a/packages/flutter/test/material/navigation_bar_test.dart +++ b/packages/flutter/test/material/navigation_bar_test.dart @@ -559,6 +559,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -568,6 +569,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); @@ -580,6 +582,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -590,6 +593,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); }); @@ -624,6 +628,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -633,6 +638,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); @@ -645,6 +651,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -655,6 +662,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); }); diff --git a/packages/flutter/test/material/navigation_drawer_test.dart b/packages/flutter/test/material/navigation_drawer_test.dart index 35c39f918d3b..d38a064469d5 100644 --- a/packages/flutter/test/material/navigation_drawer_test.dart +++ b/packages/flutter/test/material/navigation_drawer_test.dart @@ -324,6 +324,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -333,6 +334,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); @@ -345,6 +347,7 @@ void main() { textDirection: TextDirection.ltr, isFocusable: true, hasTapAction: true, + hasFocusAction: true, ), ); expect( @@ -355,6 +358,7 @@ void main() { isFocusable: true, isSelected: true, hasTapAction: true, + hasFocusAction: true, ), ); }); diff --git a/packages/flutter/test/material/navigation_rail_test.dart b/packages/flutter/test/material/navigation_rail_test.dart index de70ed5f7ad5..8e70e6cd2137 100644 --- a/packages/flutter/test/material/navigation_rail_test.dart +++ b/packages/flutter/test/material/navigation_rail_test.dart @@ -5513,25 +5513,25 @@ TestSemantics _expectedSemantics() { SemanticsFlag.isSelected, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Abc\nTab 1 of 4', textDirection: TextDirection.ltr, ), TestSemantics( flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Def\nTab 2 of 4', textDirection: TextDirection.ltr, ), TestSemantics( flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Ghi\nTab 3 of 4', textDirection: TextDirection.ltr, ), TestSemantics( flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Jkl\nTab 4 of 4', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter/test/material/outlined_button_test.dart b/packages/flutter/test/material/outlined_button_test.dart index 6b9241b7bc54..e2a9235e8783 100644 --- a/packages/flutter/test/material/outlined_button_test.dart +++ b/packages/flutter/test/material/outlined_button_test.dart @@ -1073,6 +1073,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), diff --git a/packages/flutter/test/material/popup_menu_test.dart b/packages/flutter/test/material/popup_menu_test.dart index 95cd7f0eba19..7c530194526f 100644 --- a/packages/flutter/test/material/popup_menu_test.dart +++ b/packages/flutter/test/material/popup_menu_test.dart @@ -1219,7 +1219,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '1', textDirection: TextDirection.ltr, ), @@ -1230,7 +1230,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '2', textDirection: TextDirection.ltr, ), @@ -1241,7 +1241,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '3', textDirection: TextDirection.ltr, ), @@ -1252,7 +1252,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '4', textDirection: TextDirection.ltr, ), @@ -1263,7 +1263,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '5', textDirection: TextDirection.ltr, ), @@ -1351,7 +1351,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'test1\ntest2', textDirection: TextDirection.ltr, ), @@ -1432,7 +1432,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '1', textDirection: TextDirection.ltr, ), @@ -1452,7 +1452,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '3', textDirection: TextDirection.ltr, ), @@ -1463,7 +1463,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '4', textDirection: TextDirection.ltr, ), @@ -1474,7 +1474,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: '5', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter/test/material/radio_list_tile_test.dart b/packages/flutter/test/material/radio_list_tile_test.dart index 43355b2ce871..c1bb21ae1611 100644 --- a/packages/flutter/test/material/radio_list_tile_test.dart +++ b/packages/flutter/test/material/radio_list_tile_test.dart @@ -411,7 +411,7 @@ void main() { SemanticsFlag.isInMutuallyExclusiveGroup, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Title', textDirection: TextDirection.ltr, ), @@ -448,7 +448,7 @@ void main() { SemanticsFlag.isInMutuallyExclusiveGroup, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Title', textDirection: TextDirection.ltr, ), @@ -483,6 +483,7 @@ void main() { SemanticsFlag.isInMutuallyExclusiveGroup, SemanticsFlag.isFocusable, ], + actions: [SemanticsAction.focus], label: 'Title', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter/test/material/radio_test.dart b/packages/flutter/test/material/radio_test.dart index 4aabeed1a87a..8b0456b7fc8c 100644 --- a/packages/flutter/test/material/radio_test.dart +++ b/packages/flutter/test/material/radio_test.dart @@ -221,6 +221,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ); @@ -254,6 +255,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ], @@ -284,6 +286,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ], @@ -310,6 +313,7 @@ void main() { SemanticsFlag.isInMutuallyExclusiveGroup, SemanticsFlag.isFocusable, // This flag is delayed by 1 frame. ], + actions: [SemanticsAction.focus], ), ], ), ignoreRect: true, ignoreTransform: true)); diff --git a/packages/flutter/test/material/raw_material_button_test.dart b/packages/flutter/test/material/raw_material_button_test.dart index d58db5f7851e..5f17df39f71e 100644 --- a/packages/flutter/test/material/raw_material_button_test.dart +++ b/packages/flutter/test/material/raw_material_button_test.dart @@ -160,6 +160,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: '+', textDirection: TextDirection.ltr, diff --git a/packages/flutter/test/material/reorderable_list_test.dart b/packages/flutter/test/material/reorderable_list_test.dart index 5595fe6448fc..fcd36d7d5c63 100644 --- a/packages/flutter/test/material/reorderable_list_test.dart +++ b/packages/flutter/test/material/reorderable_list_test.dart @@ -751,6 +751,7 @@ void main() { hasEnabledState: true, label: 'Switch tile', hasTapAction: true, + hasFocusAction: true, )); handle.dispose(); }); diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart index 79e856c6cb74..61963b37ecf8 100644 --- a/packages/flutter/test/material/search_test.dart +++ b/packages/flutter/test/material/search_test.dart @@ -662,7 +662,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], tooltip: 'Back', textDirection: TextDirection.ltr, ), @@ -718,7 +718,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Suggestions', textDirection: TextDirection.ltr, ), @@ -812,7 +812,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], tooltip: 'Back', textDirection: TextDirection.ltr, ), @@ -856,7 +856,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Suggestions', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter/test/material/segmented_button_test.dart b/packages/flutter/test/material/segmented_button_test.dart index c4a2f2bcd066..4ad9d933b07b 100644 --- a/packages/flutter/test/material/segmented_button_test.dart +++ b/packages/flutter/test/material/segmented_button_test.dart @@ -449,6 +449,7 @@ void main() { label: '1', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), @@ -466,6 +467,7 @@ void main() { label: '2', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), @@ -529,6 +531,7 @@ void main() { label: '1', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), @@ -544,6 +547,7 @@ void main() { label: '2', actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), diff --git a/packages/flutter/test/material/slider_test.dart b/packages/flutter/test/material/slider_test.dart index cb26860d9150..9f2786db2e30 100644 --- a/packages/flutter/test/material/slider_test.dart +++ b/packages/flutter/test/material/slider_test.dart @@ -1292,6 +1292,7 @@ void main() { SemanticsFlag.isSlider, ], actions: [ + SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease, ], @@ -1350,6 +1351,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isSlider, ], + actions: [SemanticsAction.focus], value: '50%', increasedValue: '55%', decreasedValue: '45%', @@ -1452,7 +1454,7 @@ void main() { TestSemantics( id: 4, flags: [SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider], - actions: [SemanticsAction.increase, SemanticsAction.decrease], + actions: [SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease], value: '50%', increasedValue: '60%', decreasedValue: '40%', @@ -1565,6 +1567,7 @@ void main() { SemanticsFlag.isSlider, ], actions: [ + SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease, SemanticsAction.didGainAccessibilityFocus, @@ -1625,6 +1628,7 @@ void main() { SemanticsFlag.isSlider, ], actions: [ + SemanticsAction.focus, SemanticsAction.didGainAccessibilityFocus, ], value: '50%', @@ -1729,7 +1733,7 @@ void main() { TestSemantics( id: 4, flags: [SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider], - actions: [SemanticsAction.increase, SemanticsAction.decrease], + actions: [SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease], value: '40', increasedValue: '60', decreasedValue: '20', @@ -1789,7 +1793,7 @@ void main() { TestSemantics( id: 4, flags: [SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider], - actions: [SemanticsAction.increase, SemanticsAction.decrease], + actions: [SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease], value: '40', increasedValue: '60', decreasedValue: '20', @@ -2633,6 +2637,7 @@ void main() { SemanticsFlag.isSlider, ], actions: [ + SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease, SemanticsAction.didGainAccessibilityFocus, diff --git a/packages/flutter/test/material/switch_list_tile_test.dart b/packages/flutter/test/material/switch_list_tile_test.dart index bfdf3ba9e500..c42b4e0ac615 100644 --- a/packages/flutter/test/material/switch_list_tile_test.dart +++ b/packages/flutter/test/material/switch_list_tile_test.dart @@ -78,7 +78,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isToggled, ], - actions: SemanticsAction.tap.index, + actions: SemanticsAction.tap.index | SemanticsAction.focus.index, label: 'aaa\nAAA', ), TestSemantics.rootChild( @@ -92,7 +92,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, ], - actions: SemanticsAction.tap.index, + actions: SemanticsAction.tap.index | SemanticsAction.focus.index, label: 'bbb\nBBB', ), TestSemantics.rootChild( @@ -106,7 +106,7 @@ void main() { SemanticsFlag.isFocusable, SemanticsFlag.isInMutuallyExclusiveGroup, ], - actions: SemanticsAction.tap.index, + actions: SemanticsAction.tap.index | SemanticsAction.focus.index, label: 'CCC\nccc', ), ], diff --git a/packages/flutter/test/material/tabs_test.dart b/packages/flutter/test/material/tabs_test.dart index aa9091fb6bf2..d0b66dce9016 100644 --- a/packages/flutter/test/material/tabs_test.dart +++ b/packages/flutter/test/material/tabs_test.dart @@ -3592,7 +3592,7 @@ void main() { children: [ TestSemantics( id: 4, - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], flags: [ SemanticsFlag.isSelected, SemanticsFlag.isFocusable, @@ -3604,7 +3604,7 @@ void main() { TestSemantics( id: 5, flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'TAB #1\nTab 2 of 2', rect: const Rect.fromLTRB(0.0, 0.0, 116.0, kTextTabBarHeight), transform: Matrix4.translationValues(116.0, 276.0, 0.0), @@ -3863,7 +3863,7 @@ void main() { SemanticsFlag.isSelected, SemanticsFlag.isFocusable, ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Semantics override 0\nTab 1 of 2', rect: const Rect.fromLTRB(0.0, 0.0, 116.0, kTextTabBarHeight), transform: Matrix4.translationValues(0.0, 276.0, 0.0), @@ -3871,7 +3871,7 @@ void main() { TestSemantics( id: 5, flags: [SemanticsFlag.isFocusable], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Semantics override 1\nTab 2 of 2', rect: const Rect.fromLTRB(0.0, 0.0, 116.0, kTextTabBarHeight), transform: Matrix4.translationValues(116.0, 276.0, 0.0), @@ -5652,14 +5652,14 @@ void main() { flags: [SemanticsFlag.isFocusable, SemanticsFlag.isSelected], id: 2, rect: TestSemantics.fullScreen, - actions: 1, + actions: 1 | SemanticsAction.focus.index, ), TestSemantics( label: 'TAB2\nTab 2 of 2', flags: [SemanticsFlag.isFocusable], id: 3, rect: TestSemantics.fullScreen, - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ), TestSemantics( id: 4, diff --git a/packages/flutter/test/material/text_button_test.dart b/packages/flutter/test/material/text_button_test.dart index f213635cb783..640d9649f895 100644 --- a/packages/flutter/test/material/text_button_test.dart +++ b/packages/flutter/test/material/text_button_test.dart @@ -607,6 +607,7 @@ void main() { TestSemantics.rootChild( actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], label: 'ABC', rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart index 1f667d152eed..fd1f69e7914a 100644 --- a/packages/flutter/test/material/text_field_test.dart +++ b/packages/flutter/test/material/text_field_test.dart @@ -6964,7 +6964,7 @@ void main() { ), ); - expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap]))); + expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap, SemanticsAction.focus]))); semantics.dispose(); }); @@ -7005,7 +7005,7 @@ void main() { ), ); - expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap]))); + expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap, SemanticsAction.focus]))); semantics.dispose(); }); diff --git a/packages/flutter/test/material/time_picker_test.dart b/packages/flutter/test/material/time_picker_test.dart index 60b44a4bc533..1236c63fc111 100644 --- a/packages/flutter/test/material/time_picker_test.dart +++ b/packages/flutter/test/material/time_picker_test.dart @@ -1250,7 +1250,7 @@ void main() { semantics, includesNodeWith( label: amString, - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], flags: [ SemanticsFlag.isButton, SemanticsFlag.isChecked, @@ -1264,7 +1264,7 @@ void main() { semantics, includesNodeWith( label: pmString, - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], flags: [ SemanticsFlag.isButton, SemanticsFlag.isInMutuallyExclusiveGroup, diff --git a/packages/flutter/test/material/toggle_buttons_test.dart b/packages/flutter/test/material/toggle_buttons_test.dart index 1681ca3a8015..9da18f8f8d9a 100644 --- a/packages/flutter/test/material/toggle_buttons_test.dart +++ b/packages/flutter/test/material/toggle_buttons_test.dart @@ -2117,6 +2117,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], rect: const Rect.fromLTRB(0.0, 0.0, 87.0, 48.0), ), @@ -2130,6 +2131,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0) ), @@ -2143,6 +2145,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0), ), @@ -2188,6 +2191,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), TestSemantics( @@ -2201,6 +2205,7 @@ void main() { ], actions: [ SemanticsAction.tap, + SemanticsAction.focus, ], ), ], diff --git a/packages/flutter/test/material/user_accounts_drawer_header_test.dart b/packages/flutter/test/material/user_accounts_drawer_header_test.dart index a106eaabf8fb..1da4ab880b20 100644 --- a/packages/flutter/test/material/user_accounts_drawer_header_test.dart +++ b/packages/flutter/test/material/user_accounts_drawer_header_test.dart @@ -531,6 +531,7 @@ void main() { flags: [SemanticsFlag.isFocusable], label: 'Signed in\nname\nemail', textDirection: TextDirection.ltr, + actions: [SemanticsAction.focus], children: [ TestSemantics( label: r'B', diff --git a/packages/flutter/test/widgets/absorb_pointer_test.dart b/packages/flutter/test/widgets/absorb_pointer_test.dart index 6c2a88f58ca4..5952cc69b28e 100644 --- a/packages/flutter/test/widgets/absorb_pointer_test.dart +++ b/packages/flutter/test/widgets/absorb_pointer_test.dart @@ -48,6 +48,7 @@ void main() { matchesSemantics( label: 'button', hasTapAction: true, + hasFocusAction: true, isButton: true, isFocusable: true, hasEnabledState: true, diff --git a/packages/flutter/test/widgets/actions_test.dart b/packages/flutter/test/widgets/actions_test.dart index 87d2f2b0e117..3b87e8c44f3c 100644 --- a/packages/flutter/test/widgets/actions_test.dart +++ b/packages/flutter/test/widgets/actions_test.dart @@ -1013,9 +1013,11 @@ void main() { // This semantic is from `Focus` widget under `FocusableActionDetector`. matchesSemantics( isFocusable: true, + hasFocusAction: true, children: [ matchesSemantics( hasTapAction: true, + hasFocusAction: true, isButton: true, hasEnabledState: true, isEnabled: true, @@ -1025,6 +1027,7 @@ void main() { ), matchesSemantics( hasTapAction: true, + hasFocusAction: true, isButton: true, hasEnabledState: true, isEnabled: true, @@ -1068,6 +1071,7 @@ void main() { children: [ matchesSemantics( hasTapAction: true, + hasFocusAction: true, isButton: true, hasEnabledState: true, isEnabled: true, @@ -1077,6 +1081,7 @@ void main() { ), matchesSemantics( hasTapAction: true, + hasFocusAction: true, isButton: true, hasEnabledState: true, isEnabled: true, diff --git a/packages/flutter/test/widgets/basic_test.dart b/packages/flutter/test/widgets/basic_test.dart index 8ad224376c0d..ee472a90854c 100644 --- a/packages/flutter/test/widgets/basic_test.dart +++ b/packages/flutter/test/widgets/basic_test.dart @@ -858,6 +858,7 @@ void main() { matchesSemantics( label: 'button', hasTapAction: true, + hasFocusAction: true, isButton: true, isFocusable: true, hasEnabledState: true, diff --git a/packages/flutter/test/widgets/drawer_test.dart b/packages/flutter/test/widgets/drawer_test.dart index cb3aba7fd828..e6741fb2f281 100644 --- a/packages/flutter/test/widgets/drawer_test.dart +++ b/packages/flutter/test/widgets/drawer_test.dart @@ -348,7 +348,7 @@ void main() { scaffoldKey.currentState!.openDrawer(); await tester.pump(const Duration(milliseconds: 100)); - expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap]))); + expect(semantics, isNot(includesNodeWith(actions: [SemanticsAction.tap, SemanticsAction.focus]))); expect(semantics, isNot(includesNodeWith(label: 'Dismiss'))); semantics.dispose(); diff --git a/packages/flutter/test/widgets/focus_scope_test.dart b/packages/flutter/test/widgets/focus_scope_test.dart index 13b25fe370b6..ad5514c90919 100644 --- a/packages/flutter/test/widgets/focus_scope_test.dart +++ b/packages/flutter/test/widgets/focus_scope_test.dart @@ -1999,6 +1999,47 @@ void main() { ), ); }); + + testWidgets('Focus widget gains input focus when it gains accessibility focus', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!; + final FocusNode focusNode = FocusNode(); + addTearDown(focusNode.dispose); + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.rtl, + child: Focus( + focusNode: focusNode, + child: const Text('Test'), + ), + ), + ); + + expect( + semantics, + hasSemantics( + TestSemantics.root( + children: [ + TestSemantics( + id: 1, + flags: [SemanticsFlag.isFocusable], + actions: [SemanticsAction.focus], + label: 'Test', + textDirection: TextDirection.rtl, + ), + ], + ), + ignoreRect: true, + ignoreTransform: true, + ), + ); + + expect(focusNode.hasFocus, isFalse); + semanticsOwner.performAction(1, SemanticsAction.focus); + await tester.pumpAndSettle(); + expect(focusNode.hasFocus, isTrue); + semantics.dispose(); + }); }); group('ExcludeFocus', () { diff --git a/packages/flutter/test/widgets/focus_traversal_test.dart b/packages/flutter/test/widgets/focus_traversal_test.dart index 9d9f2157305a..27ef9d5b3c1c 100644 --- a/packages/flutter/test/widgets/focus_traversal_test.dart +++ b/packages/flutter/test/widgets/focus_traversal_test.dart @@ -3182,6 +3182,9 @@ void main() { flags: [ SemanticsFlag.isFocusable, ], + actions: [ + SemanticsAction.focus, + ], ), ], ); diff --git a/packages/flutter/test/widgets/gesture_detector_semantics_test.dart b/packages/flutter/test/widgets/gesture_detector_semantics_test.dart index 4632cf53bc59..d2de05663032 100644 --- a/packages/flutter/test/widgets/gesture_detector_semantics_test.dart +++ b/packages/flutter/test/widgets/gesture_detector_semantics_test.dart @@ -333,7 +333,7 @@ void main() { ); expect(semantics, isNot(includesNodeWith( - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], ))); semantics.dispose(); diff --git a/packages/flutter/test/widgets/selectable_region_test.dart b/packages/flutter/test/widgets/selectable_region_test.dart index 6877d6f9b7a5..c1710f8dd36e 100644 --- a/packages/flutter/test/widgets/selectable_region_test.dart +++ b/packages/flutter/test/widgets/selectable_region_test.dart @@ -260,7 +260,7 @@ void main() { SemanticsFlag.isEnabled, SemanticsFlag.isFocusable ], - actions: [SemanticsAction.tap], + actions: [SemanticsAction.tap, SemanticsAction.focus], label: 'Button', textDirection: TextDirection.ltr, ), diff --git a/packages/flutter_test/lib/src/matchers.dart b/packages/flutter_test/lib/src/matchers.dart index 6e955a4fdb2c..9d75b379f56f 100644 --- a/packages/flutter_test/lib/src/matchers.dart +++ b/packages/flutter_test/lib/src/matchers.dart @@ -674,6 +674,7 @@ Matcher matchesSemantics({ bool isExpanded = false, // Actions // bool hasTapAction = false, + bool hasFocusAction = false, bool hasLongPressAction = false, bool hasScrollLeftAction = false, bool hasScrollRightAction = false, @@ -753,6 +754,7 @@ Matcher matchesSemantics({ isExpanded: isExpanded, // Actions hasTapAction: hasTapAction, + hasFocusAction: hasFocusAction, hasLongPressAction: hasLongPressAction, hasScrollLeftAction: hasScrollLeftAction, hasScrollRightAction: hasScrollRightAction, @@ -860,6 +862,7 @@ Matcher containsSemantics({ bool? isExpanded, // Actions bool? hasTapAction, + bool? hasFocusAction, bool? hasLongPressAction, bool? hasScrollLeftAction, bool? hasScrollRightAction, @@ -939,6 +942,7 @@ Matcher containsSemantics({ isExpanded: isExpanded, // Actions hasTapAction: hasTapAction, + hasFocusAction: hasFocusAction, hasLongPressAction: hasLongPressAction, hasScrollLeftAction: hasScrollLeftAction, hasScrollRightAction: hasScrollRightAction, @@ -2259,6 +2263,7 @@ class _MatchesSemanticsData extends Matcher { required bool? isExpanded, // Actions required bool? hasTapAction, + required bool? hasFocusAction, required bool? hasLongPressAction, required bool? hasScrollLeftAction, required bool? hasScrollRightAction, @@ -2317,6 +2322,7 @@ class _MatchesSemanticsData extends Matcher { }, actions = { if (hasTapAction != null) SemanticsAction.tap: hasTapAction, + if (hasFocusAction != null) SemanticsAction.focus: hasFocusAction, if (hasLongPressAction != null) SemanticsAction.longPress: hasLongPressAction, if (hasScrollLeftAction != null) SemanticsAction.scrollLeft: hasScrollLeftAction, if (hasScrollRightAction != null) SemanticsAction.scrollRight: hasScrollRightAction, @@ -2379,8 +2385,8 @@ class _MatchesSemanticsData extends Matcher { final Map flags; @override - Description describe(Description description) { - description.add('has semantics'); + Description describe(Description description, [String? index]) { + description.add('${index == null ? '' : 'Child $index '}has semantics'); if (label != null) { description.add(' with label: $label'); } @@ -2479,9 +2485,15 @@ class _MatchesSemanticsData extends Matcher { description.add(' with custom hints: $hintOverrides'); } if (children != null) { - description.add(' with children:\n'); - for (final _MatchesSemanticsData child in children!.cast<_MatchesSemanticsData>()) { - child.describe(description); + description.add(' with children:\n '); + final List<_MatchesSemanticsData> childMatches = children!.cast<_MatchesSemanticsData>(); + int childIndex = 1; + for (final _MatchesSemanticsData child in childMatches) { + child.describe(description, index != null ? '$index:$childIndex': '$childIndex'); + if (child != childMatches.last) { + description.add('\n '); + } + childIndex += 1; } } return description; diff --git a/packages/flutter_test/test/matchers_test.dart b/packages/flutter_test/test/matchers_test.dart index dd3f08f707da..034316d6d487 100644 --- a/packages/flutter_test/test/matchers_test.dart +++ b/packages/flutter_test/test/matchers_test.dart @@ -746,6 +746,7 @@ void main() { hasDidGainAccessibilityFocusAction: true, hasDidLoseAccessibilityFocusAction: true, hasDismissAction: true, + hasFocusAction: true, customActions: [action], )); }); @@ -1033,6 +1034,7 @@ void main() { hasDidGainAccessibilityFocusAction: true, hasDidLoseAccessibilityFocusAction: true, hasDismissAction: true, + hasFocusAction: true, customActions: [action], ), ); @@ -1125,6 +1127,7 @@ void main() { hasDidGainAccessibilityFocusAction: false, hasDidLoseAccessibilityFocusAction: false, hasDismissAction: false, + hasFocusAction: false, ), ); });