@@ -119,8 +119,8 @@ class FocusAttachment {
119119 assert (_node != null );
120120 if (isAttached) {
121121 assert (_node.context != null );
122- parent ?? = Focus .of (_node.context, nullOk: true );
123- parent ?? = FocusScope . of ( _node.context) ;
122+ parent ?? = Focus .of (_node.context, nullOk: true , scopeOk : true );
123+ parent ?? = _node.context.owner.focusManager.rootScope ;
124124 assert (parent != null );
125125 parent._reparent (_node);
126126 }
@@ -421,7 +421,10 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
421421 /// its descendants.
422422 /// - [FocusTraversalPolicy] , a class that can be extended to describe a
423423 /// traversal policy.
424- bool get canRequestFocus => _canRequestFocus && (enclosingScope == null || enclosingScope.canRequestFocus);
424+ bool get canRequestFocus {
425+ final FocusScopeNode scope = enclosingScope;
426+ return _canRequestFocus && (scope == null || scope.canRequestFocus);
427+ }
425428 bool _canRequestFocus;
426429 @mustCallSuper
427430 set canRequestFocus (bool value) {
@@ -450,6 +453,8 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
450453 FocusOnKeyCallback _onKey;
451454
452455 FocusManager _manager;
456+ List <FocusNode > _ancestors;
457+ List <FocusNode > _descendants;
453458 bool _hasKeyboardToken = false ;
454459
455460 /// Returns the parent node for this object.
@@ -471,7 +476,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
471476 return const < FocusNode > [];
472477 }
473478 return children.where (
474- (FocusNode node) => ! node.skipTraversal && node._canRequestFocus ,
479+ (FocusNode node) => ! node.skipTraversal && node.canRequestFocus ,
475480 );
476481 }
477482
@@ -492,11 +497,16 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
492497
493498 /// An [Iterable] over the hierarchy of children below this one, in
494499 /// depth-first order.
495- Iterable <FocusNode > get descendants sync * {
496- for (FocusNode child in _children) {
497- yield * child.descendants;
498- yield child;
500+ Iterable <FocusNode > get descendants {
501+ if (_descendants == null ) {
502+ final List <FocusNode > result = < FocusNode > [];
503+ for (FocusNode child in _children) {
504+ result.addAll (child.descendants);
505+ result.add (child);
506+ }
507+ _descendants = result;
499508 }
509+ return _descendants;
500510 }
501511
502512 /// Returns all descendants which do not have the [skipTraversal] flag set.
@@ -507,12 +517,17 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
507517 /// Iterates the ancestors of this node starting at the parent and iterating
508518 /// over successively more remote ancestors of this node, ending at the root
509519 /// [FocusScope] ([FocusManager.rootScope] ).
510- Iterable <FocusNode > get ancestors sync * {
511- FocusNode parent = _parent;
512- while (parent != null ) {
513- yield parent;
514- parent = parent._parent;
520+ Iterable <FocusNode > get ancestors {
521+ if (_ancestors == null ) {
522+ final List <FocusNode > result = < FocusNode > [];
523+ FocusNode parent = _parent;
524+ while (parent != null ) {
525+ result.add (parent);
526+ parent = parent._parent;
527+ }
528+ _ancestors = result;
515529 }
530+ return _ancestors;
516531 }
517532
518533 /// Whether this node has input focus.
@@ -710,13 +725,18 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
710725
711726 node._parent = null ;
712727 _children.remove (node);
728+ for (FocusNode ancestor in ancestors) {
729+ ancestor._descendants = null ;
730+ }
731+ _descendants = null ;
713732 assert (_manager == null || ! _manager.rootScope.descendants.contains (node));
714733 }
715734
716735 void _updateManager (FocusManager manager) {
717736 _manager = manager;
718737 for (FocusNode descendant in descendants) {
719738 descendant._manager = manager;
739+ descendant._ancestors = null ;
720740 }
721741 }
722742
@@ -737,7 +757,11 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
737757 child._parent? ._removeChild (child, removeScopeFocus: oldScope != nearestScope);
738758 _children.add (child);
739759 child._parent = this ;
760+ child._ancestors = null ;
740761 child._updateManager (_manager);
762+ for (FocusNode ancestor in child.ancestors) {
763+ ancestor._descendants = null ;
764+ }
741765 if (hadFocus) {
742766 // Update the focus chain for the current focus without changing it.
743767 _manager? .primaryFocus? ._setAsFocusedChild ();
@@ -1266,15 +1290,8 @@ class FocusManager with DiagnosticableTreeMixin {
12661290 assert (_focusDebug ('No primary focus for key event, ignored: $event ' ));
12671291 return ;
12681292 }
1269- Iterable <FocusNode > allNodes (FocusNode node) sync * {
1270- yield node;
1271- for (FocusNode ancestor in node.ancestors) {
1272- yield ancestor;
1273- }
1274- }
1275-
12761293 bool handled = false ;
1277- for (FocusNode node in allNodes ( _primaryFocus) ) {
1294+ for (FocusNode node in < FocusNode > [ _primaryFocus, ..._primaryFocus.ancestors] ) {
12781295 if (node.onKey != null && node.onKey (node, event)) {
12791296 assert (_focusDebug ('Node $node handled key event $event .' ));
12801297 handled = true ;
@@ -1338,7 +1355,7 @@ class FocusManager with DiagnosticableTreeMixin {
13381355 final FocusNode previousFocus = _primaryFocus;
13391356 if (_primaryFocus == null && _nextFocus == null ) {
13401357 // If we don't have any current focus, and nobody has asked to focus yet,
1341- // then pick a first one using widget order as a default .
1358+ // then revert to the root scope .
13421359 _nextFocus = rootScope;
13431360 }
13441361 if (_nextFocus != null && _nextFocus != _primaryFocus) {
0 commit comments