@@ -132,6 +132,9 @@ typedef struct {
132
132
*/
133
133
static nbgl_layoutInternal_t gLayout [NB_MAX_LAYOUTS ] = {0 };
134
134
135
+ // current top of stack
136
+ static nbgl_layoutInternal_t * topLayout ;
137
+
135
138
// numbers of touchable controls for the whole page
136
139
static uint8_t nbTouchableControls = 0 ;
137
140
@@ -167,28 +170,23 @@ static bool getLayoutAndLayoutObj(nbgl_obj_t *obj,
167
170
nbgl_layoutInternal_t * * layout ,
168
171
layoutObj_t * * layoutObj )
169
172
{
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)
173
175
* 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;
192
190
}
193
191
}
194
192
}
@@ -327,11 +325,7 @@ static void longTouchCallback(nbgl_obj_t *obj,
327
325
// 4th child of container is the progress bar
328
326
nbgl_progress_bar_t * progressBar = (nbgl_progress_bar_t * ) container -> children [3 ];
329
327
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 );
335
329
336
330
// case of pressing a long press button
337
331
if (eventType == TOUCHING ) {
@@ -451,22 +445,17 @@ static void radioTouchCallback(nbgl_obj_t *obj,
451
445
// callback for spinner ticker
452
446
static void spinnerTickerCallback (void )
453
447
{
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 ;
457
450
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 ;
464
453
}
465
454
466
455
// 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 ];
470
459
if (container -> nbChildren && (container -> children [0 ]-> type == SPINNER )) {
471
460
spinner = (nbgl_spinner_t * ) container -> children [0 ];
472
461
spinner -> position ++ ;
@@ -487,18 +476,10 @@ static void spinnerTickerCallback(void)
487
476
static void animTickerCallback (void )
488
477
{
489
478
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 ;
492
481
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 )) {
502
483
return ;
503
484
}
504
485
@@ -1101,27 +1082,48 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
1101
1082
{
1102
1083
nbgl_layoutInternal_t * layout = NULL ;
1103
1084
1104
- // find an empty layout in the proper "layer"
1105
1085
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
+ }
1111
1092
}
1112
1093
}
1113
1094
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
+ }
1117
1100
}
1118
1101
if (layout == NULL ) {
1119
1102
LOG_WARN (LAYOUT_LOGGER , "nbgl_layoutGet(): impossible to get a layout!\n" );
1120
1103
return NULL ;
1121
1104
}
1122
1105
1123
1106
// reset globals
1107
+ nbgl_layoutInternal_t * backgroundTop = gLayout [0 ].top ;
1124
1108
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
+ }
1125
1127
1126
1128
nbTouchableControls = 0 ;
1127
1129
@@ -1150,7 +1152,7 @@ nbgl_layout_t *nbgl_layoutGet(const nbgl_layoutDescription_t *description)
1150
1152
layout -> container -> obj .alignment = TOP_LEFT ;
1151
1153
// main container is always the second object, leaving space for header
1152
1154
layout -> children [MAIN_CONTAINER_INDEX ] = (nbgl_obj_t * ) layout -> container ;
1153
- layout -> nbChildren = NB_MAX_SCREEN_CHILDREN ;
1155
+ layout -> isUsed = true ;
1154
1156
1155
1157
// if a tap text is defined, make the container tapable and display this text in gray
1156
1158
if (description -> tapActionText != NULL ) {
@@ -3694,10 +3696,7 @@ int nbgl_layoutDraw(nbgl_layout_t *layoutParam)
3694
3696
if (layout == NULL ) {
3695
3697
return -1 ;
3696
3698
}
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 );
3701
3700
if (layout -> tapText ) {
3702
3701
// set this new container as child of main container
3703
3702
layoutAddObject (layout , (nbgl_obj_t * ) layout -> tapText );
@@ -3722,14 +3721,24 @@ int nbgl_layoutRelease(nbgl_layout_t *layoutParam)
3722
3721
{
3723
3722
nbgl_layoutInternal_t * layout = (nbgl_layoutInternal_t * ) layoutParam ;
3724
3723
LOG_DEBUG (PAGE_LOGGER , "nbgl_layoutRelease(): \n" );
3725
- if (layout == NULL ) {
3724
+ if (( layout == NULL ) || (! layout -> isUsed ) ) {
3726
3725
return -1 ;
3727
3726
}
3728
3727
// if modal
3729
3728
if (layout -> modal ) {
3730
3729
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
+ }
3731
3740
}
3732
- layout -> nbChildren = 0 ;
3741
+ layout -> isUsed = false ;
3733
3742
return 0 ;
3734
3743
}
3735
3744
0 commit comments