fix(ui): clamp launcher startup geometry

This commit is contained in:
Brad Stein 2026-04-23 12:12:44 -03:00
parent 6b202524d2
commit 7fbba1314a
4 changed files with 24 additions and 25 deletions

View File

@ -2,12 +2,12 @@ fn largest_monitor_size() -> (u32, u32) {
let (width, height) = enumerate_monitors() let (width, height) = enumerate_monitors()
.into_iter() .into_iter()
.max_by_key(|monitor| { .max_by_key(|monitor| {
effective_monitor_width(monitor) as u64 * effective_monitor_height(monitor) as u64 monitor.geometry.width().max(1) as u64 * monitor.geometry.height().max(1) as u64
}) })
.map(|monitor| { .map(|monitor| {
( (
effective_monitor_width(&monitor), monitor.geometry.width().max(1) as u32,
effective_monitor_height(&monitor), monitor.geometry.height().max(1) as u32,
) )
}) })
.unwrap_or((1920, 1080)); .unwrap_or((1920, 1080));
@ -54,18 +54,6 @@ fn probe_kscreen_display_size() -> Option<(u32, u32)> {
best best
} }
#[cfg(not(coverage))]
fn effective_monitor_width(monitor: &crate::output::display::MonitorInfo) -> u32 {
let scale = monitor.scale_factor.max(1) as u32;
(monitor.geometry.width().max(1) as u32).saturating_mul(scale)
}
#[cfg(not(coverage))]
fn effective_monitor_height(monitor: &crate::output::display::MonitorInfo) -> u32 {
let scale = monitor.scale_factor.max(1) as u32;
(monitor.geometry.height().max(1) as u32).saturating_mul(scale)
}
#[cfg(not(coverage))] #[cfg(not(coverage))]
fn normalize_breakout_limit(width: u32, height: u32) -> (u32, u32) { fn normalize_breakout_limit(width: u32, height: u32) -> (u32, u32) {
const STANDARD_SIZES: &[(u32, u32)] = &[ const STANDARD_SIZES: &[(u32, u32)] = &[
@ -87,9 +75,9 @@ fn normalize_breakout_limit(width: u32, height: u32) -> (u32, u32) {
#[cfg(not(coverage))] #[cfg(not(coverage))]
fn launcher_default_size(width: u32, height: u32) -> (i32, i32) { fn launcher_default_size(width: u32, height: u32) -> (i32, i32) {
let max_width = width.saturating_sub(48).max(640) as i32; let max_width = width.saturating_sub(72).max(640) as i32;
let max_height = height.saturating_sub(72).max(520) as i32; let max_height = height.saturating_sub(120).max(520) as i32;
(1380.min(max_width), 860.min(max_height)) (1280.min(max_width), 780.min(max_height))
} }
#[cfg(not(coverage))] #[cfg(not(coverage))]

View File

@ -6,7 +6,6 @@
.default_height(LAUNCHER_DEFAULT_HEIGHT) .default_height(LAUNCHER_DEFAULT_HEIGHT)
.resizable(false) .resizable(false)
.build(); .build();
window.set_size_request(LAUNCHER_DEFAULT_WIDTH, LAUNCHER_DEFAULT_HEIGHT);
install_css(&window); install_css(&window);
install_window_icon(&window); install_window_icon(&window);

View File

@ -181,8 +181,8 @@ pub struct LauncherView {
pub const LESAVKA_ICON_NAME: &str = "dev.lesavka.launcher"; pub const LESAVKA_ICON_NAME: &str = "dev.lesavka.launcher";
const LESAVKA_ICON_SEARCH_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/icons"); const LESAVKA_ICON_SEARCH_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/icons");
const LAUNCHER_DEFAULT_WIDTH: i32 = 1360; const LAUNCHER_DEFAULT_WIDTH: i32 = 1280;
const LAUNCHER_DEFAULT_HEIGHT: i32 = 900; const LAUNCHER_DEFAULT_HEIGHT: i32 = 780;
const OPERATIONS_RAIL_WIDTH: i32 = 304; const OPERATIONS_RAIL_WIDTH: i32 = 304;
const CAMERA_PREVIEW_VIEWPORT_HEIGHT: i32 = 146; const CAMERA_PREVIEW_VIEWPORT_HEIGHT: i32 = 146;
const CAMERA_PREVIEW_VIEWPORT_WIDTH: i32 = 280; const CAMERA_PREVIEW_VIEWPORT_WIDTH: i32 = 280;

View File

@ -9,6 +9,7 @@
const UI_LAYOUT_SRC: &str = concat!( const UI_LAYOUT_SRC: &str = concat!(
include_str!("../../client/src/launcher/ui_components/types.rs"), include_str!("../../client/src/launcher/ui_components/types.rs"),
include_str!("../../client/src/launcher/ui_components/build_shell.rs"), include_str!("../../client/src/launcher/ui_components/build_shell.rs"),
include_str!("../../client/src/launcher/ui/preview_profiles.rs"),
include_str!("../../client/src/launcher/ui_components/display_pane.rs"), include_str!("../../client/src/launcher/ui_components/display_pane.rs"),
include_str!("../../client/src/launcher/ui_components/build_device_controls.rs"), include_str!("../../client/src/launcher/ui_components/build_device_controls.rs"),
include_str!("../../client/src/launcher/ui_components/build_operations_rail.rs"), include_str!("../../client/src/launcher/ui_components/build_operations_rail.rs"),
@ -39,16 +40,27 @@ fn source_index(needle: &str) -> usize {
#[test] #[test]
fn launcher_default_size_stays_inside_1080p() { fn launcher_default_size_stays_inside_1080p() {
assert_eq!(const_i32("LAUNCHER_DEFAULT_WIDTH"), 1360); assert_eq!(const_i32("LAUNCHER_DEFAULT_WIDTH"), 1280);
assert_eq!(const_i32("LAUNCHER_DEFAULT_HEIGHT"), 900); assert_eq!(const_i32("LAUNCHER_DEFAULT_HEIGHT"), 780);
assert!(const_i32("LAUNCHER_DEFAULT_WIDTH") <= 1920); assert!(const_i32("LAUNCHER_DEFAULT_WIDTH") <= 1920);
assert!( assert!(
const_i32("LAUNCHER_DEFAULT_HEIGHT") <= 900, const_i32("LAUNCHER_DEFAULT_HEIGHT") <= 900,
"leave room for desktop panels and window chrome on a 1080p monitor" "leave room for desktop panels and window chrome on a 1080p monitor"
); );
assert!( assert!(
UI_LAYOUT_SRC !UI_LAYOUT_SRC
.contains("window.set_size_request(LAUNCHER_DEFAULT_WIDTH, LAUNCHER_DEFAULT_HEIGHT);") .contains("window.set_size_request(LAUNCHER_DEFAULT_WIDTH, LAUNCHER_DEFAULT_HEIGHT);"),
"the top-level window should not pin a larger minimum than the startup budget"
);
assert!(
UI_LAYOUT_SRC.contains("let max_width = width.saturating_sub(72).max(640) as i32;")
);
assert!(
UI_LAYOUT_SRC.contains("let max_height = height.saturating_sub(120).max(520) as i32;")
);
assert!(
UI_LAYOUT_SRC.contains("(1280.min(max_width), 780.min(max_height))"),
"the activation path must use the same compact startup budget as the shell"
); );
} }