Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot extract original character when receiving a Ctrl character. #1700

Closed
ArturKovacs opened this issue Sep 9, 2020 · 9 comments
Closed

Comments

@ArturKovacs
Copy link
Contributor

ArturKovacs commented Sep 9, 2020

When I use a keyboard layout with keys that are not from basic latin, and I press a non-basic-latin letter in conjunction with Ctrl the following happens:

  • The VirtualKeyCode seems to be the character at the same location from the US layout.
  • The ReceivedCharacter is sometimes identical to the VirtualKeyCode but it's sometimes an ASCII control character.

This happens on both Linux with X11 and on Windows. Actually, on Windows the ReceivedCharacter isn't even sent for some combinations.

The issue is that it seems the application has no way of telling what was the original key pressed. So for example if I'm using a Hungarian layout and I press Ctrl+ű I get a '\u{1c}' in ReceivedCharacter and my applications has no idea that ű was ever pressed. This may not be relevant for text input but it's relevant for shortcuts.

@chrisduerr
Copy link
Contributor

This sounds like you want to look at the VirtualKeyCode or scancode of the button press?

@ArturKovacs
Copy link
Contributor Author

I don't see how VirtualKeyCode would help me figuring out that ű was pressed. The ScanCode probably could help but I don't know of any way to transform the scancode into the appropriate character with winint. Do you @chrisduerr?

@maroider
Copy link
Member

maroider commented Sep 9, 2020

On Windows, you can use MapVirtualKeyW to map a scancode to a VK_* value, but you'd have to convert that to winit's VirtualKeyCode on your own, since the function that maps between VK_* and VirtualKeyCode isn't part of the public api. I don't know what the situation is like on any of the other platforms.

Implementing something like this directly in winit itself has been briefly mentioned, but that seems to have been intended for "display purposes".

Honestly, if you're expecting winit to have some sort of good solution for keyboard shortcuts then you're SOL, because all the options have some major downsides.

  • ReceivedCharacter is very layout-dependent, and doesn't mesh well with modifiers. Using character input for shortcuts is generally a bad idea.
  • VirtualKeyCode is also layout-dependent. VirtualKeyCode is probably what you want, but there's no built-in way to go from VirtualKeyCode to "what's (probably) printed on the key-cap" based on the current layout so you can tell the user where they should look. Some layouts also shift the virtual key-codes around in unpredictable ways, so the lack of "VirtualKeyCode-to-what's-on-the-keycap" hurts even more.
  • scancodes are layout-independent, but they are platform-dependent. They're also reported in a less-than ideal way at the moment, as evidenced by Add prefix byte for extended scancodes on Windows #1679.

I don't really expect this situation to change much unless we can get some momentum behind a solution for #753.

@ArturKovacs
Copy link
Contributor Author

ArturKovacs commented Sep 9, 2020

Thank you for the in-depth description!

I'm wondering how do other applications handle keyboard shortcuts with let's say Russian or Arabic keyboard layouts. When listing the available keyboard shortcuts, what do applications show on the GUI to the user with such layouts? Do they display the "virtual key" or do they display the layout dependent character?

If it's the virtual key than this really is not an issue - or more like an issue that already has a widely accepted workaround.

@chrisduerr
Copy link
Contributor

I don't really expect this situation to change much unless we can get some momentum behind a solution for #753.

I do expect the keyboard handling situation to get better, but that won't fix this problem. The biggest problem right now is just with consistency, one platform does it one way and another platform does it differently. Even on the same platform you run into issues where suddenly DeviceEvent has a VirtualKeyCode but WindowEvent doesn't.

Generally what winit does right now with offering all of scancode/received_char/VirtualKeyCode is relatively similar to what the browser does and it's a decent solution.

I'm wondering how do other applications handle keyboard shortcuts with let's say Russian or Arabic keyboard layouts.

Not a lot of applications have keyboard shortcuts and even fewer of those have the necessity that users type in the names of those shortcuts manually. If you set them by having the user press the button, it's becomes relatively trivial.

@dhardy
Copy link
Contributor

dhardy commented Sep 10, 2020

Portable shortcuts are not a trivial problem, and not just for Rust / winit.

Qt has some notes on this, in particular:

  • Ctrl + + actually maps to Ctrl + Shift + = on a British keyboard, but Ctrl + + (on a different key) on a Norwegian keyboard
  • Macs often use the Command key and in general different platforms have different standard shortcuts
  • Qt's key enum is considerably larger than VirtualKeyCode including, for example, Qt::Key_Adiaeresis (ä), though I think not 'U with double acute' (ű).

Thus, Qt provides a library of platform-specific common shortcuts. Of course this doesn't solve everything.

@maroider
Copy link
Member

Even on the same platform you run into issues where suddenly DeviceEvent has a VirtualKeyCode but WindowEvent doesn't.

Yep. I've been trying to untangle "Alt Graph" on the Windows backend, as well as trying to figure out how to deal with "Pause/Break" and "NumLock" being weird. I'll submit a PR when the code is in a state I'm somewhat comfortable with.

@osa1
Copy link

osa1 commented Jan 28, 2022

Will #1932 fix this issue for Linux? Are there any plans to fix this on other platforms as well?

Are there any workaround to the issue of not getting the characters in ctrl+char combinations?

@maroider
Copy link
Member

Will #1932 fix this issue for Linux?

Yes

Are there any plans to fix this on other platforms as well?

#1932 is part of an effort to overhaul the cross-platform keyboard input API (see #1806).

Are there any workaround to the issue of not getting the characters in ctrl+char combinations?

Maybe, but I can't think of a convenient one.

kchibisov added a commit that referenced this issue May 28, 2023
Overhaul the keyboard API in winit to mimic the W3C specification
to achieve better crossplatform parity. The `KeyboardInput` event
is now uses `KeyEvent` which consists of:

  - `physical_key` - a cross platform way to refer to scancodes;
  - `logical_key`  - keysym value, which shows your key respecting the
                     layout;
  - `text`         - the text produced by this keypress;
  - `location`     - the location of the key on the keyboard;
  - `repeat`       - whether the key was produced by the repeat.

And also a `platform_specific` field which encapsulates extra
information on desktop platforms, like key without modifiers
and text with all modifiers.

The `Modifiers` were also slightly reworked as in, the information
whether the left or right modifier is pressed is now also exposed
on platforms where it could be queried reliably. The support was
also added for the web and orbital platforms finishing the API
change.

This change made the `OptionAsAlt` API on macOS redundant thus it
was removed all together.

Co-Authored-By: Artúr Kovács <kovacs.artur.barnabas@gmail.com>
Co-Authored-By: Kirill Chibisov <contact@kchibisov.com>
Co-Authored-By: daxpedda <daxpedda@gmail.com>
Fixes: #2631.
Fixes: #2055.
Fixes: #2032.
Fixes: #1904.
Fixes: #1810.
Fixes: #1700.
Fixes: #1443.
Fixes: #1343.
Fixes: #1208.
Fixes: #1151.
Fixes: #812.
Fixes: #600.
Fixes: #361.
Fixes: #343.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

5 participants