use tracing::{debug, trace, warn};
use windows::Win32::Foundation::RECT;
use crate::ecs::window::DpiSuggestedRectPolicy;
use crate::ecs::{Point, SizeI};
pub(super) fn dpi_suggested_position_decision(
policy: Option<&DpiSuggestedRectPolicy>,
suggested: &RECT,
) -> Option<(i32, i32)> {
match policy {
None | Some(DpiSuggestedRectPolicy::ApplyPosition) => Some((suggested.left, suggested.top)),
Some(DpiSuggestedRectPolicy::ExternalAuthority) => None,
}
}
fn calculate_physical_size_from_box_style(
box_style: &crate::ecs::layout::BoxStyle,
dpi: &crate::ecs::window::DPI,
) -> Option<SizeI> {
use crate::ecs::layout::Dimension;
let size = box_style.size.as_ref()?;
let width = match size.width? {
Dimension::Px(w) => w,
_ => return None,
};
let height = match size.height? {
Dimension::Px(h) => h,
_ => return None,
};
Some(SizeI {
width: (width * dpi.scale_x()).ceil() as i32,
height: (height * dpi.scale_y()).ceil() as i32,
})
}
fn calculate_center_correction(old_physical_size: SizeI, new_physical_size: SizeI) -> (i32, i32) {
(
(old_physical_size.width - new_physical_size.width) / 2,
(old_physical_size.height - new_physical_size.height) / 2,
)
}
pub(super) fn correct_position_for_dpi_center_preserve(
client_pos: Point,
client_size: SizeI,
dpi_context: &Option<crate::ecs::window::DpiChangeContext>,
box_style: Option<&crate::ecs::layout::BoxStyle>,
dpi: &crate::ecs::window::DPI,
) -> Point {
let Some(_ctx) = dpi_context else {
return client_pos;
};
let Some(bs) = box_style else {
warn!("[WM_WINDOWPOSCHANGED] DPI center correction skipped: BoxStyle not found");
return client_pos;
};
let Some(new_physical_size) = calculate_physical_size_from_box_style(bs, dpi) else {
trace!("[WM_WINDOWPOSCHANGED] DPI center correction skipped: BoxStyle.size not Px");
return client_pos;
};
let (dx, dy) = calculate_center_correction(client_size, new_physical_size);
if dx == 0 && dy == 0 {
trace!("[WM_WINDOWPOSCHANGED] DPI center correction: no size change, correction = (0, 0)");
return client_pos;
}
let corrected = Point {
x: client_pos.x + dx,
y: client_pos.y + dy,
};
debug!(
old_pos_x = client_pos.x,
old_pos_y = client_pos.y,
corrected_pos_x = corrected.x,
corrected_pos_y = corrected.y,
old_size_cx = client_size.width,
old_size_cy = client_size.height,
new_size_cx = new_physical_size.width,
new_size_cy = new_physical_size.height,
correction_dx = dx,
correction_dy = dy,
"[WM_WINDOWPOSCHANGED] DPI center correction applied"
);
corrected
}
#[cfg(test)]
#[path = "dpi_helpers_tests.rs"]
mod tests;