Unverified Commit 3c73185c authored by chunhtai's avatar chunhtai Committed by GitHub

Automatically activate testfield in macOS when receives accessibility… (#78815)

parent f712fecd
......@@ -1071,6 +1071,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
final TextEditingController controller = _effectiveController;
TextSelectionControls? textSelectionControls = widget.selectionControls;
VoidCallback? handleDidGainAccessibilityFocus;
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.android:
......@@ -1082,6 +1083,13 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
case TargetPlatform.macOS:
textSelectionControls ??= cupertinoDesktopTextSelectionControls;
handleDidGainAccessibilityFocus = () {
// macOS automatically activated the TextField when it receives
// accessibility focus.
if (!_effectiveFocusNode.hasFocus && _effectiveFocusNode.canRequestFocus) {
_effectiveFocusNode.requestFocus();
}
};
break;
}
......@@ -1212,6 +1220,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
}
_requestKeyboard();
},
onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
child: IgnorePointer(
ignoring: !enabled,
child: Container(
......
......@@ -1144,6 +1144,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
final Color selectionColor;
Color? autocorrectionTextRectColor;
Radius? cursorRadius = widget.cursorRadius;
VoidCallback? handleDidGainAccessibilityFocus;
switch (theme.platform) {
case TargetPlatform.iOS:
......@@ -1169,6 +1170,13 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
selectionColor = selectionTheme.selectionColor ?? cupertinoTheme.primaryColor.withOpacity(0.40);
cursorRadius ??= const Radius.circular(2.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;
case TargetPlatform.android:
......@@ -1310,6 +1318,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
_effectiveController.selection = TextSelection.collapsed(offset: _effectiveController.text.length);
_requestKeyboard();
},
onDidGainAccessibilityFocus: handleDidGainAccessibilityFocus,
child: child,
);
},
......
......@@ -284,6 +284,56 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing);
}, 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(
'takes available space horizontally and takes intrinsic space vertically no-strut',
(WidgetTester tester) async {
......
......@@ -626,6 +626,8 @@ void main() {
debugDefaultTargetPlatformOverride != TargetPlatform.macOS) SemanticsFlag.namesRoute,
],
actions: <SemanticsAction>[
if (debugDefaultTargetPlatformOverride == TargetPlatform.macOS)
SemanticsAction.didGainAccessibilityFocus,
SemanticsAction.tap,
SemanticsAction.setSelection,
SemanticsAction.setText,
......
......@@ -255,6 +255,57 @@ void main() {
expect(find.byType(CupertinoButton), findsNothing);
}, 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 {
void onEditingComplete() { }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment