From 1b252e32d93e1e0207d2a69ee3445e1dbf6505ae Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 11 Sep 2026 18:30:58 +0200 Subject: feat(appearance): wallpaper picker and scheme switcher One drawer for how the desktop looks, on SUPER+Return, replacing the qarma file dialog that key used to open. wallp is untouched and still does the work: the panel calls it with H= and V= and it still runs from a terminal. Clicking a thumbnail stages it rather than setting it, so both screens can be composed before anything changes and Apply is a single wallp call. The mock screens show the result: the staged pick where there is one, what is set where there is not, and the hovered thumbnail on the targeted screen. They are drawn at the real proportions from hyprctl monitors, DP-3 upright because it has transform=1, centred against each other as Hyprland has them. The scheme tab reads the palette pair unified-desktop-theme keeps for each scheme, so the swatches are that scheme's real colours and the list needs no edit when a scheme is added. Applying writes roles.conf and runs install.sh, and reloads nothing, because install.sh reloads nothing: the panel says what is still showing the old scheme rather than pretending the switch is done. Two QML traps are documented in AGENTS.md because neither announces itself: there is no String.matchAll, which threw inside a try and left every swatch empty, and assigning running = true to an already-running Process does nothing, which stopped the scheme loader after the first file. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01G7NRsGyF9jGfPYS4zPqpN7 --- appearance/README.md | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 appearance/README.md (limited to 'appearance/README.md') diff --git a/appearance/README.md b/appearance/README.md new file mode 100644 index 0000000..f0e9a09 --- /dev/null +++ b/appearance/README.md @@ -0,0 +1,95 @@ +# appearance + +Wallpapers and colour scheme in one drawer. `SUPER+Return` opens it on the +Wallpaper tab; Tab switches tabs, Escape closes. + + ┌─[ Wallpaper ]─[ Theme ]──────────────────────────┐ + │ Set on [Horizontal] [Vertical] 261 wallpapers │ + │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌──┐ ┌─────┐ │ + │ │ │ │ │ │ │ │ │ │ │ │ │ │ + │ └────┘ └────┘ └────┘ └────┘ └┬─┘ └──┬──┘ │ + │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ═╧═ ══╧══ │ + │ │ │ │ │ │ │ │ │ [Apply] [Reset]│ + │ └────┘ └────┘ └────┘ └────┘ │ + └──────────────────────────────────────────────────┘ + +## Running it + + qs -p . + +It is started from `autostart.lua` and reached over IPC, so the shell has to +be running for the keybind to work: + + hl.bind(mainMod .. " + Return", hl.dsp.exec_cmd( + "qs -p ~/Programming/GIT/quickshell/appearance ipc call appearance wallpaper")) + +Write that path out in full in the real config: `exec_cmd` has no shell to +expand `~`. `ipc call appearance theme` opens the other tab. + +## Wallpapers + +Clicking a thumbnail **stages** it rather than setting it, so both screens can +be composed before anything changes, and Apply then makes a single +`wallp --set H=… V=…` call. The mock screens on the right show what the desk +would look like: the staged pick where there is one, what is currently set +where there is not, and the hovered thumbnail on the targeted screen while the +pointer is over it. + +`wallp` does the actual work, including running `udt-accent`, so the accent +follows the new wallpaper exactly as it does from a terminal. This panel +replaces its qarma file dialog, not the script. + +The two monitors are drawn at their real proportions, read from +`hyprctl monitors`: DP-1 is 2560x1080 and DP-3 is 1920x1080 with +`transform=1`, which makes it 1080x1920 on the desk. They are centred against +each other because that is how Hyprland has them, both spanning y=0. + +The bezel and stand are Rectangles rather than an SVG: no asset to ship, sharp +at any size, and the case stays a fixed near-black while the accent marks +which screen is targeted. Their proportions come from the panel **width**, not +its height. Scaling the stand off height gave the wide monitor a 20px stand +that was invisible and would have given the vertical one an absurd long neck. + +## Themes + +Each scheme shows its real colours, parsed from the pair of files +unified-desktop-theme keeps for it: `palette/.conf` holds the colours +under the scheme's own names, `palette/roles-.conf` says what each +colour is for, so a role is resolved by looking its value up as a key in the +first file. Beside the swatches is a small mock of a panel painted in that +scheme, which says how the colours sit together rather than only what they +are. + +The list comes from the palette directory rather than a hardcoded set, so +adding a scheme to unified-desktop-theme is enough to make it appear here. + +Applying writes the `scheme =` line in `~/.config/udt/roles.conf` and runs +`install.sh`, which regenerates every themed config. **It reloads nothing**, +because `install.sh` reloads nothing: the panel reports what is still showing +the old scheme instead of pretending the switch is complete. `hyprctl reload`, +waybar, kitty and conky each need a nudge, and Qt and GTK apps only reread a +theme when they restart. + +## Two QML traps met here + +**There is no `String.matchAll`.** QML's JS engine does not have it. It threw +inside a `try` and left every swatch empty with nothing in the log. The +palette parser uses an `exec` loop instead. + +**Assigning `running = true` to a Process that is already running does +nothing.** The scheme loader reuses one `Process` for each scheme in turn and +stopped after the first until it set `running = false` immediately before. + +## Theme and blur + +`Theme.qml` is the shared one: the palette comes from +`~/.cache/wal/udt-palette.qml` and is watched. Frosting is Hyprland's, matched +on this window's namespace: + + hl.layer_rule({ + name = "blur-appearance", + match = { namespace = "^(quickshell-appearance)$" }, + blur = true, + xray = false, + ignore_alpha = 0.1, + }) -- cgit v1.2.3