Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: file open dialog multiselect fix #2332

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ Manmeet Singh
Simon Fell
Nick Larsen
Thomas McAndrew
Paweł Pykało
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ You can find its changes [documented below](#070---2021-01-01).
- X11: window focus events ([#1938] by [@Maan2003]
- Preserve the aspect ratio of a clipped region in an Image ([#2195] by [@barsae])
- GTK: Hot state now properly resets when the mouse leaves the window via an occluded part. ([#2324] by [@xStrom])
- Windows: generate `commands::OPEN_FILES` when using multiselect in file open dialog. ([#2332] by [@ppykalo])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately the links aren't autogenerated. Please manually define [#2332] at the bottom of the file.


### Visual

Expand Down Expand Up @@ -578,6 +579,7 @@ Last release without a changelog :(
[@benoitryder]: https://github.com/benoitryder
[@sprocklem]: https://github.com/sprocklem
[@cbondurant]: https://github.com/cbondurant
[@ppykalo]: https://github.com/ppykalo

[#599]: https://github.com/linebender/druid/pull/599
[#611]: https://github.com/linebender/druid/pull/611
Expand Down Expand Up @@ -884,6 +886,7 @@ Last release without a changelog :(
[#2323]: https://github.com/linebender/druid/pull/2323
[#2324]: https://github.com/linebender/druid/pull/2324
[#2331]: https://github.com/linebender/druid/pull/2331
[#2332]: https://github.com/linebender/druid/pull/2332

[Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master
[0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0
Expand Down
41 changes: 31 additions & 10 deletions druid-shell/src/backend/windows/dialog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) unsafe fn get_file_dialog_path(
hwnd_owner: HWND,
ty: FileDialogType,
options: FileDialogOptions,
) -> Result<OsString, Error> {
) -> Result<Vec<OsString>, Error> {
let mut pfd: *mut IFileDialog = null_mut();
let (class, id) = match ty {
FileDialogType::Open => (&CLSID_FileOpenDialog, IFileOpenDialog::uuidof()),
Expand Down Expand Up @@ -165,13 +165,34 @@ pub(crate) unsafe fn get_file_dialog_path(

// show the dialog
as_result(file_dialog.Show(hwnd_owner))?;
let mut result_ptr: *mut IShellItem = null_mut();
as_result(file_dialog.GetResult(&mut result_ptr))?;
let shell_item = ComPtr::from_raw(result_ptr);
let mut display_name: LPWSTR = null_mut();
as_result(shell_item.GetDisplayName(SIGDN_FILESYSPATH, &mut display_name))?;
let filename = display_name.to_os_string();
CoTaskMemFree(display_name as LPVOID);

Ok(filename)

let mut result_ptr_vec = Vec::new();
if let Ok(open_file_dialog) = file_dialog.cast::<IFileOpenDialog>() {
let mut results_ptr: *mut IShellItemArray = null_mut();
as_result(open_file_dialog.GetResults(&mut results_ptr))?;
let shell_items = ComPtr::from_raw(results_ptr);
let mut count = 0;
as_result(shell_items.GetCount(&mut count))?;
for i in 0..count {
let mut result_ptr: *mut IShellItem = null_mut();
as_result(shell_items.GetItemAt(i as DWORD, &mut result_ptr))?;
result_ptr_vec.push(result_ptr);
}
} else {
let mut result_ptr: *mut IShellItem = null_mut();
as_result(file_dialog.GetResult(&mut result_ptr))?;
result_ptr_vec.push(result_ptr);
}

let mut filename_vec = Vec::with_capacity(result_ptr_vec.len());
for result_ptr in result_ptr_vec {
let shell_item = ComPtr::from_raw(result_ptr);
let mut display_name: LPWSTR = null_mut();
as_result(shell_item.GetDisplayName(SIGDN_FILESYSPATH, &mut display_name))?;
let filename = display_name.to_os_string();
CoTaskMemFree(display_name as LPVOID);
filename_vec.push(filename);
}

Ok(filename_vec)
}
35 changes: 25 additions & 10 deletions druid-shell/src/backend/windows/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,23 +622,38 @@ impl MyWndProc {
let info = unsafe {
get_file_dialog_path(hwnd, FileDialogType::Save, options)
.ok()
.map(|os_str| FileInfo {
path: os_str.into(),
.map(|s| FileInfo {
// `get_file_dialog_path` guarantees that save dialogs
// only return one path
path: s.first().unwrap().into(),
format: None,
})
};
self.with_wnd_state(|s| s.handler.save_as(token, info));
}
DeferredOp::Open(options, token) => {
let info = unsafe {
get_file_dialog_path(hwnd, FileDialogType::Open, options)
.ok()
.map(|s| FileInfo {
path: s.into(),
format: None,
})
let multi_selection = options.multi_selection;
let infos = unsafe {
match get_file_dialog_path(hwnd, FileDialogType::Open, options) {
Ok(infos) => infos
.iter()
.map(|path| FileInfo {
path: path.into(),
format: None,
})
.collect(),
Err(err) => {
tracing::error!("Error trying to open file: {}", err);
vec![]
}
}
};
self.with_wnd_state(|s| s.handler.open_file(token, info));

if multi_selection {
self.with_wnd_state(|s| s.handler.open_files(token, infos));
} else {
self.with_wnd_state(|s| s.handler.open_file(token, infos.first().cloned()));
}
}
DeferredOp::ContextMenu(menu, pos) => {
let hmenu = menu.into_hmenu();
Expand Down