aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-16 08:27:27 +0200
committerDanilo M. <danix@danix.xyz>2026-09-16 08:27:27 +0200
commite520610f5bb3512a4243f2f14f016cdd02badbcd (patch)
treef35eeb1279d6bcf5a928c1215bdee985e7a3640f
parenta183b4a054d96f310d867b79d7b9fb7a6b875bb8 (diff)
downloadunified-desktop-theme-e520610f5bb3512a4243f2f14f016cdd02badbcd.tar.gz
unified-desktop-theme-e520610f5bb3512a4243f2f14f016cdd02badbcd.zip
refactor(dunst): drop dunst as a consumer, quickshell presents now
dunst no longer runs on this desktop. notifyd owns org.freedesktop.Notifications and the quickshell notifications shell draws the balloons, reading the palette from ~/.cache/wal/udt-palette.qml like every other quickshell component. So the whole dunst path was generating a config nothing read. It was also actively wrong. pywal rendered ~/.cache/wal/dunstrc from the installed template, then wal.sh restarted dunst on it while @ACCENT@ was still an unsubstituted placeholder, and udt-accent restarted it a second time after substituting. Two restarts per wallpaper change, the first on a broken config, for a daemon that could not claim the bus name anyway. Removes gen_dunst and its TARGETS entry, write_dunst and DUNSTRC, the install block, templates/dunstrc.in and the gitignore entry. The reload table now lists quickshell, which needs no signal: it watches the generated palette and re-reads it in place. The [state] roles stay. They were never dunst-only; waybar module states and conky warnings use the same four. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
-rw-r--r--.gitignore1
-rw-r--r--AGENTS.md22
-rw-r--r--README.md14
-rwxr-xr-xbin/udt-accent36
-rwxr-xr-xbin/udt-palette20
-rw-r--r--docs/MIGRATION.md2
-rwxr-xr-xinstall.sh19
-rw-r--r--palette/roles-frappe.conf2
-rw-r--r--palette/roles-macchiato.conf2
-rw-r--r--palette/roles-mocha.conf2
-rw-r--r--templates/dunstrc.in75
11 files changed, 35 insertions, 160 deletions
diff --git a/.gitignore b/.gitignore
index 6ffe055..c9b7fbb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,7 +5,6 @@ __pycache__/
# Generated by udt-palette from palette/<scheme>.conf. Regenerated by
# install.sh, so tracking them would turn every scheme switch into a diff.
/rofi/udt/palette.rasi
-/templates/dunstrc
/templates/conky.conf
/templates/waybar/theme.css
/templates/terminal/kitty-theme.conf
diff --git a/AGENTS.md b/AGENTS.md
index 88a0123..c7f06fe 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -5,9 +5,9 @@ Guidance for agents working in this repository.
## What this is
One visual identity for a Hyprland desktop: Catppuccin Macchiato, Noto Sans for
-UI text, Inconsolata Nerd Font Mono for monospace. It covers rofi, dunst,
-Hyprland window borders, conky, Qt5/Qt6, GTK3/GTK4, waybar, kitty, Sublime Text
-and neovim.
+UI text, Inconsolata Nerd Font Mono for monospace. It covers rofi, Hyprland
+window borders, conky, Qt5/Qt6, GTK3/GTK4, waybar, kitty, Sublime Text and
+neovim.
The repo holds the canonical copies. `./install.sh` symlinks them into place, so
the working config cannot drift from what is committed. Everything outside
@@ -38,7 +38,7 @@ All nine are dark. A light scheme is not a role remap: homepage is pinned
Generated files are gitignored, because tracking them would turn every scheme
switch into a diff. Editing one is pointless: the next install overwrites it.
-The generated set is `rofi/udt/palette.rasi`, `templates/dunstrc`,
+The generated set is `rofi/udt/palette.rasi`,
`templates/conky.conf`, `templates/waybar/theme.css`,
`templates/terminal/kitty-theme.conf`, `templates/homepage/custom.css`,
`templates/kvantum/theme.{kvconfig,svg}`,
@@ -113,11 +113,10 @@ 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/wal/udt-accent.rasi` (rofi),
-`~/.cache/wal/udt-border.lua` (Hyprland), the accent substitution in
-`~/.cache/wal/dunstrc`, `~/.cache/wal/colors.json` (Firefox, via
-pywalfox), `~/.cache/wal/udt-palette.qml` (quickshell), and the accent
-substitution in Sublime's installed
+It writes five things: `~/.cache/wal/udt-accent.rasi` (rofi),
+`~/.cache/wal/udt-border.lua` (Hyprland), `~/.cache/wal/colors.json`
+(Firefox, via pywalfox), `~/.cache/wal/udt-palette.qml` (quickshell), and
+the accent substitution in Sublime's installed
`Packages/User/udt.sublime-color-scheme`.
**Sublime's accent is replaced, not substituted into a placeholder.** Its
@@ -150,7 +149,8 @@ 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, Sublime's
+Not everything tracks the wallpaper. rofi, quickshell, Hyprland borders,
+Sublime's
colour scheme and Firefox do; conky, Qt, GTK, waybar and Sublime's UI chrome 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,
@@ -232,7 +232,7 @@ The table is what it does, and what to run if you change a config by hand.
| | How |
| --- | --- |
| rofi | nothing; the theme is read per launch |
-| dunst | `udt-accent` restarts it |
+| quickshell | nothing; it watches the generated palette and re-reads it |
| Firefox | `udt-accent` runs `pywalfox update` |
| Hyprland | `hyprctl reload` |
| waybar | `killall -SIGUSR2 waybar` |
diff --git a/README.md b/README.md
index c949047..04a7dcc 100644
--- a/README.md
+++ b/README.md
@@ -6,8 +6,8 @@ fixed base, Noto Sans for UI text, Inconsolata Nerd Font Mono for monospace.
The accent color follows the current wallpaper, but is always snapped to a real
Macchiato accent, so it can never render as unreadable.
-Phase 1 covers rofi. Later phases extend the same palette to waybar, dunst,
-conky, hyprland and quickshell.
+Phase 1 covers rofi. Later phases extend the same palette to waybar, conky,
+hyprland and quickshell.
Quickshell reads the palette rather than restating it: `udt-accent` writes
`~/.cache/wal/udt-palette.qml` from `rofi/udt/palette.rasi`, and the
@@ -43,11 +43,11 @@ and run `./install.sh`. That file is yours, not the repo's: `install.sh`
creates it on a first run and never overwrites it, so switching scheme leaves
the working tree clean.
-`install.sh` reloads whatever is running (waybar, kitty, Hyprland, dunst,
-conky), so the switch is visible immediately. Qt and GTK apps only reread a
-theme on startup, so those need restarting by hand. Ships with `macchiato`, `tokyo-night`, `nord` and
-`dracula`; rofi, dunst, conky, waybar, kitty, Firefox and quickshell all
-follow.
+`install.sh` reloads whatever is running (waybar, kitty, Hyprland, conky), so
+the switch is visible immediately. Qt and GTK apps only reread a theme on
+startup, so those need restarting by hand. Ships with `macchiato`,
+`tokyo-night`, `nord` and `dracula`; rofi, conky, waybar, kitty, Firefox and
+quickshell all follow.
A scheme is two files: `palette/<name>.conf` for the colours under the
scheme's own names, and `palette/roles-<name>.conf` saying what each is for.
diff --git a/bin/udt-accent b/bin/udt-accent
index 1a542a6..3cb9438 100755
--- a/bin/udt-accent
+++ b/bin/udt-accent
@@ -31,7 +31,6 @@ 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"
SUBLIME = (Path.home() / ".config" / "sublime-text" / "Packages" / "User"
/ "udt.sublime-color-scheme")
QML_OUTPUT = Path.home() / ".cache" / "wal" / "udt-palette.qml"
@@ -258,41 +257,17 @@ def write_colors_json(name, image):
subprocess.run(["pywalfox", "update"], capture_output=True, check=False)
-def write_dunst(name):
- """Substitute the accent into the dunst config pywal just rendered.
-
- pywal owns that file, so this runs after it and rewrites in place. A
- missing file is not an error: dunst simply may not be configured here.
- """
- try:
- text = DUNSTRC.read_text()
- except FileNotFoundError:
- return
-
- if "@ACCENT@" not in text:
- return
-
- write_atomic(DUNSTRC, text.replace("@ACCENT@", ACCENTS[name]))
-
- # Restart dunst so it rereads the file. It must be started again, not just
- # killed: nothing else respawns it, and a dead dunst means no notifications
- # at all.
- if subprocess.run(["pkill", "-x", "dunst"], capture_output=True).returncode == 0:
- subprocess.Popen(["dunst"], start_new_session=True,
- stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
-
-
def write_sublime(name):
"""Substitute the accent into the Sublime colour scheme install.sh copied.
- In place, like dunst: Sublime colour schemes do not cascade, so the accent
- cannot arrive as a second file. Sublime watches Packages/User and reloads a
+ In place: Sublime colour schemes do not cascade, so the accent cannot
+ arrive as a second file. Sublime watches Packages/User and reloads a
scheme when its file changes, so no signal is needed. A missing file is not
an error, Sublime simply may not be installed here.
- Unlike dunst, this reads the installed copy and has nowhere to recover
- @ACCENT@ from once substituted, so the previous accent is replaced by
- matching the variable line rather than a placeholder.
+ This reads the installed copy and has nowhere to recover @ACCENT@ from
+ once substituted, so the previous accent is replaced by matching the
+ variable line rather than a placeholder.
"""
try:
text = SUBLIME.read_text()
@@ -316,7 +291,6 @@ def main(image):
write_accent(name)
write_border(name)
write_qml(name)
- write_dunst(name)
write_sublime(name)
write_colors_json(name, image)
diff --git a/bin/udt-palette b/bin/udt-palette
index 3fcb355..09731de 100755
--- a/bin/udt-palette
+++ b/bin/udt-palette
@@ -416,19 +416,6 @@ def gen_homepage(res, scheme, palette):
"""
-def gen_dunst(res, scheme, palette, template):
- """dunst: substitute colours into the shipped template.
-
- Kept as a template rather than fully generated: dunstrc is mostly geometry
- and behaviour that has nothing to do with colour. @ACCENT@ is left alone,
- because udt-accent substitutes it per wallpaper after pywal renders it.
- """
- out = template.replace("@SCHEME@", scheme)
- for role in ("bg", "bg_alt", "fg", "fg_dim", "border", "critical"):
- out = out.replace(f"@{role.upper()}@", hex6(res[role]))
- return out
-
-
def gen_sublime(res, scheme, palette, template):
"""Sublime Text: substitute the palette into the colour scheme.
@@ -437,9 +424,9 @@ def gen_sublime(res, scheme, palette, template):
costs no new roles and every shipped scheme satisfies it without touching
nine role maps.
- @ACCENT@ is left alone for udt-accent, exactly as in the dunst template:
- Sublime colour schemes do not cascade, so the accent cannot arrive as a
- second file and has to be substituted into this one.
+ @ACCENT@ is left alone for udt-accent: Sublime colour schemes do not
+ cascade, so the accent cannot arrive as a second file and has to be
+ substituted into this one.
"""
out = template.replace("@SCHEME@", scheme)
for role in ("bg", "bg_alt", "bg_deep", "surface", "surface_alt",
@@ -580,7 +567,6 @@ TARGETS = [
("rofi/udt/palette.rasi", gen_rofi, None),
("templates/waybar/theme.css", gen_waybar, None),
("templates/terminal/kitty-theme.conf", gen_kitty, None),
- ("templates/dunstrc", gen_dunst, "templates/dunstrc.in"),
("templates/conky.conf", gen_conky, "templates/conky.conf.in"),
("bin/udt_colors.py", gen_accent_py, None),
("templates/homepage/custom.css", gen_homepage, None),
diff --git a/docs/MIGRATION.md b/docs/MIGRATION.md
index 1f5d93b..e78b766 100644
--- a/docs/MIGRATION.md
+++ b/docs/MIGRATION.md
@@ -108,7 +108,7 @@ Verify with:
`~/.xprofile`, an X11 leftover that nothing under Wayland reads. It started
`picom`, `xscreensaver`, `numlockx`, `clipmenud`, `redshift-gtk`, `setxkbmap`,
`xrdb` and `lightsOn.sh`, none of which were running, and it also started
-`dunst`, which is running but is started by `udt-accent` now. Nothing sources
+`dunst`, the notification daemon at the time. Nothing sources
the file: no reference in `.bashrc`, `.bash_profile`, `/etc/profile.d/` or the
Hyprland config.
diff --git a/install.sh b/install.sh
index 3371bba..e5e583d 100755
--- a/install.sh
+++ b/install.sh
@@ -135,7 +135,7 @@ if command -v scp >/dev/null 2>&1; then
fi
# Reload what is running. Writing the configs is not enough: waybar, kitty and
-# Hyprland reread on a signal, dunst and conky only on a restart, and rofi
+# Hyprland reread on a signal, conky only on a restart, and rofi
# reads its theme per launch so it needs nothing. Each is guarded, because none
# of them is necessarily running, and a missing one is not an error.
reloaded=""
@@ -143,20 +143,11 @@ pgrep -x waybar >/dev/null 2>&1 && killall -SIGUSR2 waybar 2>/dev/null && reload
pgrep -x kitty >/dev/null 2>&1 && pkill -USR1 -x kitty 2>/dev/null && reloaded="$reloaded kitty"
command -v hyprctl >/dev/null 2>&1 && hyprctl reload >/dev/null 2>&1 && reloaded="$reloaded hyprland"
-# dunst reads ~/.cache/wal/dunstrc, which pywal renders from its own template
-# dir. Install the generated config into both: the template so a later `wal`
-# run keeps it, and the cache file so this install reaches dunst now. Both
-# still carry @ACCENT@, which udt-accent substitutes just below.
-if [ -f templates/dunstrc ]; then
- mkdir -p "$HOME/.config/wal/templates"
- cp templates/dunstrc "$HOME/.config/wal/templates/dunstrc"
- cp templates/dunstrc "$HOME/.cache/wal/dunstrc"
-fi
-
-# udt-accent regenerates the accent and restarts dunst itself. It needs a
-# wallpaper to read; without one the accent keeps its current value.
+# udt-accent regenerates the accent. It needs a wallpaper to read; without one
+# the accent keeps its current value. Quickshell watches the palette it writes,
+# so notifications and the rest of the shell follow without a restart.
if command -v udt-accent >/dev/null 2>&1 && [ -e "$HOME/.cache/wal/wpaper" ]; then
- udt-accent "$HOME/.cache/wal/wpaper" >/dev/null 2>&1 && reloaded="$reloaded accent+dunst"
+ udt-accent "$HOME/.cache/wal/wpaper" >/dev/null 2>&1 && reloaded="$reloaded accent"
fi
# conky has no hot-reload and nothing respawns it, so it is restarted only if
diff --git a/palette/roles-frappe.conf b/palette/roles-frappe.conf
index 20d1092..4addbdd 100644
--- a/palette/roles-frappe.conf
+++ b/palette/roles-frappe.conf
@@ -20,7 +20,7 @@ fg_dim = subtext0
fg_faint = overlay0
# The one colour that tracks the wallpaper. udt-accent overrides this per
-# wallpaper for rofi, dunst, Hyprland and Firefox; the value here is the
+# wallpaper for rofi, quickshell, Hyprland and Firefox; the value here is the
# fallback, and what the consumers that do not track it sit on permanently.
accent = lavender
diff --git a/palette/roles-macchiato.conf b/palette/roles-macchiato.conf
index 9cecca9..ec16aef 100644
--- a/palette/roles-macchiato.conf
+++ b/palette/roles-macchiato.conf
@@ -20,7 +20,7 @@ fg_dim = subtext0
fg_faint = overlay0
# The one colour that tracks the wallpaper. udt-accent overrides this per
-# wallpaper for rofi, dunst, Hyprland and Firefox; the value here is the
+# wallpaper for rofi, quickshell, Hyprland and Firefox; the value here is the
# fallback, and what the consumers that do not track it sit on permanently.
accent = lavender
diff --git a/palette/roles-mocha.conf b/palette/roles-mocha.conf
index 4d4e434..7e3af92 100644
--- a/palette/roles-mocha.conf
+++ b/palette/roles-mocha.conf
@@ -20,7 +20,7 @@ fg_dim = subtext0
fg_faint = overlay0
# The one colour that tracks the wallpaper. udt-accent overrides this per
-# wallpaper for rofi, dunst, Hyprland and Firefox; the value here is the
+# wallpaper for rofi, quickshell, Hyprland and Firefox; the value here is the
# fallback, and what the consumers that do not track it sit on permanently.
accent = lavender
diff --git a/templates/dunstrc.in b/templates/dunstrc.in
deleted file mode 100644
index 192975b..0000000
--- a/templates/dunstrc.in
+++ /dev/null
@@ -1,75 +0,0 @@
-# See dunst(5) for all configuration options
-[global]
- monitor = 1
- follow = none
- width = 300
- height = (0, 300)
- origin = top-right
- offset = (10, 50)
- scale = 0
- notification_limit = 0
- progress_bar = true
- progress_bar_height = 10
- progress_bar_frame_width = 1
- progress_bar_min_width = 150
- progress_bar_max_width = 300
- indicate_hidden = yes
- transparency = 15
- separator_height = 2
- padding = 8
- horizontal_padding = 8
- text_icon_padding = 0
- frame_width = 3
- frame_color = "@ACCENT@"
- gap_size = 0
- separator_color = frame
- sort = yes
- font = Noto Sans 12
- line_height = 0
- markup = full
- format = "<b>%a</b>\n<i>%s</i>%p %n\n%b"
- alignment = left
- vertical_alignment = center
- show_age_threshold = 60
- ellipsize = middle
- ignore_newline = no
- stack_duplicates = true
- hide_duplicate_count = false
- show_indicators = yes
- enable_recursive_icon_lookup = true
- icon_theme = MB-Blueberry-Suru-GLOW
- icon_position = left
- icon_corner_radius = 5
- min_icon_size = 32
- max_icon_size = 128
- icon_path = ~/.local/share/icons/MB-Blueberry-Suru-GLOW/status/48/:/usr/share/icons/MB-Blueberry-Suru-GLOW/devices/48/
- sticky_history = yes
- history_length = 20
- dmenu = /usr/bin/rofi -theme ~/.config/rofi/udt/list.rasi -dmenu -p dunst
- browser = /usr/bin/xdg-open
- always_run_script = true
- title = Dunst
- class = Dunst
- corner_radius = 10
- ignore_dbusclose = false
- mouse_left_click = context, close_current
- mouse_middle_click = do_action, close_current
- mouse_right_click = close_all
-# to have a consistent behaviour across releases.
-[experimental]
- per_monitor_dpi = false
-[urgency_low]
- background = "@BG_ALT@"
- foreground = "@FG_DIM@"
- frame_color = "@BORDER@"
- timeout = 10
-[urgency_normal]
- background = "@BG@"
- foreground = "@FG@"
- frame_color = "@ACCENT@"
- timeout = 10
-[urgency_critical]
- background = "@BG@"
- foreground = "@FG@"
- frame_color = "@CRITICAL@"
- timeout = 0