From ae0ad3c4d73081835102983f75ac16bb04f3703e Mon Sep 17 00:00:00 2001 From: The_miro Date: Sun, 28 Jun 2026 02:23:45 +0200 Subject: [PATCH] fix(eww): stop duplicate stacked bars from ewwstart race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diagnosed live in a VM: the bar rendered twice (two stacked rows). `hyprctl layers` showed two `gtk-layer-shell` bar surfaces owned by two different eww pids — an `eww daemon` and an `eww open bar`. The monitor count was correctly 1, so the per-monitor loop was not at fault. Root cause: ewwstart.sh started `eww daemon` and then immediately ran `eww open` in a loop. The first `eww open` frequently ran before the freshly-started daemon was ready, so it spawned its OWN second daemon and drew a second bar. Fix (all three DE variants — hyprlua, hyprland, niri): - Drop the separate `eww daemon`; rely on `eww open` to auto-start the daemon and block until the window is mapped, so the first call establishes a single daemon that the rest reuse (no race, no second daemon). - killall eww + short settle before opening, so a reload starts clean. - hyprlua/hyprland: count monitors via `hyprctl monitors -j | jq length` instead of the fragile `hyprctl monitors | grep ID | wc -l`. - export GTK_THEME (the bare assignment never took effect). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM --- desktopenvs/hyprland/scripts/ewwstart.sh | 35 ++++++++++++------ desktopenvs/hyprlua/scripts/ewwstart.sh | 45 ++++++++++++++---------- desktopenvs/niri/scripts/ewwstart.sh | 23 +++++++++--- 3 files changed, 68 insertions(+), 35 deletions(-) diff --git a/desktopenvs/hyprland/scripts/ewwstart.sh b/desktopenvs/hyprland/scripts/ewwstart.sh index 699fce9..67816e1 100755 --- a/desktopenvs/hyprland/scripts/ewwstart.sh +++ b/desktopenvs/hyprland/scripts/ewwstart.sh @@ -1,15 +1,28 @@ #!/bin/bash -killall eww -/usr/bin/eww daemon -GTK_THEME=cyberqueer -monitorsum=$(hyprctl monitors | grep ID | wc -l) +# Kill any running Eww instance(s) so we start from a clean slate (e.g. after a +# Hyprland reload or a monitor change re-runs this script). Give the old daemon a +# moment to fully exit and drop its layer-shell surfaces before opening new ones. +killall eww 2>/dev/null +sleep 1 -for i in $(seq 1 $monitorsum); -do - declare -i curmon=$i-1 - /usr/bin/eww open bar --id bar$curmon --arg monitor=$curmon +# GTK_THEME is read by the GTK3 widgets embedded in Eww. Export it (the previous +# bare assignment was never exported, so it had no effect). +export GTK_THEME=cyberqueer + +# Count connected monitors from hyprctl's JSON output. The previous +# `hyprctl monitors | grep ID | wc -l` was fragile — any extra output line that +# happened to contain "ID" would inflate the count. +monitorsum=$(hyprctl monitors -j | jq 'length') + +# Open one bar per monitor, keyed by the 0-based monitor index. +# +# IMPORTANT: we deliberately do NOT run `eww daemon` separately and then loop +# `eww open`. That RACED: the first `eww open` frequently ran before the freshly +# started daemon was ready, so it spawned its OWN second daemon and drew a second +# bar — two stacked bars on a single monitor. `eww open` already auto-starts the +# daemon and blocks until the window is mapped, so the first call establishes a +# single daemon that every subsequent call reuses. +for ((curmon=0; curmon/dev/null +sleep 1 -# Open one bar instance per monitor. Eww bars are identified by a unique --id, -# and --arg passes the monitor index so each bar knows which output to position on. -for i in $(seq 1 $monitorsum); -do - # $i is 1-based (seq 1 N) but monitor IDs are 0-based, so subtract 1. - declare -i curmon=$i-1 - /usr/bin/eww open bar --id bar$curmon --arg monitor=$curmon +# GTK_THEME is read by the GTK3 widgets embedded in Eww. Export it (the previous +# bare assignment was never exported, so it had no effect) so the bar picks up the +# cyberqueer palette. +export GTK_THEME=cyberqueer + +# Count connected monitors from hyprctl's JSON output. The previous +# `hyprctl monitors | grep ID | wc -l` was fragile — any extra output line that +# happened to contain "ID" would inflate the count. +monitorsum=$(hyprctl monitors -j | jq 'length') + +# Open one bar per monitor, keyed by the 0-based monitor index. +# +# IMPORTANT: we deliberately do NOT run `eww daemon` separately and then loop +# `eww open`. The old script did exactly that and it RACED: the first `eww open` +# frequently ran before the freshly-started daemon was ready, so it spawned its +# OWN second daemon and drew a second bar — leaving two stacked bars on a single +# monitor. `eww open` already auto-starts the daemon and blocks until the window +# is mapped, so the first call here establishes a single daemon that every +# subsequent call reuses, guaranteeing one bar per monitor. +for ((curmon=0; curmon/dev/null || true -/usr/bin/eww daemon +sleep 1 -GTK_THEME=cyberqueer +# GTK_THEME is read by the GTK3 widgets embedded in Eww. Export it (the previous +# bare assignment was never exported, so it had no effect). +export GTK_THEME=cyberqueer +# One output per "Scale:" line in `niri msg outputs`. monitorsum=$(niri msg outputs | grep -c "Scale:" || echo 1) -for i in $(seq 1 "$monitorsum"); do - declare -i curmon=$i-1 - /usr/bin/eww open bar --id "bar$curmon" --arg monitor=$curmon +# Open one bar per output, keyed by the 0-based index. +# +# IMPORTANT: we deliberately do NOT run `eww daemon` separately and then loop +# `eww open`. That RACED: the first `eww open` frequently ran before the freshly +# started daemon was ready, so it spawned its OWN second daemon and drew a second +# bar — two stacked bars on a single monitor. `eww open` already auto-starts the +# daemon and blocks until the window is mapped, so the first call establishes a +# single daemon that every subsequent call reuses. +for ((curmon=0; curmon