RawKeyEvent returns incorrect logicalKey
Hello, I've got so strange behavior with RawKeyboardListener.
keyCode is correct, but event.logicalKey.keyLabel returns 8 instead of * and the same for other key events with modifiers.
I've double-checked my OS and everything is ok in terminal, I've also checked libinput debug-events and it works as expected.
RawKeyEvent data for both keys:
Widget code
RawKeyboardListener(
focusNode: focusNode,
child: SizedBox.shrink(),
onKey: (RawKeyEvent event) {
if (event is RawKeyDownEvent) {
debugPrint(event.data.toString());
}
},
)
* (shift+8)
RawKeyEventDataLinux#ed7a0(toolkit: GTK, unicodeScalarValues: 56, scanCode: 17, keyCode: 42, modifiers: 1, isDown: true)
8:
RawKeyEventDataLinux#85610(toolkit: GTK, unicodeScalarValues: 56, scanCode: 17, keyCode: 56, modifiers: 0, isDown: true)
raspberry pi 3b+ Flutter 3.0.2 flutter-pi e919e11098dc7c5bcbbe1e0c06334013d5e37ff9 flutter-engine-binaries-for-arm 9eaa027
And the same on
Flutter 3.3.10 flutter-pi 566db0a56354bb49bbd2437186a8141b81e3e634 flutter-engine-binaries-for-arm 8522cef
The most interesting part, that I get a correct keyCode calling event.data.toString(), but incorrect (always 56) calling event.logicalKey.keyId
It works as expected on Flutter (Channel stable, 3.3.10, on Ubuntu 20.04.2 LTS 5.15.0-56-generic, locale en_US.UTF-8) that's why I thought that something goes wrong with flutter-pi.
Hey,
AFAICT this is correct behaviour: https://api.flutter.dev/flutter/services/LogicalKeyboardKey/keyLabel.html
keyLabel is basically "what it says on the keycap".
Use RawKeyEvent.character instead if you want the actual text characters that were emitted.
If you're wondering why PhysicalKeyboardKey exists then (since it seems to have the same purpose as LogicalKeyboardKey.keyLabel): The physical keyboard key is only the location on the keyboard, not what it says on the keycap.
For example, on german keyboards, Z and Y are swapped. If you press Z on a german keyboard, a RawKeyboardKey.keyY will correctly be emitted, because the Z is at the location that the Y is in, in the normal (generalized) keyboard layout.
But then, the logical keyboard key of that same key event will be LogicalKeyboardKey.keyY, and LogicalKeyboardKey.keyY.keyLabel will correctly say Y, which is the letter that's printed on the keycap.
The most interesting part, that I get a correct
keyCodecallingevent.data.toString(), but incorrect (always 56) callingevent.logicalKey.keyId
Wait so it's the keyCode that's wrong, not the keyLabel? In the logs at the top it seems like the keyCode is correct
Thanks. Gonna check it out on the weekend.
If you're wondering why PhysicalKeyboardKey exists
no, I'm just wondering why the same code works differently on Ubuntu 20.04.2 LTS 5.15.0-56-generic, locale en_US.UTF-8 in "native-flutter app" and Linux raspberry 5.10.63-v7+, locale en_US.UTF-8 via flutter-pi
So I made a hot fix by changing this:
final String v = event.logicalKey.keyLabel.toString();
to this:
final RawKeyEventDataLinux data = event.data as RawKeyEventDataLinux;
final String v = LogicalKeyboardKey(data.keyCode).keyLabel.toString();
seems like this is a known issue: https://github.com/flutter/flutter/issues/65668
EDIT: Also RawKeyEvent.character won't work since flutter infers the character from the unicodeScalarValues on linux (which is the unicode value of the produced character, without modifiers, so lowercase and without accents), but you've probably already noticed that.
Maybe the solution is to make use of the new FlutterEngineSendKeyEvent procs of the embedder API, then at least HardwareKeyboard will work correctly.
When https://github.com/ardera/flutter-pi/issues/308 is fixed, you should be able to use a KeyboardListener widget and then use the KeyDownEvent.character there to get the exact text character that was produced, which should match more closely what the official embedders (incorrectly) have for the LogicalKey.keyLabel right now.