diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-21 20:13:23 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-21 20:13:23 +0200 |
| commit | 696f3ad4f65a6516549544af13a9646f57ae523e (patch) | |
| tree | 10004eac68626f413da40c2287dd1838fbb82f86 /desktop/modules/status/statusctl | |
| parent | 34a6a3cd65370fd31877da0c54abcae15d69d3a4 (diff) | |
| download | quickshell-696f3ad4f65a6516549544af13a9646f57ae523e.tar.gz quickshell-696f3ad4f65a6516549544af13a9646f57ae523e.zip | |
feat(status): report a running game as its own presentation state
status.gaming is written by the shell's game detector and presentation is
the OR of it and the manual file, but statusctl read only the manual half.
A game therefore asserted the presentation effects while the waybar pill
still read deactivated.
Report gaming as a third state, for presentation only. The watch follows
status.gaming as well as its own file, and emits only on a real change so
an unchanged rewrite draws nothing.
Toggle is refused while a game holds the mode: the detector reasserts the
file within its poll, so the write would not stick. set stays allowed, the
manual half is worth setting for when the game exits.
gaming stays out of MODES. The detector owns that file and nothing here
may write it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/modules/status/statusctl')
| -rwxr-xr-x | desktop/modules/status/statusctl | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/desktop/modules/status/statusctl b/desktop/modules/status/statusctl index 571beef..531951b 100755 --- a/desktop/modules/status/statusctl +++ b/desktop/modules/status/statusctl @@ -82,15 +82,34 @@ tooltip() { case "$1" in activated) printf '%s: on' "$mode" ;; deactivated) printf '%s: off' "$mode" ;; + gaming) printf '%s: on (game running)' "$mode" ;; esac } +# The shell's game detector owns status.gaming and presentation is the OR of +# the two, so the CLI has to read it to agree with the shell. It is not a mode +# in MODES: nothing here may write it, and only presentation is affected. +gaming_on() { + local v="" + [[ -e "$DIR/status.gaming" ]] && v="$(tr -d '[:space:]' < "$DIR/status.gaming" 2>/dev/null)" + [[ "$v" == "1" ]] +} + # A missing file is the off state, not a distinct condition: read_mode already # reads it as 0, and this is the same path `get` uses. There is no "down": a # file cannot report whether a watcher is alive, and a missing one is exactly # what a fresh session looks like. +# +# A running game reports its own state rather than plain activated, so the +# widget can show why the mode is on and that a click will not turn it off. state_now() { - [[ "$(read_mode)" == "1" ]] && printf 'activated' || printf 'deactivated' + if [[ "$mode" == "presentation" ]] && gaming_on; then + printf 'gaming' + elif [[ "$(read_mode)" == "1" ]]; then + printf 'activated' + else + printf 'deactivated' + fi } case "$action" in @@ -106,6 +125,15 @@ case "$action" in esac ;; toggle) + # A running game pins presentation on and the detector reasserts it + # within its poll, so a toggle here would flip back on its own. Refuse + # it instead of writing a value that does not stick. `set` still works: + # it is the explicit verb, and the manual half is worth setting for + # when the game exits. + if [[ "$mode" == "presentation" ]] && gaming_on; then + printf '%s: presentation held on by a running game\n' "${0##*/}" >&2 + exit 1 + fi [[ "$(read_mode)" == "1" ]] && write_mode 0 || write_mode 1 ;; watch) @@ -123,9 +151,20 @@ case "$action" in exec 3< <(inotifywait -q -m -e close_write,moved_to,delete --format '%f' "$DIR" 2>/dev/null) watcher=$! trap 'kill "$watcher" 2>/dev/null' EXIT TERM INT + # Presentation also follows status.gaming, so a game starting or + # ending redraws the widget. Emitting only on a real change keeps a + # write of an unchanged value from firing a duplicate line. + last="$(state_now)" while read -r changed <&3; do - [[ "$changed" == "status.$mode" ]] || continue - emit "$(state_now)" + case "$changed" in + "status.$mode") ;; + status.gaming) [[ "$mode" == "presentation" ]] || continue ;; + *) continue ;; + esac + now="$(state_now)" + [[ "$now" == "$last" ]] && continue + last="$now" + emit "$now" done ;; *) |
