Skip to content

Commit f7098ed

Browse files
Implement a real screen stack in NBGL layout layer
1 parent f2eac9b commit f7098ed

File tree

2 files changed

+83
-72
lines changed

2 files changed

+83
-72
lines changed

lib_nbgl/src/nbgl_layout.c

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

184+
// current top of stack
185+
static nbgl_layoutInternal_t *topLayout;
186+
184187
// numbers of touchable controls for the whole page
185188
static uint8_t nbTouchableControls = 0;
186189

@@ -216,28 +219,23 @@ static bool getLayoutAndLayoutObj(nbgl_obj_t *obj,
216219
nbgl_layoutInternal_t **layout,
217220
layoutObj_t **layoutObj)
218221
{
219-
uint8_t i = NB_MAX_LAYOUTS;
220-
221-
// parse all layouts (starting with modals) to find the object
222+
// only try to find the object on top layout on the stack (the other cannot receive touch
223+
// events)
222224
*layout = NULL;
223-
while (i > 0) {
224-
i--;
225-
if (gLayout[i].nbChildren > 0) {
226-
uint8_t j;
227-
228-
// search index of obj in this layout
229-
for (j = 0; j < gLayout[i].nbUsedCallbackObjs; j++) {
230-
if (obj == gLayout[i].callbackObjPool[j].obj) {
231-
LOG_DEBUG(LAYOUT_LOGGER,
232-
"getLayoutAndLayoutObj(): obj found in layout[%d], index = %d, "
233-
"nbUsedCallbackObjs = %d\n",
234-
i,
235-
j,
236-
gLayout[i].nbUsedCallbackObjs);
237-
*layout = &gLayout[i];
238-
*layoutObj = &(gLayout[i].callbackObjPool[j]);
239-
return true;
240-
}
225+
if ((topLayout) && (topLayout->isUsed)) {
226+
uint8_t j;
227+
228+
// search index of obj in this layout
229+
for (j = 0; j < topLayout->nbUsedCallbackObjs; j++) {
230+
if (obj == topLayout->callbackObjPool[j].obj) {
231+
LOG_DEBUG(LAYOUT_LOGGER,
232+
"getLayoutAndLayoutObj(): obj found in layout %p "
233+
"nbUsedCallbackObjs = %d\n",
234+
topLayout,
235+
topLayout->nbUsedCallbackObjs);
236+
*layout = topLayout;
237+
*layoutObj = &(topLayout->callbackObjPool[j]);
238+
return true;
241239
}
242240
}
243241
}
@@ -376,11 +374,7 @@ static void longTouchCallback(nbgl_obj_t *obj,
376374
// 4th child of container is the progress bar
377375
nbgl_progress_bar_t *progressBar = (nbgl_progress_bar_t *) container->children[3];
378376

379-
LOG_DEBUG(LAYOUT_LOGGER,
380-
"longTouchCallback(): eventType = %d, obj = %p, gLayout[1].nbChildren = %d\n",
381-
eventType,
382-
obj,
383-
gLayout[1].nbChildren);
377+
LOG_DEBUG(LAYOUT_LOGGER, "longTouchCallback(): eventType = %d, obj = %p\n", eventType, obj);
384378

385379
// case of pressing a long press button
386380
if (eventType == TOUCHING) {
@@ -505,22 +499,17 @@ static void radioTouchCallback(nbgl_obj_t *obj,
505499
// callback for spinner ticker
506500
static void spinnerTickerCallback(void)
507501
{
508-
nbgl_spinner_t *spinner;
509-
uint8_t i = 0;
510-
nbgl_layoutInternal_t *layout;
502+
nbgl_spinner_t *spinner;
503+
uint8_t i = 0;
511504

512-
// gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event
513-
if (gLayout[1].nbChildren > 0) {
514-
layout = &gLayout[1];
515-
}
516-
else {
517-
layout = &gLayout[0];
505+
if (!topLayout || !topLayout->isUsed) {
506+
return;
518507
}
519508

520509
// get index of obj
521-
while (i < layout->container->nbChildren) {
522-
if (layout->container->children[i]->type == CONTAINER) {
523-
nbgl_container_t *container = (nbgl_container_t *) layout->container->children[i];
510+
while (i < topLayout->container->nbChildren) {
511+
if (topLayout->container->children[i]->type == CONTAINER) {
512+
nbgl_container_t *container = (nbgl_container_t *) topLayout->container->children[i];
524513
if (container->nbChildren && (container->children[0]->type == SPINNER)) {
525514
spinner = (nbgl_spinner_t *) container->children[0];
526515
spinner->position++;
@@ -541,18 +530,10 @@ static void spinnerTickerCallback(void)
541530
static void animTickerCallback(void)
542531
{
543532
nbgl_image_t *image;
544-
uint8_t i = 0;
545-
nbgl_layoutInternal_t *layout;
546-
547-
// gLayout[1] is on top of gLayout[0] so if gLayout[1] is active, it must catch the event
548-
if (gLayout[1].nbChildren > 0) {
549-
layout = &gLayout[1];
550-
}
551-
else {
552-
layout = &gLayout[0];
553-
}
533+
uint8_t i = 0;
534+
nbgl_layoutInternal_t *layout = topLayout;
554535

555-
if (layout->animation == NULL) {
536+
if (!layout || !layout->isUsed || (layout->animation == NULL)) {
556537
return;
557538
}
558539

@@ -1081,27 +1062,48 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
10811062
{
10821063
nbgl_layoutInternal_t *layout = NULL;
10831064

1084-
// find an empty layout in the proper "layer"
10851065
if (description->modal) {
1086-
if (gLayout[1].nbChildren == 0) {
1087-
layout = &gLayout[1];
1088-
}
1089-
else if (gLayout[2].nbChildren == 0) {
1090-
layout = &gLayout[2];
1066+
int i;
1067+
// find an empty layout in the array of layouts (0 is reserved for background)
1068+
for (i = 1; i < NB_MAX_LAYOUTS; i++) {
1069+
if (!gLayout[i].isUsed) {
1070+
layout = &gLayout[i];
1071+
}
10911072
}
10921073
}
10931074
else {
1094-
// automatically "release" a potentially opened non-modal layout
1095-
gLayout[0].nbChildren = 0;
1096-
layout = &gLayout[0];
1075+
// always use layout 0 for background
1076+
layout = &gLayout[0];
1077+
if (topLayout == NULL) {
1078+
topLayout = layout;
1079+
}
10971080
}
10981081
if (layout == NULL) {
10991082
LOG_WARN(LAYOUT_LOGGER, "nbgl_layoutGet(): impossible to get a layout!\n");
11001083
return NULL;
11011084
}
11021085

11031086
// reset globals
1087+
nbgl_layoutInternal_t *backgroundTop = gLayout[0].top;
11041088
memset(layout, 0, sizeof(nbgl_layoutInternal_t));
1089+
// link layout to other ones
1090+
if (description->modal) {
1091+
if (topLayout != NULL) {
1092+
// if topLayout already existing, push this new one on top of it
1093+
topLayout->top = layout;
1094+
layout->bottom = topLayout;
1095+
}
1096+
else {
1097+
// otherwise put it on top of background layout
1098+
layout->bottom = &gLayout[0];
1099+
gLayout[0].top = layout;
1100+
}
1101+
topLayout = layout;
1102+
}
1103+
else {
1104+
// restore potentially valid background top layer
1105+
gLayout[0].top = backgroundTop;
1106+
}
11051107

11061108
nbTouchableControls = 0;
11071109

@@ -1130,7 +1132,7 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
11301132
layout->container->obj.alignment = TOP_LEFT;
11311133
// main container is always the second object, leaving space for header
11321134
layout->children[MAIN_CONTAINER_INDEX] = (nbgl_obj_t *) layout->container;
1133-
layout->nbChildren = NB_MAX_SCREEN_CHILDREN;
1135+
layout->isUsed = true;
11341136

11351137
// if a tap text is defined, make the container tapable and display this text in gray
11361138
if (description->tapActionText != NULL) {
@@ -3759,10 +3761,7 @@ int nbgl_layoutDraw(nbgl_layout_t *layoutParam)
37593761
if (layout == NULL) {
37603762
return -1;
37613763
}
3762-
LOG_DEBUG(LAYOUT_LOGGER,
3763-
"nbgl_layoutDraw(): container.nbChildren =%d, layout->nbChildren = %d\n",
3764-
layout->container->nbChildren,
3765-
layout->nbChildren);
3764+
LOG_DEBUG(LAYOUT_LOGGER, "nbgl_layoutDraw(): layout->isUsed = %d\n", layout->isUsed);
37663765
if (layout->tapText) {
37673766
// set this new container as child of main container
37683767
layoutAddObject(layout, (nbgl_obj_t *) layout->tapText);
@@ -3789,14 +3788,24 @@ int nbgl_layoutRelease(nbgl_layout_t *layoutParam)
37893788
{
37903789
nbgl_layoutInternal_t *layout = (nbgl_layoutInternal_t *) layoutParam;
37913790
LOG_DEBUG(PAGE_LOGGER, "nbgl_layoutRelease(): \n");
3792-
if (layout == NULL) {
3791+
if ((layout == NULL) || (!layout->isUsed)) {
37933792
return -1;
37943793
}
37953794
// if modal
37963795
if (layout->modal) {
37973796
nbgl_screenPop(layout->layer);
3797+
// if this layout was on top, use its bottom layout as top
3798+
if (layout == topLayout) {
3799+
topLayout = layout->bottom;
3800+
topLayout->top = NULL;
3801+
}
3802+
else {
3803+
// otherwise connect top to bottom
3804+
layout->bottom->top = layout->top;
3805+
layout->top->bottom = layout->bottom;
3806+
}
37983807
}
3799-
layout->nbChildren = 0;
3808+
layout->isUsed = false;
38003809
return 0;
38013810
}
38023811

lib_nbgl/src/nbgl_layout_internal.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,16 @@ enum {
7676
*
7777
*/
7878
typedef struct nbgl_layoutInternal_s {
79-
nbgl_obj_t **children; ///< children for main screen
79+
struct nbgl_layoutInternal_s *top; ///< layout above this one, in stack
80+
struct nbgl_layoutInternal_s *bottom; ///< layout under this one, in stack
81+
nbgl_obj_t **children; ///< children for main screen
8082
nbgl_container_t
8183
*headerContainer; ///< container used to store header (progress, back, empty space...)
8284
nbgl_container_t *footerContainer; ///< container used to store footer (buttons, nav....)
8385
nbgl_container_t *upFooterContainer; ///< container used on top on footer to store special
8486
///< contents like tip-box or long-press button
8587
nbgl_text_area_t *tapText;
86-
nbgl_layoutTouchCallback_t callback; // user callback for all controls
88+
nbgl_layoutTouchCallback_t callback; ///< user callback for all controls
8789
// This is the pool of callback objects, potentially used by this layout
8890
layoutObj_t callbackObjPool[LAYOUT_OBJ_POOL_LEN];
8991

@@ -100,11 +102,11 @@ typedef struct nbgl_layoutInternal_s {
100102
///< the screen
101103
uint8_t incrementAnim : 1; ///< if true, means that animation index is currently incrementing
102104
uint8_t layer : 5; ///< layer in screen stack
103-
uint8_t nbUsedCallbackObjs; ///< number of callback objects used by the whole layout in
104-
///< callbackObjPool
105-
uint8_t nbChildren; ///< number of children in above array
106-
uint8_t iconIdxInAnim; ///< current icon index in animation
107-
bool invertedColors; ///< if true, means that background is black
105+
uint8_t nbUsedCallbackObjs : 6; ///< number of callback objects used by the whole layout in
106+
///< callbackObjPool
107+
uint8_t isUsed : 1; ///< if true, means this layout is in use
108+
uint8_t invertedColors : 1; ///< if true, means that background is black
109+
uint8_t iconIdxInAnim; ///< current icon index in animation
108110
nbgl_swipe_usage_t swipeUsage;
109111
} nbgl_layoutInternal_t;
110112

0 commit comments

Comments
 (0)