From 6602bd9b867cc8a7c23bb866de3d172d24454f84 Mon Sep 17 00:00:00 2001 From: cepetr Date: Mon, 11 Mar 2024 11:20:53 +0100 Subject: [PATCH] fixup! refactor(core): integrate new drawing library --- core/embed/rust/src/ui/component/base.rs | 14 ++-- core/embed/rust/src/ui/component/border.rs | 2 +- core/embed/rust/src/ui/component/connect.rs | 2 +- core/embed/rust/src/ui/component/empty.rs | 2 +- core/embed/rust/src/ui/component/image.rs | 4 +- core/embed/rust/src/ui/component/label.rs | 2 +- core/embed/rust/src/ui/component/map.rs | 2 +- core/embed/rust/src/ui/component/marquee.rs | 4 +- core/embed/rust/src/ui/component/maybe.rs | 2 +- core/embed/rust/src/ui/component/pad.rs | 2 +- core/embed/rust/src/ui/component/painter.rs | 2 +- core/embed/rust/src/ui/component/placed.rs | 8 +- core/embed/rust/src/ui/component/qr_code.rs | 2 +- .../rust/src/ui/component/text/formatted.rs | 4 +- .../rust/src/ui/component/text/layout.rs | 25 ++++-- .../rust/src/ui/component/text/paragraphs.rs | 8 +- core/embed/rust/src/ui/component/text/util.rs | 8 +- core/embed/rust/src/ui/component/timeout.rs | 2 +- core/embed/rust/src/ui/display/tjpgd.rs | 1 - .../rust/src/ui/model_tr/bootloader/intro.rs | 2 +- .../rust/src/ui/model_tr/bootloader/menu.rs | 4 +- .../src/ui/model_tr/bootloader/welcome.rs | 2 +- .../ui/model_tr/component/address_details.rs | 2 +- .../src/ui/model_tr/component/bl_confirm.rs | 4 +- .../rust/src/ui/model_tr/component/button.rs | 2 +- .../model_tr/component/button_controller.rs | 8 +- .../ui/model_tr/component/changing_text.rs | 8 +- .../model_tr/component/coinjoin_progress.rs | 2 +- .../rust/src/ui/model_tr/component/error.rs | 2 +- .../rust/src/ui/model_tr/component/flow.rs | 2 +- .../src/ui/model_tr/component/flow_pages.rs | 3 +- .../rust/src/ui/model_tr/component/frame.rs | 4 +- .../ui/model_tr/component/hold_to_confirm.rs | 2 +- .../src/ui/model_tr/component/homescreen.rs | 81 ++++++++++--------- .../component/input_methods/choice.rs | 22 ++--- .../component/input_methods/choice_item.rs | 19 +++-- .../component/input_methods/number_input.rs | 2 +- .../component/input_methods/passphrase.rs | 2 +- .../model_tr/component/input_methods/pin.rs | 2 +- .../component/input_methods/simple_choice.rs | 2 +- .../component/input_methods/wordlist.rs | 2 +- .../rust/src/ui/model_tr/component/loader.rs | 11 ++- .../rust/src/ui/model_tr/component/page.rs | 2 +- .../src/ui/model_tr/component/progress.rs | 2 +- .../rust/src/ui/model_tr/component/result.rs | 2 +- .../src/ui/model_tr/component/scrollbar.rs | 6 +- .../src/ui/model_tr/component/share_words.rs | 6 +- .../src/ui/model_tr/component/show_more.rs | 2 +- .../rust/src/ui/model_tr/component/title.rs | 6 +- .../ui/model_tr/component/welcome_screen.rs | 2 +- .../src/ui/model_tr/cshape/dotted_line.rs | 10 +-- .../src/ui/model_tr/cshape/loader_circular.rs | 8 +- .../src/ui/model_tr/cshape/loader_small.rs | 6 +- .../src/ui/model_tr/cshape/loader_starry.rs | 6 +- core/embed/rust/src/ui/model_tr/layout.rs | 14 +--- .../rust/src/ui/model_tt/bootloader/intro.rs | 2 +- .../rust/src/ui/model_tt/bootloader/menu.rs | 2 +- .../src/ui/model_tt/bootloader/welcome.rs | 3 +- .../ui/model_tt/component/address_details.rs | 2 +- .../src/ui/model_tt/component/bl_confirm.rs | 6 +- .../rust/src/ui/model_tt/component/button.rs | 6 +- .../model_tt/component/coinjoin_progress.rs | 2 +- .../rust/src/ui/model_tt/component/dialog.rs | 4 +- .../rust/src/ui/model_tt/component/error.rs | 2 +- .../rust/src/ui/model_tt/component/fido.rs | 14 ++-- .../rust/src/ui/model_tt/component/frame.rs | 2 +- .../ui/model_tt/component/homescreen/mod.rs | 10 +-- .../ui/model_tt/component/keyboard/bip39.rs | 2 +- .../ui/model_tt/component/keyboard/common.rs | 4 +- .../model_tt/component/keyboard/mnemonic.rs | 4 +- .../model_tt/component/keyboard/passphrase.rs | 9 +-- .../src/ui/model_tt/component/keyboard/pin.rs | 12 +-- .../ui/model_tt/component/keyboard/slip39.rs | 2 +- .../model_tt/component/keyboard/word_count.rs | 4 +- .../rust/src/ui/model_tt/component/loader.rs | 4 +- .../src/ui/model_tt/component/number_input.rs | 4 +- .../rust/src/ui/model_tt/component/page.rs | 10 ++- .../src/ui/model_tt/component/progress.rs | 2 +- .../rust/src/ui/model_tt/component/result.rs | 4 +- .../rust/src/ui/model_tt/component/scroll.rs | 2 +- .../src/ui/model_tt/component/simple_page.rs | 2 +- .../rust/src/ui/model_tt/component/swipe.rs | 2 +- .../ui/model_tt/component/welcome_screen.rs | 2 +- 83 files changed, 244 insertions(+), 238 deletions(-) diff --git a/core/embed/rust/src/ui/component/base.rs b/core/embed/rust/src/ui/component/base.rs index d8b44dea64..b82f120762 100644 --- a/core/embed/rust/src/ui/component/base.rs +++ b/core/embed/rust/src/ui/component/base.rs @@ -61,7 +61,7 @@ pub trait Component { /// the `Child` wrapper. fn paint(&mut self); - fn render(&mut self, _target: &mut impl Renderer); + fn render<'s>(&'s self, _target: &mut impl Renderer<'s>); #[cfg(feature = "ui_bounds")] /// Report current paint bounds of this component. Used for debugging. @@ -156,7 +156,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.component.render(target); } @@ -260,7 +260,7 @@ where self.inner.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } @@ -302,7 +302,7 @@ where self.1.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.0.render(target); self.1.render(target); } @@ -356,7 +356,7 @@ where self.2.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.0.render(target); self.1.render(target); self.2.render(target); @@ -389,8 +389,8 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { - if let Some(ref mut c) = self { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { + if let Some(ref c) = self { c.render(target) } } diff --git a/core/embed/rust/src/ui/component/border.rs b/core/embed/rust/src/ui/component/border.rs index 57d9100549..47941ae629 100644 --- a/core/embed/rust/src/ui/component/border.rs +++ b/core/embed/rust/src/ui/component/border.rs @@ -42,7 +42,7 @@ where self.inner.paint() } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } diff --git a/core/embed/rust/src/ui/component/connect.rs b/core/embed/rust/src/ui/component/connect.rs index 7c5a14de6e..3d7897bdf0 100644 --- a/core/embed/rust/src/ui/component/connect.rs +++ b/core/embed/rust/src/ui/component/connect.rs @@ -57,7 +57,7 @@ impl Component for Connect { }); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let font = Font::NORMAL; self.bg.render(target); diff --git a/core/embed/rust/src/ui/component/empty.rs b/core/embed/rust/src/ui/component/empty.rs index 0f982ee414..15fb017dc0 100644 --- a/core/embed/rust/src/ui/component/empty.rs +++ b/core/embed/rust/src/ui/component/empty.rs @@ -16,7 +16,7 @@ impl Component for Empty { fn paint(&mut self) {} - fn render(&mut self, _target: &mut impl Renderer) {} + fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {} } #[cfg(feature = "ui_debug")] diff --git a/core/embed/rust/src/ui/component/image.rs b/core/embed/rust/src/ui/component/image.rs index d4971cb265..959ccf2c49 100644 --- a/core/embed/rust/src/ui/component/image.rs +++ b/core/embed/rust/src/ui/component/image.rs @@ -50,7 +50,7 @@ impl Component for Image { self.draw(self.area.center(), Alignment2D::CENTER); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { shape::ToifImage::new(self.area.center(), self.toif) .with_align(Alignment2D::CENTER) .render(target); @@ -138,7 +138,7 @@ impl Component for BlendedImage { self.paint_image(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { shape::ToifImage::new(self.bg_top_left, self.bg.toif) .with_fg(self.bg_color) .render(target); diff --git a/core/embed/rust/src/ui/component/label.rs b/core/embed/rust/src/ui/component/label.rs index ed182f5757..ae05b3eafe 100644 --- a/core/embed/rust/src/ui/component/label.rs +++ b/core/embed/rust/src/ui/component/label.rs @@ -120,7 +120,7 @@ where self.layout.render_text(self.text.as_ref()); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.layout.render_text2(self.text.as_ref(), target); } diff --git a/core/embed/rust/src/ui/component/map.rs b/core/embed/rust/src/ui/component/map.rs index 8efc21ec1b..76100cbf5a 100644 --- a/core/embed/rust/src/ui/component/map.rs +++ b/core/embed/rust/src/ui/component/map.rs @@ -31,7 +31,7 @@ where self.inner.paint() } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } diff --git a/core/embed/rust/src/ui/component/marquee.rs b/core/embed/rust/src/ui/component/marquee.rs index 6ab55e0060..1a1f533d8f 100644 --- a/core/embed/rust/src/ui/component/marquee.rs +++ b/core/embed/rust/src/ui/component/marquee.rs @@ -132,7 +132,7 @@ where ); } - pub fn render_anim(&mut self, target: &mut impl Renderer, offset: i16) { + pub fn render_anim<'s>(&'s self, target: &mut impl Renderer<'s>, offset: i16) { target.in_window(self.area, &mut |target| { let text_height = self.font.text_height(); let pos = self.area.top_left() + Offset::new(offset, text_height - 1); @@ -237,7 +237,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let now = Instant::now(); match self.state { diff --git a/core/embed/rust/src/ui/component/maybe.rs b/core/embed/rust/src/ui/component/maybe.rs index 5e83c22cb9..bbc843bca1 100644 --- a/core/embed/rust/src/ui/component/maybe.rs +++ b/core/embed/rust/src/ui/component/maybe.rs @@ -95,7 +95,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); if self.visible { self.inner.render(target); diff --git a/core/embed/rust/src/ui/component/pad.rs b/core/embed/rust/src/ui/component/pad.rs index 206d83a3c3..fa6b5b065b 100644 --- a/core/embed/rust/src/ui/component/pad.rs +++ b/core/embed/rust/src/ui/component/pad.rs @@ -55,7 +55,7 @@ impl Pad { } } - pub fn render(&mut self, target: &mut impl Renderer) { + pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { shape::Bar::new(self.area) .with_bg(self.color) .render(target); diff --git a/core/embed/rust/src/ui/component/painter.rs b/core/embed/rust/src/ui/component/painter.rs index 619f0cd2d5..d361ef177d 100644 --- a/core/embed/rust/src/ui/component/painter.rs +++ b/core/embed/rust/src/ui/component/painter.rs @@ -41,7 +41,7 @@ where (self.func)(self.area); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let area = self.area; shape::Bar::new(area) .with_thickness(1) diff --git a/core/embed/rust/src/ui/component/placed.rs b/core/embed/rust/src/ui/component/placed.rs index 3174daa749..18fcc1e186 100644 --- a/core/embed/rust/src/ui/component/placed.rs +++ b/core/embed/rust/src/ui/component/placed.rs @@ -65,7 +65,7 @@ where self.inner.paint() } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } } @@ -112,7 +112,7 @@ where self.inner.paint() } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } } @@ -188,7 +188,7 @@ where self.inner.paint() } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.inner.render(target); } } @@ -283,7 +283,7 @@ where self.second.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.first.render(target); self.second.render(target); } diff --git a/core/embed/rust/src/ui/component/qr_code.rs b/core/embed/rust/src/ui/component/qr_code.rs index 55b93f6fd7..6b13e116d8 100644 --- a/core/embed/rust/src/ui/component/qr_code.rs +++ b/core/embed/rust/src/ui/component/qr_code.rs @@ -143,7 +143,7 @@ impl Component for Qr { Self::draw(&qr, area, self.border, scale); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let mut outbuffer = [0u8; QR_MAX_VERSION.buffer_len()]; let mut tempbuffer = [0u8; QR_MAX_VERSION.buffer_len()]; diff --git a/core/embed/rust/src/ui/component/text/formatted.rs b/core/embed/rust/src/ui/component/text/formatted.rs index 057bad1598..70c903dede 100644 --- a/core/embed/rust/src/ui/component/text/formatted.rs +++ b/core/embed/rust/src/ui/component/text/formatted.rs @@ -140,8 +140,8 @@ impl Component for FormattedText { self.layout_content(&mut TextRenderer); } - fn render(&mut self, target: &mut impl Renderer) { - self.layout_content(&mut TextRenderer2(target)); + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { + self.layout_content(&mut TextRenderer2::new(target)); } #[cfg(feature = "ui_bounds")] diff --git a/core/embed/rust/src/ui/component/text/layout.rs b/core/embed/rust/src/ui/component/text/layout.rs index a89acf7343..682d414251 100644 --- a/core/embed/rust/src/ui/component/text/layout.rs +++ b/core/embed/rust/src/ui/component/text/layout.rs @@ -238,8 +238,12 @@ impl TextLayout { } /// Draw as much text as possible on the current screen. - pub fn render_text2(&self, text: &str, target: &mut impl Renderer) -> LayoutFit { - self.layout_text(text, &mut self.initial_cursor(), &mut TextRenderer2(target)) + pub fn render_text2<'s>(&self, text: &str, target: &mut impl Renderer<'s>) -> LayoutFit { + self.layout_text( + text, + &mut self.initial_cursor(), + &mut TextRenderer2::new(target), + ) } /// Loop through the `text` and try to fit it on the current screen, @@ -537,13 +541,22 @@ impl LayoutSink for TextRenderer { } } -pub struct TextRenderer2<'a, R>(pub &'a mut R) +pub struct TextRenderer2<'a, 's, R>(pub &'a mut R, core::marker::PhantomData<&'s ()>) where - R: Renderer; + R: Renderer<'s>; -impl<'a, R> LayoutSink for TextRenderer2<'a, R> +impl<'a, 's, R> TextRenderer2<'a, 's, R> where - R: Renderer, + R: Renderer<'s>, +{ + pub fn new(target: &'a mut R) -> Self { + Self(target, core::marker::PhantomData) + } +} + +impl<'a, 's, R> LayoutSink for TextRenderer2<'a, 's, R> +where + R: Renderer<'s>, { fn text(&mut self, cursor: Point, layout: &TextLayout, text: &str) { shape::Text::new(cursor, text) diff --git a/core/embed/rust/src/ui/component/text/paragraphs.rs b/core/embed/rust/src/ui/component/text/paragraphs.rs index 2f59109375..3a1fc08847 100644 --- a/core/embed/rust/src/ui/component/text/paragraphs.rs +++ b/core/embed/rust/src/ui/component/text/paragraphs.rs @@ -190,7 +190,7 @@ where ) } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { Self::foreach_visible( &self.source, &self.visible, @@ -620,12 +620,12 @@ impl Checklist { ); } - fn render_icon( + fn render_icon<'s>( &self, layout: &TextLayout, icon: Icon, offset: Offset, - target: &mut impl Renderer, + target: &mut impl Renderer<'s>, ) { let top_left = Point::new(self.area.x0, layout.bounds.y0); shape::ToifImage::new(top_left + offset, icon.toif) @@ -671,7 +671,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.paragraphs.render(target); let current_visible = self.current.saturating_sub(self.paragraphs.offset.par); diff --git a/core/embed/rust/src/ui/component/text/util.rs b/core/embed/rust/src/ui/component/text/util.rs index 5b39f208eb..69ddd4de42 100644 --- a/core/embed/rust/src/ui/component/text/util.rs +++ b/core/embed/rust/src/ui/component/text/util.rs @@ -45,8 +45,8 @@ pub fn text_multiline( /// /// If it fits, returns the rest of the area. /// If it does not fit, returns `None`. -pub fn text_multiline2( - target: &mut impl Renderer, +pub fn text_multiline2<'s>( + target: &mut impl Renderer<'s>, area: Rect, text: TString<'_>, font: Font, @@ -97,8 +97,8 @@ pub fn text_multiline_bottom( /// Same as `text_multiline` above, but aligns the text to the bottom of the /// area. -pub fn text_multiline_bottom2( - target: &mut impl Renderer, +pub fn text_multiline_bottom2<'s>( + target: &mut impl Renderer<'s>, area: Rect, text: TString<'_>, font: Font, diff --git a/core/embed/rust/src/ui/component/timeout.rs b/core/embed/rust/src/ui/component/timeout.rs index c07f78b646..6da62e7255 100644 --- a/core/embed/rust/src/ui/component/timeout.rs +++ b/core/embed/rust/src/ui/component/timeout.rs @@ -46,7 +46,7 @@ impl Component for Timeout { fn paint(&mut self) {} - fn render(&mut self, _target: &mut impl Renderer) {} + fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {} } #[cfg(feature = "ui_debug")] diff --git a/core/embed/rust/src/ui/display/tjpgd.rs b/core/embed/rust/src/ui/display/tjpgd.rs index c65c7f2c04..81e2f3e85a 100644 --- a/core/embed/rust/src/ui/display/tjpgd.rs +++ b/core/embed/rust/src/ui/display/tjpgd.rs @@ -14,7 +14,6 @@ use crate::{ }, }; -#[cfg(not(feature = "new_rendering"))] pub fn jpeg(data: &[u8], pos: Point, scale: u8) { let mut buffer = BufferJpegWork::get_cleared(); let pool = buffer.buffer.as_mut_slice(); diff --git a/core/embed/rust/src/ui/model_tr/bootloader/intro.rs b/core/embed/rust/src/ui/model_tr/bootloader/intro.rs index 8743475245..8d00a854a6 100644 --- a/core/embed/rust/src/ui/model_tr/bootloader/intro.rs +++ b/core/embed/rust/src/ui/model_tr/bootloader/intro.rs @@ -105,7 +105,7 @@ impl<'a> Component for Intro<'a> { self.buttons.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.title.render(target); diff --git a/core/embed/rust/src/ui/model_tr/bootloader/menu.rs b/core/embed/rust/src/ui/model_tr/bootloader/menu.rs index 7919d9eb3d..12fbbaf0a1 100644 --- a/core/embed/rust/src/ui/model_tr/bootloader/menu.rs +++ b/core/embed/rust/src/ui/model_tr/bootloader/menu.rs @@ -73,7 +73,7 @@ impl Choice for MenuChoice { ); } - fn render_center(&self, target: &mut impl Renderer, _area: Rect, _inverse: bool) { + fn render_center<'s>(&self, target: &mut impl Renderer<'s>, _area: Rect, _inverse: bool) { // Icon on top and two lines of text below shape::ToifImage::new(SCREEN_CENTER + Offset::y(-20), self.icon.toif) .with_align(Alignment2D::CENTER) @@ -186,7 +186,7 @@ impl Component for Menu { self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.choice_page.render(target); } diff --git a/core/embed/rust/src/ui/model_tr/bootloader/welcome.rs b/core/embed/rust/src/ui/model_tr/bootloader/welcome.rs index 3b3503d141..ad261e3b17 100644 --- a/core/embed/rust/src/ui/model_tr/bootloader/welcome.rs +++ b/core/embed/rust/src/ui/model_tr/bootloader/welcome.rs @@ -60,7 +60,7 @@ impl Component for Welcome { ); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); let top_center = self.bg.area.top_center(); diff --git a/core/embed/rust/src/ui/model_tr/component/address_details.rs b/core/embed/rust/src/ui/model_tr/component/address_details.rs index 9ed6be20c2..44b407c4ad 100644 --- a/core/embed/rust/src/ui/model_tr/component/address_details.rs +++ b/core/embed/rust/src/ui/model_tr/component/address_details.rs @@ -257,7 +257,7 @@ impl Component for AddressDetails { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.buttons.render(target); match self.current_page { diff --git a/core/embed/rust/src/ui/model_tr/component/bl_confirm.rs b/core/embed/rust/src/ui/model_tr/component/bl_confirm.rs index f47bba9968..6eb18ba851 100644 --- a/core/embed/rust/src/ui/model_tr/component/bl_confirm.rs +++ b/core/embed/rust/src/ui/model_tr/component/bl_confirm.rs @@ -229,8 +229,8 @@ where self.buttons.paint(); } - fn render(&mut self, target: &mut impl Renderer) { - self.bg.paint(); + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { + self.bg.render(target); let mut display_top_left = |text: TString<'static>| { text.map(|t| { diff --git a/core/embed/rust/src/ui/model_tr/component/button.rs b/core/embed/rust/src/ui/model_tr/component/button.rs index 48323331e8..329d202e84 100644 --- a/core/embed/rust/src/ui/model_tr/component/button.rs +++ b/core/embed/rust/src/ui/model_tr/component/button.rs @@ -268,7 +268,7 @@ impl Component for Button { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let style = self.style(); let fg_color = style.text_color; let bg_color = fg_color.negate(); diff --git a/core/embed/rust/src/ui/model_tr/component/button_controller.rs b/core/embed/rust/src/ui/model_tr/component/button_controller.rs index b68459e621..2809388790 100644 --- a/core/embed/rust/src/ui/model_tr/component/button_controller.rs +++ b/core/embed/rust/src/ui/model_tr/component/button_controller.rs @@ -95,7 +95,7 @@ impl ButtonType { } } - pub fn render(&mut self, target: &mut impl Renderer) { + pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { match self { Self::Button(button) => { button.render(target); @@ -167,7 +167,7 @@ impl ButtonContainer { self.button_type.paint(); } - pub fn render(&mut self, target: &mut impl Renderer) { + pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.button_type.render(target); } @@ -592,7 +592,7 @@ impl Component for ButtonController { self.right_btn.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.left_btn.render(target); self.middle_btn.render(target); @@ -778,7 +778,7 @@ impl Component for AutomaticMover { fn paint(&mut self) {} - fn render(&mut self, _target: &mut impl Renderer) {} + fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {} fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option { // Moving automatically only when we receive a TimerToken that we have diff --git a/core/embed/rust/src/ui/model_tr/component/changing_text.rs b/core/embed/rust/src/ui/model_tr/component/changing_text.rs index 233e836210..de5cbe6d7c 100644 --- a/core/embed/rust/src/ui/model_tr/component/changing_text.rs +++ b/core/embed/rust/src/ui/model_tr/component/changing_text.rs @@ -111,7 +111,7 @@ where common::display_left(baseline, &self.text, self.font); } - fn render_left(&self, target: &mut impl Renderer) { + fn render_left<'s>(&'s self, target: &mut impl Renderer<'s>) { let baseline = Point::new(self.pad.area.x0, self.y_baseline()); shape::Text::new(baseline, &self.text.as_ref()) .with_font(self.font) @@ -123,7 +123,7 @@ where common::display_center(baseline, &self.text, self.font); } - fn render_center(&self, target: &mut impl Renderer) { + fn render_center<'s>(&'s self, target: &mut impl Renderer<'s>) { let baseline = Point::new(self.pad.area.bottom_center().x, self.y_baseline()); shape::Text::new(baseline, &self.text.as_ref()) .with_align(Alignment::Center) @@ -136,7 +136,7 @@ where common::display_right(baseline, &self.text, self.font); } - fn render_right(&self, target: &mut impl Renderer) { + fn render_right<'s>(&'s self, target: &mut impl Renderer<'s>) { let baseline = Point::new(self.pad.area.x1, self.y_baseline()); shape::Text::new(baseline, &self.text.as_ref()) .with_align(Alignment::End) @@ -201,7 +201,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); if self.show_content { // In the case text cannot fit, show ellipsis and its right part diff --git a/core/embed/rust/src/ui/model_tr/component/coinjoin_progress.rs b/core/embed/rust/src/ui/model_tr/component/coinjoin_progress.rs index d4d2dc5628..6d570518f0 100644 --- a/core/embed/rust/src/ui/model_tr/component/coinjoin_progress.rs +++ b/core/embed/rust/src/ui/model_tr/component/coinjoin_progress.rs @@ -136,7 +136,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // TOP let center = self.area.center() + Offset::y(self.loader_y_offset); diff --git a/core/embed/rust/src/ui/model_tr/component/error.rs b/core/embed/rust/src/ui/model_tr/component/error.rs index 96b5549dab..f05f6ea7f0 100644 --- a/core/embed/rust/src/ui/model_tr/component/error.rs +++ b/core/embed/rust/src/ui/model_tr/component/error.rs @@ -99,7 +99,7 @@ impl> Component for ErrorScreen { self.footer.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); if self.show_icons { diff --git a/core/embed/rust/src/ui/model_tr/component/flow.rs b/core/embed/rust/src/ui/model_tr/component/flow.rs index a1a8b7f1b2..6db519a53f 100644 --- a/core/embed/rust/src/ui/model_tr/component/flow.rs +++ b/core/embed/rust/src/ui/model_tr/component/flow.rs @@ -310,7 +310,7 @@ where self.current_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); // Scrollbars are painted only with a title and when requested if self.title.is_some() { diff --git a/core/embed/rust/src/ui/model_tr/component/flow_pages.rs b/core/embed/rust/src/ui/model_tr/component/flow_pages.rs index b43434902e..6ff71657b3 100644 --- a/core/embed/rust/src/ui/model_tr/component/flow_pages.rs +++ b/core/embed/rust/src/ui/model_tr/component/flow_pages.rs @@ -133,8 +133,7 @@ where self.formatted.paint(); } - pub fn render(&mut self, target: &mut impl Renderer) { - self.change_page(self.current_page); + pub fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.formatted.render(target); } diff --git a/core/embed/rust/src/ui/model_tr/component/frame.rs b/core/embed/rust/src/ui/model_tr/component/frame.rs index 6d974ede13..25b735c368 100644 --- a/core/embed/rust/src/ui/model_tr/component/frame.rs +++ b/core/embed/rust/src/ui/model_tr/component/frame.rs @@ -85,7 +85,7 @@ where self.content.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.title.render(target); self.content.render(target); } @@ -211,7 +211,7 @@ where self.content.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.title.render(target); self.scrollbar.render(target); self.content.render(target); diff --git a/core/embed/rust/src/ui/model_tr/component/hold_to_confirm.rs b/core/embed/rust/src/ui/model_tr/component/hold_to_confirm.rs index 89fdd41fbf..d0afb1e2cf 100644 --- a/core/embed/rust/src/ui/model_tr/component/hold_to_confirm.rs +++ b/core/embed/rust/src/ui/model_tr/component/hold_to_confirm.rs @@ -124,7 +124,7 @@ impl Component for HoldToConfirm { self.loader.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.loader.render(target); } } diff --git a/core/embed/rust/src/ui/model_tr/component/homescreen.rs b/core/embed/rust/src/ui/model_tr/component/homescreen.rs index 20d035d7a0..9b5eb57396 100644 --- a/core/embed/rust/src/ui/model_tr/component/homescreen.rs +++ b/core/embed/rust/src/ui/model_tr/component/homescreen.rs @@ -1,6 +1,10 @@ use crate::{ error::Error, - micropython::buffer::StrBuffer, + micropython::{ + buffer::{get_buffer, StrBuffer}, + gc::Gc, + obj::Obj, + }, strutil::StringType, translations::TR, trezorhal::usb::usb_configured, @@ -50,7 +54,7 @@ fn paint_default_image() { ); } -fn render_default_image(target: &mut impl Renderer) { +fn render_default_image<'s>(target: &mut impl Renderer<'s>) { shape::ToifImage::new( TOP_CENTER + Offset::y(LOGO_ICON_TOP_MARGIN), theme::ICON_LOGO.toif, @@ -74,6 +78,7 @@ where // always painted, so we need to always paint the label too label: Label, notification: Option<(T, u8)>, + custom_image: Option>, /// Used for HTC functionality to lock device from homescreen invisible_buttons: Child, /// Holds the loader component @@ -97,6 +102,7 @@ where Self { label: Label::centered(label, theme::TEXT_BIG), notification, + custom_image: get_user_custom_image().ok(), invisible_buttons: Child::new(ButtonController::new(invisible_btn_layout)), loader, show_loader: false, @@ -105,8 +111,8 @@ where } fn paint_homescreen_image(&self) { - let homescreen_bytes = get_user_custom_image().ok(); - let homescreen = homescreen_bytes + let homescreen = self + .custom_image .as_ref() .and_then(|data| Toif::new(data.as_ref()).ok()) .filter(check_homescreen_format); @@ -117,17 +123,17 @@ where } } - fn render_homescreen_image(&self, target: &mut impl Renderer) { - let homescreen_bytes = get_user_custom_image().ok(); - let homescreen = homescreen_bytes + fn render_homescreen_image<'s>(&'s self, target: &mut impl Renderer<'s>) { + let homescreen = self + .custom_image .as_ref() .and_then(|data| Toif::new(data.as_ref()).ok()) .filter(check_homescreen_format); if let Some(toif) = homescreen { - /*shape::ToifImage::new(TOP_CENTER, toif) - .with_align(Alignment2D::TOP_CENTER) - .with_fg(theme::FG) - .render(target);*/ // !@# lifetime problem + shape::ToifImage::new(TOP_CENTER, toif) + .with_align(Alignment2D::TOP_CENTER) + .with_fg(theme::FG) + .render(target); } else { render_default_image(target); } @@ -164,7 +170,7 @@ where } } - fn render_notification(&self, target: &mut impl Renderer) { + fn render_notification<'s>(&'s self, target: &mut impl Renderer<'s>) { let baseline = TOP_CENTER + Offset::y(NOTIFICATION_FONT.line_height()); if !usb_configured() { shape::Bar::new(AREA.split_top(NOTIFICATION_HEIGHT).0) @@ -217,12 +223,12 @@ where self.label.paint(); } - fn render_label(&mut self, target: &mut impl Renderer) { + fn render_label<'s>(&'s self, target: &mut impl Renderer<'s>) { // paint black background to place the label let mut outset = Insets::uniform(LABEL_OUTSET); // the margin at top is bigger (caused by text-height vs line-height?) // compensate by shrinking the outset - outset.top -= 2; + outset.top -= 5; shape::Bar::new(self.label.text_area().outset(outset)) .with_bg(theme::BG) .render(target); @@ -321,19 +327,11 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // Redraw the whole screen when the screen changes (loader vs homescreen) if self.show_loader { - if !matches!(self.current_screen, CurrentScreen::Loader) { - // display::clear(); !@# what's this?? - self.current_screen = CurrentScreen::Loader; - } self.loader.render(target); } else { - if !matches!(self.current_screen, CurrentScreen::Homescreen) { - // display::clear(); !@# what's this?? - self.current_screen = CurrentScreen::Homescreen; - } // Painting the homescreen image first, as the notification and label // should be "on top of it" self.render_homescreen_image(target); @@ -426,7 +424,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { if self.screensaver { // keep screen blank return; @@ -451,33 +449,32 @@ where } } -pub struct ConfirmHomescreen +pub struct ConfirmHomescreen where T: StringType, { title: Child>, - buffer_func: F, + image: Obj, buttons: Child, } -impl ConfirmHomescreen +impl ConfirmHomescreen where T: StringType + Clone, { - pub fn new(title: T, buffer_func: F) -> Self { + pub fn new(title: T, image: Obj) -> Self { let btn_layout = ButtonLayout::cancel_none_text(TR::buttons__change.into()); ConfirmHomescreen { title: Child::new(Label::centered(title, theme::TEXT_BOLD)), - buffer_func, + image, buttons: Child::new(ButtonController::new(btn_layout)), } } } -impl<'a, T, F> Component for ConfirmHomescreen +impl<'a, T> Component for ConfirmHomescreen where T: StringType + Clone, - F: Fn() -> &'a [u8], { type Msg = CancelConfirmMsg; @@ -504,11 +501,13 @@ where fn paint(&mut self) { // Drawing the image full-screen first and then other things on top - let buffer = (self.buffer_func)(); - if buffer.is_empty() { + // SAFETY: We expect no existing mutable reference. Resulting reference is + // discarded before returning to micropython. + let image_data = unwrap!(unsafe { get_buffer(self.image) }); + if image_data.is_empty() { paint_default_image(); } else { - let toif_data = unwrap!(Toif::new(buffer)); + let toif_data = unwrap!(Toif::new(image_data)); toif_data.draw(TOP_CENTER, Alignment2D::TOP_CENTER, theme::FG, theme::BG); }; // Need to make all the title background black, so the title text is well @@ -519,16 +518,18 @@ where self.buttons.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // Drawing the image full-screen first and then other things on top - let buffer = (self.buffer_func)(); - if buffer.is_empty() { + // SAFETY: We expect no existing mutable reference. Resulting reference is + // discarded before returning to micropython. + let image_data = unwrap!(unsafe { get_buffer(self.image) }); + if image_data.is_empty() { render_default_image(target); } else { - /*let toif_data = unwrap!(Toif::new(buffer)); + let toif_data = unwrap!(Toif::new(image_data)); shape::ToifImage::new(TOP_CENTER, toif_data) .with_fg(theme::FG) - .render(target);*/ // !@# lifetime problem + .render(target); }; // Need to make all the title background black, so the title text is well // visible @@ -572,7 +573,7 @@ where } #[cfg(feature = "ui_debug")] -impl crate::trace::Trace for ConfirmHomescreen +impl crate::trace::Trace for ConfirmHomescreen where T: StringType, { diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/choice.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/choice.rs index 5e0c70834f..9ae0892096 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/choice.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/choice.rs @@ -16,7 +16,7 @@ pub trait Choice { // and therefore has a default implementation. fn paint_center(&self, area: Rect, inverse: bool); - fn render_center(&self, target: &mut impl Renderer, _area: Rect, _inverse: bool); + fn render_center<'s>(&self, target: &mut impl Renderer<'s>, _area: Rect, _inverse: bool); fn width_center(&self) -> i16 { 0 @@ -24,7 +24,7 @@ pub trait Choice { fn paint_side(&self, _area: Rect) {} - fn render_side(&self, _target: &mut impl Renderer, _area: Rect) {} + fn render_side<'s>(&self, _target: &mut impl Renderer<'s>, _area: Rect) {} fn width_side(&self) -> i16 { 0 @@ -257,11 +257,11 @@ where /// Display current, previous and next choices according to /// the current ChoiceItem. - fn render_choices(&mut self, target: &mut impl Renderer) { + fn render_choices<'s>(&'s self, target: &mut impl Renderer<'s>) { // Getting the row area for the choices - so that displaying // items in the used font will show them in the middle vertically. let area_height_half = self.pad.area.height() / 2; - let font_size_half = theme::FONT_CHOICE_ITEMS.text_height() / 2; + let font_size_half = theme::FONT_CHOICE_ITEMS.visible_text_height("Ay") / 2; let center_row_area = self .pad .area @@ -341,14 +341,9 @@ where } /// Display the current choice in the middle. - fn show_current_choice2(&mut self, target: &mut impl Renderer, area: Rect) { + fn show_current_choice2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) { self.get_current_item() .render_center(target, area, self.inverse_selected_item); - - // Color inversion is just one-time thing. - if self.inverse_selected_item { - self.inverse_selected_item = false; - } } /// Display all the choices fitting on the left side. @@ -395,7 +390,7 @@ where /// Display all the choices fitting on the left side. /// Going as far as possible. - fn show_left_choices2(&self, target: &mut impl Renderer, area: Rect) { + fn show_left_choices2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) { // NOTE: page index can get negative here, so having it as i16 instead of usize let mut page_index = self.page_counter as i16 - 1; let mut current_area = area.split_right(self.items_distance).0; @@ -478,7 +473,7 @@ where /// Display all the choices fitting on the right side. /// Going as far as possible. - fn show_right_choices2(&self, target: &mut impl Renderer, area: Rect) { + fn show_right_choices2<'s>(&'s self, target: &mut impl Renderer<'s>, area: Rect) { let mut page_index = self.page_counter + 1; let mut current_area = area.split_left(self.items_distance).1; while current_area.width() > 0 { @@ -624,7 +619,6 @@ where } fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option { - // Cancel highlighting of the current choice. // The Highlighting is started by pressing the middle button and // canceled immediately when any other event is processed @@ -728,7 +722,7 @@ where self.paint_choices(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.buttons.render(target); self.render_choices(target); diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/choice_item.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/choice_item.rs index 6dfb580947..ed948d6994 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/choice_item.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/choice_item.rs @@ -111,12 +111,12 @@ impl Choice for ChoiceItem { /// Painting the item as the main choice in the middle. /// Showing both the icon and text, if the icon is available. - fn render_center(&self, target: &mut impl Renderer, area: Rect, inverse: bool) { + fn render_center<'s>(&self, target: &mut impl Renderer<'s>, area: Rect, inverse: bool) { let width = text_icon_width(Some(self.text.as_ref()), self.icon, self.font); render_rounded_highlight( target, area, - Offset::new(width, self.font.text_height()), + Offset::new(width, self.font.visible_text_height("Ay")), inverse, ); render_text_icon( @@ -149,7 +149,7 @@ impl Choice for ChoiceItem { } /// Painting smaller version of the item on the side. - fn render_side(&self, target: &mut impl Renderer, area: Rect) { + fn render_side<'s>(&self, target: &mut impl Renderer<'s>, area: Rect) { let width = text_icon_width(self.side_text(), self.icon, self.font); render_text_icon( target, @@ -188,7 +188,12 @@ fn paint_rounded_highlight(area: Rect, size: Offset, inverse: bool) { } } -fn render_rounded_highlight(target: &mut impl Renderer, area: Rect, size: Offset, inverse: bool) { +fn render_rounded_highlight<'s>( + target: &mut impl Renderer<'s>, + area: Rect, + size: Offset, + inverse: bool, +) { let bound = theme::BUTTON_OUTLINE; let left_bottom = area.bottom_center() + Offset::new(-size.x / 2 - bound, bound + 1); let x_size = size.x + 2 * bound; @@ -257,8 +262,8 @@ fn paint_text_icon( } } -fn render_text_icon( - target: &mut impl Renderer, +fn render_text_icon<'s>( + target: &mut impl Renderer<'s>, area: Rect, width: i16, text: Option<&str>, @@ -270,7 +275,7 @@ fn render_text_icon( let mut baseline = area.bottom_center() - Offset::x(width / 2); if let Some(icon) = icon { - let height_diff = font.text_height() - icon.toif.height(); + let height_diff = font.visible_text_height("Ay") - icon.toif.height(); let vertical_offset = Offset::y(-height_diff / 2); shape::ToifImage::new(baseline + vertical_offset, icon.toif) .with_align(Alignment2D::BOTTOM_LEFT) diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/number_input.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/number_input.rs index 699ac405de..d67124917e 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/number_input.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/number_input.rs @@ -83,7 +83,7 @@ impl Component for NumberInput { self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.choice_page.render(target); } } diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/passphrase.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/passphrase.rs index c4f77e1b06..3bb4714636 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/passphrase.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/passphrase.rs @@ -450,7 +450,7 @@ impl Component for PassphraseEntry { self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.passphrase_dots.render(target); self.choice_page.render(target); } diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/pin.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/pin.rs index 199235277d..764e02b057 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/pin.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/pin.rs @@ -331,7 +331,7 @@ where self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.header_line.render(target); self.pin_line.render(target); self.choice_page.render(target); diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/simple_choice.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/simple_choice.rs index 36cff2a437..f322c8cf17 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/simple_choice.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/simple_choice.rs @@ -117,7 +117,7 @@ impl Component for SimpleChoice { self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.choice_page.render(target); } } diff --git a/core/embed/rust/src/ui/model_tr/component/input_methods/wordlist.rs b/core/embed/rust/src/ui/model_tr/component/input_methods/wordlist.rs index 7090c2b5b2..d29f757b8b 100644 --- a/core/embed/rust/src/ui/model_tr/component/input_methods/wordlist.rs +++ b/core/embed/rust/src/ui/model_tr/component/input_methods/wordlist.rs @@ -312,7 +312,7 @@ impl Component for WordlistEntry { self.choice_page.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.chosen_letters.render(target); self.choice_page.render(target); } diff --git a/core/embed/rust/src/ui/model_tr/component/loader.rs b/core/embed/rust/src/ui/model_tr/component/loader.rs index 7c8708b727..f0c3a28e46 100644 --- a/core/embed/rust/src/ui/model_tr/component/loader.rs +++ b/core/embed/rust/src/ui/model_tr/component/loader.rs @@ -167,7 +167,12 @@ impl Loader { ); } - pub fn render_loader(&mut self, target: &mut impl Renderer, style: &LoaderStyle, done: i32) { + pub fn render_loader<'s>( + &'s self, + target: &mut impl Renderer<'s>, + style: &LoaderStyle, + done: i32, + ) { let width = self.area.width(); // NOTE: need to calculate this in `i32`, it would overflow using `i16` let split_point = (((width as i32 + 1) * done) / (display::LOADER_MAX as i32)) as i16; @@ -266,7 +271,7 @@ impl Component for Loader { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // TODO: Consider passing the current instant along with the event -- that way, // we could synchronize painting across the component tree. Also could be useful // in automated tests. @@ -397,7 +402,7 @@ where self.loader.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.loader.render(target); } } diff --git a/core/embed/rust/src/ui/model_tr/component/page.rs b/core/embed/rust/src/ui/model_tr/component/page.rs index 6a1562a9bb..935f184c88 100644 --- a/core/embed/rust/src/ui/model_tr/component/page.rs +++ b/core/embed/rust/src/ui/model_tr/component/page.rs @@ -217,7 +217,7 @@ where self.buttons.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.content.render(target); self.buttons.render(target); diff --git a/core/embed/rust/src/ui/model_tr/component/progress.rs b/core/embed/rust/src/ui/model_tr/component/progress.rs index b551fb3e8e..e41356e73a 100644 --- a/core/embed/rust/src/ui/model_tr/component/progress.rs +++ b/core/embed/rust/src/ui/model_tr/component/progress.rs @@ -185,7 +185,7 @@ where self.description.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.title.render(target); let area = constant::screen(); diff --git a/core/embed/rust/src/ui/model_tr/component/result.rs b/core/embed/rust/src/ui/model_tr/component/result.rs index 274a7c2a8a..cc1bf8f03c 100644 --- a/core/embed/rust/src/ui/model_tr/component/result.rs +++ b/core/embed/rust/src/ui/model_tr/component/result.rs @@ -110,7 +110,7 @@ impl<'a> Component for ResultScreen<'a> { self.message_bottom.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.small_pad.render(target); diff --git a/core/embed/rust/src/ui/model_tr/component/scrollbar.rs b/core/embed/rust/src/ui/model_tr/component/scrollbar.rs index e8de121a9d..3e812ee91a 100644 --- a/core/embed/rust/src/ui/model_tr/component/scrollbar.rs +++ b/core/embed/rust/src/ui/model_tr/component/scrollbar.rs @@ -108,7 +108,7 @@ impl ScrollBar { /// Create a (seemingly circular) dot given its top left point. /// Make it full when it is active, otherwise paint just the perimeter and /// leave center empty. - fn render_dot(&self, target: &mut impl Renderer, dot_type: &DotType, top_right: Point) { + fn render_dot<'s>(&self, target: &mut impl Renderer<'s>, dot_type: &DotType, top_right: Point) { let full_square = Rect::from_top_right_and_size(top_right, Offset::uniform(Self::MAX_DOT_SIZE)); @@ -234,7 +234,7 @@ impl ScrollBar { } } - fn render_horizontal(&mut self, target: &mut impl Renderer) { + fn render_horizontal<'s>(&'s self, target: &mut impl Renderer<'s>) { let mut top_right = self.pad.area.top_right(); for dot in self.get_drawable_dots().iter().rev() { self.render_dot(target, dot, top_right); @@ -274,7 +274,7 @@ impl Component for ScrollBar { } /// Displaying one dot for each page. - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // Not showing the scrollbar dot when there is only one page if self.page_count <= 1 { return; diff --git a/core/embed/rust/src/ui/model_tr/component/share_words.rs b/core/embed/rust/src/ui/model_tr/component/share_words.rs index 3dc1c77567..c9ca066675 100644 --- a/core/embed/rust/src/ui/model_tr/component/share_words.rs +++ b/core/embed/rust/src/ui/model_tr/component/share_words.rs @@ -99,7 +99,7 @@ where } /// Display the final page with user confirmation. - fn render_final_page(&mut self, target: &mut impl Renderer) { + fn render_final_page<'s>(&'s self, target: &mut impl Renderer<'s>) { let final_text = self.get_final_text(); text_multiline2( target, @@ -131,7 +131,7 @@ where } /// Display current set of recovery words. - fn render_words(&mut self, target: &mut impl Renderer) { + fn render_words<'s>(&'s self, target: &mut impl Renderer<'s>) { let mut y_offset = 0; // Showing the word index and the words itself for i in 0..WORDS_PER_PAGE { @@ -191,7 +191,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // Showing scrollbar in all cases // Individual pages are responsible for not colliding with it self.scrollbar.render(target); diff --git a/core/embed/rust/src/ui/model_tr/component/show_more.rs b/core/embed/rust/src/ui/model_tr/component/show_more.rs index 0c698dfe38..c2a10e1b55 100644 --- a/core/embed/rust/src/ui/model_tr/component/show_more.rs +++ b/core/embed/rust/src/ui/model_tr/component/show_more.rs @@ -79,7 +79,7 @@ where self.buttons.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.content.render(target); self.buttons.render(target); } diff --git a/core/embed/rust/src/ui/model_tr/component/title.rs b/core/embed/rust/src/ui/model_tr/component/title.rs index 8db4e9d6ee..07d99d6ab8 100644 --- a/core/embed/rust/src/ui/model_tr/component/title.rs +++ b/core/embed/rust/src/ui/model_tr/component/title.rs @@ -72,7 +72,7 @@ where } /// Display title/header at the top left of the given area. - pub fn render_header_left(target: &mut impl Renderer, title: &T, area: Rect) { + pub fn render_header_left<'s>(target: &mut impl Renderer<'s>, title: &T, area: Rect) { let text_height = theme::FONT_HEADER.text_height(); let title_baseline = area.top_left() + Offset::y(text_height - 1); shape::Text::new(title_baseline, title.as_ref()) @@ -95,7 +95,7 @@ where } /// Display title/header centered at the top of the given area. - pub fn render_header_centered(target: &mut impl Renderer, title: &T, area: Rect) { + pub fn render_header_centered<'s>(target: &mut impl Renderer<'s>, title: &T, area: Rect) { let text_height = theme::FONT_HEADER.text_height(); let title_baseline = area.top_center() + Offset::y(text_height - 1); shape::Text::new(title_baseline, title.as_ref()) @@ -140,7 +140,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { if self.needs_marquee { self.marquee.render(target); } else if self.centered { diff --git a/core/embed/rust/src/ui/model_tr/component/welcome_screen.rs b/core/embed/rust/src/ui/model_tr/component/welcome_screen.rs index 6269c44b22..a824d85e77 100644 --- a/core/embed/rust/src/ui/model_tr/component/welcome_screen.rs +++ b/core/embed/rust/src/ui/model_tr/component/welcome_screen.rs @@ -55,7 +55,7 @@ impl Component for WelcomeScreen { ); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { shape::ToifImage::new( self.area.bottom_center() - Offset::y(5), theme::ICON_DEVICE_NAME.toif, diff --git a/core/embed/rust/src/ui/model_tr/cshape/dotted_line.rs b/core/embed/rust/src/ui/model_tr/cshape/dotted_line.rs index fbb9dc1731..46cce7a939 100644 --- a/core/embed/rust/src/ui/model_tr/cshape/dotted_line.rs +++ b/core/embed/rust/src/ui/model_tr/cshape/dotted_line.rs @@ -44,13 +44,13 @@ impl HorizontalLine { Self { step, ..self } } - pub fn render(self, renderer: &mut impl Renderer) { + pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) { renderer.render_shape(self); } } -impl Shape for HorizontalLine { - fn bounds(&self, _cache: &DrawingCache) -> Rect { +impl<'s> Shape<'s> for HorizontalLine { + fn bounds(&self, _cache: &DrawingCache<'s>) -> Rect { let size = Offset::new(self.length, self.thickness as i16); Rect::from_top_left_and_size(self.pos, size) } @@ -77,8 +77,8 @@ impl Shape for HorizontalLine { } } -impl ShapeClone for HorizontalLine { - fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> +impl<'s> ShapeClone<'s> for HorizontalLine { + fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape<'s>> where T: LocalAllocLeakExt<'alloc>, { diff --git a/core/embed/rust/src/ui/model_tr/cshape/loader_circular.rs b/core/embed/rust/src/ui/model_tr/cshape/loader_circular.rs index 953cd2b6d3..13424e59a2 100644 --- a/core/embed/rust/src/ui/model_tr/cshape/loader_circular.rs +++ b/core/embed/rust/src/ui/model_tr/cshape/loader_circular.rs @@ -77,13 +77,13 @@ impl LoaderCircular { Rect::from_top_left_and_size(pt, Offset::uniform(self.scale)) } - pub fn render(self, renderer: &mut impl Renderer) { + pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) { renderer.render_shape(self); } } -impl Shape for LoaderCircular { - fn bounds(&self, _cache: &DrawingCache) -> Rect { +impl<'s> Shape<'s> for LoaderCircular { + fn bounds(&self, _cache: &DrawingCache<'s>) -> Rect { let cells = self.cells(); if cells.is_empty() { @@ -106,7 +106,7 @@ impl Shape for LoaderCircular { } } -impl ShapeClone for LoaderCircular { +impl ShapeClone<'_> for LoaderCircular { fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> where T: LocalAllocLeakExt<'alloc>, diff --git a/core/embed/rust/src/ui/model_tr/cshape/loader_small.rs b/core/embed/rust/src/ui/model_tr/cshape/loader_small.rs index 9911f25e76..6797eb567c 100644 --- a/core/embed/rust/src/ui/model_tr/cshape/loader_small.rs +++ b/core/embed/rust/src/ui/model_tr/cshape/loader_small.rs @@ -48,12 +48,12 @@ impl LoaderSmall { Self { color, ..self } } - pub fn render(self, renderer: &mut impl Renderer) { + pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) { renderer.render_shape(self); } } -impl Shape for LoaderSmall { +impl Shape<'_> for LoaderSmall { fn bounds(&self, _cache: &DrawingCache) -> Rect { Rect::from_top_left_and_size(self.pos, Offset::uniform(1)).expand(RADIUS + 1) } @@ -78,7 +78,7 @@ impl Shape for LoaderSmall { } } -impl ShapeClone for LoaderSmall { +impl ShapeClone<'_> for LoaderSmall { fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> where T: LocalAllocLeakExt<'alloc>, diff --git a/core/embed/rust/src/ui/model_tr/cshape/loader_starry.rs b/core/embed/rust/src/ui/model_tr/cshape/loader_starry.rs index ba95246c09..2b4c651600 100644 --- a/core/embed/rust/src/ui/model_tr/cshape/loader_starry.rs +++ b/core/embed/rust/src/ui/model_tr/cshape/loader_starry.rs @@ -52,7 +52,7 @@ impl LoaderStarry { Self { color, ..self } } - pub fn render(self, renderer: &mut impl Renderer) { + pub fn render<'s>(self, renderer: &mut impl Renderer<'s>) { renderer.render_shape(self); } @@ -72,7 +72,7 @@ impl LoaderStarry { } } -impl Shape for LoaderStarry { +impl Shape<'_> for LoaderStarry { fn bounds(&self, _cache: &DrawingCache) -> Rect { Rect::from_top_left_and_size(self.pos, Offset::uniform(1)).expand(RADIUS + STAR_LARGE) } @@ -95,7 +95,7 @@ impl Shape for LoaderStarry { } } -impl ShapeClone for LoaderStarry { +impl ShapeClone<'_> for LoaderStarry { fn clone_at_bump<'alloc, T>(self, bump: &'alloc T) -> Option<&'alloc mut dyn Shape> where T: LocalAllocLeakExt<'alloc>, diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index 84f99be6f2..731d58271a 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -234,10 +234,9 @@ where } } -impl<'a, T, F> ComponentMsgObj for ConfirmHomescreen +impl<'a, T> ComponentMsgObj for ConfirmHomescreen where T: StringType + Clone, - F: Fn() -> &'a [u8], { fn msg_try_into_obj(&self, msg: Self::Msg) -> Result { match msg { @@ -422,15 +421,8 @@ extern "C" fn new_confirm_properties(n_args: usize, args: *const Obj, kwargs: *m extern "C" fn new_confirm_homescreen(n_args: usize, args: *const Obj, kwargs: *mut Map) -> Obj { let block = move |_args: &[Obj], kwargs: &Map| { let title: StrBuffer = kwargs.get(Qstr::MP_QSTR_title)?.try_into()?; - let data: Obj = kwargs.get(Qstr::MP_QSTR_image)?; - - // Layout needs to hold the Obj to play nice with GC. Obj is resolved to &[u8] - // in every paint pass. - // SAFETY: We expect no existing mutable reference. Resulting reference is - // discarded before returning to micropython. - let buffer_func = move || unsafe { unwrap!(get_buffer(data)) }; - - let obj = LayoutObj::new(ConfirmHomescreen::new(title, buffer_func))?; + let image: Obj = kwargs.get(Qstr::MP_QSTR_image)?; + let obj = LayoutObj::new(ConfirmHomescreen::new(title, image))?; Ok(obj.into()) }; diff --git a/core/embed/rust/src/ui/model_tt/bootloader/intro.rs b/core/embed/rust/src/ui/model_tt/bootloader/intro.rs index 4114f845d3..033d86c04c 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/intro.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/intro.rs @@ -103,7 +103,7 @@ impl<'a> Component for Intro<'a> { self.menu.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.title.render(target); self.text.render(target); diff --git a/core/embed/rust/src/ui/model_tt/bootloader/menu.rs b/core/embed/rust/src/ui/model_tt/bootloader/menu.rs index cde8d389b4..234f701460 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/menu.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/menu.rs @@ -109,7 +109,7 @@ impl Component for Menu { self.reset.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.title.render(target); self.close.render(target); diff --git a/core/embed/rust/src/ui/model_tt/bootloader/welcome.rs b/core/embed/rust/src/ui/model_tt/bootloader/welcome.rs index 02ecbe548c..0e2e3302fb 100644 --- a/core/embed/rust/src/ui/model_tt/bootloader/welcome.rs +++ b/core/embed/rust/src/ui/model_tt/bootloader/welcome.rs @@ -59,8 +59,9 @@ impl Component for Welcome { ); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); + shape::Text::new(screen().top_center() + Offset::y(102), "Get started with") .with_align(Alignment::Center) .with_font(Font::NORMAL) diff --git a/core/embed/rust/src/ui/model_tt/component/address_details.rs b/core/embed/rust/src/ui/model_tt/component/address_details.rs index 76dd85b139..3308198f64 100644 --- a/core/embed/rust/src/ui/model_tt/component/address_details.rs +++ b/core/embed/rust/src/ui/model_tt/component/address_details.rs @@ -188,7 +188,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { match self.current_page { 0 => self.qr_code.render(target), 1 => self.details.render(target), diff --git a/core/embed/rust/src/ui/model_tt/component/bl_confirm.rs b/core/embed/rust/src/ui/model_tt/component/bl_confirm.rs index 89bd6ba594..daa002b1a5 100644 --- a/core/embed/rust/src/ui/model_tt/component/bl_confirm.rs +++ b/core/embed/rust/src/ui/model_tt/component/bl_confirm.rs @@ -236,11 +236,11 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.content_pad.render(target); - if let Some(info) = self.info.as_mut() { + if let Some(info) = self.info.as_ref() { if self.show_info { info.close_button.render(target); info.title.render(target); @@ -259,7 +259,7 @@ where self.alert.render(target); self.left_button.render(target); self.right_button.render(target); - match &mut self.title { + match &self.title { ConfirmTitle::Text(label) => label.render(target), ConfirmTitle::Icon(icon) => { shape::ToifImage::new(Point::new(screen().center().x, ICON_TOP), icon.toif) diff --git a/core/embed/rust/src/ui/model_tt/component/button.rs b/core/embed/rust/src/ui/model_tt/component/button.rs index 75da7204ce..a97f74651d 100644 --- a/core/embed/rust/src/ui/model_tt/component/button.rs +++ b/core/embed/rust/src/ui/model_tt/component/button.rs @@ -191,7 +191,7 @@ impl Button { } } - pub fn render_background(&self, target: &mut impl Renderer, style: &ButtonStyle) { + pub fn render_background<'s>(&self, target: &mut impl Renderer<'s>, style: &ButtonStyle) { match &self.content { ButtonContent::IconBlend(_, _, _) => {} _ => shape::Bar::new(self.area) @@ -244,7 +244,7 @@ impl Button { } } - pub fn render_content(&self, target: &mut impl Renderer, style: &ButtonStyle) + pub fn render_content<'s>(&self, target: &mut impl Renderer<'s>, style: &ButtonStyle) where T: AsRef, { @@ -375,7 +375,7 @@ where self.paint_content(style); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let style = self.style(); self.render_background(target, style); self.render_content(target, style); diff --git a/core/embed/rust/src/ui/model_tt/component/coinjoin_progress.rs b/core/embed/rust/src/ui/model_tt/component/coinjoin_progress.rs index 9b6b194947..f64a4fdb9e 100644 --- a/core/embed/rust/src/ui/model_tt/component/coinjoin_progress.rs +++ b/core/embed/rust/src/ui/model_tt/component/coinjoin_progress.rs @@ -134,7 +134,7 @@ where self.label.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.content.render(target); let center = constant::screen().center() + Offset::y(LOADER_OFFSET); diff --git a/core/embed/rust/src/ui/model_tt/component/dialog.rs b/core/embed/rust/src/ui/model_tt/component/dialog.rs index 6f7fda94b2..49c344ca85 100644 --- a/core/embed/rust/src/ui/model_tt/component/dialog.rs +++ b/core/embed/rust/src/ui/model_tt/component/dialog.rs @@ -72,7 +72,7 @@ where self.controls.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.content.render(target); self.controls.render(target); } @@ -204,7 +204,7 @@ where self.controls.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.image.render(target); self.paragraphs.render(target); self.controls.render(target); diff --git a/core/embed/rust/src/ui/model_tt/component/error.rs b/core/embed/rust/src/ui/model_tt/component/error.rs index a74cc38af9..597959a133 100644 --- a/core/embed/rust/src/ui/model_tt/component/error.rs +++ b/core/embed/rust/src/ui/model_tt/component/error.rs @@ -89,7 +89,7 @@ impl> Component for ErrorScreen<'_, T> { self.footer.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); let icon = ICON_WARNING40; diff --git a/core/embed/rust/src/ui/model_tt/component/fido.rs b/core/embed/rust/src/ui/model_tt/component/fido.rs index 71edbb489f..0f3b4d34f0 100644 --- a/core/embed/rust/src/ui/model_tt/component/fido.rs +++ b/core/embed/rust/src/ui/model_tt/component/fido.rs @@ -195,7 +195,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.icon.render(target); self.controls.render(target); self.app_name.render(target); @@ -204,8 +204,6 @@ where self.scrollbar.render(target); } - let current_account = (self.get_account)(self.active_page()); - // Erasing the old text content before writing the new one. let account_name_area = self.account_name.area(); let real_area = account_name_area @@ -215,15 +213,13 @@ where // Account name is optional. // Showing it only if it differs from app name. // (Dummy requests usually have some text as both app_name and account_name.) - if !current_account.as_ref().is_empty() - && current_account.as_ref() != self.app_name.text().as_ref() - { - self.account_name.set_text(current_account); + let account_name = self.account_name.text().as_ref(); + let app_name = self.app_name.text().as_ref(); + if !account_name.is_empty() && account_name != app_name { self.account_name.render(target); } - if self.fade { - self.fade = false; + if self.fade.take() { // Note that this is blocking and takes some time. display::fade_backlight(theme::BACKLIGHT_NORMAL); } diff --git a/core/embed/rust/src/ui/model_tt/component/frame.rs b/core/embed/rust/src/ui/model_tt/component/frame.rs index 99c2233fe8..de2705aab6 100644 --- a/core/embed/rust/src/ui/model_tt/component/frame.rs +++ b/core/embed/rust/src/ui/model_tt/component/frame.rs @@ -170,7 +170,7 @@ where self.content.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.title.render(target); self.subtitle.render(target); self.button.render(target); diff --git a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs index 2eb5208e19..0040eb3c8e 100644 --- a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs +++ b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs @@ -123,7 +123,7 @@ impl Homescreen { self.loader.paint() } - fn render_loader(&mut self, target: &mut impl Renderer) { + fn render_loader<'s>(&'s self, target: &mut impl Renderer<'s>) { TR::progress__locking_device.map_translated(|t| { shape::Text::new(TOP_CENTER + Offset::y(HOLD_Y), t) .with_align(Alignment::Center) @@ -267,13 +267,13 @@ impl Component for Homescreen { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); if self.loader.is_animating() || self.loader.is_completely_grown(Instant::now()) { self.render_loader(target); } else { let img_data = match self.custom_image { - Some(ref img) => IMAGE_HOMESCREEN, //img.as_ref(), !@# solve lifetime problem + Some(ref img) => img.as_ref(), None => IMAGE_HOMESCREEN, }; @@ -458,9 +458,9 @@ impl Component for Lockscreen { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let img_data = match self.custom_image { - Some(ref img) => IMAGE_HOMESCREEN, //img.as_ref(), !@# solve lifetime problem + Some(ref img) => img.as_ref(), None => IMAGE_HOMESCREEN, }; diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs index a5928eaa6f..3badda21cb 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/bip39.rs @@ -156,7 +156,7 @@ impl Component for Bip39Input { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let area = self.button.area(); let style = self.button.style(); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs index 619f9120b2..9868770bc4 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs @@ -131,8 +131,8 @@ pub fn paint_pending_marker(text_baseline: Point, text: &str, font: Font, color: } /// Create a visible "underscoring" of the last letter of a text. -pub fn render_pending_marker( - target: &mut impl Renderer, +pub fn render_pending_marker<'s>( + target: &mut impl Renderer<'s>, text_baseline: Point, text: &str, font: Font, diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs index cdcbde03c7..e5c6f86cd0 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/mnemonic.rs @@ -183,12 +183,12 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.prompt.render(target); self.input.render(target); self.back.render(target); - for btn in &mut self.keys { + for btn in &self.keys { btn.render(target); } } diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs index e0acfd70b5..4140e3f500 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/passphrase.rs @@ -298,16 +298,15 @@ impl Component for PassphraseKeyboard { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.input.render(target); self.scrollbar.render(target); self.confirm.render(target); self.back.render(target); - for btn in &mut self.keys { + for btn in &self.keys { btn.render(target); } - if self.fade { - self.fade = false; + if self.fade.take() { // Note that this is blocking and takes some time. display::fade_backlight(theme::BACKLIGHT_NORMAL); } @@ -393,7 +392,7 @@ impl Component for Input { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let style = theme::label_keyboard(); let text_baseline = self.area.top_left() + Offset::y(style.text_font.text_height()) diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs index d83e42841c..386ff4c98c 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/pin.rs @@ -269,11 +269,11 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.erase_btn.render(target); self.textbox_pad.render(target); if self.textbox.inner().is_empty() { - if let Some(ref mut w) = self.major_warning { + if let Some(ref w) = self.major_warning { w.render(target); } else { self.major_prompt.render(target); @@ -284,7 +284,7 @@ where self.textbox.render(target); } self.confirm_btn.render(target); - for btn in &mut self.digit_btns { + for btn in &self.digit_btns { btn.render(target); } } @@ -389,7 +389,7 @@ impl PinDots { } } - fn render_digits(&self, area: Rect, target: &mut impl Renderer) { + fn render_digits<'s>(&self, area: Rect, target: &mut impl Renderer<'s>) { let center = area.center() + Offset::y(Font::MONO.text_height() / 2); let right = center + Offset::x(Font::MONO.text_width("0") * (MAX_VISIBLE_DOTS as i16) / 2); let digits = self.digits.len(); @@ -454,7 +454,7 @@ impl PinDots { } } - fn render_dots(&self, area: Rect, target: &mut impl Renderer) { + fn render_dots<'s>(&self, area: Rect, target: &mut impl Renderer<'s>) { let mut cursor = self.size().snap(area.center(), Alignment2D::CENTER); let digits = self.digits.len(); @@ -533,7 +533,7 @@ impl Component for PinDots { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let dot_area = self.area.inset(HEADER_PADDING); self.pad.render(target); if self.display_digits { diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs index 871fe048ff..b5be2da33b 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs @@ -187,7 +187,7 @@ impl Component for Slip39Input { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let area = self.button.area(); let style = self.button.style(); diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs index e4dd0eee51..98ec6d8e46 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/word_count.rs @@ -58,8 +58,8 @@ impl Component for SelectWordCount { } } - fn render(&mut self, target: &mut impl Renderer) { - for btn in self.button.iter_mut() { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { + for btn in self.button.iter() { btn.render(target) } } diff --git a/core/embed/rust/src/ui/model_tt/component/loader.rs b/core/embed/rust/src/ui/model_tt/component/loader.rs index 6c653ec885..175a77d6b9 100644 --- a/core/embed/rust/src/ui/model_tt/component/loader.rs +++ b/core/embed/rust/src/ui/model_tt/component/loader.rs @@ -209,7 +209,7 @@ impl Component for Loader { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // TODO: Consider passing the current instant along with the event -- that way, // we could synchronize painting across the component tree. Also could be useful // in automated tests. @@ -250,7 +250,7 @@ impl Component for Loader { if let Some((icon, color)) = style.icon { shape::ToifImage::new(center, icon.toif) .with_align(Alignment2D::CENTER) - .with_bg(color) + .with_fg(color) .render(target); } } diff --git a/core/embed/rust/src/ui/model_tt/component/number_input.rs b/core/embed/rust/src/ui/model_tt/component/number_input.rs index 25ea93e7e4..43aab67cb7 100644 --- a/core/embed/rust/src/ui/model_tt/component/number_input.rs +++ b/core/embed/rust/src/ui/model_tt/component/number_input.rs @@ -124,7 +124,7 @@ where self.confirm_button.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.input.render(target); self.paragraphs_pad.render(target); self.paragraphs.render(target); @@ -240,7 +240,7 @@ impl Component for NumberInput { self.inc.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let mut buf = [0u8; 10]; if let Some(text) = strutil::format_i64(self.value as i64, &mut buf) { diff --git a/core/embed/rust/src/ui/model_tt/component/page.rs b/core/embed/rust/src/ui/model_tt/component/page.rs index ff7031b951..371ca11e6e 100644 --- a/core/embed/rust/src/ui/model_tt/component/page.rs +++ b/core/embed/rust/src/ui/model_tt/component/page.rs @@ -18,6 +18,8 @@ use super::{ SwipeDirection, }; +use core::cell::Cell; + /// Allows pagination of inner component. Shows scroll bar, confirm & cancel /// buttons. Optionally handles hold-to-confirm with loader. pub struct ButtonPage { @@ -41,7 +43,7 @@ pub struct ButtonPage { /// Whether to pass-through right swipe to parent component. swipe_right: bool, /// Fade to given backlight level on next paint(). - fade: Option, + fade: Cell>, } impl ButtonPage @@ -77,7 +79,7 @@ where cancel_from_any_page: false, swipe_left: false, swipe_right: false, - fade: None, + fade: Cell::new(None), } } @@ -157,7 +159,7 @@ where // Swipe has dimmed the screen, so fade back to normal backlight after the next // paint. - self.fade = Some(theme::BACKLIGHT_NORMAL); + self.fade.set(Some(theme::BACKLIGHT_NORMAL)); } fn is_cancel_visible(&self) -> bool { @@ -413,7 +415,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); match &self.loader { Some(l) if l.is_animating() => self.loader.render(target), diff --git a/core/embed/rust/src/ui/model_tt/component/progress.rs b/core/embed/rust/src/ui/model_tt/component/progress.rs index 579a97515b..70e1931d5e 100644 --- a/core/embed/rust/src/ui/model_tt/component/progress.rs +++ b/core/embed/rust/src/ui/model_tt/component/progress.rs @@ -123,7 +123,7 @@ where self.description.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.title.render(target); let center = constant::screen().center() + Offset::y(self.loader_y_offset); diff --git a/core/embed/rust/src/ui/model_tt/component/result.rs b/core/embed/rust/src/ui/model_tt/component/result.rs index 525dc812ac..58d3b70af7 100644 --- a/core/embed/rust/src/ui/model_tt/component/result.rs +++ b/core/embed/rust/src/ui/model_tt/component/result.rs @@ -92,7 +92,7 @@ impl> Component for ResultFooter<'_, T> { self.text.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { // divider line let bar = Rect::from_center_and_size( Point::new(self.area.center().x, self.area.y0), @@ -181,7 +181,7 @@ impl<'a, T: StringType> Component for ResultScreen<'a, T> { self.footer.paint(); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.bg.render(target); self.footer_pad.render(target); diff --git a/core/embed/rust/src/ui/model_tt/component/scroll.rs b/core/embed/rust/src/ui/model_tt/component/scroll.rs index fd1c641b0f..1ea96fd960 100644 --- a/core/embed/rust/src/ui/model_tt/component/scroll.rs +++ b/core/embed/rust/src/ui/model_tt/component/scroll.rs @@ -124,7 +124,7 @@ impl Component for ScrollBar { } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { fn dotsize(distance: usize, nhidden: usize) -> Icon { match (nhidden.saturating_sub(distance)).min(2 - distance) { 0 => theme::DOT_INACTIVE, diff --git a/core/embed/rust/src/ui/model_tt/component/simple_page.rs b/core/embed/rust/src/ui/model_tt/component/simple_page.rs index e70c11e043..160c049c54 100644 --- a/core/embed/rust/src/ui/model_tt/component/simple_page.rs +++ b/core/embed/rust/src/ui/model_tt/component/simple_page.rs @@ -166,7 +166,7 @@ where } } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { self.pad.render(target); self.content.render(target); if self.scrollbar.has_pages() { diff --git a/core/embed/rust/src/ui/model_tt/component/swipe.rs b/core/embed/rust/src/ui/model_tt/component/swipe.rs index d8217a1b96..b4cab1d2ef 100644 --- a/core/embed/rust/src/ui/model_tt/component/swipe.rs +++ b/core/embed/rust/src/ui/model_tt/component/swipe.rs @@ -161,5 +161,5 @@ impl Component for Swipe { fn paint(&mut self) {} - fn render(&mut self, _target: &mut impl Renderer) {} + fn render<'s>(&'s self, _target: &mut impl Renderer<'s>) {} } diff --git a/core/embed/rust/src/ui/model_tt/component/welcome_screen.rs b/core/embed/rust/src/ui/model_tt/component/welcome_screen.rs index cbb162e98e..6fec80d270 100644 --- a/core/embed/rust/src/ui/model_tt/component/welcome_screen.rs +++ b/core/embed/rust/src/ui/model_tt/component/welcome_screen.rs @@ -71,7 +71,7 @@ impl Component for WelcomeScreen { ); } - fn render(&mut self, target: &mut impl Renderer) { + fn render<'s>(&'s self, target: &mut impl Renderer<'s>) { let logo = if self.empty_lock { theme::ICON_LOGO_EMPTY } else {