Skip to content

Commit 0f3a88f

Browse files
Implement a real screen stack in NBGL layout layer
1 parent 8e79b2a commit 0f3a88f

File tree

2 files changed

+83
-71
lines changed

2 files changed

+83
-71
lines changed

lib_nbgl/src/nbgl_layout.c

Lines changed: 74 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ typedef struct {
132132
*/
133133
static nbgl_layoutInternal_t gLayout[NB_MAX_LAYOUTS] = {0};
134134

135+
// current top of stack
136+
static nbgl_layoutInternal_t *topLayout;
137+
135138
// numbers of touchable controls for the whole page
136139
static uint8_t nbTouchableControls = 0;
137140

@@ -167,28 +170,23 @@ static bool getLayoutAndLayoutObj(nbgl_obj_t *obj,
167170
nbgl_layoutInternal_t **layout,
168171
layoutObj_t **layoutObj)
169172
{
170-
uint8_t i = NB_MAX_LAYOUTS;
171-
172-
// parse all layouts (starting with modals) to find the object
173+
// only try to find the object on top layout on the stack (the other cannot receive touch
174+
// events)
173175
*layout = NULL;
174-
while (i > 0) {
175-
i--;
176-
if (gLayout[i].nbChildren > 0) {
177-
uint8_t j;
178-
179-
// search index of obj in this layout
180-
for (j = 0; j < gLayout[i].nbUsedCallbackObjs; j++) {
181-
if (obj == gLayout[i].callbackObjPool[j].obj) {
182-
LOG_DEBUG(LAYOUT_LOGGER,
183-
"getLayoutAndLayoutObj(): obj found in layout[%d], index = %d, "
184-
"nbUsedCallbackObjs = %d\n",
185-
i,
186-
j,
187-
gLayout[i].nbUsedCallbackObjs);
188-
*layout = &gLayout[i];
189-
*layoutObj = &(gLayout[i].callbackObjPool[j]);
190-
return true;
191-
}
176+
if ((topLayout) && (topLayout->isUsed)) {
177+
uint8_t j;
178+
179+
// search index of obj in this layout
180+
for (j = 0; j < topLayout->nbUsedCallbackObjs; j++) {
181+
if (obj == topLayout->callbackObjPool[j].obj) {
182+
LOG_DEBUG(LAYOUT_LOGGER,
183+
"getLayoutAndLayoutObj(): obj found in layout %p "
184+
"nbUsedCallbackObjs = %d\n",
185+
topLayout,
186+
topLayout->nbUsedCallbackObjs);
187+
*layout = topLayout;
188+
*layoutObj = &(topLayout->callbackObjPool[j]);
189+
return true;
192190
}
193191
}
194192
}
@@ -327,11 +325,7 @@ static void longTouchCallback(nbgl_obj_t *obj,
327325
// 4th child of container is the progress bar
328326
nbgl_progress_bar_t *progressBar = (nbgl_progress_bar_t *) container->children[3];
329327

330-
LOG_DEBUG(LAYOUT_LOGGER,
331-
"longTouchCallback(): eventType = %d, obj = %p, gLayout[1].nbChildren = %d\n",
332-
eventType,
333-
obj,
334-
gLayout[1].nbChildren);
328+
LOG_DEBUG(LAYOUT_LOGGER, "longTouchCallback(): eventType = %d, obj = %p\n", eventType, obj);
335329

336330
// case of pressing a long press button
337331
if (eventType == TOUCHING) {
@@ -451,22 +445,17 @@ static void radioTouchCallback(nbgl_obj_t *obj,
451445
// callback for spinner ticker
452446
static void spinnerTickerCallback(void)
453447
{
454-
nbgl_spinner_t *spinner;
455-
uint8_t i = 0;
456-
nbgl_layoutInternal_t *layout;
448+
nbgl_spinner_t *spinner;
449+
uint8_t i = 0;
457450

458-
// gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event
459-
if (gLayout[1].nbChildren > 0) {
460-
layout = &gLayout[1];
461-
}
462-
else {
463-
layout = &gLayout[0];
451+
if (!topLayout || !topLayout->isUsed) {
452+
return;
464453
}
465454

466455
// get index of obj
467-
while (i < layout->container->nbChildren) {
468-
if (layout->container->children[i]->type == CONTAINER) {
469-
nbgl_container_t *container = (nbgl_container_t *) layout->container->children[i];
456+
while (i < topLayout->container->nbChildren) {
457+
if (topLayout->container->children[i]->type == CONTAINER) {
458+
nbgl_container_t *container = (nbgl_container_t *) topLayout->container->children[i];
470459
if (container->nbChildren && (container->children[0]->type == SPINNER)) {
471460
spinner = (nbgl_spinner_t *) container->children[0];
472461
spinner->position++;
@@ -487,18 +476,10 @@ static void spinnerTickerCallback(void)
487476
static void animTickerCallback(void)
488477
{
489478
nbgl_image_t *image;
490-
uint8_t i = 0;
491-
nbgl_layoutInternal_t *layout;
479+
uint8_t i = 0;
480+
nbgl_layoutInternal_t *layout = topLayout;
492481

493-
// gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event
494-
if (gLayout[1].nbChildren > 0) {
495-
layout = &gLayout[1];
496-
}
497-
else {
498-
layout = &gLayout[0];
499-
}
500-
501-
if (layout->animation == NULL) {
482+
if (!layout || !layout->isUsed || (layout->animation == NULL)) {
502483
return;
503484
}
504485

@@ -1101,27 +1082,48 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
11011082
{
11021083
nbgl_layoutInternal_t *layout = NULL;
11031084

1104-
// find an empty layout in the proper "layer"
11051085
if (description->modal) {
1106-
if (gLayout[1].nbChildren == 0) {
1107-
layout = &gLayout[1];
1108-
}
1109-
else if (gLayout[2].nbChildren == 0) {
1110-
layout = &gLayout[2];
1086+
int i;
1087+
// find an empty layout in the array of layouts (0 is reserved for background)
1088+
for (i = 1; i < NB_MAX_LAYOUTS; i++) {
1089+
if (!gLayout[i].isUsed) {
1090+
layout = &gLayout[i];
1091+
}
11111092
}
11121093
}
11131094
else {
1114-
// automatically "release" a potentially opened non-modal layout
1115-
gLayout[0].nbChildren = 0;
1116-
layout = &gLayout[0];
1095+
// always use layout 0 for background
1096+
layout = &gLayout[0];
1097+
if (topLayout == NULL) {
1098+
topLayout = layout;
1099+
}
11171100
}
11181101
if (layout == NULL) {
11191102
LOG_WARN(LAYOUT_LOGGER, "nbgl_layoutGet(): impossible to get a layout!\n");
11201103
return NULL;
11211104
}
11221105

11231106
// reset globals
1107+
nbgl_layoutInternal_t *backgroundTop = gLayout[0].top;
11241108
memset(layout, 0, sizeof(nbgl_layoutInternal_t));
1109+
// link layout to other ones
1110+
if (description->modal) {
1111+
if (topLayout != NULL) {
1112+
// if topLayout already existing, push this new one on top of it
1113+
topLayout->top = layout;
1114+
layout->bottom = topLayout;
1115+
}
1116+
else {
1117+
// otherwise put it on top of background layout
1118+
layout->bottom = &gLayout[0];
1119+
gLayout[0].top = layout;
1120+
}
1121+
topLayout = layout;
1122+
}
1123+
else {
1124+
// restore potentially valid background top layer
1125+
gLayout[0].top = backgroundTop;
1126+
}
11251127

11261128
nbTouchableControls = 0;
11271129

@@ -1150,7 +1152,7 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
11501152
layout->container->obj.alignment = TOP_LEFT;
11511153
// main container is always the second object, leaving space for header
11521154
layout->children[MAIN_CONTAINER_INDEX] = (nbgl_obj_t *) layout->container;
1153-
layout->nbChildren = NB_MAX_SCREEN_CHILDREN;
1155+
layout->isUsed = true;
11541156

11551157
// if a tap text is defined, make the container tapable and display this text in gray
11561158
if (description->tapActionText != NULL) {
@@ -3694,10 +3696,7 @@ int nbgl_layoutDraw(nbgl_layout_t *layoutParam)
36943696
if (layout == NULL) {
36953697
return -1;
36963698
}
3697-
LOG_DEBUG(LAYOUT_LOGGER,
3698-
"nbgl_layoutDraw(): container.nbChildren =%d, layout->nbChildren = %d\n",
3699-
layout->container->nbChildren,
3700-
layout->nbChildren);
3699+
LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutDraw(): layout->isUsed = %d\n", layout->isUsed);
37013700
if (layout->tapText) {
37023701
// set this new container as child of main container
37033702
layoutAddObject(layout, (nbgl_obj_t *) layout->tapText);
@@ -3722,14 +3721,24 @@ int nbgl_layoutRelease(nbgl_layout_t *layoutParam)
37223721
{
37233722
nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *) layoutParam;
37243723
LOG_DEBUG(PAGE_LOGGER, "nbgl_layoutRelease(): \n");
3725-
if (layout == NULL) {
3724+
if ((layout == NULL) || (!layout->isUsed)) {
37263725
return -1;
37273726
}
37283727
// if modal
37293728
if (layout->modal) {
37303729
nbgl_screenPop(layout->layer);
3730+
// if this layout was on top, use its bottom layout as top
3731+
if (layout == topLayout) {
3732+
topLayout = layout->bottom;
3733+
topLayout->top = NULL;
3734+
}
3735+
else {
3736+
// otherwise connect top to bottom
3737+
layout->bottom->top = layout->top;
3738+
layout->top->bottom = layout->bottom;
3739+
}
37313740
}
3732-
layout->nbChildren = 0;
3741+
layout->isUsed = false;
37333742
return 0;
37343743
}
37353744

lib_nbgl/src/nbgl_layout_internal.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,16 @@ enum {
7373
*
7474
*/
7575
typedef struct nbgl_layoutInternal_s {
76-
nbgl_obj_t **children; ///< children for main screen
76+
struct nbgl_layoutInternal_s *top; ///< layout above this one, in stack
77+
struct nbgl_layoutInternal_s *bottom; ///< layout under this one, in stack
78+
nbgl_obj_t **children; ///< children for main screen
7779
nbgl_container_t
7880
*headerContainer; ///< container used to store header (progress, back, empty space...)
7981
nbgl_container_t *footerContainer; ///< container used to store footer (buttons, nav....)
8082
nbgl_container_t *upFooterContainer; ///< container used on top on footer to store special
8183
///< contents like tip-box or long-press button
8284
nbgl_text_area_t *tapText;
83-
nbgl_layoutTouchCallback_t callback; // user callback for all controls
85+
nbgl_layoutTouchCallback_t callback; ///< user callback for all controls
8486
// This is the pool of callback objects, potentially used by this layout
8587
layoutObj_t callbackObjPool[LAYOUT_OBJ_POOL_LEN];
8688

@@ -97,10 +99,11 @@ typedef struct nbgl_layoutInternal_s {
9799
///< the screen
98100
uint8_t incrementAnim : 1; ///< if true, means that animation index is currently incrementing
99101
uint8_t layer : 5; ///< layer in screen stack
100-
uint8_t nbUsedCallbackObjs; ///< number of callback objects used by the whole layout in
101-
///< callbackObjPool
102-
uint8_t nbChildren; ///< number of children in above array
103-
uint8_t iconIdxInAnim; ///< current icon index in animation
102+
uint8_t nbUsedCallbackObjs : 6; ///< number of callback objects used by the whole layout in
103+
///< callbackObjPool
104+
uint8_t isUsed : 1; ///< if true, means this layout is in use
105+
uint8_t invertedColors : 1; ///< if true, means that background is black
106+
uint8_t iconIdxInAnim; ///< current icon index in animation
104107
nbgl_swipe_usage_t swipeUsage;
105108
} nbgl_layoutInternal_t;
106109

0 commit comments

Comments
 (0)