fix(ui): restore launcher 1080p layout budget

This commit is contained in:
Brad Stein 2026-04-23 11:49:19 -03:00
parent 3f3fad7c50
commit 6b202524d2
7 changed files with 62 additions and 19 deletions

View File

@ -3,6 +3,7 @@ use crate::launcher::{
devices::DeviceCatalog, preview::PreviewBinding, state::LauncherState,
ui_components::build_launcher_view,
};
use gtk::prelude::*;
use serial_test::serial;
use std::{cell::RefCell, rc::Rc};
@ -32,6 +33,45 @@ fn gpio_power_label_tracks_detected_devices() {
assert_eq!(gpio_power_label(&power), "2 Eyes");
}
#[gtk::test]
#[serial]
fn launcher_shell_measures_inside_a_1080p_desktop_budget() {
if gtk::gdk::Display::default().is_none() {
return;
}
let app = gtk::Application::builder()
.application_id("dev.lesavka.test-layout-budget")
.build();
let _ = app.register(None::<&gtk::gio::Cancellable>);
let state = LauncherState::new();
let view = build_launcher_view(
&app,
"http://127.0.0.1:50051",
&DeviceCatalog::default(),
&state,
);
let (min_width, natural_width, _, _) = view.window.measure(gtk::Orientation::Horizontal, -1);
let (tall_min_width, tall_natural_width, _, _) =
view.window.measure(gtk::Orientation::Horizontal, 1080);
let (min_height, natural_height, _, _) = view.window.measure(gtk::Orientation::Vertical, 1920);
assert!(
min_width <= 1920 && natural_width <= 1920,
"launcher width budget regressed: min={min_width}, natural={natural_width}"
);
assert!(
tall_min_width <= 1920 && tall_natural_width <= 1920,
"launcher 1080p-tall width regressed: min={tall_min_width}, natural={tall_natural_width}"
);
assert!(
min_height <= 1080 && natural_height <= 1080,
"launcher height budget regressed: min={min_height}, natural={natural_height}"
);
}
#[test]
fn server_chip_state_tracks_connection_not_just_reachability() {
let mut state = LauncherState::new();

View File

@ -77,7 +77,8 @@
let display_row = gtk::Box::new(gtk::Orientation::Horizontal, 8);
display_row.set_hexpand(true);
display_row.set_vexpand(true);
display_row.set_vexpand(false);
display_row.set_valign(gtk::Align::Start);
display_row.set_homogeneous(true);
let left_pane = build_display_pane("Left Eye", "/dev/lesavka_l_eye");
let right_pane = build_display_pane("Right Eye", "/dev/lesavka_r_eye");

View File

@ -34,10 +34,10 @@ fn build_display_pane(title: &str, capture_path: &str) -> DisplayPaneWidgets {
preview_box.set_valign(gtk::Align::Fill);
preview_box.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
let preview_frame = gtk::AspectFrame::new(0.5, 0.5, 16.0 / 9.0, false);
preview_frame.set_hexpand(true);
preview_frame.set_vexpand(true);
preview_frame.set_halign(gtk::Align::Fill);
preview_frame.set_valign(gtk::Align::Fill);
preview_frame.set_hexpand(false);
preview_frame.set_vexpand(false);
preview_frame.set_halign(gtk::Align::Center);
preview_frame.set_valign(gtk::Align::Center);
preview_frame.set_size_request(EYE_PREVIEW_MIN_WIDTH, EYE_PREVIEW_MIN_HEIGHT);
preview_frame.set_child(Some(&picture));
preview_box.append(&preview_frame);

View File

@ -115,7 +115,7 @@ pub fn install_css(window: &gtk::ApplicationWindow) {
background: rgba(255, 255, 255, 0.08);
}
progressbar.audio-check-meter.vertical trough {
min-height: 116px;
min-height: 96px;
}
progressbar.audio-check-meter progress {
border-radius: 999px;

View File

@ -184,8 +184,8 @@ const LESAVKA_ICON_SEARCH_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/ass
const LAUNCHER_DEFAULT_WIDTH: i32 = 1360;
const LAUNCHER_DEFAULT_HEIGHT: i32 = 900;
const OPERATIONS_RAIL_WIDTH: i32 = 304;
const CAMERA_PREVIEW_VIEWPORT_HEIGHT: i32 = 158;
const CAMERA_PREVIEW_VIEWPORT_HEIGHT: i32 = 146;
const CAMERA_PREVIEW_VIEWPORT_WIDTH: i32 = 280;
const EYE_PREVIEW_MIN_HEIGHT: i32 = 300;
const EYE_PREVIEW_MIN_HEIGHT: i32 = 258;
const EYE_PREVIEW_MIN_WIDTH: i32 = 460;
const SIDE_LOG_MIN_HEIGHT: i32 = 124;

View File

@ -368,7 +368,7 @@
"client/src/launcher/ui_components/build_shell.rs": {
"clippy_warnings": 0,
"doc_debt": 0,
"loc": 110
"loc": 111
},
"client/src/launcher/ui_components/combo_helpers.rs": {
"clippy_warnings": 0,

View File

@ -46,20 +46,21 @@ fn launcher_default_size_stays_inside_1080p() {
const_i32("LAUNCHER_DEFAULT_HEIGHT") <= 900,
"leave room for desktop panels and window chrome on a 1080p monitor"
);
assert!(
UI_LAYOUT_SRC
.contains("window.set_size_request(LAUNCHER_DEFAULT_WIDTH, LAUNCHER_DEFAULT_HEIGHT);")
);
}
#[test]
fn eye_panes_keep_the_locked_larger_preview_footprint() {
fn eye_panes_keep_the_docked_preview_footprint_without_forcing_maximized_width() {
assert_eq!(const_i32("EYE_PREVIEW_MIN_WIDTH"), 460);
assert_eq!(const_i32("EYE_PREVIEW_MIN_HEIGHT"), 300);
let estimated_min_width = 20
+ 8
+ const_i32("OPERATIONS_RAIL_WIDTH")
+ 8
+ 2 * (const_i32("EYE_PREVIEW_MIN_WIDTH") + 32);
assert_eq!(const_i32("EYE_PREVIEW_MIN_HEIGHT"), 258);
assert!(UI_LAYOUT_SRC.contains("display_row.set_vexpand(false);"));
assert!(UI_LAYOUT_SRC.contains("display_row.set_valign(gtk::Align::Start);"));
assert!(
estimated_min_width <= const_i32("LAUNCHER_DEFAULT_WIDTH"),
"the eye panes must not push the operations rail off a 1360px launcher"
!UI_LAYOUT_SRC.contains("display_row.set_vexpand(true);"),
"a vertically expanding 16:9 eye row turns extra height into horizontal overflow"
);
assert!(
UI_LAYOUT_SRC.contains("caption_label.set_halign(gtk::Align::End)")
@ -115,7 +116,7 @@ fn device_staging_and_testing_bottoms_stay_locked_together() {
#[test]
fn device_testing_keeps_webcam_and_mic_playback_as_equal_bottom_columns() {
assert_eq!(const_i32("CAMERA_PREVIEW_VIEWPORT_WIDTH"), 280);
assert_eq!(const_i32("CAMERA_PREVIEW_VIEWPORT_HEIGHT"), 158);
assert_eq!(const_i32("CAMERA_PREVIEW_VIEWPORT_HEIGHT"), 146);
assert!(UI_LAYOUT_SRC.contains("webcam_group.set_valign(gtk::Align::Fill);"));
assert!(UI_LAYOUT_SRC.contains("playback_group.set_valign(gtk::Align::Fill);"));
assert!(UI_LAYOUT_SRC.contains("preview_body.set_vexpand(false);"));
@ -184,6 +185,7 @@ fn relay_controls_keep_connect_inline_with_server_entry() {
assert!(UI_LAYOUT_SRC.contains("build_panel(\"Relay Controls\")"));
assert_eq!(const_i32("OPERATIONS_RAIL_WIDTH"), 304);
assert_eq!(const_i32("RAIL_BUTTON_WIDTH"), 92);
assert_eq!(const_i32("RAIL_BUTTON_LABEL_CHARS"), 14);
assert!(UI_LAYOUT_SRC.contains("let relay_grid = gtk::Grid::new();"));
assert!(UI_LAYOUT_SRC.contains("relay_grid.set_column_homogeneous(true);"));
assert!(UI_LAYOUT_SRC.contains("relay_grid.attach(&server_entry, 0, 0, 2, 1);"));