From 2dc838f85c0de563ee19d28332f7c60f4a9c094c Mon Sep 17 00:00:00 2001 From: pythcoiner Date: Mon, 5 May 2025 11:37:45 +0200 Subject: [PATCH] gui: be smart with window size at launch --- liana-gui/src/app/settings.rs | 1 - liana-gui/src/gui/mod.rs | 115 +++++++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 4 deletions(-) diff --git a/liana-gui/src/app/settings.rs b/liana-gui/src/app/settings.rs index 01d67755..e2602f4b 100644 --- a/liana-gui/src/app/settings.rs +++ b/liana-gui/src/app/settings.rs @@ -394,7 +394,6 @@ pub mod global { #[derive(Debug, Deserialize, Serialize, Default)] pub struct GlobalSettings { - #[serde(skip)] pub bitbox: Option, pub window_config: Option, } diff --git a/liana-gui/src/gui/mod.rs b/liana-gui/src/gui/mod.rs index d3b4f623..bfbd244f 100644 --- a/liana-gui/src/gui/mod.rs +++ b/liana-gui/src/gui/mod.rs @@ -2,8 +2,9 @@ use iced::{ event::{self, Event}, keyboard, widget::{focus_next, focus_previous, pane_grid}, - Length, Subscription, Task, + Length, Size, Subscription, Task, }; +use iced_runtime::window; use tracing::{error, info}; use tracing_subscriber::filter::LevelFilter; extern crate serde; @@ -15,12 +16,23 @@ use liana_ui::widget::{Column, Container, Element}; pub mod pane; pub mod tab; -use crate::{dir::LianaDirectory, launcher, logger::setup_logger, VERSION}; +use crate::{ + app::settings::global::{GlobalSettings, WindowConfig}, + dir::LianaDirectory, + launcher, + logger::setup_logger, + VERSION, +}; + +use iced::window::Id; pub struct GUI { panes: pane_grid::State, focus: Option, config: Config, + window_id: Option, + window_init: Option, + window_config: Option, } #[derive(Debug)] @@ -39,6 +51,8 @@ pub enum Message { Clicked(pane_grid::Pane), Dragged(pane_grid::DragEvent), Resized(pane_grid::ResizeEvent), + Window(Option), + WindowSize(Size), } impl From> for Message { @@ -65,15 +79,24 @@ impl GUI { if let Err(e) = setup_logger(log_level, config.liana_directory.clone()) { tracing::warn!("Error while setting error: {}", e); } - let mut cmds = vec![Task::perform(ctrl_c(), |_| Message::CtrlC)]; + let mut cmds = vec![ + window::get_oldest().map(Message::Window), + Task::perform(ctrl_c(), |_| Message::CtrlC), + ]; let (pane, cmd) = pane::Pane::new(&config); let (panes, focused_pane) = pane_grid::State::new(pane); cmds.push(cmd.map(move |msg| Message::Pane(focused_pane, msg))); + let window_config = + GlobalSettings::load_window_config(&GlobalSettings::path(&config.liana_directory)); + let window_init = window_config.is_some().then_some(true); ( Self { panes, focus: Some(focused_pane), config, + window_id: None, + window_init, + window_config, }, Task::batch(cmds), ) @@ -81,6 +104,89 @@ impl GUI { pub fn update(&mut self, message: Message) -> Task { match message { + // we get this message only once at startup + Message::Window(id) => { + self.window_id = id; + // Common case: if there is an already saved screen size we reuse it + if let (Some(id), Some(WindowConfig { width, height })) = (id, &self.window_config) + { + window::resize( + id, + Size { + width: *width, + height: *height, + }, + ) + // Initial startup: we maximize the screen in order to know the max usable screen area + } else if let Some(id) = &self.window_id { + window::maximize(*id, true) + } else { + Task::none() + } + } + Message::WindowSize(monitor_size) => { + match ( + self.window_config.as_mut(), + &self.window_init, + &self.window_id, + ) { + // no previous screen size recorded && window maximized + (None, Some(false), Some(id)) => { + self.window_init = Some(true); + let mut batch = vec![window::maximize(*id, false)]; + let new_size = if monitor_size.height >= 1200.0 { + let size = Size { + width: 1200.0, + height: 950.0, + }; + batch.push(window::resize(*id, size)); + size + } else { + batch.push(window::resize(*id, iced::window::Settings::default().size)); + iced::window::Settings::default().size + }; + let path = GlobalSettings::path(&self.config.liana_directory); + let mut settings = GlobalSettings::load(&path) + .ok() + .flatten() + .unwrap_or_default(); + settings.window_config = Some(WindowConfig { + width: new_size.width, + height: new_size.height, + }); + settings.to_file(&path).unwrap(); + Task::batch(batch) + } + // we already have a record of the last window size and we update it + (Some(WindowConfig { width, height }), _, _) => { + if *width != monitor_size.width || *height != monitor_size.height { + *width = monitor_size.width; + *height = monitor_size.height; + let path = GlobalSettings::path(&self.config.liana_directory); + let mut settings = GlobalSettings::load(&path) + .ok() + .flatten() + .unwrap_or_default(); + settings.window_config = Some(WindowConfig { + width: *width, + height: *height, + }); + if let Err(e) = settings.to_file(&path) { + tracing::error!("Fail to write window config to file: {e}"); + } + } + Task::none() + } + // we ignore the first notification about initial window size it will always be + // the default one + _ => { + if self.window_init.is_none() { + self.window_init = Some(false); + } + Task::none() + } + } + } Message::CtrlC | Message::Event(iced::Event::Window(iced::window::Event::CloseRequested)) => { for (_, pane) in self.panes.iter_mut() { @@ -250,6 +356,9 @@ impl GUI { iced::Event::Window(iced::window::Event::CloseRequested), event::Status::Ignored, ) => Some(Message::Event(event)), + (iced::Event::Window(iced::window::Event::Resized(size)), _) => { + Some(Message::WindowSize(*size)) + } _ => None, } })];