Replace Option<Instant> with RedrawRequest enum

This commit is contained in:
Héctor Ramón Jiménez 2023-01-12 05:18:25 +01:00
parent 502c9bfbf6
commit e2ddef7438
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
8 changed files with 84 additions and 31 deletions

View file

@ -270,6 +270,7 @@ async fn run_instance<A, E, C>(
redraw_pending = matches!( redraw_pending = matches!(
start_cause, start_cause,
event::StartCause::Init event::StartCause::Init
| event::StartCause::Poll
| event::StartCause::ResumeTimeReached { .. } | event::StartCause::ResumeTimeReached { .. }
); );
} }
@ -379,8 +380,15 @@ async fn run_instance<A, E, C>(
let _ = control_sender.start_send(match interface_state { let _ = control_sender.start_send(match interface_state {
user_interface::State::Updated { user_interface::State::Updated {
redraw_requested_at: Some(at), redraw_request: Some(redraw_request),
} => ControlFlow::WaitUntil(at), } => match redraw_request {
crate::window::RedrawRequest::NextFrame => {
ControlFlow::Poll
}
crate::window::RedrawRequest::At(at) => {
ControlFlow::WaitUntil(at)
}
},
_ => ControlFlow::Wait, _ => ControlFlow::Wait,
}); });

View file

@ -1,4 +1,4 @@
use std::time::Instant; use crate::window;
/// A connection to the state of a shell. /// A connection to the state of a shell.
/// ///
@ -9,7 +9,7 @@ use std::time::Instant;
#[derive(Debug)] #[derive(Debug)]
pub struct Shell<'a, Message> { pub struct Shell<'a, Message> {
messages: &'a mut Vec<Message>, messages: &'a mut Vec<Message>,
redraw_requested_at: Option<Instant>, redraw_request: Option<window::RedrawRequest>,
is_layout_invalid: bool, is_layout_invalid: bool,
are_widgets_invalid: bool, are_widgets_invalid: bool,
} }
@ -19,7 +19,7 @@ impl<'a, Message> Shell<'a, Message> {
pub fn new(messages: &'a mut Vec<Message>) -> Self { pub fn new(messages: &'a mut Vec<Message>) -> Self {
Self { Self {
messages, messages,
redraw_requested_at: None, redraw_request: None,
is_layout_invalid: false, is_layout_invalid: false,
are_widgets_invalid: false, are_widgets_invalid: false,
} }
@ -31,21 +31,21 @@ impl<'a, Message> Shell<'a, Message> {
} }
/// Requests a new frame to be drawn at the given [`Instant`]. /// Requests a new frame to be drawn at the given [`Instant`].
pub fn request_redraw(&mut self, at: Instant) { pub fn request_redraw(&mut self, request: window::RedrawRequest) {
match self.redraw_requested_at { match self.redraw_request {
None => { None => {
self.redraw_requested_at = Some(at); self.redraw_request = Some(request);
} }
Some(current) if at < current => { Some(current) if request < current => {
self.redraw_requested_at = Some(at); self.redraw_request = Some(request);
} }
_ => {} _ => {}
} }
} }
/// Returns the requested [`Instant`] a redraw should happen, if any. /// Returns the requested [`Instant`] a redraw should happen, if any.
pub fn redraw_requested_at(&self) -> Option<Instant> { pub fn redraw_request(&self) -> Option<window::RedrawRequest> {
self.redraw_requested_at self.redraw_request
} }
/// Returns whether the current layout is invalid or not. /// Returns whether the current layout is invalid or not.
@ -90,7 +90,7 @@ impl<'a, Message> Shell<'a, Message> {
pub fn merge<B>(&mut self, other: Shell<'_, B>, f: impl Fn(B) -> Message) { pub fn merge<B>(&mut self, other: Shell<'_, B>, f: impl Fn(B) -> Message) {
self.messages.extend(other.messages.drain(..).map(f)); self.messages.extend(other.messages.drain(..).map(f));
if let Some(at) = other.redraw_requested_at { if let Some(at) = other.redraw_request {
self.request_redraw(at); self.request_redraw(at);
} }

View file

@ -5,10 +5,9 @@ use crate::layout;
use crate::mouse; use crate::mouse;
use crate::renderer; use crate::renderer;
use crate::widget; use crate::widget;
use crate::window;
use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size}; use crate::{Clipboard, Element, Layout, Point, Rectangle, Shell, Size};
use std::time::Instant;
/// A set of interactive graphical elements with a specific [`Layout`]. /// A set of interactive graphical elements with a specific [`Layout`].
/// ///
/// It can be updated and drawn. /// It can be updated and drawn.
@ -191,7 +190,7 @@ where
use std::mem::ManuallyDrop; use std::mem::ManuallyDrop;
let mut outdated = false; let mut outdated = false;
let mut redraw_requested_at = None; let mut redraw_request = None;
let mut manual_overlay = let mut manual_overlay =
ManuallyDrop::new(self.root.as_widget_mut().overlay( ManuallyDrop::new(self.root.as_widget_mut().overlay(
@ -221,12 +220,12 @@ where
event_statuses.push(event_status); event_statuses.push(event_status);
match (redraw_requested_at, shell.redraw_requested_at()) { match (redraw_request, shell.redraw_request()) {
(None, Some(at)) => { (None, Some(at)) => {
redraw_requested_at = Some(at); redraw_request = Some(at);
} }
(Some(current), Some(new)) if new < current => { (Some(current), Some(new)) if new < current => {
redraw_requested_at = Some(new); redraw_request = Some(new);
} }
_ => {} _ => {}
} }
@ -303,12 +302,12 @@ where
self.overlay = None; self.overlay = None;
} }
match (redraw_requested_at, shell.redraw_requested_at()) { match (redraw_request, shell.redraw_request()) {
(None, Some(at)) => { (None, Some(at)) => {
redraw_requested_at = Some(at); redraw_request = Some(at);
} }
(Some(current), Some(new)) if new < current => { (Some(current), Some(new)) if new < current => {
redraw_requested_at = Some(new); redraw_request = Some(new);
} }
_ => {} _ => {}
} }
@ -334,9 +333,7 @@ where
if outdated { if outdated {
State::Outdated State::Outdated
} else { } else {
State::Updated { State::Updated { redraw_request }
redraw_requested_at,
}
}, },
event_statuses, event_statuses,
) )
@ -594,6 +591,6 @@ pub enum State {
/// rebuilding. /// rebuilding.
Updated { Updated {
/// The [`Instant`] when a redraw should be performed. /// The [`Instant`] when a redraw should be performed.
redraw_requested_at: Option<Instant>, redraw_request: Option<window::RedrawRequest>,
}, },
} }

View file

@ -793,9 +793,9 @@ where
- (now - focus.updated_at).as_millis() - (now - focus.updated_at).as_millis()
% CURSOR_BLINK_INTERVAL_MILLIS; % CURSOR_BLINK_INTERVAL_MILLIS;
shell.request_redraw( shell.request_redraw(window::RedrawRequest::At(
now + Duration::from_millis(millis_until_redraw as u64), now + Duration::from_millis(millis_until_redraw as u64),
); ));
} }
} }
_ => {} _ => {}

View file

@ -2,11 +2,13 @@
mod action; mod action;
mod event; mod event;
mod mode; mod mode;
mod redraw_request;
mod user_attention; mod user_attention;
pub use action::Action; pub use action::Action;
pub use event::Event; pub use event::Event;
pub use mode::Mode; pub use mode::Mode;
pub use redraw_request::RedrawRequest;
pub use user_attention::UserAttention; pub use user_attention::UserAttention;
use crate::subscription::{self, Subscription}; use crate::subscription::{self, Subscription};

View file

@ -0,0 +1,38 @@
use std::time::Instant;
/// A request to redraw a window.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum RedrawRequest {
/// Redraw the next frame.
NextFrame,
/// Redraw at the given time.
At(Instant),
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::{Duration, Instant};
#[test]
fn ordering() {
let now = Instant::now();
let later = now + Duration::from_millis(10);
assert_eq!(RedrawRequest::NextFrame, RedrawRequest::NextFrame);
assert_eq!(RedrawRequest::At(now), RedrawRequest::At(now));
assert!(RedrawRequest::NextFrame < RedrawRequest::At(now));
assert!(RedrawRequest::At(now) > RedrawRequest::NextFrame);
assert!(RedrawRequest::At(now) < RedrawRequest::At(later));
assert!(RedrawRequest::At(later) > RedrawRequest::At(now));
assert!(RedrawRequest::NextFrame <= RedrawRequest::NextFrame);
assert!(RedrawRequest::NextFrame <= RedrawRequest::At(now));
assert!(RedrawRequest::At(now) >= RedrawRequest::NextFrame);
assert!(RedrawRequest::At(now) <= RedrawRequest::At(now));
assert!(RedrawRequest::At(now) <= RedrawRequest::At(later));
assert!(RedrawRequest::At(later) >= RedrawRequest::At(now));
}
}

View file

@ -332,6 +332,7 @@ async fn run_instance<A, E, C>(
redraw_pending = matches!( redraw_pending = matches!(
start_cause, start_cause,
event::StartCause::Init event::StartCause::Init
| event::StartCause::Poll
| event::StartCause::ResumeTimeReached { .. } | event::StartCause::ResumeTimeReached { .. }
); );
} }
@ -440,8 +441,15 @@ async fn run_instance<A, E, C>(
let _ = control_sender.start_send(match interface_state { let _ = control_sender.start_send(match interface_state {
user_interface::State::Updated { user_interface::State::Updated {
redraw_requested_at: Some(at), redraw_request: Some(redraw_request),
} => ControlFlow::WaitUntil(at), } => match redraw_request {
crate::window::RedrawRequest::NextFrame => {
ControlFlow::Poll
}
crate::window::RedrawRequest::At(at) => {
ControlFlow::WaitUntil(at)
}
},
_ => ControlFlow::Wait, _ => ControlFlow::Wait,
}); });

View file

@ -2,7 +2,7 @@
use crate::command::{self, Command}; use crate::command::{self, Command};
use iced_native::window; use iced_native::window;
pub use window::{frames, Event, Mode, UserAttention}; pub use window::{frames, Event, Mode, RedrawRequest, UserAttention};
/// Closes the current window and exits the application. /// Closes the current window and exits the application.
pub fn close<Message>() -> Command<Message> { pub fn close<Message>() -> Command<Message> {