From 52a0ccee0d6fec65da7e42742525ef508cb5dd28 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 27 Feb 2026 05:27:53 -0300 Subject: [PATCH] Add Print support --- sidebus-broker/src/main.rs | 20 ++++++--- sidebus-broker/src/portal/mod.rs | 1 + sidebus-broker/src/portal/print.rs | 66 ++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 sidebus-broker/src/portal/print.rs diff --git a/sidebus-broker/src/main.rs b/sidebus-broker/src/main.rs index 5946f48..875f480 100644 --- a/sidebus-broker/src/main.rs +++ b/sidebus-broker/src/main.rs @@ -182,6 +182,7 @@ async fn main() -> eyre::Result<()> { ) .await?; let notification_imp = portal::notification::Notification::new(&host_session_conn).await?; + let print_imp = portal::print::Print::new(&host_session_conn).await?; let settings_imp = portal::settings::Settings::new(&host_session_conn).await?; async fn on_vm_bus_connected( @@ -189,6 +190,7 @@ async fn main() -> eyre::Result<()> { file_chooser: portal::file_chooser::FileChooser, file_transfer: portal::file_transfer::FileTransfer, notification: portal::notification::Notification, + print: portal::print::Print, settings: portal::settings::Settings, ) -> Result<(), eyre::Report> { if !vm_bus_conn @@ -239,6 +241,14 @@ async fn main() -> eyre::Result<()> { } }); + if !vm_bus_conn + .object_server() + .at("/org/freedesktop/portal/desktop", print) + .await? + { + error!("org.freedesktop.portal.Print already provided"); + }; + if !vm_bus_conn .object_server() .at("/org/freedesktop/portal/desktop", settings) @@ -264,16 +274,16 @@ async fn main() -> eyre::Result<()> { if let Some(path) = cli.unix_path { let vm_unix_listener = UnixListener::bind(path)?; - server_tasks.spawn(enclose!((file_chooser_imp, file_transfer_imp, notification_imp, settings_imp) async move { + server_tasks.spawn(enclose!((file_chooser_imp, file_transfer_imp, notification_imp, print_imp, settings_imp) async move { while let Ok((socket, remote_addr)) = vm_unix_listener.accept().await { - let f = enclose!((file_chooser_imp, file_transfer_imp, notification_imp, settings_imp) async move { + let f = enclose!((file_chooser_imp, file_transfer_imp, notification_imp, print_imp, settings_imp) async move { let client_conn = zbus::connection::Builder::unix_stream(socket) .auth_mechanism(zbus::AuthMechanism::Anonymous) .name("org.freedesktop.portal.Desktop")? .name("org.freedesktop.portal.Documents")? .build() .await?; - on_vm_bus_connected(client_conn, file_chooser_imp, file_transfer_imp, notification_imp, settings_imp).await + on_vm_bus_connected(client_conn, file_chooser_imp, file_transfer_imp, notification_imp, print_imp, settings_imp).await }); tokio::spawn( async { @@ -294,10 +304,10 @@ async fn main() -> eyre::Result<()> { vsock::ListenerBuilder::new(vsock::VsockAddr::new(vsock::VMADDR_CID_HOST, port)) .with_label("VM Bus") .listen(move |client| { - enclose!((file_chooser_imp, file_transfer_imp, notification_imp, settings_imp) async move { + enclose!((file_chooser_imp, file_transfer_imp, notification_imp, print_imp, settings_imp) async move { // TODO: Not necessary to go through the channel, add vsock support to the Peer too? let client_conn = client.build().await?; - on_vm_bus_connected(client_conn, file_chooser_imp, file_transfer_imp, notification_imp, settings_imp).await + on_vm_bus_connected(client_conn, file_chooser_imp, file_transfer_imp, notification_imp, print_imp, settings_imp).await }) }) .map_ok_or_else( diff --git a/sidebus-broker/src/portal/mod.rs b/sidebus-broker/src/portal/mod.rs index 0f097ac..d43de89 100644 --- a/sidebus-broker/src/portal/mod.rs +++ b/sidebus-broker/src/portal/mod.rs @@ -2,5 +2,6 @@ pub mod documents; pub mod file_chooser; pub mod file_transfer; pub mod notification; +pub mod print; pub mod request; pub mod settings; diff --git a/sidebus-broker/src/portal/print.rs b/sidebus-broker/src/portal/print.rs new file mode 100644 index 0000000..7c77881 --- /dev/null +++ b/sidebus-broker/src/portal/print.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; + +use zbus::{Connection, ObjectServer, fdo::Result, zvariant}; + +use super::request::ReqHandler; + +#[derive(Clone)] +pub struct Print { + host: PrintProxy<'static>, +} + +#[zbus::interface( + name = "org.freedesktop.portal.Print", + proxy( + default_service = "org.freedesktop.portal.Desktop", + default_path = "/org/freedesktop/portal/desktop" + ) +)] +impl Print { + async fn prepare_print( + &self, + #[zbus(header)] hdr: zbus::message::Header<'_>, + #[zbus(object_server)] server: &ObjectServer, + #[zbus(connection)] conn: &Connection, + parent_window: &str, + title: &str, + settings: HashMap<&str, zvariant::Value<'_>>, + page_setup: HashMap<&str, zvariant::Value<'_>>, + options: HashMap<&str, zvariant::Value<'_>>, + ) -> Result { + ReqHandler::prepare(&self.host, hdr, server, conn, &options) + .perform(async || { + self.host + .prepare_print(parent_window, title, settings, page_setup, options) + .await + }) + .await + } + + async fn print( + &self, + #[zbus(header)] hdr: zbus::message::Header<'_>, + #[zbus(object_server)] server: &ObjectServer, + #[zbus(connection)] conn: &Connection, + parent_window: &str, + title: &str, + fd: zvariant::Fd<'_>, + options: HashMap<&str, zvariant::Value<'_>>, + ) -> Result { + ReqHandler::prepare(&self.host, hdr, server, conn, &options) + .perform(async || self.host.print(parent_window, title, fd, options).await) + .await + } + + #[zbus(property, name = "version")] + fn version(&self) -> Result { + Ok(3) + } +} + +impl Print { + pub async fn new(host_session_conn: &Connection) -> Result { + let host = PrintProxy::builder(host_session_conn).build().await?; + Ok(Self { host }) + } +}