-
Notifications
You must be signed in to change notification settings - Fork 289
Description
Overview
Implementing TextFieldKeyboardHandler is not user friendly for two reasons:
RawKeyEventandRawKeyboard.instance.keysPressedhave many open bugs in Flutter (listed below)- Mapping keyboard shortcut combinations to handlers is tedious.
The proposed changes would be:
-
TextFieldKeyboardHandlerwould takeLogicalKeyEvent(or something like it) as a parameter rather thanRawKeyEvent. The event would protect SuperTextField devs from the messy details of Flutter bugs. (All of these bugs have been open for months, many with no activity, so don't think they will get closed any time soon.) -
Expose a
ShortcutsHandlerto make mapping keyboard combinations toTextFieldKeyboardHandlereasier, similar to how in Flutter we can map shortcuts to intents.
Here is a gist of the relevant code we have in our own app:
https://gist.github.com/venkatd/dcdefb929206b73ccb3d73b955d80f0c#file-logical_key_event-dart
I currently convert a RawKeyEvent to a LogicalKeyEvent in each handler. In this scenario below logicalKeyEvent.character just works out of the box since the workarounds are internal to LogicalKeyEvent. I can access the character and decide if I want to insert it or not.
TextFieldKeyboardHandlerResult insertTypedCharacter({
required AttributedTextEditingController controller,
required SuperSelectableTextState selectableTextState,
required RawKeyEvent keyEvent,
}) {
final logicalKeyEvent = LogicalKeyEvent.fromRawKeyEvent(
keyEvent,
RawKeyboard.instance.keysPressed,
);
final char = logicalKeyEvent.character;
if (char == null) return TextFieldKeyboardHandlerResult.notHandled;
controller.execute(ReplaceSelectedText(char));
return TextFieldKeyboardHandlerResult.handled;
}A dev can add their own key bindings earlier in the list of actions to override default shortcuts:
final myHandlers = <TextFieldKeyboardHandler>[
ShortcutsHandler({
LogicalKeySet(LogicalKeyboardKey.enter, LogicalKeyboardKey.shift,
LogicalKeyboardKey.control): ReplaceSelectedText('\n---\n'),
LogicalKeySet(LogicalKeyboardKey.enter, LogicalKeyboardKey.shift):
ReplaceSelectedText('\n'),
}),
...kPlatformKeyboardHandlers,
];LogicalKeyEvent is also used in the shortcuts implementation so I can look up the matching key combination from a map (https://gist.github.com/venkatd/dcdefb929206b73ccb3d73b955d80f0c#file-keyboard_handlers-dart-L170-L186)
Perhaps renaming LogicalKeyEvent to TextFieldKeyboardEvent` could make the intent clearer?
Related Flutter PRs/issues
ShortcutActivator PR: flutter/flutter#78522
This is specialized to the Shortcuts/Intents/Actions, while LogicalKeyEvent takes a similar approach to remove OS keyboard combinations.
The "WHY" section in the PR explains the gotcha's on how we would want to map keyboard shortcuts to actions.
If I want to maintain a map of a KeySet to a handler and properly trigger the handlers, I need to account for the edge cases explained in "WHY".
"Sticky" modifier keys on Flutter web:
flutter/flutter#75627 (comment)
(Apparently other platforms too, but I could only repro on web)
Flutter web reports UI keys
flutter/flutter#81940
We're handling this on the keyboard handler side, but I've encapsulated this filter so any dev writing their own action doens't have to think about this edge case.
MacOS, if a keyboard shortcut combo includes the shift key, the letter becomes upper-cased so doesn't match:
flutter/flutter#75595
Finally, there's an issue related to a quote key on international keyboard layouts, but I think this would be SuperTextField specific since using a TextInputChannel would resolve the issue. Filing it inside this repo for now:
#244