.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.ccontrols are crude and hardcoded:gui_draw_button_3d= flat fill + hard 2px bevel;gui_draw_checkboxdraws 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 incompositor/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 inUIPROFIL.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_tstruct (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 currenttheme_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.baseand 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_*.creadui_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 == softso 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 buildstheme_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 inUIPROFIL.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).
- libc drawing foundation: rounded/gradient/shadow/TTF-centered + tokens +
ui_style_tplumbing (syscall to fetch active theme+style). - Style-aware primitives in libc (classic + modern renderers for each control).
- Settings app adopts the new primitives (the test bed); verify on Classic and Modern, light and dark; before/after screenshots.
- YAML theme+style loader; export 3 themes to YAML (Classic=CDE); Settings enumerates + live-applies; persistence.
- Style-aware window decorations in the kernel (border/radius/titlebar/shadow); implement window drop shadows + rounded corners for Modern.
- Roll the primitives out to remaining apps (calc/files/mediaplayer/etc.).
- Docs: update
docs/UI_STYLE_GUIDE.mdto 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.