ashpd/desktop/
screenshot.rs1use std::fmt::Debug;
37
38use serde::{Deserialize, Serialize};
39use zbus::zvariant::{
40 Optional, Type,
41 as_value::{self, optional},
42};
43
44use super::{HandleToken, Request};
45use crate::{Error, Uri, WindowIdentifier, desktop::Color, proxy::Proxy};
46
47#[derive(Serialize, Deserialize, Type, Debug, Default)]
49#[zvariant(signature = "dict")]
50pub struct ScreenshotOptions {
51 #[serde(with = "as_value", skip_deserializing)]
52 handle_token: HandleToken,
53 #[serde(default, with = "optional", skip_serializing_if = "Option::is_none")]
54 modal: Option<bool>,
55 #[serde(default, with = "optional", skip_serializing_if = "Option::is_none")]
56 interactive: Option<bool>,
57 #[serde(default, with = "optional", skip_serializing)]
58 #[cfg_attr(not(feature = "backend"), allow(dead_code))]
59 permission_store_checked: Option<bool>,
60}
61
62impl ScreenshotOptions {
63 #[must_use]
65 pub fn set_modal(mut self, modal: impl Into<Option<bool>>) -> Self {
66 self.modal = modal.into();
67 self
68 }
69
70 #[cfg(feature = "backend")]
72 pub fn modal(&self) -> Option<bool> {
73 self.modal
74 }
75
76 #[must_use]
78 pub fn set_interactive(mut self, interactive: impl Into<Option<bool>>) -> Self {
79 self.interactive = interactive.into();
80 self
81 }
82
83 #[cfg(feature = "backend")]
85 pub fn interactive(&self) -> Option<bool> {
86 self.interactive
87 }
88
89 #[cfg(feature = "backend")]
91 pub fn permission_store_checked(&self) -> Option<bool> {
92 self.permission_store_checked
93 }
94}
95
96#[derive(Serialize, Deserialize, Type)]
97#[zvariant(signature = "dict")]
98pub struct Screenshot {
100 #[serde(with = "as_value")]
101 uri: Uri,
102}
103
104impl Screenshot {
105 #[cfg(feature = "backend")]
106 #[cfg_attr(docsrs, doc(cfg(feature = "backend")))]
107 pub fn new(uri: Uri) -> Self {
109 Self { uri }
110 }
111
112 pub fn request() -> ScreenshotRequest {
117 ScreenshotRequest::default()
118 }
119
120 pub fn uri(&self) -> &Uri {
122 &self.uri
123 }
124}
125
126impl Debug for Screenshot {
127 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 f.write_str(self.uri.as_str())
129 }
130}
131
132#[derive(Serialize, Deserialize, Type, Debug, Default)]
134#[zvariant(signature = "dict")]
135pub struct ColorOptions {
136 #[serde(with = "as_value", skip_deserializing)]
137 handle_token: HandleToken,
138}
139
140#[derive(Debug)]
142#[doc(alias = "org.freedesktop.portal.Screenshot")]
143pub struct ScreenshotProxy(Proxy<'static>);
144
145impl ScreenshotProxy {
146 pub async fn new() -> Result<Self, Error> {
148 let proxy = Proxy::new_desktop("org.freedesktop.portal.Screenshot").await?;
149 Ok(Self(proxy))
150 }
151
152 pub async fn with_connection(connection: zbus::Connection) -> Result<Self, Error> {
154 let proxy =
155 Proxy::new_desktop_with_connection(connection, "org.freedesktop.portal.Screenshot")
156 .await?;
157 Ok(Self(proxy))
158 }
159
160 pub fn version(&self) -> u32 {
162 self.0.version()
163 }
164
165 #[doc(alias = "PickColor")]
175 #[doc(alias = "xdp_portal_pick_color")]
176 pub async fn pick_color(
177 &self,
178 identifier: Option<&WindowIdentifier>,
179 options: ColorOptions,
180 ) -> Result<Request<Color>, Error> {
181 let identifier = Optional::from(identifier);
182 self.0
183 .request(&options.handle_token, "PickColor", &(identifier, &options))
184 .await
185 }
186
187 #[doc(alias = "Screenshot")]
204 #[doc(alias = "xdp_portal_take_screenshot")]
205 pub async fn screenshot(
206 &self,
207 identifier: Option<&WindowIdentifier>,
208 options: ScreenshotOptions,
209 ) -> Result<Request<Screenshot>, Error> {
210 let identifier = Optional::from(identifier);
211 self.0
212 .request(&options.handle_token, "Screenshot", &(identifier, &options))
213 .await
214 }
215}
216
217impl std::ops::Deref for ScreenshotProxy {
218 type Target = zbus::Proxy<'static>;
219
220 fn deref(&self) -> &Self::Target {
221 &self.0
222 }
223}
224
225#[derive(Debug, Default)]
226#[doc(alias = "xdp_portal_pick_color")]
227pub struct ColorRequest {
231 identifier: Option<WindowIdentifier>,
232 options: ColorOptions,
233 connection: Option<zbus::Connection>,
234}
235
236impl ColorRequest {
237 #[must_use]
238 pub fn identifier(mut self, identifier: impl Into<Option<WindowIdentifier>>) -> Self {
240 self.identifier = identifier.into();
241 self
242 }
243
244 #[must_use]
245 pub fn connection(mut self, connection: Option<zbus::Connection>) -> Self {
247 self.connection = connection;
248 self
249 }
250
251 pub async fn send(self) -> Result<Request<Color>, Error> {
253 let proxy = if let Some(connection) = self.connection {
254 ScreenshotProxy::with_connection(connection).await?
255 } else {
256 ScreenshotProxy::new().await?
257 };
258 proxy
259 .pick_color(self.identifier.as_ref(), self.options)
260 .await
261 }
262}
263
264impl Color {
265 pub fn pick() -> ColorRequest {
270 ColorRequest::default()
271 }
272}
273
274#[derive(Debug, Default)]
275#[doc(alias = "xdp_portal_take_screenshot")]
276pub struct ScreenshotRequest {
280 options: ScreenshotOptions,
281 identifier: Option<WindowIdentifier>,
282 connection: Option<zbus::Connection>,
283}
284
285impl ScreenshotRequest {
286 #[must_use]
287 pub fn identifier(mut self, identifier: impl Into<Option<WindowIdentifier>>) -> Self {
289 self.identifier = identifier.into();
290 self
291 }
292
293 #[must_use]
295 pub fn modal(mut self, modal: impl Into<Option<bool>>) -> Self {
296 self.options.modal = modal.into();
297 self
298 }
299
300 #[must_use]
303 pub fn interactive(mut self, interactive: impl Into<Option<bool>>) -> Self {
304 self.options.interactive = interactive.into();
305 self
306 }
307
308 #[must_use]
309 pub fn connection(mut self, connection: Option<zbus::Connection>) -> Self {
311 self.connection = connection;
312 self
313 }
314
315 pub async fn send(self) -> Result<Request<Screenshot>, Error> {
317 let proxy = if let Some(connection) = self.connection {
318 ScreenshotProxy::with_connection(connection).await?
319 } else {
320 ScreenshotProxy::new().await?
321 };
322 proxy
323 .screenshot(self.identifier.as_ref(), self.options)
324 .await
325 }
326}