Remove screensaver inhibitors for disconnected clients

This commit is contained in:
Ian Douglas Scott 2024-10-28 17:01:52 -07:00
parent bd5487331d
commit 1cdce673df
2 changed files with 45 additions and 17 deletions

View file

@ -1,18 +1,23 @@
// https://specifications.freedesktop.org/idle-inhibit-spec/latest // https://specifications.freedesktop.org/idle-inhibit-spec/latest
// https://invent.kde.org/plasma/kscreenlocker/-/blob/master/dbus/org.freedesktop.ScreenSaver.xml
use std::collections::HashMap; use futures_lite::StreamExt;
use std::sync::{
atomic::{AtomicU32, Ordering},
Arc, Mutex,
};
#[derive(Debug)] #[derive(Debug)]
struct Inhibitor { struct Inhibitor {
cookie: u32,
application_name: String, application_name: String,
reason_for_inhibit: String, reason_for_inhibit: String,
client: zbus::names::UniqueName<'static>, client: zbus::names::UniqueName<'static>,
} }
#[derive(Default)]
pub struct Screensaver { pub struct Screensaver {
inhibitors: HashMap<u32, Inhibitor>, inhibitors: Arc<Mutex<Vec<Inhibitor>>>,
last_cookie: u32, last_cookie: AtomicU32,
} }
#[zbus::interface(name = "org.freedesktop.ScreenSaver")] #[zbus::interface(name = "org.freedesktop.ScreenSaver")]
@ -23,33 +28,57 @@ impl Screensaver {
reason_for_inhibit: String, reason_for_inhibit: String,
#[zbus(header)] header: zbus::message::Header<'_>, #[zbus(header)] header: zbus::message::Header<'_>,
) -> u32 { ) -> u32 {
self.last_cookie += 1; let cookie = self.last_cookie.fetch_add(1, Ordering::Relaxed) + 1;
if let Some(sender) = header.sender() { if let Some(sender) = header.sender() {
self.inhibitors.insert( self.inhibitors.lock().unwrap().push(Inhibitor {
self.last_cookie, cookie,
Inhibitor { application_name,
application_name, reason_for_inhibit,
reason_for_inhibit, client: sender.to_owned(),
client: sender.to_owned(), });
},
);
} }
self.last_cookie cookie
} }
fn un_inhibit(&mut self, cookie: u32) { fn un_inhibit(&mut self, cookie: u32) {
self.inhibitors.remove(&cookie); let mut inhibitors = self.inhibitors.lock().unwrap();
if let Some(idx) = inhibitors.iter().position(|x| x.cookie == cookie) {
inhibitors.remove(idx);
}
} }
} }
pub async fn serve(conn: &zbus::Connection) -> zbus::Result<()> { pub async fn serve(conn: &zbus::Connection) -> zbus::Result<()> {
let inhibitors = Arc::new(Mutex::new(Vec::new()));
conn.request_name_with_flags( conn.request_name_with_flags(
"org.freedesktop.ScreenSaver", "org.freedesktop.ScreenSaver",
zbus::fdo::RequestNameFlags::ReplaceExisting.into(), zbus::fdo::RequestNameFlags::ReplaceExisting.into(),
) )
.await?; .await?;
conn.object_server() conn.object_server()
.at("/org/freedesktop/ScreenSaver", Screensaver::default()) .at(
"/org/freedesktop/ScreenSaver",
Screensaver {
inhibitors: inhibitors.clone(),
last_cookie: AtomicU32::new(0),
},
)
.await?; .await?;
let dbus = zbus::fdo::DBusProxy::new(conn).await?;
let mut name_owner_stream = dbus.receive_name_owner_changed().await?;
while let Some(event) = name_owner_stream.next().await {
let args = event.args()?;
if args.new_owner.is_none() {
if let zbus::names::BusName::Unique(name) = args.name {
inhibitors
.lock()
.unwrap()
.retain(|inhibitor| inhibitor.client != name);
}
}
}
Ok(()) Ok(())
} }

View file

@ -338,7 +338,6 @@ fn main() {
if let Err(err) = freedesktop_screensaver::serve(&connection).await { if let Err(err) = freedesktop_screensaver::serve(&connection).await {
log::error!("failed to serve FreeDesktop screensaver interface: {}", err); log::error!("failed to serve FreeDesktop screensaver interface: {}", err);
} }
std::future::pending::<()>().await;
} }
}) })
.unwrap(); .unwrap();