diff --git a/Cargo.lock b/Cargo.lock index a20a71803777cf0a5f89a8d6776797b27800be8c..ce770d9c3094da3f9e880d60d75fc5d4619b24a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -777,6 +777,9 @@ dependencies = [ "serde", "serde_repr", "url", + "wayland-backend", + "wayland-client", + "wayland-protocols 0.32.6", "zbus", ] @@ -7120,7 +7123,7 @@ dependencies = [ "wayland-backend", "wayland-client", "wayland-cursor", - "wayland-protocols", + "wayland-protocols 0.31.2", "wayland-protocols-plasma", "windows 0.61.1", "windows-core 0.61.0", @@ -18400,6 +18403,18 @@ dependencies = [ "wayland-scanner", ] +[[package]] +name = "wayland-protocols" +version = "0.32.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" +dependencies = [ + "bitflags 2.9.0", + "wayland-backend", + "wayland-client", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.2.0" @@ -18409,7 +18424,7 @@ dependencies = [ "bitflags 2.9.0", "wayland-backend", "wayland-client", - "wayland-protocols", + "wayland-protocols 0.31.2", "wayland-scanner", ] diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index 4544b561c33f4507e8264e4eed46711425ce2a04..dc924c99aa23cafed11e0d3f1af105d79ad48ceb 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -38,7 +38,7 @@ wayland = [ "blade-macros", "blade-util", "bytemuck", - "ashpd", + "ashpd/wayland", "cosmic-text", "font-kit", "calloop-wayland-source", diff --git a/crates/gpui/src/platform/linux/platform.rs b/crates/gpui/src/platform/linux/platform.rs index 14405923ed5a78ac94f9c9a1a10fa7662a7b9649..41dc41f6b5401ddded90199cbf077449d0a2f7a6 100644 --- a/crates/gpui/src/platform/linux/platform.rs +++ b/crates/gpui/src/platform/linux/platform.rs @@ -73,6 +73,15 @@ pub trait LinuxClient { fn active_window(&self) -> Option; fn window_stack(&self) -> Option>; fn run(&self); + + #[cfg(any(feature = "wayland", feature = "x11"))] + fn window_identifier( + &self, + ) -> futures::channel::oneshot::Receiver> { + let (sources_tx, sources_rx) = futures::channel::oneshot::channel(); + sources_tx.send(None).ok(); + sources_rx + } } #[derive(Default)] @@ -290,6 +299,9 @@ impl Platform for P { #[cfg(not(any(feature = "wayland", feature = "x11")))] let _ = (done_tx.send(Ok(None)), options); + #[cfg(any(feature = "wayland", feature = "x11"))] + let identifier = self.window_identifier(); + #[cfg(any(feature = "wayland", feature = "x11"))] self.foreground_executor() .spawn(async move { @@ -298,8 +310,10 @@ impl Platform for P { } else { "Open File" }; + let identifier = identifier.await.ok().flatten(); let request = match ashpd::desktop::file_chooser::OpenFileRequest::default() + .identifier(identifier) .modal(true) .title(title) .accept_label(options.prompt.as_ref().map(crate::SharedString::as_str)) @@ -346,6 +360,9 @@ impl Platform for P { #[cfg(not(any(feature = "wayland", feature = "x11")))] let _ = (done_tx.send(Ok(None)), directory, suggested_name); + #[cfg(any(feature = "wayland", feature = "x11"))] + let identifier = self.window_identifier(); + #[cfg(any(feature = "wayland", feature = "x11"))] self.foreground_executor() .spawn({ @@ -353,8 +370,11 @@ impl Platform for P { let suggested_name = suggested_name.map(|s| s.to_owned()); async move { + let identifier = identifier.await.ok().flatten(); + let mut request_builder = ashpd::desktop::file_chooser::SaveFileRequest::default() + .identifier(identifier) .modal(true) .title("Save File") .current_folder(directory) diff --git a/crates/gpui/src/platform/linux/wayland/client.rs b/crates/gpui/src/platform/linux/wayland/client.rs index 8596bddc8dd821426982d618f661d6da621096bb..1101c6b080bc0b8b0db334e4ac0d615e5f6971b4 100644 --- a/crates/gpui/src/platform/linux/wayland/client.rs +++ b/crates/gpui/src/platform/linux/wayland/client.rs @@ -7,6 +7,7 @@ use std::{ time::{Duration, Instant}, }; +use ashpd::WindowIdentifier; use calloop::{ EventLoop, LoopHandle, timer::{TimeoutAction, Timer}, @@ -858,6 +859,25 @@ impl LinuxClient for WaylandClient { fn compositor_name(&self) -> &'static str { "Wayland" } + + fn window_identifier(&self) -> futures::channel::oneshot::Receiver> { + let (done_tx, done_rx) = futures::channel::oneshot::channel(); + let client_state = self.0.borrow(); + let executor = &client_state.common.foreground_executor; + + if let Some(active_window) = client_state.keyboard_focused_window.as_ref() { + let surface = active_window.surface(); + executor + .spawn(async move { + let window_identifier = ashpd::WindowIdentifier::from_wayland(&surface).await; + done_tx.send(window_identifier).ok(); + }) + .detach(); + } else { + done_tx.send(None).ok(); + } + done_rx + } } impl Dispatch for WaylandClientStatePtr { diff --git a/crates/gpui/src/platform/linux/x11/client.rs b/crates/gpui/src/platform/linux/x11/client.rs index e6af7c0d17a54223ecee7a9801eb7a1e59fd6a1a..1edd42d8f53b6ab82fc89d571d2cc77762e6b2fd 100644 --- a/crates/gpui/src/platform/linux/x11/client.rs +++ b/crates/gpui/src/platform/linux/x11/client.rs @@ -1,5 +1,6 @@ use crate::{Capslock, xcb_flush}; use anyhow::{Context as _, anyhow}; +use ashpd::WindowIdentifier; use calloop::{ EventLoop, LoopHandle, RegistrationToken, generic::{FdWrapper, Generic}, @@ -1660,6 +1661,21 @@ impl LinuxClient for X11Client { Some(handles) } + + fn window_identifier(&self) -> futures::channel::oneshot::Receiver> { + let (done_tx, done_rx) = futures::channel::oneshot::channel(); + let state = self.0.borrow(); + if let Some(window) = state + .keyboard_focused_window + .and_then(|focused_window| state.windows.get(&focused_window)) + { + let window_identifier = WindowIdentifier::from_xid(window.window.x_window as u64); + done_tx.send(Some(window_identifier)).ok(); + } else { + done_tx.send(None).ok(); + } + done_rx + } } impl X11ClientState { diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 79a43837252f7dc702b43176d2f06172a3acec18..936d04b677d436f2a2c8ca8d6070a2771136b234 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -284,7 +284,7 @@ pub(crate) struct X11WindowStatePtr { pub state: Rc>, pub(crate) callbacks: Rc>, xcb: Rc, - x_window: xproto::Window, + pub(crate) x_window: xproto::Window, } impl rwh::HasWindowHandle for RawWindow {