From 272fc672afcfce7a89a317be09967895f5b3b419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Mon, 23 Jun 2025 19:02:00 +0800 Subject: [PATCH] windows: Dialog QoL improvements (#33241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just like in the previous PR #33230, we need to properly set up modal windows to make them work as expected. Before this PR, when you opened an "Open File" or "Save File" dialog, clicking the main window would steal focus from the modal, even though the main window wasn’t actually interactive. With this PR, clicking the main window while a modal is open does nothing — as it should — until the modal is closed. #### Before https://github.com/user-attachments/assets/9c6bdff0-1c46-49c1-a5ff-751c52c7d613 #### After https://github.com/user-attachments/assets/8776bd28-85ff-4f32-8390-bcf5b4eec1fe Release Notes: - N/A --- crates/gpui/src/platform/windows/platform.rs | 29 ++++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/crates/gpui/src/platform/windows/platform.rs b/crates/gpui/src/platform/windows/platform.rs index bb65163e09..83e56ad3ae 100644 --- a/crates/gpui/src/platform/windows/platform.rs +++ b/crates/gpui/src/platform/windows/platform.rs @@ -295,6 +295,18 @@ impl WindowsPlatform { .log_err() .unwrap_or_default() } + + fn find_current_active_window(&self) -> Option { + let active_window_hwnd = unsafe { GetActiveWindow() }; + if active_window_hwnd.is_invalid() { + return None; + } + self.raw_window_handles + .read() + .iter() + .find(|&&hwnd| hwnd == active_window_hwnd) + .copied() + } } impl Platform for WindowsPlatform { @@ -473,9 +485,10 @@ impl Platform for WindowsPlatform { options: PathPromptOptions, ) -> Receiver>>> { let (tx, rx) = oneshot::channel(); + let window = self.find_current_active_window(); self.foreground_executor() .spawn(async move { - let _ = tx.send(file_open_dialog(options)); + let _ = tx.send(file_open_dialog(options, window)); }) .detach(); @@ -485,9 +498,10 @@ impl Platform for WindowsPlatform { fn prompt_for_new_path(&self, directory: &Path) -> Receiver>> { let directory = directory.to_owned(); let (tx, rx) = oneshot::channel(); + let window = self.find_current_active_window(); self.foreground_executor() .spawn(async move { - let _ = tx.send(file_save_dialog(directory)); + let _ = tx.send(file_save_dialog(directory, window)); }) .detach(); @@ -754,7 +768,10 @@ fn open_target_in_explorer(target: &str) { } } -fn file_open_dialog(options: PathPromptOptions) -> Result>> { +fn file_open_dialog( + options: PathPromptOptions, + window: Option, +) -> Result>> { let folder_dialog: IFileOpenDialog = unsafe { CoCreateInstance(&FileOpenDialog, None, CLSCTX_ALL)? }; @@ -768,7 +785,7 @@ fn file_open_dialog(options: PathPromptOptions) -> Result>> unsafe { folder_dialog.SetOptions(dialog_options)?; - if folder_dialog.Show(None).is_err() { + if folder_dialog.Show(window).is_err() { // User cancelled return Ok(None); } @@ -790,7 +807,7 @@ fn file_open_dialog(options: PathPromptOptions) -> Result>> Ok(Some(paths)) } -fn file_save_dialog(directory: PathBuf) -> Result> { +fn file_save_dialog(directory: PathBuf, window: Option) -> Result> { let dialog: IFileSaveDialog = unsafe { CoCreateInstance(&FileSaveDialog, None, CLSCTX_ALL)? }; if !directory.to_string_lossy().is_empty() { if let Some(full_path) = directory.canonicalize().log_err() { @@ -806,7 +823,7 @@ fn file_save_dialog(directory: PathBuf) -> Result> { pszName: windows::core::w!("All files"), pszSpec: windows::core::w!("*.*"), }])?; - if dialog.Show(None).is_err() { + if dialog.Show(window).is_err() { // User cancelled return Ok(None); }