#!/bin/bash # Suspends xset screensaver/DPMS blanking while any visible workspace has a # fullscreen window (video, game, presentation), restores normal timeouts # once nothing is fullscreen. interval="${1:-5}" # Single-instance lock: i3 restarts/reloads re-run our autostart exec, so # without this, stray duplicate loops accumulate and race each other's state. exec 9>"/tmp/.dpms-inhibit-$(id -u).lock" flock -n 9 || exit 0 has_fullscreen() { python3 - <<'EOF' import json, subprocess, sys def is_fullscreen(node): if node.get('window') and node.get('fullscreen_mode', 0) > 0: return True return any(is_fullscreen(c) for c in node.get('nodes', []) + node.get('floating_nodes', [])) def find_ws(node, name): if node.get('type') == 'workspace' and node.get('name') == name: return node for c in node.get('nodes', []) + node.get('floating_nodes', []): r = find_ws(c, name) if r: return r try: wss = json.loads(subprocess.check_output(['i3-msg', '-t', 'get_workspaces'], stderr=subprocess.DEVNULL)) tree = json.loads(subprocess.check_output(['i3-msg', '-t', 'get_tree'], stderr=subprocess.DEVNULL)) for ws in wss: if ws.get('visible'): node = find_ws(tree, ws['name']) if node and is_fullscreen(node): sys.exit(0) except Exception: pass sys.exit(1) EOF } inhibited=0 while true; do if has_fullscreen; then xset s off xset -dpms inhibited=1 else if [ "$inhibited" -eq 1 ]; then xset s 300 300 xset dpms 300 600 900 inhibited=0 fi fi sleep "$interval" done