1use zbus::{blocking::Connection, proxy};
11
12use crate::Options;
13
14pub type Error = zbus::Error;
15
16#[proxy(
17 interface = "org.freedesktop.login1.Manager",
18 default_service = "org.freedesktop.login1",
19 default_path = "/org/freedesktop/login1"
20)]
21trait Manager {
22 fn inhibit(
24 &self,
25 what: &str,
26 who: &str,
27 why: &str,
28 mode: &str,
29 ) -> zbus::Result<zbus::zvariant::OwnedFd>;
30}
31
32#[proxy(assume_defaults = true)]
33trait ScreenSaver {
34 fn inhibit(&self, application_name: &str, reason_for_inhibit: &str) -> zbus::Result<u32>;
36
37 fn un_inhibit(&self, cookie: u32) -> zbus::Result<()>;
39}
40
41pub struct KeepActive {
42 options: Options,
43
44 session_conn: Option<Connection>,
45 screensaver_proxy: Option<ScreenSaverProxyBlocking<'static>>,
46 cookie: Option<u32>,
47
48 system_conn: Option<Connection>,
49 manager_proxy: Option<ManagerProxyBlocking<'static>>,
50 idle_fd: Option<zbus::zvariant::OwnedFd>,
51 sleep_fd: Option<zbus::zvariant::OwnedFd>,
52}
53
54impl KeepActive {
55 pub fn new(options: Options) -> Result<Self, zbus::Error> {
56 let mut awake = Self {
57 options,
58
59 session_conn: None,
60 screensaver_proxy: None,
61 cookie: None,
62
63 system_conn: None,
64 manager_proxy: None,
65 idle_fd: None,
66 sleep_fd: None,
67 };
68 awake.set()?;
69 Ok(awake)
70 }
71
72 fn set(&mut self) -> Result<(), zbus::Error> {
73 self.cookie = if self.options.display {
74 self.session_conn = Some(Connection::session()?);
75 self.screensaver_proxy = Some(ScreenSaverProxyBlocking::new(
76 self.session_conn.as_ref().unwrap(),
77 )?);
78 Some(
79 self.screensaver_proxy
80 .as_ref()
81 .unwrap()
82 .inhibit(&self.options.app_reverse_domain, &self.options.reason)?,
83 )
84 } else {
85 None
86 };
87
88 if self.options.idle || self.options.sleep {
89 self.system_conn = Some(Connection::system()?);
90 self.manager_proxy = Some(ManagerProxyBlocking::new(
91 self.system_conn.as_ref().unwrap(),
92 )?);
93 }
94
95 self.idle_fd = if self.options.idle {
96 Some(self.manager_proxy.as_ref().unwrap().inhibit(
97 "idle",
98 &self.options.app_name,
99 &self.options.reason,
100 "block",
101 )?)
102 } else {
103 None
104 };
105
106 self.sleep_fd = if self.options.sleep {
107 Some(self.manager_proxy.as_ref().unwrap().inhibit(
108 "sleep",
109 &self.options.app_name,
110 &self.options.reason,
111 "block",
112 )?)
113 } else {
114 None
115 };
116
117 Ok(())
118 }
119}
120
121impl Drop for KeepActive {
122 fn drop(&mut self) {
123 if self.options.display {
124 if let (Some(p), Some(cookie)) = (self.screensaver_proxy.as_ref(), self.cookie) {
125 p.un_inhibit(cookie).unwrap()
126 }
127 }
128 }
129}