#[cfg(feature = "gnome")] mod gnome_idle; #[cfg(feature = "gnome")] mod gnome_wayland; #[cfg(feature = "gnome")] mod gnome_window; mod idle; #[cfg(feature = "kwin_window")] mod kwin_window; mod wl_connection; mod wl_ext_idle_notify; mod wl_foreign_toplevel; mod wl_kwin_idle; mod x11_connection; mod x11_screensaver_idle; mod x11_window; use crate::{config::Config, report_client::ReportClient}; use async_trait::async_trait; use std::{fmt::Display, sync::Arc}; use tokio::time; pub enum WatcherType { Idle, ActiveWindow, } impl WatcherType { fn sleep_time(&self, config: &Config) -> time::Duration { match self { WatcherType::Idle => config.poll_time_idle, WatcherType::ActiveWindow => config.poll_time_window, } } } impl Display for WatcherType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { WatcherType::Idle => write!(f, "idle"), WatcherType::ActiveWindow => write!(f, "active window"), } } } #[async_trait] pub trait Watcher: Send { async fn new(client: &Arc) -> anyhow::Result where Self: Sized; async fn run_iteration(&mut self, client: &Arc) -> anyhow::Result<()>; } async fn create_watcher(client: &Arc, name: &str) -> Option { match T::new(client).await { Ok(watcher) => { info!("Selected watcher: {name}"); Some(watcher) } Err(e) => { debug!("Watcher \"{name}\" cannot run: {e}"); None } } } macro_rules! watch { ($watcher:expr) => { if let Some(watcher) = $watcher.await { return Some(Box::new(watcher)); } }; } async fn filter_first_supported( client: &Arc, watcher_type: &WatcherType, ) -> Option> { match watcher_type { WatcherType::Idle => { watch!(create_watcher::( client, "Wayland idle (ext_idle_notification_v1)" )); watch!(create_watcher::( client, "Wayland idle (KWin)" )); watch!(create_watcher::( client, "X11 idle (screensaver)" )); #[cfg(feature = "gnome")] watch!(create_watcher::( client, "Gnome idle (Mutter/IdleMonitor)" )); } WatcherType::ActiveWindow => { watch!(create_watcher::( client, "Wayland window (wlr-foreign-toplevel-management-unstable-v1)" )); // XWayland gives _NET_WM_NAME on some windows in KDE, but not on others #[cfg(feature = "kwin_window")] watch!(create_watcher::( client, "KWin window (script)" )); watch!(create_watcher::( client, "X11 window" )); #[cfg(feature = "gnome")] watch!(create_watcher::( client, "Gnome window (extension)" )); } }; None } pub async fn run_first_supported(client: Arc, watcher_type: &WatcherType) -> bool { let supported_watcher = filter_first_supported(&client, watcher_type).await; if let Some(mut watcher) = supported_watcher { info!("Starting {watcher_type} watcher"); loop { if let Err(e) = watcher.run_iteration(&client).await { error!("Error on {watcher_type} iteration: {e}"); } time::sleep(watcher_type.sleep_time(&client.config)).await; } } false }