mirror of
https://github.com/2e3s/awatcher.git
synced 2025-06-07 03:55:29 +00:00
Implement idle watcher for X11
This commit is contained in:
parent
65ce731f03
commit
5c1b98d75f
76
Cargo.lock
generated
76
Cargo.lock
generated
@ -194,7 +194,7 @@ source = "git+https://github.com/ActivityWatch/aw-server-rust#1f4f07d86c06de89de
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aw-models",
|
"aw-models",
|
||||||
"chrono",
|
"chrono",
|
||||||
"gethostname",
|
"gethostname 0.4.1",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -220,12 +220,13 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"fern",
|
"fern",
|
||||||
"gethostname",
|
"gethostname 0.4.1",
|
||||||
"log",
|
"log",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
|
"x11rb",
|
||||||
"zbus",
|
"zbus",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -713,6 +714,16 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -1008,6 +1019,15 @@ version = "2.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -1053,6 +1073,19 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.25.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"memoffset 0.6.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@ -1062,7 +1095,7 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset 0.7.1",
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
@ -1927,7 +1960,7 @@ dependencies = [
|
|||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"io-lifetimes",
|
"io-lifetimes",
|
||||||
"nix",
|
"nix 0.26.2",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
@ -1940,7 +1973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "85bde68449abab1a808e5227b6e295f4ae3680911eb7711b4a2cb90141edb780"
|
checksum = "85bde68449abab1a808e5227b6e295f4ae3680911eb7711b4a2cb90141edb780"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"nix",
|
"nix 0.26.2",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
]
|
]
|
||||||
@ -2002,6 +2035,15 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-wsapoll"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
@ -2188,6 +2230,28 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617"
|
||||||
|
dependencies = [
|
||||||
|
"gethostname 0.2.3",
|
||||||
|
"nix 0.25.1",
|
||||||
|
"winapi",
|
||||||
|
"winapi-wsapoll",
|
||||||
|
"x11rb-protocol",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11rb-protocol"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56"
|
||||||
|
dependencies = [
|
||||||
|
"nix 0.25.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "3.11.1"
|
version = "3.11.1"
|
||||||
@ -2211,7 +2275,7 @@ dependencies = [
|
|||||||
"futures-sink",
|
"futures-sink",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"nix",
|
"nix 0.26.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ordered-stream",
|
"ordered-stream",
|
||||||
"rand",
|
"rand",
|
||||||
|
@ -15,3 +15,4 @@ zbus = "3.11.1"
|
|||||||
clap = "4.2.1"
|
clap = "4.2.1"
|
||||||
log = { version = "0.4.17", features = ["std"] }
|
log = { version = "0.4.17", features = ["std"] }
|
||||||
fern = { version = "0.6.2", features = ["colored"] }
|
fern = { version = "0.6.2", features = ["colored"] }
|
||||||
|
x11rb = { version = "0.11.1", features = ["screensaver"] }
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::path::PathBuf;
|
use std::{path::PathBuf, time::Duration};
|
||||||
|
|
||||||
use clap::{arg, value_parser, Command};
|
use clap::{arg, value_parser, Command};
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub port: u32,
|
pub port: u32,
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub idle_timeout: u32,
|
pub idle_timeout: Duration,
|
||||||
pub poll_time_idle: u32,
|
pub poll_time_idle: Duration,
|
||||||
pub poll_time_window: u32,
|
pub poll_time_window: Duration,
|
||||||
pub idle_bucket_name: String,
|
pub idle_bucket_name: String,
|
||||||
pub active_window_bucket_name: String,
|
pub active_window_bucket_name: String,
|
||||||
}
|
}
|
||||||
@ -40,13 +40,16 @@ impl Config {
|
|||||||
let hostname = gethostname::gethostname().into_string().unwrap();
|
let hostname = gethostname::gethostname().into_string().unwrap();
|
||||||
let idle_bucket_name = format!("aw-watcher-afk_{hostname}");
|
let idle_bucket_name = format!("aw-watcher-afk_{hostname}");
|
||||||
let active_window_bucket_name = format!("aw-watcher-window_{hostname}");
|
let active_window_bucket_name = format!("aw-watcher-window_{hostname}");
|
||||||
|
let poll_seconds_idle = *matches.get_one::<u32>("poll-time-idle").unwrap();
|
||||||
|
let poll_seconds_window = *matches.get_one::<u32>("poll-time-window").unwrap();
|
||||||
|
let idle_timeout_seconds = *matches.get_one::<u32>("idle-timeout").unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
port: *matches.get_one("port").unwrap(),
|
port: *matches.get_one("port").unwrap(),
|
||||||
host: String::clone(matches.get_one("host").unwrap()),
|
host: String::clone(matches.get_one("host").unwrap()),
|
||||||
idle_timeout: *matches.get_one("idle-timeout").unwrap(),
|
idle_timeout: Duration::from_secs(u64::from(idle_timeout_seconds)),
|
||||||
poll_time_idle: *matches.get_one("poll-time-idle").unwrap(),
|
poll_time_idle: Duration::from_secs(u64::from(poll_seconds_idle)),
|
||||||
poll_time_window: *matches.get_one("poll-time-window").unwrap(),
|
poll_time_window: Duration::from_secs(u64::from(poll_seconds_window)),
|
||||||
idle_bucket_name,
|
idle_bucket_name,
|
||||||
active_window_bucket_name,
|
active_window_bucket_name,
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ use std::env::temp_dir;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::{mpsc::channel, Arc, Mutex};
|
use std::sync::{mpsc::channel, Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time;
|
|
||||||
use zbus::blocking::{Connection, ConnectionBuilder};
|
use zbus::blocking::{Connection, ConnectionBuilder};
|
||||||
use zbus::dbus_interface;
|
use zbus::dbus_interface;
|
||||||
|
|
||||||
@ -196,9 +195,7 @@ impl Watcher for WindowWatcher {
|
|||||||
if let Err(error) = send_active_window(client, &active_window) {
|
if let Err(error) = send_active_window(client, &active_window) {
|
||||||
error!("Error on sending active window heartbeat: {error}");
|
error!("Error on sending active window heartbeat: {error}");
|
||||||
}
|
}
|
||||||
thread::sleep(time::Duration::from_secs(u64::from(
|
thread::sleep(client.config.poll_time_window);
|
||||||
client.config.poll_time_window,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
src/main.rs
15
src/main.rs
@ -10,6 +10,7 @@ mod wl_bindings;
|
|||||||
mod wl_connection;
|
mod wl_connection;
|
||||||
mod wl_foreign_toplevel;
|
mod wl_foreign_toplevel;
|
||||||
mod wl_kwin_idle;
|
mod wl_kwin_idle;
|
||||||
|
mod x11_screensaver_idle;
|
||||||
|
|
||||||
use config::Config;
|
use config::Config;
|
||||||
use fern::colors::{Color, ColoredLevelConfig};
|
use fern::colors::{Color, ColoredLevelConfig};
|
||||||
@ -18,6 +19,7 @@ use report_client::ReportClient;
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::{error::Error, str::FromStr, sync::Arc, thread};
|
use std::{error::Error, str::FromStr, sync::Arc, thread};
|
||||||
use wl_kwin_idle::IdleWatcher as WlKwinIdleWatcher;
|
use wl_kwin_idle::IdleWatcher as WlKwinIdleWatcher;
|
||||||
|
use x11_screensaver_idle::IdleWatcher as X11IdleWatcher;
|
||||||
|
|
||||||
use crate::wl_foreign_toplevel::WindowWatcher as WlrForeignToplevelWindowWatcher;
|
use crate::wl_foreign_toplevel::WindowWatcher as WlrForeignToplevelWindowWatcher;
|
||||||
|
|
||||||
@ -59,7 +61,8 @@ macro_rules! watcher {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const IDLE_WATCHERS: &[WatcherConstructor] = &[watcher!(WlKwinIdleWatcher)];
|
const IDLE_WATCHERS: &[WatcherConstructor] =
|
||||||
|
&[watcher!(WlKwinIdleWatcher), watcher!(X11IdleWatcher)];
|
||||||
|
|
||||||
const ACTIVE_WINDOW_WATCHERS: &[WatcherConstructor] = &[
|
const ACTIVE_WINDOW_WATCHERS: &[WatcherConstructor] = &[
|
||||||
watcher!(WlrForeignToplevelWindowWatcher),
|
watcher!(WlrForeignToplevelWindowWatcher),
|
||||||
@ -103,8 +106,14 @@ fn main() -> Result<(), BoxedError> {
|
|||||||
"Sending to server {}:{}",
|
"Sending to server {}:{}",
|
||||||
client.config.host, client.config.port
|
client.config.host, client.config.port
|
||||||
);
|
);
|
||||||
info!("Idle timeout: {} seconds", client.config.idle_timeout);
|
info!(
|
||||||
info!("Polling period: {} seconds", client.config.poll_time_idle);
|
"Idle timeout: {} seconds",
|
||||||
|
client.config.idle_timeout.as_secs()
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"Polling period: {} seconds",
|
||||||
|
client.config.poll_time_idle.as_secs()
|
||||||
|
);
|
||||||
|
|
||||||
let mut thread_handlers = Vec::new();
|
let mut thread_handlers = Vec::new();
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ impl ReportClient {
|
|||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pulsetime = f64::from(self.config.idle_timeout + self.config.poll_time_idle);
|
let pulsetime = (self.config.idle_timeout + self.config.poll_time_idle).as_secs_f64();
|
||||||
self.client
|
self.client
|
||||||
.heartbeat(&self.config.idle_bucket_name, &event, pulsetime)
|
.heartbeat(&self.config.idle_bucket_name, &event, pulsetime)
|
||||||
.map_err(|_| "Failed to send heartbeat")?;
|
.map_err(|_| "Failed to send heartbeat")?;
|
||||||
@ -58,7 +58,7 @@ impl ReportClient {
|
|||||||
data,
|
data,
|
||||||
};
|
};
|
||||||
|
|
||||||
let interval_margin: f64 = f64::from(self.config.poll_time_idle + 1);
|
let interval_margin = self.config.poll_time_idle.as_secs_f64() + 1.0;
|
||||||
self.client
|
self.client
|
||||||
.heartbeat(
|
.heartbeat(
|
||||||
&self.config.active_window_bucket_name,
|
&self.config.active_window_bucket_name,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::{sync::Arc, thread, time};
|
use std::{sync::Arc, thread};
|
||||||
|
|
||||||
use crate::{wl_connection::subscribe_state, Watcher};
|
use crate::{wl_connection::subscribe_state, Watcher};
|
||||||
|
|
||||||
@ -160,9 +160,7 @@ impl Watcher for WindowWatcher {
|
|||||||
error!("Error on iteration: {e}");
|
error!("Error on iteration: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::sleep(time::Duration::from_secs(u64::from(
|
thread::sleep(client.config.poll_time_window);
|
||||||
client.config.poll_time_window,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ use super::wl_bindings;
|
|||||||
use super::wl_connection::{subscribe_state, WlEventConnection};
|
use super::wl_connection::{subscribe_state, WlEventConnection};
|
||||||
use super::BoxedError;
|
use super::BoxedError;
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{DateTime, Duration, Utc};
|
||||||
use std::{sync::Arc, thread, time};
|
use std::{sync::Arc, thread};
|
||||||
use wayland_client::{
|
use wayland_client::{
|
||||||
globals::GlobalListContents,
|
globals::GlobalListContents,
|
||||||
protocol::{wl_registry, wl_seat::WlSeat},
|
protocol::{wl_registry, wl_seat::WlSeat},
|
||||||
@ -131,9 +131,10 @@ impl Watcher for IdleWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn watch(&mut self, client: &Arc<ReportClient>) {
|
fn watch(&mut self, client: &Arc<ReportClient>) {
|
||||||
|
let timeout = u32::try_from(client.config.idle_timeout.as_secs() * 1000);
|
||||||
let mut idle_state = IdleState::new(
|
let mut idle_state = IdleState::new(
|
||||||
self.connection
|
self.connection
|
||||||
.get_kwin_idle_timeout(client.config.idle_timeout * 1000)
|
.get_kwin_idle_timeout(timeout.unwrap())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
Arc::clone(client),
|
Arc::clone(client),
|
||||||
);
|
);
|
||||||
@ -149,9 +150,7 @@ impl Watcher for IdleWatcher {
|
|||||||
} else if let Err(e) = idle_state.send_ping() {
|
} else if let Err(e) = idle_state.send_ping() {
|
||||||
error!("Error on idle iteration: {e}");
|
error!("Error on idle iteration: {e}");
|
||||||
}
|
}
|
||||||
thread::sleep(time::Duration::from_secs(u64::from(
|
thread::sleep(client.config.poll_time_idle);
|
||||||
client.config.poll_time_idle,
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
93
src/x11_screensaver_idle.rs
Normal file
93
src/x11_screensaver_idle.rs
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
use std::{env, sync::Arc, thread};
|
||||||
|
|
||||||
|
use chrono::{Duration, Utc};
|
||||||
|
use x11rb::connection::Connection;
|
||||||
|
use x11rb::protocol::screensaver::ConnectionExt;
|
||||||
|
use x11rb::rust_connection::RustConnection;
|
||||||
|
|
||||||
|
use crate::{report_client::ReportClient, BoxedError, Watcher};
|
||||||
|
|
||||||
|
pub struct IdleWatcher {
|
||||||
|
connection: RustConnection,
|
||||||
|
screen_root: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdleWatcher {
|
||||||
|
fn seconds_since_last_input(&self) -> Result<u32, BoxedError> {
|
||||||
|
let a = self.connection.screensaver_query_info(self.screen_root)?;
|
||||||
|
let b = a.reply()?;
|
||||||
|
|
||||||
|
Ok(b.ms_since_user_input / 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(&self, is_idle: bool, client: &Arc<ReportClient>) -> Result<bool, BoxedError> {
|
||||||
|
// The logic is rewritten from the original Python code:
|
||||||
|
// https://github.com/ActivityWatch/aw-watcher-afk/blob/ef531605cd8238e00138bbb980e5457054e05248/aw_watcher_afk/afk.py#L73
|
||||||
|
let duration_1ms: Duration = Duration::milliseconds(1);
|
||||||
|
let duration_zero: Duration = Duration::zero();
|
||||||
|
|
||||||
|
let seconds_since_input = self.seconds_since_last_input()?;
|
||||||
|
let now = Utc::now();
|
||||||
|
let time_since_input = Duration::seconds(i64::from(seconds_since_input));
|
||||||
|
let last_input = now - time_since_input;
|
||||||
|
let mut is_idle_again = is_idle;
|
||||||
|
|
||||||
|
if is_idle && u64::from(seconds_since_input) < client.config.idle_timeout.as_secs() {
|
||||||
|
debug!("No longer idle");
|
||||||
|
client.ping(is_idle, last_input, duration_zero)?;
|
||||||
|
is_idle_again = false;
|
||||||
|
// ping with timestamp+1ms with the next event (to ensure the latest event gets retrieved by get_event)
|
||||||
|
client.ping(is_idle, last_input + duration_1ms, duration_zero)?;
|
||||||
|
} else if !is_idle && u64::from(seconds_since_input) >= client.config.idle_timeout.as_secs()
|
||||||
|
{
|
||||||
|
debug!("Idle again");
|
||||||
|
client.ping(is_idle, last_input, duration_zero)?;
|
||||||
|
is_idle_again = true;
|
||||||
|
// ping with timestamp+1ms with the next event (to ensure the latest event gets retrieved by get_event)
|
||||||
|
client.ping(is_idle, last_input + duration_1ms, time_since_input)?;
|
||||||
|
} else {
|
||||||
|
// Send a heartbeat if no state change was made
|
||||||
|
if is_idle {
|
||||||
|
trace!("Reporting as idle");
|
||||||
|
client.ping(is_idle, last_input, time_since_input)?;
|
||||||
|
} else {
|
||||||
|
trace!("Reporting as not idle");
|
||||||
|
client.ping(is_idle, last_input, duration_zero)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(is_idle_again)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Watcher for IdleWatcher {
|
||||||
|
fn new() -> Result<Self, BoxedError> {
|
||||||
|
if env::var("DISPLAY").is_err() {
|
||||||
|
warn!("DISPLAY is not set, setting to the default value \":0\"");
|
||||||
|
env::set_var("DISPLAY", ":0");
|
||||||
|
}
|
||||||
|
|
||||||
|
let (connection, screen_num) = x11rb::connect(None)?;
|
||||||
|
let screen_root = connection.setup().roots[screen_num].root;
|
||||||
|
|
||||||
|
Ok(IdleWatcher {
|
||||||
|
connection,
|
||||||
|
screen_root,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn watch(&mut self, client: &Arc<ReportClient>) {
|
||||||
|
info!("Starting idle watcher");
|
||||||
|
let mut is_idle = false;
|
||||||
|
loop {
|
||||||
|
match self.run(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user