Unverified Commit 75e9318d authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Revert "TextField terminal the enter and space raw key events by default (#82671)" (#84739)

parent ab9df836
......@@ -507,30 +507,6 @@ class CupertinoTextField extends StatefulWidget {
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 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
);
}
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 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
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 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
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 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
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 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
),
);
if (focusNode.onKey == null) {
paddedEditable = Focus(
onKey: _handleRawKeyEvent,
includeSemantics: false,
skipTraversal: true,
child: paddedEditable,
);
}
return Semantics(
enabled: enabled,
onTap: !enabled || widget.readOnly ? null : () {
......
......@@ -486,30 +486,6 @@ class TextField extends StatefulWidget {
///
/// 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 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
}
}
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 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
),
);
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 ]),
......
......@@ -4779,69 +4779,4 @@ void main() {
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);
}
......@@ -4537,69 +4537,6 @@ void main() {
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';
......
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