diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 59d91f42..504dbe0f 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -388,6 +388,23 @@ where
}
}
+ /// Relayouts and returns a new [`UserInterface`] using the provided
+ /// bounds.
+ ///
+ /// [`UserInterface`]: struct.UserInterface.html
+ pub fn relayout(self, bounds: Size, renderer: &mut Renderer) -> Self {
+ Self::build(
+ self.root,
+ bounds,
+ Cache {
+ base: self.base,
+ overlay: self.overlay,
+ bounds: self.bounds,
+ },
+ renderer,
+ )
+ }
+
/// Extract the [`Cache`] of the [`UserInterface`], consuming it in the
/// process.
///
diff --git a/winit/src/application.rs b/winit/src/application.rs
index dcc5a282..96438d73 100644
--- a/winit/src/application.rs
+++ b/winit/src/application.rs
@@ -9,12 +9,14 @@ use crate::{
Clipboard, Color, Command, Debug, Error, Executor, Mode, Proxy, Runtime,
Settings, Size, Subscription,
};
+
+use iced_futures::futures;
+use iced_futures::futures::channel::mpsc;
use iced_graphics::window;
use iced_native::program::Program;
use iced_native::{Cache, UserInterface};
-use iced_futures::futures;
-use iced_futures::futures::channel::mpsc;
+use std::mem::ManuallyDrop;
/// An interactive, native cross-platform application.
///
@@ -214,8 +216,9 @@ async fn run_instance(
let mut state = State::new(&application, &window);
let surface = compositor.create_surface(&window);
- let mut physical_size = state.physical_size();
+ let physical_size = state.physical_size();
+ let mut viewport_version = state.viewport_version();
let mut swap_chain = compositor.create_swap_chain(
&surface,
physical_size.width,
@@ -224,7 +227,7 @@ async fn run_instance(
let clipboard = Clipboard::new(&window);
- let mut user_interface = std::mem::ManuallyDrop::new(build_user_interface(
+ let mut user_interface = ManuallyDrop::new(build_user_interface(
&mut application,
Cache::default(),
&mut renderer,
@@ -267,8 +270,7 @@ async fn run_instance(
debug.draw_finished();
} else {
let cache =
- std::mem::ManuallyDrop::into_inner(user_interface)
- .into_cache();
+ ManuallyDrop::into_inner(user_interface).into_cache();
for message in messages.drain(..) {
debug.log_message(&message);
@@ -288,14 +290,13 @@ async fn run_instance(
// Update window
state.synchronize(&application, &window);
- user_interface =
- std::mem::ManuallyDrop::new(build_user_interface(
- &mut application,
- cache,
- &mut renderer,
- state.logical_size(),
- &mut debug,
- ));
+ user_interface = ManuallyDrop::new(build_user_interface(
+ &mut application,
+ cache,
+ &mut renderer,
+ state.logical_size(),
+ &mut debug,
+ ));
debug.draw_started();
primitive = user_interface
@@ -310,17 +311,31 @@ async fn run_instance(
}
event::Event::RedrawRequested(_) => {
debug.render_started();
+ let current_viewport_version = state.viewport_version();
- let current_physical_size = state.physical_size();
+ if viewport_version != current_viewport_version {
+ let physical_size = state.physical_size();
+ let logical_size = state.logical_size();
+
+ debug.layout_started();
+ user_interface = ManuallyDrop::new(
+ ManuallyDrop::into_inner(user_interface)
+ .relayout(logical_size, &mut renderer),
+ );
+ debug.layout_finished();
+
+ debug.draw_started();
+ primitive = user_interface
+ .draw(&mut renderer, state.cursor_position());
+ debug.draw_finished();
- if physical_size != current_physical_size {
swap_chain = compositor.create_swap_chain(
&surface,
physical_size.width,
physical_size.height,
);
- physical_size = current_physical_size;
+ viewport_version = current_viewport_version;
}
let new_mouse_interaction = compositor.draw(
diff --git a/winit/src/application/state.rs b/winit/src/application/state.rs
index 7de3ecef..1f3c77a0 100644
--- a/winit/src/application/state.rs
+++ b/winit/src/application/state.rs
@@ -12,6 +12,7 @@ pub struct State {
background_color: Color,
scale_factor: f64,
viewport: Viewport,
+ viewport_version: usize,
cursor_position: winit::dpi::PhysicalPosition,
modifiers: winit::event::ModifiersState,
application: PhantomData,
@@ -39,6 +40,7 @@ impl State {
background_color,
scale_factor,
viewport,
+ viewport_version: 0,
// TODO: Encode cursor availability in the type-system
cursor_position: winit::dpi::PhysicalPosition::new(-1.0, -1.0),
modifiers: winit::event::ModifiersState::default(),
@@ -54,6 +56,10 @@ impl State {
&self.viewport
}
+ pub fn viewport_version(&self) -> usize {
+ self.viewport_version
+ }
+
pub fn physical_size(&self) -> Size {
self.viewport.physical_size()
}
@@ -91,6 +97,8 @@ impl State {
size,
window.scale_factor() * self.scale_factor,
);
+
+ self.viewport_version = self.viewport_version.wrapping_add(1);
}
WindowEvent::ScaleFactorChanged {
scale_factor: new_scale_factor,
@@ -103,6 +111,8 @@ impl State {
size,
new_scale_factor * self.scale_factor,
);
+
+ self.viewport_version = self.viewport_version.wrapping_add(1);
}
WindowEvent::CursorMoved { position, .. } => {
self.cursor_position = *position;