Browse Source

fix(win32): Sidecar spawning a window (#14197)

Luke Parker 1 month ago
parent
commit
7033b4d0a8

+ 1 - 0
packages/desktop/src-tauri/Cargo.lock

@@ -3136,6 +3136,7 @@ dependencies = [
  "tracing-subscriber",
  "uuid",
  "webkit2gtk",
+ "windows 0.62.2",
 ]
 
 [[package]]

+ 3 - 0
packages/desktop/src-tauri/Cargo.toml

@@ -54,6 +54,9 @@ chrono = "0.4"
 tokio-stream = { version = "0.1.18", features = ["sync"] }
 process-wrap = { version = "9.0.3", features = ["tokio1"] }
 
+[target.'cfg(windows)'.dependencies]
+windows = { version = "0.62", features = ["Win32_System_Threading"] }
+
 [target.'cfg(target_os = "linux")'.dependencies]
 gtk = "0.18.2"
 webkit2gtk = "=2.0.2"

+ 18 - 6
packages/desktop/src-tauri/src/cli.rs

@@ -3,7 +3,7 @@ use process_wrap::tokio::CommandWrap;
 #[cfg(unix)]
 use process_wrap::tokio::ProcessGroup;
 #[cfg(windows)]
-use process_wrap::tokio::{JobObject, KillOnDrop};
+use process_wrap::tokio::{CommandWrapper, JobObject, KillOnDrop};
 #[cfg(unix)]
 use std::os::unix::process::ExitStatusExt;
 use std::sync::Arc;
@@ -18,9 +18,24 @@ use tokio::{
 };
 use tokio_stream::wrappers::ReceiverStream;
 use tracing::Instrument;
+#[cfg(windows)]
+use windows::Win32::System::Threading::{CREATE_NO_WINDOW, CREATE_SUSPENDED};
 
 use crate::server::get_wsl_config;
 
+#[cfg(windows)]
+#[derive(Clone, Copy, Debug)]
+// Keep this as a custom wrapper instead of process_wrap::CreationFlags.
+// JobObject pre_spawn rewrites creation flags, so this must run after it.
+struct WinCreationFlags;
+
+#[cfg(windows)]
+impl CommandWrapper for WinCreationFlags {
+    fn pre_spawn(&mut self, command: &mut Command, _core: &CommandWrap) -> std::io::Result<()> {
+        command.creation_flags((CREATE_NO_WINDOW | CREATE_SUSPENDED).0);
+        Ok(())
+    }
+}
 
 const CLI_INSTALL_DIR: &str = ".opencode/bin";
 const CLI_BINARY_NAME: &str = "opencode";
@@ -203,7 +218,7 @@ fn get_user_shell() -> String {
 }
 
 fn is_wsl_enabled(_app: &tauri::AppHandle) -> bool {
-  get_wsl_config(_app.clone()).is_ok_and(|v| v.enabled)
+    get_wsl_config(_app.clone()).is_ok_and(|v| v.enabled)
 }
 
 fn shell_escape(input: &str) -> String {
@@ -318,9 +333,6 @@ pub fn spawn_command(
     cmd.stderr(Stdio::piped());
     cmd.stdin(Stdio::null());
 
-    #[cfg(windows)]
-    cmd.creation_flags(0x0800_0000);
-
     let mut wrap = CommandWrap::from(cmd);
 
     #[cfg(unix)]
@@ -330,7 +342,7 @@ pub fn spawn_command(
 
     #[cfg(windows)]
     {
-        wrap.wrap(JobObject).wrap(KillOnDrop);
+        wrap.wrap(JobObject).wrap(WinCreationFlags).wrap(KillOnDrop);
     }
 
     let mut child = wrap.spawn()?;