Embedded SDK
Embedded SDK
Screens Stack and dynamic objects management

Introduction

This chapter describes briefly how NBGL manages the screens stack and the dynamically allocated objects

Screens stack management

All windows are full screens, some of them are considered as modals when they are displayed on top of existing ones, catching all user events (on Touchscreen), and giving back the display (and the focus) once they are dismissed.

Let's take the simple example of pin-validation window, which is displayed automatically after a period of inactivity, when the wallet is locked:

Pin-validation window doesn't want to take care of the current screen, and to restore it afterwards.

That's why it is created in a separate layer, called screen.

Screens* are organized in a stack. The top of the stack is recovering the previous screen, which is recovering the previous one, and so on.

Even if its size is static, the screens stack is considered as empty at start-up. Then most of windows (and even all of them for applications) are simply created in the background layer of the stack (index 0), by using nbgl_screenSet() function.

When a modal window needs to be displayed, a new screen is pushed on the stack and graphical objects are attached to this new screen as its children (nbgl_screenPush() function)

Then, once this modal window is dismissed, it calls nbgl_screenPop() function to remove it from the stack (even if it is not top of stack anymore), and adapt top of stack if necessary.

After any of these operations, nbgl_screenRedraw() needs to be called to actually draw the objects on Display.

Dynamic objects management

In order to save RAM by not statically allocating memory for all graphic objects of the UX, a dynamic objects allocator has been developed.

On the contrary of a regular dynamic memory allocator like malloc(), objects allocated for a given layer (= screen) are released all at once, usually when the screen is removed (or when a new one is build in replacement of it).

Actually, there are two different allocators:

  • One for graphic objects (all derived from nbgl_obj_t)
  • One for containers of object pointers, used for screen/container/panel children.

The containers of object pointers are arrays of pointers on nbgl_obj_t.

Because these two types of dynamic data are released by layer (= screen), the layer index is passed in all allocation/release API.

API

The API to get a single graphic object of the given type from pool, for the given layer is

The API to release all objects for a given layer is:

The API to get an array of nbObjs object pointers, for the given layer:

The API to release all objects pointers for a given layer is:

Note
layer can be either 0 for the background (when using nbgl_screenSet()) or the return value of nbgl_screenPush()

Automatic allocation and release

The container for children of a screen are automatically allocated by nbgl_screenSet() or nbgl_screenPush(). It is also automatically release by the next call to nbgl_screenSet() (before new allocation) or by nbgl_screenPop().

In the same spirit, all objects allocated for a given screen by the caller are released by the next call to nbgl_screenSet() or by nbgl_screenPop().