From 859d6bb97220db41e7fd8e85fbfbd9ddbdb8e1a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9ctor=20Ram=C3=B3n=20Jim=C3=A9nez?= Date: Wed, 15 Oct 2025 20:04:44 +0200 Subject: [PATCH] Run a `Task` synchronously if immediately available --- winit/src/lib.rs | 93 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 84 insertions(+), 9 deletions(-) diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 802b446b..b239260b 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -554,7 +554,7 @@ async fn run_instance

( log::info!("System theme: {system_theme:?}"); - loop { + 'next_event: loop { // Empty the queue if possible let event = if let Ok(event) = event_receiver.try_next() { event @@ -770,7 +770,8 @@ async fn run_instance

( event: event::WindowEvent::RedrawRequested, .. } => { - let Some(compositor) = &mut compositor else { + let Some(mut current_compositor) = compositor.as_mut() + else { continue; }; @@ -803,7 +804,7 @@ async fn run_instance

( ); layout_span.finish(); - compositor.configure_surface( + current_compositor.configure_surface( &mut window.surface, physical_size.width, physical_size.height, @@ -860,7 +861,11 @@ async fn run_instance

( }) .collect(); - update(&mut program, &mut runtime, &mut messages); + let actions = update( + &mut program, + &mut runtime, + &mut messages, + ); user_interfaces = ManuallyDrop::new(build_user_interfaces( @@ -869,6 +874,30 @@ async fn run_instance

( caches, )); + for action in actions { + run_action( + action, + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + ); + } + + let Some(next_compositor) = compositor.as_mut() + else { + continue 'next_event; + }; + + current_compositor = next_compositor; window = window_manager.get_mut(id).unwrap(); interface = user_interfaces.get_mut(&id).unwrap(); }; @@ -904,7 +933,7 @@ async fn run_instance

( window.draw_preedit(); let present_span = debug::present(id); - match compositor.present( + match current_compositor.present( &mut window.renderer, &mut window.surface, window.state.viewport(), @@ -1119,7 +1148,11 @@ async fn run_instance

( .map(|(id, ui)| (id, ui.into_cache())) .collect(); - update(&mut program, &mut runtime, &mut messages); + let actions = update( + &mut program, + &mut runtime, + &mut messages, + ); user_interfaces = ManuallyDrop::new(build_user_interfaces( @@ -1127,6 +1160,24 @@ async fn run_instance

( &mut window_manager, cached_interfaces, )); + + for action in actions { + run_action( + action, + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + ); + } } if let Some(redraw_at) = window_manager.redraw_at() { @@ -1176,14 +1227,36 @@ fn update( program: &mut program::Instance

, runtime: &mut Runtime, Action>, messages: &mut Vec, -) where +) -> Vec> +where P::Theme: theme::Base, { + use futures::futures; + + let mut actions = Vec::new(); + for message in messages.drain(..) { let task = runtime.enter(|| program.update(message)); - if let Some(stream) = runtime::task::into_stream(task) { - runtime.run(stream); + if let Some(mut stream) = runtime::task::into_stream(task) { + let waker = futures::task::noop_waker_ref(); + let mut context = futures::task::Context::from_waker(waker); + + // Run immediately available actions synchronously (e.g. widget operations) + loop { + match runtime.enter(|| stream.poll_next_unpin(&mut context)) { + futures::task::Poll::Ready(Some(action)) => { + actions.push(action); + } + futures::task::Poll::Ready(None) => { + break; + } + futures::task::Poll::Pending => { + runtime.run(stream); + break; + } + } + } } } @@ -1191,6 +1264,8 @@ fn update( let recipes = subscription::into_recipes(subscription.map(Action::Output)); runtime.track(recipes); + + actions } fn run_action<'a, P, C>(