Esempio n. 1
0
 async def __iter__(self) -> ResultValue:
     """
     Run the layout and wait until it completes.  Returns the result value.
     Usually not overridden.
     """
     value = None
     try:
         # If any other layout is running (waiting on the layout channel),
         # we close it with the Cancelled exception, and wait until it is
         # closed, just to be sure.
         if layout_chan.takers:
             await layout_chan.put(Cancelled())
         # Now, no other layout should be running.  In a loop, we create new
         # layout tasks and execute them in parallel, while waiting on the
         # layout channel.  This allows other layouts to cancel us, and the
         # layout tasks to trigger restart by exiting (new tasks are created
         # and we continue, because we are in a loop).
         if __debug__:
             notify_layout_change(self)
         while True:
             await loop.race(layout_chan.take(), *self.create_tasks())
     except Result as result:
         # Result exception was raised, this means this layout is complete.
         value = result.value
     return value
Esempio n. 2
0
    async def handle_paging(self) -> None:
        if self.page == 0:
            directions = SWIPE_UP
        elif self.page == len(self.pages) - 1:
            directions = SWIPE_DOWN
        else:
            directions = SWIPE_VERTICAL

        if __debug__:
            swipe = await loop.race(Swipe(directions), swipe_signal())
        else:
            swipe = await Swipe(directions)

        if swipe is SWIPE_UP:
            self.page = min(self.page + 1, len(self.pages) - 1)
        elif swipe is SWIPE_DOWN:
            self.page = max(self.page - 1, 0)

        self.pages[self.page].dispatch(ui.REPAINT, 0, 0)
        self.repaint = True

        if __debug__:
            notify_layout_change(self)

        self.on_change()
Esempio n. 3
0
    def handle_rendering(self) -> loop.Task:  # type: ignore
        """Task that is rendering the layout in a busy loop."""
        # Before the first render, we dim the display.
        backlight_fade(style.BACKLIGHT_DIM)
        # Clear the screen of any leftovers, make sure everything is marked for
        # repaint (we can be running the same layout instance multiple times)
        # and paint it.
        display.clear()
        self.dispatch(REPAINT, 0, 0)
        self.dispatch(RENDER, 0, 0)

        if __debug__ and self.should_notify_layout_change:
            # notify about change and do not notify again until next await.
            # (handle_rendering might be called multiple times in a single await,
            # because of the endless loop in __iter__)
            self.should_notify_layout_change = False
            notify_layout_change(self)

        # Display is usually refreshed after every loop step, but here we are
        # rendering everything synchronously, so refresh it manually and turn
        # the brightness on again.
        refresh()
        backlight_fade(self.BACKLIGHT_LEVEL)
        sleep = self.RENDER_SLEEP
        while True:
            # Wait for a couple of ms and render the layout again.  Because
            # components use re-paint marking, they do not really draw on the
            # display needlessly.  Using `yield` instead of `await` to avoid allocations.
            # TODO: remove the busy loop
            yield sleep
            self.dispatch(RENDER, 0, 0)
Esempio n. 4
0
        async def handle_swipe(self):
            from apps.debug import notify_layout_change, swipe_signal
            from trezor.ui.components.common import (
                SWIPE_UP,
                SWIPE_DOWN,
                SWIPE_LEFT,
                SWIPE_RIGHT,
            )

            while True:
                direction = await swipe_signal()
                orig_x = orig_y = 120
                off_x, off_y = {
                    SWIPE_UP: (0, -30),
                    SWIPE_DOWN: (0, 30),
                    SWIPE_LEFT: (-30, 0),
                    SWIPE_RIGHT: (30, 0),
                }[direction]

                for event, x, y in (
                    (io.TOUCH_START, orig_x, orig_y),
                    (io.TOUCH_MOVE, orig_x + 1 * off_x, orig_y + 1 * off_y),
                    (io.TOUCH_END, orig_x + 2 * off_x, orig_y + 2 * off_y),
                ):
                    msg = self.layout.touch_event(event, x, y)
                    self.layout.paint()
                    if msg is not None:
                        raise ui.Result(msg)

                notify_layout_change(self)
Esempio n. 5
0
    def _before_render(self) -> None:
        # Clear the screen of any leftovers.
        ui.backlight_fade(ui.style.BACKLIGHT_DIM)
        ui.display.clear()

        if __debug__ and self.should_notify_layout_change:
            from apps.debug import notify_layout_change

            # notify about change and do not notify again until next await.
            # (handle_rendering might be called multiple times in a single await,
            # because of the endless loop in __iter__)
            self.should_notify_layout_change = False
            notify_layout_change(self)

        # Turn the brightness on again.
        ui.backlight_fade(self.BACKLIGHT_LEVEL)
Esempio n. 6
0
    def _before_render(self) -> None:
        # Before the first render, we dim the display.
        backlight_fade(style.BACKLIGHT_DIM)
        # Clear the screen of any leftovers, make sure everything is marked for
        # repaint (we can be running the same layout instance multiple times)
        # and paint it.
        display.clear()
        self.dispatch(REPAINT, 0, 0)
        self.dispatch(RENDER, 0, 0)

        if __debug__ and self.should_notify_layout_change:
            from apps.debug import notify_layout_change

            # notify about change and do not notify again until next await.
            # (handle_rendering might be called multiple times in a single await,
            # because of the endless loop in __iter__)
            self.should_notify_layout_change = False
            notify_layout_change(self)

        # Display is usually refreshed after every loop step, but here we are
        # rendering everything synchronously, so refresh it manually and turn
        # the brightness on again.
        refresh()
        backlight_fade(self.BACKLIGHT_LEVEL)