fix(eww): stop duplicate stacked bars from ewwstart race

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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R5kHioUMK3mtf2eiLEozCM
main
Amir Alexander Abdelbaki 2026-06-28 02:23:45 +02:00
parent 2a54a0302b
commit ae0ad3c4d7
3 changed files with 68 additions and 35 deletions

View File

@ -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<monitorsum; curmon++)); do
eww open bar --id "bar${curmon}" --arg "monitor=${curmon}"
done
#/usr/bin/eww open bar --id primary --arg monitor=1
#/usr/bin/eww open bar --id secondary --arg monitor=0

View File

@ -1,23 +1,30 @@
#!/bin/bash
# Kill any running Eww instance before starting a fresh daemon to avoid
# duplicate bars or stale widget state after a reload/monitor change.
killall eww
# Start the Eww daemon in the background; subsequent `eww open` calls connect to it.
/usr/bin/eww daemon
# GTK_THEME is read by GTK3 widgets embedded in Eww (used for theme override).
GTK_THEME=cyberqueer
# Count connected monitors via hyprctl — each "ID" line corresponds to one monitor.
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
# 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<monitorsum; curmon++)); do
eww open bar --id "bar${curmon}" --arg "monitor=${curmon}"
done
#/usr/bin/eww open bar --id primary --arg monitor=1
#/usr/bin/eww open bar --id secondary --arg monitor=0

View File

@ -1,13 +1,26 @@
#!/bin/bash
# Kill any running Eww instance(s) so we start from a clean slate (e.g. after a
# 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 || 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<monitorsum; curmon++)); do
eww open bar --id "bar${curmon}" --arg "monitor=${curmon}"
done