From 38270bc027a46671f680b09d06cd7a13a62bbc99 Mon Sep 17 00:00:00 2001 From: HuaGu-Dragon <1801943622@qq.com> Date: Sat, 18 Apr 2026 07:11:47 +0800 Subject: [PATCH] Fix Alt modifier stuck after Alt-Tab on Windows (#52220) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Context Fixes a bug on Windows where the Alt modifier key becomes stuck in the pressed state after using Alt-Tab to switch away from and back to the Zed application. ### Root Cause In `crates/gpui_windows/src/events.rs`, when the window loses focus during Alt-Tab, the WM_KEYUP event for the Alt key is never delivered to the application. The pending modifier state in GPUI remains as `alt=true`. When the window regains focus, there is no synchronization point to reset this stale state. ## How to Review In `handle_activate_msg()` (WM_ACTIVATE handler), when the window is activated: 1. Reset the cached modifier tracking state (`last_reported_modifiers` and `last_reported_capslock` set to `None`) 2. Query the actual current modifier state from Windows using `GetKeyState()` APIs 3. Dispatch a `ModifiersChanged` event with the true state to synchronize GPUI ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [ ] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable I think it's difficult to add tests for this because it's platform-dependent, but I recorded a video for comparison — sorry I only have an anime‑style app to show the key presses.
Video https://github.com/user-attachments/assets/b545178c-b360-4e2b-8d60-d6f95a0b4b79 https://github.com/user-attachments/assets/bc4d41eb-6f42-4040-a588-0fc46c576db7
Closes #45485 Release Notes: - Fixed Alt modifier key stuck after Alt-Tab on Windows. Modifier state is now synchronized when the window regains focus, ensuring correct key interpretation after window switching. --- crates/gpui_windows/src/events.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/crates/gpui_windows/src/events.rs b/crates/gpui_windows/src/events.rs index 21eb6bed899687e1c639efdc40788c229fdc4728..23b0c078b8ae62e22c7dae5f5441245559feec9c 100644 --- a/crates/gpui_windows/src/events.rs +++ b/crates/gpui_windows/src/events.rs @@ -725,6 +725,25 @@ impl WindowsWindowInner { fn handle_activate_msg(self: &Rc, wparam: WPARAM) -> Option { let activated = wparam.loword() > 0; let this = self.clone(); + + // When the window is activated (gains focus), reset the modifier tracking state. + // This fixes the issue where Alt-Tab away and back leaves stale modifier state + // (especially the Alt key) because Windows doesn't always send key-up events to + // windows that have lost focus. + if activated { + this.state.last_reported_modifiers.set(None); + this.state.last_reported_capslock.set(None); + + if let Some(mut func) = this.state.callbacks.input.take() { + let input = PlatformInput::ModifiersChanged(ModifiersChangedEvent { + modifiers: current_modifiers(), + capslock: current_capslock(), + }); + func(input); + this.state.callbacks.input.set(Some(func)); + } + } + self.executor .spawn(async move { if let Some(mut func) = this.state.callbacks.active_status_change.take() {