From bc54893c1c8981a1315867e53ce49ce195d1b4e3 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Sat, 19 Oct 2024 09:10:12 -0700 Subject: [PATCH] Disable resizable automatically with fixed roots Closes #188 --- CHANGELOG.md | 3 +++ src/value.rs | 11 +++++++++ src/window.rs | 63 +++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 644bfa3..ffb8797 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `WrapperWidget::activate`'s default implementation now activates the wrapped widget. - `Space` now intercepts mouse events if its color has a non-zero alpha channel. +- If the root widget of a window is a `Resize` with an exact width and height, + the window will have its resizable attribute disabled. This will not update + the resizable `Dynamic` on `Window`. ### Fixed diff --git a/src/value.rs b/src/value.rs index fcdbb86..2217808 100644 --- a/src/value.rs +++ b/src/value.rs @@ -4095,6 +4095,17 @@ where self.current_generation = self.source.generation(); } } + + /// Updates the value stored in the source. + pub fn set(&mut self, new_value: Source::Value) + where + Source::Value: PartialEq + Clone, + { + self.current = new_value; + if self.source.set(self.current.clone()) { + self.current_generation = self.source.generation(); + } + } } /// A [`Source`] that can be used in a [`Tracked`] instance. diff --git a/src/window.rs b/src/window.rs index c99f2cc..422fd48 100644 --- a/src/window.rs +++ b/src/window.rs @@ -1377,6 +1377,7 @@ struct OpenWindow { modifiers: Dynamic, shortcuts: Value, on_file_drop: Option>, + disabled_resize_automatically: bool, } impl OpenWindow @@ -1814,6 +1815,7 @@ where fullscreen: Tracked::from(settings.fullscreen).ignoring_first(), shortcuts: settings.shortcuts, on_file_drop: settings.on_file_drop, + disabled_resize_automatically: false, }; this.synchronize_platform_window(&mut window); @@ -1854,7 +1856,7 @@ where self.new_frame(graphics); let resize_to_fit = self.resize_to_fit.get(); - let resizable = window.is_resizable() || resize_to_fit; + let resizable = *self.resizable.peek() || resize_to_fit; let mut window = RunningWindow::new( window, graphics.id(), @@ -1883,13 +1885,9 @@ where ), gfx: Exclusive::Owned(Graphics::new(graphics)), }; - if self.initial_frame { - self.root - .lock() - .as_widget() - .mounted(&mut context.as_event_context()); - } self.theme_mode.redraw_when_changed(&context); + self.inner_size.invalidate_when_changed(&context); + self.resize_to_fit.invalidate_when_changed(&context); let mut layout_context = LayoutContext::new(&mut context); let window_size = layout_context.gfx.size(); @@ -1910,19 +1908,12 @@ where layout_size }; let render_size = actual_size.min(window_size); - layout_context.invalidate_when_changed(&self.inner_size); - layout_context.invalidate_when_changed(&self.resize_to_fit); self.root.set_layout(Rect::from(render_size.into_signed())); if self.initial_frame { self.initial_frame = false; - self.root - .lock() - .as_widget() - .mounted(&mut layout_context.as_event_context()); - layout_context.focus(); - layout_context.as_event_context().apply_pending_state(); + Self::mount_and_focus_root(&self.root, &mut layout_context); } if render_size.width < window_size.width || render_size.height < window_size.height { @@ -1933,6 +1924,15 @@ where layout_context.redraw(); } + let resizable = resizable + && !Self::enforce_fixed_size( + self.max_inner_size, + self.max_inner_size, + &self.resizable, + &mut self.disabled_resize_automatically, + &mut layout_context, + ); + let new_size = if let Some(new_size) = self.inner_size.updated() { layout_context.request_inner_size(*new_size) } else if actual_size != window_size && !resizable { @@ -1959,6 +1959,38 @@ where layout_context.as_event_context().update_hovered_widget(); } + fn mount_and_focus_root(root: &MountedWidget, context: &mut LayoutContext<'_, '_, '_, '_>) { + root.lock() + .as_widget() + .mounted(&mut context.as_event_context()); + context.focus(); + context.as_event_context().apply_pending_state(); + } + + fn enforce_fixed_size( + min_inner_size: Option>, + max_inner_size: Option>, + resizable: &Tracked>, + disabled_resize_automatically: &mut bool, + context: &mut LayoutContext<'_, '_, '_, '_>, + ) -> bool { + let fixed_size = max_inner_size.is_some() + && min_inner_size.is_some() + && max_inner_size == min_inner_size; + if fixed_size && *resizable.peek() && !*disabled_resize_automatically { + *disabled_resize_automatically = true; + if let Some(winit) = context.window().winit() { + winit.set_resizable(false); + } + } else if !fixed_size && *resizable.peek() && *disabled_resize_automatically { + *disabled_resize_automatically = false; + if let Some(winit) = context.window().winit() { + winit.set_resizable(true); + } + } + fixed_size + } + fn close_requested(&mut self, window: W, kludgine: &mut Kludgine) -> bool where W: PlatformWindowImplementation, @@ -2066,6 +2098,7 @@ where }); when_updated!(resizable, handle, { winit.set_resizable(*resizable); + println!("Setting resizable {resizable}"); redraw = true; }); when_updated!(window_icon, handle, {