From 57cbd312253591d463e4c053b51e41c70a53c03e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20K=C3=B6stler?= Date: Fri, 11 Dec 2020 15:38:49 +0100 Subject: [PATCH] Respect starting directory for dialogs on Windows Before this change, FileDialogOptions::starting_directory had not been used on Windows and therefore had no influence on the starting directory of a FileDialog window. This has now been fixed. The use of `SHCreateItemFromParsingName` makes it mandatory to explicitly link against shell32.lib because this is not done automatically since Rust 1.33.0. See https://github.com/rust-lang/rust/pull/56568 for details. --- AUTHORS | 1 + CHANGELOG.md | 3 +++ druid-shell/build.rs | 26 ++++++++++++++++++++++ druid-shell/src/platform/windows/dialog.rs | 16 +++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 druid-shell/build.rs diff --git a/AUTHORS b/AUTHORS index b1bd42ff80..22ddab5b01 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,3 +14,4 @@ Andrey Kabylin Garrett Risley Robert Wittams Jaap Aarts +Maximilian Köstler diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c6a52ff4a..8ffdb3ba9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,7 @@ You can find its changes [documented below](#060---2020-06-01). - `WidgetPod::is_initialized` to check if a widget has received `WidgetAdded`. ([#1259] by [@finnerale]) - `TextBox::with_text_alignment` and `TextBox::set_text_alignment` ([#1371] by [@cmyr]) - Add default minimum size to `WindowConfig`. ([#1438] by [@colinfruit]) +- Windows: Dialogs now respect the parameter passed to `force_starting_directory()` ([#TBD] by [@MaximilianKoestler]) ### Changed @@ -362,6 +363,7 @@ Last release without a changelog :( [@colinfruit]: https://github.com/colinfruit [@Maan2003]: https://github.com/Maan2003 [@derekdreery]: https://github.com/derekdreery +[@MaximilianKoestler]: https://github.com/MaximilianKoestler [#599]: https://github.com/linebender/druid/pull/599 [#611]: https://github.com/linebender/druid/pull/611 @@ -550,6 +552,7 @@ Last release without a changelog :( [#1438]: https://github.com/linebender/druid/pull/1438 [#1441]: https://github.com/linebender/druid/pull/1441 [#1448]: https://github.com/linebender/druid/pull/1448 +[#TBD]: https://github.com/linebender/druid/pull/TBD [Unreleased]: https://github.com/linebender/druid/compare/v0.6.0...master [0.6.0]: https://github.com/linebender/druid/compare/v0.5.0...v0.6.0 diff --git a/druid-shell/build.rs b/druid-shell/build.rs new file mode 100644 index 0000000000..7b6927a929 --- /dev/null +++ b/druid-shell/build.rs @@ -0,0 +1,26 @@ +// Copyright 2020 The Druid Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Build script to modify the build environment + +use std::env; + +fn main() { + let env = env::var("TARGET").unwrap(); + if env.contains("windows") { + // Since https://github.com/rust-lang/rust/pull/56568, shell32 is not included in all + // Windows binaries by default. + println!("cargo:rustc-link-lib=shell32"); + } +} diff --git a/druid-shell/src/platform/windows/dialog.rs b/druid-shell/src/platform/windows/dialog.rs index 6beed7725a..f68d0eb29e 100644 --- a/druid-shell/src/platform/windows/dialog.rs +++ b/druid-shell/src/platform/windows/dialog.rs @@ -26,6 +26,7 @@ use std::convert::TryInto; use std::ffi::OsString; use std::ptr::null_mut; +use winapi::ctypes::c_void; use winapi::shared::minwindef::*; use winapi::shared::ntdef::LPWSTR; use winapi::shared::windef::*; @@ -147,6 +148,21 @@ pub(crate) unsafe fn get_file_dialog_path( as_result(file_dialog.SetOptions(flags))?; + // set a starting directory + if let Some(path) = options.starting_directory { + let mut item: *mut IShellItem = null_mut(); + if let Err(err) = as_result(SHCreateItemFromParsingName( + path.as_os_str().to_wide().as_ptr(), + null_mut(), + &IShellItem::uuidof(), + &mut item as *mut *mut IShellItem as *mut *mut c_void, + )) { + log::warn!("Failed to convert path: {}", err.to_string()); + } else { + as_result(file_dialog.SetDefaultFolder(item))?; + } + } + // show the dialog as_result(file_dialog.Show(hwnd_owner))?; let mut result_ptr: *mut IShellItem = null_mut();