Migrate ShortcutActivator and ShortcutManager to KeyEvent system
Summary
#For some time now (years), Flutter has had two key event systems implemented. The new system reached parity with the old platform-specific raw key event system, and the raw system will be removed. To prepare for that, the Flutter APIs that use the old system are being modified, and for a select few of them we have decided to make breaking changes in the API in order to preserve the quality of the API.
Context
#In the original key event subsystem handling each platform's quirks in the framework and in client apps caused overly complex code, and the old system didn't properly represent the true state of key events on the system.
So, the new KeyEvent
-based system was born, and to minimize breaking changes, was implemented in parallel with the old system with the intention of eventually deprecating the raw system. That time is quickly arriving, and to prepare for it, we have made some minimal breaking changes required to preserve the quality of the API.
Description of change
#Summary of APIs that have been affected:
ShortcutActivator.accepts
now takes aKeyEvent
andHardwareKeyboard
.ShortcutActivator.isActivatedBy
is now deprecated. Just callaccepts
instead.ShortcutActivator.triggers
is now optional, and returns null if not implemented.ShortcutManager.handleKeypress
now takes aKeyEvent
.
The change modifies the ShortcutActivator.accepts
method to take a KeyEvent
and HardwareKeyboard
instead of the previous RawKeyEvent
and RawKeyboard
.
The meaning of ShortcutActivator.accepts
has changed slightly. Before the change, it was assumed that accepts
was only called if ShortcutActivator.triggers
returned null, or if the key event sent to accepts
had a logical key that was in the triggers
list. Now it is always called, and may use the triggers
list as a performance improvement, but is not required to. Flutter subclasses such as SingleActivator
and CharacterActivator
already do this.
The change also modifies the ShortcutManager.handleKeypress
method to take a KeyEvent
instead of RawKeyEvent
.
Migration guide
#APIs provided by the Flutter framework are already migrated. Migration is needed only if you're using any of the methods listed in the previous section.
Migrating your APIs that use ShortcutActivator
or its subclasses.
#Pass a KeyEvent
instead of a RawKeyEvent
to ShortcutActivator.accepts
. This may mean switching where you get your key events from. Depending on where you get them, this can either mean switching to using Focus.onKeyEvent
instead of Focus.onKey
, or a similar change if using FocusScope
, FocusNode
or FocusScopeNode
.
If you're using a RawKeyboardListener
, switch to using a KeyboardListener
instead. If you're accessing RawKeyboard
directly, use HardwareKeyboard
instead. You'll find that there are non-raw equivalents for all of the key event sources.
Migrating your APIs that extend ShortcutActivator
#The ShortcutActivator.accepts
method was modified to take a KeyEvent
and a HardwareKeyboard
instead of a RawKeyEvent
and RawKeyboard
.
Before:
class MyActivator extends ShortcutActivator {
@override
bool accepts(RawKeyEvent event, RawKeyboard state) {
// ... (your implementation here)
returns false;
}
// ...
}
After:
class MyActivator extends ShortcutActivator {
@override
bool accepts(KeyEvent event, HardwareKeyboard state) {
// ... (your implementation here)
returns false;
}
// ...
}
Migrating your APIs that extend ShortcutManager
#The ShortcutManager
class was modified to take KeyEvent
s in handleKeypress
instead of RawKeyEvent
s. One difference in the two APIs is that repeated keys are determined differently. In the RawKeyEvent
case, the repeat
member indicated a repeat, but in RawKeyEvent
code, the event is a different type (KeyRepeatEvent
).
Before:
class _MyShortcutManager extends ShortcutManager {
@override
KeyEventResult handleKeypress(BuildContext context, RawKeyEvent event) {
if (event is! RawKeyDownEvent) {
return KeyEventResult.ignored;
}
if (event.repeat) {
// (Do something with repeated keys.)
}
// ... (your implementation here)
return KeyEventResult.handled;
}
}
After:
class _MyShortcutManager extends ShortcutManager {
@override
KeyEventResult handleKeypress(BuildContext context, KeyEvent event) {
if (event is! KeyDownEvent && event is! KeyRepeatEvent) {
return KeyEventResult.ignored;
}
if (event is KeyRepeatEvent) {
// (Do something with repeated keys.)
}
// ... (your implementation here)
return KeyEventResult.handled;
}
}
Timeline
#Landed in version: 3.17.0-5.0.pre
In stable release: 3.19.0
References
#API documentation:
Relevant issues:
Relevant PRs:
Unless stated otherwise, the documentation on this site reflects the latest stable version of Flutter. Page last updated on 2024-04-06. View source or report an issue.