fix(tv): preserve native text input routing

This commit is contained in:
edde746
2026-05-19 11:17:44 +02:00
parent 48cf8accfa
commit d2650667b8
7 changed files with 178 additions and 9 deletions
+39
View File
@@ -31,6 +31,45 @@ void main() {
expect(events[1], isA<KeyUpEvent>());
expect(events.map((event) => event.deviceType), everyElement(ui.KeyEventDeviceType.directionalPad));
});
testWidgets('simulateKeyPress stops at skipRemainingHandlers', (tester) async {
final childEvents = <KeyEvent>[];
final parentEvents = <KeyEvent>[];
late BuildContext childContext;
await tester.pumpWidget(
MaterialApp(
home: Focus(
onKeyEvent: (_, event) {
parentEvents.add(event);
return KeyEventResult.handled;
},
child: Focus(
autofocus: true,
onKeyEvent: (_, event) {
childEvents.add(event);
return KeyEventResult.skipRemainingHandlers;
},
child: Builder(
builder: (context) {
childContext = context;
return const SizedBox.shrink();
},
),
),
),
),
);
Focus.of(childContext).requestFocus();
await tester.pump();
simulateKeyPress(LogicalKeyboardKey.enter);
await tester.pump();
await tester.pump();
expect(childEvents, hasLength(2));
expect(parentEvents, isEmpty);
});
}
Future<List<KeyEvent>> _pumpKeyEventRecorder(WidgetTester tester) async {
@@ -337,6 +337,55 @@ void main() {
expect(find.byType(Dialog), findsNothing);
});
testWidgets('Android TV native text input focus is reported to platform', (tester) async {
TvDetectionService.debugSetAppleTVOverride(null);
await TvDetectionService.getInstance(forceTv: true);
TvDetectionService.setForceTVSync(true);
const channel = MethodChannel('com.plezy/text_input');
final calls = <MethodCall>[];
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, (call) async {
calls.add(call);
return null;
});
addTearDown(
() => TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler(channel, null),
);
final controller = TextEditingController();
final fieldFocusNode = FocusNode(debugLabel: 'server_url_field');
final otherFocusNode = FocusNode(debugLabel: 'other');
addTearDown(controller.dispose);
addTearDown(fieldFocusNode.dispose);
addTearDown(otherFocusNode.dispose);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: Column(
children: [
FocusableTextFormField(controller: controller, focusNode: fieldFocusNode),
Focus(focusNode: otherFocusNode, child: const SizedBox.shrink()),
],
),
),
),
);
fieldFocusNode.requestFocus();
await tester.pump();
await tester.pump();
expect(calls.last.method, 'setNativeTextInputFocused');
expect(calls.last.arguments, isTrue);
otherFocusNode.requestFocus();
await tester.pump();
await tester.pump();
expect(calls.last.method, 'setNativeTextInputFocused');
expect(calls.last.arguments, isFalse);
});
testWidgets('Android TV physical keyboard still uses field navigation', (tester) async {
TvDetectionService.debugSetAppleTVOverride(null);
await TvDetectionService.getInstance(forceTv: true);