From db813693f3f186dac0bcf67fd939f93ca48a0300 Mon Sep 17 00:00:00 2001 From: gsurrel <1993113+gsurrel@users.noreply.github.com> Date: Mon, 11 May 2026 08:30:17 +0000 Subject: [PATCH 1/2] fix(windows): delegate to winebrowser under Wine When running a Windows-targeted binary under Wine, open requests previously fell back to Wine's bundled `explorer.exe`, which lacks proper host desktop integration. This change detects the Wine environment at runtime (via `WINEPREFIX`, `WINELOADER`, or `WINEDEBUG`) and prepends a winebrowser command to the launcher list. `winebrowser` is Wine's official utility for forwarding file/URL requests to the host OS's default handler (e.g., `xdg-open` on Linux, `open` on macOS). If winebrowser is unavailable or fails, the existing `cmd /c start` fallback is used automatically, preserving backward compatibility. No public API changes or compile-time flags are introduced. --- src/windows.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/windows.rs b/src/windows.rs index 0558222..426f563 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -7,14 +7,41 @@ use std::os::windows::process::CommandExt; const CREATE_NO_WINDOW: u32 = 0x08000000; +/// Detects if the current process is running under Wine by checking environment +/// variables that Wine injects into guest processes. +fn is_running_under_wine() -> bool { + std::env::var_os("WINEPREFIX").is_some() + || std::env::var_os("WINELOADER").is_some() + || std::env::var_os("WINEDEBUG").is_some() +} + +/// Constructs a Command to invoke Wine's winebrowser utility, which forwards +/// file/URL open requests to the host OS's default handler. +fn winebrowser_command>(path: T) -> Command { + let mut cmd = Command::new("winebrowser"); + cmd.arg(path.as_ref()); + // Match Windows behavior: suppress console window flash + cmd.creation_flags(CREATE_NO_WINDOW); + cmd +} + pub fn commands>(path: T) -> Vec { + let mut cmds = Vec::new(); + + // When under Wine, try winebrowser first for seamless host integration. + if is_running_under_wine() { + cmds.push(winebrowser_command(&path)); + } + let mut cmd = Command::new("cmd"); cmd.arg("/c") .arg("start") .raw_arg("\"\"") - .raw_arg(wrap_in_quotes(path)) + .raw_arg(wrap_in_quotes(&path)) .creation_flags(CREATE_NO_WINDOW); - vec![cmd] + cmds.push(cmd); + + cmds } pub fn with_command>(path: T, app: impl Into) -> Command { From f72e64456bc3d46b0d3f910597ebc638b96ae75d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Tue, 12 May 2026 06:22:49 +0800 Subject: [PATCH 2/2] review --- src/windows.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/windows.rs b/src/windows.rs index 426f563..a47f45e 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -27,17 +27,18 @@ fn winebrowser_command>(path: T) -> Command { pub fn commands>(path: T) -> Vec { let mut cmds = Vec::new(); + let path = path.as_ref(); // When under Wine, try winebrowser first for seamless host integration. if is_running_under_wine() { - cmds.push(winebrowser_command(&path)); + cmds.push(winebrowser_command(path)); } let mut cmd = Command::new("cmd"); cmd.arg("/c") .arg("start") .raw_arg("\"\"") - .raw_arg(wrap_in_quotes(&path)) + .raw_arg(wrap_in_quotes(path)) .creation_flags(CREATE_NO_WINDOW); cmds.push(cmd);