{ lib , writeShellScriptBin , coreutils , eww , procps , systemd , util-linux }: # `eww open` silently becomes a NEW daemon when it can't reach the socket, # rebinding the same socket path and orphaning the previous daemon. The old # daemon keeps rendering its layer-shell surfaces but no longer answers any # `eww close` — that is the "zombie panel I can't close" / "bar opened twice". # Every open path must go through here first, so the socket is always live and # owned by the managed user service before a client touches it. writeShellScriptBin "eww-ensure-daemon" '' eww=${lib.getExe eww} uid="$(${coreutils}/bin/id -u)" runtime_dir="''${XDG_RUNTIME_DIR:-/run/user/$uid}" lock_file="$runtime_dir/eww-ensure-daemon.lock" service_active() { ${systemd}/bin/systemctl --user is-active --quiet eww.service } daemon_healthy() { "$eww" ping >/dev/null 2>&1 && service_active } wait_for_ping() { i=0 while [ "$i" -lt 100 ]; do daemon_healthy && return 0 ${coreutils}/bin/sleep 0.1 i=$((i + 1)) done return 1 } daemon_healthy && exit 0 ${coreutils}/bin/mkdir -p "$runtime_dir" ( ${util-linux}/bin/flock -x 9 daemon_healthy && exit 0 ${systemd}/bin/systemctl --user stop eww.service >/dev/null 2>&1 || true ${procps}/bin/pkill -TERM -x -u "$uid" eww >/dev/null 2>&1 || true ${coreutils}/bin/sleep 0.2 ${procps}/bin/pkill -KILL -x -u "$uid" eww >/dev/null 2>&1 || true ${coreutils}/bin/rm -f "$runtime_dir"/eww-server_* ${systemd}/bin/systemctl --user reset-failed eww.service >/dev/null 2>&1 || true ${systemd}/bin/systemctl --user start eww.service >/dev/null 2>&1 || true wait_for_ping ) 9>"$lock_file" ''