mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-30 20:58:46 +00:00
refactor(core/rust/ui): expose page count to python
[no changelog]
This commit is contained in:
parent
ee1497b87e
commit
dd9a7d30e5
@ -30,6 +30,7 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_paint;
|
MP_QSTR_paint;
|
||||||
MP_QSTR_trace;
|
MP_QSTR_trace;
|
||||||
MP_QSTR_bounds;
|
MP_QSTR_bounds;
|
||||||
|
MP_QSTR_page_count;
|
||||||
|
|
||||||
MP_QSTR_title;
|
MP_QSTR_title;
|
||||||
MP_QSTR_action;
|
MP_QSTR_action;
|
||||||
|
@ -314,6 +314,7 @@ pub struct EventCtx {
|
|||||||
place_requested: bool,
|
place_requested: bool,
|
||||||
paint_requested: bool,
|
paint_requested: bool,
|
||||||
anim_frame_scheduled: bool,
|
anim_frame_scheduled: bool,
|
||||||
|
page_count: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventCtx {
|
impl EventCtx {
|
||||||
@ -338,6 +339,7 @@ impl EventCtx {
|
|||||||
paint_requested: false, /* We also need to paint, but this is supplemented by
|
paint_requested: false, /* We also need to paint, but this is supplemented by
|
||||||
* `Child::marked_for_paint` being true. */
|
* `Child::marked_for_paint` being true. */
|
||||||
anim_frame_scheduled: false,
|
anim_frame_scheduled: false,
|
||||||
|
page_count: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +378,16 @@ impl EventCtx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_page_count(&mut self, count: usize) {
|
||||||
|
#[cfg(feature = "ui_debug")]
|
||||||
|
assert!(self.page_count.is_none());
|
||||||
|
self.page_count = Some(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn page_count(&self) -> Option<usize> {
|
||||||
|
self.page_count
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_timer(&mut self) -> Option<(TimerToken, Duration)> {
|
pub fn pop_timer(&mut self) -> Option<(TimerToken, Duration)> {
|
||||||
self.timers.pop()
|
self.timers.pop()
|
||||||
}
|
}
|
||||||
@ -384,6 +396,7 @@ impl EventCtx {
|
|||||||
self.place_requested = false;
|
self.place_requested = false;
|
||||||
self.paint_requested = false;
|
self.paint_requested = false;
|
||||||
self.anim_frame_scheduled = false;
|
self.anim_frame_scheduled = false;
|
||||||
|
self.page_count = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_timer(&mut self, token: TimerToken, deadline: Duration) {
|
fn register_timer(&mut self, token: TimerToken, deadline: Duration) {
|
||||||
|
@ -112,6 +112,7 @@ struct LayoutObjInner {
|
|||||||
root: Gc<dyn ObjComponent>,
|
root: Gc<dyn ObjComponent>,
|
||||||
event_ctx: EventCtx,
|
event_ctx: EventCtx,
|
||||||
timer_fn: Obj,
|
timer_fn: Obj,
|
||||||
|
page_count: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutObj {
|
impl LayoutObj {
|
||||||
@ -130,6 +131,7 @@ impl LayoutObj {
|
|||||||
root,
|
root,
|
||||||
event_ctx: EventCtx::new(),
|
event_ctx: EventCtx::new(),
|
||||||
timer_fn: Obj::const_none(),
|
timer_fn: Obj::const_none(),
|
||||||
|
page_count: 1,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -174,6 +176,10 @@ impl LayoutObj {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(count) = inner.event_ctx.page_count() {
|
||||||
|
inner.page_count = count as u16;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +253,10 @@ impl LayoutObj {
|
|||||||
.trace(&mut CallbackTracer(callback));
|
.trace(&mut CallbackTracer(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn obj_page_count(&self) -> Obj {
|
||||||
|
self.inner.borrow().page_count.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
fn obj_bounds(&self) {
|
fn obj_bounds(&self) {
|
||||||
use crate::ui::display;
|
use crate::ui::display;
|
||||||
@ -275,6 +285,7 @@ impl LayoutObj {
|
|||||||
Qstr::MP_QSTR_paint => obj_fn_1!(ui_layout_paint).as_obj(),
|
Qstr::MP_QSTR_paint => obj_fn_1!(ui_layout_paint).as_obj(),
|
||||||
Qstr::MP_QSTR_trace => obj_fn_2!(ui_layout_trace).as_obj(),
|
Qstr::MP_QSTR_trace => obj_fn_2!(ui_layout_trace).as_obj(),
|
||||||
Qstr::MP_QSTR_bounds => obj_fn_1!(ui_layout_bounds).as_obj(),
|
Qstr::MP_QSTR_bounds => obj_fn_1!(ui_layout_bounds).as_obj(),
|
||||||
|
Qstr::MP_QSTR_page_count => obj_fn_1!(ui_layout_page_count).as_obj(),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
&TYPE
|
&TYPE
|
||||||
@ -411,6 +422,14 @@ extern "C" fn ui_layout_paint(this: Obj) -> Obj {
|
|||||||
unsafe { util::try_or_raise(block) }
|
unsafe { util::try_or_raise(block) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" fn ui_layout_page_count(this: Obj) -> Obj {
|
||||||
|
let block = || {
|
||||||
|
let this: Gc<LayoutObj> = this.try_into()?;
|
||||||
|
Ok(this.obj_page_count())
|
||||||
|
};
|
||||||
|
unsafe { util::try_or_raise(block) }
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ui_debug")]
|
#[cfg(feature = "ui_debug")]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn ui_debug_layout_type() -> &'static Type {
|
pub extern "C" fn ui_debug_layout_type() -> &'static Type {
|
||||||
|
@ -67,6 +67,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
ctx.set_page_count(self.scrollbar.page_count);
|
||||||
if self.scrollbar.has_previous_page() {
|
if self.scrollbar.has_previous_page() {
|
||||||
if let Some(ButtonMsg::Clicked) = self.prev.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.prev.event(ctx, event) {
|
||||||
// Scroll up.
|
// Scroll up.
|
||||||
|
@ -67,6 +67,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
ctx.set_page_count(self.scrollbar.page_count);
|
||||||
if self.scrollbar.has_previous_page() {
|
if self.scrollbar.has_previous_page() {
|
||||||
if let Some(ButtonMsg::Clicked) = self.prev.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.prev.event(ctx, event) {
|
||||||
// Scroll up.
|
// Scroll up.
|
||||||
|
@ -99,6 +99,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
fn event(&mut self, ctx: &mut EventCtx, event: Event) -> Option<Self::Msg> {
|
||||||
|
ctx.set_page_count(self.scrollbar.page_count);
|
||||||
if let Some(swipe) = self.swipe.event(ctx, event) {
|
if let Some(swipe) = self.swipe.event(ctx, event) {
|
||||||
match swipe {
|
match swipe {
|
||||||
SwipeDirection::Up => {
|
SwipeDirection::Up => {
|
||||||
@ -339,6 +340,7 @@ mod tests {
|
|||||||
TouchEvent::TouchMove(p)
|
TouchEvent::TouchMove(p)
|
||||||
};
|
};
|
||||||
component.event(&mut ctx, Event::Touch(ev));
|
component.event(&mut ctx, Event::Touch(ev));
|
||||||
|
ctx.clear();
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -577,11 +577,19 @@ class spawn(Syscall):
|
|||||||
class Timer(Syscall):
|
class Timer(Syscall):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.task: Task | None = None
|
self.task: Task | None = None
|
||||||
|
# Event::Attach is evaluated before task is set. Use this list to
|
||||||
|
# buffer timers until task is set.
|
||||||
|
self.before_task: list[tuple[int, Any]] = []
|
||||||
|
|
||||||
def handle(self, task: Task) -> None:
|
def handle(self, task: Task) -> None:
|
||||||
self.task = task
|
self.task = task
|
||||||
|
for deadline, value in self.before_task:
|
||||||
|
schedule(self.task, value, deadline)
|
||||||
|
self.before_task.clear()
|
||||||
|
|
||||||
def schedule(self, deadline: int, value: Any) -> None:
|
def schedule(self, deadline: int, value: Any) -> None:
|
||||||
deadline = utime.ticks_add(utime.ticks_ms(), deadline)
|
deadline = utime.ticks_add(utime.ticks_ms(), deadline)
|
||||||
if self.task is not None:
|
if self.task is not None:
|
||||||
schedule(self.task, value, deadline)
|
schedule(self.task, value, deadline)
|
||||||
|
else:
|
||||||
|
self.before_task.append((deadline, value))
|
||||||
|
@ -16,11 +16,15 @@ async def button_request(
|
|||||||
ctx: wire.GenericContext,
|
ctx: wire.GenericContext,
|
||||||
br_type: str,
|
br_type: str,
|
||||||
code: ButtonRequestType = ButtonRequestType.Other,
|
code: ButtonRequestType = ButtonRequestType.Other,
|
||||||
|
pages: int | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
if __debug__:
|
if __debug__:
|
||||||
log.debug(__name__, "ButtonRequest.type=%s", br_type)
|
log.debug(__name__, "ButtonRequest.type=%s", br_type)
|
||||||
workflow.close_others()
|
workflow.close_others()
|
||||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
if pages is not None:
|
||||||
|
await ctx.call(ButtonRequest(code=code, pages=pages), ButtonAck)
|
||||||
|
else:
|
||||||
|
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||||
|
|
||||||
|
|
||||||
async def interact(
|
async def interact(
|
||||||
@ -34,6 +38,9 @@ async def interact(
|
|||||||
|
|
||||||
assert isinstance(layout, Paginated)
|
assert isinstance(layout, Paginated)
|
||||||
return await layout.interact(ctx, code=br_code)
|
return await layout.interact(ctx, code=br_code)
|
||||||
|
elif hasattr(layout, "page_count") and layout.page_count() > 1: # type: ignore [Cannot access member "page_count" for type "LayoutType"]
|
||||||
|
await button_request(ctx, br_type, br_code, pages=layout.page_count()) # type: ignore [Cannot access member "page_count" for type "LayoutType"]
|
||||||
|
return await ctx.wait(layout)
|
||||||
else:
|
else:
|
||||||
await button_request(ctx, br_type, br_code)
|
await button_request(ctx, br_type, br_code)
|
||||||
return await ctx.wait(layout)
|
return await ctx.wait(layout)
|
||||||
|
@ -19,6 +19,7 @@ class _RustLayout(ui.Layout):
|
|||||||
def __init__(self, layout: Any):
|
def __init__(self, layout: Any):
|
||||||
self.layout = layout
|
self.layout = layout
|
||||||
self.timer = loop.Timer()
|
self.timer = loop.Timer()
|
||||||
|
self.layout.attach_timer_fn(self.set_timer)
|
||||||
|
|
||||||
def set_timer(self, token: int, deadline: int) -> None:
|
def set_timer(self, token: int, deadline: int) -> None:
|
||||||
self.timer.schedule(deadline, token)
|
self.timer.schedule(deadline, token)
|
||||||
@ -71,7 +72,6 @@ class _RustLayout(ui.Layout):
|
|||||||
def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator]
|
def handle_input_and_rendering(self) -> loop.Task: # type: ignore [awaitable-is-generator]
|
||||||
touch = loop.wait(io.TOUCH)
|
touch = loop.wait(io.TOUCH)
|
||||||
self._before_render()
|
self._before_render()
|
||||||
self.layout.attach_timer_fn(self.set_timer)
|
|
||||||
self.layout.paint()
|
self.layout.paint()
|
||||||
# self.layout.bounds()
|
# self.layout.bounds()
|
||||||
while True:
|
while True:
|
||||||
@ -95,6 +95,9 @@ class _RustLayout(ui.Layout):
|
|||||||
if msg is not None:
|
if msg is not None:
|
||||||
raise ui.Result(msg)
|
raise ui.Result(msg)
|
||||||
|
|
||||||
|
def page_count(self) -> int:
|
||||||
|
return self.layout.page_count()
|
||||||
|
|
||||||
|
|
||||||
async def confirm_action(
|
async def confirm_action(
|
||||||
ctx: wire.GenericContext,
|
ctx: wire.GenericContext,
|
||||||
|
Loading…
Reference in New Issue
Block a user