mirror of
https://github.com/2e3s/awatcher.git
synced 2025-06-06 11:35:46 +00:00
Refactor to use common watchers loop
This commit is contained in:
parent
cdc05e0d5f
commit
79f8e53850
@ -13,54 +13,113 @@ mod x11_connection;
|
||||
mod x11_screensaver_idle;
|
||||
mod x11_window;
|
||||
|
||||
use crate::report_client::ReportClient;
|
||||
use crate::{config::Config, report_client::ReportClient};
|
||||
use std::{
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
fmt::Display,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
thread::{self, JoinHandle},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
pub enum WatcherType {
|
||||
Idle,
|
||||
ActiveWindow,
|
||||
}
|
||||
|
||||
impl WatcherType {
|
||||
fn sleep_time(&self, config: &Config) -> Duration {
|
||||
match self {
|
||||
WatcherType::Idle => config.poll_time_idle,
|
||||
WatcherType::ActiveWindow => config.poll_time_idle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Watcher: Send {
|
||||
fn new() -> anyhow::Result<Self>
|
||||
fn new(client: &Arc<ReportClient>) -> anyhow::Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>);
|
||||
|
||||
fn run(
|
||||
&mut self,
|
||||
watcher_type: &WatcherType,
|
||||
client: &Arc<ReportClient>,
|
||||
is_stopped: Arc<AtomicBool>,
|
||||
) {
|
||||
info!("Starting {watcher_type} watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down {watcher_type}");
|
||||
break;
|
||||
}
|
||||
self.run_iteration(client);
|
||||
thread::sleep(watcher_type.sleep_time(&client.config));
|
||||
}
|
||||
}
|
||||
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>);
|
||||
}
|
||||
|
||||
type BoxedWatcher = Box<dyn Watcher>;
|
||||
|
||||
type WatcherConstructor = (&'static str, fn() -> anyhow::Result<BoxedWatcher>);
|
||||
type WatcherConstructors = [WatcherConstructor];
|
||||
type WatcherConstructors = [(
|
||||
&'static str,
|
||||
WatcherType,
|
||||
fn(&Arc<ReportClient>) -> anyhow::Result<BoxedWatcher>,
|
||||
)];
|
||||
|
||||
pub trait ConstructorFilter {
|
||||
fn filter_first_supported(&self) -> Option<BoxedWatcher>;
|
||||
fn filter_first_supported(
|
||||
&self,
|
||||
client: &Arc<ReportClient>,
|
||||
) -> Option<(&WatcherType, BoxedWatcher)>;
|
||||
|
||||
fn run_first_supported(
|
||||
&self,
|
||||
&'static self,
|
||||
client: &Arc<ReportClient>,
|
||||
is_stopped: Arc<AtomicBool>,
|
||||
) -> Option<JoinHandle<()>>;
|
||||
}
|
||||
|
||||
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) => {
|
||||
debug!("{name} cannot run: {e}");
|
||||
None
|
||||
}
|
||||
})
|
||||
fn filter_first_supported(
|
||||
&self,
|
||||
client: &Arc<ReportClient>,
|
||||
) -> Option<(&WatcherType, BoxedWatcher)> {
|
||||
self.iter()
|
||||
.find_map(|(name, watcher_type, watcher)| match watcher(client) {
|
||||
Ok(watcher) => {
|
||||
info!("Selected {name} as {watcher_type} watcher");
|
||||
Some((watcher_type, watcher))
|
||||
}
|
||||
Err(e) => {
|
||||
debug!("{name} cannot run: {e}");
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn run_first_supported(
|
||||
&self,
|
||||
&'static self,
|
||||
client: &Arc<ReportClient>,
|
||||
is_stopped: Arc<AtomicBool>,
|
||||
) -> Option<JoinHandle<()>> {
|
||||
let idle_watcher = self.filter_first_supported();
|
||||
if let Some(mut watcher) = idle_watcher {
|
||||
let idle_watcher = self.filter_first_supported(client);
|
||||
if let Some((watcher_type, mut watcher)) = idle_watcher {
|
||||
let thread_client = Arc::clone(client);
|
||||
let idle_handler = thread::spawn(move || watcher.watch(&thread_client, is_stopped));
|
||||
let idle_handler =
|
||||
thread::spawn(move || watcher.run(watcher_type, &thread_client, is_stopped));
|
||||
Some(idle_handler)
|
||||
} else {
|
||||
None
|
||||
@ -69,26 +128,29 @@ impl ConstructorFilter for WatcherConstructors {
|
||||
}
|
||||
|
||||
macro_rules! watcher {
|
||||
($watcher_struct:ty) => {
|
||||
(stringify!($watcher_struct), || {
|
||||
Ok(Box::new(<$watcher_struct>::new()?))
|
||||
($watcher_struct:ty, $watcher_type:expr) => {
|
||||
(stringify!($watcher_struct), $watcher_type, |client| {
|
||||
Ok(Box::new(<$watcher_struct>::new(client)?))
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
pub const IDLE: &WatcherConstructors = &[
|
||||
watcher!(wl_kwin_idle::IdleWatcher),
|
||||
watcher!(x11_screensaver_idle::IdleWatcher),
|
||||
watcher!(wl_kwin_idle::IdleWatcher, WatcherType::Idle),
|
||||
watcher!(x11_screensaver_idle::IdleWatcher, WatcherType::Idle),
|
||||
#[cfg(feature = "gnome")]
|
||||
watcher!(gnome_idle::IdleWatcher),
|
||||
watcher!(gnome_idle::IdleWatcher, WatcherType::Idle),
|
||||
];
|
||||
|
||||
pub const ACTIVE_WINDOW: &WatcherConstructors = &[
|
||||
watcher!(wl_foreign_toplevel::WindowWatcher),
|
||||
watcher!(
|
||||
wl_foreign_toplevel::WindowWatcher,
|
||||
WatcherType::ActiveWindow
|
||||
),
|
||||
// XWayland gives _NET_WM_NAME on some windows in KDE, but not on others
|
||||
#[cfg(feature = "kwin_window")]
|
||||
watcher!(kwin_window::WindowWatcher),
|
||||
watcher!(x11_window::WindowWatcher),
|
||||
watcher!(kwin_window::WindowWatcher, WatcherType::ActiveWindow),
|
||||
watcher!(x11_window::WindowWatcher, WatcherType::ActiveWindow),
|
||||
#[cfg(feature = "gnome")]
|
||||
watcher!(gnome_window::WindowWatcher),
|
||||
watcher!(gnome_window::WindowWatcher, WatcherType::ActiveWindow),
|
||||
];
|
||||
|
@ -1,13 +1,12 @@
|
||||
use super::{idle, Watcher};
|
||||
use crate::report_client::ReportClient;
|
||||
use anyhow::Context;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use zbus::blocking::Connection;
|
||||
|
||||
pub struct IdleWatcher {
|
||||
dbus_connection: Connection,
|
||||
is_idle: bool,
|
||||
}
|
||||
|
||||
impl idle::SinceLastInput for IdleWatcher {
|
||||
@ -27,30 +26,22 @@ impl idle::SinceLastInput for IdleWatcher {
|
||||
}
|
||||
|
||||
impl Watcher for IdleWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut watcher = Self {
|
||||
dbus_connection: Connection::session()?,
|
||||
is_idle: false,
|
||||
};
|
||||
idle::SinceLastInput::seconds_since_input(&mut watcher)?;
|
||||
|
||||
Ok(watcher)
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
let mut is_idle = false;
|
||||
info!("Starting idle watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
match idle::ping_since_last_input(self, self.is_idle, client) {
|
||||
Ok(is_idle_again) => {
|
||||
self.is_idle = is_idle_again;
|
||||
}
|
||||
match idle::ping_since_last_input(self, is_idle, client) {
|
||||
Ok(is_idle_again) => {
|
||||
is_idle = is_idle_again;
|
||||
}
|
||||
Err(e) => error!("Error on idle iteration: {e}"),
|
||||
};
|
||||
thread::sleep(client.config.poll_time_idle);
|
||||
}
|
||||
Err(e) => error!("Error on idle iteration: {e}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
use crate::report_client::ReportClient;
|
||||
use anyhow::Context;
|
||||
use serde::Deserialize;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use zbus::blocking::Connection;
|
||||
|
||||
use super::Watcher;
|
||||
@ -77,7 +75,7 @@ impl WindowWatcher {
|
||||
}
|
||||
|
||||
impl Watcher for WindowWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let watcher = Self {
|
||||
dbus_connection: Connection::session()?,
|
||||
last_app_id: String::new(),
|
||||
@ -87,17 +85,9 @@ impl Watcher for WindowWatcher {
|
||||
Ok(watcher)
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
info!("Starting active window watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
}
|
||||
if let Err(error) = self.send_active_window(client) {
|
||||
error!("Error on active window: {error}");
|
||||
}
|
||||
thread::sleep(client.config.poll_time_window);
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
if let Err(error) = self.send_active_window(client) {
|
||||
error!("Error on active window: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ use crate::report_client::ReportClient;
|
||||
use anyhow::{anyhow, Context};
|
||||
use std::env::temp_dir;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{mpsc::channel, Arc, Mutex};
|
||||
use std::thread;
|
||||
use zbus::blocking::{Connection, ConnectionBuilder};
|
||||
@ -151,22 +150,19 @@ impl ActiveWindowInterface {
|
||||
}
|
||||
|
||||
pub struct WindowWatcher {
|
||||
kwin_script: KWinScript,
|
||||
active_window: Arc<Mutex<ActiveWindow>>,
|
||||
// Prolong its lifetime
|
||||
_kwin_script: KWinScript,
|
||||
}
|
||||
|
||||
impl Watcher for WindowWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
let kwin_script = KWinScript::new(Connection::session()?);
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut kwin_script = KWinScript::new(Connection::session()?);
|
||||
if kwin_script.is_loaded()? {
|
||||
debug!("KWin script is already loaded, unloading");
|
||||
kwin_script.unload()?;
|
||||
}
|
||||
|
||||
Ok(Self { kwin_script })
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
self.kwin_script.load().unwrap();
|
||||
kwin_script.load().unwrap();
|
||||
|
||||
let active_window = Arc::new(Mutex::new(ActiveWindow {
|
||||
caption: String::new(),
|
||||
@ -199,16 +195,15 @@ impl Watcher for WindowWatcher {
|
||||
panic!("Failed to run a DBus interface: {error}");
|
||||
}
|
||||
|
||||
info!("Starting active window watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
}
|
||||
if let Err(error) = send_active_window(client, &active_window) {
|
||||
error!("Error on sending active window: {error}");
|
||||
}
|
||||
thread::sleep(client.config.poll_time_window);
|
||||
Ok(Self {
|
||||
active_window,
|
||||
_kwin_script: kwin_script,
|
||||
})
|
||||
}
|
||||
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
if let Err(error) = send_active_window(client, &self.active_window) {
|
||||
error!("Error on sending active window: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,7 @@ use super::{wl_connection::subscribe_state, Watcher};
|
||||
use crate::report_client::ReportClient;
|
||||
use anyhow::{anyhow, Context};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{sync::Arc, thread};
|
||||
use std::sync::Arc;
|
||||
use wayland_client::{
|
||||
event_created_child, globals::GlobalListContents, protocol::wl_registry, Connection, Dispatch,
|
||||
Proxy, QueueHandle,
|
||||
@ -24,15 +23,13 @@ struct WindowData {
|
||||
struct ToplevelState {
|
||||
windows: HashMap<String, WindowData>,
|
||||
current_window_id: Option<String>,
|
||||
client: Arc<ReportClient>,
|
||||
}
|
||||
|
||||
impl ToplevelState {
|
||||
fn new(client: Arc<ReportClient>) -> Self {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
windows: HashMap::new(),
|
||||
current_window_id: None,
|
||||
client,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -114,55 +111,59 @@ impl Dispatch<ZwlrForeignToplevelHandleV1, ()> for ToplevelState {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToplevelState {
|
||||
fn send_active_window(&self) -> anyhow::Result<()> {
|
||||
pub struct WindowWatcher {
|
||||
connection: WlEventConnection<ToplevelState>,
|
||||
toplevel_state: ToplevelState,
|
||||
}
|
||||
|
||||
impl WindowWatcher {
|
||||
fn send_active_window(&self, client: &Arc<ReportClient>) -> anyhow::Result<()> {
|
||||
let active_window_id = self
|
||||
.toplevel_state
|
||||
.current_window_id
|
||||
.as_ref()
|
||||
.ok_or(anyhow!("Current window is unknown"))?;
|
||||
let active_window = self.windows.get(active_window_id).ok_or(anyhow!(
|
||||
"Current window is not found by ID {active_window_id}"
|
||||
))?;
|
||||
let active_window = self
|
||||
.toplevel_state
|
||||
.windows
|
||||
.get(active_window_id)
|
||||
.ok_or(anyhow!(
|
||||
"Current window is not found by ID {active_window_id}"
|
||||
))?;
|
||||
|
||||
self.client
|
||||
client
|
||||
.send_active_window(&active_window.app_id, &active_window.title)
|
||||
.with_context(|| "Failed to send heartbeat for active window")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WindowWatcher {
|
||||
connection: WlEventConnection<ToplevelState>,
|
||||
}
|
||||
|
||||
impl Watcher for WindowWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
let connection: WlEventConnection<ToplevelState> = WlEventConnection::connect()?;
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut connection: WlEventConnection<ToplevelState> = WlEventConnection::connect()?;
|
||||
connection.get_foreign_toplevel_manager()?;
|
||||
|
||||
Ok(Self { connection })
|
||||
}
|
||||
let mut toplevel_state = ToplevelState::new();
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
let mut toplevel_state = ToplevelState::new(Arc::clone(client));
|
||||
|
||||
self.connection
|
||||
connection
|
||||
.event_queue
|
||||
.roundtrip(&mut toplevel_state)
|
||||
.unwrap();
|
||||
|
||||
info!("Starting wlr foreign toplevel watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
}
|
||||
if let Err(e) = self.connection.event_queue.roundtrip(&mut toplevel_state) {
|
||||
error!("Event queue is not processed: {e}");
|
||||
} else if let Err(e) = toplevel_state.send_active_window() {
|
||||
error!("Error on iteration: {e}");
|
||||
}
|
||||
Ok(Self {
|
||||
connection,
|
||||
toplevel_state,
|
||||
})
|
||||
}
|
||||
|
||||
thread::sleep(client.config.poll_time_window);
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
if let Err(e) = self
|
||||
.connection
|
||||
.event_queue
|
||||
.roundtrip(&mut self.toplevel_state)
|
||||
{
|
||||
error!("Event queue is not processed: {e}");
|
||||
} else if let Err(e) = self.send_active_window(client) {
|
||||
error!("Error on iteration: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ use super::wl_connection::{subscribe_state, WlEventConnection};
|
||||
use super::Watcher;
|
||||
use crate::report_client::ReportClient;
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::{sync::Arc, thread};
|
||||
use std::sync::Arc;
|
||||
use wayland_client::{
|
||||
globals::GlobalListContents,
|
||||
protocol::{wl_registry, wl_seat::WlSeat},
|
||||
@ -20,7 +19,6 @@ struct IdleState {
|
||||
last_input_time: DateTime<Utc>,
|
||||
is_idle: bool,
|
||||
is_changed: bool,
|
||||
client: Arc<ReportClient>,
|
||||
}
|
||||
|
||||
impl Drop for IdleState {
|
||||
@ -31,13 +29,12 @@ impl Drop for IdleState {
|
||||
}
|
||||
|
||||
impl IdleState {
|
||||
fn new(idle_timeout: OrgKdeKwinIdleTimeout, client: Arc<ReportClient>) -> Self {
|
||||
fn new(idle_timeout: OrgKdeKwinIdleTimeout) -> Self {
|
||||
Self {
|
||||
idle_timeout,
|
||||
last_input_time: Utc::now(),
|
||||
is_idle: false,
|
||||
is_changed: false,
|
||||
client,
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,7 +51,7 @@ impl IdleState {
|
||||
debug!("Resumed");
|
||||
}
|
||||
|
||||
fn send_ping(&mut self) -> anyhow::Result<()> {
|
||||
fn send_ping(&mut self, client: &Arc<ReportClient>) -> anyhow::Result<()> {
|
||||
let now = Utc::now();
|
||||
if !self.is_idle {
|
||||
self.last_input_time = now;
|
||||
@ -63,9 +60,8 @@ impl IdleState {
|
||||
if self.is_changed {
|
||||
let result = if self.is_idle {
|
||||
debug!("Reporting as changed to idle");
|
||||
self.client
|
||||
.ping(false, self.last_input_time, Duration::zero())?;
|
||||
self.client.ping(
|
||||
client.ping(false, self.last_input_time, Duration::zero())?;
|
||||
client.ping(
|
||||
true,
|
||||
self.last_input_time + Duration::milliseconds(1),
|
||||
Duration::zero(),
|
||||
@ -73,9 +69,8 @@ impl IdleState {
|
||||
} else {
|
||||
debug!("Reporting as no longer idle");
|
||||
|
||||
self.client
|
||||
.ping(true, self.last_input_time, Duration::zero())?;
|
||||
self.client.ping(
|
||||
client.ping(true, self.last_input_time, Duration::zero())?;
|
||||
client.ping(
|
||||
false,
|
||||
self.last_input_time + Duration::milliseconds(1),
|
||||
Duration::zero(),
|
||||
@ -85,12 +80,10 @@ impl IdleState {
|
||||
result
|
||||
} else if self.is_idle {
|
||||
trace!("Reporting as idle");
|
||||
self.client
|
||||
.ping(true, self.last_input_time, now - self.last_input_time)
|
||||
client.ping(true, self.last_input_time, now - self.last_input_time)
|
||||
} else {
|
||||
trace!("Reporting as not idle");
|
||||
self.client
|
||||
.ping(false, self.last_input_time, Duration::zero())
|
||||
client.ping(false, self.last_input_time, Duration::zero())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,41 +112,30 @@ impl Dispatch<OrgKdeKwinIdleTimeout, ()> for IdleState {
|
||||
|
||||
pub struct IdleWatcher {
|
||||
connection: WlEventConnection<IdleState>,
|
||||
idle_state: IdleState,
|
||||
}
|
||||
|
||||
impl Watcher for IdleWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
let connection: WlEventConnection<IdleState> = WlEventConnection::connect()?;
|
||||
fn new(client: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut connection: WlEventConnection<IdleState> = WlEventConnection::connect()?;
|
||||
connection.get_kwin_idle()?;
|
||||
|
||||
Ok(Self { connection })
|
||||
let timeout = u32::try_from(client.config.idle_timeout.as_secs() * 1000);
|
||||
let mut idle_state =
|
||||
IdleState::new(connection.get_kwin_idle_timeout(timeout.unwrap()).unwrap());
|
||||
connection.event_queue.roundtrip(&mut idle_state).unwrap();
|
||||
|
||||
Ok(Self {
|
||||
connection,
|
||||
idle_state,
|
||||
})
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
let timeout = u32::try_from(client.config.idle_timeout.as_secs() * 1000);
|
||||
let mut idle_state = IdleState::new(
|
||||
self.connection
|
||||
.get_kwin_idle_timeout(timeout.unwrap())
|
||||
.unwrap(),
|
||||
Arc::clone(client),
|
||||
);
|
||||
self.connection
|
||||
.event_queue
|
||||
.roundtrip(&mut idle_state)
|
||||
.unwrap();
|
||||
|
||||
info!("Starting idle watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
}
|
||||
if let Err(e) = self.connection.event_queue.roundtrip(&mut idle_state) {
|
||||
error!("Event queue is not processed: {e}");
|
||||
} else if let Err(e) = idle_state.send_ping() {
|
||||
error!("Error on idle iteration: {e}");
|
||||
}
|
||||
thread::sleep(client.config.poll_time_idle);
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
if let Err(e) = self.connection.event_queue.roundtrip(&mut self.idle_state) {
|
||||
error!("Event queue is not processed: {e}");
|
||||
} else if let Err(e) = self.idle_state.send_ping(client) {
|
||||
error!("Error on idle iteration: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
use super::{idle, x11_connection::X11Client, Watcher};
|
||||
use crate::report_client::ReportClient;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
pub struct IdleWatcher {
|
||||
client: X11Client,
|
||||
is_idle: bool,
|
||||
}
|
||||
|
||||
impl idle::SinceLastInput for IdleWatcher {
|
||||
@ -15,31 +14,24 @@ impl idle::SinceLastInput for IdleWatcher {
|
||||
}
|
||||
|
||||
impl Watcher for IdleWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut client = X11Client::new()?;
|
||||
|
||||
// Check if screensaver extension is supported
|
||||
client.seconds_since_last_input()?;
|
||||
|
||||
Ok(IdleWatcher { client })
|
||||
Ok(IdleWatcher {
|
||||
client,
|
||||
is_idle: false,
|
||||
})
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
info!("Starting idle watcher");
|
||||
let mut is_idle = false;
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
match idle::ping_since_last_input(self, self.is_idle, client) {
|
||||
Ok(is_idle_again) => {
|
||||
self.is_idle = is_idle_again;
|
||||
}
|
||||
match idle::ping_since_last_input(self, is_idle, client) {
|
||||
Ok(is_idle_again) => {
|
||||
is_idle = is_idle_again;
|
||||
}
|
||||
Err(e) => error!("Error on idle iteration: {e}"),
|
||||
};
|
||||
|
||||
thread::sleep(client.config.poll_time_idle);
|
||||
}
|
||||
Err(e) => error!("Error on idle iteration: {e}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,7 @@
|
||||
use super::{x11_connection::X11Client, Watcher};
|
||||
use crate::report_client::ReportClient;
|
||||
use anyhow::Context;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
|
||||
pub struct WindowWatcher {
|
||||
client: X11Client,
|
||||
@ -31,7 +29,7 @@ impl WindowWatcher {
|
||||
}
|
||||
|
||||
impl Watcher for WindowWatcher {
|
||||
fn new() -> anyhow::Result<Self> {
|
||||
fn new(_: &Arc<ReportClient>) -> anyhow::Result<Self> {
|
||||
let mut client = X11Client::new()?;
|
||||
client.active_window_data()?;
|
||||
|
||||
@ -42,18 +40,9 @@ impl Watcher for WindowWatcher {
|
||||
})
|
||||
}
|
||||
|
||||
fn watch(&mut self, client: &Arc<ReportClient>, is_stopped: Arc<AtomicBool>) {
|
||||
info!("Starting active window watcher");
|
||||
loop {
|
||||
if is_stopped.load(Ordering::Relaxed) {
|
||||
warn!("Received an exit signal, shutting down");
|
||||
break;
|
||||
}
|
||||
if let Err(error) = self.send_active_window(client) {
|
||||
error!("Error on sending active window: {error}");
|
||||
}
|
||||
|
||||
thread::sleep(client.config.poll_time_window);
|
||||
fn run_iteration(&mut self, client: &Arc<ReportClient>) {
|
||||
if let Err(error) = self.send_active_window(client) {
|
||||
error!("Error on sending active window: {error}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user