gamemode-session: reference-counted state machine core
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# gamemode-session — compositor-level gamemode for niri.
|
||||
# Reference-counted over two sources (feral, manual). Applies effects on the
|
||||
# first active source (0->1) and reverts on the last (1->0).
|
||||
# Spec: docs/superpowers/specs/2026-07-15-niri-gamemode-design.md
|
||||
set -u
|
||||
|
||||
STATE_DIR="${GAMEMODE_STATE_DIR:-${XDG_RUNTIME_DIR:-/run/user/$(id -u)}/gamemode}"
|
||||
FAN_AUTO="${XDG_STATE_HOME:-$HOME/.local/state}/fan-profile-auto"
|
||||
DRYRUN="${GAMEMODE_DRYRUN:-0}"
|
||||
|
||||
log() { printf 'gamemode: %s\n' "$*" >&2; }
|
||||
run() { if [ "$DRYRUN" = 1 ]; then log "would: $*"; else "$@"; fi; }
|
||||
|
||||
is_active() {
|
||||
[ -n "$(find "$STATE_DIR" -maxdepth 1 -name 'src.*' -print -quit 2>/dev/null)" ]
|
||||
}
|
||||
|
||||
snapshot_baseline() {
|
||||
mkdir -p "$STATE_DIR"
|
||||
powerprofilesctl get 2>/dev/null > "$STATE_DIR/baseline.profile" || : > "$STATE_DIR/baseline.profile"
|
||||
if pgrep -x waybar >/dev/null 2>&1; then echo 1; else echo 0; fi > "$STATE_DIR/baseline.waybar"
|
||||
if [ -f "$FAN_AUTO" ]; then echo 1; else echo 0; fi > "$STATE_DIR/baseline.fanauto"
|
||||
}
|
||||
|
||||
# --- effects (bodies filled in Task 2; dryrun-safe stubs for now) -------------
|
||||
effect_idle_on() { run : "idle inhibit on"; }
|
||||
effect_idle_off() { run : "idle inhibit off"; }
|
||||
effect_dnd_on() { run : "dnd on"; }
|
||||
effect_dnd_off() { run : "dnd off"; }
|
||||
effect_perf_on() { run : "perf on"; }
|
||||
effect_perf_off() { run : "perf off"; }
|
||||
effect_waybar_on() { run : "waybar hide"; }
|
||||
effect_waybar_off(){ run : "waybar restore"; }
|
||||
|
||||
apply_effects() { effect_idle_on; effect_dnd_on; effect_perf_on; effect_waybar_on; }
|
||||
revert_effects() { effect_idle_off; effect_dnd_off; effect_perf_off; effect_waybar_off; }
|
||||
|
||||
# --- state machine ------------------------------------------------------------
|
||||
cmd_add() {
|
||||
local src="$1" was=0
|
||||
is_active && was=1
|
||||
mkdir -p "$STATE_DIR"
|
||||
touch "$STATE_DIR/src.$src"
|
||||
if [ "$was" = 0 ]; then
|
||||
snapshot_baseline
|
||||
apply_effects
|
||||
log "activated (source: $src)"
|
||||
else
|
||||
log "already active; +source: $src"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_del() {
|
||||
local src="$1"
|
||||
rm -f "$STATE_DIR/src.$src"
|
||||
if ! is_active; then
|
||||
revert_effects
|
||||
rm -f "$STATE_DIR"/baseline.* "$STATE_DIR/idle.pid"
|
||||
log "deactivated (last source: $src)"
|
||||
else
|
||||
log "still active; -source: $src"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_toggle() {
|
||||
if [ -e "$STATE_DIR/src.manual" ]; then cmd_del manual; else cmd_add manual; fi
|
||||
}
|
||||
|
||||
cmd_status() { if is_active; then echo active; exit 0; else echo inactive; exit 1; fi; }
|
||||
|
||||
cmd_reset() {
|
||||
revert_effects 2>/dev/null || true
|
||||
rm -rf "$STATE_DIR"
|
||||
log "reset"
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
add) [ -n "${2:-}" ] || { log "add needs a source"; exit 2; }; cmd_add "$2" ;;
|
||||
del) [ -n "${2:-}" ] || { log "del needs a source"; exit 2; }; cmd_del "$2" ;;
|
||||
toggle) cmd_toggle ;;
|
||||
status) cmd_status ;;
|
||||
reset) cmd_reset ;;
|
||||
*) log "usage: gamemode-session {add|del <source>|toggle|status|reset}"; exit 2 ;;
|
||||
esac
|
||||
Executable
+44
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
# Drives gamemode-session in dryrun against a temp state dir and asserts the
|
||||
# reference-counting state machine. No live effects run.
|
||||
set -u
|
||||
HERE=$(cd "$(dirname "$0")/.." && pwd)
|
||||
SCRIPT="$HERE/gamemode-session.sh"
|
||||
TMP=$(mktemp -d)
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
export GAMEMODE_STATE_DIR="$TMP/state"
|
||||
export GAMEMODE_DRYRUN=1
|
||||
|
||||
fail=0
|
||||
check() { # desc, actual, expected
|
||||
if [ "$2" = "$3" ]; then printf 'ok - %s\n' "$1"
|
||||
else printf 'FAIL - %s (got [%s] want [%s])\n' "$1" "$2" "$3"; fail=1; fi
|
||||
}
|
||||
active() { "$SCRIPT" status >/dev/null 2>&1 && echo active || echo inactive; }
|
||||
|
||||
check "starts inactive" "$(active)" "inactive"
|
||||
|
||||
"$SCRIPT" add feral >/dev/null 2>&1
|
||||
check "feral activates" "$(active)" "active"
|
||||
check "src.feral marker set" "$([ -e "$GAMEMODE_STATE_DIR/src.feral" ] && echo y)" "y"
|
||||
check "baseline captured" "$([ -e "$GAMEMODE_STATE_DIR/baseline.profile" ] && echo y)" "y"
|
||||
|
||||
"$SCRIPT" add manual >/dev/null 2>&1
|
||||
check "manual keeps active" "$(active)" "active"
|
||||
|
||||
"$SCRIPT" del feral >/dev/null 2>&1
|
||||
check "still active on 1 left" "$(active)" "active"
|
||||
|
||||
"$SCRIPT" del manual >/dev/null 2>&1
|
||||
check "last del deactivates" "$(active)" "inactive"
|
||||
check "baseline cleared" "$([ -e "$GAMEMODE_STATE_DIR/baseline.profile" ] && echo y || echo n)" "n"
|
||||
|
||||
"$SCRIPT" toggle >/dev/null 2>&1
|
||||
check "toggle on activates" "$(active)" "active"
|
||||
"$SCRIPT" toggle >/dev/null 2>&1
|
||||
check "toggle off deactivates" "$(active)" "inactive"
|
||||
|
||||
"$SCRIPT" reset >/dev/null 2>&1
|
||||
check "reset leaves inactive" "$(active)" "inactive"
|
||||
|
||||
exit $fail
|
||||
Reference in New Issue
Block a user