Desktop: keep the off-screen check until the monitor size is known (#23) (#76)

This commit is contained in:
MarekSpodBiedry
2026-10-10 06:01:48 -04:00
committed by GitHub
parent 869ac16110
commit 1633cbcfaa
2 changed files with 27 additions and 2 deletions
+2 -2
View File
@@ -14,7 +14,7 @@ mod graphics;
mod logging;
use wordcraft_engine::Session;
use wordcraft_ui_egui::{Services, UiState, WordApp, window_geometry::WindowGeometry};
use wordcraft_ui_egui::{Services, UiState, WordApp, window_geometry::{WindowGeometry, take_rescue}};
/// The app, and the restored window geometry until the first frame has checked it.
struct App(WordApp, Option<WindowGeometry>);
@@ -24,7 +24,7 @@ impl eframe::App for App {
self.0.logic(ctx);
let prev = self.0.ui.window;
self.0.ui.window = ctx.input(|i| WindowGeometry::track(prev, i.viewport(), i.viewport_rect().size()));
if let Some(pos) = self.1.take().and_then(|g| ctx.input(|i| g.rescue_position(i.viewport()))) {
if let Some(pos) = ctx.input(|i| take_rescue(&mut self.1, i.viewport())) {
ctx.send_viewport_cmd(egui::ViewportCommand::OuterPosition(pos));
}
if self.0.quit_requested {
+25
View File
@@ -91,6 +91,14 @@ impl WindowGeometry {
}
}
/// Checks the restored geometry in `pending` once, and only once the monitor size is known: while
/// `info` doesn't report a usable one, `pending` is left in place for a later frame. Then it is taken
/// and [`WindowGeometry::rescue_position`] decides where to move the window, if anywhere.
pub fn take_rescue(pending: &mut Option<WindowGeometry>, info: &egui::ViewportInfo) -> Option<egui::Pos2> {
info.monitor_size.filter(|s| s.is_finite() && s.x > 0.0 && s.y > 0.0)?;
pending.take()?.rescue_position(info)
}
#[cfg(test)]
mod tests {
use super::*;
@@ -174,6 +182,23 @@ mod tests {
assert_eq!(saved().rescue_position(&egui::ViewportInfo::default()), None);
}
#[test]
fn the_rescue_waits_for_the_monitor_size() {
let on = egui::Rect::from_min_size(egui::pos2(2000.0, 50.0), egui::vec2(1200.0, 800.0));
// The first frame doesn't know the monitor yet: nothing happens and the geometry is kept.
let mut pending = Some(saved());
assert_eq!(take_rescue(&mut pending, &egui::ViewportInfo::default()), None);
assert_eq!(pending, Some(saved()));
// A later frame reports a different monitor: centred on it, and the check is done.
assert_eq!(take_rescue(&mut pending, &info(on, egui::vec2(1600.0, 900.0))), Some(egui::pos2(200.0, 50.0)));
assert_eq!(pending, None);
assert_eq!(take_rescue(&mut pending, &info(on, egui::vec2(1024.0, 768.0))), None);
// The same monitor: no move, and the check is done as well.
let mut pending = Some(saved());
assert_eq!(take_rescue(&mut pending, &info(on, egui::vec2(1920.0, 1080.0))), None);
assert_eq!(pending, None);
}
#[test]
fn survives_the_prefs_round_trip() {
let ui = crate::UiState { window: Some(saved()), ..Default::default() };