Skip to content

Conversation

@jvb0
Copy link
Contributor

@jvb0 jvb0 commented Oct 17, 2025

Problem

On Windows, the right Alt key was not working in keybindings (e.g., Ctrl+Right Alt+B), while the left Alt key worked correctly. This was due to overly aggressive AltGr detection that treated any right Alt + left Ctrl combination as AltGr, even on US keyboards where AltGr doesn't exist.

Root Cause

Windows internally represents AltGr (Alt Graph) as right Alt + left Ctrl pressed simultaneously. The previous implementation always excluded this combination from being treated as regular modifier keys to support international keyboards. However, this broke keybindings using right Alt on US/UK keyboards where users expect right Alt to behave identically to left Alt.

Solution

Implemented keyboard layout-aware AltGr detection:

  1. Added uses_altgr() method to WindowsKeyboardLayout that checks if the current keyboard layout is known to use AltGr (German, French, Spanish, Polish, etc.)
  2. Modified current_modifiers() to only apply AltGr special handling when the keyboard layout actually uses it
  3. Added explicit checking for both VK_LMENU and VK_RMENU instead of relying solely on the generic VK_MENU

Behavior

  • US/UK keyboards: Right Alt now works identically to left Alt in keybindings. Ctrl+Right Alt+B triggers the same action as Ctrl+Left Alt+B
  • International keyboards (German, French, Spanish, etc.): AltGr continues to work correctly for typing special characters and doesn't trigger keybindings
  • All keyboards: Both Alt keys are detected symmetrically, matching the behavior of left/right Windows keys

Testing

Manually tested on Windows with US keyboard layout:

  • Ctrl+Left Alt+B triggers keybinding
  • Ctrl+Right Alt+B triggers keybinding
  • Both Alt keys work independently in keybindings

Release Notes:

  • Fixed Right Alt key not working in keybindings on Windows
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Oct 17, 2025
@zed-industries-bot

This comment was marked as outdated.

@nia-e nia-e self-assigned this Oct 17, 2025
@nia-e
Copy link
Member

nia-e commented Oct 17, 2025

Hey, thanks for the PR - everything looks good except some little nits ^^

@nia-e nia-e merged commit 3d6722b into zed-industries:main Oct 18, 2025
21 checks passed
@jvb0 jvb0 deleted the fix-alt-windows branch October 18, 2025 00:29
@jvb0
Copy link
Contributor Author

jvb0 commented Oct 18, 2025

Thank you @nia-e

@nia-e
Copy link
Member

nia-e commented Oct 18, 2025

Thank you for the contribution! :D

Copy link
Contributor

@Sh4rK Sh4rK left a comment

Choose a reason for hiding this comment

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

Hey, sorry for the passing by comments, I was just interested in this change since I did the previous AltGr handling code. I didn't think anybody would use Left Ctrl + Right Alt for hotkeys, but it seems I was wrong :D

Modifiers {
control: is_virtual_key_pressed(VK_CONTROL) && !altgr,
alt: is_virtual_key_pressed(VK_MENU) && !altgr,
alt: (lmenu_pressed || rmenu_pressed) && !altgr,
Copy link
Contributor

Choose a reason for hiding this comment

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

This line does exactly the same as before (is_virtual_key_pressed(VK_MENU) returns true for both alt buttons), so I'm pretty sure just adding keyboard_uses_altgr() && to the beginning of the let altgr line, without changing anything else, would also work the same.


fn keyboard_uses_altgr() -> bool {
use crate::platform::windows::keyboard::WindowsKeyboardLayout;
WindowsKeyboardLayout::new()
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't it expensive/wasteful to create a WindowsKeyboardLayout on basically every keypress? This calls a Windows API to retrieve the current layout + fetches a registry key as well. The current layout is already stored in App, though only through a dyn trait, so this windows specific uses_altgr method would not be visible, unless added to the base trait. We also don't have access to an App here unfortunately, so I guess unless we do a bit of refactoring (or a thread-local + on_keyboard_layout_change) we can't really do better :/

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, I had that same concern here but didn't see a nice way around. A thread local is probably a smart approach though; would you be able to submit a PR? If not I'll put this on my backlog

Copy link
Contributor

Choose a reason for hiding this comment

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

I may give it a go tomorrow or on the weekend, will ping you in the PR if that's fine by you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for taking a look 😅

@purpleb3ar
Copy link

This change (which unfortunately made it into release) breaks non-us layouts. Pressing AltGr + B, which normally inserts a left curly brace, toggles the notification panel instead (right dock). It seems that the system is erroneously interpreting AltGr + B as Ctrl + Alt + B (which corresponds to ToggleRightDock according to the default keymap).

@Sh4rK
Copy link
Contributor

Sh4rK commented Nov 2, 2025

@purpleb3ar may I ask what keyboard layout you're using?

@purpleb3ar
Copy link

purpleb3ar commented Nov 2, 2025

@Sh4rK Yes, I am using the Slovenian layout.

After I made the comment, I went ahead and tried to fix the issue, it seems that the lang_id is returned in a different byte order than the patterns in the matches! macro (in the uses_altgr method on the WindowsKeyboardLayout struct) and the zero in the pattern needed to be escaped (e.g. b"0424" -> "b424\0"). This change fixed the issue for me.

@Sh4rK
Copy link
Contributor

Sh4rK commented Nov 3, 2025

it seems that the lang_id is returned in a different byte order than the patterns in the matches! macro

It's actually not in a different byte order, but instead the id string contains a trailing zero byte, which the previous line (let lang_id = &id_bytes[id_bytes.len() - 4..];) doesn't take into account. TBH, the trailing zero should probably be cut off when converting to a String when creating the WindowsKeyboardLayout.

Other than this, I've been staring at this keyboard code for a few hours, it's not the easiest thing to understand / come up with a good solution, but I'll look at it a bit more later.

I'll open a PR soon to fix the immediate problem of the language id matching, but the frequent calling of WindowsKeyboardLayout will need to wait a bit more.

Sh4rK added a commit to Sh4rK/zed that referenced this pull request Nov 3, 2025
It is unnecessary, and it broke the `uses_altgr` function.

Ref: zed-industries#40536 (comment)
Sh4rK added a commit to Sh4rK/zed that referenced this pull request Nov 3, 2025
It is unnecessary, and it broke the `uses_altgr` function.

Also add Slovenian layout as using AltGr.

Ref: zed-industries#40536 (comment)
nia-e pushed a commit that referenced this pull request Nov 3, 2025
Closes #41486, closes #35862 

It is unnecessary, and it broke the `uses_altgr` function.

Also add Slovenian layout as using AltGr.

This should fix:
-
#40536 (comment)
- #41486
- #35862

As the current strategy relies on manually adding layouts that have
AltGr, it's brittle and not very elegant. It also has other issues (it
requests the current layout on every kesytroke and mouse movement).

**A potentially better and more comprehensive solution is at
#41259
This is just to fix the immediate issues while that gets reviewed.

Release Notes:

- windows: Fix AltGr handling on non-US layouts again.
P1n3appl3 pushed a commit to bnjjj/zed that referenced this pull request Nov 4, 2025
Closes zed-industries#41486, closes zed-industries#35862 

It is unnecessary, and it broke the `uses_altgr` function.

Also add Slovenian layout as using AltGr.

This should fix:
-
zed-industries#40536 (comment)
- zed-industries#41486
- zed-industries#35862

As the current strategy relies on manually adding layouts that have
AltGr, it's brittle and not very elegant. It also has other issues (it
requests the current layout on every kesytroke and mouse movement).

**A potentially better and more comprehensive solution is at
zed-industries#41259
This is just to fix the immediate issues while that gets reviewed.

Release Notes:

- windows: Fix AltGr handling on non-US layouts again.
tomatitito pushed a commit to tomatitito/zed that referenced this pull request Nov 7, 2025
Closes zed-industries#41486, closes zed-industries#35862 

It is unnecessary, and it broke the `uses_altgr` function.

Also add Slovenian layout as using AltGr.

This should fix:
-
zed-industries#40536 (comment)
- zed-industries#41486
- zed-industries#35862

As the current strategy relies on manually adding layouts that have
AltGr, it's brittle and not very elegant. It also has other issues (it
requests the current layout on every kesytroke and mouse movement).

**A potentially better and more comprehensive solution is at
zed-industries#41259
This is just to fix the immediate issues while that gets reviewed.

Release Notes:

- windows: Fix AltGr handling on non-US layouts again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement

5 participants