1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use std::borrow::Cow;
use std::time::Duration;
use dbus::arg::OwnedFd;
use dbus::blocking::{BlockingSender, Connection};
use dbus::message::Message;
use wasmer_enumset::EnumSet;
use crate::LockType;
pub struct InhibitionManager {
connection: Connection,
}
const DBUS_TIMEOUT: Duration = Duration::from_millis(250);
impl InhibitionManager {
pub fn new() -> Result<Self, dbus::Error> {
let connection = Connection::new_system()?;
Ok(Self { connection })
}
}
const LOGIND_NAME: &'static str = "org.freedesktop.login1";
const LOGIND_PATH: &'static str = "/org/freedesktop/login1";
const LOGIND_MANAGER_INTERFACE: &'static str = "org.freedesktop.login1.Manager";
impl crate::InhibitionManager for InhibitionManager {
type Lock = Lock;
type Error = dbus::Error;
fn lock(
&self,
types: EnumSet<LockType>,
who: &str,
why: &str,
) -> Result<Self::Lock, dbus::Error> {
let what = lock_types_str(types);
let msg = Message::call_with_args(
LOGIND_NAME,
LOGIND_PATH,
LOGIND_MANAGER_INTERFACE,
"Inhibit",
(&*what, who, why, "block"),
);
let (handle,) = self
.connection
.send_with_reply_and_block(msg, DBUS_TIMEOUT)?
.read_all()?;
Ok(Lock { _handle: handle })
}
}
#[derive(Debug)]
pub struct Lock {
_handle: OwnedFd,
}
impl crate::Lock for Lock {}
fn lock_types_str(types: EnumSet<LockType>) -> Cow<'static, str> {
match types.len() {
0 => Cow::Borrowed(""),
1 => Cow::Borrowed(lock_type_name(types.iter().next().unwrap())),
_ => {
let names: Vec<_> = types.iter().map(lock_type_name).collect();
Cow::Owned(names[..].join(":"))
}
}
}
fn lock_type_name(lock_type: LockType) -> &'static str {
match lock_type {
LockType::AutomaticSuspend => "idle",
LockType::ManualSuspend => "sleep",
LockType::ManualShutdown => "shutdown",
}
}