diff --git a/src/locker.rs b/src/locker.rs index 457fb0f..3744850 100644 --- a/src/locker.rs +++ b/src/locker.rs @@ -195,6 +195,8 @@ pub enum Message { SessionLockEvent(SessionLockEvent), Channel(mpsc::Sender), BackgroundState(cosmic_bg_config::state::State), + LogindLock, + LogindUnlock, NetworkIcon(Option<&'static str>), PowerInfo(Option<(String, f64)>), Prompt(String, bool, Option), @@ -405,6 +407,12 @@ impl cosmic::Application for App { self.surface_images.clear(); self.update_wallpapers(); } + Message::LogindLock => { + log::warn!("TODO: LogindLock"); + } + Message::LogindUnlock => { + log::warn!("TODO: LogindUnlock"); + } Message::NetworkIcon(network_icon_opt) => { self.network_icon_opt = network_icon_opt; } @@ -660,11 +668,22 @@ impl cosmic::Application for App { struct PamSubscription; //TODO: just use one vec for all subscriptions - let mut extra_suscriptions = Vec::with_capacity(2); + let mut extra_subscriptions = Vec::with_capacity(3); + + #[cfg(feature = "logind")] + { + extra_subscriptions.push(crate::logind::subscription().map(|lock| { + if lock { + Message::LogindLock + } else { + Message::LogindUnlock + } + })); + } #[cfg(feature = "networkmanager")] { - extra_suscriptions.push( + extra_subscriptions.push( crate::networkmanager::subscription() .map(|icon_opt| Message::NetworkIcon(icon_opt)), ); @@ -672,7 +691,7 @@ impl cosmic::Application for App { #[cfg(feature = "upower")] { - extra_suscriptions + extra_subscriptions .push(crate::upower::subscription().map(|info_opt| Message::PowerInfo(info_opt))); } @@ -750,7 +769,7 @@ impl cosmic::Application for App { } }, ), - Subscription::batch(extra_suscriptions), + Subscription::batch(extra_subscriptions), ]) } } diff --git a/src/logind.rs b/src/logind.rs index d6b6df5..8cc00c9 100644 --- a/src/logind.rs +++ b/src/logind.rs @@ -1,20 +1,71 @@ -use logind_zbus::manager::ManagerProxy; -use zbus::{Connection, Result}; +use cosmic::iced::{ + futures::{channel::mpsc, SinkExt, StreamExt}, + subscription, Subscription, +}; +use logind_zbus::{manager::ManagerProxy, session::SessionProxy}; +use std::{any::TypeId, error::Error, process}; +use tokio::time; +use zbus::Connection; -pub async fn power_off() -> Result<()> { +pub async fn power_off() -> zbus::Result<()> { let connection = Connection::system().await?; let manager = ManagerProxy::new(&connection).await?; manager.power_off(false).await } -pub async fn reboot() -> Result<()> { +pub async fn reboot() -> zbus::Result<()> { let connection = Connection::system().await?; let manager = ManagerProxy::new(&connection).await?; manager.reboot(false).await } -pub async fn suspend() -> Result<()> { +pub async fn suspend() -> zbus::Result<()> { let connection = Connection::system().await?; let manager = ManagerProxy::new(&connection).await?; manager.suspend(false).await } + +pub fn subscription() -> Subscription { + struct LogindSubscription; + + subscription::channel( + TypeId::of::(), + 16, + |mut msg_tx| async move { + match handler(&mut msg_tx).await { + Ok(()) => {} + Err(err) => { + log::warn!("logind error: {}", err); + //TODO: send error + } + } + + //TODO: should we retry on error? + loop { + time::sleep(time::Duration::new(60, 0)).await; + } + }, + ) +} + +//TODO: use never type? +pub async fn handler(msg_tx: &mut mpsc::Sender) -> Result<(), Box> { + let connection = Connection::system().await?; + let manager = ManagerProxy::new(&connection).await?; + let session_path = manager.get_session_by_PID(process::id()).await?; + let session = SessionProxy::builder(&connection) + .path(&session_path)? + .build() + .await?; + + let mut lock = session.receive_lock().await?; + let mut unlock = session.receive_unlock().await?; + loop { + // Waits until lock or unlock signals have been received + tokio::select!(_ = lock.next() => { + msg_tx.send(true).await?; + }, _ = unlock.next() => { + msg_tx.send(false).await?; + }); + } +}