use super::{HandleToken, SessionProxy, DESTINATION, PATH};
use crate::{
helpers::{call_basic_response_method, call_method, call_request_method, receive_signal},
Error, WindowIdentifier,
};
use enumflags2::BitFlags;
use futures::TryFutureExt;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use zvariant::OwnedObjectPath;
use zvariant_derive::{DeserializeDict, SerializeDict, Type, TypeDict};
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
struct CreateMonitorOptions {
handle_token: HandleToken,
session_handle_token: HandleToken,
}
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
struct InhibitOptions {
handle_token: HandleToken,
reason: Option<String>,
}
impl InhibitOptions {
pub fn reason(mut self, reason: &str) -> Self {
self.reason = Some(reason.to_string());
self
}
}
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone, Copy, BitFlags, Type)]
#[repr(u32)]
pub enum InhibitFlags {
Logout = 1,
UserSwitch = 2,
Suspend = 4,
Idle = 8,
}
#[derive(Debug, SerializeDict, DeserializeDict, TypeDict)]
struct CreateMonitor {
session_handle: OwnedObjectPath,
}
#[derive(Debug, SerializeDict, DeserializeDict, TypeDict)]
#[doc(hidden)]
struct State {
#[zvariant(rename = "screensaver-active")]
screensaver_active: bool,
#[zvariant(rename = "session-state")]
session_state: SessionState,
}
#[derive(Debug, Serialize, Deserialize, Type)]
pub struct InhibitState(OwnedObjectPath, State);
impl InhibitState {
pub fn screensaver_active(&self) -> bool {
self.1.screensaver_active
}
pub fn session_state(&self) -> SessionState {
self.1.session_state
}
}
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug, Clone, Copy, Type)]
#[repr(u32)]
pub enum SessionState {
Running = 1,
QueryEnd = 2,
Ending = 3,
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Inhibit")]
pub struct InhibitProxy<'a>(zbus::azync::Proxy<'a>);
impl<'a> InhibitProxy<'a> {
pub async fn new(connection: &zbus::azync::Connection) -> Result<InhibitProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Inhibit")
.path(PATH)?
.destination(DESTINATION)
.build_async()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::azync::Proxy<'_> {
&self.0
}
#[doc(alias = "CreateMonitor")]
pub async fn create_monitor(
&self,
identifier: WindowIdentifier,
) -> Result<SessionProxy<'a>, Error> {
let options = CreateMonitorOptions::default();
let body = &(identifier, &options);
let (monitor, proxy): (CreateMonitor, SessionProxy) = futures::try_join!(
call_request_method(&self.0, &options.handle_token, "CreateMonitor", body)
.into_future(),
SessionProxy::from_unique_name(self.0.connection(), &options.session_handle_token)
.into_future(),
)?;
assert_eq!(proxy.inner().path(), &monitor.session_handle.into_inner());
Ok(proxy)
}
#[doc(alias = "Inhibit")]
pub async fn inhibit(
&self,
identifier: WindowIdentifier,
flags: BitFlags<InhibitFlags>,
reason: &str,
) -> Result<(), Error> {
let options = InhibitOptions::default().reason(reason);
call_basic_response_method(
&self.0,
&options.handle_token,
"Inhibit",
&(identifier, flags, &options),
)
.await
}
#[doc(alias = "StateChanged")]
pub async fn receive_state_changed(&self) -> Result<InhibitState, Error> {
receive_signal(&self.0, "StateChanged").await
}
#[doc(alias = "QueryEndResponse")]
pub async fn query_end_response(&self, session: &SessionProxy<'_>) -> Result<(), Error> {
call_method(&self.0, "QueryEndResponse", &(session)).await
}
}