diff options
Diffstat (limited to 'src/helpers/idle.rs')
-rw-r--r-- | src/helpers/idle.rs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/helpers/idle.rs b/src/helpers/idle.rs new file mode 100644 index 0000000..074eba9 --- /dev/null +++ b/src/helpers/idle.rs @@ -0,0 +1,120 @@ +// Furtherance - Track your time without being tracked +// Copyright (C) 2024 Ricky Kresslein <rk@unobserved.io> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +use std::env; +use std::time::Duration; + +#[cfg(target_os = "linux")] +use { + std::path::Path, std::sync::Arc +}; + +pub fn get_mac_windows_x11_idle_seconds() -> u64 { + 0 // unimplemented +} + +pub fn get_idle_time() -> Result<u64, Box<dyn std::error::Error>> { + match env::consts::OS { + "windows" => Ok(get_mac_windows_x11_idle_seconds()), + "macos" => Ok(get_mac_windows_x11_idle_seconds()), + #[cfg(target_os = "linux")] + "linux" => { + if is_wayland() { + if is_gnome() { + get_gnome_idle_sync() + } else { + get_wayland_idle_sync() + } + } else if is_x11() { + Ok(get_mac_windows_x11_idle_seconds()) + } else { + Ok(0) + } + } + _ => Ok(0), + } +} + +#[cfg(target_os = "linux")] +fn is_wayland() -> bool { + if let Ok(_) = env::var("XDG_SESSION_TYPE").map(|v| v == "wayland") { + return true; + } else if let Ok(display) = env::var("WAYLAND_DISPLAY") { + if display.chars().next() == Some('/') { + return Path::new(&display).exists(); + } + if let Ok(runtime_dir) = env::var("XDG_RUNTIME_DIR") { + return Path::new( + &format!("{}/{}", runtime_dir, display) + ).exists(); + } + } + false +} + +#[cfg(target_os = "linux")] +fn is_x11() -> bool { + x11rb::connect(None).is_ok() +} + +#[cfg(target_os = "linux")] +fn get_wayland_idle_sync() -> Result<u64, Box<dyn std::error::Error>> { + use crate::helpers::wayland_idle; + + wayland_idle::initialize_wayland().unwrap(); + + Ok(wayland_idle::get_idle_time()) +} + +#[cfg(target_os = "linux")] +fn get_gnome_idle_sync() -> Result<u64, Box<dyn std::error::Error>> { + use dbus::blocking::stdintf::org_freedesktop_dbus::Properties; + let c = dbus::blocking::Connection::new_session()?; + + let p = c.with_proxy( + "org.gnome.Mutter.IdleMonitor", + "/org/gnome/Mutter/IdleMonitor/Core", + Duration::from_millis(5000), + ); + let (idle_time,): (u64,) = + p.method_call("org.gnome.Mutter.IdleMonitor", "GetIdletime", ())?; + Ok(idle_time / 1000) +} + +#[cfg(target_os = "linux")] +pub fn is_kde() -> bool { + if let Ok(desktop) = std::env::var("XDG_CURRENT_DESKTOP") { + return desktop.to_uppercase().contains("KDE"); + } + false +} + +#[cfg(target_os = "linux")] +fn is_gnome() -> bool { + if let Ok(xdg_current_desktop) = env::var("XDG_CURRENT_DESKTOP") { + if xdg_current_desktop.to_lowercase().contains("gnome") { + return true; + } + } + + if let Ok(gdm_session) = env::var("GDMSESSION") { + if gdm_session.to_lowercase().contains("gnome") { + return true; + } + } + + false +} |