From db5d9303041a89241dc2d6bbc5ee78daac6e5e7a Mon Sep 17 00:00:00 2001 From: meowtec Date: Fri, 17 Jun 2022 23:28:31 +0800 Subject: [PATCH 1/2] feat: remove manifest from build.rs and leave it to users --- Cargo.toml | 4 ---- build.rs | 5 ----- examples/message-custom-buttons/.gitignore | 2 ++ examples/message-custom-buttons/Cargo.toml | 12 ++++++++++++ .../message-custom-buttons/app.exe.manifest | 0 examples/message-custom-buttons/build.rs | 6 ++++++ .../message-custom-buttons/manifest.rc | 0 .../src/main.rs} | 0 src/lib.rs | 13 +++++++++++++ 9 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 examples/message-custom-buttons/.gitignore create mode 100644 examples/message-custom-buttons/Cargo.toml rename app.exe.manifest => examples/message-custom-buttons/app.exe.manifest (100%) create mode 100644 examples/message-custom-buttons/build.rs rename manifest.rc => examples/message-custom-buttons/manifest.rc (100%) rename examples/{msg-custom-buttons.rs => message-custom-buttons/src/main.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 7214512..0ef7f80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,11 +70,7 @@ wasm-bindgen-futures = "0.4.19" name = "simple" [[example]] name = "async" -[[example]] -name = "msg-custom-buttons" [package.metadata.docs.rs] features = ["file-handle-inner"] -[build-dependencies] -embed-resource = "1.6" diff --git a/build.rs b/build.rs index adf70d3..cf8219a 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,3 @@ -extern crate embed_resource; - fn main() { let target = std::env::var("TARGET").unwrap(); @@ -12,7 +10,4 @@ fn main() { #[cfg(not(any(feature = "gtk3", feature = "xdg-portal")))] compile_error!("You need to choose at least one backend: `gtk3` or `xdg-portal` features"); - - #[cfg(all(target_os = "windows", feature = "common-controls-v6"))] - embed_resource::compile("manifest.rc"); } diff --git a/examples/message-custom-buttons/.gitignore b/examples/message-custom-buttons/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/examples/message-custom-buttons/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/examples/message-custom-buttons/Cargo.toml b/examples/message-custom-buttons/Cargo.toml new file mode 100644 index 0000000..4d60e38 --- /dev/null +++ b/examples/message-custom-buttons/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "message-custom-buttons" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rfd = {version = "0.9.0", path = "../..", features=["common-controls-v6"]} + +[build-dependencies] +embed-resource = "1.6" diff --git a/app.exe.manifest b/examples/message-custom-buttons/app.exe.manifest similarity index 100% rename from app.exe.manifest rename to examples/message-custom-buttons/app.exe.manifest diff --git a/examples/message-custom-buttons/build.rs b/examples/message-custom-buttons/build.rs new file mode 100644 index 0000000..f108ec0 --- /dev/null +++ b/examples/message-custom-buttons/build.rs @@ -0,0 +1,6 @@ +extern crate embed_resource; + +fn main() { + #[cfg(target_os = "windows")] + embed_resource::compile("manifest.rc"); +} diff --git a/manifest.rc b/examples/message-custom-buttons/manifest.rc similarity index 100% rename from manifest.rc rename to examples/message-custom-buttons/manifest.rc diff --git a/examples/msg-custom-buttons.rs b/examples/message-custom-buttons/src/main.rs similarity index 100% rename from examples/msg-custom-buttons.rs rename to examples/message-custom-buttons/src/main.rs diff --git a/src/lib.rs b/src/lib.rs index 9c0ec83..624f194 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,9 +80,22 @@ //! to [spawn on main and await in other thread](https://github.com/PolyMeilex/rfd/blob/master/examples/async.rs). //! Non-windowed apps will never be able to spawn async dialogs or from threads other than the main thread. //! +//! # Customize button texts of message dialog in Windows +//! +//! `TaskDialogIndirect` API is used for showing message dialog which can have customized button texts. +//! It is only provided by ComCtl32.dll v6 but Windows use v5 by default. +//! If you want to customize button texts or just need a modern dialog style (aka *visual styles*), you will need to: +//! +//! 1. Enable cargo feature `common-controls-v6`. +//! 2. Add an application manifest to use ComCtl32.dll v5. See [Windows Controls / Enabling Visual Styles](https://docs.microsoft.com/en-us/windows/win32/controls/cookbook-overview) +//! +//! +//! Here is an [example](https://github.com/PolyMeilex/rfd/tree/master/examples/message-custom-buttons) using [embed-resource](https://docs.rs/embed-resource/latest/embed_resource/). +//! //! # Cargo features //! * `gtk3`: Uses GTK for dialogs on Linux & BSDs; has no effect on Windows and macOS //! * `xdg-portal`: Uses XDG Desktop Portal instead of GTK on Linux & BSDs +//! * `common-controls-v6`: Use `TaskDialogIndirect` API from ComCtl32.dll v6 for showing message dialog. This is necessary if you need to customize dialog button texts. //! //! # State //! From 6c53cb663004f09fcdbfcccc1bf5ad7be17133ea Mon Sep 17 00:00:00 2001 From: meowtec Date: Fri, 17 Jun 2022 23:52:13 +0800 Subject: [PATCH 2/2] fmt --- examples/message-custom-buttons/Cargo.toml | 2 - src/backend/gtk3/message_dialog.rs | 13 +- src/backend/macos/message_dialog.rs | 23 +--- src/backend/wasm.rs | 4 +- src/backend/win_cid/file_dialog/dialog_ffi.rs | 4 +- src/backend/win_cid/message_dialog.rs | 112 ++++++------------ src/backend/xdg_desktop_portal.rs | 6 +- src/message_dialog.rs | 2 +- 8 files changed, 64 insertions(+), 102 deletions(-) diff --git a/examples/message-custom-buttons/Cargo.toml b/examples/message-custom-buttons/Cargo.toml index 4d60e38..61cb087 100644 --- a/examples/message-custom-buttons/Cargo.toml +++ b/examples/message-custom-buttons/Cargo.toml @@ -3,8 +3,6 @@ name = "message-custom-buttons" version = "0.1.0" edition = "2021" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] rfd = {version = "0.9.0", path = "../..", features=["common-controls-v6"]} diff --git a/src/backend/gtk3/message_dialog.rs b/src/backend/gtk3/message_dialog.rs index 18dd031..7f40cda 100644 --- a/src/backend/gtk3/message_dialog.rs +++ b/src/backend/gtk3/message_dialog.rs @@ -32,11 +32,14 @@ impl GtkMessageDialog { let custom_buttons = match opt.buttons { MessageButtons::OkCustom(ok_text) => vec![ Some((CString::new(ok_text).unwrap(), gtk_sys::GTK_RESPONSE_OK)), - None + None, ], MessageButtons::OkCancelCustom(ok_text, cancel_text) => vec![ Some((CString::new(ok_text).unwrap(), gtk_sys::GTK_RESPONSE_OK)), - Some((CString::new(cancel_text).unwrap(), gtk_sys::GTK_RESPONSE_CANCEL)), + Some(( + CString::new(cancel_text).unwrap(), + gtk_sys::GTK_RESPONSE_CANCEL, + )), ], _ => vec![], }; @@ -58,7 +61,11 @@ impl GtkMessageDialog { for custom_button in custom_buttons { if let Some((custom_button_cstr, response_id)) = custom_button { - gtk_sys::gtk_dialog_add_button(dialog, custom_button_cstr.as_ptr(), response_id); + gtk_sys::gtk_dialog_add_button( + dialog, + custom_button_cstr.as_ptr(), + response_id, + ); } } diff --git a/src/backend/macos/message_dialog.rs b/src/backend/macos/message_dialog.rs index 5d42268..352d700 100644 --- a/src/backend/macos/message_dialog.rs +++ b/src/backend/macos/message_dialog.rs @@ -55,24 +55,11 @@ impl NSAlert { } let buttons = match opt.buttons { - MessageButtons::Ok => vec![ - "OK".to_owned(), - ], - MessageButtons::OkCancel => vec![ - "OK".to_owned(), - "Cancel".to_owned(), - ], - MessageButtons::YesNo => vec![ - "Yes".to_owned(), - "No".to_owned(), - ], - MessageButtons::OkCustom(ok_text) => vec![ - ok_text, - ], - MessageButtons::OkCancelCustom(ok_text, cancel_text) => vec![ - ok_text, - cancel_text, - ], + MessageButtons::Ok => vec!["OK".to_owned()], + MessageButtons::OkCancel => vec!["OK".to_owned(), "Cancel".to_owned()], + MessageButtons::YesNo => vec!["Yes".to_owned(), "No".to_owned()], + MessageButtons::OkCustom(ok_text) => vec![ok_text], + MessageButtons::OkCancelCustom(ok_text, cancel_text) => vec![ok_text, cancel_text], }; for button in buttons { diff --git a/src/backend/wasm.rs b/src/backend/wasm.rs index 2b2ef89..961f507 100644 --- a/src/backend/wasm.rs +++ b/src/backend/wasm.rs @@ -182,7 +182,9 @@ impl MessageDialogImpl for MessageDialog { alert(&text); true } - MessageButtons::OkCancel | MessageButtons::YesNo | MessageButtons::OkCancelCustom(_, _) => confirm(&text), + MessageButtons::OkCancel + | MessageButtons::YesNo + | MessageButtons::OkCancelCustom(_, _) => confirm(&text), } } } diff --git a/src/backend/win_cid/file_dialog/dialog_ffi.rs b/src/backend/win_cid/file_dialog/dialog_ffi.rs index 07ab498..421961a 100644 --- a/src/backend/win_cid/file_dialog/dialog_ffi.rs +++ b/src/backend/win_cid/file_dialog/dialog_ffi.rs @@ -8,8 +8,8 @@ use windows::Win32::{ System::Com::{CoCreateInstance, CoTaskMemFree, CLSCTX_INPROC_SERVER}, UI::Shell::{ Common::COMDLG_FILTERSPEC, FileOpenDialog, FileSaveDialog, IFileDialog, IFileOpenDialog, - IFileSaveDialog, IShellItem, SHCreateItemFromParsingName, FOS_ALLOWMULTISELECT, - FOS_PICKFOLDERS, SIGDN_FILESYSPATH, FILEOPENDIALOGOPTIONS, + IFileSaveDialog, IShellItem, SHCreateItemFromParsingName, FILEOPENDIALOGOPTIONS, + FOS_ALLOWMULTISELECT, FOS_PICKFOLDERS, SIGDN_FILESYSPATH, }, }; diff --git a/src/backend/win_cid/message_dialog.rs b/src/backend/win_cid/message_dialog.rs index 305d705..cf861b1 100644 --- a/src/backend/win_cid/message_dialog.rs +++ b/src/backend/win_cid/message_dialog.rs @@ -4,30 +4,18 @@ use crate::message_dialog::{MessageButtons, MessageDialog}; use windows::{ core::PCWSTR, Win32::{ - Foundation::{ - HWND, - }, - UI::{ - WindowsAndMessaging::{ - IDOK, IDYES - }, - } + Foundation::HWND, + UI::WindowsAndMessaging::{IDOK, IDYES}, }, }; #[cfg(not(feature = "common-controls-v6"))] -use crate::message_dialog::{MessageLevel}; +use crate::message_dialog::MessageLevel; #[cfg(not(feature = "common-controls-v6"))] -use windows::{ - Win32::{ - UI::{ - WindowsAndMessaging::{ - MessageBoxW, MB_ICONERROR, MB_ICONINFORMATION, MB_ICONWARNING, MB_OK, - MB_OKCANCEL, MB_YESNO, MESSAGEBOX_STYLE, - }, - } - }, +use windows::Win32::UI::WindowsAndMessaging::{ + MessageBoxW, MB_ICONERROR, MB_ICONINFORMATION, MB_ICONWARNING, MB_OK, MB_OKCANCEL, MB_YESNO, + MESSAGEBOX_STYLE, }; use raw_window_handle::RawWindowHandle; @@ -49,10 +37,7 @@ pub struct WinMessageDialog { unsafe impl Send for WinMessageDialog {} fn str_to_vec_u16(str: &str) -> Vec { - OsStr::new(str) - .encode_wide() - .chain(once(0)) - .collect() + OsStr::new(str).encode_wide().chain(once(0)).collect() } impl WinMessageDialog { @@ -94,18 +79,12 @@ impl WinMessageDialog { #[cfg(feature = "common-controls-v6")] pub fn run(mut self) -> bool { use windows::Win32::{ + Foundation::BOOL, UI::Controls::{ - TASKDIALOGCONFIG, - TDF_ALLOW_DIALOG_CANCELLATION, - TASKDIALOG_BUTTON, - TaskDialogIndirect, - TASKDIALOG_COMMON_BUTTON_FLAGS, - TDCBF_YES_BUTTON, - TDCBF_NO_BUTTON, - TDCBF_OK_BUTTON, - TDCBF_CANCEL_BUTTON, + TaskDialogIndirect, TASKDIALOGCONFIG, TASKDIALOG_BUTTON, + TASKDIALOG_COMMON_BUTTON_FLAGS, TDCBF_CANCEL_BUTTON, TDCBF_NO_BUTTON, + TDCBF_OK_BUTTON, TDCBF_YES_BUTTON, TDF_ALLOW_DIALOG_CANCELLATION, }, - Foundation::BOOL, }; let mut pf_verification_flag_checked = BOOL(0); @@ -126,44 +105,35 @@ impl WinMessageDialog { }; let (system_buttons, custom_buttons) = match self.opt.buttons { - MessageButtons::Ok => { - (TDCBF_OK_BUTTON, vec![]) - }, - MessageButtons::OkCancel => { - ( - TASKDIALOG_COMMON_BUTTON_FLAGS(TDCBF_OK_BUTTON.0 | TDCBF_CANCEL_BUTTON.0), - vec![], - ) - }, - MessageButtons::YesNo => { - ( - TASKDIALOG_COMMON_BUTTON_FLAGS(TDCBF_YES_BUTTON.0 | TDCBF_NO_BUTTON.0), - vec![], - ) - }, - MessageButtons::OkCustom(ok_text) => { - ( - Default::default(), - vec![ - (id_custom_ok, str_to_vec_u16(&ok_text)), - ], - ) - }, - MessageButtons::OkCancelCustom(ok_text, cancel_text) => { - ( - Default::default(), - vec![ - (id_custom_ok, str_to_vec_u16(&ok_text)), - (id_custom_cancel, str_to_vec_u16(&cancel_text)), - ], - ) - }, + MessageButtons::Ok => (TDCBF_OK_BUTTON, vec![]), + MessageButtons::OkCancel => ( + TASKDIALOG_COMMON_BUTTON_FLAGS(TDCBF_OK_BUTTON.0 | TDCBF_CANCEL_BUTTON.0), + vec![], + ), + MessageButtons::YesNo => ( + TASKDIALOG_COMMON_BUTTON_FLAGS(TDCBF_YES_BUTTON.0 | TDCBF_NO_BUTTON.0), + vec![], + ), + MessageButtons::OkCustom(ok_text) => ( + Default::default(), + vec![(id_custom_ok, str_to_vec_u16(&ok_text))], + ), + MessageButtons::OkCancelCustom(ok_text, cancel_text) => ( + Default::default(), + vec![ + (id_custom_ok, str_to_vec_u16(&ok_text)), + (id_custom_cancel, str_to_vec_u16(&cancel_text)), + ], + ), }; - let p_buttons = custom_buttons.iter().map(|(id, text)| TASKDIALOG_BUTTON { - nButtonID: *id, - pszButtonText: PCWSTR(text.as_ptr()), - }).collect::>(); + let p_buttons = custom_buttons + .iter() + .map(|(id, text)| TASKDIALOG_BUTTON { + nButtonID: *id, + pszButtonText: PCWSTR(text.as_ptr()), + }) + .collect::>(); task_dialog_config.dwCommonButtons = system_buttons; task_dialog_config.pButtons = p_buttons.as_ptr(); task_dialog_config.cButtons = custom_buttons.len() as u32; @@ -177,11 +147,7 @@ impl WinMessageDialog { ) }; - ret.is_ok() && ( - pn_button == id_custom_ok - || pn_button == IDYES.0 - || pn_button == IDOK.0 - ) + ret.is_ok() && (pn_button == id_custom_ok || pn_button == IDYES.0 || pn_button == IDOK.0) } #[cfg(not(feature = "common-controls-v6"))] diff --git a/src/backend/xdg_desktop_portal.rs b/src/backend/xdg_desktop_portal.rs index b464f9d..3f0a685 100644 --- a/src/backend/xdg_desktop_portal.rs +++ b/src/backend/xdg_desktop_portal.rs @@ -48,8 +48,10 @@ fn add_filters_to_save_file_options( // refer to https://github.com/flatpak/xdg-desktop-portal/issues/213 fn uri_to_pathbuf(uri: &str) -> Option { - urlencoding::decode(uri).ok()? - .strip_prefix("file://").map(PathBuf::from) + urlencoding::decode(uri) + .ok()? + .strip_prefix("file://") + .map(PathBuf::from) } fn ok_or_warn(result: Result) -> Option { diff --git a/src/message_dialog.rs b/src/message_dialog.rs index 079d802..8ef80ae 100644 --- a/src/message_dialog.rs +++ b/src/message_dialog.rs @@ -163,7 +163,7 @@ pub enum MessageButtons { OkCustom(String), /// Two customizable buttons. /// Notice that in Windows, this only works with the feature *common-controls-v6* enabled - OkCancelCustom(String, String) + OkCancelCustom(String, String), } impl Default for MessageButtons {