fix(waybar): carry tray-menu counter-rules in the bar stylesheet itself
Some checks failed
Check / eval (push) Has been cancelled

The e8658fe cure (USER-priority gtk.css counter-rules) verified in a
plain GTK app but not in the real Waybar-hosted nm-applet menu: Waybar
adds its provider at GTK_STYLE_PROVIDER_PRIORITY_USER as well
(src/client.cpp), and in practice its rules win the tie against
~/.config/gtk-3.0/gtk.css on GTK 3.24 — reproduced by injecting the
bar stylesheet above USER priority: arrow, checkmark and separator all
vanish, matching the live menu exactly.

The only placement that wins at ANY provider priority is inside the
same stylesheet: after each '*' reset, restore the CSS-sized menu
nodes (menuitem arrow 16px, check/radio 14px, separator 1px line) and
give menus a text face instead of the bar's glyph font. Applied to
boreal + executive-slate waybar.css and waybar.nix generatedStyle;
stylix.nix comment corrected (its rules now cover ordinary GTK apps
only).

Ground truth checked over D-Bus first: nm-applet exports per-network
Wi-Fi icons as dbusmenu icon-data, and with gtk-menu-images=1 the
connected network's icon already renders in the live menu — the
remaining loss was arrows/checks/separators, all CSS-box nodes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-12 08:15:08 +01:00
parent 0416eafd71
commit 8eb672bada
4 changed files with 61 additions and 19 deletions

View File

@@ -70,13 +70,13 @@ in
} }
/* Submenu disclosure arrows need no icon remap: pan-end-symbolic /* Submenu disclosure arrows need no icon remap: pan-end-symbolic
resolves via Papirus-Dark's breeze-dark inheritance. The resolves via Papirus-Dark's breeze-dark inheritance. The
"invisible arrow" bug is Waybar's process-wide stylesheet: "invisible arrow" bug was Waybar's process-wide stylesheet:
its `* { min-height: 0; }` reset also hits the SNI tray menus its `* { min-height: 0; }` reset also hits the SNI tray menus
Waybar hosts and collapses the arrow node. This file loads at Waybar hosts and collapses arrow/check nodes. NB: this file
USER priority (~/.config/gtk-3.0/gtk.css), which outranks any CANNOT fix that Waybar adds its provider at USER priority
waybar.css (APPLICATION priority) restore the arrow's box too and wins the tie in practice (GTK 3.24, observed), so
here, exactly like the check/radio rule below already does every waybar.css carries its own menu counter-rules. The
for the same collapse. */ rules here cover menus in ordinary GTK apps only. */
menu menuitem arrow, .menu menuitem arrow, .context-menu menuitem arrow { menu menuitem arrow, .menu menuitem arrow, .context-menu menuitem arrow {
min-width: 16px; min-width: 16px;
min-height: 16px; min-height: 16px;

View File

@@ -382,17 +382,28 @@ let
${colorDefs} ${colorDefs}
/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too /* NB: this `*` reset reaches the SNI tray menus Waybar hosts too
(its stylesheet applies process-wide) the menu-side damage (its stylesheet applies process-wide, at a priority user gtk.css
(collapsed arrows/checks) is undone by USER-priority counter-rules cannot out-rank). The menu block right below undoes the damage
in stylix.nix, which outrank any waybar.css. Do NOT scope this to keep the two in sync. Do NOT scope `*` to window#waybar instead:
window#waybar: the id's specificity would beat the class rules the id's specificity would beat the class rules below and wreck
below (pills, workspaces) and wreck the bar. */ the bar. Whole-swap theme waybar.css files carry the same pair. */
* { * {
font-family: "${t.fonts.ui}", "${t.fonts.mono}"; font-family: "${t.fonts.ui}", "${t.fonts.mono}";
font-size: ${toString t.fonts.size}pt; font-size: ${toString t.fonts.size}pt;
min-height: 0; min-height: 0;
} }
/* Tray menus: undo the `*` reset same stylesheet, higher
specificity. Arrows/checks/separators are CSS-sized nodes;
min-height 0 makes them invisible. */
menu menuitem arrow { min-width: 16px; min-height: 16px; }
menu check, menu radio { min-width: 14px; min-height: 14px; }
menu separator {
min-height: 1px;
margin: 5px 0;
background: alpha(@text, 0.15);
}
window#waybar { window#waybar {
background: alpha(@base, 0.85); background: alpha(@base, 0.85);
color: @text; color: @text;

View File

@@ -23,10 +23,12 @@
@define-color warn #E6C384; @define-color warn #E6C384;
@define-color bad #E2818A; @define-color bad #E2818A;
/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too — the /* NB: this `*` reset reaches the SNI tray menus Waybar hosts too (its
menu-side damage (collapsed arrows) is undone by USER-priority rules in stylesheet applies process-wide, at a priority user gtk.css cannot
stylix.nix. Do NOT scope it to window#waybar: the id's specificity would out-rank). The menu block right below undoes the damage — keep the two
beat the class rules below (pills) and wreck the bar. */ in sync. Do NOT scope `*` to window#waybar instead: the id's
specificity would beat the class rules below (pills) and wreck the
bar. */
* { * {
/* Mono Nerd face for status glyphs (tight right bearings on the /* Mono Nerd face for status glyphs (tight right bearings on the
proportional Symbols face make icon+percentage collide). */ proportional Symbols face make icon+percentage collide). */
@@ -38,6 +40,20 @@
min-height: 0; min-height: 0;
} }
/* ── Tray menus (nm-applet & co live in Waybar's process) ─────────────
Undo the `*` reset for them: same stylesheet, higher specificity.
Arrows/checks are CSS-sized nodes — min-height 0 makes them invisible;
separators die the same way; the bar's mono face reads wrong in text
menus. */
menu { font-family: "Inter", sans-serif; }
menu menuitem arrow { min-width: 16px; min-height: 16px; }
menu check, menu radio { min-width: 14px; min-height: 14px; }
menu separator {
min-height: 1px;
margin: 5px 0;
background: alpha(@text, 0.15);
}
/* The bar itself is invisible — the pills float over the wallpaper. */ /* The bar itself is invisible — the pills float over the wallpaper. */
window#waybar { window#waybar {
background: transparent; background: transparent;

View File

@@ -21,10 +21,11 @@
@define-color warn #DBA85A; @define-color warn #DBA85A;
@define-color bad #D06B71; @define-color bad #D06B71;
/* NB: this `*` reset reaches the SNI tray menus Waybar hosts too — the /* NB: this `*` reset reaches the SNI tray menus Waybar hosts too (its
menu-side damage (collapsed arrows) is undone by USER-priority rules in stylesheet applies process-wide, at a priority user gtk.css cannot
stylix.nix. Do NOT scope it to window#waybar: the id's specificity would out-rank). The menu block right below undoes the damage — keep the two
beat the class rules below and wreck the bar. */ in sync. Do NOT scope `*` to window#waybar instead: the id's
specificity would beat the class rules below and wreck the bar. */
* { * {
/* Mono Nerd face first for status glyphs: proportional "Symbols Nerd /* Mono Nerd face first for status glyphs: proportional "Symbols Nerd
Font" has tight right bearings that make icon+percentage collide. */ Font" has tight right bearings that make icon+percentage collide. */
@@ -36,6 +37,20 @@
min-height: 0; min-height: 0;
} }
/* ── Tray menus (nm-applet & co live in Waybar's process) ─────────────
Undo the `*` reset for them: same stylesheet, higher specificity.
Arrows/checks are CSS-sized nodes — min-height 0 makes them invisible;
separators die the same way; the glyph-first face reads wrong in text
menus. */
menu { font-family: "Inter", sans-serif; }
menu menuitem arrow { min-width: 16px; min-height: 16px; }
menu check, menu radio { min-width: 14px; min-height: 14px; }
menu separator {
min-height: 1px;
margin: 5px 0;
background: alpha(@text, 0.15);
}
/* Solid bar, crisp edge against the content below. */ /* Solid bar, crisp edge against the content below. */
window#waybar { window#waybar {
background: @base; background: @base;