use std::os::unix::prelude::AsRawFd;
use std::{fmt, str::FromStr};
use serde::{self, Deserialize, Serialize, Serializer};
use zbus::zvariant::{DeserializeDict, Fd, SerializeDict, Signature, Type};
use crate::{
desktop::{HandleToken, DESTINATION, PATH},
helpers::call_basic_response_method,
Error, WindowIdentifier,
};
#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Hash)]
pub enum SetOn {
Lockscreen,
Background,
Both,
}
impl fmt::Display for SetOn {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Lockscreen => write!(f, "Lockscreen"),
Self::Background => write!(f, "Background"),
Self::Both => write!(f, "Both"),
}
}
}
impl AsRef<str> for SetOn {
fn as_ref(&self) -> &str {
match self {
Self::Lockscreen => "Lockscreen",
Self::Background => "Background",
Self::Both => "Both",
}
}
}
impl From<SetOn> for &'static str {
fn from(s: SetOn) -> Self {
match s {
SetOn::Lockscreen => "Lockscreen",
SetOn::Background => "Background",
SetOn::Both => "Both",
}
}
}
impl FromStr for SetOn {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Lockscreen" => Ok(SetOn::Lockscreen),
"Background" => Ok(SetOn::Background),
"Both" => Ok(SetOn::Both),
_ => Err(Error::ParseError(
"Failed to parse SetOn, invalid value".to_string(),
)),
}
}
}
impl Serialize for SetOn {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string().to_lowercase())
}
}
impl Type for SetOn {
fn signature() -> Signature<'static> {
String::signature()
}
}
#[derive(SerializeDict, DeserializeDict, Clone, Type, Debug, Default)]
#[zvariant(signature = "dict")]
struct WallpaperOptions {
handle_token: HandleToken,
#[zvariant(rename = "show-preview")]
show_preview: Option<bool>,
#[zvariant(rename = "set-on")]
set_on: Option<SetOn>,
}
impl WallpaperOptions {
#[must_use]
pub fn show_preview(mut self, show_preview: bool) -> Self {
self.show_preview = Some(show_preview);
self
}
#[must_use]
pub fn set_on(mut self, set_on: SetOn) -> Self {
self.set_on = Some(set_on);
self
}
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Wallpaper")]
pub struct WallpaperProxy<'a>(zbus::Proxy<'a>);
impl<'a> WallpaperProxy<'a> {
pub async fn new(connection: &zbus::Connection) -> Result<WallpaperProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Wallpaper")?
.path(PATH)?
.destination(DESTINATION)?
.build()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::Proxy<'_> {
&self.0
}
#[doc(alias = "SetWallpaperFile")]
#[doc(alias = "xdp_portal_set_wallpaper")]
pub async fn set_wallpaper_file(
&self,
identifier: &WindowIdentifier,
file: &impl AsRawFd,
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.inner(),
&options.handle_token,
"SetWallpaperFile",
&(&identifier, Fd::from(file.as_raw_fd()), &options),
)
.await
}
#[doc(alias = "SetWallpaperURI")]
#[doc(alias = "xdp_portal_set_wallpaper")]
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.inner(),
&options.handle_token,
"SetWallpaperURI",
&(&identifier, uri, &options),
)
.await
}
}
#[doc(alias = "xdp_portal_set_wallpaper")]
pub async fn set_from_uri(
identifier: &WindowIdentifier,
uri: &str,
show_preview: bool,
set_on: SetOn,
) -> Result<(), Error> {
let connection = zbus::Connection::session().await?;
let proxy = WallpaperProxy::new(&connection).await?;
proxy
.set_wallpaper_uri(identifier, uri, show_preview, set_on)
.await?;
Ok(())
}
#[doc(alias = "xdp_portal_set_wallpaper")]
pub async fn set_from_file(
identifier: &WindowIdentifier,
file: &impl AsRawFd,
show_preview: bool,
set_on: SetOn,
) -> Result<(), Error> {
let connection = zbus::Connection::session().await?;
let proxy = WallpaperProxy::new(&connection).await?;
proxy
.set_wallpaper_file(identifier, file, show_preview, set_on)
.await?;
Ok(())
}