use windows::Win32::Foundation::HWND;
use super::types::FlowWM;
use crate::common::{InvisibleBounds, Rect};
use crate::registry::win32;
impl FlowWM {
pub fn rescue_stranded_windows(&self) {
let work_area = self.active_monitor().work_area();
let mut rescued = 0_usize;
for (hwnd_val, anchor, invisible_bounds) in self.registry.restorable_windows() {
let hwnd = HWND(hwnd_val as *mut _);
let Ok(current) = win32::get_window_rect(hwnd) else {
log::warn!("shutdown rescue: GetWindowRect failed for hwnd {hwnd_val}, skipping");
continue;
};
if content_overlaps_work_area(current, invisible_bounds, work_area) {
continue;
}
let target = anchor.clamped_into(work_area);
if win32::set_window_rect(hwnd_val, target.x, target.y, target.width, target.height) {
rescued += 1;
}
}
log::info!("shutdown rescue: brought {rescued} stranded window(s) back on-screen");
}
}
fn content_overlaps_work_area(window_rect: Rect, bounds: InvisibleBounds, work_area: Rect) -> bool {
bounds.window_to_visible(window_rect).overlaps(work_area)
}
#[cfg(test)]
mod tests {
use crate::common::{InvisibleBounds, Rect};
use super::content_overlaps_work_area;
const BOUNDS: InvisibleBounds = InvisibleBounds {
left: 7,
top: 0,
right: 7,
bottom: 7,
};
const WORK_AREA: Rect = Rect {
x: 0,
y: 0,
width: 1920,
height: 1040,
};
#[test]
fn parked_right_window_is_not_visible_despite_border_bleed() {
let window_rect = Rect {
x: 1913,
y: 0,
width: 974, height: 607,
};
assert!(!content_overlaps_work_area(window_rect, BOUNDS, WORK_AREA));
}
#[test]
fn parked_left_window_is_not_visible_despite_border_bleed() {
let window_rect = Rect {
x: -967,
y: 0,
width: 974,
height: 607,
};
assert!(!content_overlaps_work_area(window_rect, BOUNDS, WORK_AREA));
}
#[test]
fn genuinely_on_screen_window_is_visible() {
let visible = Rect {
x: 100,
y: 100,
width: 800,
height: 600,
};
let window_rect = BOUNDS.visible_to_window(visible);
assert!(content_overlaps_work_area(window_rect, BOUNDS, WORK_AREA));
}
#[test]
fn parked_flush_with_zero_bounds_is_not_visible() {
let window_rect = Rect {
x: 1920,
y: 0,
width: 960,
height: 600,
};
assert!(!content_overlaps_work_area(
window_rect,
InvisibleBounds::zero(),
WORK_AREA,
));
}
#[test]
fn inter_workspace_vertically_parked_window_is_not_visible() {
let visible_above = Rect {
x: 0,
y: -1040,
width: 960,
height: 600,
};
let window_rect = BOUNDS.visible_to_window(visible_above);
assert!(!content_overlaps_work_area(window_rect, BOUNDS, WORK_AREA));
}
}