Revert "TextField terminal the enter and space raw key events by default (#82671)" (#84739) (#84746)
Co-authored-by: LongCatIsLooong <31859944+LongCatIsLooong@users.noreply.github.com>
diff --git a/packages/flutter/lib/src/cupertino/text_field.dart b/packages/flutter/lib/src/cupertino/text_field.dart
index ba5ed40..7b7489b 100644
--- a/packages/flutter/lib/src/cupertino/text_field.dart
+++ b/packages/flutter/lib/src/cupertino/text_field.dart
@@ -507,30 +507,6 @@
final TextEditingController? controller;
/// {@macro flutter.widgets.Focus.focusNode}
- ///
- /// ## Key handling
- ///
- /// By default, [CupertinoTextField] absorbs key events of the Space key and
- /// Enter key, because they are commonly used as both shortcuts and text field
- /// inputs. This means that, if these keys are pressed when
- /// [CupertinoTextField] is the primary focus, they will not be sent to other
- /// enclosing widgets.
- ///
- /// If [FocusNode.onKey] is not null, this filter is bypassed. In the likely
- /// case that this filter is still desired, check these keys and return
- /// [KeyEventResult.skipRemainingHandlers].
- ///
- /// ```dart
- /// final FocusNode focusNode = FocusNode(
- /// onKey: (FocusNode node, RawKeyEvent event) {
- /// if (event.logicalKey == LogicalKeyboardKey.space
- /// || event.logicalKey == LogicalKeyboardKey.enter) {
- /// return KeyEventResult.skipRemainingHandlers;
- /// }
- /// // Now process the event as desired.
- /// },
- /// );
- /// ```
final FocusNode? focusNode;
/// Controls the [BoxDecoration] of the box behind the text input.
@@ -1091,25 +1067,11 @@
);
}
- KeyEventResult _handleRawKeyEvent(FocusNode node, RawKeyEvent event) {
- assert(node.hasFocus);
- // TextField uses "enter" to finish the input or create a new line, and "space" as
- // a normal input character, so we default to terminate the handling of these
- // two keys to avoid ancestor behaving incorrectly for handling the two keys
- // (such as `ListTile` or `Material`).
- if (event.logicalKey == LogicalKeyboardKey.space
- || event.logicalKey == LogicalKeyboardKey.enter) {
- return KeyEventResult.skipRemainingHandlers;
- }
- return KeyEventResult.ignored;
- }
-
@override
Widget build(BuildContext context) {
super.build(context); // See AutomaticKeepAliveClientMixin.
assert(debugCheckHasDirectionality(context));
final TextEditingController controller = _effectiveController;
- final FocusNode focusNode = _effectiveFocusNode;
TextSelectionControls? textSelectionControls = widget.selectionControls;
VoidCallback? handleDidGainAccessibilityFocus;
@@ -1127,8 +1089,8 @@
handleDidGainAccessibilityFocus = () {
// macOS automatically activated the TextField when it receives
// accessibility focus.
- if (!focusNode.hasFocus && focusNode.canRequestFocus) {
- focusNode.requestFocus();
+ if (!_effectiveFocusNode.hasFocus && _effectiveFocusNode.canRequestFocus) {
+ _effectiveFocusNode.requestFocus();
}
};
break;
@@ -1191,7 +1153,7 @@
final Color selectionColor = CupertinoTheme.of(context).primaryColor.withOpacity(0.2);
- Widget paddedEditable = Padding(
+ final Widget paddedEditable = Padding(
padding: widget.padding,
child: RepaintBoundary(
child: UnmanagedRestorationScope(
@@ -1203,7 +1165,7 @@
toolbarOptions: widget.toolbarOptions,
showCursor: widget.showCursor,
showSelectionHandles: _showSelectionHandles,
- focusNode: focusNode,
+ focusNode: _effectiveFocusNode,
keyboardType: widget.keyboardType,
textInputAction: widget.textInputAction,
textCapitalization: widget.textCapitalization,
@@ -1253,15 +1215,6 @@
),
);
- if (focusNode.onKey == null) {
- paddedEditable = Focus(
- onKey: _handleRawKeyEvent,
- includeSemantics: false,
- skipTraversal: true,
- child: paddedEditable,
- );
- }
-
return Semantics(
enabled: enabled,
onTap: !enabled || widget.readOnly ? null : () {
diff --git a/packages/flutter/lib/src/material/text_field.dart b/packages/flutter/lib/src/material/text_field.dart
index 10d2b04..cdcad90 100644
--- a/packages/flutter/lib/src/material/text_field.dart
+++ b/packages/flutter/lib/src/material/text_field.dart
@@ -486,30 +486,6 @@
///
/// This widget builds an [EditableText] and will ensure that the keyboard is
/// showing when it is tapped by calling [EditableTextState.requestKeyboard()].
- ///
- /// ## Key handling
- ///
- /// By default, [TextField] absorbs key events of the Space key and Enter key,
- /// because they are commonly used as both shortcuts and text field inputs.
- /// This means that, if these keys are pressed when [TextField] is the
- /// primary focus, they will not be sent to other widgets (such as triggering
- /// an enclosing [ListTile]).
- ///
- /// If [FocusNode.onKey] is not null, this filter is bypassed. In the likely
- /// case that this filter is still desired, check these keys and return
- /// [KeyEventResult.skipRemainingHandlers].
- ///
- /// ```dart
- /// final FocusNode focusNode = FocusNode(
- /// onKey: (FocusNode node, RawKeyEvent event) {
- /// if (event.logicalKey == LogicalKeyboardKey.space
- /// || event.logicalKey == LogicalKeyboardKey.enter) {
- /// return KeyEventResult.skipRemainingHandlers;
- /// }
- /// // Now process the event as desired.
- /// },
- /// );
- /// ```
final FocusNode? focusNode;
/// The decoration to show around the text field.
@@ -1135,19 +1111,6 @@
}
}
- KeyEventResult _handleRawKeyEvent(FocusNode node, RawKeyEvent event) {
- assert(node.hasFocus);
- // TextField uses "enter" to finish the input or create a new line, and "space" as
- // a normal input character, so we default to terminate the handling of these
- // two keys to avoid ancestor behaving incorrectly for handling the two keys
- // (such as `ListTile` or `Material`).
- if (event.logicalKey == LogicalKeyboardKey.space
- || event.logicalKey == LogicalKeyboardKey.enter) {
- return KeyEventResult.skipRemainingHandlers;
- }
- return KeyEventResult.ignored;
- }
-
@override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
@@ -1300,15 +1263,6 @@
),
);
- if (focusNode.onKey == null) {
- child = Focus(
- onKey: _handleRawKeyEvent,
- includeSemantics: false,
- skipTraversal: true,
- child: child,
- );
- }
-
if (widget.decoration != null) {
child = AnimatedBuilder(
animation: Listenable.merge(<Listenable>[ focusNode, controller ]),
diff --git a/packages/flutter/test/cupertino/text_field_test.dart b/packages/flutter/test/cupertino/text_field_test.dart
index 5404ddb..daf43f3 100644
--- a/packages/flutter/test/cupertino/text_field_test.dart
+++ b/packages/flutter/test/cupertino/text_field_test.dart
@@ -4779,69 +4779,4 @@
expect(disabledColor, isSameColorAs(const Color(0xFFFAFAFA)));
},
);
-
- // Regression test for https://github.com/flutter/flutter/issues/81233
- testWidgets('CupertinoTextField should terminate the `space` and `enter` raw key events by default', (WidgetTester tester) async {
- final Set<FocusNode> outerReceivedAnEvent = <FocusNode>{};
- final FocusNode outerFocusNode = FocusNode(debugLabel: 'outerFocusNode');
- KeyEventResult outerHandleEvent(FocusNode node, RawKeyEvent event) {
- outerReceivedAnEvent.add(node);
- return KeyEventResult.handled;
- }
- outerFocusNode.onKey = outerHandleEvent;
-
- final Set<FocusNode> innerReceivedAnEvent = <FocusNode>{};
- final FocusNode innerFocusNode = FocusNode(debugLabel: 'innerFocusNode');
-
- Future<void> sendEvent(LogicalKeyboardKey key) async {
- await tester.sendKeyEvent(key, platform: 'windows');
- }
-
- Widget buildFrame() {
- return CupertinoApp(
- home: Center(
- child: Focus(
- onKey: outerFocusNode.onKey,
- focusNode: outerFocusNode,
- child: CupertinoTextField(
- focusNode: innerFocusNode,
- ),
- ),
- ),
- );
- }
-
- await tester.pumpWidget(buildFrame());
- innerFocusNode.requestFocus();
- await tester.pump();
-
- // The inner TextField's focus node terminal the raw key event by default.
- await sendEvent(LogicalKeyboardKey.space);
- expect(outerReceivedAnEvent.length, 0);
-
- await sendEvent(LogicalKeyboardKey.enter);
- expect(outerReceivedAnEvent.length, 0);
-
- // The `onKey` of the focus node of the TextField can be customized.
- KeyEventResult innerHandleEvent(FocusNode node, RawKeyEvent event) {
- innerReceivedAnEvent.add(node);
- // The key event has not been handled, and the event should continue to be
- // propagated to the outer key event handlers.
- return KeyEventResult.ignored;
- }
- innerFocusNode.onKey = innerHandleEvent;
- await tester.pumpWidget(buildFrame());
-
- await sendEvent(LogicalKeyboardKey.space);
-
- expect(innerReceivedAnEvent.length, 1);
- expect(outerReceivedAnEvent.length, 1);
-
- outerReceivedAnEvent.clear();
- innerReceivedAnEvent.clear();
-
- await sendEvent(LogicalKeyboardKey.enter);
- expect(outerReceivedAnEvent.length, 1);
- expect(innerReceivedAnEvent.length, 1);
- }, skip: kIsWeb);
}
diff --git a/packages/flutter/test/material/text_field_test.dart b/packages/flutter/test/material/text_field_test.dart
index 178dade..7efe682 100644
--- a/packages/flutter/test/material/text_field_test.dart
+++ b/packages/flutter/test/material/text_field_test.dart
@@ -4537,69 +4537,6 @@
await tester.pump();
}
- // Regression test for https://github.com/flutter/flutter/issues/81233
- testWidgets('TextField should terminate the `space` and `enter` raw key events by default', (WidgetTester tester) async {
- final Set<FocusNode> outerReceivedAnEvent = <FocusNode>{};
- final FocusNode outerFocusNode = FocusNode();
- KeyEventResult outerHandleEvent(FocusNode node, RawKeyEvent event) {
- outerReceivedAnEvent.add(node);
- return KeyEventResult.handled;
- }
- outerFocusNode.onKey = outerHandleEvent;
-
- final Set<FocusNode> innerReceivedAnEvent = <FocusNode>{};
- final FocusNode innerFocusNode = FocusNode();
-
- Future<void> sendEvent(LogicalKeyboardKey key) async {
- await tester.sendKeyEvent(key, platform: 'windows');
- }
-
- Widget buildFrame() {
- return MaterialApp(
- home: Material(
- child: Focus(
- onKey: outerFocusNode.onKey,
- focusNode: outerFocusNode,
- child: TextField(
- focusNode: innerFocusNode,
- ),
- ),
- ),
- );
- }
- await tester.pumpWidget(buildFrame());
- innerFocusNode.requestFocus();
- await tester.pump();
-
- // The inner TextField's focus node terminal the raw key event by default.
- await sendEvent(LogicalKeyboardKey.space);
- expect(outerReceivedAnEvent.length, 0);
-
- await sendEvent(LogicalKeyboardKey.enter);
- expect(outerReceivedAnEvent.length, 0);
-
- // The `onKey` of the focus node of the TextField can be customized.
- KeyEventResult innerHandleEvent(FocusNode node, RawKeyEvent event) {
- innerReceivedAnEvent.add(node);
- // The key event has not been handled, and the event should continue to be
- // propagated to the outer key event handlers.
- return KeyEventResult.ignored;
- }
- innerFocusNode.onKey = innerHandleEvent;
- await tester.pumpWidget(buildFrame());
-
- await sendEvent(LogicalKeyboardKey.space);
- expect(outerReceivedAnEvent.length, 1);
- expect(innerReceivedAnEvent.length, 1);
-
- outerReceivedAnEvent.clear();
- innerReceivedAnEvent.clear();
-
- await sendEvent(LogicalKeyboardKey.enter);
- expect(outerReceivedAnEvent.length, 1);
- expect(innerReceivedAnEvent.length, 1);
- }, skip: areKeyEventsHandledByPlatform);
-
testWidgets('Shift test 1', (WidgetTester tester) async {
await setupWidget(tester);
const String testValue = 'a big house';