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

Fix incorrect Unicode key mapping on Windows #100960

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

buresu
Copy link
Contributor

@buresu buresu commented Dec 30, 2024

This PR fixes incorrect keycode mapping for Unicode input on Windows platform.

Details

When a key is pressed, MapVirtualKey() converts the scan code to a virtual key code. However, some converted virtual key codes are defined as OEM codes and do not take keyboard layout into account.
Although ToUnicodeEx() is then used to convert to actual Unicode characters, currently only key_label is updated while keycode remains unchanged.
To resolve this problem, we need to have a Unicode key mapping table and override Godot's key codes based on it.

Test project

debug_key.zip

@buresu buresu requested a review from a team as a code owner December 30, 2024 22:33
@buresu buresu force-pushed the fix-windows-keymapping branch 2 times, most recently from 23cf20d to 6c128cf Compare December 30, 2024 22:43
@Repiteo Repiteo added this to the 4.x milestone Dec 30, 2024
Copy link
Member

@bruvzg bruvzg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide any extra details for the conditions when MapVirtualKey() is not working properly (keyboard layout and specific keys not working)?

@@ -5787,6 +5787,8 @@ void DisplayServerWindows::_process_key_events() {
if (!(ke.lParam & (1 << 24)) && ToUnicodeEx(extended_code, (ke.lParam >> 16) & 0xFF, keyboard_state, chars, 255, 4, GetKeyboardLayout(0)) > 0) {
String keysym = String::utf16((char16_t *)chars, 255);
if (!keysym.is_empty()) {
Key unicode_keysym = KeyMappingWindows::get_unicode_keysym(keysym[0]);
Copy link
Member

@bruvzg bruvzg Jan 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ASCII values are mapped to Godot key constants exactly, there's no need for the mapping:

Suggested change
Key unicode_keysym = KeyMappingWindows::get_unicode_keysym(keysym[0]);
Key unicode_keysym = (Key)keysym[0];

plus range check, since keycode should not have other values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you.
Indeed, when Godot's key codes match ASCII key codes, no lookup table is needed.

@buresu buresu force-pushed the fix-windows-keymapping branch from 6c128cf to 4885ac6 Compare January 1, 2025 18:45
@buresu
Copy link
Contributor Author

buresu commented Jan 1, 2025

@bruvzg Thank you for the review.

Can you provide any extra details for the conditions when MapVirtualKey() is not working properly (keyboard layout and specific keys not working)?

I am using a Japanese keyboard (jp106).
For example, when typing the '@' key, the input value is converted to VK_OEM_3 (0xC0) by MapVirtualKey(). While this represents QuoteLeft on US keyboards, since it's an OEM code, the assigned key code differs depending on the keyboard.

There are some OEM key codes. Please refer to the following URL for details:
https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes

@buresu buresu force-pushed the fix-windows-keymapping branch from 4885ac6 to 8c73194 Compare January 1, 2025 19:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants