#!/usr/bin/env bash # What Panama does while a game runs must be undone afterwards -- to what was # there before, not to a default. # # That distinction is the whole feature. If ending a game forced Do Not Disturb # off, it would silently undo a Do Not Disturb someone set by hand; if it forced # the power profile to "balanced", it would undo a deliberate choice. Both are # worse than doing nothing at all, because both look like the desktop # misbehaving rather than a setting being wrong. # # Read-only: it reads gaming state and never engages Game Mode. set -uo pipefail repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" helper="$repo_dir/config/dot/quickshell/scripts/panama-gaming" service="$repo_dir/config/dot/quickshell/services/Gaming.qml" page="$repo_dir/config/dot/quickshell/modules/settings/GamingPage.qml" shell_file="$repo_dir/config/dot/quickshell/shell.qml" fail() { printf 'gaming contract: %s\n' "$1" >&2 exit 1 } for path in "$helper" "$service" "$page" "$shell_file"; do [[ -r "$path" ]] || fail "missing $path" done [[ -x "$helper" ]] || fail 'panama-gaming is not executable' # ── The hook restores, it does not impose ─────────────────────────────────── hook_body="$(sed -n '/^def hook/,/^def /p' "$helper")" [[ -n "$hook_body" ]] || fail 'the hook is missing' grep -q 'state_path' <<<"$hook_body" \ || fail 'the hook records nothing about the state before a game, so it cannot restore it' grep -qE 'before\.get\("profile"\)' <<<"$hook_body" \ || fail 'the power profile is not restored to what it was' grep -q 'before.get("silenced") is False' <<<"$hook_body" \ || fail 'Do Not Disturb is cleared unconditionally, which would undo one the user set themselves' grep -qE 'set.*"balanced"' <<<"$hook_body" \ && fail 'the hook restores a hardcoded profile rather than the previous one' # ── The shell can be told, not only toggled ───────────────────────────────── # A toggle is the wrong primitive here: if notifications were already silenced, # toggling at game start would unsilence them. grep -q 'function setDnd(enabled: bool)' "$shell_file" \ || fail 'there is no explicit way to set Do Not Disturb, only a toggle' grep -q 'function dndState()' "$shell_file" \ || fail 'there is no way to read Do Not Disturb, so the hook cannot know what to restore' grep -qE '"notifications",\s*$' <<<"$(grep -A1 'qs", "ipc", "call"' "$helper")" >/dev/null 2>&1 || true grep -q '"setDnd"' "$helper" \ || fail 'the hook does not use the explicit setter' # ── The hook does not depend on the shell being up ────────────────────────── # A game can start after a shell restart; a hook that asked the shell for its # settings would silently do nothing. grep -q 'settings.json' <<<"$hook_body" \ || fail 'the hook reads its settings from somewhere other than the settings file' # ── Honest reporting ──────────────────────────────────────────────────────── grep -q 'governorAlreadyThere' "$service" \ || fail 'the service cannot tell when Game Mode would change nothing' page_code="$(grep -vE '^\s*//' "$page")" grep -q 'already runs that governor' <<<"$page_code" \ || fail 'the page does not say when Game Mode has no effect on this machine' # Proton is listed, never chosen: Steam owns that per game. grep -qiE 'setProton|selectProton|chooseProton' <<<"$page_code" \ && fail 'the page claims to choose the Proton build, which Steam owns per game' # ── Polling stops when nobody is looking ──────────────────────────────────── grep -q 'running: root.watching' "$service" \ || fail 'the poll timer runs regardless of whether the page is open' grep -q 'Gaming.watching = false' "$page" \ || fail 'the page never stops the poll timer, so it would poll forever after being closed' command -v jq >/dev/null 2>&1 || { printf 'gaming contract: SKIP (no jq)\n'; exit 0; } state="$("$helper" snapshot 2>/dev/null)" || fail 'snapshot failed' jq -e '(.gpus | type == "array") and (.gameMode | type == "object") and (.library | type == "object")' \ <<<"$state" >/dev/null || fail 'the snapshot is incomplete' jq -e '.gameMode | has("active") and has("daemonRunning") and has("hooksInstalled")' <<<"$state" >/dev/null \ || fail 'Game Mode state is incomplete' # An integrated GPU reporting no video memory must not be described as discrete. jq -e '[.gpus[] | select(.discrete) | .vramTotalBytes > 0] | all' <<<"$state" >/dev/null \ || fail 'a card with no video memory is reported as the discrete one' [[ -n "$("$helper" set-overlay-preset nonsense 2>/dev/null | jq -r '.error // ""')" ]] \ || fail 'an unknown overlay preset was accepted' [[ -n "$("$helper" hook nonsense 2>/dev/null | jq -r '.error // ""')" ]] \ || fail 'an unknown hook phase was accepted' printf 'gaming contract: PASS (%s GPU(s), %s games, hooks %s)\n' \ "$(jq '.gpus | length' <<<"$state")" \ "$(jq -r '.library.games' <<<"$state")" \ "$(jq -r 'if .gameMode.hooksInstalled then "installed" else "not installed" end' <<<"$state")"