Fix some Focus related documentation typos (#118576)
* Fix focus area documentation typos * Restore intentional spaces that illustrate bigger buttons
This commit is contained in:
parent
f989d551ce
commit
0eaa83ad63
@ -954,7 +954,7 @@ class Actions extends StatefulWidget {
|
|||||||
final Action<T>? result = _castAction(actions, intent: intent);
|
final Action<T>? result = _castAction(actions, intent: intent);
|
||||||
if (result != null && result.isEnabled(intent)) {
|
if (result != null && result.isEnabled(intent)) {
|
||||||
// Invoke the action we found using the relevant dispatcher from the Actions
|
// Invoke the action we found using the relevant dispatcher from the Actions
|
||||||
// Element we found.
|
// element we found.
|
||||||
returnValue = _findDispatcher(element).invokeAction(result, intent, context);
|
returnValue = _findDispatcher(element).invokeAction(result, intent, context);
|
||||||
}
|
}
|
||||||
return result != null;
|
return result != null;
|
||||||
@ -1478,7 +1478,8 @@ class ActivateIntent extends Intent {
|
|||||||
/// * [WidgetsApp.shortcuts], which defines the shortcuts to use in an
|
/// * [WidgetsApp.shortcuts], which defines the shortcuts to use in an
|
||||||
/// application (and defaults to [WidgetsApp.defaultShortcuts]).
|
/// application (and defaults to [WidgetsApp.defaultShortcuts]).
|
||||||
class ButtonActivateIntent extends Intent {
|
class ButtonActivateIntent extends Intent {
|
||||||
/// Creates an intent that the currently focused control, if it's a button.
|
/// Creates an intent that activates the currently focused control,
|
||||||
|
/// if it's a button.
|
||||||
const ButtonActivateIntent();
|
const ButtonActivateIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1581,7 +1582,7 @@ mixin _OverridableActionMixin<T extends Intent> on Action<T> {
|
|||||||
bool debugAssertConsumeKeyMutuallyRecursive = false;
|
bool debugAssertConsumeKeyMutuallyRecursive = false;
|
||||||
|
|
||||||
// The default action to invoke if an enabled override Action can't be found
|
// The default action to invoke if an enabled override Action can't be found
|
||||||
// using [lookupContext];
|
// using [lookupContext].
|
||||||
Action<T> get defaultAction;
|
Action<T> get defaultAction;
|
||||||
|
|
||||||
// The [BuildContext] used to find the override of this [Action].
|
// The [BuildContext] used to find the override of this [Action].
|
||||||
|
@ -110,7 +110,7 @@ class _Autofocus {
|
|||||||
// The widget tree is responsible for calling reparent/detach on attached
|
// The widget tree is responsible for calling reparent/detach on attached
|
||||||
// nodes to keep their parent/manager information up-to-date, so here we can
|
// nodes to keep their parent/manager information up-to-date, so here we can
|
||||||
// safely check if the scope/node involved in each autofocus request is
|
// safely check if the scope/node involved in each autofocus request is
|
||||||
// still attached, and discard the ones are no longer attached to the
|
// still attached, and discard the ones which are no longer attached to the
|
||||||
// original manager.
|
// original manager.
|
||||||
void applyIfValid(FocusManager manager) {
|
void applyIfValid(FocusManager manager) {
|
||||||
final bool shouldApply = (scope.parent != null || identical(scope, manager.rootScope))
|
final bool shouldApply = (scope.parent != null || identical(scope, manager.rootScope))
|
||||||
@ -128,8 +128,8 @@ class _Autofocus {
|
|||||||
|
|
||||||
/// An attachment point for a [FocusNode].
|
/// An attachment point for a [FocusNode].
|
||||||
///
|
///
|
||||||
/// Using a [FocusAttachment] is rarely needed, unless you are building
|
/// Using a [FocusAttachment] is rarely needed, unless building something
|
||||||
/// something akin to the [Focus] or [FocusScope] widgets from scratch.
|
/// akin to the [Focus] or [FocusScope] widgets from scratch.
|
||||||
///
|
///
|
||||||
/// Once created, a [FocusNode] must be attached to the widget tree by its
|
/// Once created, a [FocusNode] must be attached to the widget tree by its
|
||||||
/// _host_ [StatefulWidget] via a [FocusAttachment] object. [FocusAttachment]s
|
/// _host_ [StatefulWidget] via a [FocusAttachment] object. [FocusAttachment]s
|
||||||
@ -261,8 +261,8 @@ enum UnfocusDisposition {
|
|||||||
///
|
///
|
||||||
/// _Please see the [Focus] and [FocusScope] widgets, which are utility widgets
|
/// _Please see the [Focus] and [FocusScope] widgets, which are utility widgets
|
||||||
/// that manage their own [FocusNode]s and [FocusScopeNode]s, respectively. If
|
/// that manage their own [FocusNode]s and [FocusScopeNode]s, respectively. If
|
||||||
/// they aren't appropriate, [FocusNode]s can be managed directly, but doing
|
/// they aren't appropriate, [FocusNode]s can be managed directly, but doing this
|
||||||
/// this yourself is rare._
|
/// is rare._
|
||||||
///
|
///
|
||||||
/// [FocusNode]s are persistent objects that form a _focus tree_ that is a
|
/// [FocusNode]s are persistent objects that form a _focus tree_ that is a
|
||||||
/// representation of the widgets in the hierarchy that are interested in focus.
|
/// representation of the widgets in the hierarchy that are interested in focus.
|
||||||
@ -1405,8 +1405,8 @@ enum FocusHighlightStrategy {
|
|||||||
/// The focus manager is responsible for tracking which [FocusNode] has the
|
/// The focus manager is responsible for tracking which [FocusNode] has the
|
||||||
/// primary input focus (the [primaryFocus]), holding the [FocusScopeNode] that
|
/// primary input focus (the [primaryFocus]), holding the [FocusScopeNode] that
|
||||||
/// is the root of the focus tree (the [rootScope]), and what the current
|
/// is the root of the focus tree (the [rootScope]), and what the current
|
||||||
/// [highlightMode] is. It also distributes key events from [RawKeyboard] to the
|
/// [highlightMode] is. It also distributes key events from [KeyEventManager]
|
||||||
/// nodes in the focus tree.
|
/// to the nodes in the focus tree.
|
||||||
///
|
///
|
||||||
/// The singleton [FocusManager] instance is held by the [WidgetsBinding] as
|
/// The singleton [FocusManager] instance is held by the [WidgetsBinding] as
|
||||||
/// [WidgetsBinding.focusManager], and can be conveniently accessed using the
|
/// [WidgetsBinding.focusManager], and can be conveniently accessed using the
|
||||||
|
@ -195,7 +195,7 @@ class Focus extends StatefulWidget {
|
|||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// A non-null [focusNode] must be supplied if using the
|
/// A non-null [focusNode] must be supplied if using the
|
||||||
/// [Focus.withExternalFocusNode] constructor is used.
|
/// [Focus.withExternalFocusNode] constructor.
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
|
||||||
/// {@template flutter.widgets.Focus.autofocus}
|
/// {@template flutter.widgets.Focus.autofocus}
|
||||||
|
@ -200,7 +200,7 @@ abstract class FocusTraversalPolicy with Diagnosticable {
|
|||||||
///
|
///
|
||||||
/// See also:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [previous], the function that is called to move the focus to the next node.
|
/// * [previous], the function that is called to move the focus to the previous node.
|
||||||
/// * [DirectionalFocusTraversalPolicyMixin.findFirstFocusInDirection], a
|
/// * [DirectionalFocusTraversalPolicyMixin.findFirstFocusInDirection], a
|
||||||
/// function that finds the first focusable widget in a particular direction.
|
/// function that finds the first focusable widget in a particular direction.
|
||||||
FocusNode findLastFocus(FocusNode currentNode, {bool ignoreCurrentFocus = false}) {
|
FocusNode findLastFocus(FocusNode currentNode, {bool ignoreCurrentFocus = false}) {
|
||||||
@ -1139,7 +1139,7 @@ class ReadingOrderTraversalPolicy extends FocusTraversalPolicy with DirectionalF
|
|||||||
// It has to have at least topmost in it if the topmost is not degenerate.
|
// It has to have at least topmost in it if the topmost is not degenerate.
|
||||||
assert(topmost.rect.isEmpty || inBandOfTop.isNotEmpty);
|
assert(topmost.rect.isEmpty || inBandOfTop.isNotEmpty);
|
||||||
|
|
||||||
// The topmost rect in is in a band by itself, so just return that one.
|
// The topmost rect is in a band by itself, so just return that one.
|
||||||
if (inBandOfTop.length <= 1) {
|
if (inBandOfTop.length <= 1) {
|
||||||
return topmost;
|
return topmost;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,6 @@ class KeySet<T extends KeyboardKey> {
|
|||||||
&& setEquals<T>(other._keys, _keys);
|
&& setEquals<T>(other._keys, _keys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Cached hash code value. Improves [hashCode] performance by 27%-900%,
|
// Cached hash code value. Improves [hashCode] performance by 27%-900%,
|
||||||
// depending on key set size and read/write ratio.
|
// depending on key set size and read/write ratio.
|
||||||
@override
|
@override
|
||||||
@ -334,8 +333,8 @@ class LogicalKeySet extends KeySet<LogicalKeyboardKey> with Diagnosticable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [DiagnosticsProperty] which handles formatting a `Map<LogicalKeySet,
|
/// A [DiagnosticsProperty] which handles formatting a `Map<LogicalKeySet, Intent>`
|
||||||
/// Intent>` (the same type as the [Shortcuts.shortcuts] property) so that its
|
/// (the same type as the [Shortcuts.shortcuts] property) so that its
|
||||||
/// diagnostic output is human-readable.
|
/// diagnostic output is human-readable.
|
||||||
class ShortcutMapProperty extends DiagnosticsProperty<Map<ShortcutActivator, Intent>> {
|
class ShortcutMapProperty extends DiagnosticsProperty<Map<ShortcutActivator, Intent>> {
|
||||||
/// Create a diagnostics property for `Map<ShortcutActivator, Intent>` objects,
|
/// Create a diagnostics property for `Map<ShortcutActivator, Intent>` objects,
|
||||||
@ -1183,7 +1182,7 @@ class ShortcutRegistryEntry {
|
|||||||
///
|
///
|
||||||
/// The registry may be listened to (with [addListener]/[removeListener]) for
|
/// The registry may be listened to (with [addListener]/[removeListener]) for
|
||||||
/// change notifications when the registered shortcuts change. Change
|
/// change notifications when the registered shortcuts change. Change
|
||||||
/// notifications take place after the the current frame is drawn, so that
|
/// notifications take place after the current frame is drawn, so that
|
||||||
/// widgets that are not descendants of the registry can listen to it (e.g. in
|
/// widgets that are not descendants of the registry can listen to it (e.g. in
|
||||||
/// overlays).
|
/// overlays).
|
||||||
class ShortcutRegistry with ChangeNotifier {
|
class ShortcutRegistry with ChangeNotifier {
|
||||||
|
@ -74,6 +74,7 @@ void main() {
|
|||||||
expect(result, isTrue);
|
expect(result, isTrue);
|
||||||
expect(invoked, isTrue);
|
expect(invoked, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Actions widget can invoke actions with default dispatcher and maybeInvoke', (WidgetTester tester) async {
|
testWidgets('Actions widget can invoke actions with default dispatcher and maybeInvoke', (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
bool invoked = false;
|
bool invoked = false;
|
||||||
@ -1083,6 +1084,7 @@ void main() {
|
|||||||
action._testInvoke(intent);
|
action._testInvoke(intent);
|
||||||
expect(passedIntent, equals(intent));
|
expect(passedIntent, equals(intent));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('VoidCallbackAction', (WidgetTester tester) async {
|
testWidgets('VoidCallbackAction', (WidgetTester tester) async {
|
||||||
bool called = false;
|
bool called = false;
|
||||||
void testCallback() {
|
void testCallback() {
|
||||||
@ -1121,6 +1123,7 @@ void main() {
|
|||||||
|
|
||||||
expect(description, isEmpty);
|
expect(description, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('default Actions debugFillProperties', (WidgetTester tester) async {
|
testWidgets('default Actions debugFillProperties', (WidgetTester tester) async {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
|
||||||
@ -1146,6 +1149,7 @@ void main() {
|
|||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Actions implements debugFillProperties', (WidgetTester tester) async {
|
testWidgets('Actions implements debugFillProperties', (WidgetTester tester) async {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ void main() {
|
|||||||
expect(find.text('b'), findsOneWidget);
|
expect(find.text('b'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Adding a new FocusScope attaches the child it to its parent.', (WidgetTester tester) async {
|
testWidgets('Adding a new FocusScope attaches the child to its parent.', (WidgetTester tester) async {
|
||||||
final GlobalKey<TestFocusState> keyA = GlobalKey();
|
final GlobalKey<TestFocusState> keyA = GlobalKey();
|
||||||
final FocusScopeNode parentFocusScope = FocusScopeNode(debugLabel: 'Parent Scope Node');
|
final FocusScopeNode parentFocusScope = FocusScopeNode(debugLabel: 'Parent Scope Node');
|
||||||
final FocusScopeNode childFocusScope = FocusScopeNode(debugLabel: 'Child Scope Node');
|
final FocusScopeNode childFocusScope = FocusScopeNode(debugLabel: 'Child Scope Node');
|
||||||
@ -540,24 +540,24 @@ void main() {
|
|||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
FocusScope.withExternalFocusNode(
|
FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: topNode,
|
focusScopeNode: topNode,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FocusScope.withExternalFocusNode(
|
FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: parentNode,
|
focusScopeNode: parentNode,
|
||||||
child: const SizedBox(),
|
child: const SizedBox(),
|
||||||
|
),
|
||||||
|
FocusScope.withExternalFocusNode(
|
||||||
|
focusScopeNode: childNode,
|
||||||
|
parentNode: parentNode,
|
||||||
|
child: const Focus(
|
||||||
|
autofocus: true,
|
||||||
|
child: SizedBox(),
|
||||||
),
|
),
|
||||||
FocusScope.withExternalFocusNode(
|
)
|
||||||
focusScopeNode: childNode,
|
],
|
||||||
parentNode: parentNode,
|
|
||||||
child: const Focus(
|
|
||||||
autofocus: true,
|
|
||||||
child: SizedBox(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
@ -568,27 +568,27 @@ void main() {
|
|||||||
// Check that inserting a Focus in between doesn't reparent the child.
|
// Check that inserting a Focus in between doesn't reparent the child.
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
FocusScope.withExternalFocusNode(
|
FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: topNode,
|
focusScopeNode: topNode,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FocusScope.withExternalFocusNode(
|
FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: parentNode,
|
focusScopeNode: parentNode,
|
||||||
child: const SizedBox(),
|
child: const SizedBox(),
|
||||||
),
|
),
|
||||||
FocusScope.withExternalFocusNode(
|
FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: insertedNode,
|
focusScopeNode: insertedNode,
|
||||||
child: FocusScope.withExternalFocusNode(
|
child: FocusScope.withExternalFocusNode(
|
||||||
focusScopeNode: childNode,
|
focusScopeNode: childNode,
|
||||||
parentNode: parentNode,
|
parentNode: parentNode,
|
||||||
child: const Focus(
|
child: const Focus(
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
child: SizedBox(),
|
child: SizedBox(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
@ -1673,6 +1673,7 @@ void main() {
|
|||||||
await pumpTest(traverseScope1: true);
|
await pumpTest(traverseScope1: true);
|
||||||
expect(scope1.traversalDescendants, equals(<FocusNode>[focus2, focus1, scope2]));
|
expect(scope1.traversalDescendants, equals(<FocusNode>[focus2, focus1, scope2]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('descendantsAreFocusable works as expected.', (WidgetTester tester) async {
|
testWidgets('descendantsAreFocusable works as expected.', (WidgetTester tester) async {
|
||||||
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
||||||
final GlobalKey key2 = GlobalKey(debugLabel: '2');
|
final GlobalKey key2 = GlobalKey(debugLabel: '2');
|
||||||
@ -1756,13 +1757,11 @@ void main() {
|
|||||||
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
bool? keyEventHandled;
|
bool? keyEventHandled;
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult handleCallback(FocusNode node, RawKeyEvent event) {
|
||||||
final FocusOnKeyCallback handleCallback = (FocusNode node, RawKeyEvent event) {
|
|
||||||
keyEventHandled = true;
|
keyEventHandled = true;
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
};
|
}
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult ignoreCallback(FocusNode node, RawKeyEvent event) => KeyEventResult.ignored;
|
||||||
final FocusOnKeyCallback ignoreCallback = (FocusNode node, RawKeyEvent event) => KeyEventResult.ignored;
|
|
||||||
Focus focusWidget = Focus(
|
Focus focusWidget = Focus(
|
||||||
onKey: ignoreCallback, // This one does nothing.
|
onKey: ignoreCallback, // This one does nothing.
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -1807,13 +1806,11 @@ void main() {
|
|||||||
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
bool? keyEventHandled;
|
bool? keyEventHandled;
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult handleEventCallback(FocusNode node, KeyEvent event) {
|
||||||
final FocusOnKeyEventCallback handleEventCallback = (FocusNode node, KeyEvent event) {
|
|
||||||
keyEventHandled = true;
|
keyEventHandled = true;
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
};
|
}
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult ignoreEventCallback(FocusNode node, KeyEvent event) => KeyEventResult.ignored;
|
||||||
final FocusOnKeyEventCallback ignoreEventCallback = (FocusNode node, KeyEvent event) => KeyEventResult.ignored;
|
|
||||||
Focus focusWidget = Focus(
|
Focus focusWidget = Focus(
|
||||||
onKeyEvent: ignoreEventCallback, // This one does nothing.
|
onKeyEvent: ignoreEventCallback, // This one does nothing.
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
@ -1858,20 +1855,16 @@ void main() {
|
|||||||
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
final GlobalKey key1 = GlobalKey(debugLabel: '1');
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
bool? keyEventHandled;
|
bool? keyEventHandled;
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult handleCallback(FocusNode node, RawKeyEvent event) {
|
||||||
final FocusOnKeyCallback handleCallback = (FocusNode node, RawKeyEvent event) {
|
|
||||||
keyEventHandled = true;
|
keyEventHandled = true;
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
};
|
}
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult handleEventCallback(FocusNode node, KeyEvent event) {
|
||||||
final FocusOnKeyEventCallback handleEventCallback = (FocusNode node, KeyEvent event) {
|
|
||||||
keyEventHandled = true;
|
keyEventHandled = true;
|
||||||
return KeyEventResult.handled;
|
return KeyEventResult.handled;
|
||||||
};
|
}
|
||||||
// ignore: prefer_function_declarations_over_variables
|
KeyEventResult ignoreCallback(FocusNode node, RawKeyEvent event) => KeyEventResult.ignored;
|
||||||
final FocusOnKeyCallback ignoreCallback = (FocusNode node, RawKeyEvent event) => KeyEventResult.ignored;
|
KeyEventResult ignoreEventCallback(FocusNode node, KeyEvent event) => KeyEventResult.ignored;
|
||||||
// ignore: prefer_function_declarations_over_variables
|
|
||||||
final FocusOnKeyEventCallback ignoreEventCallback = (FocusNode node, KeyEvent event) => KeyEventResult.ignored;
|
|
||||||
focusNode.onKey = ignoreCallback;
|
focusNode.onKey = ignoreCallback;
|
||||||
focusNode.onKeyEvent = ignoreEventCallback;
|
focusNode.onKeyEvent = ignoreEventCallback;
|
||||||
focusNode.descendantsAreFocusable = false;
|
focusNode.descendantsAreFocusable = false;
|
||||||
@ -1974,6 +1967,7 @@ void main() {
|
|||||||
expect(containerNode.hasFocus, isFalse);
|
expect(containerNode.hasFocus, isFalse);
|
||||||
expect(unfocusableNode.hasFocus, isFalse);
|
expect(unfocusableNode.hasFocus, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/61700
|
// Regression test for https://github.com/flutter/flutter/issues/61700
|
||||||
testWidgets("ExcludeFocus doesn't transfer focus to another descendant.", (WidgetTester tester) async {
|
testWidgets("ExcludeFocus doesn't transfer focus to another descendant.", (WidgetTester tester) async {
|
||||||
final FocusNode parentFocusNode = FocusNode(debugLabel: 'group');
|
final FocusNode parentFocusNode = FocusNode(debugLabel: 'group');
|
||||||
|
@ -2153,6 +2153,7 @@ void main() {
|
|||||||
expect(events.length, 2);
|
expect(events.length, 2);
|
||||||
}, variant: KeySimulatorTransitModeVariant.all());
|
}, variant: KeySimulatorTransitModeVariant.all());
|
||||||
});
|
});
|
||||||
|
|
||||||
group(FocusTraversalGroup, () {
|
group(FocusTraversalGroup, () {
|
||||||
testWidgets("Focus traversal group doesn't introduce a Semantics node", (WidgetTester tester) async {
|
testWidgets("Focus traversal group doesn't introduce a Semantics node", (WidgetTester tester) async {
|
||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
@ -2381,11 +2382,11 @@ void main() {
|
|||||||
final SemanticsTester semantics = SemanticsTester(tester);
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
final FocusNode focusNode = FocusNode();
|
final FocusNode focusNode = FocusNode();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
RawKeyboardListener(
|
RawKeyboardListener(
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
includeSemantics: false,
|
includeSemantics: false,
|
||||||
child: Container(),
|
child: Container(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final TestSemantics expectedSemantics = TestSemantics.root();
|
final TestSemantics expectedSemantics = TestSemantics.root();
|
||||||
expect(semantics, hasSemantics(expectedSemantics));
|
expect(semantics, hasSemantics(expectedSemantics));
|
||||||
|
@ -72,6 +72,7 @@ void main() {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('LogicalKeySet works as a map key.', () {
|
test('LogicalKeySet works as a map key.', () {
|
||||||
final LogicalKeySet set1 = LogicalKeySet(LogicalKeyboardKey.keyA);
|
final LogicalKeySet set1 = LogicalKeySet(LogicalKeyboardKey.keyA);
|
||||||
final LogicalKeySet set2 = LogicalKeySet(
|
final LogicalKeySet set2 = LogicalKeySet(
|
||||||
@ -109,6 +110,7 @@ void main() {
|
|||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('handles two keys', (WidgetTester tester) async {
|
testWidgets('handles two keys', (WidgetTester tester) async {
|
||||||
int invoked = 0;
|
int invoked = 0;
|
||||||
await tester.pumpWidget(activatorTester(
|
await tester.pumpWidget(activatorTester(
|
||||||
@ -537,6 +539,7 @@ void main() {
|
|||||||
expect(shortcuts.shortcuts, isNotNull);
|
expect(shortcuts.shortcuts, isNotNull);
|
||||||
expect(shortcuts.shortcuts, isEmpty);
|
expect(shortcuts.shortcuts, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Default constructed Shortcuts.manager has empty shortcuts', (WidgetTester tester) async {
|
testWidgets('Default constructed Shortcuts.manager has empty shortcuts', (WidgetTester tester) async {
|
||||||
final ShortcutManager manager = ShortcutManager();
|
final ShortcutManager manager = ShortcutManager();
|
||||||
expect(manager.shortcuts, isNotNull);
|
expect(manager.shortcuts, isNotNull);
|
||||||
@ -546,9 +549,10 @@ void main() {
|
|||||||
expect(shortcuts.shortcuts, isNotNull);
|
expect(shortcuts.shortcuts, isNotNull);
|
||||||
expect(shortcuts.shortcuts, isEmpty);
|
expect(shortcuts.shortcuts, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts.manager passes on shortcuts', (WidgetTester tester) async {
|
testWidgets('Shortcuts.manager passes on shortcuts', (WidgetTester tester) async {
|
||||||
final Map<LogicalKeySet, Intent> testShortcuts = <LogicalKeySet, Intent>{
|
final Map<LogicalKeySet, Intent> testShortcuts = <LogicalKeySet, Intent>{
|
||||||
LogicalKeySet(LogicalKeyboardKey.shift): const TestIntent(),
|
LogicalKeySet(LogicalKeyboardKey.shift): const TestIntent(),
|
||||||
};
|
};
|
||||||
final ShortcutManager manager = ShortcutManager(shortcuts: testShortcuts);
|
final ShortcutManager manager = ShortcutManager(shortcuts: testShortcuts);
|
||||||
expect(manager.shortcuts, isNotNull);
|
expect(manager.shortcuts, isNotNull);
|
||||||
@ -558,6 +562,7 @@ void main() {
|
|||||||
expect(shortcuts.shortcuts, isNotNull);
|
expect(shortcuts.shortcuts, isNotNull);
|
||||||
expect(shortcuts.shortcuts, equals(testShortcuts));
|
expect(shortcuts.shortcuts, equals(testShortcuts));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('ShortcutManager handles shortcuts', (WidgetTester tester) async {
|
testWidgets('ShortcutManager handles shortcuts', (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -592,6 +597,7 @@ void main() {
|
|||||||
expect(invoked, isTrue);
|
expect(invoked, isTrue);
|
||||||
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts.manager lets manager handle shortcuts', (WidgetTester tester) async {
|
testWidgets('Shortcuts.manager lets manager handle shortcuts', (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -633,6 +639,7 @@ void main() {
|
|||||||
expect(shortcutsSet, isFalse);
|
expect(shortcutsSet, isFalse);
|
||||||
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('ShortcutManager ignores key presses with no primary focus', (WidgetTester tester) async {
|
testWidgets('ShortcutManager ignores key presses with no primary focus', (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -665,6 +672,7 @@ void main() {
|
|||||||
expect(invoked, isFalse);
|
expect(invoked, isFalse);
|
||||||
expect(pressedKeys, isEmpty);
|
expect(pressedKeys, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets("Shortcuts passes to the next Shortcuts widget if it doesn't map the key", (WidgetTester tester) async {
|
testWidgets("Shortcuts passes to the next Shortcuts widget if it doesn't map the key", (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -704,6 +712,7 @@ void main() {
|
|||||||
expect(invoked, isTrue);
|
expect(invoked, isTrue);
|
||||||
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.shiftLeft]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts can disable a shortcut with Intent.doNothing', (WidgetTester tester) async {
|
testWidgets('Shortcuts can disable a shortcut with Intent.doNothing', (WidgetTester tester) async {
|
||||||
final GlobalKey containerKey = GlobalKey();
|
final GlobalKey containerKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -745,6 +754,7 @@ void main() {
|
|||||||
expect(invoked, isFalse);
|
expect(invoked, isFalse);
|
||||||
expect(pressedKeys, isEmpty);
|
expect(pressedKeys, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets("Shortcuts that aren't bound to an action don't absorb keys meant for text fields", (WidgetTester tester) async {
|
testWidgets("Shortcuts that aren't bound to an action don't absorb keys meant for text fields", (WidgetTester tester) async {
|
||||||
final GlobalKey textFieldKey = GlobalKey();
|
final GlobalKey textFieldKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -769,6 +779,7 @@ void main() {
|
|||||||
expect(handled, isFalse);
|
expect(handled, isFalse);
|
||||||
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.keyA]));
|
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.keyA]));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts that are bound to an action do override text fields', (WidgetTester tester) async {
|
testWidgets('Shortcuts that are bound to an action do override text fields', (WidgetTester tester) async {
|
||||||
final GlobalKey textFieldKey = GlobalKey();
|
final GlobalKey textFieldKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -805,6 +816,7 @@ void main() {
|
|||||||
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.keyA]));
|
expect(pressedKeys, equals(<LogicalKeyboardKey>[LogicalKeyboardKey.keyA]));
|
||||||
expect(invoked, isTrue);
|
expect(invoked, isTrue);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts can override intents that apply to text fields', (WidgetTester tester) async {
|
testWidgets('Shortcuts can override intents that apply to text fields', (WidgetTester tester) async {
|
||||||
final GlobalKey textFieldKey = GlobalKey();
|
final GlobalKey textFieldKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -845,6 +857,7 @@ void main() {
|
|||||||
expect(result, isFalse);
|
expect(result, isFalse);
|
||||||
expect(invoked, isFalse);
|
expect(invoked, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts can override intents that apply to text fields with DoNothingAndStopPropagationIntent', (WidgetTester tester) async {
|
testWidgets('Shortcuts can override intents that apply to text fields with DoNothingAndStopPropagationIntent', (WidgetTester tester) async {
|
||||||
final GlobalKey textFieldKey = GlobalKey();
|
final GlobalKey textFieldKey = GlobalKey();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -885,6 +898,7 @@ void main() {
|
|||||||
expect(result, isFalse);
|
expect(result, isFalse);
|
||||||
expect(invoked, isFalse);
|
expect(invoked, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Shortcuts diagnostics work.', () {
|
test('Shortcuts diagnostics work.', () {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
|
||||||
@ -914,6 +928,7 @@ void main() {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Shortcuts diagnostics work when debugLabel specified.', () {
|
test('Shortcuts diagnostics work when debugLabel specified.', () {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
|
||||||
@ -935,6 +950,7 @@ void main() {
|
|||||||
expect(description.length, equals(1));
|
expect(description.length, equals(1));
|
||||||
expect(description[0], equals('shortcuts: <Debug Label>'));
|
expect(description[0], equals('shortcuts: <Debug Label>'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Shortcuts diagnostics work when manager not specified.', () {
|
test('Shortcuts diagnostics work when manager not specified.', () {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
|
|
||||||
@ -955,6 +971,7 @@ void main() {
|
|||||||
expect(description.length, equals(1));
|
expect(description.length, equals(1));
|
||||||
expect(description[0], equalsIgnoringHashCodes('shortcuts: {{Key A + Key B}: ActivateIntent#00000}'));
|
expect(description[0], equalsIgnoringHashCodes('shortcuts: {{Key A + Key B}: ActivateIntent#00000}'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Shortcuts diagnostics work when manager specified.', () {
|
test('Shortcuts diagnostics work when manager specified.', () {
|
||||||
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
|
||||||
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
final List<LogicalKeyboardKey> pressedKeys = <LogicalKeyboardKey>[];
|
||||||
@ -981,6 +998,7 @@ void main() {
|
|||||||
expect(description[0], equalsIgnoringHashCodes('manager: TestShortcutManager#00000(shortcuts: {LogicalKeySet#00000(keys: Key A + Key B): ActivateIntent#00000})'));
|
expect(description[0], equalsIgnoringHashCodes('manager: TestShortcutManager#00000(shortcuts: {LogicalKeySet#00000(keys: Key A + Key B): ActivateIntent#00000})'));
|
||||||
expect(description[1], equalsIgnoringHashCodes('shortcuts: {{Key A + Key B}: ActivateIntent#00000}'));
|
expect(description[1], equalsIgnoringHashCodes('shortcuts: {{Key A + Key B}: ActivateIntent#00000}'));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Shortcuts support multiple intents', (WidgetTester tester) async {
|
testWidgets('Shortcuts support multiple intents', (WidgetTester tester) async {
|
||||||
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
|
||||||
bool? value = true;
|
bool? value = true;
|
||||||
@ -1952,11 +1970,11 @@ class TestShortcutManager extends ShortcutManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget activatorTester(
|
Widget activatorTester(
|
||||||
ShortcutActivator activator,
|
ShortcutActivator activator,
|
||||||
ValueSetter<Intent> onInvoke, [
|
ValueSetter<Intent> onInvoke, [
|
||||||
ShortcutActivator? activator2,
|
ShortcutActivator? activator2,
|
||||||
ValueSetter<Intent>? onInvoke2,
|
ValueSetter<Intent>? onInvoke2,
|
||||||
]) {
|
]) {
|
||||||
final bool hasSecond = activator2 != null && onInvoke2 != null;
|
final bool hasSecond = activator2 != null && onInvoke2 != null;
|
||||||
return Actions(
|
return Actions(
|
||||||
key: GlobalKey(),
|
key: GlobalKey(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user