aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AGENTS.md29
-rwxr-xr-xbin/udt-accent55
2 files changed, 75 insertions, 9 deletions
diff --git a/AGENTS.md b/AGENTS.md
index cbb4c14..bd67064 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -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)