From b959cd90da236b971121de6ad8d2c03481c90edc Mon Sep 17 00:00:00 2001 From: DENNIS MUUO Date: Sat, 17 Oct 2026 03:31:34 +0300 Subject: [PATCH] Print: open printing preferences for the selected printer on Windows (#2569) When pressing Ctrl+P to open the Print dialog and clicking Setup (or Settings), print.printerSetup previously discarded the selected printer name and unconditionally launched explorer ms-settings:printers. On Windows 10, this opened the Windows Settings Printers and scanners page, displaying the list of installed printers instead of the printer driver printing preferences. Launch Windows native Printing Preferences dialog for the target printer using rundll32.exe printui.dll,PrintUIEntry /e /n printer, falling back to the system default printer or Settings if no printer is available or detected. Add unit tests covering command construction and fallback behavior. Fixes #2569. --- apps/vectorcraft/src/printing.rs | 63 +++++++++++++++++++++++++++++++- contributors/people.toml | 3 ++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/apps/vectorcraft/src/printing.rs b/apps/vectorcraft/src/printing.rs index 525f8bc31..38047a0c5 100644 --- a/apps/vectorcraft/src/printing.rs +++ b/apps/vectorcraft/src/printing.rs @@ -43,11 +43,32 @@ mod system { let settings = craft_print::Job { printer: job.printer.map(str::to_string), title: job.title.into(), ..Default::default() }; craft_print::submit(job.pdf, &settings).map(|note| if note.is_empty() { note } else { format!(" ({note})") }).map_err(|e| e.to_string()) } + #[cfg(windows)] + pub(crate) fn setup_command(printer: Option<&str>, default_printer: Option<&str>) -> Command { + let target = printer + .map(str::trim) + .filter(|p| !p.is_empty()) + .or_else(|| default_printer.map(str::trim).filter(|p| !p.is_empty())); + if let Some(name) = target { + let mut cmd = Command::new("rundll32.exe"); + cmd.args(["printui.dll,PrintUIEntry", "/e", "/n", name]); + cmd + } else { + let mut cmd = Command::new("explorer"); + cmd.arg("ms-settings:printers"); + cmd + } + } pub fn setup(printer: Option<&str>) -> Result<(), String> { #[cfg(windows)] { - let _ = printer; - Command::new("explorer").arg("ms-settings:printers").spawn().map(|_| ()).map_err(|e| e.to_string()) + let list = printers(); + let default = list.iter().find(|p| p.default).or_else(|| list.first()).map(|p| p.name.as_str()); + let mut cmd = setup_command(printer, default); + match cmd.spawn() { + Ok(_) => Ok(()), + Err(_) => Command::new("explorer").arg("ms-settings:printers").spawn().map(|_| ()).map_err(|e| e.to_string()), + } } #[cfg(target_os = "macos")] { @@ -68,3 +89,41 @@ mod system { } } } + +#[cfg(all(test, windows, not(any(feature = "windows7", target_vendor = "win7"))))] +mod tests { + use super::system::setup_command; + use std::ffi::OsStr; + + #[test] + fn setup_command_uses_printui_for_specified_printer() { + let cmd = setup_command(Some("Office Laser"), None); + assert_eq!(cmd.get_program(), "rundll32.exe"); + let args: Vec<&OsStr> = cmd.get_args().collect(); + assert_eq!(args, ["printui.dll,PrintUIEntry", "/e", "/n", "Office Laser"]); + } + + #[test] + fn setup_command_falls_back_to_default_printer() { + let cmd = setup_command(None, Some("Default Proofer")); + assert_eq!(cmd.get_program(), "rundll32.exe"); + let args: Vec<&OsStr> = cmd.get_args().collect(); + assert_eq!(args, ["printui.dll,PrintUIEntry", "/e", "/n", "Default Proofer"]); + } + + #[test] + fn setup_command_trims_whitespace_and_skips_empty() { + let cmd = setup_command(Some(" "), Some("Default Proofer")); + assert_eq!(cmd.get_program(), "rundll32.exe"); + let args: Vec<&OsStr> = cmd.get_args().collect(); + assert_eq!(args, ["printui.dll,PrintUIEntry", "/e", "/n", "Default Proofer"]); + } + + #[test] + fn setup_command_falls_back_to_settings_when_no_printer() { + let cmd = setup_command(None, None); + assert_eq!(cmd.get_program(), "explorer"); + let args: Vec<&OsStr> = cmd.get_args().collect(); + assert_eq!(args, ["ms-settings:printers"]); + } +} diff --git a/contributors/people.toml b/contributors/people.toml index 0716520f9..b62e005ac 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -123,3 +123,6 @@ sync_github_name = false [people.theromis] sync_github_name = true + +[people.dennismutuku2005] +sync_github_name = true