Give the desktop real themes, video wallpapers, and honest titlebars
Appearance now opens on Themes: light and dark side by side, each remembering its own choice, over galleries of ten shipped themes — Tokyo Moon and Day joined by Moon Rose, Catppuccin, Nord, Gruvbox and Everforest in both modes. A theme is a complete palette: the catalog lives in themes.json, Theme.qml reads every color token from the active record, and one render pipeline carries it to kitty, tmux, btop, GTK, Vicinae, Firefox's chrome, and the lock screen. The Theme editor builds new ones from four wells — wheel, hex, or eyedropper — with derived surfaces, a saturation slider, debounced fine-tune, and effects that save with the theme. Custom edits finally keep GNOME's accent, kitty's border, and hyprlock in sync. Wallpapers can be video: mpvpaper per output, hardware-decoded, muted and looped, supervised and respawned. Panama owns the pausing — games, battery, and a bar pill for right now — because the compositor rebuilds full-screen blur for every frame a video wallpaper draws. The lock screen gets a still frame. Titlebars stop lying. GNOME apps get close-only on your chosen side, the maximize and double-click settings are gone, the Settings window obeys the same rules, and its titlebar can be turned off entirely. Typography becomes five labeled dropdowns instead of a wall of samples. Contracts updated and written throughout (165 now); per the redesign workflow none were executed — the full sweep runs once at the end. Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -78,6 +78,73 @@ The final card is the ownership boundary. Network configuration and the exact
|
||||
Users, Sharing, Color profiles, and Digital wellbeing handoffs open GNOME
|
||||
Settings because Fedora's system services own those areas.
|
||||
|
||||
## Appearance
|
||||
|
||||
Six tabs, in the order the questions are actually asked: **Themes**, **Theme
|
||||
editor**, **Background**, **Typography**, **Windows**, **Shell**. Themes leads
|
||||
because light and dark is the control reached most often, and it used to be the
|
||||
third section down, under a wallpaper grid and the whole lock screen. The old
|
||||
`theme` section id still resolves to it, so deep links and IPC calls keep
|
||||
working.
|
||||
|
||||
### Themes
|
||||
|
||||
`config/themes.json` is the catalog: ten shipped themes, each a full palette of
|
||||
nineteen tokens plus sixteen ANSI colors. `services/ThemeCatalog.qml` reads it
|
||||
with a `FileView` and carries Moon and Day as an embedded fallback, so the
|
||||
shell renders correctly for the instant before the file loads and forever on a
|
||||
machine where it is missing.
|
||||
|
||||
The tab is two galleries — dark and light — rather than a card each. Selection
|
||||
is **per mode**: `themeDark` and `themeLight` remember what you chose on each
|
||||
side, so flipping light and dark lands on your theme for that side rather than
|
||||
resetting to the shipped defaults.
|
||||
|
||||
`services/ThemeProfiles.qml` resolves the active record; `Theme.qml` reads
|
||||
every one of its nineteen color tokens from `ThemeProfiles.activePalette`.
|
||||
There are no palette ternaries left in `Theme.qml`, which is what makes a
|
||||
tenth theme a data change rather than a code change.
|
||||
|
||||
### Theme editor
|
||||
|
||||
Four wells — primary, secondary, background, foreground — a saturation slider,
|
||||
an effects card, and the six HSV rows demoted to a fine-tune behind a
|
||||
disclosure. Background and foreground are never stored alone: the five surfaces
|
||||
and two text tints are mixed from them, so changing the ground moves the whole
|
||||
family instead of leaving twelve tokens pointing at the old one.
|
||||
|
||||
Every route that writes color — typed hex, the colour wheel, the eyedropper,
|
||||
the HSV sliders — ends in `ThemeProfiles.commitActive`, which also recomputes
|
||||
`accentName` as the nearest curated accent. That is what keeps GNOME's accent
|
||||
enum, kitty's border and the lock screen from going stale after a custom edit.
|
||||
Editing a shipped theme forks it into a named custom carrying the whole
|
||||
palette; saving snapshots the palette, the terminal colors, and all ten effect
|
||||
values into the record.
|
||||
|
||||
The HSV rows commit on a **debounce**, not per move. Writing on every move
|
||||
meant one drag across the hue row spent the whole gesture in apply-and-verify
|
||||
round trips with the desktop repainting behind the pointer.
|
||||
|
||||
### Backgrounds, still and moving
|
||||
|
||||
Stills go through hyprpaper. Videos go through mpvpaper, supervised by
|
||||
`services/VideoWallpaper.qml`, and Panama owns the pause policy rather than the
|
||||
compositor: the video pauses whenever a game runs, on battery if the preference
|
||||
says so, and whenever the bar pill is clicked — over mpv's JSON IPC socket, so
|
||||
resuming does not restart the clip. hyprpaper's service is stopped while a
|
||||
video plays, because both claim the background layer and stacking within a
|
||||
layer is creation order. The lock screen gets a cached still frame; hyprlock
|
||||
cannot play motion, and pretending otherwise would show a black screen.
|
||||
|
||||
### The honest titlebar
|
||||
|
||||
There is no minimize or maximize control, and no setting for one. Hyprland has
|
||||
no minimize — it receives the request and does nothing with it — and maximize
|
||||
is noise in a tiler, so `DesktopStyle` pushes a close-only GNOME button layout
|
||||
and Panama's own Settings titlebar shows one button. `panamaTitlebar` turns
|
||||
that bar off entirely, leaving the window pure Hyprland: Super+Q closes,
|
||||
Super+drag moves, Escape still works.
|
||||
|
||||
## Adding a setting
|
||||
|
||||
One schema entry. That is the whole job.
|
||||
@@ -141,13 +208,15 @@ or a copied default. Additions to this table require a concrete discoverability
|
||||
reason and an update to `tests/quickshell/settings-ownership-contract`.
|
||||
|
||||
Window border color follows the same ownership rule. The inactive border is a
|
||||
**scheme-relative role** owned by `ColorScheme.qml`: it changes only to retain
|
||||
neutral contrast in light and dark modes. The focused Prism border is the
|
||||
**accent role**, driven by the chosen `accentName` and also owned by
|
||||
`ColorScheme.qml`: each accent carries a separate pair for light and dark, so
|
||||
`ColorScheme.qml` restates the focused border alongside the inactive one on
|
||||
every scheme change, rather than leaving a scheme flip to erase a
|
||||
user-selected accent.
|
||||
neutral contrast role — a **scheme-relative role** in the sense that it exists
|
||||
to stay legible on either ground — owned by `ColorScheme.qml`, and it is drawn
|
||||
from the active theme's `gutter` rather than from a hardcoded pair. The two
|
||||
literals that used to live there were correct for two of the ten shipped themes
|
||||
and for no custom one. The focused Prism border is the **accent role**, driven
|
||||
by the chosen `accentName` and also owned by `ColorScheme.qml`: each accent
|
||||
carries a separate pair for light and dark. Both roles are restated on a scheme
|
||||
change, an accent change, and a theme change, rather than leaving a flip to
|
||||
erase a user-selected accent or a theme switch to leave the border behind.
|
||||
|
||||
## The rows
|
||||
|
||||
|
||||
Reference in New Issue
Block a user