Harden window evidence adapters
This commit is contained in:
+36
-7
@@ -27,8 +27,12 @@ pub fn get_snapshot() -> WindowSnapshot {
|
|||||||
|
|
||||||
pub fn minimize_other(title: &str) {
|
pub fn minimize_other(title: &str) {
|
||||||
let window_info = get_window_info();
|
let window_info = get_window_info();
|
||||||
if &window_info.title != title {
|
if window_info.wid.is_empty() {
|
||||||
run(&format!("xdotool windowminimize {}", window_info.wid));
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if window_info.title != title {
|
||||||
|
run_xdotool(&["windowminimize", &window_info.wid]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,8 +42,12 @@ struct WindowInfo {
|
|||||||
wid: String,
|
wid: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(cmd: &str) -> Option<String> {
|
fn is_valid_window_id(wid: &str) -> bool {
|
||||||
let output = Command::new("sh").arg("-c").arg(cmd).output();
|
!wid.is_empty() && wid.bytes().all(|byte| byte.is_ascii_digit())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_xdotool(args: &[&str]) -> Option<String> {
|
||||||
|
let output = Command::new("xdotool").args(args).output();
|
||||||
|
|
||||||
let Ok(Output {
|
let Ok(Output {
|
||||||
status,
|
status,
|
||||||
@@ -68,17 +76,38 @@ fn get_window_info() -> WindowInfo {
|
|||||||
wid: "".to_string(),
|
wid: "".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(wid) = run("xdotool getactivewindow") else {
|
let Some(wid) = run_xdotool(&["getactivewindow"]) else {
|
||||||
return none;
|
return none;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(class) = run(&format!("xdotool getwindowclassname {wid}")) else {
|
if !is_valid_window_id(&wid) {
|
||||||
return none;
|
return none;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(title) = run(&format!("xdotool getwindowname {wid}")) else {
|
let Some(class) = run_xdotool(&["getwindowclassname", &wid]) else {
|
||||||
|
return none;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(title) = run_xdotool(&["getwindowname", &wid]) else {
|
||||||
return none;
|
return none;
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowInfo { title, class, wid }
|
WindowInfo { title, class, wid }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn valid_window_id_accepts_ascii_digits_only() {
|
||||||
|
assert!(is_valid_window_id("12345"));
|
||||||
|
assert!(is_valid_window_id("0"));
|
||||||
|
|
||||||
|
assert!(!is_valid_window_id(""));
|
||||||
|
assert!(!is_valid_window_id("12abc"));
|
||||||
|
assert!(!is_valid_window_id(" 123"));
|
||||||
|
assert!(!is_valid_window_id("123 "));
|
||||||
|
assert!(!is_valid_window_id("123"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+25
-5
@@ -10,19 +10,32 @@ pub fn get_title_clean() -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_snapshot() -> WindowSnapshot {
|
pub fn get_snapshot() -> WindowSnapshot {
|
||||||
let title = get_window_info().title;
|
let window_info = get_window_info();
|
||||||
|
if window_info.hwnd.is_null() {
|
||||||
|
return WindowSnapshot::unavailable("foreground window unavailable");
|
||||||
|
}
|
||||||
|
|
||||||
let re = Regex::new(r"-?\d+([:.]\d+)+%?").unwrap();
|
let re = Regex::new(r"-?\d+([:.]\d+)+%?").unwrap();
|
||||||
|
let title = re.replace_all(&window_info.title, "").to_string();
|
||||||
|
let health = if window_info.title.is_empty() {
|
||||||
|
EvidenceHealth::Degraded("foreground window title unavailable".to_string())
|
||||||
|
} else {
|
||||||
|
EvidenceHealth::Degraded("window class unavailable on current Windows adapter".to_string())
|
||||||
|
};
|
||||||
|
|
||||||
WindowSnapshot {
|
WindowSnapshot {
|
||||||
title: re.replace_all(&title, "").to_string(),
|
title,
|
||||||
class: None,
|
class: None,
|
||||||
health: EvidenceHealth::Degraded(
|
health,
|
||||||
"window class unavailable on current Windows adapter".to_string(),
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn minimize_other(title: &str) {
|
pub fn minimize_other(title: &str) {
|
||||||
let window_info = get_window_info();
|
let window_info = get_window_info();
|
||||||
|
if window_info.hwnd.is_null() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if window_info.title != title {
|
if window_info.title != title {
|
||||||
unsafe {
|
unsafe {
|
||||||
ShowWindow(window_info.hwnd, SW_MINIMIZE);
|
ShowWindow(window_info.hwnd, SW_MINIMIZE);
|
||||||
@@ -38,6 +51,13 @@ struct WindowInfo {
|
|||||||
fn get_window_info() -> WindowInfo {
|
fn get_window_info() -> WindowInfo {
|
||||||
unsafe {
|
unsafe {
|
||||||
let hwnd = GetForegroundWindow();
|
let hwnd = GetForegroundWindow();
|
||||||
|
if hwnd.is_null() {
|
||||||
|
return WindowInfo {
|
||||||
|
title: String::new(),
|
||||||
|
hwnd,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
let mut text: [u16; 512] = [0; 512];
|
let mut text: [u16; 512] = [0; 512];
|
||||||
let len = GetWindowTextW(hwnd, text.as_mut_ptr(), text.len() as i32) as usize;
|
let len = GetWindowTextW(hwnd, text.as_mut_ptr(), text.len() as i32) as usize;
|
||||||
let title = OsString::from_wide(&text[..len])
|
let title = OsString::from_wide(&text[..len])
|
||||||
|
|||||||
Reference in New Issue
Block a user