From 7a3004bc0d9db76f4a5c60022ac7d7d151ad19f4 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 28 Oct 2024 18:12:24 -0700 Subject: [PATCH] Use `Event` for screensaver inhibit state --- src/freedesktop_screensaver.rs | 28 +++++++++++++++++++--------- src/main.rs | 30 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/freedesktop_screensaver.rs b/src/freedesktop_screensaver.rs index 577648a..0c84129 100644 --- a/src/freedesktop_screensaver.rs +++ b/src/freedesktop_screensaver.rs @@ -7,6 +7,8 @@ use std::sync::{ Arc, Mutex, }; +use crate::{Event, EventSender}; + #[derive(Debug)] pub struct Inhibitor { cookie: u32, @@ -18,6 +20,7 @@ pub struct Inhibitor { pub struct Screensaver { inhibitors: Arc>>, last_cookie: AtomicU32, + event_sender: EventSender, } #[zbus::interface(name = "org.freedesktop.ScreenSaver")] @@ -37,7 +40,11 @@ impl Screensaver { reason_for_inhibit, cookie ); - self.inhibitors.lock().unwrap().push(Inhibitor { + let mut inhibitors = self.inhibitors.lock().unwrap(); + if inhibitors.is_empty() { + let _ = self.event_sender.send(Event::ScreensaverInhibit(false)); + } + inhibitors.push(Inhibitor { cookie, application_name, reason_for_inhibit, @@ -62,10 +69,9 @@ impl Screensaver { } } -pub async fn serve( - conn: &zbus::Connection, - inhibitors: Arc>>, -) -> zbus::Result<()> { +pub async fn serve(conn: &zbus::Connection, event_sender: EventSender) -> zbus::Result<()> { + let inhibitors = Arc::new(Mutex::new(Vec::new())); + conn.request_name_with_flags( "org.freedesktop.ScreenSaver", zbus::fdo::RequestNameFlags::ReplaceExisting.into(), @@ -76,6 +82,7 @@ pub async fn serve( "/org/freedesktop/ScreenSaver", Screensaver { inhibitors: inhibitors.clone(), + event_sender: event_sender.clone(), last_cookie: AtomicU32::new(0), }, ) @@ -87,10 +94,13 @@ pub async fn serve( 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); + let mut inhibitors = inhibitors.lock().unwrap(); + if !inhibitors.is_empty() { + inhibitors.retain(|inhibitor| inhibitor.client != name); + if inhibitors.is_empty() { + let _ = event_sender.send(Event::ScreensaverInhibit(false)); + } + } } } } diff --git a/src/main.rs b/src/main.rs index 2e6a104..5823aec 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,10 +5,7 @@ use calloop_wayland_source::WaylandSource; use cosmic_config::{calloop::ConfigWatchSource, CosmicConfigEntry}; use cosmic_idle_config::CosmicIdleConfig; use futures_lite::stream::StreamExt; -use std::{ - process::Command, - sync::{Arc, Mutex}, -}; +use std::process::Command; use upower_dbus::UPowerProxy; use wayland_client::{ delegate_noop, @@ -35,8 +32,11 @@ mod freedesktop_screensaver; #[derive(Debug)] enum Event { OnBattery(bool), + ScreensaverInhibit(bool), } +type EventSender = channel::Sender; + struct IdleNotification { notification: ext_idle_notification_v1::ExtIdleNotificationV1, time: u32, @@ -58,7 +58,7 @@ impl Drop for IdleNotification { } } -async fn receive_battery_task(sender: channel::Sender) -> zbus::Result<()> { +async fn receive_battery_task(sender: EventSender) -> zbus::Result<()> { let connection = zbus::Connection::system().await?; let upower = UPowerProxy::new(&connection).await?; let mut stream = upower.receive_on_battery_changed().await; @@ -95,12 +95,12 @@ struct State { screen_off_idle_notification: Option, suspend_idle_notification: Option, on_battery: bool, - screensaver_inhibitors: Arc>>, + screensaver_inhibit: bool, } impl State { fn update_screen_off_idle(&mut self, is_idle: bool) { - if !self.screensaver_inhibitors.lock().unwrap().is_empty() { + if self.screensaver_inhibit { return; } for output in &mut self.outputs { @@ -114,7 +114,7 @@ impl State { } fn update_suspend_idle(&mut self, is_idle: bool) { - if !self.screensaver_inhibitors.lock().unwrap().is_empty() { + if self.screensaver_inhibit { return; } if is_idle { @@ -154,6 +154,9 @@ impl State { Event::OnBattery(value) => { self.on_battery = value; } + Event::ScreensaverInhibit(value) => { + self.screensaver_inhibit = value; + } } } } @@ -224,8 +227,6 @@ fn main() { conf }); - let screensaver_inhibitors = Arc::new(Mutex::new(Vec::new())); - let mut state = State { inner: StateInner { compositor, @@ -242,7 +243,7 @@ fn main() { outputs, conf, on_battery: false, - screensaver_inhibitors: screensaver_inhibitors.clone(), + screensaver_inhibit: false, }; state.recreate_notification(); @@ -264,9 +265,10 @@ fn main() { let (executor, scheduler) = calloop::futures::executor().unwrap(); let (sender, receiver) = channel::channel(); + let sender_clone = sender.clone(); scheduler .schedule(async move { - if let Err(err) = receive_battery_task(sender).await { + if let Err(err) = receive_battery_task(sender_clone).await { log::error!("Getting battery status from upower: {}", err); } }) @@ -274,9 +276,7 @@ fn main() { scheduler .schedule(async move { if let Ok(connection) = zbus::Connection::session().await { - if let Err(err) = - freedesktop_screensaver::serve(&connection, screensaver_inhibitors).await - { + if let Err(err) = freedesktop_screensaver::serve(&connection, sender).await { log::error!("failed to serve FreeDesktop screensaver interface: {}", err); } }