ashpd 0.2.0-alpha-2

XDG portals wrapper in Rust using zbus
Documentation
//! # Examples
//!
//! ## Sets a wallpaper from a file:
//!
//!```rust,no_run
//! use ashpd::desktop::wallpaper::{self, SetOn};
//! use std::fs::File;
//!
//! async fn run() -> Result<(), ashpd::Error> {
//!     let file = File::open("/home/bilelmoussaoui/adwaita-day.jpg").unwrap();
//!     wallpaper::set_from_file(Default::default(), &file, true, SetOn::Both).await?;
//!     Ok(())
//! }
//! ```
//!
//! Or by using the Proxy directly
//!
//! ```rust,no_run
//! use ashpd::desktop::wallpaper::{SetOn, WallpaperProxy};
//! use std::fs::File;
//!
//! async fn run() -> Result<(), ashpd::Error> {
//!     let wallpaper = File::open("/home/bilelmoussaoui/adwaita-day.jpg").unwrap();
//!
//!     let connection = zbus::azync::Connection::new_session().await?;
//!     let proxy = WallpaperProxy::new(&connection).await?;
//!     proxy
//!         .set_wallpaper_file(Default::default(), &wallpaper, true, SetOn::Both)
//!         .await?;
//!     Ok(())
//! }
//! ```
//!
//! ## Sets a wallpaper from a URI:
//!
//!```rust,no_run
//! use ashpd::desktop::wallpaper::{self, SetOn};
//!
//! async fn run() -> Result<(), ashpd::Error> {
//!     let uri = "file:///home/bilelmoussaoui/Downloads/adwaita-night.jpg";
//!     wallpaper::set_from_uri(Default::default(), &uri, true, SetOn::Both).await?;
//!     Ok(())
//! }
//! ```
//!
//! Or by using the Proxy directly
//!
//! ```rust,no_run
//! use ashpd::desktop::wallpaper::{SetOn, WallpaperProxy};
//!
//! async fn run() -> Result<(), ashpd::Error> {
//!     let connection = zbus::azync::Connection::new_session().await?;
//!     let proxy = WallpaperProxy::new(&connection).await?;
//!     proxy
//!         .set_wallpaper_uri(
//!             Default::default(),
//!             "file:///home/bilelmoussaoui/Downloads/adwaita-night.jpg",
//!             true,
//!             SetOn::Both,
//!         )
//!         .await?;
//!     Ok(())
//! }
//! ```

use crate::{
    desktop::{HandleToken, DESTINATION, PATH},
    helpers::call_basic_response_method,
    Error, WindowIdentifier,
};
use serde::{self, Deserialize, Serialize, Serializer};
use std::os::unix::prelude::AsRawFd;
use strum_macros::{AsRefStr, EnumString, IntoStaticStr, ToString};
use zvariant::{Fd, Signature, Type};
use zvariant_derive::{DeserializeDict, SerializeDict, TypeDict};

#[derive(
    Deserialize, Debug, Clone, Copy, PartialEq, Hash, AsRefStr, EnumString, IntoStaticStr, ToString,
)]
#[serde(rename = "lowercase")]
/// Where to set the wallpaper on.
pub enum SetOn {
    /// Set the wallpaper only on the lock-screen.
    Lockscreen,
    /// Set the wallpaper only on the background.
    Background,
    /// Set the wallpaper on both lock-screen and background.
    Both,
}

impl Type for SetOn {
    fn signature() -> Signature<'static> {
        String::signature()
    }
}

impl Serialize for SetOn {
    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        String::serialize(&self.to_string(), serializer)
    }
}

#[derive(SerializeDict, DeserializeDict, Clone, TypeDict, Debug, Default)]
/// Specified options for a [`WallpaperProxy::set_wallpaper_file`] or a [`WallpaperProxy::set_wallpaper_uri`] request.
struct WallpaperOptions {
    /// A string that will be used as the last element of the handle.
    handle_token: HandleToken,
    /// Whether to show a preview of the picture
    #[zvariant(rename = "show-preview")]
    show_preview: Option<bool>,
    /// Where to set the wallpaper on
    #[zvariant(rename = "set-on")]
    set_on: Option<SetOn>,
}

impl WallpaperOptions {
    /// Whether to show a preview of the picture.
    /// **Note** the portal may decide to show a preview even if this option is not set.
    pub fn show_preview(mut self, show_preview: bool) -> Self {
        self.show_preview = Some(show_preview);
        self
    }

    /// Sets where to set the wallpaper on.
    pub fn set_on(mut self, set_on: SetOn) -> Self {
        self.set_on = Some(set_on);
        self
    }
}
/// The interface lets sandboxed applications set the user's desktop background
/// picture.
///
/// Wrapper of the DBus interface: [`org.freedesktop.portal.Wallpaper`](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Wallpaper).
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Wallpaper")]
pub struct WallpaperProxy<'a>(zbus::azync::Proxy<'a>);

impl<'a> WallpaperProxy<'a> {
    /// Create a new instance of [`WallpaperProxy`].
    pub async fn new(connection: &zbus::azync::Connection) -> Result<WallpaperProxy<'a>, Error> {
        let proxy = zbus::ProxyBuilder::new_bare(connection)
            .interface("org.freedesktop.portal.Wallpaper")
            .path(PATH)?
            .destination(DESTINATION)
            .build_async()
            .await?;
        Ok(Self(proxy))
    }

    /// Get a reference to the underlying Proxy.
    pub fn inner(&self) -> &zbus::azync::Proxy<'_> {
        &self.0
    }

    /// Sets the lock-screen, background or both wallpaper's from a file
    /// descriptor.
    ///
    /// # Arguments
    ///
    /// * `identifier` - Identifier for the application window.
    /// * `file` - The wallpaper file descriptor.
    /// * `show_preview` - Whether to show a preview of the picture.
    /// * `set_on` - Where to set the wallpaper on.
    ///
    /// # Specifications
    ///
    /// See also [`SetWallpaperFile`](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-method-org-freedesktop-portal-Wallpaper.SetWallpaperFile).
    #[doc(alias = "SetWallpaperFile")]
    pub async fn set_wallpaper_file<F>(
        &self,
        identifier: WindowIdentifier,
        file: &F,
        show_preview: bool,
        set_on: SetOn,
    ) -> Result<(), Error>
    where
        F: AsRawFd,
    {
        let options = WallpaperOptions::default()
            .show_preview(show_preview)
            .set_on(set_on);
        call_basic_response_method(
            &self.0,
            &options.handle_token,
            "SetWallpaperFile",
            &(identifier, Fd::from(file.as_raw_fd()), &options),
        )
        .await
    }

    /// Sets the lock-screen, background or both wallpaper's from an URI.
    ///
    /// # Arguments
    ///
    /// * `identifier` - Identifier for the application window.
    /// * `uri` - The wallpaper URI.
    /// * `show_preview` - Whether to show a preview of the picture.
    /// * `set_on` - Where to set the wallpaper on.
    ///
    /// # Specifications
    ///
    /// See also [`SetWallpaperURI`](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-method-org-freedesktop-portal-Wallpaper.SetWallpaperURI).
    #[doc(alias = "SetWallpaperURI")]
    pub async fn set_wallpaper_uri(
        &self,
        identifier: WindowIdentifier,
        uri: &str,
        show_preview: bool,
        set_on: SetOn,
    ) -> Result<(), Error> {
        let options = WallpaperOptions::default()
            .show_preview(show_preview)
            .set_on(set_on);
        call_basic_response_method(
            &self.0,
            &options.handle_token,
            "SetWallpaperURI",
            &(identifier, uri, &options),
        )
        .await
    }
}

#[doc(alias = "xdp_portal_set_wallpaper")]
/// A handy wrapper around [`WallpaperProxy::set_wallpaper_uri`].
pub async fn set_from_uri(
    window: WindowIdentifier,
    uri: &str,
    show_preview: bool,
    set_on: SetOn,
) -> Result<(), Error> {
    let connection = zbus::azync::Connection::new_session().await?;
    let proxy = WallpaperProxy::new(&connection).await?;
    proxy
        .set_wallpaper_uri(window, uri, show_preview, set_on)
        .await?;
    Ok(())
}

#[doc(alias = "xdp_portal_set_wallpaper")]
/// A handy wrapper around [`WallpaperProxy::set_wallpaper_file`].
pub async fn set_from_file<F: AsRawFd>(
    window: WindowIdentifier,
    file: &F,
    show_preview: bool,
    set_on: SetOn,
) -> Result<(), Error> {
    let connection = zbus::azync::Connection::new_session().await?;
    let proxy = WallpaperProxy::new(&connection).await?;
    proxy
        .set_wallpaper_file(window, file, show_preview, set_on)
        .await?;
    Ok(())
}