Detailed changes
@@ -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",
]
@@ -38,7 +38,7 @@ wayland = [
"blade-macros",
"blade-util",
"bytemuck",
- "ashpd",
+ "ashpd/wayland",
"cosmic-text",
"font-kit",
"calloop-wayland-source",
@@ -73,6 +73,15 @@ pub trait LinuxClient {
fn active_window(&self) -> Option<AnyWindowHandle>;
fn window_stack(&self) -> Option<Vec<AnyWindowHandle>>;
fn run(&self);
+
+ #[cfg(any(feature = "wayland", feature = "x11"))]
+ fn window_identifier(
+ &self,
+ ) -> futures::channel::oneshot::Receiver<Option<ashpd::WindowIdentifier>> {
+ let (sources_tx, sources_rx) = futures::channel::oneshot::channel();
+ sources_tx.send(None).ok();
+ sources_rx
+ }
}
#[derive(Default)]
@@ -290,6 +299,9 @@ impl<P: LinuxClient + 'static> 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<P: LinuxClient + 'static> 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<P: LinuxClient + 'static> 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<P: LinuxClient + 'static> 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)
@@ -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<Option<WindowIdentifier>> {
+ 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<wl_registry::WlRegistry, GlobalListContents> for WaylandClientStatePtr {
@@ -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<Option<WindowIdentifier>> {
+ 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 {
@@ -284,7 +284,7 @@ pub(crate) struct X11WindowStatePtr {
pub state: Rc<RefCell<X11WindowState>>,
pub(crate) callbacks: Rc<RefCell<Callbacks>>,
xcb: Rc<XCBConnection>,
- x_window: xproto::Window,
+ pub(crate) x_window: xproto::Window,
}
impl rwh::HasWindowHandle for RawWindow {