Automatically activate testfield in macOS when receives accessibility… (#78815)
This commit is contained in:
parent
f712fecde2
commit
3c73185cac
@ -1071,6 +1071,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
|
|||||||
final TextEditingController controller = _effectiveController;
|
final TextEditingController controller = _effectiveController;
|
||||||
|
|
||||||
TextSelectionControls? textSelectionControls = widget.selectionControls;
|
TextSelectionControls? textSelectionControls = widget.selectionControls;
|
||||||
|
VoidCallback? handleDidGainAccessibilityFocus;
|
||||||
switch (defaultTargetPlatform) {
|
switch (defaultTargetPlatform) {
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
@ -1082,6 +1083,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
|
|||||||
|
|
||||||
case TargetPlatform.macOS:
|
case TargetPlatform.macOS:
|
||||||
textSelectionControls ??= cupertinoDesktopTextSelectionControls;
|
textSelectionControls ??= cupertinoDesktopTextSelectionControls;
|
||||||
|
handleDidGainAccessibilityFocus = () {
|
||||||
|
// macOS automatically activated the TextField when it receives
|
||||||
|
// accessibility focus.
|
||||||
|
if (!_effectiveFocusNode.hasFocus && _effectiveFocusNode.canRequestFocus) {
|
||||||
|
_effectiveFocusNode.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1212,6 +1220,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
|
|||||||
}
|
}
|
||||||
_requestKeyboard();
|
_requestKeyboard();
|
||||||
},
|
},
|
||||||
|
onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
|
||||||
child: IgnorePointer(
|
child: IgnorePointer(
|
||||||
ignoring: !enabled,
|
ignoring: !enabled,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -1144,6 +1144,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
final Color selectionColor;
|
final Color selectionColor;
|
||||||
Color? autocorrectionTextRectColor;
|
Color? autocorrectionTextRectColor;
|
||||||
Radius? cursorRadius = widget.cursorRadius;
|
Radius? cursorRadius = widget.cursorRadius;
|
||||||
|
VoidCallback? handleDidGainAccessibilityFocus;
|
||||||
|
|
||||||
switch (theme.platform) {
|
switch (theme.platform) {
|
||||||
case TargetPlatform.iOS:
|
case TargetPlatform.iOS:
|
||||||
@ -1169,6 +1170,13 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
selectionColor = selectionTheme.selectionColor ?? cupertinoTheme.primaryColor.withOpacity(0.40);
|
selectionColor = selectionTheme.selectionColor ?? cupertinoTheme.primaryColor.withOpacity(0.40);
|
||||||
cursorRadius ??= const Radius.circular(2.0);
|
cursorRadius ??= const Radius.circular(2.0);
|
||||||
cursorOffset = Offset(iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
|
cursorOffset = Offset(iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio, 0);
|
||||||
|
handleDidGainAccessibilityFocus = () {
|
||||||
|
// macOS automatically activated the TextField when it receives
|
||||||
|
// accessibility focus.
|
||||||
|
if (!_effectiveFocusNode.hasFocus && _effectiveFocusNode.canRequestFocus) {
|
||||||
|
_effectiveFocusNode.requestFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TargetPlatform.android:
|
case TargetPlatform.android:
|
||||||
@ -1310,6 +1318,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
|
|||||||
_effectiveController.selection = TextSelection.collapsed(offset: _effectiveController.text.length);
|
_effectiveController.selection = TextSelection.collapsed(offset: _effectiveController.text.length);
|
||||||
_requestKeyboard();
|
_requestKeyboard();
|
||||||
},
|
},
|
||||||
|
onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -284,6 +284,56 @@ void main() {
|
|||||||
expect(find.byType(CupertinoButton), findsNothing);
|
expect(find.byType(CupertinoButton), findsNothing);
|
||||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }), skip: kIsWeb);
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }), skip: kIsWeb);
|
||||||
|
|
||||||
|
testWidgets('Activates the text field when receives semantics focus on Mac', (WidgetTester tester) async {
|
||||||
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
CupertinoApp(
|
||||||
|
home: CupertinoTextField(focusNode: focusNode)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(semantics, hasSemantics(
|
||||||
|
TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 1,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 2,
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 3,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 4,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.isTextField,
|
||||||
|
SemanticsFlag.hasEnabledState, SemanticsFlag.isEnabled],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap,
|
||||||
|
SemanticsAction.didGainAccessibilityFocus],
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreRect: true,
|
||||||
|
ignoreTransform: true,
|
||||||
|
));
|
||||||
|
|
||||||
|
expect(focusNode.hasFocus, isFalse);
|
||||||
|
semanticsOwner.performAction(4, SemanticsAction.didGainAccessibilityFocus);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, isTrue);
|
||||||
|
semantics.dispose();
|
||||||
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }), skip: kIsWeb);
|
||||||
|
|
||||||
testWidgets(
|
testWidgets(
|
||||||
'takes available space horizontally and takes intrinsic space vertically no-strut',
|
'takes available space horizontally and takes intrinsic space vertically no-strut',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
@ -626,6 +626,8 @@ void main() {
|
|||||||
debugDefaultTargetPlatformOverride != TargetPlatform.macOS) SemanticsFlag.namesRoute,
|
debugDefaultTargetPlatformOverride != TargetPlatform.macOS) SemanticsFlag.namesRoute,
|
||||||
],
|
],
|
||||||
actions: <SemanticsAction>[
|
actions: <SemanticsAction>[
|
||||||
|
if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
|
||||||
|
SemanticsAction.didGainAccessibilityFocus,
|
||||||
SemanticsAction.tap,
|
SemanticsAction.tap,
|
||||||
SemanticsAction.setSelection,
|
SemanticsAction.setSelection,
|
||||||
SemanticsAction.setText,
|
SemanticsAction.setText,
|
||||||
|
@ -255,6 +255,57 @@ void main() {
|
|||||||
expect(find.byType(CupertinoButton), findsNothing);
|
expect(find.byType(CupertinoButton), findsNothing);
|
||||||
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS, TargetPlatform.windows, TargetPlatform.linux }), skip: kIsWeb);
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS, TargetPlatform.windows, TargetPlatform.linux }), skip: kIsWeb);
|
||||||
|
|
||||||
|
testWidgets('Activates the text field when receives semantics focus on Mac', (WidgetTester tester) async {
|
||||||
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
final SemanticsOwner semanticsOwner = tester.binding.pipelineOwner.semanticsOwner!;
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: Material(
|
||||||
|
child: TextField(focusNode: focusNode),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(semantics, hasSemantics(
|
||||||
|
TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 1,
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 2,
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 3,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
id: 4,
|
||||||
|
flags: <SemanticsFlag>[SemanticsFlag.isTextField],
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap,
|
||||||
|
SemanticsAction.didGainAccessibilityFocus],
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
ignoreRect: true,
|
||||||
|
ignoreTransform: true,
|
||||||
|
));
|
||||||
|
|
||||||
|
expect(focusNode.hasFocus, isFalse);
|
||||||
|
semanticsOwner.performAction(4, SemanticsAction.didGainAccessibilityFocus);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
expect(focusNode.hasFocus, isTrue);
|
||||||
|
semantics.dispose();
|
||||||
|
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.macOS }), skip: kIsWeb);
|
||||||
|
|
||||||
testWidgets('TextField passes onEditingComplete to EditableText', (WidgetTester tester) async {
|
testWidgets('TextField passes onEditingComplete to EditableText', (WidgetTester tester) async {
|
||||||
void onEditingComplete() { }
|
void onEditingComplete() { }
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user