theme: add linux system theme sources

This commit is contained in:
2026-10-31 07:57:27 +07:00
parent dacdd84aa4
commit c45f939211
11 changed files with 1187 additions and 10 deletions
+7 -5
View File
@@ -168,11 +168,13 @@ Controls through unit 10 paint from existing roles and ramps.
| --- | --- | --- | --- |
| macOS | compile target | `NSColor` semantic palette (`windowBackgroundColor`, `labelColor`, `controlColor`, `controlAccentColor`, `selectedTextBackgroundColor`, `keyboardFocusIndicatorColor`, …) in the effective appearance via `objc2-app-kit`; `NSWorkspace` accessibility flags | distributed notifications + GPUI appearance events |
| Windows 11 (WinUI) | compile target | WinRT `UISettings` (`AccentColor`, `AccentLight1–3`, `AccentDark1–2`, `Background`, `Foreground`), `TextScaleFactor`, `AccessibilitySettings` high-contrast; `Personalize` registry fallback | `UISettings.ColorValuesChanged` |
| GNOME / generic Linux | portal reachable | portal `org.freedesktop.appearance` (`color-scheme`, `accent-color`, `contrast`, `reduced-motion`); `gsettings` fallback | portal `SettingChanged` |
| KDE | `kdeglobals` present | `kdeglobals` color groups + scheme hash + accent; portal for mode/accent | inotify on `kdeglobals` |
| Omarchy | `~/.local/state/omarchy` or `~/.config/omarchy` marker | `current/theme/colors.toml` + `theme.name` (semantic keys or ANSI `color0..15`); portal for contrast/reduced-motion | inotify on the `current` dir (palette edits + symlink replacement) |
| GNOME / generic Linux | portal reachable (else `gsettings`) | portal `org.freedesktop.appearance` (`color-scheme`, `accent-color` as `(ddd)`, `contrast`, `reduced-motion`); `gsettings` fallback (`color-scheme` name + the libadwaita accent-name table) | portal `SettingChanged` |
| KDE | `kdeglobals` present | `kdeglobals` `[Colors:*]` groups (Window/View/Button/Selection) + `[General] AccentColor` (`-1,-1,-1` = wallpaper-derived, covered by the portal); portal for mode/accent | inotify on `~/.config`, filtered to `kdeglobals` (survives kconfig's replace-on-write) |
| Omarchy | `~/.local/state/omarchy` marker (`theme.name`, `current/theme`, or `~/.config/omarchy`) | `current/theme/colors.toml` (semantic keys, or the ANSI `color0..15` fallback the alacritty generator writes); portal for contrast/reduced-motion; mode from the file's `mode` key or background lightness | inotify on the `current` dir — catches theme-set's whole-directory swaps and `theme.name` writes (hand edits of the deployed copy need a switch to re-fire) |
| Fallback / unknown | none of the above, or reader failure | bundled neutral light/dark theme | manual only |
Linux adapters landed 2026-10-30 (fixture-tested parsers on every OS; payload facts transcribed from the portal spec, plasma's Breeze schemes, omarchy's `bin/omarchy-theme-set`, and libadwaita). The pinned gpui's `AsyncApp` is not `Send`, so watcher threads signal through an `async_channel` and a main-thread `App::spawn` loop reapplies.
### 5.4 Accent ramp engine
Every target supplies one accent color (or a stated ramp). Where the platform states shades (WinUI `AccentLight1–3`/`AccentDark1–2`, KDE scheme ramps) use them as-is; elsewhere derive the state shades components need (hover, pressed, selected, disabled, subtle fills) in OKLCH with fixed lightness/chroma offsets toward the background or foreground, hue preserved. Derived colors compute once per resolve, never per frame.
@@ -192,7 +194,7 @@ Native feel is half geometry. Per-platform tables for: control heights and paddi
### 5.7 Implementation vehicles
`objc2` + `objc2-app-kit` (macOS), `windows` (WinRT `UISettings`), `zbus` (portal DBus), `notify` (file watches), `serde` + `toml` (definitions) — all behind the `ThemeSource` seam so the engine core stays platform-free and testable.
`objc2` + `objc2-app-kit` (macOS), `windows` (WinRT `UISettings`), `zbus` 5 blocking API on a dedicated thread (portal DBus), `async-channel` (watcher→main-thread reapply bridge), `notify` (file watches), `serde` + `toml` (definitions) — all behind the `ThemeSource` seam so the engine core stays platform-free and testable.
### 5.8 What we do differently from native-theme
@@ -323,7 +325,7 @@ Dropped from rev 3: D2, D5, D9 (port-era decisions); the review gate returns in
4. ~~Phase D input~~ ✅ — single-line Input (unit 10) + the §6.2 completion pass (modifiers, undo/redo, read-only, actions + key context, caret blink, paint polish). NumberInput and multiline remain open as deferred units.
5. ~~Phase E overlays~~ ✅ — Popover (unit 11), ScrollArea (unit 11.5), Menu (unit 12), Tooltip + Dialog/AlertDialog + Toast (unit 11+ row; Sheet dropped). Phase gate held: escape/dismiss semantics and focus behavior per overlay.
6. ~~Unit 14 — motion, per component (§6 row 14, D21)~~ ✅ Landed in five passes (2026-10-30): (a) theme `reduce_motion` → `cx.set_reduce_motion` in `reapply`; (b) Switch thumb `with_spring`; (c) Toast 8 px slide-in; (d) Dialog scrim enters with the panel; (e) Progress 30 fps cap. Exits and hover washes stay deferred (§6 deferred list).
7. ~~Phase F, data first~~ ✅ data complete (2026-10-30) — `crates/data` opened with List, then Tree, Tabs, Sidebar (the dead `sheet` feature dropped from core along the way; Table dropped from the roadmap). Also extracted `crates/utils` (2026-10-30): `h_flex`/`v_flex` (core's `common` re-exports them), `focus_handle` (the namespaced keyed handle, 8 call sites), `focus_ring` (7 sites), `adjacent_selectable` + `nav_key` (4 sites), and the selectable-row paint helpers `selectable_label_color`/`paint_selectable_row` (3 sites, reading `&Theme` directly — no intermediate color struct) — `core` and `data` depend on it; the facade doesn't re-export it. Remaining Phase F: **Windows/GNOME/KDE/Omarchy theme sources** and the **Segoe Fluent/freedesktop icon resolvers**, slotted in as verification environments allow — a source may state `Motion.overlay` when it needs platform timing (§5.5) — with side-by-side gallery screenshots per platform. NumberInput/multiline return as deferred units when needed.
7. ~~Phase F, data first~~ ✅ data complete (2026-10-30) — `crates/data` opened with List, then Tree, Tabs, Sidebar (the dead `sheet` feature dropped from core along the way; Table dropped from the roadmap). Also extracted `crates/utils` (2026-10-30): `h_flex`/`v_flex` (core's `common` re-exports them), `focus_handle` (the namespaced keyed handle, 8 call sites), `focus_ring` (7 sites), `adjacent_selectable` + `nav_key` (4 sites), and the selectable-row paint helpers `selectable_label_color`/`paint_selectable_row` (3 sites, reading `&Theme` directly — no intermediate color struct) — `core` and `data` depend on it; the facade doesn't re-export it. **Linux theme sources landed (2026-10-30)**: Omarchy (colors.toml parse + state-dir detection + inotify on `current`), KDE (kdeglobals `[Colors:*]` + AccentColor + `~/.config` inotify), GNOME/generic (portal `ReadAll` + `SettingChanged` via zbus 5 blocking on its own thread, gsettings fallback with the libadwaita accent table) — `SourceKind::Omarchy/Kde/Gnome`, detection cascade Omarchy → KDE → portal → fallback, all parsers fixture-tested on every OS and the Linux build compile-checked via `cargo check --target x86_64-unknown-linux-gnu`. Remaining Phase F: the **Windows source (WinRT `UISettings`)** and the **Segoe Fluent/freedesktop icon resolvers**, slotted in as verification environments allow — with side-by-side gallery screenshots per platform. NumberInput/multiline return as deferred units when needed.
8. Then — Phase G: pickers, polish, → 0.1; start `crates/editor` if wanted.
Batched polish candidates between units: scrollbar auto-hide + horizontal thumb, `Undo`/`Redo` menu events.