Skip to main content

ashpd/desktop/
remote_desktop.rs

1//! # Examples
2//!
3//! ```rust,no_run
4//! use ashpd::desktop::{
5//!     PersistMode,
6//!     remote_desktop::{DeviceType, KeyState, RemoteDesktop, SelectDevicesOptions},
7//! };
8//!
9//! async fn run() -> ashpd::Result<()> {
10//!     let proxy = RemoteDesktop::new().await?;
11//!     let session = proxy.create_session(Default::default()).await?;
12//!     proxy
13//!         .select_devices(
14//!             &session,
15//!             SelectDevicesOptions::default()
16//!                 .set_devices(DeviceType::Keyboard | DeviceType::Pointer),
17//!         )
18//!         .await?;
19//!
20//!     let response = proxy
21//!         .start(&session, None, Default::default())
22//!         .await?
23//!         .response()?;
24//!     println!("{:#?}", response.devices());
25//!
26//!     // 13 for Enter key code
27//!     proxy
28//!         .notify_keyboard_keycode(&session, 13, KeyState::Pressed, Default::default())
29//!         .await?;
30//!
31//!     Ok(())
32//! }
33//! ```
34//!
35//! You can also use the Remote Desktop portal with the ScreenCast one. In order
36//! to do so, you need to call
37//! [`Screencast::select_sources()`][select_sources]
38//! on the session created with
39//! [`RemoteDesktop::create_session()`][create_session]
40//!
41//! ```rust,no_run
42//! use ashpd::desktop::{
43//!     PersistMode,
44//!     remote_desktop::{DeviceType, KeyState, RemoteDesktop, SelectDevicesOptions},
45//!     screencast::{CursorMode, Screencast, SelectSourcesOptions, SourceType},
46//! };
47//!
48//! async fn run() -> ashpd::Result<()> {
49//!     let remote_desktop = RemoteDesktop::new().await?;
50//!     let screencast = Screencast::new().await?;
51//!     let session = remote_desktop.create_session(Default::default()).await?;
52//!
53//!     remote_desktop
54//!         .select_devices(
55//!             &session,
56//!             SelectDevicesOptions::default()
57//!                 .set_devices(DeviceType::Keyboard | DeviceType::Pointer),
58//!         )
59//!         .await?;
60//!     screencast
61//!         .select_sources(
62//!             &session,
63//!             SelectSourcesOptions::default()
64//!                 .set_cursor_mode(CursorMode::Metadata)
65//!                 .set_sources(SourceType::Monitor | SourceType::Window)
66//!                 .set_multiple(true)
67//!                 .set_persist_mode(PersistMode::DoNot),
68//!         )
69//!         .await?;
70//!
71//!     let response = remote_desktop
72//!         .start(&session, None, Default::default())
73//!         .await?
74//!         .response()?;
75//!     println!("{:#?}", response.devices());
76//!     println!("{:#?}", response.streams());
77//!
78//!     // 13 for Enter key code
79//!     remote_desktop
80//!         .notify_keyboard_keycode(&session, 13, KeyState::Pressed, Default::default())
81//!         .await?;
82//!
83//!     Ok(())
84//! }
85//! ```
86//! [select_sources]: crate::desktop::screencast::Screencast::select_sources
87//! [create_session]: crate::desktop::remote_desktop::RemoteDesktop::create_session
88
89use std::os::fd::OwnedFd;
90
91use enumflags2::{BitFlags, bitflags};
92use serde::{Deserialize, Serialize};
93use serde_repr::{Deserialize_repr, Serialize_repr};
94use zbus::zvariant::{
95    self, Optional, Type,
96    as_value::{self, optional},
97};
98
99use super::{
100    HandleToken, PersistMode, Request, Session, screencast::Stream, session::SessionPortal,
101};
102use crate::{
103    Error, WindowIdentifier,
104    desktop::session::{CreateSessionOptions, CreateSessionResponse},
105    proxy::Proxy,
106};
107
108#[cfg_attr(feature = "glib", derive(glib::Enum))]
109#[cfg_attr(feature = "glib", enum_type(name = "AshpdKeyState"))]
110#[derive(Serialize_repr, Deserialize_repr, Copy, Clone, PartialEq, Eq, Debug, Type)]
111#[doc(alias = "XdpKeyState")]
112/// The keyboard key state.
113#[repr(u32)]
114pub enum KeyState {
115    #[doc(alias = "XDP_KEY_PRESSED")]
116    /// The key is pressed.
117    Pressed = 1,
118    #[doc(alias = "XDP_KEY_RELEASED")]
119    /// The key is released..
120    Released = 0,
121}
122
123#[bitflags]
124#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Debug, Clone, Copy, Type)]
125#[repr(u32)]
126#[doc(alias = "XdpDeviceType")]
127/// A bit flag for the available devices.
128pub enum DeviceType {
129    #[doc(alias = "XDP_DEVICE_KEYBOARD")]
130    /// A keyboard.
131    Keyboard,
132    #[doc(alias = "XDP_DEVICE_POINTER")]
133    /// A mouse pointer.
134    Pointer,
135    #[doc(alias = "XDP_DEVICE_TOUCHSCREEN")]
136    /// A touchscreen
137    Touchscreen,
138}
139
140#[cfg_attr(feature = "glib", derive(glib::Enum))]
141#[cfg_attr(feature = "glib", enum_type(name = "AshpdAxis"))]
142#[derive(Serialize_repr, Deserialize_repr, PartialEq, Eq, Debug, Clone, Copy, Type)]
143#[doc(alias = "XdpDiscreteAxis")]
144#[repr(u32)]
145/// The available axis.
146pub enum Axis {
147    #[doc(alias = "XDP_AXIS_VERTICAL_SCROLL")]
148    /// Vertical axis.
149    Vertical = 0,
150    #[doc(alias = "XDP_AXIS_HORIZONTAL_SCROLL")]
151    /// Horizontal axis.
152    Horizontal = 1,
153}
154
155#[derive(Serialize, Type, Debug, Default)]
156#[zvariant(signature = "dict")]
157/// Specified options for a [`RemoteDesktop::notify_keyboard_keycode`] request.
158pub struct NotifyKeyboardKeycodeOptions {}
159
160#[derive(Serialize, Type, Debug, Default)]
161#[zvariant(signature = "dict")]
162/// Specified options for a [`RemoteDesktop::notify_keyboard_keysym`] request.
163pub struct NotifyKeyboardKeysymOptions {}
164
165#[derive(Serialize, Type, Debug, Default)]
166#[zvariant(signature = "dict")]
167/// Specified options for a [`RemoteDesktop::notify_pointer_axis_discrete`]
168/// request.
169pub struct NotifyPointerAxisDiscreteOptions {}
170
171#[derive(Serialize, Type, Debug, Default)]
172#[zvariant(signature = "dict")]
173/// Specified options for a [`RemoteDesktop::notify_touch_up`] request.
174pub struct NotifyTouchUpOptions {}
175
176#[derive(Serialize, Type, Debug, Default)]
177#[zvariant(signature = "dict")]
178/// Specified options for a [`RemoteDesktop::notify_touch_down`] request.
179pub struct NotifyTouchDownOptions {}
180
181#[derive(Serialize, Type, Debug, Default)]
182#[zvariant(signature = "dict")]
183/// Specified options for a [`RemoteDesktop::notify_touch_motion`] request.
184pub struct NotifyTouchMotionOptions {}
185
186#[derive(Serialize, Type, Debug, Default)]
187#[zvariant(signature = "dict")]
188/// Specified options for a [`RemoteDesktop::notify_pointer_button`] request.
189pub struct NotifyPointerButtonOptions {}
190
191#[derive(Serialize, Type, Debug, Default)]
192#[zvariant(signature = "dict")]
193/// Specified options for a [`RemoteDesktop::notify_pointer_motion`] request.
194pub struct NotifyPointerMotionOptions {}
195
196#[derive(Serialize, Type, Debug, Default)]
197#[zvariant(signature = "dict")]
198/// Specified options for a [`RemoteDesktop::notify_pointer_motion_absolute`]
199/// request.
200pub struct NotifyPointerMotionAbsoluteOptions {}
201
202#[derive(Serialize, Type, Debug, Default)]
203#[zvariant(signature = "dict")]
204/// Specified options for a [`RemoteDesktop::notify_pointer_axis`] request.
205pub struct NotifyPointerAxisOptions {
206    #[serde(with = "as_value")]
207    finish: bool,
208}
209
210impl NotifyPointerAxisOptions {
211    /// Sets whether the axis event is the last one in a sequence.
212    pub fn set_finish(mut self, finish: bool) -> Self {
213        self.finish = finish;
214        self
215    }
216}
217
218#[derive(Serialize, Type, Debug, Default)]
219/// Specified options for a [`RemoteDesktop::select_devices`] request.
220#[zvariant(signature = "dict")]
221pub struct SelectDevicesOptions {
222    #[serde(with = "as_value")]
223    handle_token: HandleToken,
224    #[serde(with = "optional", skip_serializing_if = "Option::is_none")]
225    types: Option<BitFlags<DeviceType>>,
226    #[serde(with = "optional", skip_serializing_if = "Option::is_none")]
227    restore_token: Option<String>,
228    #[serde(with = "optional", skip_serializing_if = "Option::is_none")]
229    persist_mode: Option<PersistMode>,
230}
231
232impl SelectDevicesOptions {
233    /// Sets the device types to request remote controlling of.
234    pub fn set_devices(mut self, types: impl Into<Option<BitFlags<DeviceType>>>) -> Self {
235        self.types = types.into();
236        self
237    }
238
239    /// Sets the persist mode.
240    pub fn set_persist_mode(mut self, persist_mode: impl Into<Option<PersistMode>>) -> Self {
241        self.persist_mode = persist_mode.into();
242        self
243    }
244
245    /// Sets the restore token.
246    pub fn set_restore_token<'a>(mut self, token: impl Into<Option<&'a str>>) -> Self {
247        self.restore_token = token.into().map(ToOwned::to_owned);
248        self
249    }
250}
251
252#[derive(Serialize, Type, Debug, Default)]
253/// Specified options for a [`RemoteDesktop::start`] request.
254#[zvariant(signature = "dict")]
255pub struct StartOptions {
256    #[serde(with = "as_value")]
257    handle_token: HandleToken,
258}
259
260#[derive(Deserialize, Type, Debug, Default)]
261/// A response to a [`RemoteDesktop::select_devices`] request.
262#[zvariant(signature = "dict")]
263pub struct SelectedDevices {
264    #[serde(default, with = "as_value")]
265    devices: BitFlags<DeviceType>,
266    #[serde(default, with = "as_value")]
267    streams: Vec<Stream>,
268    #[serde(default, with = "optional")]
269    restore_token: Option<String>,
270    #[serde(default, with = "optional")]
271    clipboard_enabled: Option<bool>,
272}
273
274impl SelectedDevices {
275    /// The selected devices.
276    pub fn devices(&self) -> BitFlags<DeviceType> {
277        self.devices
278    }
279
280    /// The selected streams if a ScreenCast portal is used on the same session
281    pub fn streams(&self) -> &[Stream] {
282        &self.streams
283    }
284
285    /// The session restore token.
286    pub fn restore_token(&self) -> Option<&str> {
287        self.restore_token.as_deref()
288    }
289
290    /// Whether the clipboard was enabled.
291    pub fn is_clipboard_enabled(&self) -> bool {
292        self.clipboard_enabled.unwrap_or(false)
293    }
294}
295
296#[derive(Default, Debug, Serialize, Type)]
297#[zvariant(signature = "dict")]
298/// Specified options for a [`RemoteDesktop::connect_to_eis`] request.
299pub struct ConnectToEISOptions {}
300
301/// The interface lets sandboxed applications create remote desktop sessions.
302///
303/// Wrapper of the DBus interface: [`org.freedesktop.portal.RemoteDesktop`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html).
304#[derive(Debug)]
305#[doc(alias = "org.freedesktop.portal.RemoteDesktop")]
306pub struct RemoteDesktop(Proxy<'static>);
307
308impl RemoteDesktop {
309    /// Create a new instance of [`RemoteDesktop`].
310    pub async fn new() -> Result<Self, Error> {
311        let proxy = Proxy::new_desktop("org.freedesktop.portal.RemoteDesktop").await?;
312        Ok(Self(proxy))
313    }
314
315    /// Create a new instance of [`RemoteDesktop`].
316    pub async fn with_connection(connection: zbus::Connection) -> Result<Self, Error> {
317        let proxy =
318            Proxy::new_desktop_with_connection(connection, "org.freedesktop.portal.RemoteDesktop")
319                .await?;
320        Ok(Self(proxy))
321    }
322
323    /// Returns the version of the portal interface.
324    pub fn version(&self) -> u32 {
325        self.0.version()
326    }
327
328    /// Create a remote desktop session.
329    /// A remote desktop session is used to allow remote controlling a desktop
330    /// session. It can also be used together with a screen cast session.
331    ///
332    /// # Specifications
333    ///
334    /// See also [`CreateSession`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-createsession).
335    #[doc(alias = "CreateSession")]
336    #[doc(alias = "xdp_portal_create_remote_desktop_session")]
337    pub async fn create_session(
338        &self,
339        options: CreateSessionOptions,
340    ) -> Result<Session<Self>, Error> {
341        let (request, proxy) = futures_util::try_join!(
342            self.0.request::<CreateSessionResponse>(
343                &options.handle_token,
344                "CreateSession",
345                &options
346            ),
347            Session::from_unique_name(self.0.connection().clone(), &options.session_handle_token)
348        )?;
349        assert_eq!(proxy.path(), &request.response()?.session_handle.as_ref());
350        Ok(proxy)
351    }
352
353    /// Select input devices to remote control.
354    ///
355    /// # Arguments
356    ///
357    /// * `session` - A [`Session`], created with
358    ///   [`create_session()`][`RemoteDesktop::create_session`].
359    /// * `types` - The device types to request remote controlling of.
360    ///
361    /// # Specifications
362    ///
363    /// See also [`SelectDevices`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-selectdevices).
364    #[doc(alias = "SelectDevices")]
365    pub async fn select_devices(
366        &self,
367        session: &Session<Self>,
368        options: SelectDevicesOptions,
369    ) -> Result<Request<()>, Error> {
370        self.0
371            .empty_request(&options.handle_token, "SelectDevices", &(session, &options))
372            .await
373    }
374
375    ///  Start the remote desktop session.
376    ///
377    /// This will typically result in the portal presenting a dialog letting
378    /// the user select what to share, including devices and optionally screen
379    /// content if screen cast sources was selected.
380    ///
381    /// # Arguments
382    ///
383    /// * `session` - A [`Session`], created with
384    ///   [`create_session()`][`RemoteDesktop::create_session`].
385    /// * `identifier` - The application window identifier.
386    ///
387    /// # Specifications
388    ///
389    /// See also [`Start`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-start).
390    #[doc(alias = "Start")]
391    pub async fn start(
392        &self,
393        session: &Session<Self>,
394        identifier: Option<&WindowIdentifier>,
395        options: StartOptions,
396    ) -> Result<Request<SelectedDevices>, Error> {
397        let identifier = Optional::from(identifier);
398        self.0
399            .request(
400                &options.handle_token,
401                "Start",
402                &(session, identifier, &options),
403            )
404            .await
405    }
406
407    /// Notify keyboard code.
408    ///
409    /// **Note** only works if [`DeviceType::Keyboard`] access was provided
410    /// after starting the session.
411    ///
412    /// # Arguments
413    ///
414    /// * `session` - A [`Session`], created with
415    ///   [`create_session()`][`RemoteDesktop::create_session`].
416    /// * `keycode` - Keyboard code that was pressed or released.
417    /// * `state` - The new state of the keyboard code.
418    ///
419    /// # Specifications
420    ///
421    /// See also [`NotifyKeyboardKeycode`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifykeyboardkeycode).
422    #[doc(alias = "NotifyKeyboardKeycode")]
423    pub async fn notify_keyboard_keycode(
424        &self,
425        session: &Session<Self>,
426        keycode: i32,
427        state: KeyState,
428        options: NotifyKeyboardKeycodeOptions,
429    ) -> Result<(), Error> {
430        self.0
431            .call("NotifyKeyboardKeycode", &(session, options, keycode, state))
432            .await
433    }
434
435    /// Notify keyboard symbol.
436    ///
437    /// **Note** only works if [`DeviceType::Keyboard`] access was provided
438    /// after starting the session.
439    ///
440    /// # Arguments
441    ///
442    /// * `session` - A [`Session`], created with
443    ///   [`create_session()`][`RemoteDesktop::create_session`].
444    /// * `keysym` - Keyboard symbol that was pressed or released.
445    /// * `state` - The new state of the keyboard code.
446    ///
447    /// # Specifications
448    ///
449    /// See also [`NotifyKeyboardKeysym`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifykeyboardkeysym).
450    #[doc(alias = "NotifyKeyboardKeysym")]
451    pub async fn notify_keyboard_keysym(
452        &self,
453        session: &Session<Self>,
454        keysym: i32,
455        state: KeyState,
456        options: NotifyKeyboardKeysymOptions,
457    ) -> Result<(), Error> {
458        self.0
459            .call("NotifyKeyboardKeysym", &(session, options, keysym, state))
460            .await
461    }
462
463    /// Notify about a new touch up event.
464    ///
465    /// **Note** only works if [`DeviceType::Touchscreen`] access was provided
466    /// after starting the session.
467    ///
468    /// # Arguments
469    ///
470    /// * `session` - A [`Session`], created with
471    ///   [`create_session()`][`RemoteDesktop::create_session`].
472    /// * `slot` - Touch slot where touch point appeared.
473    ///
474    /// # Specifications
475    ///
476    /// See also [`NotifyTouchUp`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifytouchup).
477    #[doc(alias = "NotifyTouchUp")]
478    pub async fn notify_touch_up(
479        &self,
480        session: &Session<Self>,
481        slot: u32,
482        options: NotifyTouchUpOptions,
483    ) -> Result<(), Error> {
484        self.0
485            .call("NotifyTouchUp", &(session, options, slot))
486            .await
487    }
488
489    /// Notify about a new touch down event.
490    /// The (x, y) position represents the new touch point position in the
491    /// streams logical coordinate space.
492    ///
493    /// **Note** only works if [`DeviceType::Touchscreen`] access was provided
494    /// after starting the session.
495    ///
496    /// # Arguments
497    ///
498    /// * `session` - A [`Session`], created with
499    ///   [`create_session()`][`RemoteDesktop::create_session`].
500    /// * `stream` - The PipeWire stream node the coordinate is relative to.
501    /// * `slot` - Touch slot where touch point appeared.
502    /// * `x` - Touch down x coordinate.
503    /// * `y` - Touch down y coordinate.
504    ///
505    /// # Specifications
506    ///
507    /// See also [`NotifyTouchDown`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifytouchdown).
508    #[doc(alias = "NotifyTouchDown")]
509    pub async fn notify_touch_down(
510        &self,
511        session: &Session<Self>,
512        stream: u32,
513        slot: u32,
514        x: f64,
515        y: f64,
516        options: NotifyTouchDownOptions,
517    ) -> Result<(), Error> {
518        self.0
519            .call("NotifyTouchDown", &(session, options, stream, slot, x, y))
520            .await
521    }
522
523    /// Notify about a new touch motion event.
524    /// The (x, y) position represents where the touch point position in the
525    /// streams logical coordinate space moved.
526    ///
527    /// **Note** only works if [`DeviceType::Touchscreen`] access was provided
528    /// after starting the session.
529    ///
530    /// # Arguments
531    ///
532    /// * `session` - A [`Session`], created with
533    ///   [`create_session()`][`RemoteDesktop::create_session`].
534    /// * `stream` - The PipeWire stream node the coordinate is relative to.
535    /// * `slot` - Touch slot where touch point appeared.
536    /// * `x` - Touch motion x coordinate.
537    /// * `y` - Touch motion y coordinate.
538    ///
539    /// # Specifications
540    ///
541    /// See also [`NotifyTouchMotion`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifytouchmotion).
542    #[doc(alias = "NotifyTouchMotion")]
543    pub async fn notify_touch_motion(
544        &self,
545        session: &Session<Self>,
546        stream: u32,
547        slot: u32,
548        x: f64,
549        y: f64,
550        options: NotifyTouchMotionOptions,
551    ) -> Result<(), Error> {
552        self.0
553            .call("NotifyTouchMotion", &(session, options, stream, slot, x, y))
554            .await
555    }
556
557    /// Notify about a new absolute pointer motion event.
558    /// The (x, y) position represents the new pointer position in the streams
559    /// logical coordinate space.
560    ///
561    /// # Arguments
562    ///
563    /// * `session` - A [`Session`], created with
564    ///   [`create_session()`][`RemoteDesktop::create_session`].
565    /// * `stream` - The PipeWire stream node the coordinate is relative to.
566    /// * `x` - Pointer motion x coordinate.
567    /// * `y` - Pointer motion y coordinate.
568    ///
569    /// # Specifications
570    ///
571    /// See also [`NotifyPointerMotionAbsolute`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifypointermotionabsolute).
572    #[doc(alias = "NotifyPointerMotionAbsolute")]
573    pub async fn notify_pointer_motion_absolute(
574        &self,
575        session: &Session<Self>,
576        stream: u32,
577        x: f64,
578        y: f64,
579        options: NotifyPointerMotionAbsoluteOptions,
580    ) -> Result<(), Error> {
581        self.0
582            .call(
583                "NotifyPointerMotionAbsolute",
584                &(session, options, stream, x, y),
585            )
586            .await
587    }
588
589    /// Notify about a new relative pointer motion event.
590    /// The (dx, dy) vector represents the new pointer position in the streams
591    /// logical coordinate space.
592    ///
593    /// # Arguments
594    ///
595    /// * `session` - A [`Session`], created with
596    ///   [`create_session()`][`RemoteDesktop::create_session`].
597    /// * `dx` - Relative movement on the x axis.
598    /// * `dy` - Relative movement on the y axis.
599    ///
600    /// # Specifications
601    ///
602    /// See also [`NotifyPointerMotion`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifypointermotion).
603    #[doc(alias = "NotifyPointerMotion")]
604    pub async fn notify_pointer_motion(
605        &self,
606        session: &Session<Self>,
607        dx: f64,
608        dy: f64,
609        options: NotifyPointerMotionOptions,
610    ) -> Result<(), Error> {
611        self.0
612            .call("NotifyPointerMotion", &(session, options, dx, dy))
613            .await
614    }
615
616    /// Notify pointer button.
617    /// The pointer button is encoded according to Linux Evdev button codes.
618    ///
619    ///
620    /// **Note** only works if [`DeviceType::Pointer`] access was provided after
621    /// starting the session.
622    ///
623    /// # Arguments
624    ///
625    /// * `session` - A [`Session`], created with
626    ///   [`create_session()`][`RemoteDesktop::create_session`].
627    /// * `button` - The pointer button was pressed or released.
628    /// * `state` - The new state of the keyboard code.
629    ///
630    /// # Specifications
631    ///
632    /// See also [`NotifyPointerButton`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifypointerbutton).
633    #[doc(alias = "NotifyPointerButton")]
634    pub async fn notify_pointer_button(
635        &self,
636        session: &Session<Self>,
637        button: i32,
638        state: KeyState,
639        options: NotifyPointerButtonOptions,
640    ) -> Result<(), Error> {
641        self.0
642            .call("NotifyPointerButton", &(session, options, button, state))
643            .await
644    }
645
646    /// Notify pointer axis discrete.
647    ///
648    /// **Note** only works if [`DeviceType::Pointer`] access was provided after
649    /// starting the session.
650    ///
651    /// # Arguments
652    ///
653    /// * `session` - A [`Session`], created with
654    ///   [`create_session()`][`RemoteDesktop::create_session`].
655    /// * `axis` - The axis that was scrolled.
656    ///
657    /// # Specifications
658    ///
659    /// See also [`NotifyPointerAxisDiscrete`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifypointeraxisdiscrete).
660    #[doc(alias = "NotifyPointerAxisDiscrete")]
661    pub async fn notify_pointer_axis_discrete(
662        &self,
663        session: &Session<Self>,
664        axis: Axis,
665        steps: i32,
666        options: NotifyPointerAxisDiscreteOptions,
667    ) -> Result<(), Error> {
668        self.0
669            .call(
670                "NotifyPointerAxisDiscrete",
671                &(session, options, axis, steps),
672            )
673            .await
674    }
675
676    /// Notify pointer axis.
677    /// The axis movement from a "smooth scroll" device, such as a touchpad.
678    /// When applicable, the size of the motion delta should be equivalent to
679    /// the motion vector of a pointer motion done using the same advice.
680    ///
681    ///
682    /// **Note** only works if [`DeviceType::Pointer`] access was provided after
683    /// starting the session.
684    ///
685    /// # Arguments
686    ///
687    /// * `session` - A [`Session`], created with
688    ///   [`create_session()`][`RemoteDesktop::create_session`].
689    /// * `dx` - Relative axis movement on the x axis.
690    /// * `dy` - Relative axis movement on the y axis.
691    /// * `finish` - Whether it is the last axis event.
692    ///
693    /// # Specifications
694    ///
695    /// See also [`NotifyPointerAxis`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-notifypointeraxis).
696    #[doc(alias = "NotifyPointerAxis")]
697    pub async fn notify_pointer_axis(
698        &self,
699        session: &Session<Self>,
700        dx: f64,
701        dy: f64,
702        options: NotifyPointerAxisOptions,
703    ) -> Result<(), Error> {
704        self.0
705            .call("NotifyPointerAxis", &(session, options, dx, dy))
706            .await
707    }
708
709    /// Connect to EIS.
710    ///
711    /// **Note** only succeeds if called after [`RemoteDesktop::start`].
712    ///
713    /// Requires RemoteDesktop version 2.
714    ///
715    /// # Arguments
716    ///
717    /// * `session` - A [`Session`], created with
718    ///   [`create_session()`][`RemoteDesktop::create_session`].
719    ///
720    /// # Required version
721    ///
722    /// The method requires the 2nd version implementation of the portal and
723    /// would fail with [`Error::RequiresVersion`] otherwise.
724    ///
725    /// # Specifications
726    ///
727    /// See also [`ConnectToEIS`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-connecttoeis).
728    #[doc(alias = "ConnectToEIS")]
729    pub async fn connect_to_eis(
730        &self,
731        session: &Session<Self>,
732        options: ConnectToEISOptions,
733    ) -> Result<OwnedFd, Error> {
734        let fd = self
735            .0
736            .call_versioned::<zvariant::OwnedFd>("ConnectToEIS", &(session, options), 2)
737            .await?;
738        Ok(fd.into())
739    }
740
741    /// Available source types.
742    ///
743    /// # Specifications
744    ///
745    /// See also [`AvailableDeviceTypes`](https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.RemoteDesktop.html#org-freedesktop-portal-remotedesktop-availabledevicetypes).
746    #[doc(alias = "AvailableDeviceTypes")]
747    pub async fn available_device_types(&self) -> Result<BitFlags<DeviceType>, Error> {
748        self.0.property("AvailableDeviceTypes").await
749    }
750}
751
752impl std::ops::Deref for RemoteDesktop {
753    type Target = zbus::Proxy<'static>;
754
755    fn deref(&self) -> &Self::Target {
756        &self.0
757    }
758}
759
760impl crate::Sealed for RemoteDesktop {}
761impl SessionPortal for RemoteDesktop {}
762#[cfg(feature = "clipboard")]
763impl crate::desktop::clipboard::IsClipboardSession for RemoteDesktop {}
764#[cfg(feature = "screencast")]
765impl crate::desktop::screencast::IsScreencastSession for RemoteDesktop {}