mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 20:38:10 +00:00
ui: reduce flicker in buttons, text, and pin dialog
This commit is contained in:
parent
faa665a80b
commit
dd5eba8da9
@ -159,6 +159,11 @@ def grid(
|
|||||||
|
|
||||||
|
|
||||||
class Widget:
|
class Widget:
|
||||||
|
tainted = True
|
||||||
|
|
||||||
|
def taint(self):
|
||||||
|
self.tainted = True
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -173,21 +178,3 @@ class Widget:
|
|||||||
event, *pos = yield touch
|
event, *pos = yield touch
|
||||||
result = self.touch(event, pos)
|
result = self.touch(event, pos)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class LazyWidget(Widget):
|
|
||||||
render_next_frame = True
|
|
||||||
|
|
||||||
def taint(self):
|
|
||||||
self.render_next_frame = True
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
touch = loop.wait(io.TOUCH)
|
|
||||||
result = None
|
|
||||||
while result is None:
|
|
||||||
if self.render_next_frame:
|
|
||||||
self.render()
|
|
||||||
self.render_next_frame = False
|
|
||||||
event, *pos = yield touch
|
|
||||||
result = self.touch(event, pos)
|
|
||||||
return result
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
from trezor import io, ui
|
from trezor import io, ui
|
||||||
from trezor.ui import LazyWidget, contains, display, rotate
|
from trezor.ui import Widget, contains, display, rotate
|
||||||
|
|
||||||
# button events
|
# button events
|
||||||
BTN_CLICKED = const(1)
|
BTN_CLICKED = const(1)
|
||||||
@ -17,7 +17,7 @@ ICON = const(16) # icon size in pixels
|
|||||||
BORDER = const(4) # border size in pixels
|
BORDER = const(4) # border size in pixels
|
||||||
|
|
||||||
|
|
||||||
class Button(LazyWidget):
|
class Button(Widget):
|
||||||
def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY):
|
def __init__(self, area: tuple, content: str, style: dict = ui.BTN_KEY):
|
||||||
self.area = area
|
self.area = area
|
||||||
self.content = content
|
self.content = content
|
||||||
@ -29,14 +29,16 @@ class Button(LazyWidget):
|
|||||||
def enable(self):
|
def enable(self):
|
||||||
if self.state == BTN_DISABLED:
|
if self.state == BTN_DISABLED:
|
||||||
self.state = BTN_INITIAL
|
self.state = BTN_INITIAL
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
if self.state != BTN_DISABLED:
|
if self.state != BTN_DISABLED:
|
||||||
self.state = BTN_DISABLED
|
self.state = BTN_DISABLED
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
if not self.tainted:
|
||||||
|
return
|
||||||
state = self.state
|
state = self.state
|
||||||
if state == BTN_DISABLED:
|
if state == BTN_DISABLED:
|
||||||
s = self.disabled_style
|
s = self.disabled_style
|
||||||
@ -47,6 +49,7 @@ class Button(LazyWidget):
|
|||||||
ax, ay, aw, ah = self.area
|
ax, ay, aw, ah = self.area
|
||||||
self.render_background(s, ax, ay, aw, ah)
|
self.render_background(s, ax, ay, aw, ah)
|
||||||
self.render_content(s, ax, ay, aw, ah)
|
self.render_content(s, ax, ay, aw, ah)
|
||||||
|
self.tainted = False
|
||||||
|
|
||||||
def render_background(self, s, ax, ay, aw, ah):
|
def render_background(self, s, ax, ay, aw, ah):
|
||||||
radius = s["radius"]
|
radius = s["radius"]
|
||||||
@ -89,20 +92,21 @@ class Button(LazyWidget):
|
|||||||
if event == io.TOUCH_START:
|
if event == io.TOUCH_START:
|
||||||
if contains(self.area, pos):
|
if contains(self.area, pos):
|
||||||
self.state = BTN_ACTIVE
|
self.state = BTN_ACTIVE
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
|
|
||||||
elif event == io.TOUCH_MOVE:
|
elif event == io.TOUCH_MOVE:
|
||||||
if contains(self.area, pos):
|
if contains(self.area, pos):
|
||||||
if state == BTN_FOCUSED:
|
if state == BTN_FOCUSED:
|
||||||
self.state = BTN_ACTIVE
|
self.state = BTN_ACTIVE
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
else:
|
else:
|
||||||
if state == BTN_ACTIVE:
|
if state == BTN_ACTIVE:
|
||||||
self.state = BTN_FOCUSED
|
self.state = BTN_FOCUSED
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
|
|
||||||
elif event == io.TOUCH_END:
|
elif event == io.TOUCH_END:
|
||||||
|
if state != BTN_INITIAL:
|
||||||
self.state = BTN_INITIAL
|
self.state = BTN_INITIAL
|
||||||
self.render_next_frame = True
|
self.tainted = True
|
||||||
if state == BTN_ACTIVE and contains(self.area, pos):
|
if state == BTN_ACTIVE and contains(self.area, pos):
|
||||||
return BTN_CLICKED
|
return BTN_CLICKED
|
||||||
|
@ -79,7 +79,6 @@ class HoldToConfirmDialog(Widget):
|
|||||||
self.loader.start()
|
self.loader.start()
|
||||||
return _STARTED
|
return _STARTED
|
||||||
if was_active and not is_active:
|
if was_active and not is_active:
|
||||||
if isinstance(self.content, ui.LazyWidget):
|
|
||||||
self.content.taint()
|
self.content.taint()
|
||||||
if self.loader.stop():
|
if self.loader.stop():
|
||||||
return CONFIRMED
|
return CONFIRMED
|
||||||
|
@ -35,6 +35,13 @@ class PinMatrix(ui.Widget):
|
|||||||
self.onchange = None
|
self.onchange = None
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
# pin matrix buttons
|
||||||
|
for btn in self.pin_buttons:
|
||||||
|
btn.render()
|
||||||
|
|
||||||
|
if not self.tainted:
|
||||||
|
return
|
||||||
|
|
||||||
# clear canvas under input line
|
# clear canvas under input line
|
||||||
display.bar(0, 0, ui.WIDTH, 45, ui.BG)
|
display.bar(0, 0, ui.WIDTH, 45, ui.BG)
|
||||||
|
|
||||||
@ -52,9 +59,7 @@ class PinMatrix(ui.Widget):
|
|||||||
# input line with header label
|
# input line with header label
|
||||||
display.text_center(ui.WIDTH // 2, 36, self.label, ui.BOLD, ui.GREY, ui.BG)
|
display.text_center(ui.WIDTH // 2, 36, self.label, ui.BOLD, ui.GREY, ui.BG)
|
||||||
|
|
||||||
# pin matrix buttons
|
self.tainted = False
|
||||||
for btn in self.pin_buttons:
|
|
||||||
btn.render()
|
|
||||||
|
|
||||||
def touch(self, event, pos):
|
def touch(self, event, pos):
|
||||||
for btn in self.pin_buttons:
|
for btn in self.pin_buttons:
|
||||||
@ -64,6 +69,7 @@ class PinMatrix(ui.Widget):
|
|||||||
break
|
break
|
||||||
|
|
||||||
def change(self, pin):
|
def change(self, pin):
|
||||||
|
self.tainted = True
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
for btn in self.pin_buttons:
|
for btn in self.pin_buttons:
|
||||||
if len(self.pin) == self.maxlength:
|
if len(self.pin) == self.maxlength:
|
||||||
|
@ -106,7 +106,7 @@ def render_text(words: list, new_lines: bool, max_lines: int) -> None:
|
|||||||
offset_x += SPACE
|
offset_x += SPACE
|
||||||
|
|
||||||
|
|
||||||
class Text(ui.LazyWidget):
|
class Text(ui.Widget):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
header_text: str,
|
header_text: str,
|
||||||
@ -121,6 +121,7 @@ class Text(ui.LazyWidget):
|
|||||||
self.max_lines = max_lines
|
self.max_lines = max_lines
|
||||||
self.new_lines = new_lines
|
self.new_lines = new_lines
|
||||||
self.content = []
|
self.content = []
|
||||||
|
self.tainted = True
|
||||||
|
|
||||||
def normal(self, *content):
|
def normal(self, *content):
|
||||||
self.content.append(ui.NORMAL)
|
self.content.append(ui.NORMAL)
|
||||||
@ -142,7 +143,10 @@ class Text(ui.LazyWidget):
|
|||||||
self.content.append(BR)
|
self.content.append(BR)
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
|
if not self.tainted:
|
||||||
|
return
|
||||||
ui.header(
|
ui.header(
|
||||||
self.header_text, self.header_icon, ui.TITLE_GREY, ui.BG, self.icon_color
|
self.header_text, self.header_icon, ui.TITLE_GREY, ui.BG, self.icon_color
|
||||||
)
|
)
|
||||||
render_text(self.content, self.new_lines, self.max_lines)
|
render_text(self.content, self.new_lines, self.max_lines)
|
||||||
|
self.tainted = False
|
||||||
|
Loading…
Reference in New Issue
Block a user