diff --git a/glock-d/Cargo.toml b/glock-d/Cargo.toml index 690d0e4..b30e4e9 100644 --- a/glock-d/Cargo.toml +++ b/glock-d/Cargo.toml @@ -6,3 +6,4 @@ description = "Screen idle time tracker daemon for glock screenlock" [dependencies] glock-conf = { version = "0.1.0", path = "../glock-conf" } +x11rb = { version = "0.13.2", features = ["screensaver"] } diff --git a/glock-d/src/main.rs b/glock-d/src/main.rs index e7a11a9..7c8a477 100644 --- a/glock-d/src/main.rs +++ b/glock-d/src/main.rs @@ -1,3 +1,54 @@ -fn main() { - println!("Hello, world!"); +// Screen idle timeout daemon that triggers the screen locker. +// +// This daemon runs continuously, queries the X server for global +// user idle time, and triggers the screen locker once the idle +// timeout is exceeded. + +use std::thread; +use std::time::Duration; + +use x11rb::connection::Connection; +use x11rb::protocol::screensaver; + +fn main() -> Result<(), Box> { + // Daemon entry point. + // For now, this only prints when the screen should be locked. + println!("glock-d: starting idle tracker daemon"); + + // Hard-coded idle timeout in milliseconds. + // This will later be loaded from the config crate. + let idle_timeout_ms: u64 = 60_000; + + // Interval between idle checks. + // Short enough to feel responsive, long enough to stay efficient. + let poll_interval = Duration::from_millis(500); + + // Connect to the X server using the default display. + // The screen number is required to access the root window. + let (conn, screen_num) = x11rb::connect(None)?; + + // The root window represents the entire screen. + // XScreenSaver reports idle time relative to this window. + let root = conn.setup().roots[screen_num].root; + + // Main daemon loop. + // This loop runs forever unless the process is terminated. + loop { + // Sleep before querying to avoid busy-looping and CPU waste. + thread::sleep(poll_interval); + + // Query the XScreenSaver extension for idle information. + // The value returned is milliseconds since last keyboard or mouse input. + let reply = screensaver::query_info(&conn, root)?.reply()?; + let idle_ms = u64::from(reply.ms_since_user_input); + + // If the user has been idle longer than the timeout, + // trigger the screen lock. + if idle_ms >= idle_timeout_ms { + // Placeholder for the real locker invocation. + // In the final version, this will spawn the glock locker + // and wait for it to exit before continuing. + println!("screen lock"); + } + } }