Skip to content

Commit

Permalink
windows: Implement cli and handle open_urls (#25412)
Browse files Browse the repository at this point in the history
Closes #ISSUE

Release Notes:

- N/A
  • Loading branch information
JunkuiZhang authored Feb 27, 2025
1 parent 9822d96 commit 672a472
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ zeta = { path = "crates/zeta" }
#

aho-corasick = "1.1"
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", rev = "03c2907b44b4189aac5fdeaea331f5aab5c7072e"}
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", rev = "03c2907b44b4189aac5fdeaea331f5aab5c7072e" }
any_vec = "0.14"
anyhow = "1.0.86"
arrayvec = { version = "0.7.4", features = ["serde"] }
Expand Down Expand Up @@ -544,7 +544,7 @@ tree-sitter-cpp = "0.23"
tree-sitter-css = "0.23"
tree-sitter-elixir = "0.3"
tree-sitter-embedded-template = "0.23.0"
tree-sitter-gitcommit = {git = "https://github.com/zed-industries/tree-sitter-git-commit", rev = "88309716a69dd13ab83443721ba6e0b491d37ee9"}
tree-sitter-gitcommit = { git = "https://github.com/zed-industries/tree-sitter-git-commit", rev = "88309716a69dd13ab83443721ba6e0b491d37ee9" }
tree-sitter-go = "0.23"
tree-sitter-go-mod = { git = "https://github.com/camdencheek/tree-sitter-go-mod", rev = "6efb59652d30e0e9cd5f3b3a669afd6f1a926d3c", package = "tree-sitter-gomod" }
tree-sitter-gowork = { git = "https://github.com/zed-industries/tree-sitter-go-work", rev = "acb0617bf7f4fda02c6217676cc64acb89536dc7" }
Expand Down Expand Up @@ -619,6 +619,7 @@ features = [
"Win32_Storage_FileSystem",
"Win32_System_Com",
"Win32_System_Com_StructuredStorage",
"Win32_System_Console",
"Win32_System_DataExchange",
"Win32_System_LibraryLoader",
"Win32_System_Memory",
Expand All @@ -639,7 +640,7 @@ features = [
# TODO livekit https://github.com/RustAudio/cpal/pull/891
[patch.crates-io]
cpal = { git = "https://github.com/zed-industries/cpal", rev = "fd8bc2fd39f1f5fdee5a0690656caff9a26d9d50" }
real-async-tls = { git = "https://github.com/zed-industries/async-tls", rev = "1e759a4b5e370f87dc15e40756ac4f8815b61d9d", package = "async-tls"}
real-async-tls = { git = "https://github.com/zed-industries/async-tls", rev = "1e759a4b5e370f87dc15e40756ac4f8815b61d9d", package = "async-tls" }

[profile.dev]
split-debuginfo = "unpacked"
Expand Down
5 changes: 4 additions & 1 deletion crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,13 @@ util.workspace = true
tempfile.workspace = true

[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
exec.workspace = true
exec.workspace = true
fork.workspace = true

[target.'cfg(target_os = "macos")'.dependencies]
core-foundation.workspace = true
core-services = "0.2"
plist = "1.3"

[target.'cfg(target_os = "windows")'.dependencies]
windows.workspace = true
98 changes: 88 additions & 10 deletions crates/cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,30 +521,108 @@ mod flatpak {
}
}

// todo("windows")
#[cfg(target_os = "windows")]
mod windows {
use anyhow::Context;
use release_channel::APP_IDENTIFIER;
use windows::{
core::HSTRING,
Win32::{
Foundation::{CloseHandle, GetLastError, ERROR_ALREADY_EXISTS, GENERIC_WRITE},
Storage::FileSystem::{
CreateFileW, WriteFile, FILE_FLAGS_AND_ATTRIBUTES, FILE_SHARE_MODE, OPEN_EXISTING,
},
System::Threading::CreateMutexW,
},
};

use crate::{Detect, InstalledApp};
use std::io;
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::ExitStatus;

struct App;
fn check_single_instance() -> bool {
let mutex = unsafe {
CreateMutexW(
None,
false,
&HSTRING::from(format!("{}-Instance-Mutex", *APP_IDENTIFIER)),
)
.expect("Unable to create instance sync event")
};
let last_err = unsafe { GetLastError() };
let _ = unsafe { CloseHandle(mutex) };
last_err != ERROR_ALREADY_EXISTS
}

struct App(PathBuf);

impl InstalledApp for App {
fn zed_version_string(&self) -> String {
unimplemented!()
format!(
"Zed {}{}{} – {}",
if *release_channel::RELEASE_CHANNEL_NAME == "stable" {
"".to_string()
} else {
format!("{} ", *release_channel::RELEASE_CHANNEL_NAME)
},
option_env!("RELEASE_VERSION").unwrap_or_default(),
match option_env!("ZED_COMMIT_SHA") {
Some(commit_sha) => format!(" {commit_sha} "),
None => "".to_string(),
},
self.0.display(),
)
}
fn launch(&self, _ipc_url: String) -> anyhow::Result<()> {
unimplemented!()

fn launch(&self, ipc_url: String) -> anyhow::Result<()> {
if check_single_instance() {
std::process::Command::new(self.0.clone())
.arg(ipc_url)
.spawn()?;
} else {
unsafe {
let pipe = CreateFileW(
&HSTRING::from(format!("\\\\.\\pipe\\{}-Named-Pipe", *APP_IDENTIFIER)),
GENERIC_WRITE.0,
FILE_SHARE_MODE::default(),
None,
OPEN_EXISTING,
FILE_FLAGS_AND_ATTRIBUTES::default(),
None,
)?;
let message = ipc_url.as_bytes();
let mut bytes_written = 0;
WriteFile(pipe, Some(message), Some(&mut bytes_written), None)?;
CloseHandle(pipe)?;
}
}
Ok(())
}
fn run_foreground(&self, _ipc_url: String) -> io::Result<ExitStatus> {
unimplemented!()

fn run_foreground(&self, ipc_url: String) -> io::Result<ExitStatus> {
std::process::Command::new(self.0.clone())
.arg(ipc_url)
.arg("--foreground")
.spawn()?
.wait()
}
}

impl Detect {
pub fn detect(_path: Option<&Path>) -> anyhow::Result<impl InstalledApp> {
Ok(App)
pub fn detect(path: Option<&Path>) -> anyhow::Result<impl InstalledApp> {
let path = if let Some(path) = path {
path.to_path_buf().canonicalize()?
} else {
std::env::current_exe()?
.parent()
.context("no parent path for cli")?
.parent()
.context("no parent path for cli folder")?
.join("Zed.exe")
};

Ok(App(path))
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions crates/release_channel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ pub static RELEASE_CHANNEL: LazyLock<ReleaseChannel> =
_ => panic!("invalid release channel {}", *RELEASE_CHANNEL_NAME),
});

/// The app identifier for the current release channel, Windows only.
#[cfg(target_os = "windows")]
pub static APP_IDENTIFIER: LazyLock<&str> = LazyLock::new(|| match *RELEASE_CHANNEL {
ReleaseChannel::Dev => "Zed-Editor-Dev",
ReleaseChannel::Nightly => "Zed-Editor-Nightly",
ReleaseChannel::Preview => "Zed-Editor-Preview",
ReleaseChannel::Stable => "Zed-Editor-Stable",
});

/// The Git commit SHA that Zed was built at.
#[derive(Clone)]
pub struct AppCommitSha(pub String);
Expand Down
27 changes: 25 additions & 2 deletions crates/zed/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,22 @@ fn fail_to_open_window(e: anyhow::Error, _cx: &mut App) {
}

fn main() {
let args = Args::parse();

#[cfg(target_os = "windows")]
let run_foreground = args.foreground;

#[cfg(all(not(debug_assertions), target_os = "windows"))]
if run_foreground {
unsafe {
use windows::Win32::System::Console::{AttachConsole, ATTACH_PARENT_PROCESS};

if run_foreground {
let _ = AttachConsole(ATTACH_PARENT_PROCESS);
}
}
}

menu::init();
zed_actions::init();

Expand Down Expand Up @@ -217,7 +233,10 @@ fn main() {

#[cfg(target_os = "windows")]
{
!crate::zed::windows_only_instance::check_single_instance()
!crate::zed::windows_only_instance::check_single_instance(
open_listener.clone(),
run_foreground,
)
}

#[cfg(target_os = "macos")]
Expand Down Expand Up @@ -574,7 +593,6 @@ fn main() {
})
.detach_and_log_err(cx);

let args = Args::parse();
let urls: Vec<_> = args
.paths_or_urls
.iter()
Expand Down Expand Up @@ -1012,6 +1030,11 @@ struct Args {
/// Instructs zed to run as a dev server on this machine. (not implemented)
#[arg(long)]
dev_server_token: Option<String>,

/// Run zed in the foreground, only used on Windows, to match the behavior of the behavior on macOS.
#[arg(long)]
#[cfg(target_os = "windows")]
foreground: bool,
}

#[derive(Clone, Debug)]
Expand Down
Loading

0 comments on commit 672a472

Please sign in to comment.