Desktop: Add support for opening files through the already-running instance via a local socket (#4123)

* Desktop: Forward file-open args from a second launch to the running instance

Also adds socket infrastructure that can be used in the future to allow dispatching actions from another process

* Use socket instead of ipc terminologie

* Fix

* Fix

* Better pipe name on windows
This commit is contained in:
Timon
2026-05-09 18:11:44 +00:00
committed by GitHub
parent a28b9437aa
commit 98daa75c26
10 changed files with 260 additions and 83 deletions
+20 -24
View File
@@ -45,7 +45,6 @@ pub(crate) struct App {
start_render_sender: SyncSender<()>,
web_communication_initialized: bool,
web_communication_startup_buffer: Vec<Vec<u8>>,
#[cfg_attr(not(target_os = "macos"), expect(unused))]
preferences: Preferences,
launch_documents: Option<Vec<PathBuf>>,
startup_time: Option<Instant>,
@@ -320,7 +319,7 @@ impl App {
tracing::error!("OpenLaunchDocuments should only be sent once");
return;
};
self.open_files(launch_documents);
self.app_event_scheduler.schedule(AppEvent::OpenFiles(launch_documents));
}
DesktopFrontendMessage::UpdateMenu { entries } => {
if let Some(window) = &self.window {
@@ -478,13 +477,28 @@ impl App {
tracing::info!("Exiting main event loop");
event_loop.exit();
}
#[cfg(target_os = "macos")]
AppEvent::AddLaunchDocuments(paths) => {
AppEvent::OpenFiles(paths) => {
// Accumulate launch documents until OpenLaunchDocuments message is received
if let Some(launch_documents) = &mut self.launch_documents {
launch_documents.extend(paths);
} else {
self.open_files(paths);
return;
}
if paths.is_empty() {
return;
}
let app_event_scheduler = self.app_event_scheduler.clone();
let _ = thread::spawn(move || {
for path in paths {
tracing::info!("Opening file: {}", path.display());
if let Ok(content) = fs::read(&path) {
let message = DesktopWrapperMessage::OpenFile { path, content };
app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
} else {
tracing::error!("Failed to read file: {}", path.display());
}
}
});
}
#[cfg(target_os = "macos")]
AppEvent::MenuEvent { id } => {
@@ -492,24 +506,6 @@ impl App {
}
}
}
fn open_files(&mut self, paths: Vec<PathBuf>) {
if paths.is_empty() {
return;
}
let app_event_scheduler = self.app_event_scheduler.clone();
let _ = thread::spawn(move || {
for path in paths {
tracing::info!("Opening file: {}", path.display());
if let Ok(content) = fs::read(&path) {
let message = DesktopWrapperMessage::OpenFile { path, content };
app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message));
} else {
tracing::error!("Failed to read file: {}", path.display());
}
}
});
}
}
impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {