From 4a72abc8ec1d973cd80b5978184c3904b04ea12e Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 13 Dec 2022 09:09:36 +0100 Subject: [PATCH] Clamp eframe window size to at most the size of the largest monitor (#2445) This can hopefully fix some reported bugs where --- crates/eframe/src/epi.rs | 4 +-- crates/eframe/src/native/epi_integration.rs | 33 +++++++++++++++++---- crates/eframe/src/native/run.rs | 4 +-- crates/egui-winit/src/window_settings.rs | 7 +++-- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 62c1d2f2..2cd652ff 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -255,10 +255,10 @@ pub struct NativeOptions { /// The initial inner size of the native window in points (logical pixels). pub initial_window_size: Option, - /// The minimum inner window size + /// The minimum inner window size in points (logical pixels). pub min_window_size: Option, - /// The maximum inner window size + /// The maximum inner window size in points (logical pixels). pub max_window_size: Option, /// Should the app window be resizable? diff --git a/crates/eframe/src/native/epi_integration.rs b/crates/eframe/src/native/epi_integration.rs index b3c76660..ff54d12f 100644 --- a/crates/eframe/src/native/epi_integration.rs +++ b/crates/eframe/src/native/epi_integration.rs @@ -5,6 +5,7 @@ use winit::platform::macos::WindowBuilderExtMacOS as _; #[cfg(feature = "accesskit")] use egui::accesskit; +use egui::NumExt as _; #[cfg(feature = "accesskit")] use egui_winit::accesskit_winit; use egui_winit::{native_pixels_per_point, EventResponse, WindowSettings}; @@ -48,10 +49,11 @@ pub fn read_window_info(window: &winit::window::Window, pixels_per_point: f32) - } } -pub fn window_builder( +pub fn window_builder( + event_loop: &EventLoopWindowTarget, title: &str, native_options: &epi::NativeOptions, - window_settings: &Option, + window_settings: Option, ) -> winit::window::WindowBuilder { let epi::NativeOptions { always_on_top, @@ -103,7 +105,9 @@ pub fn window_builder( window_builder = window_builder_drag_and_drop(window_builder, *drag_and_drop_support); - if let Some(window_settings) = window_settings { + if let Some(mut window_settings) = window_settings { + // Restore pos/size from previous session + window_settings.clamp_to_sane_values(largest_monitor_point_size(event_loop)); window_builder = window_settings.initialize_window(window_builder); } else { if let Some(pos) = *initial_window_pos { @@ -112,7 +116,10 @@ pub fn window_builder( y: pos.y as f64, }); } + if let Some(initial_window_size) = *initial_window_size { + let initial_window_size = + initial_window_size.at_most(largest_monitor_point_size(event_loop)); window_builder = window_builder.with_inner_size(points_to_size(initial_window_size)); } } @@ -120,6 +127,22 @@ pub fn window_builder( window_builder } +fn largest_monitor_point_size(event_loop: &EventLoopWindowTarget) -> egui::Vec2 { + let mut max_size = egui::Vec2::ZERO; + + for monitor in event_loop.available_monitors() { + let size = monitor.size().to_logical::(monitor.scale_factor()); + let size = egui::vec2(size.width, size.height); + max_size = max_size.max(size); + } + + if max_size == egui::Vec2::ZERO { + egui::Vec2::splat(16000.0) + } else { + max_size + } +} + fn load_icon(icon_data: epi::IconData) -> Option { winit::window::Icon::from_rgba(icon_data.rgba, icon_data.width, icon_data.height).ok() } @@ -445,9 +468,7 @@ const STORAGE_WINDOW_KEY: &str = "window"; pub fn load_window_settings(_storage: Option<&dyn epi::Storage>) -> Option { #[cfg(feature = "persistence")] { - let mut settings: WindowSettings = epi::get_value(_storage?, STORAGE_WINDOW_KEY)?; - settings.clamp_to_sane_values(); - Some(settings) + epi::get_value(_storage?, STORAGE_WINDOW_KEY) } #[cfg(not(feature = "persistence"))] None diff --git a/crates/eframe/src/native/run.rs b/crates/eframe/src/native/run.rs index 865d8825..fb2bb508 100644 --- a/crates/eframe/src/native/run.rs +++ b/crates/eframe/src/native/run.rs @@ -504,7 +504,7 @@ mod glow_integration { let window_settings = epi_integration::load_window_settings(storage); let winit_window = - epi_integration::window_builder(title, native_options, &window_settings) + epi_integration::window_builder(event_loop, title, native_options, window_settings) .build(event_loop)?; // a lot of the code below has been lifted from glutin example in their repo. let glutin_window_context = @@ -937,7 +937,7 @@ mod wgpu_integration { ) -> Result { let window_settings = epi_integration::load_window_settings(storage); Ok( - epi_integration::window_builder(title, native_options, &window_settings) + epi_integration::window_builder(event_loop, title, native_options, window_settings) .build(event_loop)?, ) } diff --git a/crates/egui-winit/src/window_settings.rs b/crates/egui-winit/src/window_settings.rs index e7bd746c..f81b754d 100644 --- a/crates/egui-winit/src/window_settings.rs +++ b/crates/egui-winit/src/window_settings.rs @@ -76,11 +76,14 @@ impl WindowSettings { } } - pub fn clamp_to_sane_values(&mut self) { + pub fn clamp_to_sane_values(&mut self, max_size: egui::Vec2) { + use egui::NumExt as _; + if let Some(size) = &mut self.inner_size_points { // Prevent ridiculously small windows let min_size = egui::Vec2::splat(64.0); - *size = size.max(min_size); + *size = size.at_least(min_size); + *size = size.at_most(max_size); } } }