fix freeze eww
This commit is contained in:
+49
-21
@@ -56,6 +56,9 @@ log() { printf 'eww-bar: %s\n' "$*" >&2; }
|
||||
ewwc() { timeout 5 eww --no-daemonize "$@" 9>&-; }
|
||||
|
||||
ping_daemon() { ewwc ping >/dev/null 2>&1; }
|
||||
# Empty when the daemon did not answer within the client's 100 ms deadline —
|
||||
# its main thread is busy (a popup takes seconds to build) — as well as when
|
||||
# nothing is open. Only a non-empty listing is authoritative.
|
||||
list_windows() { ewwc active-windows 2>/dev/null || true; }
|
||||
bar_open() { list_windows | grep -qx 'bar: bar'; }
|
||||
|
||||
@@ -69,6 +72,28 @@ wait_for_window() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# window_state NAME [SECONDS] → open | closed (listed without NAME) |
|
||||
# busy (nothing listed within SECONDS: main thread stuck, or nothing open)
|
||||
window_state() {
|
||||
local i n=$((${2:-5} * 5)) out
|
||||
for ((i = 0; i < n; i++)); do
|
||||
out=$(list_windows)
|
||||
if [[ -n $out ]]; then
|
||||
if grep -qx "$1: $1" <<<"$out"; then echo open; else echo closed; fi
|
||||
return 0
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
echo busy
|
||||
}
|
||||
|
||||
# The compositor's view: does the daemon own any layer surface? Tells a
|
||||
# daemon that is merely not answering from one with nothing on screen.
|
||||
daemon_has_layer() {
|
||||
hyprctl -j layers 2>/dev/null \
|
||||
| jq -e --argjson pid "$(main_pid)" '[.. | objects | select(.pid? == $pid)] | length > 0' >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------- daemon ---
|
||||
|
||||
# nixpkgs wraps eww (wrapGAppsHook), so the running process is `.eww-wrapped`;
|
||||
@@ -126,13 +151,13 @@ wait_for_daemon() {
|
||||
|
||||
start_unit() {
|
||||
systemctl --user reset-failed "$unit" >/dev/null 2>&1 || true
|
||||
systemctl --user start "$unit"
|
||||
systemctl --user start --no-block "$unit"
|
||||
}
|
||||
|
||||
restart_unit() {
|
||||
log "restarting $unit"
|
||||
systemctl --user reset-failed "$unit" >/dev/null 2>&1 || true
|
||||
systemctl --user restart "$unit"
|
||||
systemctl --user restart --no-block "$unit"
|
||||
}
|
||||
|
||||
ensure() {
|
||||
@@ -194,7 +219,7 @@ close_popups() {
|
||||
|
||||
# open_bar [--force] [SPEC]
|
||||
open_bar() {
|
||||
local force=0 spec screen
|
||||
local force=0 spec screen state
|
||||
if [[ ${1:-} == --force ]]; then force=1; shift; fi
|
||||
spec=${1:-$(saved_screen)}
|
||||
spec=${spec:-$default_screen}
|
||||
@@ -210,17 +235,18 @@ open_bar() {
|
||||
# client deadline), so the result is verified instead.
|
||||
close_popups
|
||||
ewwc open bar --screen "$screen" >/dev/null 2>&1 || true
|
||||
if ! wait_for_window bar 5; then
|
||||
if [[ $screen != "$default_screen" ]]; then
|
||||
log "cannot open the bar on '$screen', using screen $default_screen"
|
||||
screen=$default_screen
|
||||
ewwc open bar --screen "$screen" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if ! wait_for_window bar 5; then
|
||||
log "the bar does not come up, restarting $unit"
|
||||
restart_unit
|
||||
exit 1
|
||||
fi
|
||||
state=$(window_state bar 10)
|
||||
# Only an answered "no bar" means the screen was refused; busy just needs time.
|
||||
if [[ $state == closed && $screen != "$default_screen" ]]; then
|
||||
log "cannot open the bar on '$screen', using screen $default_screen"
|
||||
screen=$default_screen
|
||||
ewwc open bar --screen "$screen" >/dev/null 2>&1 || true
|
||||
state=$(window_state bar 10)
|
||||
fi
|
||||
if [[ $state != open ]]; then
|
||||
log "the bar does not come up ($state), restarting $unit"
|
||||
restart_unit
|
||||
exit 1
|
||||
fi
|
||||
printf '%s\n' "$spec" >"$screen_file"
|
||||
printf '%s\n' "$screen" >"$current_file"
|
||||
@@ -301,14 +327,16 @@ check() {
|
||||
strike "daemon does not answer"
|
||||
return 0
|
||||
fi
|
||||
if wait_for_window bar 3; then
|
||||
rm -f "$fail_file"
|
||||
return 0
|
||||
fi
|
||||
# Either nothing is open or the main loop is frozen (empty reply). Try to
|
||||
# open the bar: a frozen daemon still won't list it afterwards.
|
||||
case $(window_state bar 10) in
|
||||
open) rm -f "$fail_file"; return 0 ;;
|
||||
# Nothing listed for 10 s while something is on screen: the main loop is
|
||||
# frozen or still building a popup. Leave the windows alone; a second
|
||||
# miss restarts the unit.
|
||||
busy) if daemon_has_layer; then strike "UI unresponsive"; return 0; fi ;;
|
||||
esac
|
||||
# Listed without the bar, or nothing on screen at all: it really is gone.
|
||||
open_bar || true
|
||||
if wait_for_window bar 3; then
|
||||
if wait_for_window bar 5; then
|
||||
rm -f "$fail_file"
|
||||
log "bar was missing, reopened"
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user