Home / Docs / UI Primitives

Historical engineering note, substantially superseded. This is a point-in-time design and progress document from the project archive (build 115 / v1.24.21). The "Remaining" work it lists at the end of the Phases section has since been completed and then some: the theme format shipped is not the YAML file this document specifies but a binary .mtheme format, and 14 themes ship today (classic, dark, light, high-contrast, fluent-dark/light, forest, ocean, sunset, maytera-dark/light, modern-dark/light, retro-unix), not the 3 described here. Rounded window corners, which this document defers as unfinished, are implemented across the compositor's draw path. The theme interface has also gone through a second major revision since ("mtheme v2"). Treat the architecture reasoning and phase history below as background, not as a description of what ships; see Theming and the Syscall Reference for current specifics.

Theme & Widget-Style Engine Plan

Goal: turn the UI into a style-driven system where a THEME controls the whole visual language, not just colors: window decorations, widget rendering style (beveled vs rounded vs flat), gradients, drop shadows, borders, corner radius, typography. Ship multiple built-in styles; "Classic" keeps the 1990s CDE/Motif beveled look, others are modern (gradients, shadows, rounded). Themes are defined in user-editable YAML (folds in #141), apply live with no reboot, and are downloadable. First adopter for the new controls: the Settings app.

This supersedes the earlier "replace the primitives" idea: Classic is preserved as one style; the engine adds others. It also subsumes #141 (themes in YAML).

Current state (grounded in code)

  • libc/gui.c controls are crude and hardcoded: gui_draw_button_3d = flat fill + hard 2px bevel; gui_draw_checkbox draws an "X" not a tick; no slider/radio/ toggle; colors are literals, not theme-driven; labels use the bitmap font.
  • Nice rounded/gradient/AA helpers (draw_rounded_rect, draw_gradient_v) exist only in compositor/draw.c, unavailable to apps.
  • Window decorations are drawn in the kernel (gui/window.c, decor_retro.c, decor_modern.c) with per-theme colors but a fixed beveled shape.
  • Themes today are baked into the kernel (theme_t + THEME_COLOR_*), selected in Settings, persisted in UIPROFIL.YML. Three exist: retro-unix, modern-dark, modern-light.

The model: a Theme = Colors + Style

Extend the theme definition (YAML on disk, see #141) to carry a STYLE block in addition to the color palette:

name: Classic
base_style: classic        # classic | modern | flat  (selects the renderer family)
palette:                   # existing THEME_COLOR_* keys
  taskbar_bg: 0x00C0C0C0
  ...
window:
  border_width: 2
  corner_radius: 0         # 0 = square (Classic), >0 = rounded (Modern)
  titlebar: bevel          # bevel | gradient | flat
  titlebar_gradient: [top, bottom]
  shadow: none             # none | soft   (drop shadow under windows)
  shadow_size: 0
controls:
  button: bevel            # bevel | raised-gradient | flat
  button_radius: 0
  checkbox: box-x          # box-x (classic) | rounded-tick | switch-style
  focus: dotted            # dotted (classic) | ring (modern)
  shadow: none             # control elevation shadow
fx:
  gradients: false
  shadows: false

Renderer families (base_style) shipped: classic, modern, AND flat (minimal borders, no bevel/gradient, clean "metro" look).

Built-in themes shipped initially (a theme pairs a base_style with a palette):

  • Classic (CDE/Motif, base_style=classic): bevel everything, square corners, dotted focus, no gradients/shadows. The current look, refined (centered text, real tick).
  • Modern Dark / Modern Light (base_style=modern): rounded corners, raised gradient buttons, accent fills, focus rings, soft window drop shadows and control elevation.
  • Nord and Ocean (KEEP these existing palettes): retained as themes; pair them with base_style=modern (or flat) so they get the modern dressing.
  • A Flat theme (base_style=flat) to showcase the third renderer.

DECISIONS (from user):

  • Ship all THREE renderer families (classic + modern + flat) in the first cut.
  • Do NOT remove the Nord / Ocean color sets; keep them as themes.
  • The OS is NOT limited to 5 themes; any number of YAML themes are supported.
  • Settings theme selection MUST be a DROPDOWN list (scrollable), not a row of buttons, so it scales to many themes.
  • Full shadows: soft drop shadows under WINDOWS and elevation shadows on CONTROLS (for modern style), plus rounded window corners. (More themes can be added purely by dropping a YAML file in /THEMES.)

Architecture

A. Style descriptor (single source of truth)

  • A ui_style_t struct (base_style enum + the window/controls/fx params above), loaded from the active theme YAML. Lives where both apps and the kernel can get it: apps read it via libc (a syscall returns the active theme+style, like the current theme_color), the kernel reads it directly for decorations.

B. Style-aware primitive renderers in libc

  • Each primitive (button, checkbox, radio, toggle, slider, textfield, progress, scrollbar, card/section) branches on style.base and reads its params:
  • classic -> beveled renderer (refined current look)
  • modern -> rounded + gradient + optional shadow renderer
  • flat -> minimal borders, no bevel/gradient
  • Shared foundation added to libc first: gui_fill_rounded, gui_gradient_v, gui_soft_shadow (alpha-blended), gui_text_ttf_centered, semantic theme accessors, and a design-tokens header.
  • Even Classic benefits from the correctness fixes (truly centered TTF labels, real checkmark) while keeping bevels.

C. Style-aware window decorations (kernel)

  • gui/window.c + decor_*.c read ui_style_t.window: border width, corner radius, titlebar bevel/gradient/flat, and drop shadow.
  • Drop shadow: draw a soft alpha shadow under the window rect before the window (z-order). This needs the window/compositor draw path to render a shadow band around each window; gate it on window.shadow == soft so Classic pays nothing.
  • Rounded window corners: corner masking in the decoration + content clip.

D. Themes in YAML (folds in #141)

  • Theme files at /THEMES/*.YML (8.3 names). Parser builds theme_t + ui_style_t.
  • Export the 3 current themes to YAML byte-for-byte (Classic = retro-unix).
  • Compiled-in fallback theme if /THEMES is missing/corrupt.
  • Settings Themes panel: a scrollable DROPDOWN listing every /THEMES/*.YML (not buttons), applies live (reuse the existing live-apply path), persists the choice by name in UIPROFIL.YML. Optional live preview swatch.
  • Live apply must refresh decorations + all app windows with no reboot.

Phases

STATUS: Phases 0-2 DONE (build 104 / v1.24.11). Engine in libc + Settings adopts it + theme dropdown; modern style verified in a test virtual machine. Phase 4a DONE (build 107 / v1.24.14): kernel window decorations are style-aware - modern themes get a gradient titlebar, Classic keeps the flat bevel (win_modern_style() in gui/window.c). Phase 4b (window DROP SHADOWS + ROUNDED CORNERS) DEFERRED to the compositor: kernel window_invalidate() redraws a single window with no background clear, so per-frame alpha shadows would accumulate/trail. The correct home is the userland compositor (full desktop redraw each frame + SYS_WM_GET_WINDOWS to enumerate window bounds and draw a soft shadow under each before the kernel paints the window). Phase 4b DONE (build 115 / v1.24.21): the compositor draws soft drop shadows under app windows (windows_render_shadows() in main.c, gated on modern themes via g_compositor_theme_id != 4; uses wm_get_windows + g_draw_blend; classic + screensaver unaffected). ROUNDED WINDOW CORNERS still deferred (kernel corner masking + compositor notch). Remaining: 3 (YAML loader), rounded corners, 5 (roll out to other apps - Files done), 6 (docs).

  1. libc drawing foundation: rounded/gradient/shadow/TTF-centered + tokens + ui_style_t plumbing (syscall to fetch active theme+style).
  2. Style-aware primitives in libc (classic + modern renderers for each control).
  3. Settings app adopts the new primitives (the test bed); verify on Classic and Modern, light and dark; before/after screenshots.
  4. YAML theme+style loader; export 3 themes to YAML (Classic=CDE); Settings enumerates + live-applies; persistence.
  5. Style-aware window decorations in the kernel (border/radius/titlebar/shadow); implement window drop shadows + rounded corners for Modern.
  6. Roll the primitives out to remaining apps (calc/files/mediaplayer/etc.).
  7. Docs: update docs/UI_STYLE_GUIDE.md to document the style engine + each style.

Sequencing / dependency

  • GATED behind the kernel FAT-corruption fix (#150): no userland/kernel deploy cycles until the filesystem is hardened and a stress test shows it stays clean.
  • Then 0 -> 1 -> 2 (Settings, review with user) -> 3 -> 4 -> 5 -> 6.

Risks

  • Window drop shadows + rounded corners touch the kernel window/compositor draw path and z-order; the most complex piece. Gate strictly so Classic is unaffected.
  • Live re-theming must refresh kernel decorations AND running apps; the existing live-apply path covers colors, needs extending to style params.
  • TTF in tight controls can hit narrow-glyph issues ('l','7'); use existing fixes, fall back to bitmap for very small controls.
  • YAML parser must be robust (the FAT corruption showed how fragile on-disk state is); always keep a compiled fallback.