# 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: ```toml [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 ```slint // Auto-generated from tokens.toml — do not hand-edit export global Theme { // Colors in-out property window-bg: #1E2A3AE6; in-out property surface-glass: #1E2E4280; in-out property title-bar-bg: #2A3E55E6; in-out property title-bar-text: #B0C8DCFF; in-out property color-primary: #4A8B82FF; in-out property text-primary: #C8DDE8FF; in-out property text-secondary: #8AA4B8FF; in-out property button-bg: #2A3E55CC; in-out property button-border: #3A5A78FF; // ... all color tokens // Spacing in-out property spacing-xs: 4px; in-out property spacing-sm: 8px; in-out property spacing-md: 12px; in-out property spacing-lg: 16px; in-out property spacing-xl: 24px; // Corner radii in-out property corner-sm: 3px; in-out property corner-md: 6px; in-out property corner-lg: 8px; in-out property corner-panel: 16px; in-out property corner-window: 8px; // Dimensions in-out property title-bar-height: 32px; in-out property front-panel-height: 80px; in-out property menu-bar-height: 28px; in-out property status-bar-height: 24px; in-out property icon-size: 64px; in-out property scrollbar-width: 16px; // Typography in-out property font-ui: "IBM Plex Sans"; in-out property font-mono: "IBM Plex Mono"; in-out property font-size-xs: 12px; in-out property font-size-sm: 14px; in-out property font-size-md: 13px; in-out property font-size-body: 15px; in-out property font-size-lg: 20px; in-out property font-size-xl: 28px; } ``` ### Generated wrsrvd-theme.ron (for compositor SSD) ```ron 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.rs` → `slint_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