Glyph Widget Toolkit

Glyph is the widget toolkit for the Aegis graphical environment. It provides a retained-mode widget tree with automatic dirty-rect propagation, layout containers, and a dark-mode visual language designed to blend with Lumen’s frosted glass compositing. Glyph renders directly to surface_t pixel buffers – it has no dependency on a display server protocol, GPU driver, or rendering library beyond its own software rasterizer.

v1 note: Glyph is v1 software – functional and tested, but still evolving. Contributions are welcome – file issues or propose changes at exec/aegis.

 Glyph library architecture:
 +----------------------------------------------------------+
 |  glyph_window_t                                          |
 |  +------------------------------------------------------+|
 |  | Chrome: titlebar, traffic-light buttons, border      ||
 |  | (render_chrome in window.c)                          ||
 |  +------------------------------------------------------+|
 |  | Client area                                          ||
 |  | +--------------------------------------------------+ ||
 |  | | glyph_widget_t tree (retained mode)              | ||
 |  | |   draw_fn(), on_mouse(), on_key(), on_destroy()  | ||
 |  | |   automatic dirty propagation to window          | ||
 |  | +--------------------------------------------------+ ||
 |  +------------------------------------------------------+|
 |  | surface_t: offscreen XRGB pixel buffer               ||
 |  | dirty_rect: accumulated dirty region for compositor  ||
 +----------------------------------------------------------+
         |
         v
 +----------------------------------------------------------+
 |  draw.c: Software rasterizer primitives                  |
 |  font.c: stb_truetype TTF renderer with atlas caching    |
 |  terminus20.h: Bitmap fallback font (10x20)              |
 +----------------------------------------------------------+

Core Concepts

Surface

All drawing targets a surface_t:

typedef struct {
    uint32_t *buf;
    int w, h, pitch;  /* pitch in pixels */
} surface_t;

Pixels are 32-bit XRGB (top byte unused). pitch is in pixels, not bytes, allowing framebuffers with stride padding. All drawing primitives take a surface_t * and perform bounds checking.

Widget Base Type

Every widget embeds glyph_widget_t as its first member, enabling safe casting between base and concrete types:

struct glyph_widget {
    glyph_widget_type_t type;
    glyph_widget_t *parent;
    glyph_widget_t *children[GLYPH_MAX_CHILDREN];  /* max 32 */
    int nchildren;
    int x, y, w, h;        /* bounds relative to parent */
    int pref_w, pref_h;    /* preferred size for layout */
    int dirty;
    int visible;
    int focusable;
    int hovered;            /* set by compositor hover tracking */
    void (*draw_fn)(glyph_widget_t *self, surface_t *surf, int ox, int oy);
    void (*on_mouse)(glyph_widget_t *self, int btn, int local_x, int local_y);
    void (*on_key)(glyph_widget_t *self, char key);
    void (*on_destroy)(glyph_widget_t *self);
    glyph_window_t *window; /* owning window (set recursively) */
};

The type field is used for runtime type identification – layout containers check type == GLYPH_WIDGET_HBOX || type == GLYPH_WIDGET_VBOX to trigger auto-layout when children are added.

Widget Type Enum

typedef enum {
    GLYPH_WIDGET_LABEL,      GLYPH_WIDGET_BUTTON,
    GLYPH_WIDGET_TEXTFIELD,  GLYPH_WIDGET_CHECKBOX,
    GLYPH_WIDGET_LISTVIEW,   GLYPH_WIDGET_SCROLLBAR,
    GLYPH_WIDGET_IMAGE,      GLYPH_WIDGET_PROGRESS,
    GLYPH_WIDGET_MENUBAR,    GLYPH_WIDGET_TABS,
    GLYPH_WIDGET_HBOX,       GLYPH_WIDGET_VBOX,
    GLYPH_WIDGET_SLIDER,     GLYPH_WIDGET_RADIO,
    GLYPH_WIDGET_SEPARATOR,  GLYPH_WIDGET_TOGGLE,
} glyph_widget_type_t;

Widget Tree Operations

Tree Construction

glyph_widget_init(w, type);           /* zero + set type, visible=1, dirty=1 */
glyph_widget_add_child(parent, child); /* append child, auto-layout if box */
glyph_widget_remove_child(parent, child);
glyph_widget_set_window(root, win);   /* recursive window pointer assignment */

glyph_widget_add_child is the primary tree-building operation. When the parent is an HBox or VBox, adding a child immediately triggers glyph_box_layout to recompute positions.

Dirty Rect Propagation

When a widget is marked dirty, it computes its absolute position by walking up the parent chain and reports the dirty rectangle to the owning window:

void glyph_widget_mark_dirty(glyph_widget_t *w)
{
    w->dirty = 1;
    if (w->window) {
        /* Walk parent chain to compute absolute offset */
        int ax = 0, ay = 0;
        glyph_widget_t *p = w;
        while (p) { ax += p->x; ay += p->y; p = p->parent; }
        glyph_rect_t r = { ax, ay, w->w, w->h };
        glyph_window_mark_dirty_rect(w->window, r);
    }
}

The window accumulates dirty rects via union. During the next compositor frame, the window’s dirty rect is converted to screen coordinates and fed to the compositor’s dirty rect system.

Hit Testing

Hit testing is depth-first, reverse-order (topmost child wins):

glyph_widget_t *glyph_widget_hit_test(glyph_widget_t *root, int x, int y);

The algorithm recursively descends through the widget tree. At each level, children are tested in reverse order (highest index first) since later children are drawn on top. If no child matches, the parent widget itself is returned. Coordinates are relative to the parent’s origin at each level.

Focus Cycling

Tab key cycling walks the widget tree depth-first to find the next focusable widget:

glyph_widget_t *glyph_widget_focus_next(root, current);

If current is NULL, returns the first focusable widget. After the last focusable widget, wraps to the first.

Tree Rendering

void glyph_widget_draw_tree(root, surf, ox, oy);

Recursive pre-order traversal: draws the parent first (via draw_fn), then each child with accumulated offset. Clears each widget’s dirty flag after drawing.

Window System

glyph_window_t

struct glyph_window {
    int x, y;                  /* screen position (top-left of border) */
    int client_w, client_h;    /* client area dimensions */
    int surf_w, surf_h;        /* total surface including chrome */
    surface_t surface;          /* offscreen pixel buffer */
    char title[64];
    glyph_widget_t *root;      /* root widget for client area */
    glyph_widget_t *focused;   /* focused widget (receives keys) */
    glyph_rect_t dirty_rect;   /* accumulated dirty region */
    int has_dirty;
    int visible;
    int closeable;
    int focused_window;         /* 1 if compositor's active window */
    int frosted;                /* 1 = frosted glass compositing */
    int chromeless;             /* 1 = no titlebar/border */
    void (*on_key)(glyph_window_t *self, char key);
    void (*on_render)(glyph_window_t *self);    /* custom content render */
    void (*on_mouse_down)(glyph_window_t *self, int x, int y);
    void (*on_mouse_move)(glyph_window_t *self, int x, int y);
    void (*on_mouse_up)(glyph_window_t *self, int x, int y);
    void (*on_scroll)(glyph_window_t *self, int direction);
    void *priv;                /* opaque data (terminal state, etc.) */
    int tag;                   /* generic int (PTY master fd) */
};

Window Chrome

Chrome constants:

Constant Value Purpose
GLYPH_TITLEBAR_HEIGHT 30 Titlebar height in pixels
GLYPH_BORDER_WIDTH 1 Border width around window
GLYPH_SHADOW_OFFSET 0 No drop shadow (frosted glass replaces it)
CORNER_R 10 Rounded corner radius

Surface dimensions are computed as:

  • surf_w = client_w + 2 * BORDER_WIDTH
  • surf_h = client_h + TITLEBAR_HEIGHT + 2 * BORDER_WIDTH

Chrome rendering (render_chrome in window.c) draws:

  1. Rounded body using draw_rounded_rect for frosted windows (single key color) or per-pixel corner tests for non-frosted (two-color titlebar/client)
  2. Divider line between titlebar and client area
  3. Title text centered horizontally (TTF at 13px or bitmap fallback)
  4. Traffic-light buttons: three filled circles (red close, yellow minimize, green maximize) with 22px spacing, 7px radius

For frosted windows, the entire surface is filled with C_SHADOW (the color key). The compositor’s blur+tint shows through where this key color appears, and actual content is drawn on top.

Window Render Pipeline

void glyph_window_render(glyph_window_t *win)
{
    render_chrome(win);        /* border, titlebar, buttons */
    if (win->on_render)
        win->on_render(win);   /* custom content (terminal) */
    if (win->root)
        glyph_widget_draw_tree(win->root, &win->surface, ox, oy);
}

The custom on_render callback is called AFTER chrome but BEFORE the widget tree. This ordering allows terminal windows (which render directly, not via widgets) to draw into the client area without being overwritten by chrome.

Input Dispatch

Mouse: glyph_window_dispatch_mouse converts screen coordinates to client-area coordinates, checks close button, then hit-tests the widget tree. The hit widget receives focus (if focusable) and an on_mouse callback with local coordinates.

Keyboard: glyph_window_dispatch_key first checks for a window-level on_key handler (used by terminal windows). If absent, Tab cycles focus, and other keys are forwarded to the focused widget’s on_key.

Hover Tracking

The compositor calls glyph_window_update_hover on the focused window each frame when the mouse moves:

void glyph_window_update_hover(win, screen_x, screen_y);

This walks the widget tree with an iterative stack (max 64 depth), updating hovered flags and marking dirty any widget whose hover state changed. Buttons use this flag to switch between normal and hover background colors.

Widget Catalog

Label (label.c)

Non-interactive text display.

glyph_label_t *glyph_label_create(const char *text, uint32_t color);
void glyph_label_set_text(glyph_label_t *label, const char *text);

Labels default to transparent mode (transparent = 1) so the frosted glass background shows through. When opaque, they fill their bounds with bg_color before drawing text. Text is rendered via draw_text_ui (TTF at 14px if available, bitmap fallback otherwise). Maximum text length: 127 characters.

Button (button.c)

Clickable button with four states: Normal, Hover, Pressed, Disabled.

glyph_button_t *glyph_button_create(const char *text, void (*on_click)(glyph_widget_t *));
void glyph_button_set_state(btn, GLYPH_BTN_DISABLED);

Button rendering uses alpha-blended backgrounds rather than solid fills to maintain the frosted glass aesthetic:

State Background Alpha Text Color
Normal 0x002A3850 180 0x00E8E8F0
Hover 0x00344868 180 0x00E8E8F0
Pressed 0x00203040 180 0x00E8E8F0
Disabled 0x00282830 180 0x00606068

Hover state is driven automatically by the compositor’s glyph_window_update_hover mechanism – no explicit state management needed. The pressed state adds a 1px text offset for a sunken effect. Border highlights: top and left edges get a subtle white blend (alpha 15-20), bottom and right get a dark blend (alpha 20-30).

Preferred size: text_width + 2 * 12px horizontal, text_height + 2 * 4px vertical.

Text Field (textfield.c)

Single-line text input with cursor.

glyph_textfield_t *glyph_textfield_create(int width_chars, void (*on_change)(...));
void glyph_textfield_set_mask(tf, '*');  /* password mode */

Features:

  • Cursor rendered as a 1px vertical accent-colored line
  • Click positions the cursor at the clicked character
  • Backspace deletes before cursor with memmove
  • Enter fires on_change without insertion
  • Printable characters (32-126) inserted at cursor position
  • Password mask mode replaces visible characters
  • Maximum buffer: 255 characters

The field background uses draw_blend_rect with alpha 80 (dark glass look). Border: top/left are dark inset, bottom/right are light highlight.

Checkbox (checkbox.c)

Toggle checkbox with label.

glyph_checkbox_t *glyph_checkbox_create(const char *label, void (*on_change)(..., int checked));

The check box is 16x16 pixels. When checked, an X-shaped mark is drawn using accent color (C_ACCENT = 0x004488CC). The box background uses a subtle dark blend. The label is drawn 6px to the right of the box, vertically centered.

Progress Bar (progress.c)

Horizontal progress indicator (0-100%).

glyph_progress_t *glyph_progress_create(int width);
void glyph_progress_set_value(bar, 50);

Height is fixed at 20px. The filled portion uses draw_blend_rect with the accent color at alpha 200. The background is dark glass (alpha 60). Not focusable.

List View (listview.c)

Scrollable list with integrated scrollbar.

glyph_listview_t *glyph_listview_create(int width, int visible_rows, void (*on_select)(...));
void glyph_listview_set_items(lv, items, count);

Maximum items: GLYPH_LISTVIEW_MAX_ITEMS = 256. The selected row gets a subtle light blend (alpha 25). Keyboard navigation uses vi-style keys (j/k or n/p) since single-char input doesn’t support arrow keys. The scrollbar (16px wide) is created as a child widget and updated automatically.

The list background is filled with C_SHADOW first (to prevent blend accumulation on repeated redraws), then a dark glass blend is applied on top.

Scrollbar (scrollbar.c)

Vertical scroll bar (typically used internally by List View).

glyph_scrollbar_t *glyph_scrollbar_create(int height, void (*on_scroll)(...));
void glyph_scrollbar_set_range(sb, max_val, page_size);

The thumb height is proportional to page_size / (range + page_size), with a minimum of 20px. Clicking anywhere on the track sets the scroll position. Not focusable.

Tabs (tabs.c)

Tabbed container that shows one panel at a time.

glyph_tabs_t *glyph_tabs_create(void (*on_change)(..., int index));
void glyph_tabs_add(tabs, "Label", panel_widget);

Maximum tabs: GLYPH_TABS_MAX = 8. Inactive panel widgets have visible = 0, so the tree walker skips them. The active tab gets a lighter blend highlight. Tab header height: text_height + 8px. The tab container’s dimensions are computed as the max of total header width vs widest panel, plus header height plus tallest panel.

Horizontal menu bar with dropdown menus.

glyph_menubar_t *glyph_menubar_create(void (*on_select)(..., int menu_idx, int item_idx));
void glyph_menubar_add_menu(mb, "File", items, count);

Maximum menus: 8. Maximum items per menu: 16. Clicking a label toggles the dropdown; clicking an item fires on_select and closes the menu. Escape closes the open menu. The dropdown width is the maximum of item text widths and the label width.

Image (image.c)

Raw pixel buffer display.

glyph_image_t *glyph_image_create(uint32_t *pixels, int w, int h);

Blits the pixel buffer directly to the surface via draw_blit. Does not own the pixel data. Not focusable.

Layout Containers (box.c)

HBox and VBox arrange children horizontally or vertically.

glyph_box_t *glyph_hbox_create(int padding, int spacing);
glyph_box_t *glyph_vbox_create(int padding, int spacing);

Layout algorithm (glyph_box_layout):

  1. For each visible child, set w = pref_w, h = pref_h
  2. Position sequentially along the primary axis (x for HBox, y for VBox) with spacing between children
  3. Set cross-axis position to padding
  4. Track the maximum cross-axis dimension
  5. Remove trailing spacing, add final padding
  6. Set the box’s own dimensions to fit all children

Layout is triggered automatically when children are added via glyph_widget_add_child. If a child is itself a box, layout recurses.

The draw function for boxes is a no-op – box containers are invisible. Children draw themselves via the standard glyph_widget_draw_tree traversal.

Additional Widgets

The header declares additional widget types that follow the same pattern:

  • Slider (glyph_slider_t): Horizontal slider with min/max range and drag interaction
  • Radio Group (glyph_radio_t): Mutually exclusive selection from up to 12 options
  • Separator (glyph_separator_t): Visual divider line
  • Toggle Switch (glyph_toggle_t): On/off switch with label

Terminal Emulator Core (glyph_term.c)

The glyph_term module provides a window-system-agnostic PTY terminal emulator. It was extracted from Lumen’s in-process terminal.c during Phase 47b subsystem peeling so both the in-process dropdown terminal and the standalone /bin/terminal external client can share one emulator.

The primary struct is glyph_term_t, which owns the cell grid, ANSI/CSI parser state, scrollback ring, selection state, and scrollbar. Callers supply a surface_t * for rendering and own dirty-marking and presentation.

Key API:

Function Purpose
glyph_term_create(cols, rows, cell_w, cell_h, pad_x, pad_y) Allocate a terminal; returns NULL on OOM
glyph_term_feed(t, data, len) Feed PTY bytes through the escape parser into the cell grid
glyph_term_render(t, s, cx, cy, cw, ch) Render grid + cursor + selection + scrollbar into surface
glyph_pty_open_and_spawn(fail_reason_out, pid_out) Open a PTY pair and spawn /bin/stsh via sys_spawn; returns master fd (O_NONBLOCK) or -1
glyph_term_translate_key(key, out) Translate one byte (incl. synthetic 0xF1-0xF4 arrow codes) to PTY bytes; returns count (1-3)
glyph_term_copy_selection(t, buf, max) Extract selected text (strips trailing whitespace per row)

Lumen Client Library (lumen_client.c)

The lumen_client module is the AF_UNIX client for the Lumen external window protocol. External clients (citadel-dock, terminal, applications, app bundles) use this instead of hand-rolling their own socket code.

Key API:

Function Purpose
lumen_connect() Connect to /run/lumen.sock; returns fd or -errno
lumen_window_create(fd, title, w, h) Send LUMEN_OP_CREATE_WINDOW; returns lumen_window_t * with memfd-backed backbuf
lumen_panel_create(fd, w, h) Send LUMEN_OP_CREATE_PANEL; returns lumen_window_t *
lumen_window_present(win) Send LUMEN_OP_DAMAGE for the full window rect
lumen_invoke(fd, name) Send LUMEN_OP_INVOKE with the given name
lumen_wait_event(fd, ev, timeout_ms) Block until an event arrives (or timeout); fills lumen_event_t

App Bundle Scanner (apps.c)

The /apps bundle scanner provides discovery for the system application bundles at /apps/<id>/. Each bundle contains an ELF binary and an app.ini manifest (name=, exec=).

int glyph_apps_scan(glyph_app_t *out, int max);  /* sorted by display name */
int glyph_apps_find(const char *id, glyph_app_t *out);

Bundles whose ELF is missing are silently skipped (e.g., gui-installer after vigil removes it on first installed boot). /apps is in the kernel’s trusted-path anchor, so bundles may carry capability policy files in /etc/aegis/caps.d/. Per-user app directories are deliberately not scanned.

Shared App Icons (icons.c)

glyph_icon_draw renders a procedural icon for a given app id at any integer size:

void glyph_icon_draw(surface_t *s, const char *id, const char *label,
                     int x, int y, int size);

Known ids with dedicated icons: "applications", "settings", "filemanager" (alias "files"), "terminal", "calculator", "editor", "widgets", "gui-installer". Unknown ids get a letter-tile fallback (rounded rect in a color hashed from id, first letter of label centered). The dock uses size 48; the Applications launcher uses size 72.

Drawing Primitives (draw.c)

The software rasterizer provides all rendering operations. No hardware acceleration is used.

Primitive Functions

Function Description
draw_px Bounds-checked single pixel write
draw_fill_rect Clamped filled rectangle
draw_rect Outlined rectangle (4 edges)
draw_gradient_v Vertical linear gradient
draw_line Bresenham line
draw_circle Midpoint circle (outline)
draw_circle_filled Filled circle via horizontal spans
draw_rounded_rect Filled rounded rectangle (Bresenham quarter-circles + rect fills)
draw_blit Opaque pixel copy with clamp
draw_blit_scaled Nearest-neighbor scaling with 16.16 fixed-point stepping
draw_blit_keyed Color-keyed blit (skip pixels matching key color)
draw_blend_rect Alpha-blended filled rectangle
draw_blend_rounded_rect Alpha-blended rounded rectangle (no double-blend)
draw_box_blur Two-pass (H+V) box blur with running sum
draw_text Bitmap font text with background
draw_text_t Bitmap font text, transparent background
draw_text_center Centered bitmap text in a given width
draw_text_ui TTF text with bitmap fallback

Box Blur Implementation

The draw_box_blur function implements a separable two-pass box blur:

Pass 1 (horizontal): For each row, maintain a running sum over a window
  of (2*radius+1) pixels. Slide the window across, dividing by span.
  Edge pixels are clamped (replicated).

Pass 2 (vertical): Same algorithm applied to each column.

A static scratch buffer (uint16_t *tmp) is retained between calls to avoid per-frame allocation. This is important since draw_box_blur is called for every frosted element: top bar, dock, each frosted window, and the context menu.

Alpha Blending

draw_blend_rect performs per-pixel alpha compositing:

uint32_t or_ = (cr * alpha + pr * inv_alpha) / 255;

The draw_blend_rounded_rect function carefully avoids double-blending by decomposing the rounded rectangle into three non-overlapping rectangular strips plus four quarter-circle corner regions, each blended exactly once.

Font Rendering (font.c)

Glyph supports TTF vector fonts via stb_truetype, with automatic bitmap fallback.

Architecture

 Font rendering pipeline:
 +---------------------------+
 | TTF file on disk          |
 | /usr/share/fonts/*.ttf    |
 +---------------------------+
          |  font_load()
          v
 +---------------------------+
 | font_t                    |
 |   stbtt_fontinfo          |
 |   raw TTF data            |
 +---------------------------+
          |  font_bake(size_px)
          v
 +---------------------------+
 | baked_size_t              |
 |   512x512 alpha atlas     |
 |   stbtt_bakedchar[95]     |
 |   ascent, descent, height |
 +---------------------------+
          |  font_draw_char()
          v
 +---------------------------+
 | Alpha-blended glyph blit  |
 | per-pixel: fg*alpha +     |
 |            bg*(255-alpha) |
 +---------------------------+

Font Loading and Baking

void font_init(void);  /* loads Inter + JetBrains Mono */

font_init attempts to load two fonts:

  • Inter (/usr/share/fonts/Inter-Regular.ttf) – UI font, pre-baked at sizes 11, 12, 13, 14, 16, 20
  • JetBrains Mono (/usr/share/fonts/JetBrainsMono-Regular.ttf) – terminal font, pre-baked at sizes 14, 16, 18, 20

Each baked size produces a 512x512 grayscale alpha atlas covering ASCII 32-126 (95 characters). Maximum 16 baked sizes per font (MAX_BAKED_SIZES = 16). If a caller requests a size that was not pre-baked, find_or_bake bakes it on first use — this is the “font auto-bake” feature (added post-1.1.1) that fixed invisible text in apps rendering at non-pre-baked sizes. Partial baking is tolerated (some characters may render as empty space).

TTF-Aware Measurement

int glyph_text_width(const char *text);  /* uses g_font_ui at 14px */
int glyph_text_height(void);             /* line height at 14px */
int glyph_char_width(void);              /* width of "M" at 14px */

These helpers are used by all widget sizing code. If the TTF font is not available, they fall back to the bitmap font constants (FONT_W = 10, FONT_H = 20).

Bitmap Font Fallback

The Terminus 10x20 bitmap font (terminus20.h) provides a complete ASCII glyph set as a compiled-in byte array. Each character is 20 rows of 16-bit bitmaps (10 significant bits per row). This is the guaranteed-available renderer when TTF fonts are missing.

Color Palette

Glyph uses a dark-mode palette with a blue tinge, defined in draw.h:

Constant Value Usage
C_BG1 0x001B2838 Desktop background
C_BG2 0x000D1B2A Darker background variant
C_WIN 0x00E8E8F0 Primary text on dark backgrounds
C_WIN_BG 0x00222838 Widget surface / card background
C_TEXT 0x00E0E0E8 General text color
C_ACCENT 0x004488CC Accent blue (buttons, selections)
C_SUBTLE 0x00808898 Deemphasized text
C_SHADOW 0x00080810 Color key for frosted transparency
C_TERM_FG 0x00E0E0E0 Terminal foreground
C_TERM_BG 0x000A0A14 Terminal background / frosted key
C_INPUT_BG 0x001A2030 Text field / list background
C_INPUT_BD 0x00404860 Text field / list border
C_SEL_BG 0x00305880 Selection / hover highlight
C_RED 0x00FF5F57 Close button, errors
C_GREEN 0x0028C840 Maximize button, success
C_YELLOW 0x00FEBC2E Minimize button, warnings

Build

Glyph compiles to a static library:

SRCS = draw.c widget.c window.c box.c label.c button.c textfield.c \
       checkbox.c progress.c image.c scrollbar.c listview.c menubar.c \
       tabs.c font.c lumen_client.c glyph_term.c apps.c icons.c \
       image_load.c

libglyph.a: $(OBJS)
    ar rcs $@ $(OBJS)

Compiled with musl-gcc (-O2 -fno-pie -no-pie -Wall). The library is linked by Lumen (compositor), Bastion (display manager), citadel-dock, /bin/terminal, /bin/applications, and all /apps/* bundle binaries.

Source Files

File Purpose
glyph.h Public API: all widget types, window, geometry
draw.h Drawing primitive declarations, color palette
draw.c Software rasterizer: rects, circles, blur, blend, text
font.h TTF font API declarations
font.c stb_truetype integration, atlas baking (find_or_bake), glyph rendering
widget.c Base widget tree operations: add, remove, dirty, hit test, focus
window.c Window: chrome rendering, dirty tracking, input dispatch
box.c HBox/VBox layout containers
label.c Static text label
button.c Clickable button with states
textfield.c Single-line text input
checkbox.c Toggle checkbox
progress.c Progress bar
scrollbar.c Vertical scrollbar
listview.c Scrollable list view
menubar.c Menu bar with dropdowns
tabs.c Tabbed container
image.c Raw pixel buffer display
image_load.c PNG/JPEG image loading via stb_image
lumen_client.c AF_UNIX client library: lumen_connect, lumen_window_create, lumen_panel_create, lumen_invoke, lumen_wait_event
lumen_client.h Lumen client API + lumen_window_t type
lumen_proto.h Wire protocol structs (shared by client and server)
glyph_term.c Terminal emulator core: cell grid, ANSI/CSI parser, 500-line scrollback, selection, scrollbar, PTY spawn helper
glyph_term.h Terminal emulator API (glyph_term_t, glyph_term_feed, glyph_pty_open_and_spawn, etc.)
apps.c /apps bundle scanner: glyph_apps_scan, glyph_apps_find
apps.h Apps scanner API + glyph_app_t struct
icons.c Shared procedural app icons: glyph_icon_draw (size-parameterized, letter-tile fallback)
icons.h Icon API
terminus20.h Compiled-in Terminus 10x20 bitmap font data
stb_truetype.h Third-party TTF parser/rasterizer (header-only)
stb_image.h Third-party PNG/JPEG decoder (header-only)