focus_scope.dart 35.9 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Ian Hickson's avatar
Ian Hickson committed
4

5
import 'package:flutter/foundation.dart';
6 7 8 9

import 'basic.dart';
import 'focus_manager.dart';
import 'framework.dart';
10
import 'inherited_notifier.dart';
11

12 13
/// A widget that manages a [FocusNode] to allow keyboard focus to be given
/// to this widget and its descendants.
14
///
15
/// When the focus is gained or lost, [onFocusChange] is called.
16
///
17 18 19 20
/// For keyboard events, [onKey] and [onKeyEvent] are called if
/// [FocusNode.hasFocus] is true for this widget's [focusNode], unless a focused
/// descendant's [onKey] or [onKeyEvent] callback returned
/// [KeyEventResult.handled] when called.
Adam Barth's avatar
Adam Barth committed
21
///
22
/// This widget does not provide any visual indication that the focus has
23
/// changed. Any desired visual changes should be made when [onFocusChange] is
24 25 26 27 28 29 30
/// called.
///
/// To access the [FocusNode] of the nearest ancestor [Focus] widget and
/// establish a relationship that will rebuild the widget when the focus
/// changes, use the [Focus.of] and [FocusScope.of] static methods.
///
/// To access the focused state of the nearest [Focus] widget, use
31 32 33
/// [FocusNode.hasFocus] from a build method, which also establishes a
/// relationship between the calling widget and the [Focus] widget that will
/// rebuild the calling widget when the focus changes.
34 35 36
///
/// Managing a [FocusNode] means managing its lifecycle, listening for changes
/// in focus, and re-parenting it when needed to keep the focus hierarchy in
37 38 39 40 41
/// sync with the widget hierarchy. This widget does all of those things for
/// you. See [FocusNode] for more information about the details of what node
/// management entails if you are not using a [Focus] widget and you need to do
/// it yourself.
///
42 43 44 45 46 47 48 49 50 51 52 53
/// If the [Focus] default constructor is used, then this widget will manage any
/// given [focusNode] by overwriting the appropriate values of the [focusNode]
/// with the values of [FocusNode.onKey], [FocusNode.onKeyEvent],
/// [FocusNode.skipTraversal], [FocusNode.canRequestFocus], and
/// [FocusNode.descendantsAreFocusable] whenever the [Focus] widget is updated.
///
/// If the [Focus.withExternalFocusNode] is used instead, then the values
/// returned by [onKey], [onKeyEvent], [skipTraversal], [canRequestFocus], and
/// [descendantsAreFocusable] will be the values in the external focus node, and
/// the external focus node's values will not be overwritten when the widget is
/// updated.
///
54 55 56 57
/// To collect a sub-tree of nodes into an exclusive group that restricts focus
/// traversal to the group, use a [FocusScope]. To collect a sub-tree of nodes
/// into a group that has a specific order to its traversal but allows the
/// traversal to escape the group, use a [FocusTraversalGroup].
58
///
59 60 61 62
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
63
///
64
/// {@tool dartpad}
65 66 67 68
/// This example shows how to manage focus using the [Focus] and [FocusScope]
/// widgets. See [FocusNode] for a similar example that doesn't use [Focus] or
/// [FocusScope].
///
69
/// ** See code in examples/api/lib/widgets/focus_scope/focus.0.dart **
70
/// {@end-tool}
Adam Barth's avatar
Adam Barth committed
71
///
72
/// {@tool dartpad}
73 74 75 76 77 78 79 80
/// This example shows how to wrap another widget in a [Focus] widget to make it
/// focusable. It wraps a [Container], and changes the container's color when it
/// is set as the [FocusManager.primaryFocus].
///
/// If you also want to handle mouse hover and/or keyboard actions on a widget,
/// consider using a [FocusableActionDetector], which combines several different
/// widgets to provide those capabilities.
///
81
/// ** See code in examples/api/lib/widgets/focus_scope/focus.1.dart **
82 83
/// {@end-tool}
///
84
/// {@tool dartpad}
85 86 87 88 89 90 91
/// This example shows how to focus a newly-created widget immediately after it
/// is created.
///
/// The focus node will not actually be given the focus until after the frame in
/// which it has requested focus is drawn, so it is OK to call
/// [FocusNode.requestFocus] on a node which is not yet in the focus tree.
///
92
/// ** See code in examples/api/lib/widgets/focus_scope/focus.2.dart **
93 94
/// {@end-tool}
///
95
/// See also:
Adam Barth's avatar
Adam Barth committed
96
///
97 98 99 100 101 102 103 104 105 106 107
///  * [FocusNode], which represents a node in the focus hierarchy and
///    [FocusNode]'s API documentation includes a detailed explanation of its role
///    in the overall focus system.
///  * [FocusScope], a widget that manages a group of focusable widgets using a
///    [FocusScopeNode].
///  * [FocusScopeNode], a node that collects focus nodes into a group for
///    traversal.
///  * [FocusManager], a singleton that manages the primary focus and
///    distributes key events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
108 109
///  * [FocusTraversalGroup], a widget that groups together and imposes a
///    traversal policy on the [Focus] nodes below it in the widget hierarchy.
110 111
class Focus extends StatefulWidget {
  /// Creates a widget that manages a [FocusNode].
112
  ///
113 114
  /// The [child] argument is required and must not be null.
  ///
115
  /// The [autofocus] argument must not be null.
116
  const Focus({
117
    super.key,
118
    required this.child,
119
    this.focusNode,
120
    this.parentNode,
121
    this.autofocus = false,
122
    this.onFocusChange,
123 124 125 126 127
    FocusOnKeyEventCallback? onKeyEvent,
    FocusOnKeyCallback? onKey,
    bool? canRequestFocus,
    bool? skipTraversal,
    bool? descendantsAreFocusable,
128
    bool? descendantsAreTraversable,
129
    this.includeSemantics = true,
130 131 132 133 134 135
    String? debugLabel,
  })  : _onKeyEvent = onKeyEvent,
        _onKey = onKey,
        _canRequestFocus = canRequestFocus,
        _skipTraversal = skipTraversal,
        _descendantsAreFocusable = descendantsAreFocusable,
136
        _descendantsAreTraversable = descendantsAreTraversable,
137 138
        _debugLabel = debugLabel,
        assert(child != null),
139
        assert(autofocus != null),
140
        assert(includeSemantics != null);
141

142 143 144 145 146 147
  /// Creates a Focus widget that uses the given [focusNode] as the source of
  /// truth for attributes on the node, rather than the attributes of this widget.
  const factory Focus.withExternalFocusNode({
    Key? key,
    required Widget child,
    required FocusNode focusNode,
148
    FocusNode? parentNode,
149 150 151 152 153 154 155 156
    bool autofocus,
    ValueChanged<bool>? onFocusChange,
    bool includeSemantics,
  }) = _FocusWithExternalFocusNode;

  // Indicates whether the widget's focusNode attributes should have priority
  // when then widget is updated.
  bool get _usingExternalFocus => false;
157

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
  /// The optional parent node to use when reparenting the [focusNode] for this
  /// [Focus] widget.
  ///
  /// If [parentNode] is null, then [Focus.maybeOf] is used to find the parent
  /// in the widget tree, which is typically what is desired, since it is easier
  /// to reason about the focus tree if it mirrors the shape of the widget tree.
  ///
  /// Set this property if the focus tree needs to have a different shape than
  /// the widget tree. This is typically in cases where a dialog is in an
  /// [Overlay] (or another part of the widget tree), and focus should
  /// behave as if the widgets in the overlay are descendants of the given
  /// [parentNode] for purposes of focus.
  ///
  /// Defaults to null.
  final FocusNode? parentNode;

174
  /// The child widget of this [Focus].
175
  ///
176
  /// {@macro flutter.widgets.ProxyWidget.child}
177
  final Widget child;
178

179 180 181 182 183
  /// {@template flutter.widgets.Focus.focusNode}
  /// An optional focus node to use as the focus node for this widget.
  ///
  /// If one is not supplied, then one will be automatically allocated, owned,
  /// and managed by this widget. The widget will be focusable even if a
184
  /// [focusNode] is not supplied. If supplied, the given [focusNode] will be
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
  /// _hosted_ by this widget, but not owned. See [FocusNode] for more
  /// information on what being hosted and/or owned implies.
  ///
  /// Supplying a focus node is sometimes useful if an ancestor to this widget
  /// wants to control when this widget has the focus. The owner will be
  /// responsible for calling [FocusNode.dispose] on the focus node when it is
  /// done with it, but this widget will attach/detach and reparent the node
  /// when needed.
  /// {@endtemplate}
  ///
  /// A non-null [focusNode] must be supplied if using the
  /// [Focus.withExternalFocusNode] constructor is used.
  final FocusNode? focusNode;

  /// {@template flutter.widgets.Focus.autofocus}
  /// True if this widget will be selected as the initial focus when no other
  /// node in its scope is currently focused.
  ///
  /// Ideally, there is only one widget with autofocus set in each [FocusScope].
  /// If there is more than one widget with autofocus set, then the first one
  /// added to the tree will get focus.
  ///
  /// Must not be null. Defaults to false.
  /// {@endtemplate}
  final bool autofocus;

  /// Handler called when the focus changes.
  ///
  /// Called with true if this widget's node gains focus, and false if it loses
214
  /// focus.
215 216 217 218
  final ValueChanged<bool>? onFocusChange;

  /// A handler for keys that are pressed when this object or one of its
  /// children has focus.
219
  ///
220
  /// Key events are first given to the [FocusNode] that has primary focus, and
221 222 223
  /// if its [onKeyEvent] method returns [KeyEventResult.ignored], then they are
  /// given to each ancestor node up the focus hierarchy in turn. If an event
  /// reaches the root of the hierarchy, it is discarded.
224 225 226 227 228 229
  ///
  /// This is not the way to get text input in the manner of a text field: it
  /// leaves out support for input method editors, and doesn't support soft
  /// keyboards in general. For text input, consider [TextField],
  /// [EditableText], or [CupertinoTextField] instead, which do support these
  /// things.
230 231
  FocusOnKeyEventCallback? get onKeyEvent => _onKeyEvent ?? focusNode?.onKeyEvent;
  final FocusOnKeyEventCallback? _onKeyEvent;
232

233 234
  /// A handler for keys that are pressed when this object or one of its
  /// children has focus.
235 236 237 238 239
  ///
  /// This is a legacy API based on [RawKeyEvent] and will be deprecated in the
  /// future. Prefer [onKeyEvent] instead.
  ///
  /// Key events are first given to the [FocusNode] that has primary focus, and
240 241 242 243 244 245 246 247 248
  /// if its [onKey] method return false, then they are given to each ancestor
  /// node up the focus hierarchy in turn. If an event reaches the root of the
  /// hierarchy, it is discarded.
  ///
  /// This is not the way to get text input in the manner of a text field: it
  /// leaves out support for input method editors, and doesn't support soft
  /// keyboards in general. For text input, consider [TextField],
  /// [EditableText], or [CupertinoTextField] instead, which do support these
  /// things.
249 250
  FocusOnKeyCallback? get onKey => _onKey ?? focusNode?.onKey;
  final FocusOnKeyCallback? _onKey;
251

252
  /// {@template flutter.widgets.Focus.canRequestFocus}
253 254
  /// If true, this widget may request the primary focus.
  ///
255
  /// Defaults to true. Set to false if you want the [FocusNode] this widget
256 257 258
  /// manages to do nothing when [FocusNode.requestFocus] is called on it. Does
  /// not affect the children of this node, and [FocusNode.hasFocus] can still
  /// return true if this node is the ancestor of the primary focus.
259
  ///
260 261
  /// This is different than [Focus.skipTraversal] because [Focus.skipTraversal]
  /// still allows the widget to be focused, just not traversed to.
262
  ///
263 264
  /// Setting [FocusNode.canRequestFocus] to false implies that the widget will
  /// also be skipped for traversal purposes.
265 266 267
  ///
  /// See also:
  ///
268 269 270 271
  /// * [FocusTraversalGroup], a widget that sets the traversal policy for its
  ///   descendants.
  /// * [FocusTraversalPolicy], a class that can be extended to describe a
  ///   traversal policy.
272
  /// {@endtemplate}
273 274 275 276 277 278 279 280 281 282 283 284 285 286
  bool get canRequestFocus => _canRequestFocus ?? focusNode?.canRequestFocus ?? true;
  final bool? _canRequestFocus;

  /// Sets the [FocusNode.skipTraversal] flag on the focus node so that it won't
  /// be visited by the [FocusTraversalPolicy].
  ///
  /// This is sometimes useful if a [Focus] widget should receive key events as
  /// part of the focus chain, but shouldn't be accessible via focus traversal.
  ///
  /// This is different from [FocusNode.canRequestFocus] because it only implies
  /// that the widget can't be reached via traversal, not that it can't be
  /// focused. It may still be focused explicitly.
  bool get skipTraversal => _skipTraversal ?? focusNode?.skipTraversal ?? false;
  final bool? _skipTraversal;
287

288 289 290 291
  /// {@template flutter.widgets.Focus.descendantsAreFocusable}
  /// If false, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true. Does not affect focusability of this node (just its
292
  /// descendants): for that, use [FocusNode.canRequestFocus].
293 294
  ///
  /// If any descendants are focused when this is set to false, they will be
295
  /// unfocused. When [descendantsAreFocusable] is set to true again, they will
296 297
  /// not be refocused, although they will be able to accept focus again.
  ///
298 299
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
300
  ///
301 302 303
  /// If a descendant node loses focus when this value is changed, the focus
  /// will move to the scope enclosing this node.
  ///
304 305
  /// See also:
  ///
306 307
  /// * [ExcludeFocus], a widget that uses this property to conditionally
  ///   exclude focus for a subtree.
308 309 310 311
  /// * [descendantsAreTraversable], which makes this widget's descendants
  ///   untraversable.
  /// * [ExcludeFocusTraversal], a widget that conditionally excludes focus
  ///   traversal for a subtree.
312 313 314 315
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
316
  /// {@endtemplate}
317 318 319
  bool get descendantsAreFocusable => _descendantsAreFocusable ?? focusNode?.descendantsAreFocusable ?? true;
  final bool? _descendantsAreFocusable;

320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
  /// {@template flutter.widgets.Focus.descendantsAreTraversable}
  /// If false, will make this widget's descendants untraversable.
  ///
  /// Defaults to true. Does not affect traversablility of this node (just its
  /// descendants): for that, use [FocusNode.skipTraversal].
  ///
  /// Does not affect the value of [FocusNode.skipTraversal] on the
  /// descendants. Does not affect focusability of the descendants.
  ///
  /// See also:
  ///
  /// * [ExcludeFocusTraversal], a widget that uses this property to
  ///   conditionally exclude focus traversal for a subtree.
  /// * [descendantsAreFocusable], which makes this widget's descendants
  ///   unfocusable.
  /// * [ExcludeFocus], a widget that conditionally excludes focus for a subtree.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
  /// {@endtemplate}
  bool get descendantsAreTraversable => _descendantsAreTraversable ?? focusNode?.descendantsAreTraversable ?? true;
  final bool? _descendantsAreTraversable;

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
  /// {@template flutter.widgets.Focus.includeSemantics}
  /// Include semantics information in this widget.
  ///
  /// If true, this widget will include a [Semantics] node that indicates the
  /// [SemanticsProperties.focusable] and [SemanticsProperties.focused]
  /// properties.
  ///
  /// It is not typical to set this to false, as that can affect the semantics
  /// information available to accessibility systems.
  ///
  /// Must not be null, defaults to true.
  /// {@endtemplate}
  final bool includeSemantics;

  /// A debug label for this widget.
  ///
  /// Not used for anything except to be printed in the diagnostic output from
  /// [toString] or [toStringDeep].
  ///
  /// To get a string with the entire tree, call [debugDescribeFocusTree]. To
  /// print it to the console call [debugDumpFocusTree].
  ///
  /// Defaults to null.
  String? get debugLabel => _debugLabel ?? focusNode?.debugLabel;
  final String? _debugLabel;
369

370 371
  /// Returns the [focusNode] of the [Focus] that most tightly encloses the
  /// given [BuildContext].
372
  ///
373 374
  /// If no [Focus] node is found before reaching the nearest [FocusScope]
  /// widget, or there is no [Focus] widget in scope, then this method will
375
  /// throw an exception.
376
  ///
377
  /// The `context` and `scopeOk` arguments must not be null.
378 379 380
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
381 382 383 384 385 386
  ///
  /// See also:
  ///
  ///  * [maybeOf], which is similar to this function, but will return null
  ///    instead of throwing if it doesn't find a [Focus] node.
  static FocusNode of(BuildContext context, { bool scopeOk = false }) {
387
    assert(context != null);
388
    assert(scopeOk != null);
389 390
    final _FocusMarker? marker = context.dependOnInheritedWidgetOfExactType<_FocusMarker>();
    final FocusNode? node = marker?.notifier;
391 392
    assert(() {
      if (node == null) {
393
        throw FlutterError(
394 395 396 397 398
          'Focus.of() was called with a context that does not contain a Focus widget.\n'
          'No Focus widget ancestor could be found starting from the context that was passed to '
          'Focus.of(). This can happen because you are using a widget that looks for a Focus '
          'ancestor, and do not have a Focus widget descendant in the nearest FocusScope.\n'
          'The context used was:\n'
399
          '  $context',
400 401
        );
      }
402 403 404 405
      return true;
    }());
    assert(() {
      if (!scopeOk && node is FocusScopeNode) {
406
        throw FlutterError(
407 408 409 410 411 412 413
          'Focus.of() was called with a context that does not contain a Focus between the given '
          'context and the nearest FocusScope widget.\n'
          'No Focus ancestor could be found starting from the context that was passed to '
          'Focus.of() to the point where it found the nearest FocusScope widget. This can happen '
          'because you are using a widget that looks for a Focus ancestor, and do not have a '
          'Focus widget ancestor in the current FocusScope.\n'
          'The context used was:\n'
414
          '  $context',
415 416
        );
      }
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
      return true;
    }());
    return node!;
  }

  /// Returns the [focusNode] of the [Focus] that most tightly encloses the
  /// given [BuildContext].
  ///
  /// If no [Focus] node is found before reaching the nearest [FocusScope]
  /// widget, or there is no [Focus] widget in scope, then this method will
  /// return null.
  ///
  /// The `context` and `scopeOk` arguments must not be null.
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
  ///
  /// See also:
  ///
  ///  * [of], which is similar to this function, but will throw an exception if
  ///    it doesn't find a [Focus] node instead of returning null.
  static FocusNode? maybeOf(BuildContext context, { bool scopeOk = false }) {
    assert(context != null);
    assert(scopeOk != null);
    final _FocusMarker? marker = context.dependOnInheritedWidgetOfExactType<_FocusMarker>();
    final FocusNode? node = marker?.notifier;
    if (node == null) {
      return null;
    }
    if (!scopeOk && node is FocusScopeNode) {
447 448 449
      return null;
    }
    return node;
450 451
  }

452 453 454
  /// Returns true if the nearest enclosing [Focus] widget's node is focused.
  ///
  /// A convenience method to allow build methods to write:
455 456 457 458 459 460
  /// `Focus.isAt(context)` to get whether or not the nearest [Focus] above them
  /// in the widget hierarchy currently has the input focus.
  ///
  /// Returns false if no [Focus] widget is found before reaching the nearest
  /// [FocusScope], or if the root of the focus tree is reached without finding
  /// a [Focus] widget.
461 462 463
  ///
  /// Calling this function creates a dependency that will rebuild the given
  /// context when the focus changes.
464
  static bool isAt(BuildContext context) => Focus.maybeOf(context)?.hasFocus ?? false;
465

466
  @override
467 468 469 470
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(StringProperty('debugLabel', debugLabel, defaultValue: null));
    properties.add(FlagProperty('autofocus', value: autofocus, ifTrue: 'AUTOFOCUS', defaultValue: false));
471 472
    properties.add(FlagProperty('canRequestFocus', value: canRequestFocus, ifFalse: 'NOT FOCUSABLE', defaultValue: false));
    properties.add(FlagProperty('descendantsAreFocusable', value: descendantsAreFocusable, ifFalse: 'DESCENDANTS UNFOCUSABLE', defaultValue: true));
473
    properties.add(FlagProperty('descendantsAreTraversable', value: descendantsAreTraversable, ifFalse: 'DESCENDANTS UNTRAVERSABLE', defaultValue: true));
474
    properties.add(DiagnosticsProperty<FocusNode>('focusNode', focusNode, defaultValue: null));
475 476 477
  }

  @override
478
  State<Focus> createState() => _FocusState();
479 480
}

481 482 483 484
// Implements the behavior differences when the Focus.withExternalFocusNode
// constructor is used.
class _FocusWithExternalFocusNode extends Focus {
  const _FocusWithExternalFocusNode({
485 486 487
    super.key,
    required super.child,
    required FocusNode super.focusNode,
488
    super.parentNode,
489 490 491 492
    super.autofocus,
    super.onFocusChange,
    super.includeSemantics,
  });
493 494 495 496 497 498 499 500 501 502 503 504 505 506

  @override
  bool get _usingExternalFocus => true;
  @override
  FocusOnKeyEventCallback? get onKeyEvent => focusNode!.onKeyEvent;
  @override
  FocusOnKeyCallback? get onKey => focusNode!.onKey;
  @override
  bool get canRequestFocus => focusNode!.canRequestFocus;
  @override
  bool get skipTraversal => focusNode!.skipTraversal;
  @override
  bool get descendantsAreFocusable => focusNode!.descendantsAreFocusable;
  @override
507 508
  bool? get _descendantsAreTraversable => focusNode!.descendantsAreTraversable;
  @override
509 510 511
  String? get debugLabel => focusNode!.debugLabel;
}

512
class _FocusState extends State<Focus> {
513 514
  FocusNode? _internalNode;
  FocusNode get focusNode => widget.focusNode ?? _internalNode!;
515 516 517
  late bool _hadPrimaryFocus;
  late bool _couldRequestFocus;
  late bool _descendantsWereFocusable;
518
  late bool _descendantsWereTraversable;
519
  bool _didAutofocus = false;
520
  FocusAttachment? _focusAttachment;
521 522 523 524 525 526 527 528 529 530

  @override
  void initState() {
    super.initState();
    _initNode();
  }

  void _initNode() {
    if (widget.focusNode == null) {
      // Only create a new node if the widget doesn't have one.
531 532
      // This calls a function instead of just allocating in place because
      // _createNode is overridden in _FocusScopeState.
533 534
      _internalNode ??= _createNode();
    }
535
    focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
536
    focusNode.descendantsAreTraversable = widget.descendantsAreTraversable;
537
    if (widget.skipTraversal != null) {
538
      focusNode.skipTraversal = widget.skipTraversal;
539
    }
540 541
    if (widget._canRequestFocus != null) {
      focusNode.canRequestFocus = widget._canRequestFocus!;
542
    }
543 544
    _couldRequestFocus = focusNode.canRequestFocus;
    _descendantsWereFocusable = focusNode.descendantsAreFocusable;
545
    _descendantsWereTraversable = focusNode.descendantsAreTraversable;
546
    _hadPrimaryFocus = focusNode.hasPrimaryFocus;
547
    _focusAttachment = focusNode.attach(context, onKeyEvent: widget.onKeyEvent, onKey: widget.onKey);
548

549
    // Add listener even if the _internalNode existed before, since it should
550
    // not be listening now if we're re-using a previous one because it should
551
    // have already removed its listener.
552
    focusNode.addListener(_handleFocusChanged);
553 554
  }

555 556 557
  FocusNode _createNode() {
    return FocusNode(
      debugLabel: widget.debugLabel,
558
      canRequestFocus: widget.canRequestFocus,
559
      descendantsAreFocusable: widget.descendantsAreFocusable,
560
      descendantsAreTraversable: widget.descendantsAreTraversable,
561
      skipTraversal: widget.skipTraversal,
562 563
    );
  }
564 565 566 567 568

  @override
  void dispose() {
    // Regardless of the node owner, we need to remove it from the tree and stop
    // listening to it.
569
    focusNode.removeListener(_handleFocusChanged);
570
    _focusAttachment!.detach();
571

572 573 574 575 576
    // Don't manage the lifetime of external nodes given to the widget, just the
    // internal node.
    _internalNode?.dispose();
    super.dispose();
  }
577 578 579 580

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
581
    _focusAttachment?.reparent();
582 583 584 585
    _handleAutofocus();
  }

  void _handleAutofocus() {
586
    if (!_didAutofocus && widget.autofocus) {
587
      FocusScope.of(context).autofocus(focusNode);
588 589 590 591 592
      _didAutofocus = true;
    }
  }

  @override
593 594
  void deactivate() {
    super.deactivate();
595 596 597 598 599 600 601
    // The focus node's location in the tree is no longer valid here. But
    // we can't unfocus or remove the node from the tree because if the widget
    // is moved to a different part of the tree (via global key) it should
    // retain its focus state. That's why we temporarily park it on the root
    // focus node (via reparent) until it either gets moved to a different part
    // of the tree (via didChangeDependencies) or until it is disposed.
    _focusAttachment?.reparent();
602 603 604 605 606 607
    _didAutofocus = false;
  }

  @override
  void didUpdateWidget(Focus oldWidget) {
    super.didUpdateWidget(oldWidget);
608
    assert(() {
609 610 611 612 613
      // Only update the debug label in debug builds.
      if (oldWidget.focusNode == widget.focusNode &&
          !widget._usingExternalFocus &&
          oldWidget.debugLabel != widget.debugLabel) {
        focusNode.debugLabel = widget.debugLabel;
614 615 616 617 618
      }
      return true;
    }());

    if (oldWidget.focusNode == widget.focusNode) {
619 620 621 622 623 624 625 626 627 628
      if (!widget._usingExternalFocus) {
        if (widget.onKey != focusNode.onKey) {
          focusNode.onKey = widget.onKey;
        }
        if (widget.onKeyEvent != focusNode.onKeyEvent) {
          focusNode.onKeyEvent = widget.onKeyEvent;
        }
        if (widget.skipTraversal != null) {
          focusNode.skipTraversal = widget.skipTraversal;
        }
629 630
        if (widget._canRequestFocus != null) {
          focusNode.canRequestFocus = widget._canRequestFocus!;
631 632
        }
        focusNode.descendantsAreFocusable = widget.descendantsAreFocusable;
633
        focusNode.descendantsAreTraversable = widget.descendantsAreTraversable;
634
      }
635
    } else {
636
      _focusAttachment!.detach();
637
      oldWidget.focusNode?.removeListener(_handleFocusChanged);
638
      _initNode();
639
    }
640

641 642 643
    if (oldWidget.autofocus != widget.autofocus) {
      _handleAutofocus();
    }
644 645 646
  }

  void _handleFocusChanged() {
647 648
    final bool hasPrimaryFocus = focusNode.hasPrimaryFocus;
    final bool canRequestFocus = focusNode.canRequestFocus;
649
    final bool descendantsAreFocusable = focusNode.descendantsAreFocusable;
650
    final bool descendantsAreTraversable = focusNode.descendantsAreTraversable;
651
    widget.onFocusChange?.call(focusNode.hasFocus);
652 653 654
    // Check the cached states that matter here, and call setState if they have
    // changed.
    if (_hadPrimaryFocus != hasPrimaryFocus) {
655
      setState(() {
656
        _hadPrimaryFocus = hasPrimaryFocus;
657 658
      });
    }
659
    if (_couldRequestFocus != canRequestFocus) {
660
      setState(() {
661
        _couldRequestFocus = canRequestFocus;
662 663
      });
    }
664
    if (_descendantsWereFocusable != descendantsAreFocusable) {
665
      setState(() {
666
        _descendantsWereFocusable = descendantsAreFocusable;
667 668
      });
    }
669 670 671 672 673
    if (_descendantsWereTraversable != descendantsAreTraversable) {
      setState(() {
        _descendantsWereTraversable = descendantsAreTraversable;
      });
    }
674 675 676 677
  }

  @override
  Widget build(BuildContext context) {
678
    _focusAttachment!.reparent(parent: widget.parentNode);
679 680 681
    Widget child = widget.child;
    if (widget.includeSemantics) {
      child = Semantics(
682 683
        focusable: _couldRequestFocus,
        focused: _hadPrimaryFocus,
684
        child: widget.child,
685 686 687 688 689
      );
    }
    return _FocusMarker(
      node: focusNode,
      child: child,
690 691 692 693
    );
  }
}

694 695 696 697 698 699 700 701 702 703
/// A [FocusScope] is similar to a [Focus], but also serves as a scope for its
/// descendants, restricting focus traversal to the scoped controls.
///
/// For example a new [FocusScope] is created automatically when a route is
/// pushed, keeping the focus traversal from moving to a control in a previous
/// route.
///
/// If you just want to group widgets together in a group so that they are
/// traversed in a particular order, but the focus can still leave the group,
/// use a [FocusTraversalGroup].
704 705 706 707 708 709 710
///
/// Like [Focus], [FocusScope] provides an [onFocusChange] as a way to be
/// notified when the focus is given to or removed from this widget.
///
/// The [onKey] argument allows specification of a key event handler that is
/// invoked when this node or one of its children has focus. Keys are handed to
/// the primary focused widget first, and then they propagate through the
711 712 713
/// ancestors of that node, stopping if one of them returns
/// [KeyEventResult.handled] from [onKey], indicating that it has handled the
/// event.
714
///
715 716 717 718 719 720
/// Managing a [FocusScopeNode] means managing its lifecycle, listening for
/// changes in focus, and re-parenting it when needed to keep the focus
/// hierarchy in sync with the widget hierarchy. This widget does all of those
/// things for you. See [FocusScopeNode] for more information about the details
/// of what node management entails if you are not using a [FocusScope] widget
/// and you need to do it yourself.
721 722 723 724 725 726 727
///
/// [FocusScopeNode]s remember the last [FocusNode] that was focused within
/// their descendants, and can move that focus to the next/previous node, or a
/// node in a particular direction when the [FocusNode.nextFocus],
/// [FocusNode.previousFocus], or [FocusNode.focusInDirection] are called on a
/// [FocusNode] or [FocusScopeNode].
///
728 729 730 731 732
/// To move the focus, use methods on [FocusNode] by getting the [FocusNode]
/// through the [of] method. For instance, to move the focus to the next node in
/// the focus traversal order, call `Focus.of(context).nextFocus()`. To unfocus
/// a widget, call `Focus.of(context).unfocus()`.
///
733
/// {@tool dartpad}
734 735 736 737
/// This example demonstrates using a [FocusScope] to restrict focus to a particular
/// portion of the app. In this case, restricting focus to the visible part of a
/// Stack.
///
738
/// ** See code in examples/api/lib/widgets/focus_scope/focus_scope.0.dart **
739
/// {@end-tool}
740
///
741 742
/// See also:
///
743 744 745 746 747 748 749 750 751
///  * [FocusScopeNode], which represents a scope node in the focus hierarchy.
///  * [FocusNode], which represents a node in the focus hierarchy and has an
///    explanation of the focus system.
///  * [Focus], a widget that manages a [FocusNode] and allows easy access to
///    managing focus without having to manage the node.
///  * [FocusManager], a singleton that manages the focus and distributes key
///    events to focused nodes.
///  * [FocusTraversalPolicy], an object used to determine how to move the focus
///    to other nodes.
752 753
///  * [FocusTraversalGroup], a widget used to configure the focus traversal
///    policy for a widget subtree.
754 755 756 757 758
class FocusScope extends Focus {
  /// Creates a widget that manages a [FocusScopeNode].
  ///
  /// The [child] argument is required and must not be null.
  ///
759
  /// The [autofocus] argument must not be null.
760
  const FocusScope({
761
    super.key,
762
    FocusScopeNode? node,
763
    super.parentNode,
764 765 766 767 768 769 770 771
    required super.child,
    super.autofocus,
    super.onFocusChange,
    super.canRequestFocus,
    super.skipTraversal,
    super.onKeyEvent,
    super.onKey,
    super.debugLabel,
772 773 774 775 776 777
  })  : assert(child != null),
        assert(autofocus != null),
        super(
          focusNode: node,
        );

778 779 780 781 782 783 784
  /// Creates a FocusScope widget that uses the given [focusScopeNode] as the
  /// source of truth for attributes on the node, rather than the attributes of
  /// this widget.
  const factory FocusScope.withExternalFocusNode({
    Key? key,
    required Widget child,
    required FocusScopeNode focusScopeNode,
785
    FocusNode? parentNode,
786 787 788 789
    bool autofocus,
    ValueChanged<bool>? onFocusChange,
  })  = _FocusScopeWithExternalFocusNode;

790 791 792 793 794 795 796 797 798
  /// Returns the [FocusScopeNode] of the [FocusScope] that most tightly
  /// encloses the given [context].
  ///
  /// If this node doesn't have a [Focus] widget ancestor, then the
  /// [FocusManager.rootScope] is returned.
  ///
  /// The [context] argument must not be null.
  static FocusScopeNode of(BuildContext context) {
    assert(context != null);
799 800
    final _FocusMarker? marker = context.dependOnInheritedWidgetOfExactType<_FocusMarker>();
    return marker?.notifier?.nearestScope ?? context.owner!.focusManager.rootScope;
801 802 803
  }

  @override
804
  State<Focus> createState() => _FocusScopeState();
805 806
}

807 808 809 810
// Implements the behavior differences when the FocusScope.withExternalFocusNode
// constructor is used.
class _FocusScopeWithExternalFocusNode extends FocusScope {
  const _FocusScopeWithExternalFocusNode({
811 812
    super.key,
    required super.child,
813
    required FocusScopeNode focusScopeNode,
814
    super.parentNode,
815 816
    super.autofocus,
    super.onFocusChange,
817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833
  }) : super(
    node: focusScopeNode,
  );

  @override
  bool get _usingExternalFocus => true;
  @override
  FocusOnKeyEventCallback? get onKeyEvent => focusNode!.onKeyEvent;
  @override
  FocusOnKeyCallback? get onKey => focusNode!.onKey;
  @override
  bool get canRequestFocus => focusNode!.canRequestFocus;
  @override
  bool get skipTraversal => focusNode!.skipTraversal;
  @override
  bool get descendantsAreFocusable => focusNode!.descendantsAreFocusable;
  @override
834 835
  bool get descendantsAreTraversable => focusNode!.descendantsAreTraversable;
  @override
836 837 838
  String? get debugLabel => focusNode!.debugLabel;
}

839 840 841 842 843
class _FocusScopeState extends _FocusState {
  @override
  FocusScopeNode _createNode() {
    return FocusScopeNode(
      debugLabel: widget.debugLabel,
844 845
      canRequestFocus: widget.canRequestFocus,
      skipTraversal: widget.skipTraversal,
846 847 848 849 850
    );
  }

  @override
  Widget build(BuildContext context) {
851
    _focusAttachment!.reparent(parent: widget.parentNode);
852
    return Semantics(
853
      explicitChildNodes: true,
854
      child: _FocusMarker(
855
        node: focusNode,
856
        child: widget.child,
857 858 859 860
      ),
    );
  }
}
861 862 863 864

// The InheritedWidget marker for Focus and FocusScope.
class _FocusMarker extends InheritedNotifier<FocusNode> {
  const _FocusMarker({
865
    required FocusNode node,
866
    required super.child,
867 868
  })  : assert(node != null),
        assert(child != null),
869
        super(notifier: node);
870
}
871 872 873 874

/// A widget that controls whether or not the descendants of this widget are
/// focusable.
///
875
/// Does not affect the value of [Focus.canRequestFocus] on the descendants.
876 877 878 879 880 881 882 883 884 885 886 887 888 889
///
/// See also:
///
///  * [Focus], a widget for adding and managing a [FocusNode] in the widget tree.
///  * [FocusTraversalGroup], a widget that groups widgets for focus traversal,
///    and can also be used in the same way as this widget by setting its
///    `descendantsAreFocusable` attribute.
class ExcludeFocus extends StatelessWidget {
  /// Const constructor for [ExcludeFocus] widget.
  ///
  /// The [excluding] argument must not be null.
  ///
  /// The [child] argument is required, and must not be null.
  const ExcludeFocus({
890
    super.key,
891
    this.excluding = true,
892
    required this.child,
893
  })  : assert(excluding != null),
894
        assert(child != null);
895 896 897 898 899 900

  /// If true, will make this widget's descendants unfocusable.
  ///
  /// Defaults to true.
  ///
  /// If any descendants are focused when this is set to true, they will be
901
  /// unfocused. When [excluding] is set to false again, they will not be
902 903
  /// refocused, although they will be able to accept focus again.
  ///
904 905
  /// Does not affect the value of [FocusNode.canRequestFocus] on the
  /// descendants.
906 907 908
  ///
  /// See also:
  ///
909 910 911 912 913 914
  /// * [Focus.descendantsAreFocusable], the attribute of a [Focus] widget that
  ///   controls this same property for focus widgets.
  /// * [FocusTraversalGroup], a widget used to group together and configure the
  ///   focus traversal policy for a widget subtree that has a
  ///   `descendantsAreFocusable` parameter to conditionally block focus for a
  ///   subtree.
915 916 917 918
  final bool excluding;

  /// The child widget of this [ExcludeFocus].
  ///
919
  /// {@macro flutter.widgets.ProxyWidget.child}
920 921 922 923 924 925 926
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return Focus(
      canRequestFocus: false,
      skipTraversal: true,
927
      includeSemantics: false,
928 929 930 931 932
      descendantsAreFocusable: !excluding,
      child: child,
    );
  }
}