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;
|
||||
|
||||
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() { }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user