diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-29 11:42:09 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-29 11:42:09 +0200 |
| commit | ff7dcf3ef2338a0aef1856a33da06d1a92c2434c (patch) | |
| tree | 65f48abed7b214cd27492afadd1aeb7cad90d254 | |
| parent | 8164e17276bb37f5f24c9f84df5923c090efed79 (diff) | |
| download | unified-desktop-theme-ff7dcf3ef2338a0aef1856a33da06d1a92c2434c.tar.gz unified-desktop-theme-ff7dcf3ef2338a0aef1856a33da06d1a92c2434c.zip | |
feat(grub): rebuild on every wallpaper change via udt-grub
GRUB's background is a wallpaper snapshot, but only install.sh rebuilt it,
so a wallpaper change left the /boot copy stale with no hint. udt-grub now
holds the build-and-print logic; install.sh runs it in the foreground and
udt-accent starts it detached next to udt-homepage. A stale installed theme
gets a notification carrying the root copy command. A flock serialises the
two runs install.sh triggers, since build swaps dist/udt in by rename.
AGENTS.md: udt-accent writes seven outputs (SDDM was missing), and names
the two detached helpers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| -rw-r--r-- | AGENTS.md | 18 | ||||
| -rwxr-xr-x | bin/udt-accent | 9 | ||||
| -rwxr-xr-x | bin/udt-grub | 50 | ||||
| -rwxr-xr-x | install.sh | 35 |
4 files changed, 74 insertions, 38 deletions
@@ -24,9 +24,11 @@ Sibling checkouts are wired from here, each skipped when not cloned: `~/.config/conky/`) and `hypr-theme`, which is the whole of `~/.config/hypr` as one symlink. A real `~/.config/hypr` directory is left alone with a warning. `grub-theme-udt` is SDDM's shape: udt-palette renders its `theme.txt.in`, -`install.sh` runs its `build` as the user, then prints the root copy. A copy, -not a link, because GRUB reads `/boot` before `/home` is mounted; it needs -rerunning after a scheme or wallpaper change. +`bin/udt-grub` runs its `build` as the user, then prints the root copy. A copy, +not a link, because GRUB reads `/boot` before `/home` is mounted, so it goes +stale on a scheme or wallpaper change. `install.sh` runs `udt-grub` in the +foreground and `udt-accent` starts it detached, and when an installed theme +differs from the new build the root command arrives as a notification. Its panel title is `PRETTY_HOSTNAME` from `/etc/machine-info`, which `bin/udt-machine-name` writes (root, run by the user; there is no hostnamectl without systemd). It rewrites that one key and keeps the rest. @@ -166,12 +168,16 @@ One colour moves: `@accent`. `bin/udt-accent` reads the current wallpaper, extracts its signature colour, and snaps it to the nearest of ten Catppuccin accents by perceptual hue in CIELAB. `wallp` calls it on every wallpaper change. -It writes six things: `~/.cache/udt/udt-accent.rasi` (rofi), +It writes seven things: `~/.cache/udt/udt-accent.rasi` (rofi), `~/.cache/udt/udt-border.lua` (Hyprland), `~/.cache/udt/hyprlock-border.conf` (hyprlock, the same three hues as the window border, as a hyprlang gradient), `~/.cache/wal/colors.json` (Firefox, via pywalfox), -`~/.cache/udt/udt-palette.qml` (quickshell), and the accent substitution in -Sublime's installed `Packages/User/udt.sublime-color-scheme`. +`~/.cache/udt/udt-palette.qml` (quickshell), +`~/.local/share/udt/sddm-theme.conf` (the SDDM greeter, palette plus wallpaper, +read through a root-made `theme.conf.user` symlink), and the accent +substitution in Sublime's installed `Packages/User/udt.sublime-color-scheme`. +It then starts `udt-homepage` and `udt-grub` detached, for the two outputs +that need a root step on another filesystem or host. **Sublime's accent is replaced, not substituted into a placeholder.** Its colour scheme cannot cascade, so the accent has to live in the one generated diff --git a/bin/udt-accent b/bin/udt-accent index 72d3a64..1027fab 100755 --- a/bin/udt-accent +++ b/bin/udt-accent @@ -477,9 +477,12 @@ def main(image): # The dashboard host. Detached, because wallp runs this synchronously and # an unreachable host would hold the wallpaper change for the scp timeout. - subprocess.Popen([Path(__file__).resolve().parent / "udt-homepage"], - stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, start_new_session=True) + # GRUB's background is a wallpaper snapshot. Detached for the same reason; + # it only rebuilds and notifies, since the copy into /boot needs root. + for helper in ("udt-homepage", "udt-grub"): + subprocess.Popen([Path(__file__).resolve().parent / helper], + stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, start_new_session=True) before, after = hue_neighbours(name) print(f"{name} {ACCENTS[name]} (border: {before} .. {name} .. {after})") diff --git a/bin/udt-grub b/bin/udt-grub new file mode 100755 index 0000000..20fd296 --- /dev/null +++ b/bin/udt-grub @@ -0,0 +1,50 @@ +#!/bin/bash +# udt-grub: rebuild the GRUB theme and say what root has to copy into /boot. +# Copyright (C) 2026 Danilo M. <danix@danix.xyz> +# Licensed under the GNU General Public License v2 only. +# +# Built, not installed: GRUB reads /boot before /home is mounted, so the theme +# is a root-owned copy of grub-theme-udt's dist/udt/, and this script only +# prints the command that refreshes it. Its background is a snapshot of the +# wallpaper and its colours come from the scheme, so both a wallpaper change +# and a scheme switch leave the copy stale. +# +# udt-accent starts this detached on every run; install.sh runs it in the +# foreground. A notification goes out only when an installed theme is stale: +# a machine that never installed it has nothing to refresh. + +repo="$(dirname "$(readlink -f "$0")")/.." +grub_repo="$(realpath -m "$repo/../grub-theme-udt")" +[ -x "$grub_repo/build" ] || exit 0 + +# install.sh runs udt-accent, which starts this detached, and then runs this +# itself. build swaps dist/udt/ in with a rename, so two at once can collide. +mkdir -p "$grub_repo/dist" +exec 9>"$grub_repo/dist/.lock" +flock 9 + +"$grub_repo/build" >/dev/null || { echo "grub: its build failed, theme not refreshed" >&2; exit 1; } + +theme=/boot/grub/themes/udt +copy="rm -rf $theme && cp -r \"$grub_repo/dist/udt\" /boot/grub/themes/" + +if diff -rq "$grub_repo/dist/udt" "$theme" >/dev/null 2>&1; then + echo "grub theme: up to date" +elif [ -d "$theme" ]; then + echo "grub theme: refresh as root" + echo " $copy" + command -v notify-send >/dev/null 2>&1 && + notify-send -a udt "grub: theme rebuilt" "As root: +$copy" +else + echo "grub theme: run these as root to install it" + echo " $copy" +fi +grep -q "^GRUB_THEME=\"$theme/theme.txt\"" /etc/default/grub 2>/dev/null || { + echo " # once: GRUB_THEME=\"$theme/theme.txt\" in /etc/default/grub, then" + echo " grub-mkconfig -o /boot/grub/grub.cfg" +} +# The panel title falls back to the OS name until one is set. +[ -n "$("$repo/bin/udt-machine-name")" ] || + echo " # optional, the panel title: sudo \"$repo/bin/udt-machine-name\" \"My Machine\"" +exit 0 @@ -104,7 +104,7 @@ ln -sfn "$HOME/.cache/udt/colors.json" "$HOME/.cache/wal/colors.json" # The rofi menus are bound by name in hypr-theme's keybindings, so they keep # the names they had when they lived loose in ~/bin. -for f in udt-accent udt-palette udt-machine-name udt-powermenu.sh udt-launcher.sh qar-scrotmenu.sh; do +for f in udt-accent udt-grub udt-palette udt-machine-name udt-powermenu.sh udt-launcher.sh qar-scrotmenu.sh; do ln -sfn "$repo/bin/$f" "$HOME/bin/$f" done @@ -339,34 +339,11 @@ if [ -d "$sddm_repo/theme" ]; then echo " printf '[Theme]\\nCurrent=udt\\n' > /etc/sddm.conf.d/udt.conf" fi -# GRUB. Same shape as SDDM: udt-palette has rendered theme.txt, the sibling -# repo's build assembles the theme as the user, and the root half is printed. -# A copy, not a link: GRUB reads /boot before /home is mounted. The background -# is a snapshot of the wallpaper, so the copy needs rerunning after a scheme -# or wallpaper change; grub-mkconfig only when GRUB_THEME changes. -grub_repo="$(realpath -m "$repo/../grub-theme-udt")" -if [ -x "$grub_repo/build" ]; then - if "$grub_repo/build"; then - grub_theme='/boot/grub/themes/udt/theme.txt' - echo - if diff -rq "$grub_repo/dist/udt" /boot/grub/themes/udt >/dev/null 2>&1; then - echo "grub theme: up to date" - elif grep -q "^GRUB_THEME=\"$grub_theme\"" /etc/default/grub 2>/dev/null; then - echo "grub theme: refresh as root" - echo " rm -rf /boot/grub/themes/udt && cp -r \"$grub_repo/dist/udt\" /boot/grub/themes/" - else - echo "grub theme: run these as root to install or refresh it" - echo " rm -rf /boot/grub/themes/udt && cp -r \"$grub_repo/dist/udt\" /boot/grub/themes/" - echo " # once: GRUB_THEME=\"$grub_theme\" in /etc/default/grub, then" - echo " grub-mkconfig -o /boot/grub/grub.cfg" - fi - # The panel title falls back to the OS name until one is set. - [ -n "$("$repo/bin/udt-machine-name")" ] || \ - echo " # optional, the panel title: sudo \"$repo/bin/udt-machine-name\" \"My Machine\"" - else - echo "grub: its build failed, theme not refreshed" >&2 - fi -fi +# GRUB. Same shape as SDDM: udt-palette has rendered theme.txt, and udt-grub +# builds the theme as the user and prints the root half. udt-accent also runs +# it, detached, so a wallpaper change alone rebuilds it too. +echo +"$repo/bin/udt-grub" [ -n "$reloaded" ] && echo "reloaded:$reloaded" |
