NeoCDE/ARCHITECTURE.md
Till Wegmueller 65184b897d Add NeoCDE technical architecture plan
Documents the full toolkit decision (Slint + layer-shika + SCTK) for
building a modernized CDE desktop environment on the WayRay compositor.
Covers the design token pipeline (Pencil .pen → tokens.toml → theme.slint
+ wrsrvd-theme.ron), WM architecture (pure protocol client, zero GUI),
shell components (layer-shika layer-shell surfaces), and project structure
with hard designer-AI / code-AI separation boundaries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:41:21 +02:00

18 KiB

NeoCDE — Technical Architecture Plan

A modernized CDE (Common Desktop Environment) for Wayland, built on the WayRay compositor (wrsrvd) with its pluggable WM protocol.

System Architecture

┌─────────────────────────────────────┐
│  wrsrvd (WayRay Compositor)         │
│  • Rendering / encoding             │
│  • Input dispatch                   │
│  • wayray_wm_v1 protocol server     │
│  • wlr-layer-shell server           │
│  • SSD decoration rendering (5.1)   │
│  • Reads wrsrvd-theme.ron           │
└──────┬──────────┬───────────────────┘
       │          │
   WM Protocol    │  Layer-shell / xdg-shell
       │          │
┌──────▼──────┐ ┌─▼──────────────────────────┐
│ neocde-wm   │ │ NeoCDE Shell + Apps         │
│ (wm client) │ │ • Front Panel (layer-shell) │
│             │ │ • Taskbar    (layer-shell)  │
│ • Layout    │ │ • App Drawer (layer-shell)  │
│ • Focus     │ │ • File Manager (xdg-shell)  │
│ • Keybinds  │ │ • Terminal     (xdg-shell)  │
│ • Decor     │ │ • Settings     (xdg-shell)  │
│   policy    │ │ • Style Mgr    (xdg-shell)  │
└─────────────┘ └─────────────────────────────┘

Toolkit Decision: Slint + layer-shika

Primary Stack

Component Technology
Compositor wrsrvd (WayRay — Smithay-based)
WM Client Pure Rust: wayland-client + wayray-wm-protocol
Shell Components Slint + layer-shika (SCTK-based)
Desktop Apps Slint (standard xdg-shell via winit)
Design Tokens TOML → codegen → .slint + .ron
Event Loop calloop (via layer-shika)
GPU Rendering femtovg (OpenGL ES 2.0) via layer-shika

Why Slint

  1. Design/code separation: .slint markup files are a declarative DSL purpose-built for separating UI design from business logic. Designer AIs edit .slint files; code AIs edit .rs files. Hard boundary.
  2. Hot reload: slint-viewer --auto-reload for design iteration without recompilation.
  3. Runtime interpreter: slint-interpreter crate loads .slint files at runtime — AI can iterate on designs without triggering a build.
  4. Design token globals: Slint's export global Theme { ... } maps directly to our Pencil design variables.
  5. Rust-native: First-class Rust API, no C FFI or GObject complexity.
  6. License: Royalty-free for desktop applications at no cost.

Why Not Alternatives

  • libcosmic (COSMIC DE toolkit): Proven for desktop environments but tightly coupled to COSMIC's design system. No external design file separation — styling is in Rust code. Forking an entire DE toolkit to make it look like CDE is more work than building on Slint.
  • GTK4-rs / Relm4: LGPL licensing requires dynamic linking. C-based with GObject complexity. CSS is looser than .slint for AI-driven design. GTK is opinionated about HIG — CDE aesthetics fight its design philosophy.
  • iced (vanilla): No built-in external style file system. Styling is entirely code-based.
  • egui: Immediate-mode paradigm is wrong for persistent desktop shell UI.
  • Xilem/Masonry: Pre-alpha, 1-2 years from production readiness.

WM Architecture (neocde-wm)

The WM is a pure protocol client with zero GUI dependencies. It connects to wrsrvd via the wayray_wm_v1 Wayland protocol.

Dependencies: wayland-client, wayray-wm-protocol only. No rendering libraries.

Decoration policy: The WM sends use_ssd to tell the compositor to render server-side decorations. The actual CDE Motif-style title bar/border rendering is 100% the compositor's responsibility (wrsrvd Phase 5.1). The WM never renders pixels.

Two-phase transaction model (from wayray_wm_v1):

  • Phase 1 — Manage: Compositor sends manage_start → WM responds with propose_dimensions, set_focus, decoration choices, fullscreen grant/deny → WM calls manage_done
  • Phase 2 — Render: After apps commit → compositor sends render_start → WM sends set_position, set_z_top/bottom, show/hide → WM calls render_done → atomic frame apply

CDE-specific WM behaviors:

  • Click-to-focus, raise-on-focus
  • CDE floating layout with centered initial placement
  • Virtual desktops (workspace switching mapped to Front Panel buttons)
  • Alt+F4 close, Alt+Tab window cycling
  • Interactive move/resize via wayray_wm_seat_v1

Shell Components (layer-shika)

Shell components are layer-shell Wayland clients rendered by Slint via layer-shika's SCTK-based platform backend.

layer-shika (v0.3.1, Feb 2026)

Architecture:

  • domain: Core models, port traits, zero external deps
  • adapters: SCTK for Wayland, femtovg + EGL for rendering, Slint platform integration
  • composition: Public API with builder patterns

Capabilities:

  • Multi-surface layer shell windows (Front Panel + Taskbar = separate surfaces)
  • Per-monitor instances (panel on every output)
  • xdg-popup protocol (menus, tooltips)
  • ext-session-lock-v1 (lock screen)
  • HiDPI / fractional scaling
  • Runtime .slint compilation via slint-interpreter

License: AGPL-3.0. NeoCDE shell components must be AGPL-3.0 compatible, or negotiate with the author, or write a custom SCTK-based Slint platform backend (~500 lines following their architecture).

Shell Surfaces

Component Layer Purpose
Front Panel bottom Workspace buttons, app launchers, clock
Taskbar top Window list (via wlr-foreign-toplevel)
App Drawer overlay Application launcher grid
Lock Screen overlay ext-session-lock-v1
Notifications top Desktop notifications

Design Token Pipeline

Pencil (.pen)  ←── Designer AI / Pencil MCP edits here
     │
     │  export (pen-to-toml tool)
     ▼
tokens.toml  ←── Canonical source of truth
     │
     ├── build.rs codegen ──► theme.slint    (shell + apps consume)
     │
     └── build.rs codegen ──► wrsrvd-theme.ron  (compositor SSD rendering)

tokens.toml (canonical format)

Maps directly from Pencil's 70+ design variables:

[metadata]
name = "neocde-glassy-workstation"
is_dark = true

[colors]
window-bg = "#1E2A3AE6"
window-bg-solid = "#1E2A3AFF"
window-border = "#3A5068FF"
surface-glass = "#1E2E4280"
surface-dark = "#0E1620FF"
surface-medium = "#1A2838FF"
surface-light = "#2A3E52FF"
title-bar-bg = "#2A3E55E6"
title-bar-text = "#B0C8DCFF"
color-primary = "#4A8B82FF"
color-primary-hover = "#5BB0A4FF"
accent = "#4A8A90FF"
accent-hover = "#5AA0A8FF"
color-accent = "#C16B58FF"
color-background = "#15171AFF"
color-frame = "#24282DFF"
color-terminal-bg = "#0D0E11FF"
color-input-bg = "#0D0E11E6"
text-primary = "#C8DDE8FF"
text-secondary = "#8AA4B8FF"
text-muted = "#5A7A90FF"
color-muted = "#8B949EFF"
color-text = "#E4E7EBFF"
button-bg = "#2A3E55CC"
button-border = "#3A5A78FF"
button-hover = "#3A5068CC"
taskbar-bg = "#141E2CE6"
color-panel-bg = "#202428A6"
color-surface = "#202428A6"
danger = "#C85050FF"
success = "#50A868FF"
color-folder = "#C8A868FF"
color-folder-shadow = "#8A7040FF"
color-divider = "#2A3040FF"
desktop-bg = "#0A1018FF"
scrollbar-thumb = "#3A5A78FF"
scrollbar-bg = "#1A2838FF"
input-bg = "#0E1A28E6"
input-border = "#2A4058FF"
divider = "#2A4058FF"
color-selection = "#4A8B8233"
color-highlight-border = "#FFFFFF0D"
color-shadow-inset-dark = "#00000066"
color-shadow-inset-light = "#FFFFFF0D"
color-scrollbar-thumb = "#4A8B82FF"
color-scrollbar-track = "#24282DFF"

[spacing]
xs = 4
sm = 8
md = 12
lg = 16
xl = 24

[corner-radii]
sm = 3
md = 6
lg = 8
panel = 16
inner = 0
outer = 4
window = 8

[typography]
font-ui = "IBM Plex Sans"
font-mono = "IBM Plex Mono"
font-main = "IBM Plex Mono"

[typography.sizes]
xs = 12
sm = 14
md = 13
body = 15
lg = 20
xl = 28
clock = 14

[dimensions]
title-bar-height = 32
front-panel-height = 80
menu-bar-height = 28
status-bar-height = 24
icon-size = 64
scrollbar-width = 16
border-width = 1
border-thick = 8

Generated theme.slint

// Auto-generated from tokens.toml — do not hand-edit
export global Theme {
    // Colors
    in-out property<color> window-bg: #1E2A3AE6;
    in-out property<color> surface-glass: #1E2E4280;
    in-out property<color> title-bar-bg: #2A3E55E6;
    in-out property<color> title-bar-text: #B0C8DCFF;
    in-out property<color> color-primary: #4A8B82FF;
    in-out property<color> text-primary: #C8DDE8FF;
    in-out property<color> text-secondary: #8AA4B8FF;
    in-out property<color> button-bg: #2A3E55CC;
    in-out property<color> button-border: #3A5A78FF;
    // ... all color tokens

    // Spacing
    in-out property<length> spacing-xs: 4px;
    in-out property<length> spacing-sm: 8px;
    in-out property<length> spacing-md: 12px;
    in-out property<length> spacing-lg: 16px;
    in-out property<length> spacing-xl: 24px;

    // Corner radii
    in-out property<length> corner-sm: 3px;
    in-out property<length> corner-md: 6px;
    in-out property<length> corner-lg: 8px;
    in-out property<length> corner-panel: 16px;
    in-out property<length> corner-window: 8px;

    // Dimensions
    in-out property<length> title-bar-height: 32px;
    in-out property<length> front-panel-height: 80px;
    in-out property<length> menu-bar-height: 28px;
    in-out property<length> status-bar-height: 24px;
    in-out property<length> icon-size: 64px;
    in-out property<length> scrollbar-width: 16px;

    // Typography
    in-out property<string> font-ui: "IBM Plex Sans";
    in-out property<string> font-mono: "IBM Plex Mono";
    in-out property<length> font-size-xs: 12px;
    in-out property<length> font-size-sm: 14px;
    in-out property<length> font-size-md: 13px;
    in-out property<length> font-size-body: 15px;
    in-out property<length> font-size-lg: 20px;
    in-out property<length> font-size-xl: 28px;
}

Generated wrsrvd-theme.ron (for compositor SSD)

NeoCdeDecorations((
    title_bar: (
        height: 32,
        bg: (red: 0.165, green: 0.243, blue: 0.333, alpha: 0.902),
        text: (red: 0.690, green: 0.784, blue: 0.863, alpha: 1.0),
        font: "IBM Plex Sans",
        font_size: 13,
    ),
    border: (
        color: (red: 0.227, green: 0.353, blue: 0.471, alpha: 1.0),
        width: 1,
        corner_radius: 8,
    ),
    buttons: (
        close: (bg: (red: 0.784, green: 0.314, blue: 0.314, alpha: 1.0)),
        minimize: (bg: (red: 0.165, green: 0.243, blue: 0.333, alpha: 0.8)),
        maximize: (bg: (red: 0.165, green: 0.243, blue: 0.333, alpha: 0.8)),
    ),
))

AI Workflow Model

Separation of Concerns

Designer AI (Pencil MCP, Slint editor)     Code AI (Rust)
─────────────────────────────────────       ──────────────────────
Edits:                                      Edits:
  designs/*.pen                               */src/**/*.rs
  tokens/tokens.toml                          Cargo.toml, Cargo.lock
  */ui/**/*.slint                             build.rs

Never touches:                              Never touches:
  *.rs                                        *.slint
  Cargo.toml                                  *.pen
                                              tokens.toml

Two Runtime Modes

Mode Use Case How .slint is loaded Trade-off
Compiled (production) Release builds build.rsslint_build::compile()slint::include_modules!() Type-safe, fast startup, AOT
Interpreted (design iteration) AI design workflow slint_interpreter::Compiler::build_from_path() Hot reload, no recompilation, string-keyed properties

Wayland Protocols Required

Protocol Purpose Priority
wayray_wm_v1 WM ↔ compositor (custom) Critical
wlr-layer-shell-v1 Panel, taskbar, overlays Critical
xdg-shell Application windows Critical
xdg-decoration Server-side CDE window chrome Critical
wlr-foreign-toplevel-management Taskbar window list Critical
ext-session-lock-v1 Lock screen High
wlr-output-management Display settings High
wp-fractional-scale HiDPI support High
xdg-activation-v1 Focus management Medium
wp-idle-inhibit Screensaver prevention Medium
wlr-data-control Clipboard manager Medium
ext-idle-notify Screensaver triggering Low

Dependencies (target versions, early 2026)

Crate Version Used By
slint 1.14+ Shell + Apps
slint-interpreter 1.14+ AI design workflow
slint-build 1.14+ build.rs codegen
layer-shika 0.3+ (git) Shell surfaces
smithay-client-toolkit 0.20 Wayland protocols
wayland-client 0.31+ WM client
calloop 0.14+ Event loop
toml 0.8+ Token parsing
ron 0.8+ RON generation
serde 1.x Serialization

Project Structure

neocde/
├── designs/
│   └── untitled.pen                # Pencil source of truth
├── images/
│   └── *.png                       # Reference imagery
├── tokens/
│   ├── tokens.toml                 # Canonical design tokens
│   ├── pen-to-toml/                # Tool: .pen export → tokens.toml
│   │   ├── Cargo.toml
│   │   └── src/main.rs
│   └── token-codegen/              # Shared codegen library
│       ├── Cargo.toml
│       └── src/lib.rs              # generate_slint(), generate_ron()
├── neocde-wm/                      # WM client (zero GUI deps)
│   ├── Cargo.toml                  # wayland-client, wayray-wm-protocol
│   └── src/
│       ├── main.rs
│       ├── layout.rs               # CDE floating layout
│       ├── focus.rs                # Click-to-focus, raise-on-focus
│       ├── keybinds.rs             # Alt+F4, Alt+Tab, workspaces
│       ├── workspaces.rs           # Virtual desktops
│       └── config.rs               # WM config (TOML)
├── neocde-shell/                   # Shell (layer-shika + Slint)
│   ├── Cargo.toml                  # slint, layer-shika, sctk
│   ├── build.rs                    # tokens.toml → theme.slint
│   ├── ui/                         # DESIGNER AI TERRITORY
│   │   ├── theme.slint             # Generated from tokens
│   │   ├── components/
│   │   │   ├── button.slint
│   │   │   ├── window-chrome.slint # CSD fallback
│   │   │   ├── input.slint
│   │   │   ├── tab-bar.slint
│   │   │   ├── menu-bar.slint
│   │   │   ├── scrollbar.slint
│   │   │   └── status-bar.slint
│   │   ├── front-panel.slint       # CDE Front Panel
│   │   ├── taskbar.slint           # Window list + clock
│   │   └── app-drawer.slint        # App launcher
│   └── src/                        # CODE AI TERRITORY
│       ├── main.rs
│       ├── panel.rs
│       ├── taskbar.rs
│       ├── clock.rs
│       └── launcher.rs
├── neocde-filemanager/             # App (Slint, xdg-shell)
│   ├── Cargo.toml
│   ├── build.rs
│   ├── ui/
│   │   └── file-manager.slint
│   └── src/
│       ├── main.rs
│       └── filesystem.rs
├── neocde-terminal/                # App (custom GPU or Slint)
├── neocde-settings/                # App (Slint)
│   ├── ui/
│   │   └── style-manager.slint
│   └── src/
└── Cargo.toml                      # Workspace root

Build Order

  1. token-codegen — build.rs library: tokens.toml → theme.slint + wrsrvd-theme.ron
  2. neocde-shell (Front Panel only) — proves: Pencil tokens → TOML → Slint → layer-shell → WayRay
  3. neocde-wm — connect to wrsrvd, CDE floating layout, use_ssd
  4. neocde-shell (Taskbar) — second layer-shika surface, foreign-toplevel window list
  5. neocde-filemanager — first standard Slint app (xdg-shell)
  6. neocde-settings / Style Manager — theme editor that writes back to tokens.toml
  7. neocde-terminal — may need custom renderer for terminal grid performance