mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 14:28:07 +00:00
feat(core): Add preliminary anim frame support
This commit is contained in:
parent
be3e99b96d
commit
117a0bd518
@ -135,35 +135,42 @@ pub enum Event {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
pub struct TimerToken(usize);
|
pub struct TimerToken(u32);
|
||||||
|
|
||||||
impl TimerToken {
|
impl TimerToken {
|
||||||
/// Value of an invalid (or missing) token.
|
/// Value of an invalid (or missing) token.
|
||||||
pub const INVALID: TimerToken = TimerToken(0);
|
pub const INVALID: TimerToken = TimerToken(0);
|
||||||
|
|
||||||
pub fn from_raw(raw: usize) -> Self {
|
pub const fn from_raw(raw: u32) -> Self {
|
||||||
Self(raw)
|
Self(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_raw(self) -> usize {
|
pub const fn into_raw(self) -> u32 {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventCtx {
|
pub struct EventCtx {
|
||||||
timers: Vec<(TimerToken, Duration), { Self::MAX_TIMERS }>,
|
timers: Vec<(TimerToken, Duration), { Self::MAX_TIMERS }>,
|
||||||
next_token: usize,
|
next_token: u32,
|
||||||
paint_requested: bool,
|
paint_requested: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventCtx {
|
impl EventCtx {
|
||||||
|
/// Timer token dedicated for animation frames.
|
||||||
|
pub const ANIM_FRAME_TIMER: TimerToken = TimerToken(1);
|
||||||
|
|
||||||
|
// 0 == `TimerToken::INVALID`,
|
||||||
|
// 1 == `Self::ANIM_FRAME_TIMER`.
|
||||||
|
const STARTING_TIMER_TOKEN: u32 = 2;
|
||||||
|
|
||||||
/// Maximum amount of timers requested in one event tick.
|
/// Maximum amount of timers requested in one event tick.
|
||||||
const MAX_TIMERS: usize = 4;
|
const MAX_TIMERS: usize = 4;
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
timers: Vec::new(),
|
timers: Vec::new(),
|
||||||
next_token: 1,
|
next_token: Self::STARTING_TIMER_TOKEN,
|
||||||
paint_requested: false,
|
paint_requested: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -182,21 +189,37 @@ impl EventCtx {
|
|||||||
/// Request a timer event to be delivered after `deadline` elapses.
|
/// Request a timer event to be delivered after `deadline` elapses.
|
||||||
pub fn request_timer(&mut self, deadline: Duration) -> TimerToken {
|
pub fn request_timer(&mut self, deadline: Duration) -> TimerToken {
|
||||||
let token = self.next_timer_token();
|
let token = self.next_timer_token();
|
||||||
if self.timers.push((token, deadline)).is_err() {
|
self.register_timer(token, deadline);
|
||||||
// The timer queue is full. Let's just ignore this request.
|
|
||||||
#[cfg(feature = "ui_debug")]
|
|
||||||
panic!("timer queue is full");
|
|
||||||
}
|
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Request an animation frame timer to fire as soon as possible.
|
||||||
|
pub fn request_anim_frame(&mut self) {
|
||||||
|
self.register_timer(Self::ANIM_FRAME_TIMER, Duration::ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_timer(&mut self) -> Option<(TimerToken, Duration)> {
|
pub fn pop_timer(&mut self) -> Option<(TimerToken, Duration)> {
|
||||||
self.timers.pop()
|
self.timers.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_timer(&mut self, token: TimerToken, deadline: Duration) {
|
||||||
|
if self.timers.push((token, deadline)).is_err() {
|
||||||
|
// The timer queue is full, this would be a development error in the layout
|
||||||
|
// layer. Let's panic in the debug env.
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
panic!("timer queue is full");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn next_timer_token(&mut self) -> TimerToken {
|
fn next_timer_token(&mut self) -> TimerToken {
|
||||||
let token = TimerToken(self.next_token);
|
let token = TimerToken(self.next_token);
|
||||||
self.next_token += 1;
|
// We start again from the beginning if the token counter overflows. This would
|
||||||
|
// probably happen in case of a bug and a long-running session. Let's risk the
|
||||||
|
// collisions in such case.
|
||||||
|
self.next_token = self
|
||||||
|
.next_token
|
||||||
|
.checked_add(1)
|
||||||
|
.unwrap_or(Self::STARTING_TIMER_TOKEN);
|
||||||
token
|
token
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ impl TryFrom<Obj> for TimerToken {
|
|||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(value: Obj) -> Result<Self, Self::Error> {
|
fn try_from(value: Obj) -> Result<Self, Self::Error> {
|
||||||
let raw: usize = value.try_into()?;
|
let raw: u32 = value.try_into()?;
|
||||||
let this = Self::from_raw(raw);
|
let this = Self::from_raw(raw);
|
||||||
Ok(this)
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
@ -67,10 +67,14 @@ impl Loader {
|
|||||||
pub fn progress(&self, now: Instant) -> Option<u16> {
|
pub fn progress(&self, now: Instant) -> Option<u16> {
|
||||||
match &self.state {
|
match &self.state {
|
||||||
State::Initial => None,
|
State::Initial => None,
|
||||||
State::Growing(animation) | State::Shrinking(animation) => Some(animation.value(now)),
|
State::Growing(anim) | State::Shrinking(anim) => Some(anim.value(now)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_started(&self) -> bool {
|
||||||
|
matches!(self.state, State::Growing(_) | State::Shrinking(_))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_finished(&self, now: Instant) -> bool {
|
pub fn is_finished(&self, now: Instant) -> bool {
|
||||||
self.progress(now) == Some(display::LOADER_MAX)
|
self.progress(now) == Some(display::LOADER_MAX)
|
||||||
}
|
}
|
||||||
@ -79,7 +83,13 @@ impl Loader {
|
|||||||
impl Component for Loader {
|
impl Component for Loader {
|
||||||
type Msg = Never;
|
type Msg = Never;
|
||||||
|
|
||||||
fn event(&mut self, _ctx: &mut EventCtx, _event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
if let Event::Timer(EventCtx::ANIM_FRAME_TIMER) = event {
|
||||||
|
if self.is_started() {
|
||||||
|
ctx.request_paint();
|
||||||
|
ctx.request_anim_frame();
|
||||||
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user