diff --git a/watchers/src/watchers/gnome_idle.rs b/watchers/src/watchers/gnome_idle.rs index f59addd..3c3adfc 100644 --- a/watchers/src/watchers/gnome_idle.rs +++ b/watchers/src/watchers/gnome_idle.rs @@ -3,15 +3,16 @@ use crate::report_client::ReportClient; use anyhow::Context; use async_trait::async_trait; use std::sync::Arc; -use zbus::blocking::Connection; +use zbus::Connection; pub struct IdleWatcher { dbus_connection: Connection, is_idle: bool, } +#[async_trait] impl idle::SinceLastInput for IdleWatcher { - fn seconds_since_input(&mut self) -> anyhow::Result { + async fn seconds_since_input(&mut self) -> anyhow::Result { let ms = self .dbus_connection .call_method( @@ -20,7 +21,8 @@ impl idle::SinceLastInput for IdleWatcher { Some("org.gnome.Mutter.IdleMonitor"), "GetIdletime", &(), - )? + ) + .await? .body::()?; u32::try_from(ms / 1000).with_context(|| format!("Number {ms} is invalid")) } @@ -30,10 +32,10 @@ impl idle::SinceLastInput for IdleWatcher { impl Watcher for IdleWatcher { async fn new(_: &Arc) -> anyhow::Result { let mut watcher = Self { - dbus_connection: Connection::session()?, + dbus_connection: Connection::session().await?, is_idle: false, }; - idle::SinceLastInput::seconds_since_input(&mut watcher)?; + idle::SinceLastInput::seconds_since_input(&mut watcher).await?; Ok(watcher) } diff --git a/watchers/src/watchers/idle.rs b/watchers/src/watchers/idle.rs index d9bc08b..911ce65 100644 --- a/watchers/src/watchers/idle.rs +++ b/watchers/src/watchers/idle.rs @@ -1,9 +1,11 @@ use crate::report_client::ReportClient; +use async_trait::async_trait; use chrono::{Duration, Utc}; use std::sync::Arc; +#[async_trait] pub trait SinceLastInput { - fn seconds_since_input(&mut self) -> anyhow::Result; + async fn seconds_since_input(&mut self) -> anyhow::Result; } pub async fn ping_since_last_input( @@ -16,7 +18,7 @@ pub async fn ping_since_last_input( let duration_1ms: Duration = Duration::milliseconds(1); let duration_zero: Duration = Duration::zero(); - let seconds_since_input = watcher.seconds_since_input()?; + let seconds_since_input = watcher.seconds_since_input().await?; let now = Utc::now(); let time_since_input = Duration::seconds(i64::from(seconds_since_input)); let last_input = now - time_since_input; diff --git a/watchers/src/watchers/kwin_window.rs b/watchers/src/watchers/kwin_window.rs index 5855ad8..a4fcc1a 100644 --- a/watchers/src/watchers/kwin_window.rs +++ b/watchers/src/watchers/kwin_window.rs @@ -12,8 +12,8 @@ use std::path::Path; use std::sync::{mpsc::channel, Arc}; use std::thread; use tokio::sync::Mutex; -use zbus::blocking::{Connection, ConnectionBuilder}; use zbus::dbus_interface; +use zbus::{Connection, ConnectionBuilder}; const KWIN_SCRIPT_NAME: &str = "activity_watcher"; const KWIN_SCRIPT: &str = include_str!("kwin_window.js"); @@ -31,20 +31,19 @@ impl KWinScript { } } - fn load(&mut self) -> anyhow::Result<()> { + async fn load(&mut self) -> anyhow::Result<()> { let path = temp_dir().join("kwin_window.js"); std::fs::write(&path, KWIN_SCRIPT).unwrap(); - let result = self - .get_registered_number(&path) - .and_then(|number| self.start(number)); + let number = self.get_registered_number(&path).await?; + let result = self.start(number).await; std::fs::remove_file(&path)?; self.is_loaded = true; result } - fn is_loaded(&self) -> anyhow::Result { + async fn is_loaded(&self) -> anyhow::Result { self.dbus_connection .call_method( Some("org.kde.KWin"), @@ -52,12 +51,13 @@ impl KWinScript { Some("org.kde.kwin.Scripting"), "isScriptLoaded", &KWIN_SCRIPT_NAME, - )? + ) + .await? .body::() .map_err(std::convert::Into::into) } - fn get_registered_number(&self, path: &Path) -> anyhow::Result { + async fn get_registered_number(&self, path: &Path) -> anyhow::Result { let temp_path = path .to_str() .ok_or(anyhow!("Temporary file path is not valid"))?; @@ -70,12 +70,13 @@ impl KWinScript { "loadScript", // since OsStr does not implement zvariant::Type, the temp-path must be valid utf-8 &(temp_path, KWIN_SCRIPT_NAME), - )? + ) + .await? .body::() .map_err(std::convert::Into::into) } - fn unload(&self) -> anyhow::Result { + async fn unload(&self) -> anyhow::Result { self.dbus_connection .call_method( Some("org.kde.KWin"), @@ -83,12 +84,13 @@ impl KWinScript { Some("org.kde.kwin.Scripting"), "unloadScript", &KWIN_SCRIPT_NAME, - )? + ) + .await? .body::() .map_err(std::convert::Into::into) } - fn start(&self, script_number: i32) -> anyhow::Result<()> { + async fn start(&self, script_number: i32) -> anyhow::Result<()> { debug!("Starting KWin script {script_number}"); self.dbus_connection .call_method( @@ -98,6 +100,7 @@ impl KWinScript { "run", &(), ) + .await .with_context(|| "Error on starting the script")?; Ok(()) } @@ -106,10 +109,16 @@ impl KWinScript { impl Drop for KWinScript { fn drop(&mut self) { if self.is_loaded { - debug!("Unloading KWin script"); - if let Err(e) = self.unload() { - error!("Problem during stopping KWin script: {e}"); - }; + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(async { + debug!("Unloading KWin script"); + if let Err(e) = self.unload().await { + error!("Problem during stopping KWin script: {e}"); + }; + }); } } } @@ -161,12 +170,12 @@ pub struct WindowWatcher { #[async_trait] impl Watcher for WindowWatcher { async fn new(_: &Arc) -> anyhow::Result { - let mut kwin_script = KWinScript::new(Connection::session()?); - if kwin_script.is_loaded()? { + let mut kwin_script = KWinScript::new(Connection::session().await?); + if kwin_script.is_loaded().await? { debug!("KWin script is already loaded, unloading"); - kwin_script.unload()?; + kwin_script.unload().await?; } - kwin_script.load().unwrap(); + kwin_script.load().await.unwrap(); let active_window = Arc::new(Mutex::new(ActiveWindow { caption: String::new(), @@ -179,21 +188,32 @@ impl Watcher for WindowWatcher { let (tx, rx) = channel(); thread::spawn(move || { - let result = (|| { + async fn get_connection( + active_window_interface: ActiveWindowInterface, + ) -> zbus::Result { ConnectionBuilder::session()? .name("com._2e3s.Awatcher")? .serve_at("/com/_2e3s/Awatcher", active_window_interface)? .build() - })(); - match result { - Ok(connection) => { - tx.send(None).unwrap(); - loop { - connection.monitor_activity().wait(); - } - } - Err(e) => tx.send(Some(e)), + .await } + + tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap() + .block_on(async move { + match get_connection(active_window_interface).await { + Ok(connection) => { + tx.send(None).unwrap(); + loop { + connection.monitor_activity().wait(); + } + } + Err(e) => tx.send(Some(e)), + } + }) + .unwrap(); }); if let Some(error) = rx.recv().unwrap() { panic!("Failed to run a DBus interface: {error}"); diff --git a/watchers/src/watchers/x11_screensaver_idle.rs b/watchers/src/watchers/x11_screensaver_idle.rs index 0349393..f11f831 100644 --- a/watchers/src/watchers/x11_screensaver_idle.rs +++ b/watchers/src/watchers/x11_screensaver_idle.rs @@ -9,8 +9,9 @@ pub struct IdleWatcher { is_idle: bool, } +#[async_trait] impl idle::SinceLastInput for IdleWatcher { - fn seconds_since_input(&mut self) -> anyhow::Result { + async fn seconds_since_input(&mut self) -> anyhow::Result { self.client.seconds_since_last_input() } }