Fine-tune event loop of multi-window applications

This commit is contained in:
Héctor Ramón Jiménez 2024-01-17 08:05:19 +01:00
parent 03f5a351c3
commit 985acb2b15
No known key found for this signature in database
GPG key ID: 7CC46565708259A7

View file

@ -229,8 +229,22 @@ where
task::Poll::Pending => match control_receiver.try_next() { task::Poll::Pending => match control_receiver.try_next() {
Ok(Some(control)) => match control { Ok(Some(control)) => match control {
Control::ChangeFlow(flow) => { Control::ChangeFlow(flow) => {
use winit::event_loop::ControlFlow;
match (event_loop.control_flow(), flow) {
(
ControlFlow::WaitUntil(current),
ControlFlow::WaitUntil(new),
) if new < current => {}
(
ControlFlow::WaitUntil(target),
ControlFlow::Wait,
) if target > Instant::now() => {}
_ => {
event_loop.set_control_flow(flow); event_loop.set_control_flow(flow);
} }
}
}
Control::CreateWindow { Control::CreateWindow {
id, id,
settings, settings,
@ -362,7 +376,6 @@ async fn run_instance<A, E, C>(
runtime.track(application.subscription().into_recipes()); runtime.track(application.subscription().into_recipes());
let mut messages = Vec::new(); let mut messages = Vec::new();
let mut redraw_pending = false;
debug.startup_finished(); debug.startup_finished();
@ -409,13 +422,15 @@ async fn run_instance<A, E, C>(
} }
Event::EventLoopAwakened(event) => { Event::EventLoopAwakened(event) => {
match event { match event {
event::Event::NewEvents(start_cause) => { event::Event::NewEvents(
redraw_pending = matches!(
start_cause,
event::StartCause::Init event::StartCause::Init
| event::StartCause::Poll | event::StartCause::ResumeTimeReached { .. },
| event::StartCause::ResumeTimeReached { .. } ) => {
); for (_id, window) in window_manager.iter_mut() {
// TODO once widgets can request to be redrawn, we can avoid always requesting a
// redraw
window.raw.request_redraw();
}
} }
event::Event::PlatformSpecific( event::Event::PlatformSpecific(
event::PlatformSpecific::MacOS( event::PlatformSpecific::MacOS(
@ -503,7 +518,9 @@ async fn run_instance<A, E, C>(
redraw_request: Some(redraw_request), redraw_request: Some(redraw_request),
} => match redraw_request { } => match redraw_request {
window::RedrawRequest::NextFrame => { window::RedrawRequest::NextFrame => {
ControlFlow::Poll window.raw.request_redraw();
ControlFlow::Wait
} }
window::RedrawRequest::At(at) => { window::RedrawRequest::At(at) => {
ControlFlow::WaitUntil(at) ControlFlow::WaitUntil(at)
@ -653,9 +670,9 @@ async fn run_instance<A, E, C>(
} }
} }
} }
_ => {} event::Event::AboutToWait => {
} if events.is_empty() && messages.is_empty() {
} continue;
} }
debug.event_processing_started(); debug.event_processing_started();
@ -665,7 +682,8 @@ async fn run_instance<A, E, C>(
let mut window_events = vec![]; let mut window_events = vec![];
events.retain(|(window_id, event)| { events.retain(|(window_id, event)| {
if *window_id == Some(id) || window_id.is_none() { if *window_id == Some(id) || window_id.is_none()
{
window_events.push(event.clone()); window_events.push(event.clone());
false false
} else { } else {
@ -673,10 +691,7 @@ async fn run_instance<A, E, C>(
} }
}); });
if !redraw_pending if window_events.is_empty() && messages.is_empty() {
&& window_events.is_empty()
&& messages.is_empty()
{
continue; continue;
} }
@ -691,12 +706,18 @@ async fn run_instance<A, E, C>(
&mut messages, &mut messages,
); );
window.raw.request_redraw();
if !uis_stale { if !uis_stale {
uis_stale = matches!(ui_state, user_interface::State::Outdated); uis_stale = matches!(
ui_state,
user_interface::State::Outdated
);
} }
for (event, status) in for (event, status) in window_events
window_events.into_iter().zip(statuses.into_iter()) .into_iter()
.zip(statuses.into_iter())
{ {
runtime.broadcast(event, status); runtime.broadcast(event, status);
} }
@ -731,25 +752,31 @@ async fn run_instance<A, E, C>(
// we must synchronize all window states with application state after an // we must synchronize all window states with application state after an
// application update since we don't know what changed // application update since we don't know what changed
for (id, window) in window_manager.iter_mut() { for (id, window) in window_manager.iter_mut() {
window.state.synchronize(&application, id, &window.raw); window.state.synchronize(
&application,
id,
&window.raw,
);
// TODO once widgets can request to be redrawn, we can avoid always requesting a
// redraw
window.raw.request_redraw();
} }
// rebuild UIs with the synchronized states // rebuild UIs with the synchronized states
user_interfaces = ManuallyDrop::new(build_user_interfaces( user_interfaces =
ManuallyDrop::new(build_user_interfaces(
&application, &application,
&mut debug, &mut debug,
&mut window_manager, &mut window_manager,
cached_interfaces, cached_interfaces,
)); ));
} }
for (_id, window) in window_manager.iter_mut() {
// TODO once widgets can request to be redrawn, we can avoid always requesting a
// redraw
window.raw.request_redraw();
} }
_ => {}
redraw_pending = false; }
}
}
} }
let _ = ManuallyDrop::into_inner(user_interfaces); let _ = ManuallyDrop::into_inner(user_interfaces);