ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_widget.c File Reference

Implementation of the ra8_widget composable-UI layer (#145). More...

#include "ra8_widget.h"
#include "ra8_attributes.h"
#include "ra8_check.h"
Include dependency graph for ra8_widget.c:

Go to the source code of this file.

Functions

static bool internal_rect_empty (const ra8_ui_rect_t *r)
 True if a rect covers no pixels (used as the union identity).
static int32_t internal_min_i32 (int32_t a, int32_t b)
 Smaller of two signed values.
static int32_t internal_max_i32 (int32_t a, int32_t b)
 Larger of two signed values.
static ra8_ui_rect_t internal_rect_union (ra8_ui_rect_t acc, ra8_ui_rect_t r)
 Bounding union of two rects (empty acts as the identity).
static uint16_t internal_visible_count (const ra8_widget_t *widgets, uint16_t count)
 Count the visible widgets in widgets[0..count).
static ra8_err_t internal_build_stack_tree (const ra8_widget_t *widgets, uint16_t count, ra8_widget_axis_t axis, int16_t gap, int16_t pad, ra8_box_t *scratch, uint16_t cap, ra8_box_tree_t *out_tree, int16_t *out_root)
 Build a ra8_box stack tree: one container + a leaf per visible widget.
ra8_err_t ra8_widget_layout_stack (ra8_widget_t *widgets, uint16_t count, const ra8_ui_rect_t *frame, ra8_widget_axis_t axis, int16_t gap, int16_t pad, ra8_box_t *box_scratch, uint16_t box_cap)
 Lay a stack of widgets out inside a frame (delegates to ra8_box).
ra8_err_t ra8_widget_dispatch (ra8_widget_t *widgets, uint16_t count, const ra8_widget_event_t *ev, bool *out_handled)
 Route an event to the widget that should handle it.
ra8_err_t ra8_widget_invalidate (ra8_widget_t *w, ra8_widget_refresh_t refresh)
 Mark a widget dirty with a refresh hint (folds upward in strength).
ra8_err_t ra8_widget_damage (const ra8_widget_t *widgets, uint16_t count, ra8_ui_rect_t *out_rect, ra8_widget_refresh_t *out_hint, uint16_t *out_count)
 Compute the minimal damage rectangle + refresh hint to flush.
ra8_err_t ra8_widget_render_dirty (ra8_widget_t *widgets, uint16_t count)
 Render every visible + dirty widget, clearing its damage.

Variables

static const char * s_tag = "ra8_widget"
 Logging / check tag.

Detailed Description

Implementation of the ra8_widget composable-UI layer (#145).

Implements bounded widget traversal, invalidation, event routing, and drawing over caller-owned widget and rendering state.

Definition in file ra8_widget.c.

Function Documentation

◆ internal_build_stack_tree()

ra8_err_t internal_build_stack_tree ( const ra8_widget_t * widgets,
uint16_t count,
ra8_widget_axis_t axis,
int16_t gap,
int16_t pad,
ra8_box_t * scratch,
uint16_t cap,
ra8_box_tree_t * out_tree,
int16_t * out_root )
static

Build a ra8_box stack tree: one container + a leaf per visible widget.

Sizes the scratch against the visible count, adds a stack container (row/column) then one leaf per visible widget carrying its fixed/flex. The caller then runs ra8_box_layout and copies the leaf rects back. Split out so ra8_widget_layout_stack stays within the NASA Rule 4 function-size cap.

Parameters
[in]widgetsWidget array.
[in]countNumber of widgets.
[in]axisStack main axis.
[in]gapGap between children.
[in]padInner padding.
[in]scratchCaller ra8_box scratch.
[in]capCapacity of scratch.
[out]out_treeReceives the built tree.
[out]out_rootReceives the container root index.
Returns
ra8_err_t
Return values
k_ra8_okTree built; out_root is the container.
k_ra8_err_invalid_argScratch too small or a box add failed.
<ra8_box_tree_init's>Forwarded from ra8_box_tree_init.
Precondition
out_tree / out_root non-NULL; scratch covers cap.
cap >= visible_count + 1.
Postcondition
On success out_tree holds the container + visible leaves.
On failure the caller must not use out_root.
Note
Not thread-safe; loop bounded by count (NASA Rule 2).
Since
0.1.0

Definition at line 170 of file ra8_widget.c.

References ra8_box_t::fixed, ra8_box_t::flex, ra8_box_t::gap, internal_visible_count(), k_ra8_box_leaf, k_ra8_box_none, k_ra8_box_stack_h, k_ra8_box_stack_v, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_widget_axis_row, ra8_box_t::kind, ra8_box_t::pad, ra8_box_add(), ra8_box_tree_init(), and ra8_box_t::tag.

Referenced by ra8_widget_layout_stack().

◆ internal_max_i32()

int32_t internal_max_i32 ( int32_t a,
int32_t b )
static

Larger of two signed values.

Branch-style max used by the rect-union corner math.

Parameters
[in]aFirst value.
[in]bSecond value.
Returns
The greater of a and b.
Return values
aWhen a > b.
bOtherwise.
Precondition
None.
None.
Postcondition
No state is modified.
Return is max(a, b).
Note
Pure.
Since
0.1.0

Definition at line 77 of file ra8_widget.c.

Referenced by internal_rect_union().

◆ internal_min_i32()

int32_t internal_min_i32 ( int32_t a,
int32_t b )
static

Smaller of two signed values.

Branch-style min used by the rect-union corner math.

Parameters
[in]aFirst value.
[in]bSecond value.
Returns
The lesser of a and b.
Return values
aWhen a < b.
bOtherwise.
Precondition
None.
None.
Postcondition
No state is modified.
Return is min(a, b).
Note
Pure.
Since
0.1.0

Definition at line 56 of file ra8_widget.c.

Referenced by internal_rect_union().

◆ internal_rect_empty()

bool internal_rect_empty ( const ra8_ui_rect_t * r)
static

True if a rect covers no pixels (used as the union identity).

A w <= 0 and h <= 0 rect is the empty/identity element of internal_rect_union, so the damage accumulator can start at {}.

Parameters
[in]rRect to test (non-NULL).
Returns
true if r covers no pixels, false otherwise.
Return values
trueBoth width and height are non-positive.
falseAt least one dimension is positive.
Precondition
r is non-NULL.
None.
Postcondition
No state is modified.
Return reflects emptiness only.
Note
Pure.
Since
0.1.0

Definition at line 35 of file ra8_widget.c.

References ra8_ui_rect_t::h, and ra8_ui_rect_t::w.

Referenced by internal_rect_union().

◆ internal_rect_union()

ra8_ui_rect_t internal_rect_union ( ra8_ui_rect_t acc,
ra8_ui_rect_t r )
static

Bounding union of two rects (empty acts as the identity).

Returns the smallest rect covering both inputs; an empty input returns the other unchanged, so a {} accumulator folds cleanly.

Parameters
[in]accAccumulated rect (or empty identity).
[in]rRect to fold in.
Returns
The bounding union of acc and r.
Return values
rWhen acc is empty.
accWhen r is empty.
Precondition
None.
None.
Postcondition
No input is modified (by value).
Return contains every pixel of both non-empty inputs.
Note
Pure.
Since
0.1.0

Definition at line 99 of file ra8_widget.c.

References ra8_ui_rect_t::h, internal_max_i32(), internal_min_i32(), internal_rect_empty(), ra8_ui_rect_t::w, ra8_ui_rect_t::x, and ra8_ui_rect_t::y.

Referenced by ra8_widget_damage().

◆ internal_visible_count()

uint16_t internal_visible_count ( const ra8_widget_t * widgets,
uint16_t count )
static

Count the visible widgets in widgets[0..count).

Used to size the ra8_box scratch (one leaf per visible widget plus the container) before laying a stack out.

Parameters
[in]widgetsWidget array (non-NULL when count > 0).
[in]countNumber of widgets.
Returns
The number of widgets whose visible flag is set.
Return values
0No widget is visible.
Precondition
widgets covers count entries.
None.
Postcondition
No state is modified.
Return is in [0, count].
Note
Pure; loop bounded by count (NASA Rule 2).
Since
0.1.0

Definition at line 131 of file ra8_widget.c.

Referenced by internal_build_stack_tree().

◆ ra8_widget_damage()

ra8_err_t ra8_widget_damage ( const ra8_widget_t * widgets,
uint16_t count,
ra8_ui_rect_t * out_rect,
ra8_widget_refresh_t * out_hint,
uint16_t * out_count )
nodiscard

Compute the minimal damage rectangle + refresh hint to flush.

Unions the rects of every visible AND dirty widget into one bounding rectangle and folds their refresh hints into the strongest one. This is the single display_pal flush the compositor issues: changing only the status bar yields just the status bar's rect with the fast hint; a full redraw yields the whole frame with the quality hint.

Parameters
[in]widgetsWidget array.
[in]countNumber of widgets.
[out]out_rectReceives the union rect (w == h == 0 if nothing dirty).
[out]out_hintReceives the folded refresh hint (none if clean).
[out]out_countReceives the number of dirty widgets.
Returns
ra8_err_t
Return values
k_ra8_okComputed (see out_count).
k_ra8_err_null_ptrAny output pointer, or widgets (count>0), NULL.
Precondition
All output pointers non-NULL.
Postcondition
*out_count == 0 iff nothing was dirty (then *out_rect is empty).
Note
Pure; not thread-safe vs concurrent mutation.
Since
0.1.0

Definition at line 299 of file ra8_widget.c.

References internal_rect_union(), k_ra8_err_null_ptr, k_ra8_ok, k_ra8_widget_refresh_none, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by ra8_widget_panel_compose(), wa_verify_or_halt(), and wd_check_damage().

◆ ra8_widget_dispatch()

ra8_err_t ra8_widget_dispatch ( ra8_widget_t * widgets,
uint16_t count,
const ra8_widget_event_t * ev,
bool * out_handled )
nodiscard

Route an event to the widget that should handle it.

For a touch event, finds the first visible widget whose rect contains (ev->x, ev->y) (earlier widgets win on overlap) and calls its on_input. For a button event, offers it to each visible widget in order until one consumes it. A widget with a NULL on_input never consumes.

Parameters
[in,out]widgetsWidget array.
[in]countNumber of widgets.
[in]evThe event to route.
[out]out_handledReceives true if some widget consumed the event.
Returns
ra8_err_t
Return values
k_ra8_okRouted (see out_handled).
k_ra8_err_null_ptrwidgets (with count>0), ev, or out_handled is NULL.
Precondition
ev and out_handled non-NULL.
Postcondition
On a hit *out_handled == true; otherwise false.
Note
Not thread-safe.
Since
0.1.0

Definition at line 252 of file ra8_widget.c.

References k_ra8_err_null_ptr, k_ra8_ok, k_ra8_widget_ev_touch, ra8_widget_event_t::kind, RA8_CHECK_NULL_PTR, ra8_ui_rect_contains(), s_tag, ra8_widget_event_t::x, and ra8_widget_event_t::y.

Referenced by internal_panel_on_input(), and wd_app_on_input().

◆ ra8_widget_invalidate()

ra8_err_t ra8_widget_invalidate ( ra8_widget_t * w,
ra8_widget_refresh_t refresh )
nodiscard

Mark a widget dirty with a refresh hint (folds upward in strength).

Parameters
[in,out]wWidget to invalidate.
[in]refreshk_ra8_widget_refresh_fast / _quality.
Returns
ra8_err_t
Return values
k_ra8_okMarked dirty.
k_ra8_err_null_ptrw is NULL.
k_ra8_err_invalid_argrefresh is k_ra8_widget_refresh_none.
Precondition
w non-NULL.
Postcondition
w->dirty == true; w->refresh is the stronger of old/new.
Note
Not thread-safe.
Since
0.1.0

Definition at line 286 of file ra8_widget.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_widget_refresh_none, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by er_render_keyboard(), er_render_library(), er_render_reading(), internal_bg_on_input(), internal_button_on_input(), internal_kbd_on_input(), internal_nav_on_input(), internal_panel_render(), internal_rv_link(), internal_rv_on_input(), internal_tb_on_input(), wa_app_render(), wa_verify_or_halt(), wc_check_partial(), wc_invalidate_all(), wc_tick_live(), wd_app_render(), wd_check_damage(), wd_check_partial(), wd_invalidate_all(), wd_tick_live(), wk_invalidate_all(), and wk_on_button_press().

◆ ra8_widget_layout_stack()

ra8_err_t ra8_widget_layout_stack ( ra8_widget_t * widgets,
uint16_t count,
const ra8_ui_rect_t * frame,
ra8_widget_axis_t axis,
int16_t gap,
int16_t pad,
ra8_box_t * box_scratch,
uint16_t box_cap )
nodiscard

Lay a stack of widgets out inside a frame (delegates to ra8_box).

Builds a transient ra8_box tree – one container plus a leaf per visible widget (invisible widgets are skipped, dwm-style) carrying that widget's fixed / flex – runs ra8_box_layout, then copies each visible widget's computed rect back into widget->rect. Invisible widgets keep their old rect. No allocation: the caller supplies the ra8_box scratch.

Parameters
[in,out]widgetsWidget array.
[in]countNumber of widgets.
[in]frameOuter rectangle the stack fills.
[in]axisk_ra8_widget_axis_col / _row.
[in]gapGap between children (pixels).
[in]padInner padding of the frame (pixels).
[in]box_scratchCaller ra8_box_t scratch (>= count + 1 nodes).
[in]box_capCapacity of box_scratch.
Returns
ra8_err_t
Return values
k_ra8_okLaid out; every visible widget's rect set.
k_ra8_err_null_ptrwidgets, frame, or box_scratch NULL.
k_ra8_err_invalid_argbox_cap < (visible count + 1).
Precondition
widgets covers count; frame non-NULL.
box_scratch holds at least (visible_count + 1) nodes.
Postcondition
Every visible widget reachable has its rect assigned.
Note
Not thread-safe.
Since
0.1.0

Definition at line 215 of file ra8_widget.c.

References internal_build_stack_tree(), k_ra8_box_none, k_ra8_ok, ra8_box_layout(), RA8_CHECK_NULL_PTR, ra8_box_t::rect, and s_tag.

Referenced by er_render_keyboard(), er_render_library(), er_render_reading(), internal_panel_layout(), wa_app_render(), and wd_app_render().

◆ ra8_widget_render_dirty()

ra8_err_t ra8_widget_render_dirty ( ra8_widget_t * widgets,
uint16_t count )
nodiscard

Render every visible + dirty widget, clearing its damage.

Calls each visible, dirty widget's render (skipping NULL render callbacks) and then clears its dirty flag and resets refresh to none. The selection of which widgets render is pure (host-testable with a recording mock vtable); the pixel drawing inside render is the on-target part.

Parameters
[in,out]widgetsWidget array.
[in]countNumber of widgets.
Returns
ra8_err_t
Return values
k_ra8_okRendered + cleared.
k_ra8_err_null_ptrwidgets is NULL while count > 0.
Precondition
widgets covers count.
Postcondition
Every rendered widget has dirty == false, refresh == none.
Note
Not thread-safe.
Since
0.1.0

Definition at line 331 of file ra8_widget.c.

References k_ra8_err_null_ptr, k_ra8_ok, and k_ra8_widget_refresh_none.

Referenced by er_render_current(), er_render_keyboard(), er_render_library(), er_render_nag_region(), er_render_reading(), internal_panel_render(), ra8_widget_panel_compose(), wa_app_render(), and wd_app_render().

Variable Documentation

◆ s_tag

const char* s_tag = "ra8_widget"
static

Logging / check tag.

Definition at line 17 of file ra8_widget.c.