Fix ActivateIntent overriding the spacebar for text entry (#91129)
This commit is contained in:
parent
acf6464996
commit
a24d55660b
@ -1149,6 +1149,10 @@ class WidgetsApp extends StatefulWidget {
|
|||||||
/// with "s".
|
/// with "s".
|
||||||
static bool debugAllowBannerOverride = true;
|
static bool debugAllowBannerOverride = true;
|
||||||
|
|
||||||
|
// Any shortcuts added here have the potential to conflict with normal text
|
||||||
|
// input. If this should not happen and text input should take preference,
|
||||||
|
// then add a shortcut for the relevant key in DefaultTextEditingShortcuts
|
||||||
|
// mapped to DoNothingAndStopPropagationTextIntent.
|
||||||
static const Map<ShortcutActivator, Intent> _defaultShortcuts = <ShortcutActivator, Intent>{
|
static const Map<ShortcutActivator, Intent> _defaultShortcuts = <ShortcutActivator, Intent>{
|
||||||
// Activation
|
// Activation
|
||||||
SingleActivator(LogicalKeyboardKey.enter): ActivateIntent(),
|
SingleActivator(LogicalKeyboardKey.enter): ActivateIntent(),
|
||||||
@ -1206,6 +1210,11 @@ class WidgetsApp extends StatefulWidget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Default shortcuts for the macOS platform.
|
// Default shortcuts for the macOS platform.
|
||||||
|
//
|
||||||
|
// Any shortcuts added here have the potential to conflict with normal text
|
||||||
|
// input. If this should not happen and text input should take preference,
|
||||||
|
// then add a shortcut for the relevant key in DefaultTextEditingShortcuts
|
||||||
|
// mapped to DoNothingAndStopPropagationTextIntent.
|
||||||
static const Map<ShortcutActivator, Intent> _defaultAppleOsShortcuts = <ShortcutActivator, Intent>{
|
static const Map<ShortcutActivator, Intent> _defaultAppleOsShortcuts = <ShortcutActivator, Intent>{
|
||||||
// Activation
|
// Activation
|
||||||
SingleActivator(LogicalKeyboardKey.enter): ActivateIntent(),
|
SingleActivator(LogicalKeyboardKey.enter): ActivateIntent(),
|
||||||
|
@ -160,6 +160,13 @@ class DefaultTextEditingShortcuts extends Shortcuts {
|
|||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static const Map<ShortcutActivator, Intent> _commonShortcuts = <ShortcutActivator, Intent>{
|
||||||
|
// Allows space and enter to be used as input instead of a shortcut by
|
||||||
|
// another widget. See https://github.com/flutter/flutter/issues/90907
|
||||||
|
SingleActivator(LogicalKeyboardKey.space): DoNothingAndStopPropagationTextIntent(),
|
||||||
|
SingleActivator(LogicalKeyboardKey.enter): DoNothingAndStopPropagationTextIntent(),
|
||||||
|
};
|
||||||
|
|
||||||
static const Map<ShortcutActivator, Intent> _androidShortcuts = <ShortcutActivator, Intent>{
|
static const Map<ShortcutActivator, Intent> _androidShortcuts = <ShortcutActivator, Intent>{
|
||||||
SingleActivator(LogicalKeyboardKey.backspace): DeleteTextIntent(),
|
SingleActivator(LogicalKeyboardKey.backspace): DeleteTextIntent(),
|
||||||
SingleActivator(LogicalKeyboardKey.backspace, control: true): DeleteByWordTextIntent(),
|
SingleActivator(LogicalKeyboardKey.backspace, control: true): DeleteByWordTextIntent(),
|
||||||
@ -532,7 +539,7 @@ class DefaultTextEditingShortcuts extends Shortcuts {
|
|||||||
SingleActivator(LogicalKeyboardKey.keyA, meta: true): DoNothingAndStopPropagationTextIntent(),
|
SingleActivator(LogicalKeyboardKey.keyA, meta: true): DoNothingAndStopPropagationTextIntent(),
|
||||||
};
|
};
|
||||||
|
|
||||||
static Map<ShortcutActivator, Intent> get _shortcuts {
|
static Map<ShortcutActivator, Intent> get _platformShortcuts {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
return _webShortcuts;
|
return _webShortcuts;
|
||||||
}
|
}
|
||||||
@ -552,4 +559,11 @@ class DefaultTextEditingShortcuts extends Shortcuts {
|
|||||||
return _windowsShortcuts;
|
return _windowsShortcuts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Map<ShortcutActivator, Intent> get _shortcuts {
|
||||||
|
return <ShortcutActivator, Intent>{
|
||||||
|
..._commonShortcuts,
|
||||||
|
..._platformShortcuts,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import 'package:flutter/gestures.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import '../rendering/mock_canvas.dart';
|
import '../rendering/mock_canvas.dart';
|
||||||
@ -8635,6 +8636,71 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(scrollController.offset.roundToDouble(), 0.0);
|
expect(scrollController.offset.roundToDouble(), 0.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/90907.
|
||||||
|
testWidgets("ActivateIntent doesn't block space entry", (WidgetTester tester) async {
|
||||||
|
final FocusNode focusNode = FocusNode();
|
||||||
|
bool invoked = false;
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
body: Align(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
child: SizedBox(
|
||||||
|
width: 100,
|
||||||
|
child: ListTile(
|
||||||
|
title: Actions(
|
||||||
|
actions: <Type, Action<Intent>>{
|
||||||
|
ActivateIntent: CallbackAction<ActivateIntent>(
|
||||||
|
onInvoke: (ActivateIntent intent) {
|
||||||
|
invoked = true;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
EditableText(
|
||||||
|
autofocus: true,
|
||||||
|
showSelectionHandles: true,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: TextEditingController(),
|
||||||
|
focusNode: FocusNode(),
|
||||||
|
cursorColor: Colors.red,
|
||||||
|
backgroundCursorColor: Colors.blue,
|
||||||
|
style: Typography.material2018(platform: TargetPlatform.android).black.subtitle1!.copyWith(fontFamily: 'Roboto'),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
),
|
||||||
|
Focus(
|
||||||
|
focusNode: focusNode,
|
||||||
|
child: const Text('Hello'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
|
||||||
|
await tester.pump();
|
||||||
|
expect(invoked, isFalse);
|
||||||
|
|
||||||
|
focusNode.requestFocus();
|
||||||
|
await tester.pump();
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.space);
|
||||||
|
await tester.pump();
|
||||||
|
expect(invoked, isTrue);
|
||||||
|
|
||||||
|
invoked = false;
|
||||||
|
await tester.pump();
|
||||||
|
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
|
||||||
|
await tester.pump();
|
||||||
|
// On the web, enter doesn't activate any controls except for buttons.
|
||||||
|
expect(invoked, kIsWeb ? isFalse : isTrue);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class UnsettableController extends TextEditingController {
|
class UnsettableController extends TextEditingController {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user