From 1606a7016e4ed33150924454e1af87cd793ba8a4 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 20 May 2021 12:23:35 -0300 Subject: [PATCH 1/2] feat(windows): allow parent window to be set --- src/backend/win_cid/file_dialog/dialog_ffi.rs | 44 ++++++++++++++----- src/dialog.rs | 4 +- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/backend/win_cid/file_dialog/dialog_ffi.rs b/src/backend/win_cid/file_dialog/dialog_ffi.rs index 72222ac..858600e 100644 --- a/src/backend/win_cid/file_dialog/dialog_ffi.rs +++ b/src/backend/win_cid/file_dialog/dialog_ffi.rs @@ -1,7 +1,7 @@ use crate::FileDialog; use std::{ - ffi::{OsStr, OsString}, + ffi::{c_void, OsStr, OsString}, iter::once, ops::Deref, os::windows::{ffi::OsStrExt, prelude::OsStringExt}, @@ -28,6 +28,9 @@ use winapi::{ Interface, }; +#[cfg(feature = "parent")] +use raw_window_handle::RawWindowHandle; + use super::super::utils::ToResult; fn to_os_string(s: &LPWSTR) -> OsString { @@ -41,7 +44,7 @@ fn to_os_string(s: &LPWSTR) -> OsString { OsStringExt::from_wide(slice) } -pub struct IDialog(pub *mut IFileDialog); +pub struct IDialog(pub *mut IFileDialog, Option<*mut c_void>); impl IDialog { fn new_file_dialog(class: &GUID, id: &GUID) -> Result<*mut IFileDialog, HRESULT> { @@ -61,14 +64,30 @@ impl IDialog { Ok(dialog) } - fn new_open_dialog() -> Result { + fn new_open_dialog(opt: &FileDialog) -> Result { let ptr = Self::new_file_dialog(&CLSID_FileOpenDialog, &IFileOpenDialog::uuidof())?; - Ok(Self(ptr)) + #[cfg(feature = "parent")] + let parent = match opt.parent { + Some(RawWindowHandle::Windows(handle)) => Some(handle.hwnd), + None => None, + _ => unreachable!("Unsuported window handle, expected: Windows"), + }; + #[cfg(not(feature = "parent"))] + let parent = None; + Ok(Self(ptr, parent)) } - fn new_save_dialog() -> Result { + fn new_save_dialog(opt: &FileDialog) -> Result { let ptr = Self::new_file_dialog(&CLSID_FileSaveDialog, &IFileSaveDialog::uuidof())?; - Ok(Self(ptr)) + #[cfg(feature = "parent")] + let parent = match opt.parent { + Some(RawWindowHandle::Windows(handle)) => Some(handle.hwnd), + None => None, + _ => unreachable!("Unsuported window handle, expected: Windows"), + }; + #[cfg(not(feature = "parent"))] + let parent = None; + Ok(Self(ptr, parent)) } fn add_filters(&self, filters: &[crate::dialog::Filter]) -> Result<(), HRESULT> { @@ -202,14 +221,17 @@ impl IDialog { } pub fn show(&self) -> Result<(), HRESULT> { - unsafe { self.Show(ptr::null_mut()).check()? }; + unsafe { + self.Show(self.1.unwrap_or_else(|| ptr::null_mut()) as _) + .check()? + }; Ok(()) } } impl IDialog { pub fn build_pick_file(opt: &FileDialog) -> Result { - let dialog = IDialog::new_open_dialog()?; + let dialog = IDialog::new_open_dialog(opt)?; dialog.add_filters(&opt.filters)?; dialog.set_path(&opt.starting_directory)?; @@ -219,7 +241,7 @@ impl IDialog { } pub fn build_save_file(opt: &FileDialog) -> Result { - let dialog = IDialog::new_save_dialog()?; + let dialog = IDialog::new_save_dialog(opt)?; dialog.add_filters(&opt.filters)?; dialog.set_path(&opt.starting_directory)?; @@ -229,7 +251,7 @@ impl IDialog { } pub fn build_pick_folder(opt: &FileDialog) -> Result { - let dialog = IDialog::new_open_dialog()?; + let dialog = IDialog::new_open_dialog(opt)?; dialog.set_path(&opt.starting_directory)?; @@ -241,7 +263,7 @@ impl IDialog { } pub fn build_pick_files(opt: &FileDialog) -> Result { - let dialog = IDialog::new_open_dialog()?; + let dialog = IDialog::new_open_dialog(opt)?; dialog.add_filters(&opt.filters)?; dialog.set_path(&opt.starting_directory)?; diff --git a/src/dialog.rs b/src/dialog.rs index 74af461..d790d62 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -73,7 +73,7 @@ impl FileDialog { } #[cfg(feature = "parent")] - fn set_parent(mut self, parent: &W) -> Self { + pub fn set_parent(mut self, parent: &W) -> Self { self.parent = Some(parent.raw_window_handle()); self } @@ -171,7 +171,7 @@ impl AsyncFileDialog { #[cfg(feature = "parent")] /// Set parent windows explicitly (optional) - /// Suported in: `macos` + /// Suported in: `macos` and `windows` pub fn set_parent(mut self, parent: &W) -> Self { self.file_dialog = self.file_dialog.set_parent(parent); self From 4c990bb0be58f105465a98887ff65b733b40d150 Mon Sep 17 00:00:00 2001 From: Poly Date: Thu, 20 May 2021 23:29:02 +0200 Subject: [PATCH 2/2] Add `set_parent` docs to synchronous `FileDialog` --- src/dialog.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dialog.rs b/src/dialog.rs index d790d62..dfdb04c 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -73,6 +73,8 @@ impl FileDialog { } #[cfg(feature = "parent")] + /// Set parent windows explicitly (optional) + /// Suported in: `macos` and `windows` pub fn set_parent(mut self, parent: &W) -> Self { self.parent = Some(parent.raw_window_handle()); self