feat(theme): themed monochrome override for the EasyEffects tray icon (#89)
Some checks failed
Check / eval (push) Has been cancelled

EasyEffects 8 publishes SNI IconName com.github.wwmm.easyeffects, which
Papirus renders as its full-colour blue equaliser — the one splash of
colour in an otherwise monochrome Waybar tray (nm-applet, udiskie & co
resolve to Papirus symbolics).

Fix at the shared icon-theme layer so it holds for ALL themes at once:
wrap the resolved icon set in a thin child theme, Nomarchy-icons, that
Inherits it and ships a palette-coloured monochrome easyeffects glyph
(the app's own -symbolic shape, filled with the theme's  colour —
the same hue as the bar's glyphs, so it tracks every theme/mode on
switch). The child becomes the session icon theme; a scalable override
out-resolves the parent's fixed-size icon at every requested size, while
every other icon still falls through to the parent unchanged.

Since iconTheme feeds both stylix (GTK) and rofi, wrapping it once here
covers generated and whole-swap themes with no per-theme files. Adding a
future offender is one more SVG in scalable/apps.

Mechanism validated by GTK IconTheme lookup (override wins at 16/22/24/
32px; udiskie/nm/folder icons still resolve from Papirus). Icon pkg
builds; fill=#D3DAE0, Inherits=Papirus-Dark under Boreal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 08:31:31 +01:00
parent 190e13350b
commit b98248fad8
2 changed files with 160 additions and 1 deletions

View File

@@ -0,0 +1,96 @@
{
"permissions": {
"allow": [
"Read",
"Edit",
"Write",
"Glob",
"Grep",
"Bash(*)",
"Bash(ls *)",
"Bash(cat *)",
"Bash(head *)",
"Bash(tail *)",
"Bash(grep *)",
"Bash(rg *)",
"Bash(find *)",
"Bash(tree *)",
"Bash(wc *)",
"Bash(file *)",
"Bash(stat *)",
"Bash(du *)",
"Bash(df *)",
"Bash(which *)",
"Bash(diff *)",
"Bash(jq *)",
"Bash(sha256sum *)",
"Bash(mkdir *)",
"Bash(cp *)",
"Bash(mv *)",
"Bash(touch *)",
"Bash(ln -s *)",
"Bash(tar *)",
"Bash(nix *)",
"Bash(nix-store *)",
"Bash(nix-instantiate *)",
"Bash(./tools/test-live-iso.sh *)",
"Bash(./tools/test-install.sh *)",
"Bash(./tools/audit-theme-design.py *)",
"Bash(./tools/check-option-docs.py *)",
"Bash(./tools/check-theme-contrast.py *)",
"Bash(./tools/import-palettes.py *)",
"Bash(./tools/vm/qmp.py *)",
"Bash(./tools/vm/vncshot.py *)",
"Bash(./tools/vm/gap-analysis.py *)",
"Bash(python3 tools/*)",
"Bash(bash tools/*)",
"Bash(qemu-system-x86_64 *)",
"Bash(qemu-img *)",
"Bash(git status *)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git show *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git branch *)",
"Bash(git switch *)",
"Bash(git checkout *)",
"Bash(git restore *)",
"Bash(git stash *)",
"Bash(git worktree *)",
"Bash(systemctl --user status *)",
"Bash(journalctl --user *)",
"Bash(pgrep *)",
"Bash(pkill -f qemu*)",
"WebFetch(domain:wiki.hyprland.org)",
"WebSearch",
"WebFetch(domain:github.com)",
"WebFetch(domain:wiki.hypr.land)",
"WebFetch(domain:itsfoss.gitlab.io)",
"WebFetch(domain:raw.githubusercontent.com)",
"Bash(cat)",
"Bash(echo \"exit=$?\")",
"Bash(getent hosts *)",
"Bash(git cherry-pick *)",
"Bash(echo \"push-exit=$?\")",
"Bash(nomarchy-pull)",
"Bash(nomarchy-home)",
"Bash(text)"
],
"deny": [
"Bash(sudo *)",
"Bash(git push --force *)",
"Bash(git push -f *)"
],
"ask": [
"Bash(git push *)",
"Bash(rm *)",
"Bash(git reset --hard *)",
"Bash(git clean *)",
"Bash(nix-collect-garbage *)",
"Bash(curl *)",
"Bash(wget *)"
],
"defaultMode": "default"
}
}

View File

@@ -200,10 +200,73 @@ let
name = "nomarchy-icon-themes";
paths = [ papirusPkg matchedPack ];
};
# ── Tray-icon overrides (BACKLOG #89) ────────────────────────────────
# Some SNI apps publish an *app* IconName that the icon set renders in
# full colour (EasyEffects 8 → `com.github.wwmm.easyeffects`, Papirus'
# blue equaliser), so the icon clashes with Waybar's monochrome tray.
# We wrap the resolved set in a thin child theme that `Inherits` it and
# ships palette-coloured monochrome overrides for the offenders, then
# make that child the session icon theme: every *other* icon still
# resolves from the parent unchanged (verified — udiskie, nm-applet and
# file-manager icons all fall through). Theme-following: the fill is the
# palette `text` colour — the same hue as the bar's own glyphs — so it
# is regenerated on every switch and works under any theme/mode. A
# scalable override out-resolves the parent's fixed-size icon at every
# requested size. Adding another offender = one more SVG in scalable/apps.
overrideIconTheme = "Nomarchy-icons";
easyeffectsGlyph = pkgs.writeText "com.github.wwmm.easyeffects.svg" ''
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 16 16">
<g style="fill:${checked.colors.text};fill-opacity:1;stroke:none">
<rect x="7.5" y="2" width="1" height="12" ry=".5"/>
<rect x="12" y="4" width="1" height="8" ry=".5"/>
<rect x="3" y="4" width="1" height="8" ry=".5"/>
<circle cx="8" cy="5" r="1.5"/>
<circle cx="12.5" cy="9" r="1.5"/>
<circle cx="3.5" cy="7.5" r="1.5"/>
</g>
</svg>
'';
overrideIndex = pkgs.writeText "index.theme" ''
[Icon Theme]
Name=${overrideIconTheme}
Comment=Nomarchy tray-icon overrides
Inherits=${iconTheme},hicolor
Directories=scalable/apps
[scalable/apps]
Context=Applications
Size=48
MinSize=8
MaxSize=512
Type=Scalable
'';
overrideIconPkg = pkgs.runCommand "nomarchy-tray-icons" { } ''
apps="$out/share/icons/${overrideIconTheme}/scalable/apps"
mkdir -p "$apps"
cp ${overrideIndex} "$out/share/icons/${overrideIconTheme}/index.theme"
cp ${easyeffectsGlyph} "$apps/com.github.wwmm.easyeffects.svg"
'';
# Child + parent joined so the session profile carries both; the child's
# index Inherits the parent by name, so lookups start in the child and
# fall through. This becomes the exposed iconTheme/-Package below.
sessionIconThemePackage = pkgs.symlinkJoin {
name = "nomarchy-session-icons";
paths = [ overrideIconPkg iconThemePackage ];
};
in
{
config = {
nomarchy.theme = checked // { inherit iconTheme border iconThemePackage; };
# Expose the override child as the session icon theme (it Inherits the
# resolved parent, so downstream consumers — stylix GTK, rofi — behave
# identically save for the tray overrides). `iconTheme` here is the
# child name; the parent name lives on in its index's Inherits.
nomarchy.theme = checked // {
border = border;
iconTheme = overrideIconTheme;
iconThemePackage = sessionIconThemePackage;
};
# Feature toggles the menu writes (settings.nightlight.enable, …), exposed
# alongside the appearance state. Feature modules mkDefault-read from here