1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-08-05 13:26:57 +00:00

perf(core): use 16-bit duration for Button long-press duration

Also, use zero duration to disable long-press mechanism.

[no changelog]
This commit is contained in:
Roman Zeyde 2025-06-08 11:56:39 +03:00
parent 0b4c44e32f
commit a7849ab838
10 changed files with 58 additions and 32 deletions

View File

@ -10,6 +10,19 @@ const MILLIS_PER_MINUTE: u32 = MILLIS_PER_SEC * 60;
const MILLIS_PER_HOUR: u32 = MILLIS_PER_MINUTE * 60; const MILLIS_PER_HOUR: u32 = MILLIS_PER_MINUTE * 60;
const MILLIS_PER_DAY: u32 = MILLIS_PER_HOUR * 24; const MILLIS_PER_DAY: u32 = MILLIS_PER_HOUR * 24;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ShortDuration {
millis: u16,
}
impl ShortDuration {
pub const ZERO: Self = Self::from_millis(0);
pub const fn from_millis(millis: u16) -> Self {
Self { millis }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)] #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct Duration { pub struct Duration {
millis: u32, millis: u32,
@ -168,6 +181,12 @@ impl Div<Duration> for Duration {
} }
} }
impl From<ShortDuration> for Duration {
fn from(value: ShortDuration) -> Self {
Self::from_millis(value.millis.into())
}
}
/* Instants can wrap around and we want them to be comparable even after /* Instants can wrap around and we want them to be comparable even after
* wrapping around. This works by setting a maximum allowable difference * wrapping around. This works by setting a maximum allowable difference
* between two Instants to half the range. In checked_add and checked_sub, we * between two Instants to half the range. In checked_add and checked_sub, we

View File

@ -2,7 +2,7 @@
use crate::trezorhal::haptic::{self, HapticEffect}; use crate::trezorhal::haptic::{self, HapticEffect};
use crate::{ use crate::{
strutil::TString, strutil::TString,
time::Duration, time::ShortDuration,
ui::{ ui::{
component::{ component::{
Component, ComponentExt, Event, EventCtx, FixedHeightBar, MsgMap, Split, Timer, Component, ComponentExt, Event, EventCtx, FixedHeightBar, MsgMap, Split, Timer,
@ -41,7 +41,7 @@ pub struct Button {
content: ButtonContent, content: ButtonContent,
styles: ButtonStyleSheet, styles: ButtonStyleSheet,
state: State, state: State,
long_press: Duration, long_press: ShortDuration, // long press requires non-zero duration
long_timer: Timer, long_timer: Timer,
haptics: bool, haptics: bool,
} }
@ -58,7 +58,7 @@ impl Button {
touch_expand: Insets::zero(), touch_expand: Insets::zero(),
styles: theme::button_default(), styles: theme::button_default(),
state: State::Initial, state: State::Initial,
long_press: Duration::ZERO, long_press: ShortDuration::ZERO,
long_timer: Timer::new(), long_timer: Timer::new(),
haptics: true, haptics: true,
} }
@ -94,7 +94,8 @@ impl Button {
self self
} }
pub fn with_long_press(mut self, duration: Duration) -> Self { pub fn with_long_press(mut self, duration: ShortDuration) -> Self {
debug_assert_ne!(duration, ShortDuration::ZERO);
self.long_press = duration; self.long_press = duration;
self self
} }
@ -251,8 +252,8 @@ impl Component for Button {
haptic::play(HapticEffect::ButtonPress); haptic::play(HapticEffect::ButtonPress);
} }
self.set(ctx, State::Pressed); self.set(ctx, State::Pressed);
if self.long_press != Duration::ZERO { if self.long_press != ShortDuration::ZERO {
self.long_timer.start(ctx, self.long_press) self.long_timer.start(ctx, self.long_press.into())
} }
return Some(ButtonMsg::Pressed); return Some(ButtonMsg::Pressed);
} }

View File

@ -2,7 +2,7 @@ pub mod backlight;
pub mod bootloader; pub mod bootloader;
use crate::{ use crate::{
time::Duration, time::ShortDuration,
ui::{ ui::{
component::{ component::{
text::{layout::Chunks, LineBreaking, PageBreaking, TextStyle}, text::{layout::Chunks, LineBreaking, PageBreaking, TextStyle},
@ -19,7 +19,7 @@ use super::{
fonts, fonts,
}; };
pub const ERASE_HOLD_DURATION: Duration = Duration::from_millis(1500); pub const ERASE_HOLD_DURATION: ShortDuration = ShortDuration::from_millis(1500);
// Color palette. // Color palette.
pub const WHITE: Color = Color::rgb(0xFF, 0xFF, 0xFF); pub const WHITE: Color = Color::rgb(0xFF, 0xFF, 0xFF);

View File

@ -2,7 +2,7 @@
use crate::trezorhal::haptic::{play, HapticEffect}; use crate::trezorhal::haptic::{play, HapticEffect};
use crate::{ use crate::{
strutil::TString, strutil::TString,
time::Duration, time::ShortDuration,
ui::{ ui::{
component::{Component, Event, EventCtx, Timer}, component::{Component, Event, EventCtx, Timer},
display::{toif::Icon, Color, Font}, display::{toif::Icon, Color, Font},
@ -30,7 +30,7 @@ pub struct Button {
text_align: Alignment, text_align: Alignment,
radius: Option<u8>, radius: Option<u8>,
state: State, state: State,
long_press: Option<Duration>, long_press: ShortDuration, // long press requires non-zero duration
long_timer: Timer, long_timer: Timer,
haptic: bool, haptic: bool,
} }
@ -50,7 +50,7 @@ impl Button {
text_align: Alignment::Start, text_align: Alignment::Start,
radius: None, radius: None,
state: State::Initial, state: State::Initial,
long_press: None, long_press: ShortDuration::ZERO,
long_timer: Timer::new(), long_timer: Timer::new(),
haptic: true, haptic: true,
} }
@ -87,8 +87,9 @@ impl Button {
self self
} }
pub fn with_long_press(mut self, duration: Duration) -> Self { pub fn with_long_press(mut self, duration: ShortDuration) -> Self {
self.long_press = Some(duration); debug_assert_ne!(duration, ShortDuration::ZERO);
self.long_press = duration;
self self
} }
@ -271,8 +272,8 @@ impl Component for Button {
play(HapticEffect::ButtonPress); play(HapticEffect::ButtonPress);
} }
self.set(ctx, State::Pressed); self.set(ctx, State::Pressed);
if let Some(duration) = self.long_press { if self.long_press != ShortDuration::ZERO {
self.long_timer.start(ctx, duration); self.long_timer.start(ctx, self.long_press.into());
} }
return Some(ButtonMsg::Pressed); return Some(ButtonMsg::Pressed);
} }

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
time::Duration, time::{Duration, ShortDuration},
translations::TR, translations::TR,
ui::{ ui::{
component::{Component, Event, EventCtx}, component::{Component, Event, EventCtx},
@ -180,7 +180,7 @@ impl HoldToConfirm {
pub fn new(circle_color: Color, circle_inner_color: Color) -> Self { pub fn new(circle_color: Color, circle_inner_color: Color) -> Self {
let button = Button::new(ButtonContent::Empty) let button = Button::new(ButtonContent::Empty)
.styled(theme::button_default()) .styled(theme::button_default())
.with_long_press(Duration::from_millis(2200)) .with_long_press(ShortDuration::from_millis(2200))
.without_haptics(); .without_haptics();
Self { Self {
title: Label::new( title: Label::new(

View File

@ -3,7 +3,7 @@ pub mod bootloader;
pub mod backlight; pub mod backlight;
use crate::{ use crate::{
time::Duration, time::ShortDuration,
ui::{ ui::{
component::{ component::{
text::{layout::Chunks, LineBreaking, PageBreaking, TextStyle}, text::{layout::Chunks, LineBreaking, PageBreaking, TextStyle},
@ -20,7 +20,7 @@ use super::{
fonts, fonts,
}; };
pub const ERASE_HOLD_DURATION: Duration = Duration::from_millis(1500); pub const ERASE_HOLD_DURATION: ShortDuration = ShortDuration::from_millis(1500);
// Color palette. // Color palette.
pub const WHITE: Color = Color::rgb(0xFF, 0xFF, 0xFF); pub const WHITE: Color = Color::rgb(0xFF, 0xFF, 0xFF);

View File

@ -2,7 +2,7 @@
use crate::trezorhal::haptic::{play, HapticEffect}; use crate::trezorhal::haptic::{play, HapticEffect};
use crate::{ use crate::{
strutil::TString, strutil::TString,
time::Duration, time::{Duration, ShortDuration},
ui::{ ui::{
component::{text::TextStyle, Component, Event, EventCtx, Timer}, component::{text::TextStyle, Component, Event, EventCtx, Timer},
constant, constant,
@ -42,7 +42,7 @@ pub struct Button {
text_align: Alignment, text_align: Alignment,
radius_or_gradient: RadiusOrGradient, radius_or_gradient: RadiusOrGradient,
state: State, state: State,
long_press: Option<Duration>, long_press: ShortDuration, // long press requires non-zero duration
long_timer: Timer, long_timer: Timer,
haptic: bool, haptic: bool,
} }
@ -76,7 +76,7 @@ impl Button {
text_align: Alignment::Center, text_align: Alignment::Center,
radius_or_gradient: RadiusOrGradient::None, radius_or_gradient: RadiusOrGradient::None,
state: State::Initial, state: State::Initial,
long_press: None, long_press: ShortDuration::ZERO,
long_timer: Timer::new(), long_timer: Timer::new(),
haptic: true, haptic: true,
} }
@ -168,8 +168,9 @@ impl Button {
self self
} }
pub fn with_long_press(mut self, duration: Duration) -> Self { pub fn with_long_press(mut self, duration: ShortDuration) -> Self {
self.long_press = Some(duration); debug_assert_ne!(duration, ShortDuration::ZERO);
self.long_press = duration;
self self
} }
@ -223,7 +224,11 @@ impl Button {
} }
pub fn long_press(&self) -> Option<Duration> { pub fn long_press(&self) -> Option<Duration> {
self.long_press if self.long_press != ShortDuration::ZERO {
Some(self.long_press.into())
} else {
None
}
} }
pub fn is_disabled(&self) -> bool { pub fn is_disabled(&self) -> bool {
@ -584,7 +589,7 @@ impl Component for Button {
play(HapticEffect::ButtonPress); play(HapticEffect::ButtonPress);
} }
self.set(ctx, State::Pressed); self.set(ctx, State::Pressed);
if let Some(duration) = self.long_press { if let Some(duration) = self.long_press() {
self.long_timer.start(ctx, duration); self.long_timer.start(ctx, duration);
} }
return Some(ButtonMsg::Pressed); return Some(ButtonMsg::Pressed);

View File

@ -57,7 +57,7 @@ impl HoldToConfirmAnim {
pub fn new() -> Self { pub fn new() -> Self {
let default_color = theme::GREEN_LIME; let default_color = theme::GREEN_LIME;
Self { Self {
total_duration: theme::CONFIRM_HOLD_DURATION, total_duration: theme::CONFIRM_HOLD_DURATION.into(),
color: default_color, color: default_color,
border: ScreenBorder::new(default_color), border: ScreenBorder::new(default_color),
timer: Stopwatch::default(), timer: Stopwatch::default(),

View File

@ -2,7 +2,7 @@ use crate::{
error::Error, error::Error,
io::BinaryData, io::BinaryData,
strutil::TString, strutil::TString,
time::Duration, time::ShortDuration,
translations::TR, translations::TR,
ui::{ ui::{
component::{text::TextStyle, Component, Event, EventCtx, Label, Never}, component::{text::TextStyle, Component, Event, EventCtx, Label, Never},
@ -24,7 +24,7 @@ use super::{
ActionBar, ActionBarMsg, Hint, ActionBar, ActionBarMsg, Hint,
}; };
const LOCK_HOLD_DURATION: Duration = Duration::from_millis(3000); const LOCK_HOLD_DURATION: ShortDuration = ShortDuration::from_millis(3000);
/// Full-screen component for the homescreen and lockscreen. /// Full-screen component for the homescreen and lockscreen.
pub struct Homescreen { pub struct Homescreen {

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
time::Duration, time::ShortDuration,
ui::component::text::{ ui::component::text::{
layout::{Chunks, LineBreaking, PageBreaking}, layout::{Chunks, LineBreaking, PageBreaking},
TextStyle, TextStyle,
@ -14,8 +14,8 @@ use super::{
*, *,
}; };
pub const CONFIRM_HOLD_DURATION: Duration = Duration::from_millis(1500); pub const CONFIRM_HOLD_DURATION: ShortDuration = ShortDuration::from_millis(1500);
pub const ERASE_HOLD_DURATION: Duration = Duration::from_millis(1500); pub const ERASE_HOLD_DURATION: ShortDuration = ShortDuration::from_millis(1500);
// Text styles // Text styles
/// Alias for use with copied code, might be deleted later /// Alias for use with copied code, might be deleted later