mirror of
https://github.com/2e3s/awatcher.git
synced 2025-07-28 13:51:58 +00:00
140 lines
3.9 KiB
Rust
140 lines
3.9 KiB
Rust
#[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<ReportClient>) -> anyhow::Result<Self>
|
|
where
|
|
Self: Sized;
|
|
|
|
async fn run_iteration(&mut self, client: &Arc<ReportClient>) -> anyhow::Result<()>;
|
|
}
|
|
|
|
async fn create_watcher<T: Watcher>(client: &Arc<ReportClient>, name: &str) -> Option<T> {
|
|
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<ReportClient>,
|
|
watcher_type: &WatcherType,
|
|
) -> Option<Box<dyn Watcher>> {
|
|
match watcher_type {
|
|
WatcherType::Idle => {
|
|
watch!(create_watcher::<wl_ext_idle_notify::IdleWatcher>(
|
|
client,
|
|
"Wayland idle (ext_idle_notification_v1)"
|
|
));
|
|
watch!(create_watcher::<wl_kwin_idle::IdleWatcher>(
|
|
client,
|
|
"Wayland idle (KWin)"
|
|
));
|
|
watch!(create_watcher::<x11_screensaver_idle::IdleWatcher>(
|
|
client,
|
|
"X11 idle (screensaver)"
|
|
));
|
|
#[cfg(feature = "gnome")]
|
|
watch!(create_watcher::<gnome_idle::IdleWatcher>(
|
|
client,
|
|
"Gnome idle (Mutter/IdleMonitor)"
|
|
));
|
|
}
|
|
WatcherType::ActiveWindow => {
|
|
watch!(create_watcher::<wl_foreign_toplevel::WindowWatcher>(
|
|
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::<kwin_window::WindowWatcher>(
|
|
client,
|
|
"KWin window (script)"
|
|
));
|
|
watch!(create_watcher::<x11_window::WindowWatcher>(
|
|
client,
|
|
"X11 window"
|
|
));
|
|
#[cfg(feature = "gnome")]
|
|
watch!(create_watcher::<gnome_window::WindowWatcher>(
|
|
client,
|
|
"Gnome window (extension)"
|
|
));
|
|
}
|
|
};
|
|
|
|
None
|
|
}
|
|
|
|
pub async fn run_first_supported(client: Arc<ReportClient>, 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
|
|
}
|