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.
This commit is contained in:
Greg Spencer 2024-06-04 17:42:59 -07:00 committed by GitHub
parent 4d21d2dd5f
commit dd700e6d7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
58 changed files with 281 additions and 70 deletions

View File

@ -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',
));

View File

@ -671,6 +671,14 @@ class _FocusState extends State<Focus> {
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,

View File

@ -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>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
await tester.pumpWidget(
@ -268,7 +272,7 @@ void main() {
SemanticsFlag.isChecked,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
await tester.pumpWidget(
@ -288,7 +292,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
semantics.dispose();

View File

@ -147,6 +147,7 @@ void main() {
],
actions: <SemanticsAction>[
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();

View File

@ -1945,7 +1945,7 @@ void main() {
await tester.pumpAndSettle();
expect(semantics, isNot(includesNodeWith(
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Dismiss',
)));
debugDefaultTargetPlatformOverride = null;

View File

@ -2621,7 +2621,7 @@ void main() {
),
);
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap])));
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus])));
semantics.dispose();
});

View File

@ -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();

View File

@ -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>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'A\nTab 1 of 2',
textDirection: TextDirection.ltr,
),
TestSemantics(
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'B\nTab 2 of 2',
textDirection: TextDirection.ltr,
),

View File

@ -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,

View File

@ -130,6 +130,7 @@ void main() {
textDirection: TextDirection.ltr,
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,

View File

@ -1189,6 +1189,7 @@ void main() {
hasEnabledState: true,
isEnabled: true,
hasTapAction: true,
hasFocusAction: true,
isFocusable: true,
label: 'Hello\nthere',
));

View File

@ -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>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
await tester.pumpWidget(
@ -341,7 +346,7 @@ void main() {
SemanticsFlag.isChecked,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
await tester.pumpWidget(
@ -364,7 +369,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
), hasLength(1));
semantics.dispose();

View File

@ -2971,7 +2971,7 @@ void main() {
children: <TestSemantics>[
TestSemantics(
tooltip: 'Delete',
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
textDirection: TextDirection.ltr,
flags: <SemanticsFlag>[
SemanticsFlag.isButton,
@ -3030,7 +3030,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),
@ -3088,7 +3088,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),
@ -3141,7 +3141,7 @@ void main() {
SemanticsFlag.isFocusable,
SemanticsFlag.isSelected,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),
@ -3295,7 +3295,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),

View File

@ -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,

View File

@ -1319,6 +1319,7 @@ void main() {
matchesSemantics(
label: '30, Saturday, January 30, 2016, Today',
hasTapAction: true,
hasFocusAction: true,
isFocusable: true,
),
);

View File

@ -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();

View File

@ -147,7 +147,7 @@ void main() {
expect(semantics, isNot(includesNodeWith(
label: const DefaultMaterialLocalizations().modalBarrierDismissLabel,
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
)));
semantics.dispose();

View File

@ -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: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
TestSemantics(
label: 'two',
textDirection: TextDirection.ltr,
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
TestSemantics(
label: 'three',
textDirection: TextDirection.ltr,
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
TestSemantics(
label: 'four',
textDirection: TextDirection.ltr,
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
tags: <SemanticsTag>[const SemanticsTag('RenderViewport.twoPane')],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),

View File

@ -819,6 +819,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),

View File

@ -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: <Matcher>[
matchesSemantics(
hasTapAction: true,
hasFocusAction: true,
hasEnabledState: true,
isEnabled: true,
isFocusable: true,
@ -277,6 +280,7 @@ void main() {
children: <Matcher>[
matchesSemantics(
hasTapAction: true,
hasFocusAction: true,
hasEnabledState: true,
isEnabled: true,
isFocusable: true,

View File

@ -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();

View File

@ -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,

View File

@ -1004,6 +1004,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),

View File

@ -631,6 +631,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
],
@ -699,6 +700,7 @@ void main() {
tooltip: 'Add Photo',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
@ -922,6 +924,7 @@ void main() {
tester.getSemantics(find.byType(FloatingActionButton)),
matchesSemantics(
hasTapAction: true,
hasFocusAction: true,
hasEnabledState: true,
isButton: true,
isEnabled: true,

View File

@ -616,6 +616,7 @@ void main() {
rect: const Rect.fromLTRB(0.0, 0.0, 48.0, 48.0),
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
@ -690,6 +691,7 @@ void main() {
TestSemantics(
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
@ -2177,6 +2179,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
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),

View File

@ -1178,7 +1178,7 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async {
),
),
));
expect(semantics, includesNodeWith(label: 'Button', actions: <SemanticsAction>[SemanticsAction.tap]));
expect(semantics, includesNodeWith(label: 'Button', actions: <SemanticsAction>[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>[SemanticsAction.tap])));
expect(semantics, isNot(includesNodeWith(label: 'Button', actions: <SemanticsAction>[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,

View File

@ -308,7 +308,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'two',
),
TestSemantics.rootChild(

View File

@ -620,6 +620,7 @@ void main() {
label: 'Button',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
flags: <SemanticsFlag>[
SemanticsFlag.hasEnabledState,
@ -661,6 +662,7 @@ void main() {
SemanticsFlag.isButton,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.focus],
),
],
),

View File

@ -3421,6 +3421,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
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>[SemanticsAction.tap],
actions: <SemanticsAction>[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>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
],
),
@ -3621,7 +3622,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
),

View File

@ -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,
),
);
});

View File

@ -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,
),
);
});

View File

@ -5513,25 +5513,25 @@ TestSemantics _expectedSemantics() {
SemanticsFlag.isSelected,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Abc\nTab 1 of 4',
textDirection: TextDirection.ltr,
),
TestSemantics(
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Def\nTab 2 of 4',
textDirection: TextDirection.ltr,
),
TestSemantics(
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Ghi\nTab 3 of 4',
textDirection: TextDirection.ltr,
),
TestSemantics(
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Jkl\nTab 4 of 4',
textDirection: TextDirection.ltr,
),

View File

@ -1073,6 +1073,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),

View File

@ -1219,7 +1219,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '1',
textDirection: TextDirection.ltr,
),
@ -1230,7 +1230,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '2',
textDirection: TextDirection.ltr,
),
@ -1241,7 +1241,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '3',
textDirection: TextDirection.ltr,
),
@ -1252,7 +1252,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '4',
textDirection: TextDirection.ltr,
),
@ -1263,7 +1263,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '5',
textDirection: TextDirection.ltr,
),
@ -1351,7 +1351,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'test1\ntest2',
textDirection: TextDirection.ltr,
),
@ -1432,7 +1432,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '1',
textDirection: TextDirection.ltr,
),
@ -1452,7 +1452,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '3',
textDirection: TextDirection.ltr,
),
@ -1463,7 +1463,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '4',
textDirection: TextDirection.ltr,
),
@ -1474,7 +1474,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: '5',
textDirection: TextDirection.ltr,
),

View File

@ -411,7 +411,7 @@ void main() {
SemanticsFlag.isInMutuallyExclusiveGroup,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Title',
textDirection: TextDirection.ltr,
),
@ -448,7 +448,7 @@ void main() {
SemanticsFlag.isInMutuallyExclusiveGroup,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Title',
textDirection: TextDirection.ltr,
),
@ -483,6 +483,7 @@ void main() {
SemanticsFlag.isInMutuallyExclusiveGroup,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.focus],
label: 'Title',
textDirection: TextDirection.ltr,
),

View File

@ -221,6 +221,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
);
@ -254,6 +255,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
],
@ -284,6 +286,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
],
@ -310,6 +313,7 @@ void main() {
SemanticsFlag.isInMutuallyExclusiveGroup,
SemanticsFlag.isFocusable, // This flag is delayed by 1 frame.
],
actions: <SemanticsAction>[SemanticsAction.focus],
),
],
), ignoreRect: true, ignoreTransform: true));

View File

@ -160,6 +160,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
label: '+',
textDirection: TextDirection.ltr,

View File

@ -751,6 +751,7 @@ void main() {
hasEnabledState: true,
label: 'Switch tile',
hasTapAction: true,
hasFocusAction: true,
));
handle.dispose();
});

View File

@ -662,7 +662,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
tooltip: 'Back',
textDirection: TextDirection.ltr,
),
@ -718,7 +718,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Suggestions',
textDirection: TextDirection.ltr,
),
@ -812,7 +812,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
tooltip: 'Back',
textDirection: TextDirection.ltr,
),
@ -856,7 +856,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Suggestions',
textDirection: TextDirection.ltr,
),

View File

@ -449,6 +449,7 @@ void main() {
label: '1',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
@ -466,6 +467,7 @@ void main() {
label: '2',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
@ -529,6 +531,7 @@ void main() {
label: '1',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
@ -544,6 +547,7 @@ void main() {
label: '2',
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),

View File

@ -1292,6 +1292,7 @@ void main() {
SemanticsFlag.isSlider,
],
actions: <SemanticsAction>[
SemanticsAction.focus,
SemanticsAction.increase,
SemanticsAction.decrease,
],
@ -1350,6 +1351,7 @@ void main() {
SemanticsFlag.isFocusable,
SemanticsFlag.isSlider,
],
actions: <SemanticsAction>[SemanticsAction.focus],
value: '50%',
increasedValue: '55%',
decreasedValue: '45%',
@ -1452,7 +1454,7 @@ void main() {
TestSemantics(
id: 4,
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
actions: <SemanticsAction>[SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease],
value: '50%',
increasedValue: '60%',
decreasedValue: '40%',
@ -1565,6 +1567,7 @@ void main() {
SemanticsFlag.isSlider,
],
actions: <SemanticsAction>[
SemanticsAction.focus,
SemanticsAction.increase,
SemanticsAction.decrease,
SemanticsAction.didGainAccessibilityFocus,
@ -1625,6 +1628,7 @@ void main() {
SemanticsFlag.isSlider,
],
actions: <SemanticsAction>[
SemanticsAction.focus,
SemanticsAction.didGainAccessibilityFocus,
],
value: '50%',
@ -1729,7 +1733,7 @@ void main() {
TestSemantics(
id: 4,
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
actions: <SemanticsAction>[SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease],
value: '40',
increasedValue: '60',
decreasedValue: '20',
@ -1789,7 +1793,7 @@ void main() {
TestSemantics(
id: 4,
flags: <SemanticsFlag>[SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled, SemanticsFlag.isFocusable, SemanticsFlag.isSlider],
actions: <SemanticsAction>[SemanticsAction.increase, SemanticsAction.decrease],
actions: <SemanticsAction>[SemanticsAction.focus, SemanticsAction.increase, SemanticsAction.decrease],
value: '40',
increasedValue: '60',
decreasedValue: '20',
@ -2633,6 +2637,7 @@ void main() {
SemanticsFlag.isSlider,
],
actions: <SemanticsAction>[
SemanticsAction.focus,
SemanticsAction.increase,
SemanticsAction.decrease,
SemanticsAction.didGainAccessibilityFocus,

View File

@ -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',
),
],

View File

@ -3592,7 +3592,7 @@ void main() {
children: <TestSemantics>[
TestSemantics(
id: 4,
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
flags: <SemanticsFlag>[
SemanticsFlag.isSelected,
SemanticsFlag.isFocusable,
@ -3604,7 +3604,7 @@ void main() {
TestSemantics(
id: 5,
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[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>[SemanticsAction.tap],
actions: <SemanticsAction>[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>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[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>[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>[SemanticsFlag.isFocusable],
id: 3,
rect: TestSemantics.fullScreen,
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
),
TestSemantics(
id: 4,

View File

@ -607,6 +607,7 @@ void main() {
TestSemantics.rootChild(
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
label: 'ABC',
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),

View File

@ -6964,7 +6964,7 @@ void main() {
),
);
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap])));
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus])));
semantics.dispose();
});
@ -7005,7 +7005,7 @@ void main() {
),
);
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap])));
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus])));
semantics.dispose();
});

View File

@ -1250,7 +1250,7 @@ void main() {
semantics,
includesNodeWith(
label: amString,
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
flags: <SemanticsFlag>[
SemanticsFlag.isButton,
SemanticsFlag.isChecked,
@ -1264,7 +1264,7 @@ void main() {
semantics,
includesNodeWith(
label: pmString,
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
flags: <SemanticsFlag>[
SemanticsFlag.isButton,
SemanticsFlag.isInMutuallyExclusiveGroup,

View File

@ -2117,6 +2117,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
rect: const Rect.fromLTRB(0.0, 0.0, 87.0, 48.0),
),
@ -2130,6 +2131,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0)
),
@ -2143,6 +2145,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
rect: const Rect.fromLTRB(0.0, 0.0, 88.0, 48.0),
),
@ -2188,6 +2191,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
TestSemantics(
@ -2201,6 +2205,7 @@ void main() {
],
actions: <SemanticsAction>[
SemanticsAction.tap,
SemanticsAction.focus,
],
),
],

View File

@ -531,6 +531,7 @@ void main() {
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
label: 'Signed in\nname\nemail',
textDirection: TextDirection.ltr,
actions: <SemanticsAction>[SemanticsAction.focus],
children: <TestSemantics>[
TestSemantics(
label: r'B',

View File

@ -48,6 +48,7 @@ void main() {
matchesSemantics(
label: 'button',
hasTapAction: true,
hasFocusAction: true,
isButton: true,
isFocusable: true,
hasEnabledState: true,

View File

@ -1013,9 +1013,11 @@ void main() {
// This semantic is from `Focus` widget under `FocusableActionDetector`.
matchesSemantics(
isFocusable: true,
hasFocusAction: true,
children: <Matcher>[
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: <Matcher>[
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,

View File

@ -858,6 +858,7 @@ void main() {
matchesSemantics(
label: 'button',
hasTapAction: true,
hasFocusAction: true,
isButton: true,
isFocusable: true,
hasEnabledState: true,

View File

@ -348,7 +348,7 @@ void main() {
scaffoldKey.currentState!.openDrawer();
await tester.pump(const Duration(milliseconds: 100));
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap])));
expect(semantics, isNot(includesNodeWith(actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus])));
expect(semantics, isNot(includesNodeWith(label: 'Dismiss')));
semantics.dispose();

View File

@ -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>[
TestSemantics(
id: 1,
flags: <SemanticsFlag>[SemanticsFlag.isFocusable],
actions: <SemanticsAction>[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', () {

View File

@ -3182,6 +3182,9 @@ void main() {
flags: <SemanticsFlag>[
SemanticsFlag.isFocusable,
],
actions: <SemanticsAction>[
SemanticsAction.focus,
],
),
],
);

View File

@ -333,7 +333,7 @@ void main() {
);
expect(semantics, isNot(includesNodeWith(
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
)));
semantics.dispose();

View File

@ -260,7 +260,7 @@ void main() {
SemanticsFlag.isEnabled,
SemanticsFlag.isFocusable
],
actions: <SemanticsAction>[SemanticsAction.tap],
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.focus],
label: 'Button',
textDirection: TextDirection.ltr,
),

View File

@ -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 = <SemanticsAction, bool>{
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<SemanticsFlag, bool> 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;

View File

@ -746,6 +746,7 @@ void main() {
hasDidGainAccessibilityFocusAction: true,
hasDidLoseAccessibilityFocusAction: true,
hasDismissAction: true,
hasFocusAction: true,
customActions: <CustomSemanticsAction>[action],
));
});
@ -1033,6 +1034,7 @@ void main() {
hasDidGainAccessibilityFocusAction: true,
hasDidLoseAccessibilityFocusAction: true,
hasDismissAction: true,
hasFocusAction: true,
customActions: <CustomSemanticsAction>[action],
),
);
@ -1125,6 +1127,7 @@ void main() {
hasDidGainAccessibilityFocusAction: false,
hasDidLoseAccessibilityFocusAction: false,
hasDismissAction: false,
hasFocusAction: false,
),
);
});