From 456ba32ea72148900c2f928f6b3606a7e60474ec Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Fri, 3 Oct 2025 20:38:29 +0530 Subject: [PATCH] macOS: Fix keyboards shortcuts does not work until mouse clicked inside Zed (#39467) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #38258 Regressed in https://github.com/zed-industries/zed/pull/33334 Release Notes: - Fixed an issue on macOS where keyboard shortcuts wouldn’t work until you clicked inside Zed. --- crates/gpui/src/platform/mac/window.rs | 35 +++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 1e822a5b72873a77f692676608f0de0a84ff5151..899ac4498bec4728b214e2576b98bf7abaeafca4 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -418,6 +418,7 @@ struct MacWindowState { select_next_tab_callback: Option>, select_previous_tab_callback: Option>, toggle_tab_bar_callback: Option>, + activated_least_once: bool, } impl MacWindowState { @@ -723,6 +724,7 @@ impl MacWindow { select_next_tab_callback: None, select_previous_tab_callback: None, toggle_tab_bar_callback: None, + activated_least_once: false, }))); (*native_window).set_ivar( @@ -1995,23 +1997,32 @@ extern "C" fn window_did_change_key_status(this: &Object, selector: Sel, _: id) let executor = lock.executor.clone(); drop(lock); - // If window is becoming active, trigger immediate synchronous frame request. + // When a window becomes active, trigger an immediate synchronous frame request to prevent + // tab flicker when switching between windows in native tabs mode. + // + // This is only done on subsequent activations (not the first) to ensure the initial focus + // path is properly established. Without this guard, the focus state would remain unset until + // the first mouse click, causing keybindings to be non-functional. if selector == sel!(windowDidBecomeKey:) && is_active { let window_state = unsafe { get_window_state(this) }; let mut lock = window_state.lock(); - if let Some(mut callback) = lock.request_frame_callback.take() { - #[cfg(not(feature = "macos-blade"))] - lock.renderer.set_presents_with_transaction(true); - lock.stop_display_link(); - drop(lock); - callback(Default::default()); + if lock.activated_least_once { + if let Some(mut callback) = lock.request_frame_callback.take() { + #[cfg(not(feature = "macos-blade"))] + lock.renderer.set_presents_with_transaction(true); + lock.stop_display_link(); + drop(lock); + callback(Default::default()); - let mut lock = window_state.lock(); - lock.request_frame_callback = Some(callback); - #[cfg(not(feature = "macos-blade"))] - lock.renderer.set_presents_with_transaction(false); - lock.start_display_link(); + let mut lock = window_state.lock(); + lock.request_frame_callback = Some(callback); + #[cfg(not(feature = "macos-blade"))] + lock.renderer.set_presents_with_transaction(false); + lock.start_display_link(); + } + } else { + lock.activated_least_once = true; } }