summaryrefslogtreecommitdiffstats
path: root/winit/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--winit/src/program.rs185
-rw-r--r--winit/src/program/state.rs5
-rw-r--r--winit/src/program/window_manager.rs16
3 files changed, 118 insertions, 88 deletions
diff --git a/winit/src/program.rs b/winit/src/program.rs
index 8d1eec3a..130bf220 100644
--- a/winit/src/program.rs
+++ b/winit/src/program.rs
@@ -758,12 +758,23 @@ async fn run_instance<P, C>(
}
Event::EventLoopAwakened(event) => {
match event {
+ event::Event::NewEvents(event::StartCause::Init) => {
+ for (_id, window) in window_manager.iter_mut() {
+ window.raw.request_redraw();
+ }
+ }
event::Event::NewEvents(
- event::StartCause::Init
- | event::StartCause::ResumeTimeReached { .. },
+ event::StartCause::ResumeTimeReached { .. },
) => {
+ let now = Instant::now();
+
for (_id, window) in window_manager.iter_mut() {
- window.raw.request_redraw();
+ if let Some(redraw_at) = window.redraw_at {
+ if redraw_at <= now {
+ window.raw.request_redraw();
+ window.redraw_at = None;
+ }
+ }
}
}
event::Event::PlatformSpecific(
@@ -807,11 +818,39 @@ async fn run_instance<P, C>(
continue;
};
- // TODO: Avoid redrawing all the time by forcing widgets to
- // request redraws on state changes
- //
- // Then, we can use the `interface_state` here to decide if a redraw
- // is needed right away, or simply wait until a specific time.
+ let physical_size = window.state.physical_size();
+
+ if physical_size.width == 0 || physical_size.height == 0
+ {
+ continue;
+ }
+
+ if window.viewport_version
+ != window.state.viewport_version()
+ {
+ let logical_size = window.state.logical_size();
+
+ debug.layout_started();
+ let ui = user_interfaces
+ .remove(&id)
+ .expect("Remove user interface");
+
+ let _ = user_interfaces.insert(
+ id,
+ ui.relayout(logical_size, &mut window.renderer),
+ );
+ debug.layout_finished();
+
+ compositor.configure_surface(
+ &mut window.surface,
+ physical_size.width,
+ physical_size.height,
+ );
+
+ window.viewport_version =
+ window.state.viewport_version();
+ }
+
let redraw_event = core::Event::Window(
window::Event::RedrawRequested(Instant::now()),
);
@@ -857,81 +896,18 @@ async fn run_instance<P, C>(
status: core::event::Status::Ignored,
});
- let _ = control_sender.start_send(Control::ChangeFlow(
- match ui_state {
- user_interface::State::Updated {
- redraw_request: Some(redraw_request),
- } => match redraw_request {
- window::RedrawRequest::NextFrame => {
- window.raw.request_redraw();
-
- ControlFlow::Wait
- }
- window::RedrawRequest::At(at) => {
- ControlFlow::WaitUntil(at)
- }
- },
- _ => ControlFlow::Wait,
- },
- ));
-
- let physical_size = window.state.physical_size();
-
- if physical_size.width == 0 || physical_size.height == 0
+ if let user_interface::State::Updated {
+ redraw_request: Some(redraw_request),
+ } = ui_state
{
- continue;
- }
-
- if window.viewport_version
- != window.state.viewport_version()
- {
- let logical_size = window.state.logical_size();
-
- debug.layout_started();
- let ui = user_interfaces
- .remove(&id)
- .expect("Remove user interface");
-
- let _ = user_interfaces.insert(
- id,
- ui.relayout(logical_size, &mut window.renderer),
- );
- debug.layout_finished();
-
- debug.draw_started();
- let new_mouse_interaction = user_interfaces
- .get_mut(&id)
- .expect("Get user interface")
- .draw(
- &mut window.renderer,
- window.state.theme(),
- &renderer::Style {
- text_color: window.state.text_color(),
- },
- window.state.cursor(),
- );
- debug.draw_finished();
-
- if new_mouse_interaction != window.mouse_interaction
- {
- window.raw.set_cursor(
- conversion::mouse_interaction(
- new_mouse_interaction,
- ),
- );
-
- window.mouse_interaction =
- new_mouse_interaction;
+ match redraw_request {
+ window::RedrawRequest::NextFrame => {
+ window.raw.request_redraw();
+ }
+ window::RedrawRequest::At(at) => {
+ window.redraw_at = Some(at);
+ }
}
-
- compositor.configure_surface(
- &mut window.surface,
- physical_size.width,
- physical_size.height,
- );
-
- window.viewport_version =
- window.state.viewport_version();
}
debug.render_started();
@@ -995,6 +971,13 @@ async fn run_instance<P, C>(
if matches!(
window_event,
+ winit::event::WindowEvent::Resized(_)
+ ) {
+ window.raw.request_redraw();
+ }
+
+ if matches!(
+ window_event,
winit::event::WindowEvent::CloseRequested
) && window.exit_on_close_request
{
@@ -1031,7 +1014,10 @@ async fn run_instance<P, C>(
}
}
event::Event::AboutToWait => {
- if events.is_empty() && messages.is_empty() {
+ if events.is_empty()
+ && messages.is_empty()
+ && window_manager.is_idle()
+ {
continue;
}
@@ -1065,13 +1051,27 @@ async fn run_instance<P, C>(
&mut messages,
);
+ #[cfg(feature = "unconditional-rendering")]
window.raw.request_redraw();
- if !uis_stale {
- uis_stale = matches!(
- ui_state,
- user_interface::State::Outdated
- );
+ match ui_state {
+ #[cfg(not(
+ feature = "unconditional-rendering"
+ ))]
+ user_interface::State::Updated {
+ redraw_request: Some(redraw_request),
+ } => match redraw_request {
+ window::RedrawRequest::NextFrame => {
+ window.raw.request_redraw();
+ }
+ window::RedrawRequest::At(at) => {
+ window.redraw_at = Some(at);
+ }
+ },
+ user_interface::State::Outdated => {
+ uis_stale = true;
+ }
+ user_interface::State::Updated { .. } => {}
}
for (event, status) in window_events
@@ -1139,6 +1139,17 @@ async fn run_instance<P, C>(
actions = 0;
}
}
+
+ if let Some(redraw_at) = window_manager.redraw_at() {
+ let _ =
+ control_sender.start_send(Control::ChangeFlow(
+ ControlFlow::WaitUntil(redraw_at),
+ ));
+ } else {
+ let _ = control_sender.start_send(
+ Control::ChangeFlow(ControlFlow::Wait),
+ );
+ }
}
_ => {}
}
diff --git a/winit/src/program/state.rs b/winit/src/program/state.rs
index a7fa2788..b8a58960 100644
--- a/winit/src/program/state.rs
+++ b/winit/src/program/state.rs
@@ -190,7 +190,10 @@ where
..
},
..
- } => _debug.toggle(),
+ } => {
+ _debug.toggle();
+ window.request_redraw();
+ }
_ => {}
}
}
diff --git a/winit/src/program/window_manager.rs b/winit/src/program/window_manager.rs
index 3d22e155..10a973fe 100644
--- a/winit/src/program/window_manager.rs
+++ b/winit/src/program/window_manager.rs
@@ -1,4 +1,5 @@
use crate::core::mouse;
+use crate::core::time::Instant;
use crate::core::window::Id;
use crate::core::{Point, Size};
use crate::graphics::Compositor;
@@ -62,6 +63,7 @@ where
surface,
renderer,
mouse_interaction: mouse::Interaction::None,
+ redraw_at: None,
},
);
@@ -74,6 +76,19 @@ where
self.entries.is_empty()
}
+ pub fn is_idle(&self) -> bool {
+ self.entries
+ .values()
+ .all(|window| window.redraw_at.is_none())
+ }
+
+ pub fn redraw_at(&self) -> Option<Instant> {
+ self.entries
+ .values()
+ .filter_map(|window| window.redraw_at)
+ .min()
+ }
+
pub fn first(&self) -> Option<&Window<P, C>> {
self.entries.first_key_value().map(|(_id, window)| window)
}
@@ -138,6 +153,7 @@ where
pub mouse_interaction: mouse::Interaction,
pub surface: C::Surface,
pub renderer: P::Renderer,
+ pub redraw_at: Option<Instant>,
}
impl<P, C> Window<P, C>