diff options
| -rw-r--r-- | AGENTS.md | 29 | ||||
| -rwxr-xr-x | bin/udt-accent | 55 |
2 files changed, 75 insertions, 9 deletions
@@ -19,20 +19,30 @@ 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 three things: `~/.cache/wal/udt-accent.rasi` (rofi), -`~/.cache/wal/udt-border.lua` (Hyprland), and the accent substitution in -`~/.cache/wal/dunstrc`. +It writes four things: `~/.cache/wal/udt-accent.rasi` (rofi), +`~/.cache/wal/udt-border.lua` (Hyprland), the accent substitution in +`~/.cache/wal/dunstrc`, and `~/.cache/wal/colors.json` (Firefox, via +pywalfox). **Extraction is deliberately isolated from the pywal cache.** It calls `pywal.backends.colorz.get()` directly, which returns a list and writes nothing. Running `wal -i` instead would rewrite all of `~/.cache/wal`, including the terminal's ANSI colours, and that is the exact failure this design exists to -avoid. If you change that function, verify `~/.cache/wal/colors.json` is -byte-identical afterwards. - -Not everything tracks the wallpaper. rofi, dunst and Hyprland borders do; conky, -Qt, GTK and waybar sit on fixed lavender, which is also the fallback when a -wallpaper is too grey to snap. Qt and GTK apps only reread a theme on restart, +avoid. If you change `signature_color()`, verify it still writes nothing. + +`colors.json` is the one pywal file `udt-accent` does rewrite, and it rewrites +it wholesale rather than editing it: a fixed Macchiato palette with the accent +in the cursor and the two highlight slots. That is deliberate. pywalfox reads +`colors.json` and nothing else, so it is the only way Firefox can follow the +accent, and overwriting it costs nothing because nothing else reads it. In +particular kitty reads `~/.config/kitty/current-theme.conf`, not this file, so +the terminal palette stays fixed no matter what the wallpaper looks like. The +write lands after `wallp` has already run `wal --theme`, so it wins; reorder +those two and pywal's wallpaper-derived colours come back. + +Not everything tracks the wallpaper. rofi, dunst, Hyprland borders and Firefox +do; conky, Qt, GTK and waybar sit on fixed lavender, which is also the fallback +when a wallpaper is too grey to snap. Qt and GTK apps only reread a theme on restart, so a moving accent there would leave running apps disagreeing with new ones. ## Verifying visual changes @@ -104,6 +114,7 @@ them by exit code: rofi exits non-zero for ordinary reasons such as Escape. | --- | --- | | rofi | nothing; the theme is read per launch | | dunst | `udt-accent` restarts it | +| Firefox | `udt-accent` runs `pywalfox update` | | Hyprland | `hyprctl reload` | | waybar | `killall -SIGUSR2 waybar` | | kitty | `pkill -USR1 -x kitty` | diff --git a/bin/udt-accent b/bin/udt-accent index e88a512..703f483 100755 --- a/bin/udt-accent +++ b/bin/udt-accent @@ -12,6 +12,7 @@ running `wal -i`, because `wal -i` rewrites the whole ~/.cache/wal directory including the terminal's ANSI colors. See the design spec for why that matters. """ +import json import math import os import subprocess @@ -43,6 +44,19 @@ MIN_CHROMA = 10.0 OUTPUT = Path.home() / ".cache" / "wal" / "udt-accent.rasi" BORDER_OUTPUT = Path.home() / ".cache" / "wal" / "udt-border.lua" DUNSTRC = Path.home() / ".cache" / "wal" / "dunstrc" +COLORS_JSON = Path.home() / ".cache" / "wal" / "colors.json" + +# Catppuccin Macchiato, in pywal's slot order. Firefox is themed from this +# via pywalfox, which reads colors.json and nothing else. +MACCHIATO = { + "background": "#24273a", "foreground": "#cad3f5", "cursor": "#f4dbd6", + "colors": [ + "#494d64", "#ed8796", "#a6da95", "#eed49f", + "#8aadf4", "#f5bde6", "#8bd5ca", "#b8c0e0", + "#5b6078", "#ed8796", "#a6da95", "#eed49f", + "#8aadf4", "#f5bde6", "#8bd5ca", "#a5adcb", + ], +} def _to_lab(hexval): @@ -166,6 +180,46 @@ def write_border(name): raise +def write_colors_json(name, image): + """Rewrite colors.json as Macchiato with the accent in the highlight slots. + + pywalfox reads this file and nothing else, so this is how Firefox tracks the + wallpaper. pywal wrote the file moments earlier with wallpaper-derived ANSI + colours; this replaces them wholesale, which is the point: the terminal + palette stays fixed Macchiato while only the accent moves. + """ + hexval = ACCENTS[name] + colors = list(MACCHIATO["colors"]) + # Slots 4 and 12 are pywalfox's link/highlight colour. + colors[4] = colors[12] = hexval + + doc = { + "wallpaper": str(image), + "alpha": "100", + "special": { + "background": MACCHIATO["background"], + "foreground": MACCHIATO["foreground"], + "cursor": hexval, + }, + "colors": {f"color{i}": c for i, c in enumerate(colors)}, + } + + fd, tmp = tempfile.mkstemp(dir=str(COLORS_JSON.parent), suffix=".tmp") + try: + with os.fdopen(fd, "w") as handle: + json.dump(doc, handle, indent=4) + handle.write("\n") + os.replace(tmp, COLORS_JSON) + except BaseException: + if os.path.exists(tmp): + os.unlink(tmp) + raise + + # Firefox only picks the new colours up when pywalfox pushes them. Never + # fatal: pywalfox may not be installed, and the desktop theme is unaffected. + subprocess.run(["pywalfox", "update"], capture_output=True, check=False) + + def write_dunst(name): """Substitute the accent into the dunst config pywal just rendered. @@ -209,6 +263,7 @@ def main(image): write_accent(name) write_border(name) write_dunst(name) + write_colors_json(name, image) # Hyprland only rereads its config on request, and may not be running. subprocess.run(["hyprctl", "reload"], capture_output=True, check=False) |
