aboutsummaryrefslogtreecommitdiffstats
path: root/bin/wb-icon
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-17 08:07:00 +0200
committerDanilo M. <danix@danix.xyz>2026-09-17 08:07:00 +0200
commit121235db5ca23e53e0dad3a402c521dc7a940fbc (patch)
treea899aff77c6cd08ee763d418d4904e51eaf3bb5c /bin/wb-icon
parent2c23c9cc2fa5c26e408e7276f7da7d0cb37922d6 (diff)
downloadwaybar-theme-udt-121235db5ca23e53e0dad3a402c521dc7a940fbc.tar.gz
waybar-theme-udt-121235db5ca23e53e0dad3a402c521dc7a940fbc.zip
feat(icons): read the icon theme from gsettings
The icon theme name was hardcoded in three places (bin/wb-icon, modules/extras/taskbar.jsonc and install.sh), so switching themes in the appearance drawer was silently reverted as far as this bar was concerned. wb-icon now reads org.gnome.desktop.interface icon-theme and gains two modes for install.sh: --path NAME prints one icon's absolute path, --theme prints the resolved theme name. Icons are resolved per name rather than by substituting a directory prefix, because themes disagree about both subdirectory and file extension: the Suru themes keep web-browser at categories/22/*.svg, elementary-xfce at apps/22/*.png. Only a real GTK lookup knows the path. styles/modules.css therefore carries @ICON:name@ placeholders and modules/extras/taskbar.jsonc carries @ICON_THEME@, both filled at install time. taskbar.jsonc is generated rather than symlinked for that reason, and install.sh removes the old symlink first so the redirect cannot overwrite the committed source. A theme missing one of the twenty names fails the install at the --selftest step rather than drawing empty pills. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'bin/wb-icon')
-rwxr-xr-xbin/wb-icon57
1 files changed, 52 insertions, 5 deletions
diff --git a/bin/wb-icon b/bin/wb-icon
index 9e011b9..1d76369 100755
--- a/bin/wb-icon
+++ b/bin/wb-icon
@@ -10,6 +10,7 @@
#
# wb-icon volume # reads wpctl, prints the matching icon
# wb-icon mic
+# wb-icon --path NAME # absolute path of one icon, for install.sh
# wb-icon --selftest # every name this bar asks for must resolve
#
# Icons keep their own colours: this desktop's icon theme draws them with
@@ -24,9 +25,29 @@ import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk # noqa: E402 (must follow require_version)
-# The icon theme to draw from. Kept in one place because changing it is a
-# single edit, and because --selftest needs the same value the modules use.
-THEME = "Material-Black-Plum-Suru"
+# The icon theme to draw from: whatever the desktop is set to. The appearance
+# drawer switches it through gsettings, so reading that key is what keeps this
+# bar following a switch instead of silently pointing at the old theme.
+#
+# The fallback only matters when gsettings is unreadable; GTK falls back to
+# hicolor on its own if the named theme is missing.
+FALLBACK_THEME = "Adwaita"
+
+
+def icon_theme():
+ """The desktop's icon theme name, per gsettings."""
+ try:
+ out = subprocess.run(
+ ["gsettings", "get", "org.gnome.desktop.interface", "icon-theme"],
+ capture_output=True, text=True, timeout=2,
+ ).stdout.strip()
+ except (OSError, subprocess.SubprocessError):
+ return FALLBACK_THEME
+ # gsettings quotes its answer: 'Material-Black-Plum-Suru'
+ return out.strip("'\"") or FALLBACK_THEME
+
+
+THEME = icon_theme()
SIZE = 22
@@ -47,7 +68,13 @@ ICONS = {
def lookup(name):
- """Absolute path of an icon in THEME, or None."""
+ """Absolute path of an icon in THEME, or None.
+
+ GTK resolves the theme's own layout, so this works across icon themes
+ that disagree about subdirectory and file extension: the Suru themes keep
+ web-browser under categories/22/*.svg, elementary-xfce under apps/22/*.png.
+ Nothing outside this function may assume a path shape.
+ """
theme = Gtk.IconTheme.new()
theme.set_custom_theme(THEME)
info = theme.lookup_icon(name, SIZE, 0)
@@ -138,7 +165,8 @@ def selftest():
def main(argv):
if len(argv) < 2 or argv[1] in ("-h", "--help"):
- print(__doc__ or "usage: wb-icon <volume|mic|idle|--selftest> [state]")
+ print(__doc__ or
+ "usage: wb-icon <volume|mic|--path NAME|--theme|--selftest>")
return 0
what = argv[1]
@@ -146,6 +174,25 @@ def main(argv):
if what == "--selftest":
return selftest()
+ # install.sh bakes icon paths into the generated stylesheet, because CSS
+ # cannot look an icon up by name. It asks here so that the theme is
+ # resolved in exactly one place.
+ if what == "--path":
+ if len(argv) < 3:
+ print("wb-icon: --path needs an icon name", file=sys.stderr)
+ return 2
+ path = lookup(argv[2])
+ if not path:
+ print(f"wb-icon: no icon named {argv[2]!r} in {THEME}",
+ file=sys.stderr)
+ return 1
+ print(path)
+ return 0
+
+ if what == "--theme":
+ print(THEME)
+ return 0
+
if what == "volume":
pct, muted = wpctl("@DEFAULT_AUDIO_SINK@")
if pct is None: