2024-04-05 11:01:57 -06:00
|
|
|
use cosmic::iced::{
|
2025-02-21 17:05:50 -05:00
|
|
|
Subscription,
|
2025-04-10 13:03:53 +02:00
|
|
|
futures::{SinkExt, StreamExt, channel::mpsc},
|
2024-04-05 11:01:57 -06:00
|
|
|
};
|
2024-04-05 19:02:20 -06:00
|
|
|
use logind_zbus::{
|
|
|
|
|
manager::{InhibitType, ManagerProxy},
|
|
|
|
|
session::SessionProxy,
|
|
|
|
|
};
|
2025-04-10 13:03:53 +02:00
|
|
|
use std::{any::TypeId, error::Error, os::fd::OwnedFd, sync::Arc, time::Duration};
|
2024-04-05 11:01:57 -06:00
|
|
|
use zbus::Connection;
|
2023-11-29 08:02:14 -07:00
|
|
|
|
2024-04-05 19:02:20 -06:00
|
|
|
use crate::locker::Message;
|
|
|
|
|
|
2024-04-05 11:01:57 -06:00
|
|
|
pub async fn power_off() -> zbus::Result<()> {
|
2023-11-29 08:02:14 -07:00
|
|
|
let connection = Connection::system().await?;
|
|
|
|
|
let manager = ManagerProxy::new(&connection).await?;
|
2024-04-05 06:21:40 -04:00
|
|
|
manager.power_off(false).await
|
2023-11-29 08:02:14 -07:00
|
|
|
}
|
|
|
|
|
|
2024-04-05 11:01:57 -06:00
|
|
|
pub async fn reboot() -> zbus::Result<()> {
|
2023-11-29 08:02:14 -07:00
|
|
|
let connection = Connection::system().await?;
|
|
|
|
|
let manager = ManagerProxy::new(&connection).await?;
|
|
|
|
|
manager.reboot(false).await
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-05 11:01:57 -06:00
|
|
|
pub async fn suspend() -> zbus::Result<()> {
|
2023-11-29 08:02:14 -07:00
|
|
|
let connection = Connection::system().await?;
|
|
|
|
|
let manager = ManagerProxy::new(&connection).await?;
|
|
|
|
|
manager.suspend(false).await
|
|
|
|
|
}
|
2024-04-05 11:01:57 -06:00
|
|
|
|
2024-04-05 19:02:20 -06:00
|
|
|
async fn inhibit(manager: &ManagerProxy<'_>) -> zbus::Result<OwnedFd> {
|
|
|
|
|
let what = InhibitType::Sleep;
|
|
|
|
|
let who = "COSMIC Greeter";
|
|
|
|
|
let why = "COSMIC Greeter needs to display a lock screen";
|
|
|
|
|
let mode = "delay";
|
|
|
|
|
//TODO: update logind-zbus to fix inhibit signature
|
|
|
|
|
let fd: zbus::zvariant::OwnedFd = manager
|
|
|
|
|
.inner()
|
|
|
|
|
.call("Inhibit", &(what, who, why, mode))
|
|
|
|
|
.await?;
|
|
|
|
|
// Have to convert to std type to avoid leaking zbus dependency
|
2024-05-17 09:11:50 -06:00
|
|
|
Ok(fd.into())
|
2024-04-05 19:02:20 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn subscription() -> Subscription<Message> {
|
2024-04-05 11:01:57 -06:00
|
|
|
struct LogindSubscription;
|
|
|
|
|
|
2025-02-21 17:05:50 -05:00
|
|
|
Subscription::run_with_id(
|
2024-04-05 11:01:57 -06:00
|
|
|
TypeId::of::<LogindSubscription>(),
|
2025-02-21 17:05:50 -05:00
|
|
|
cosmic::iced_futures::stream::channel(16, |mut msg_tx| async move {
|
2024-04-05 11:01:57 -06:00
|
|
|
match handler(&mut msg_tx).await {
|
|
|
|
|
Ok(()) => {}
|
|
|
|
|
Err(err) => {
|
|
|
|
|
log::warn!("logind error: {}", err);
|
|
|
|
|
//TODO: send error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-31 18:01:07 -04:00
|
|
|
std::process::exit(1);
|
2025-02-21 17:05:50 -05:00
|
|
|
}),
|
2024-04-05 11:01:57 -06:00
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//TODO: use never type?
|
2024-04-05 19:02:20 -06:00
|
|
|
pub async fn handler(msg_tx: &mut mpsc::Sender<Message>) -> Result<(), Box<dyn Error>> {
|
2024-04-05 11:01:57 -06:00
|
|
|
let connection = Connection::system().await?;
|
|
|
|
|
let manager = ManagerProxy::new(&connection).await?;
|
2024-11-07 09:37:16 -07:00
|
|
|
let session_path = manager
|
|
|
|
|
.get_session_by_PID(std::os::unix::process::parent_id())
|
|
|
|
|
.await?;
|
2024-04-05 11:01:57 -06:00
|
|
|
let session = SessionProxy::builder(&connection)
|
|
|
|
|
.path(&session_path)?
|
|
|
|
|
.build()
|
|
|
|
|
.await?;
|
|
|
|
|
|
2024-04-05 19:02:20 -06:00
|
|
|
let mut inhibit_opt = Some(inhibit(&manager).await?);
|
|
|
|
|
let mut prepare_for_sleep = manager.receive_prepare_for_sleep().await?;
|
2024-04-05 11:01:57 -06:00
|
|
|
let mut lock = session.receive_lock().await?;
|
|
|
|
|
let mut unlock = session.receive_unlock().await?;
|
2025-04-10 13:03:53 +02:00
|
|
|
|
|
|
|
|
let mut interval = tokio::time::interval(Duration::from_secs(1));
|
|
|
|
|
|
2024-04-05 11:01:57 -06:00
|
|
|
loop {
|
2024-04-05 19:02:20 -06:00
|
|
|
// Waits until a signal has been received
|
|
|
|
|
tokio::select!(
|
|
|
|
|
signal_opt = prepare_for_sleep.next() => {
|
|
|
|
|
match signal_opt {
|
|
|
|
|
Some(signal) => match signal.args() {
|
|
|
|
|
Ok(args) => {
|
|
|
|
|
if args.start {
|
|
|
|
|
log::info!("logind prepare for sleep");
|
|
|
|
|
if let Some(inhibit) = inhibit_opt.take() {
|
|
|
|
|
msg_tx.send(Message::Inhibit(Arc::new(inhibit))).await?;
|
|
|
|
|
}
|
|
|
|
|
msg_tx.send(Message::Lock).await?;
|
|
|
|
|
} else {
|
|
|
|
|
log::info!("logind resume");
|
|
|
|
|
if inhibit_opt.is_none() {
|
|
|
|
|
inhibit_opt = Some(inhibit(&manager).await?);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Err(err) => {
|
|
|
|
|
log::warn!("logind prepare to sleep invalid data: {}", err);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
None => {
|
|
|
|
|
log::warn!("logind prepare to sleep missing data");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_ = lock.next() => {
|
2024-04-05 11:31:15 -06:00
|
|
|
log::info!("logind lock");
|
2024-04-05 19:02:20 -06:00
|
|
|
msg_tx.send(Message::Lock).await?;
|
2024-04-05 11:01:57 -06:00
|
|
|
}, _ = unlock.next() => {
|
2024-04-05 11:31:15 -06:00
|
|
|
log::info!("logind unlock");
|
2024-04-05 19:02:20 -06:00
|
|
|
msg_tx.send(Message::Unlock).await?;
|
2024-04-05 11:01:57 -06:00
|
|
|
});
|
2025-04-10 13:03:53 +02:00
|
|
|
|
|
|
|
|
interval.tick().await;
|
2024-04-05 11:01:57 -06:00
|
|
|
}
|
|
|
|
|
}
|