diff --git a/src/window/linux.rs b/src/window/linux.rs index 2ebd90d..3d6e6a6 100644 --- a/src/window/linux.rs +++ b/src/window/linux.rs @@ -1,10 +1,28 @@ +use super::WindowSnapshot; +use crate::domain::EvidenceHealth; use regex::Regex; use std::{process::Command, process::Output, str}; pub fn get_title_clean() -> String { - let title = get_window_info().title; + get_snapshot().title +} + +pub fn get_snapshot() -> WindowSnapshot { + let window_info = get_window_info(); let re = Regex::new(r"-?\d+([:.]\d+)+%?").unwrap(); - re.replace_all(&title, "").to_string() + let title = re.replace_all(&window_info.title, "").to_string(); + let class = (window_info.class != "none").then_some(window_info.class); + let health = if window_info.wid.is_empty() { + EvidenceHealth::Unavailable("xdotool active window unavailable".to_string()) + } else { + EvidenceHealth::Available + }; + + WindowSnapshot { + title, + class, + health, + } } pub fn minimize_other(title: &str) { @@ -16,7 +34,7 @@ pub fn minimize_other(title: &str) { struct WindowInfo { title: String, - _class: String, + class: String, wid: String, } @@ -46,7 +64,7 @@ fn run(cmd: &str) -> Option { fn get_window_info() -> WindowInfo { let none = WindowInfo { title: "none".to_string(), - _class: "none".to_string(), + class: "none".to_string(), wid: "".to_string(), }; @@ -62,9 +80,5 @@ fn get_window_info() -> WindowInfo { return none; }; - WindowInfo { - title, - _class: class, - wid, - } + WindowInfo { title, class, wid } } diff --git a/src/window/mod.rs b/src/window/mod.rs index 1d44178..f28e785 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -1,3 +1,22 @@ +use crate::domain::EvidenceHealth; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct WindowSnapshot { + pub title: String, + pub class: Option, + pub health: EvidenceHealth, +} + +impl WindowSnapshot { + pub fn unavailable(reason: impl Into) -> Self { + Self { + title: "none".to_string(), + class: None, + health: EvidenceHealth::Unavailable(reason.into()), + } + } +} + #[cfg(target_os = "windows")] mod windows; #[cfg(target_os = "windows")] @@ -7,3 +26,20 @@ pub use windows::*; mod linux; #[cfg(target_os = "linux")] pub use linux::*; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn unavailable_snapshot_records_reason_without_evidence() { + assert_eq!( + WindowSnapshot::unavailable("no active window"), + WindowSnapshot { + title: "none".to_string(), + class: None, + health: EvidenceHealth::Unavailable("no active window".to_string()), + } + ); + } +} diff --git a/src/window/windows.rs b/src/window/windows.rs index e79dd8e..651ec07 100644 --- a/src/window/windows.rs +++ b/src/window/windows.rs @@ -1,12 +1,24 @@ +use super::WindowSnapshot; +use crate::domain::EvidenceHealth; use regex::Regex; use std::{ffi::OsString, os::windows::ffi::OsStringExt}; use winapi::shared::windef::HWND; use winapi::um::winuser::{GetForegroundWindow, GetWindowTextW, ShowWindow, SW_MINIMIZE}; pub fn get_title_clean() -> String { + get_snapshot().title +} + +pub fn get_snapshot() -> WindowSnapshot { let title = get_window_info().title; let re = Regex::new(r"-?\d+([:.]\d+)+%?").unwrap(); - re.replace_all(&title, "").to_string() + WindowSnapshot { + title: re.replace_all(&title, "").to_string(), + class: None, + health: EvidenceHealth::Degraded( + "window class unavailable on current Windows adapter".to_string(), + ), + } } pub fn minimize_other(title: &str) {