Unverified Commit 6d8c850e authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter] tab navigation does not notify the focus scope node (#86141)

parent 731360fd
...@@ -2011,11 +2011,8 @@ class _FocusTrap extends SingleChildRenderObjectWidget { ...@@ -2011,11 +2011,8 @@ class _FocusTrap extends SingleChildRenderObjectWidget {
} }
class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior { class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
_RenderFocusTrap(this._focusScopeNode) { _RenderFocusTrap(this._focusScopeNode);
focusScopeNode.addListener(_currentFocusListener);
}
FocusNode? currentFocus;
Rect? currentFocusRect; Rect? currentFocusRect;
Expando<BoxHitTestResult> cachedResults = Expando<BoxHitTestResult>(); Expando<BoxHitTestResult> cachedResults = Expando<BoxHitTestResult>();
...@@ -2024,13 +2021,7 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior { ...@@ -2024,13 +2021,7 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
set focusScopeNode(FocusScopeNode value) { set focusScopeNode(FocusScopeNode value) {
if (focusScopeNode == value) if (focusScopeNode == value)
return; return;
focusScopeNode.removeListener(_currentFocusListener);
_focusScopeNode = value; _focusScopeNode = value;
focusScopeNode.addListener(_currentFocusListener);
}
void _currentFocusListener() {
currentFocus = focusScopeNode.focusedChild;
} }
@override @override
...@@ -2069,11 +2060,11 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior { ...@@ -2069,11 +2060,11 @@ class _RenderFocusTrap extends RenderProxyBoxWithHitTestBehavior {
|| event.buttons != kPrimaryButton || event.buttons != kPrimaryButton
|| event.kind != PointerDeviceKind.mouse || event.kind != PointerDeviceKind.mouse
|| _shouldIgnoreEvents || _shouldIgnoreEvents
|| currentFocus == null) { || _focusScopeNode.focusedChild == null) {
return; return;
} }
final BoxHitTestResult? result = cachedResults[entry]; final BoxHitTestResult? result = cachedResults[entry];
final FocusNode? focusNode = currentFocus; final FocusNode? focusNode = _focusScopeNode.focusedChild;
if (focusNode == null || result == null) if (focusNode == null || result == null)
return; return;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
...@@ -429,4 +430,62 @@ void main() { ...@@ -429,4 +430,62 @@ void main() {
expect(focusNodeA.hasFocus, false); expect(focusNodeA.hasFocus, false);
expect(focusNodeB.hasFocus, true); expect(focusNodeB.hasFocus, true);
}, variant: TargetPlatformVariant.desktop()); }, variant: TargetPlatformVariant.desktop());
testWidgets('A Focused text-field will lose focus when clicking outside of its hitbox with a mouse on desktop after tab navigation', (WidgetTester tester) async {
final FocusNode focusNodeA = FocusNode();
final FocusNode focusNodeB = FocusNode();
final Key key = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Material(
child: ListView(
children: <Widget>[
const TextField(),
const TextField(),
TextField(
focusNode: focusNodeA,
),
Container(
key: key,
height: 200,
),
TextField(
focusNode: focusNodeB,
),
],
),
),
),
);
// Tab over to the 3rd text field.
for (int i = 0; i < 3; i += 1) {
await tester.sendKeyDownEvent(LogicalKeyboardKey.tab);
await tester.sendKeyUpEvent(LogicalKeyboardKey.tab);
}
expect(focusNodeA.hasFocus, true);
expect(focusNodeB.hasFocus, false);
// Click on the container to not hit either text field.
final TestGesture down2 = await tester.startGesture(tester.getCenter(find.byKey(key)), kind: PointerDeviceKind.mouse);
await tester.pump();
await tester.pumpAndSettle();
await down2.up();
await down2.removePointer();
expect(focusNodeA.hasFocus, false);
expect(focusNodeB.hasFocus, false);
// Second text field can still gain focus.
final TestGesture down3 = await tester.startGesture(tester.getCenter(find.byType(TextField).last), kind: PointerDeviceKind.mouse);
await tester.pump();
await tester.pumpAndSettle();
await down3.up();
await down3.removePointer();
expect(focusNodeA.hasFocus, false);
expect(focusNodeB.hasFocus, true);
}, variant: TargetPlatformVariant.desktop());
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment