use bevy::prelude::*;
use bevy_kana::ToI32;
use bevy_kana::ToU32;
use super::Platform;
use super::monitors::MonitorInfo;
use super::monitors::Monitors;
use super::types::TargetPosition;
use super::types::WindowState;
#[must_use]
pub(crate) fn resolve_target_monitor_and_position(
saved_monitor_index: usize,
saved_position: Option<(i32, i32)>,
monitors: &Monitors,
) -> (&MonitorInfo, Option<(i32, i32)>, bool) {
monitors.by_index(saved_monitor_index).map_or_else(
|| (monitors.first(), None, true),
|info| (info, saved_position, false),
)
}
#[must_use]
pub(crate) fn compute_target_position(
saved_state: &WindowState,
target_info: &MonitorInfo,
fallback_position: Option<(i32, i32)>,
decoration: UVec2,
starting_scale: f64,
platform: Platform,
) -> TargetPosition {
let logical_width = saved_state.logical_width;
let logical_height = saved_state.logical_height;
let target_scale = target_info.scale;
let width = (f64::from(logical_width) * target_scale).to_u32();
let height = (f64::from(logical_height) * target_scale).to_u32();
let outer_width = width + decoration.x;
let outer_height = height + decoration.y;
let position = fallback_position.map(|(x, y)| {
let physical_x = (f64::from(x) * target_scale).round().to_i32();
let physical_y = (f64::from(y) * target_scale).round().to_i32();
clamp_position_to_monitor(
physical_x,
physical_y,
target_info,
outer_width,
outer_height,
platform,
)
});
TargetPosition {
position,
width,
height,
logical_width,
logical_height,
target_scale,
starting_scale,
scale_strategy: platform.scale_strategy(starting_scale, target_scale),
mode: saved_state.mode.clone(),
target_monitor_index: target_info.index,
fullscreen_state: if saved_state.mode.is_fullscreen() {
Some(platform.fullscreen_restore_state())
} else {
None
},
settle_state: None,
}
}
#[must_use]
fn clamp_position_to_monitor(
saved_x: i32,
saved_y: i32,
target_info: &MonitorInfo,
outer_width: u32,
outer_height: u32,
platform: Platform,
) -> IVec2 {
if platform.should_clamp_position() {
let monitor_right = target_info.position.x + target_info.size.x.to_i32();
let monitor_bottom = target_info.position.y + target_info.size.y.to_i32();
let mut x = saved_x;
let mut y = saved_y;
if x + outer_width.to_i32() > monitor_right {
x = monitor_right - outer_width.to_i32();
}
if y + outer_height.to_i32() > monitor_bottom {
y = monitor_bottom - outer_height.to_i32();
}
x = x.max(target_info.position.x);
y = y.max(target_info.position.y);
if x != saved_x || y != saved_y {
debug!(
"[clamp_position_to_monitor] Clamped: ({saved_x}, {saved_y}) -> ({x}, {y}) for outer size {outer_width}x{outer_height}"
);
}
IVec2::new(x, y)
} else {
IVec2::new(saved_x, saved_y)
}
}