Skip to content

Commit

Permalink
Merge pull request #14 from lucasfernog/feat/dialog-owner
Browse files Browse the repository at this point in the history
feat(windows): allow parent window to be set
  • Loading branch information
PolyMeilex authored May 20, 2021
2 parents 059f5f1 + 4c990bb commit 6a361d5
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
44 changes: 33 additions & 11 deletions src/backend/win_cid/file_dialog/dialog_ffi.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -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 {
Expand All @@ -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> {
Expand All @@ -61,14 +64,30 @@ impl IDialog {
Ok(dialog)
}

fn new_open_dialog() -> Result<Self, HRESULT> {
fn new_open_dialog(opt: &FileDialog) -> Result<Self, HRESULT> {
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<Self, HRESULT> {
fn new_save_dialog(opt: &FileDialog) -> Result<Self, HRESULT> {
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> {
Expand Down Expand Up @@ -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<Self, HRESULT> {
let dialog = IDialog::new_open_dialog()?;
let dialog = IDialog::new_open_dialog(opt)?;

dialog.add_filters(&opt.filters)?;
dialog.set_path(&opt.starting_directory)?;
Expand All @@ -219,7 +241,7 @@ impl IDialog {
}

pub fn build_save_file(opt: &FileDialog) -> Result<Self, HRESULT> {
let dialog = IDialog::new_save_dialog()?;
let dialog = IDialog::new_save_dialog(opt)?;

dialog.add_filters(&opt.filters)?;
dialog.set_path(&opt.starting_directory)?;
Expand All @@ -229,7 +251,7 @@ impl IDialog {
}

pub fn build_pick_folder(opt: &FileDialog) -> Result<Self, HRESULT> {
let dialog = IDialog::new_open_dialog()?;
let dialog = IDialog::new_open_dialog(opt)?;

dialog.set_path(&opt.starting_directory)?;

Expand All @@ -241,7 +263,7 @@ impl IDialog {
}

pub fn build_pick_files(opt: &FileDialog) -> Result<Self, HRESULT> {
let dialog = IDialog::new_open_dialog()?;
let dialog = IDialog::new_open_dialog(opt)?;

dialog.add_filters(&opt.filters)?;
dialog.set_path(&opt.starting_directory)?;
Expand Down
6 changes: 4 additions & 2 deletions src/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ impl FileDialog {
}

#[cfg(feature = "parent")]
fn set_parent<W: HasRawWindowHandle>(mut self, parent: &W) -> Self {
/// Set parent windows explicitly (optional)
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasRawWindowHandle>(mut self, parent: &W) -> Self {
self.parent = Some(parent.raw_window_handle());
self
}
Expand Down Expand Up @@ -171,7 +173,7 @@ impl AsyncFileDialog {

#[cfg(feature = "parent")]
/// Set parent windows explicitly (optional)
/// Suported in: `macos`
/// Suported in: `macos` and `windows`
pub fn set_parent<W: HasRawWindowHandle>(mut self, parent: &W) -> Self {
self.file_dialog = self.file_dialog.set_parent(parent);
self
Expand Down

0 comments on commit 6a361d5

Please sign in to comment.