Separate watchers to a module

This commit is contained in:
Demmie 2023-04-23 21:58:49 -04:00
parent 56f492438f
commit a758913d52
No known key found for this signature in database
GPG Key ID: B06DAA3D432C6E9A
13 changed files with 85 additions and 85 deletions

View File

@ -4,15 +4,8 @@
extern crate log;
mod config;
mod kwin_window;
mod report_client;
mod wl_bindings;
mod wl_connection;
mod wl_foreign_toplevel;
mod wl_kwin_idle;
mod x11_connection;
mod x11_screensaver_idle;
mod x11_window;
mod watchers;
use config::Config;
use fern::colors::{Color, ColoredLevelConfig};
@ -20,55 +13,10 @@ use report_client::ReportClient;
use std::env;
use std::{error::Error, str::FromStr, sync::Arc, thread};
use crate::watchers::ConstructorFilter;
type BoxedError = Box<dyn Error>;
trait Watcher: Send {
fn new() -> Result<Self, BoxedError>
where
Self: Sized;
fn watch(&mut self, client: &Arc<ReportClient>);
}
type BoxedWatcher = Box<dyn Watcher>;
type WatcherConstructor = (&'static str, fn() -> Result<BoxedWatcher, BoxedError>);
type WatcherConstructors = [WatcherConstructor];
trait WatchersFilter {
fn filter_first_supported(&self) -> Option<BoxedWatcher>;
}
impl WatchersFilter for WatcherConstructors {
fn filter_first_supported(&self) -> Option<BoxedWatcher> {
self.iter().find_map(|(name, watcher)| match watcher() {
Ok(watcher) => Some(watcher),
Err(e) => {
info!("{name} cannot run: {e}");
None
}
})
}
}
macro_rules! watcher {
($watcher_struct:ty) => {
(stringify!($watcher_struct), || {
Ok(Box::new(<$watcher_struct>::new()?))
})
};
}
const IDLE_WATCHERS: &[WatcherConstructor] = &[
watcher!(wl_kwin_idle::IdleWatcher),
watcher!(x11_screensaver_idle::IdleWatcher),
];
const ACTIVE_WINDOW_WATCHERS: &[WatcherConstructor] = &[
watcher!(wl_foreign_toplevel::WindowWatcher),
watcher!(kwin_window::WindowWatcher),
watcher!(x11_window::WindowWatcher),
];
fn setup_logger() -> Result<(), fern::InitError> {
let log_setting = env::var("AWATCHER_LOG").unwrap_or("info".to_string());
@ -128,7 +76,7 @@ fn main() -> Result<(), BoxedError> {
let mut thread_handlers = Vec::new();
let idle_watcher = IDLE_WATCHERS.filter_first_supported();
let idle_watcher = watchers::IDLE.filter_first_supported();
if let Some(mut watcher) = idle_watcher {
let thread_client = Arc::clone(&client);
let idle_handler = thread::spawn(move || watcher.watch(&thread_client));
@ -137,7 +85,7 @@ fn main() -> Result<(), BoxedError> {
warn!("No supported idle handler is found");
}
let window_watcher = ACTIVE_WINDOW_WATCHERS.filter_first_supported();
let window_watcher = watchers::ACTIVE_WINDOW.filter_first_supported();
if let Some(mut watcher) = window_watcher {
let thread_client = Arc::clone(&client);
let active_window_handler = thread::spawn(move || watcher.watch(&thread_client));

58
src/watchers.rs Normal file
View File

@ -0,0 +1,58 @@
mod kwin_window;
mod wl_bindings;
mod wl_connection;
mod wl_foreign_toplevel;
mod wl_kwin_idle;
mod x11_connection;
mod x11_screensaver_idle;
mod x11_window;
use crate::{report_client::ReportClient, BoxedError};
use std::sync::Arc;
pub trait Watcher: Send {
fn new() -> Result<Self, BoxedError>
where
Self: Sized;
fn watch(&mut self, client: &Arc<ReportClient>);
}
type BoxedWatcher = Box<dyn Watcher>;
type WatcherConstructor = (&'static str, fn() -> Result<BoxedWatcher, BoxedError>);
type WatcherConstructors = [WatcherConstructor];
pub trait ConstructorFilter {
fn filter_first_supported(&self) -> Option<BoxedWatcher>;
}
impl ConstructorFilter for WatcherConstructors {
fn filter_first_supported(&self) -> Option<BoxedWatcher> {
self.iter().find_map(|(name, watcher)| match watcher() {
Ok(watcher) => Some(watcher),
Err(e) => {
info!("{name} cannot run: {e}");
None
}
})
}
}
macro_rules! watcher {
($watcher_struct:ty) => {
(stringify!($watcher_struct), || {
Ok(Box::new(<$watcher_struct>::new()?))
})
};
}
pub const IDLE: &WatcherConstructors = &[
watcher!(wl_kwin_idle::IdleWatcher),
watcher!(x11_screensaver_idle::IdleWatcher),
];
pub const ACTIVE_WINDOW: &WatcherConstructors = &[
watcher!(wl_foreign_toplevel::WindowWatcher),
watcher!(kwin_window::WindowWatcher),
watcher!(x11_window::WindowWatcher),
];

View File

@ -1,12 +1,10 @@
use crate::Watcher;
/*
* This uses a hack with KWin scripts in order to receive the active window.
* For the moment of writing, KWin doesn't implement the appropriate protocols to get a top level window.
* Inspired by https://github.com/k0kubun/xremap/
*/
use super::report_client::ReportClient;
use super::BoxedError;
use super::{BoxedError, Watcher};
use crate::report_client::ReportClient;
use std::env::temp_dir;
use std::path::Path;
use std::sync::{mpsc::channel, Arc, Mutex};

View File

@ -14,11 +14,11 @@ pub mod idle {
pub mod __interfaces {
use wayland_client::protocol::__interfaces::*;
wayland_scanner::generate_interfaces!("src/wl-protocols/idle.xml");
wayland_scanner::generate_interfaces!("src/watchers/wl-protocols/idle.xml");
}
use self::__interfaces::*;
wayland_scanner::generate_client_code!("src/wl-protocols/idle.xml");
wayland_scanner::generate_client_code!("src/watchers/wl-protocols/idle.xml");
}
pub mod wlr_foreign_toplevel {
@ -33,9 +33,9 @@ pub mod wlr_foreign_toplevel {
pub mod __interfaces {
use wayland_client::protocol::__interfaces::*;
wayland_scanner::generate_interfaces!("src/wl-protocols/wlr-foreign-toplevel-management-unstable-v1.xml");
wayland_scanner::generate_interfaces!("src/watchers/wl-protocols/wlr-foreign-toplevel-management-unstable-v1.xml");
}
use self::__interfaces::*;
wayland_scanner::generate_client_code!("src/wl-protocols/wlr-foreign-toplevel-management-unstable-v1.xml");
wayland_scanner::generate_client_code!("src/watchers/wl-protocols/wlr-foreign-toplevel-management-unstable-v1.xml");
}

View File

@ -1,22 +1,19 @@
use std::collections::HashMap;
use std::{sync::Arc, thread};
use crate::{wl_connection::subscribe_state, Watcher};
use super::report_client::ReportClient;
use super::wl_bindings;
use super::wl_bindings::wlr_foreign_toplevel::zwlr_foreign_toplevel_handle_v1::{
Event as HandleEvent, State as HandleState, ZwlrForeignToplevelHandleV1,
};
use super::wl_bindings::wlr_foreign_toplevel::zwlr_foreign_toplevel_manager_v1::{
Event as ManagerEvent, ZwlrForeignToplevelManagerV1, EVT_TOPLEVEL_OPCODE,
};
use super::wl_connection::WlEventConnection;
use super::BoxedError;
use super::{wl_connection::subscribe_state, Watcher};
use crate::report_client::ReportClient;
use std::collections::HashMap;
use std::{sync::Arc, thread};
use wayland_client::{
event_created_child, globals::GlobalListContents, protocol::wl_registry, Connection, Dispatch,
Proxy, QueueHandle,
};
use wl_bindings::wlr_foreign_toplevel::zwlr_foreign_toplevel_handle_v1::{
Event as HandleEvent, State as HandleState, ZwlrForeignToplevelHandleV1,
};
use wl_bindings::wlr_foreign_toplevel::zwlr_foreign_toplevel_manager_v1::{
Event as ManagerEvent, ZwlrForeignToplevelManagerV1, EVT_TOPLEVEL_OPCODE,
};
struct WindowData {
app_id: String,

View File

@ -1,9 +1,8 @@
use crate::Watcher;
use super::report_client::ReportClient;
use super::wl_bindings;
use super::wl_connection::{subscribe_state, WlEventConnection};
use super::BoxedError;
use super::Watcher;
use crate::report_client::ReportClient;
use chrono::{DateTime, Duration, Utc};
use std::{sync::Arc, thread};
use wayland_client::{

View File

@ -1,9 +1,9 @@
use std::{sync::Arc, thread};
use super::{x11_connection::X11Connection, BoxedError, Watcher};
use crate::report_client::ReportClient;
use chrono::{Duration, Utc};
use crate::{report_client::ReportClient, x11_connection::X11Connection, BoxedError, Watcher};
pub struct IdleWatcher {
connection: X11Connection,
}

View File

@ -1,7 +1,7 @@
use super::{x11_connection::X11Connection, BoxedError, Watcher};
use crate::report_client::ReportClient;
use std::thread;
use crate::{report_client::ReportClient, x11_connection::X11Connection, BoxedError, Watcher};
pub struct WindowWatcher {
connection: X11Connection,
last_title: String,