use windows::Win32::Foundation::{HWND, RECT};
use windows::Win32::Graphics::Dwm::DwmFlush;
use windows::Win32::UI::WindowsAndMessaging::{
GetWindowRect, SWP_NOACTIVATE, SWP_NOZORDER, SetWindowPos,
};
use crate::animation::backend::WindowBackend;
use crate::animation::types::{AnimationError, Rect, Result, WindowRef};
#[allow(dead_code)] pub struct Win32Backend;
#[allow(dead_code)] impl Win32Backend {
pub fn new() -> Self {
Self
}
}
impl Default for Win32Backend {
fn default() -> Self {
Self::new()
}
}
impl WindowBackend for Win32Backend {
fn get_window_rect(&self, window: WindowRef) -> Result<Rect> {
let mut rect = RECT::default();
unsafe { GetWindowRect(HWND(window.0 as _), &mut rect) }
.map_err(|e| AnimationError::Backend(e.message().to_string()))?;
Ok(Rect {
x: rect.left,
y: rect.top,
w: rect.right - rect.left,
h: rect.bottom - rect.top,
})
}
fn apply_batch(&self, updates: &[(WindowRef, Rect)]) -> Result<()> {
if updates.is_empty() {
return Ok(());
}
let mut first_error = None;
for (window, rect) in updates {
let result = unsafe {
SetWindowPos(
HWND(window.0 as _),
None, rect.x,
rect.y,
rect.w,
rect.h,
SWP_NOZORDER | SWP_NOACTIVATE,
)
};
if let Err(e) = result {
log::warn!("SetWindowPos failed for window {:?}: {e}", window);
if first_error.is_none() {
first_error = Some(e);
}
}
}
match first_error {
Some(e) => Err(AnimationError::Backend(e.message().to_string())),
None => Ok(()),
}
}
fn dwm_flush(&self) -> Result<()> {
unsafe { DwmFlush() }.map_err(|e| AnimationError::Backend(e.message().to_string()))
}
}