Fix Alt modifier stuck after Alt-Tab on Windows (#52220)

HuaGu-Dragon created

## 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

<!-- Check before requesting review: -->
- [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.

<details>
  <summary>Video</summary>
  


https://github.com/user-attachments/assets/b545178c-b360-4e2b-8d60-d6f95a0b4b79



https://github.com/user-attachments/assets/bc4d41eb-6f42-4040-a588-0fc46c576db7


</details>

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.

Change summary

crates/gpui_windows/src/events.rs | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)

Detailed changes

crates/gpui_windows/src/events.rs 🔗

@@ -725,6 +725,25 @@ impl WindowsWindowInner {
     fn handle_activate_msg(self: &Rc<Self>, wparam: WPARAM) -> Option<isize> {
         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() {