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.acceptsnow takes aKeyEventandHardwareKeyboard. - 
                    
ShortcutActivator.isActivatedByis now deprecated. Just callacceptsinstead. ShortcutActivator.triggersis now optional, and returns null if not implemented.ShortcutManager.handleKeypressnow 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 KeyEvents in handleKeypress
                  
                  instead of RawKeyEvents.  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 Flutter 3.35.5. Page last updated on 2025-10-28. View source or report an issue.