flutter-pi icon indicating copy to clipboard operation
flutter-pi copied to clipboard

RawKeyEvent returns incorrect logicalKey

Open mikekosulin opened this issue 2 years ago • 7 comments

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

mikekosulin avatar Dec 19 '22 00:12 mikekosulin

And the same on

Flutter 3.3.10 flutter-pi 566db0a56354bb49bbd2437186a8141b81e3e634 flutter-engine-binaries-for-arm 8522cef

mikekosulin avatar Dec 19 '22 01:12 mikekosulin

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.

mikekosulin avatar Dec 19 '22 02:12 mikekosulin

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.

ardera avatar Dec 20 '22 13:12 ardera

The most interesting part, that I get a correct keyCode calling event.data.toString(), but incorrect (always 56) calling event.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

ardera avatar Dec 20 '22 14:12 ardera

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();

mikekosulin avatar Dec 21 '22 20:12 mikekosulin

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.

ardera avatar Jan 03 '23 14:01 ardera

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.

ardera avatar Jan 03 '23 15:01 ardera