diff options
author | 2023-01-12 02:59:08 +0100 | |
---|---|---|
committer | 2023-01-12 02:59:08 +0100 | |
commit | 7354f68b3ca345767de3f09dccddf168493977bf (patch) | |
tree | a09626c11a25ab4260c576733f1700e9ad12894b /winit/src/application.rs | |
parent | 7ccd87c36b54e0d53f65f5774f140a0528ae4504 (diff) | |
download | iced-7354f68b3ca345767de3f09dccddf168493977bf.tar.gz iced-7354f68b3ca345767de3f09dccddf168493977bf.tar.bz2 iced-7354f68b3ca345767de3f09dccddf168493977bf.zip |
Draft `Shell:request_redraw` API
... and implement `TextInput` cursor blink :tada:
Diffstat (limited to 'winit/src/application.rs')
-rw-r--r-- | winit/src/application.rs | 72 |
1 files changed, 61 insertions, 11 deletions
diff --git a/winit/src/application.rs b/winit/src/application.rs index 74c73815..0f5309d2 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -11,7 +11,7 @@ use crate::mouse; use crate::renderer; use crate::widget::operation; use crate::{ - Command, Debug, Error, Executor, Proxy, Runtime, Settings, Size, + Command, Debug, Error, Event, Executor, Proxy, Runtime, Settings, Size, Subscription, }; @@ -25,6 +25,7 @@ use iced_native::user_interface::{self, UserInterface}; pub use iced_native::application::{Appearance, StyleSheet}; use std::mem::ManuallyDrop; +use std::time::Instant; #[cfg(feature = "trace")] pub use profiler::Profiler; @@ -186,7 +187,8 @@ where let (compositor, renderer) = C::new(compositor_settings, Some(&window))?; - let (mut sender, receiver) = mpsc::unbounded(); + let (mut event_sender, event_receiver) = mpsc::unbounded(); + let (control_sender, mut control_receiver) = mpsc::unbounded(); let mut instance = Box::pin({ let run_instance = run_instance::<A, E, C>( @@ -196,7 +198,8 @@ where runtime, proxy, debug, - receiver, + event_receiver, + control_sender, init_command, window, settings.exit_on_close_request, @@ -234,13 +237,19 @@ where }; if let Some(event) = event { - sender.start_send(event).expect("Send event"); + event_sender.start_send(event).expect("Send event"); let poll = instance.as_mut().poll(&mut context); - *control_flow = match poll { - task::Poll::Pending => ControlFlow::Wait, - task::Poll::Ready(_) => ControlFlow::Exit, + match poll { + task::Poll::Pending => { + if let Ok(Some(flow)) = control_receiver.try_next() { + *control_flow = flow; + } + } + task::Poll::Ready(_) => { + *control_flow = ControlFlow::Exit; + } }; } }) @@ -253,7 +262,10 @@ async fn run_instance<A, E, C>( mut runtime: Runtime<E, Proxy<A::Message>, A::Message>, mut proxy: winit::event_loop::EventLoopProxy<A::Message>, mut debug: Debug, - mut receiver: mpsc::UnboundedReceiver<winit::event::Event<'_, A::Message>>, + mut event_receiver: mpsc::UnboundedReceiver< + winit::event::Event<'_, A::Message>, + >, + mut control_sender: mpsc::UnboundedSender<winit::event_loop::ControlFlow>, init_command: Command<A::Message>, window: winit::window::Window, exit_on_close_request: bool, @@ -265,6 +277,7 @@ async fn run_instance<A, E, C>( { use iced_futures::futures::stream::StreamExt; use winit::event; + use winit::event_loop::ControlFlow; let mut clipboard = Clipboard::connect(&window); let mut cache = user_interface::Cache::default(); @@ -309,13 +322,21 @@ async fn run_instance<A, E, C>( let mut mouse_interaction = mouse::Interaction::default(); let mut events = Vec::new(); let mut messages = Vec::new(); + let mut redraw_pending = false; debug.startup_finished(); - while let Some(event) = receiver.next().await { + while let Some(event) = event_receiver.next().await { match event { + event::Event::NewEvents(start_cause) => { + redraw_pending = matches!( + start_cause, + event::StartCause::Init + | event::StartCause::ResumeTimeReached { .. } + ); + } event::Event::MainEventsCleared => { - if events.is_empty() && messages.is_empty() { + if !redraw_pending && events.is_empty() && messages.is_empty() { continue; } @@ -338,7 +359,7 @@ async fn run_instance<A, E, C>( if !messages.is_empty() || matches!( interface_state, - user_interface::State::Outdated, + user_interface::State::Outdated ) { let mut cache = @@ -376,6 +397,24 @@ async fn run_instance<A, E, C>( } } + // 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 whether + // if a redraw is needed right away, or simply wait until a + // specific time. + let redraw_event = Event::Window( + crate::window::Event::RedrawRequested(Instant::now()), + ); + + let (interface_state, _) = user_interface.update( + &[redraw_event.clone()], + state.cursor_position(), + &mut renderer, + &mut clipboard, + &mut messages, + ); + debug.draw_started(); let new_mouse_interaction = user_interface.draw( &mut renderer, @@ -396,6 +435,17 @@ async fn run_instance<A, E, C>( } window.request_redraw(); + runtime + .broadcast((redraw_event, crate::event::Status::Ignored)); + + let _ = control_sender.start_send(match interface_state { + user_interface::State::Updated { + redraw_requested_at: Some(at), + } => ControlFlow::WaitUntil(at), + _ => ControlFlow::Wait, + }); + + redraw_pending = false; } event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( event::MacOS::ReceivedUrl(url), |