gui: don't redraw newly active items unless the activity is already displayed
What changed, and why it matters
This is a minor user-interface cleanup in the Blockstream Jade hardware wallet's screen-drawing code. It prevents the device from trying to redraw menu items before the screen layout has been fully calculated, which avoids harmless warnings, possible flicker, and wasted processor cycles. There is no indication this change fixes a security vulnerability or allows any attack.
No security action required. Treat as a normal UI/robustness improvement. If auditing, verify that skipping repaint before first layout does not leave any node in an inconsistent visual state, but the commit message explicitly states this is at worst a no-op/flicker issue.
Security signals we found
No security framing in commit title or message
Change is defensive UI optimization, not input validation, memory safety, or cryptographic fix
No references to vulnerabilities, CVEs, researchers, or security reports
No buffer bounds, pointer dereference, or cryptographic changes in diff
Evidence from the diff
The commit modifies main/gui.c to skip gui_repaint() calls when render_data.is_first_time is true, meaning the GUI node/activity has not yet been laid out and displayed. Two call sites are guarded: gui_set_active() and gui_activity_set_active_selection(). The change is framed by the commit message as a robustness/efficiency improvement, not a security fix. A third hunk is a typo fix in a comment (‘dislay’ -> ‘display’).
Changed components
main/gui.cgui_set_active()gui_activity_set_active_selection()repaint_node() comment onlyInspect captured patch +8 / −4
diff --git a/main/gui.c b/main/gui.c
index 6276172..cf55644 100644
--- a/main/gui.c
+++ b/main/gui.c
@@ -346,7 +346,9 @@ void gui_set_active(gui_view_node_t* node, const bool value)
// Set passed node to active/inactive and redraw
set_tree_active(node, value);
- gui_repaint(node);
+ if (!node->render_data.is_first_time) {
+ gui_repaint(node); // Repaint since screen is "live"
+ }
}
static gui_view_node_t* get_first_active_node(gui_activity_t* activity)
@@ -573,8 +575,10 @@ void gui_activity_set_active_selection(gui_activity_t* activity, gui_view_node_t
// 'selected' should have been seen in 'nodes'
JADE_ASSERT(set_selected);
- // May as well repaint the whole activity
- gui_repaint(activity->root_node);
+ if (activity->root_node && !activity->root_node->render_data.is_first_time) {
+ // Screen is "live": repaint the whole activity
+ gui_repaint(activity->root_node);
+ }
}
// push a selectable element to the `selectables` list of `activity`
@@ -2163,7 +2167,7 @@ static void repaint_node(gui_view_node_t* node)
{
JADE_ASSERT(node);
- // Ensure we only call the underlying dislay library from the gui_task
+ // Ensure we only call the underlying display library from the gui_task
JADE_ASSERT_MSG(gui_is_gui_task(), "ERROR: repaint_node() called from non-gui-task: %s", pcTaskGetName(NULL));
// borders use the un-padded constraints
Why this scored 17/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.