host: a restored window fits the monitor it opens on

A state saved on a larger or rearranged screen (2720x1800 at x=3347 on a smaller second monitor)
left the titlebar off-screen and the window could not be moved. After the window-state restore,
the window is moved inside, and shrunk to, the work area of the monitor it is mostly on (the
primary one when that monitor is gone). Maximized and full-screen windows are left to the OS.
window_fit::fit is pure and unit tested.
This commit is contained in:
CRTkafa 2026-10-01 11:29:35 +07:00
parent 7a98146b73
commit b3f6960dc3
3 changed files with 136 additions and 0 deletions

View file

@ -1160,6 +1160,32 @@ pub fn reset_lost_geometry(window: &tauri::Window, size: (f64, f64), min: (f64,
}
}
/// A restored window lies inside the work area of the monitor it opens on (the primary one when
/// that monitor is gone): a state saved on a larger or rearranged screen would otherwise leave
/// its titlebar out of reach ([`crate::window_fit::fit`]). A maximized or full-screen window is
/// the OS's to place.
pub fn fit_to_monitor(window: &tauri::Window) {
use crate::window_fit::{fit, Rect};
if window.is_maximized().unwrap_or(false) || window.is_fullscreen().unwrap_or(false) {
return;
}
let (Ok(position), Ok(size), Ok(monitors)) = (window.outer_position(), window.outer_size(), window.available_monitors()) else { return };
let area = |monitor: &tauri::Monitor| {
let work = monitor.work_area();
Rect::new(work.position.x, work.position.y, work.size.width, work.size.height)
};
let areas: Vec<Rect> = monitors.iter().map(area).collect();
let primary = window.primary_monitor().ok().flatten().map(|monitor| area(&monitor));
let Some(fitted) = fit(Rect::new(position.x, position.y, size.width, size.height), &areas, primary) else { return };
if (fitted.width, fitted.height) != (size.width, size.height) {
// The outer frame must fit; the inner size is what can be set, so the frame's border comes off it.
let inner = window.inner_size().unwrap_or(size);
let (extra_w, extra_h) = (size.width.saturating_sub(inner.width), size.height.saturating_sub(inner.height));
let _ = window.set_size(tauri::PhysicalSize::new(fitted.width.saturating_sub(extra_w), fitted.height.saturating_sub(extra_h)));
}
let _ = window.set_position(tauri::PhysicalPosition::new(fitted.x, fitted.y));
}
/// The host's commands ([`commands::SHELL`], [`commands::TAB`], [`commands::SITE`]).
fn host_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 'static {
tauri::generate_handler![
@ -1459,6 +1485,7 @@ fn open_window(app: &mut tauri::App<Wry>, config: &AppConfig) -> Result<(), Box<
let _ = window.restore_state(window_state_flags());
}
reset_lost_geometry(&window, config.window_size, config.min_window_size);
fit_to_monitor(&window);
// `taskkill` (and anything else closing "the first visible window") must close the app
// even when a minimized window sits below the runtime's helper windows.
host::route_helper_closes(&window);