Skip to content

Commit

Permalink
Reverts "Fixes ability to call nextFocus() on a node to focus its des…
Browse files Browse the repository at this point in the history
…cendant" (#136894)

Reverts flutter/flutter#136773
Initiated by: itsjustkevin
This change reverts the following previous change:
Original Description:
fixes flutter/flutter#134854
  • Loading branch information
auto-submit[bot] authored Oct 19, 2023
1 parent 8ab8767 commit c2bd2c1
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 122 deletions.
12 changes: 4 additions & 8 deletions packages/flutter/lib/src/widgets/focus_traversal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ abstract class FocusTraversalPolicy with Diagnosticable {
final FocusScopeNode scope = currentNode.nearestScope!;
FocusNode? candidate = scope.focusedChild;
if (ignoreCurrentFocus || candidate == null && scope.descendants.isNotEmpty) {
final Iterable<FocusNode> sorted = _sortAllDescendants(scope, currentNode).where((FocusNode node) => _canRequestTraversalFocus(node));
final Iterable<FocusNode> sorted = _sortAllDescendants(scope, currentNode);
if (sorted.isEmpty) {
candidate = null;
} else {
Expand Down Expand Up @@ -405,17 +405,13 @@ abstract class FocusTraversalPolicy with Diagnosticable {
@protected
Iterable<FocusNode> sortDescendants(Iterable<FocusNode> descendants, FocusNode currentNode);

static bool _canRequestTraversalFocus(FocusNode node) {
return node.canRequestFocus && !node.skipTraversal;
}

static Iterable<FocusNode> _getDescendantsWithoutExpandingScope(FocusNode node) {
final List<FocusNode> result = <FocusNode>[];
for (final FocusNode child in node.children) {
result.add(child);
if (child is! FocusScopeNode) {
result.addAll(_getDescendantsWithoutExpandingScope(child));
}
result.add(child);
}
return result;
}
Expand Down Expand Up @@ -492,15 +488,15 @@ abstract class FocusTraversalPolicy with Diagnosticable {
// They were left in above because they were needed to find their members
// during sorting.
sortedDescendants.removeWhere((FocusNode node) {
return node != currentNode && !_canRequestTraversalFocus(node);
return node != currentNode && (!node.canRequestFocus || node.skipTraversal);
});

// Sanity check to make sure that the algorithm above doesn't diverge from
// the one in FocusScopeNode.traversalDescendants in terms of which nodes it
// finds.
assert((){
final Set<FocusNode> difference = sortedDescendants.toSet().difference(scope.traversalDescendants.toSet());
if (!_canRequestTraversalFocus(currentNode)) {
if (currentNode.skipTraversal || !currentNode.canRequestFocus) {
// The scope.traversalDescendants will not contain currentNode if it
// skips traversal or not focusable.
assert(
Expand Down
116 changes: 2 additions & 114 deletions packages/flutter/test/widgets/focus_traversal_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -96,113 +96,6 @@ void main() {
expect(scope.hasFocus, isTrue);
});

testWidgetsWithLeakTracking('focus traversal should work case 1', (WidgetTester tester) async {
final FocusNode outer1 = FocusNode(debugLabel: 'outer1', skipTraversal: true);
final FocusNode outer2 = FocusNode(debugLabel: 'outer2', skipTraversal: true);
final FocusNode inner1 = FocusNode(debugLabel: 'inner1', );
final FocusNode inner2 = FocusNode(debugLabel: 'inner2', );
addTearDown(() {
outer1.dispose();
outer2.dispose();
inner1.dispose();
inner2.dispose();
});

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: FocusTraversalGroup(
child: Row(
children: <Widget>[
FocusScope(
child: Focus(
focusNode: outer1,
child: Focus(
focusNode: inner1,
child: const SizedBox(width: 10, height: 10),
),
),
),
FocusScope(
child: Focus(
focusNode: outer2,
// Add a padding to ensure both Focus widgets have different
// sizes.
child: Padding(
padding: const EdgeInsets.all(5),
child: Focus(
focusNode: inner2,
child: const SizedBox(width: 10, height: 10),
),
),
),
),
],
),
),
),
);

expect(FocusManager.instance.primaryFocus, isNull);
inner1.requestFocus();
await tester.pump();
expect(FocusManager.instance.primaryFocus, inner1);
outer2.nextFocus();
await tester.pump();
expect(FocusManager.instance.primaryFocus, inner2);
});

testWidgetsWithLeakTracking('focus traversal should work case 2', (WidgetTester tester) async {
final FocusNode outer1 = FocusNode(debugLabel: 'outer1', skipTraversal: true);
final FocusNode outer2 = FocusNode(debugLabel: 'outer2', skipTraversal: true);
final FocusNode inner1 = FocusNode(debugLabel: 'inner1', );
final FocusNode inner2 = FocusNode(debugLabel: 'inner2', );
addTearDown(() {
outer1.dispose();
outer2.dispose();
inner1.dispose();
inner2.dispose();
});

await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: FocusTraversalGroup(
child: Row(
children: <Widget>[
FocusScope(
child: Focus(
focusNode: outer1,
child: Focus(
focusNode: inner1,
child: const SizedBox(width: 10, height: 10),
),
),
),
FocusScope(
child: Focus(
focusNode: outer2,
child: Focus(
focusNode: inner2,
child: const SizedBox(width: 10, height: 10),
),
),
),
],
),
),
),
);

expect(FocusManager.instance.primaryFocus, isNull);
inner1.requestFocus();
await tester.pump();
expect(FocusManager.instance.primaryFocus, inner1);
outer2.nextFocus();
await tester.pump();
expect(FocusManager.instance.primaryFocus, inner2);
});

testWidgetsWithLeakTracking('Move focus to next node.', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final GlobalKey key2 = GlobalKey(debugLabel: '2');
Expand Down Expand Up @@ -823,13 +716,8 @@ void main() {
final bool didFindNode = node1.nextFocus();
await tester.pump();
expect(didFindNode, isTrue);
if (canRequestFocus) {
expect(node1.hasPrimaryFocus, isTrue);
expect(node2.hasPrimaryFocus, isFalse);
} else {
expect(node1.hasPrimaryFocus, isFalse);
expect(node2.hasPrimaryFocus, isTrue);
}
expect(node1.hasPrimaryFocus, isFalse);
expect(node2.hasPrimaryFocus, isTrue);
}
});

Expand Down

0 comments on commit c2bd2c1

Please sign in to comment.