Lock on suspend with inhibit
This commit is contained in:
parent
eb3ba78e57
commit
9d4fe5bb0b
2 changed files with 73 additions and 15 deletions
|
|
@ -24,8 +24,10 @@ use std::{
|
|||
collections::HashMap,
|
||||
ffi::{CStr, CString},
|
||||
fs,
|
||||
os::fd::OwnedFd,
|
||||
path::Path,
|
||||
process,
|
||||
sync::Arc,
|
||||
};
|
||||
use tokio::{sync::mpsc, task, time};
|
||||
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
|
||||
|
|
@ -195,6 +197,7 @@ pub enum Message {
|
|||
SessionLockEvent(SessionLockEvent),
|
||||
Channel(mpsc::Sender<String>),
|
||||
BackgroundState(cosmic_bg_config::state::State),
|
||||
Inhibit(Arc<OwnedFd>),
|
||||
NetworkIcon(Option<&'static str>),
|
||||
PowerInfo(Option<(String, f64)>),
|
||||
Prompt(String, bool, Option<String>),
|
||||
|
|
@ -223,6 +226,7 @@ pub struct App {
|
|||
surface_images: HashMap<SurfaceId, widget::image::Handle>,
|
||||
surface_names: HashMap<SurfaceId, String>,
|
||||
text_input_ids: HashMap<SurfaceId, widget::Id>,
|
||||
inhibit_opt: Option<Arc<OwnedFd>>,
|
||||
network_icon_opt: Option<&'static str>,
|
||||
power_info_opt: Option<(String, f64)>,
|
||||
value_tx_opt: Option<mpsc::Sender<String>>,
|
||||
|
|
@ -318,6 +322,7 @@ impl cosmic::Application for App {
|
|||
surface_images: HashMap::new(),
|
||||
surface_names: HashMap::new(),
|
||||
text_input_ids: HashMap::new(),
|
||||
inhibit_opt: None,
|
||||
network_icon_opt: None,
|
||||
power_info_opt: None,
|
||||
value_tx_opt: None,
|
||||
|
|
@ -415,6 +420,8 @@ impl cosmic::Application for App {
|
|||
SessionLockEvent::Locked => {
|
||||
log::info!("session locked");
|
||||
self.state = State::Locked;
|
||||
// Allow suspend
|
||||
self.inhibit_opt = None;
|
||||
let mut commands = Vec::with_capacity(self.surface_ids.len());
|
||||
for (output, surface_id) in self.surface_ids.iter() {
|
||||
commands.push(get_lock_surface(*surface_id, output.clone()));
|
||||
|
|
@ -443,6 +450,9 @@ impl cosmic::Application for App {
|
|||
self.surface_images.clear();
|
||||
self.update_wallpapers();
|
||||
}
|
||||
Message::Inhibit(inhibit) => {
|
||||
self.inhibit_opt = Some(inhibit);
|
||||
}
|
||||
Message::NetworkIcon(network_icon_opt) => {
|
||||
self.network_icon_opt = network_icon_opt;
|
||||
}
|
||||
|
|
@ -813,13 +823,7 @@ impl cosmic::Application for App {
|
|||
|
||||
#[cfg(feature = "logind")]
|
||||
{
|
||||
subscriptions.push(crate::logind::subscription().map(|lock| {
|
||||
if lock {
|
||||
Message::Lock
|
||||
} else {
|
||||
Message::Unlock
|
||||
}
|
||||
}));
|
||||
subscriptions.push(crate::logind::subscription());
|
||||
}
|
||||
|
||||
#[cfg(feature = "networkmanager")]
|
||||
|
|
|
|||
|
|
@ -2,11 +2,22 @@ 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 logind_zbus::{
|
||||
manager::{InhibitType, ManagerProxy},
|
||||
session::SessionProxy,
|
||||
};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
error::Error,
|
||||
os::fd::{FromRawFd, IntoRawFd, OwnedFd},
|
||||
process,
|
||||
sync::Arc,
|
||||
};
|
||||
use tokio::time;
|
||||
use zbus::Connection;
|
||||
|
||||
use crate::locker::Message;
|
||||
|
||||
pub async fn power_off() -> zbus::Result<()> {
|
||||
let connection = Connection::system().await?;
|
||||
let manager = ManagerProxy::new(&connection).await?;
|
||||
|
|
@ -25,7 +36,21 @@ pub async fn suspend() -> zbus::Result<()> {
|
|||
manager.suspend(false).await
|
||||
}
|
||||
|
||||
pub fn subscription() -> Subscription<bool> {
|
||||
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
|
||||
Ok(unsafe { OwnedFd::from_raw_fd(fd.into_raw_fd()) })
|
||||
}
|
||||
|
||||
pub fn subscription() -> Subscription<Message> {
|
||||
struct LogindSubscription;
|
||||
|
||||
subscription::channel(
|
||||
|
|
@ -49,7 +74,7 @@ pub fn subscription() -> Subscription<bool> {
|
|||
}
|
||||
|
||||
//TODO: use never type?
|
||||
pub async fn handler(msg_tx: &mut mpsc::Sender<bool>) -> Result<(), Box<dyn Error>> {
|
||||
pub async fn handler(msg_tx: &mut mpsc::Sender<Message>) -> Result<(), Box<dyn Error>> {
|
||||
let connection = Connection::system().await?;
|
||||
let manager = ManagerProxy::new(&connection).await?;
|
||||
let session_path = manager.get_session_by_PID(process::id()).await?;
|
||||
|
|
@ -58,16 +83,45 @@ pub async fn handler(msg_tx: &mut mpsc::Sender<bool>) -> Result<(), Box<dyn Erro
|
|||
.build()
|
||||
.await?;
|
||||
|
||||
let mut inhibit_opt = Some(inhibit(&manager).await?);
|
||||
let mut prepare_for_sleep = manager.receive_prepare_for_sleep().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() => {
|
||||
// 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() => {
|
||||
log::info!("logind lock");
|
||||
msg_tx.send(true).await?;
|
||||
msg_tx.send(Message::Lock).await?;
|
||||
}, _ = unlock.next() => {
|
||||
log::info!("logind unlock");
|
||||
msg_tx.send(false).await?;
|
||||
msg_tx.send(Message::Unlock).await?;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue