#!/usr/bin/env bash # Turn off idle detection, screen blanking, DPMS, and auto-lock across common Arch Linux setups. # # Supported environments: # - X11 (xset: DPMS/screensaver/blanking) # - GNOME (gsettings: idle/lock + power 'nothing') # - KDE Plasma (best-effort: disable kscreenlocker; X11 DPMS still handled by xset) # - Sway/Wayland (kill swayidle) # - Linux console TTYs (setterm) # # Optional persistence (requires sudo): # --persist-systemd -> Set IdleAction=ignore in /etc/systemd/logind.conf and restart logind # Optional activity watcher: # --watch-controller -> Treat game controller (e.g., Xbox) input as user activity to keep session awake # # Notes: # - This script focuses on keeping the screen on and unlocked. Use with care on shared systems. # - For desktop-specific persistence (GNOME/KDE), settings are applied per-user and should persist. set -euo pipefail log() { printf "[idle-off] %s\n" "$*"; } warn() { printf "[idle-off][WARN] %s\n" "$*" >&2; } has_cmd() { command -v "$1" >/dev/null 2>&1; } persist_systemd=false watch_controller=false for arg in "${@:-}"; do case "$arg" in --persist-systemd) persist_systemd=true ;; --watch-controller) watch_controller=true ;; -h|--help) cat </dev/null | grep -q '^org\.gnome\.desktop\.session$'; then log "Applying GNOME settings to disable idle and lock" # No lock on idle gsettings set org.gnome.desktop.screensaver lock-enabled false 2>/dev/null || warn "Failed to set GNOME lock-enabled" # No idle delay (0 = never) gsettings set org.gnome.desktop.session idle-delay 0 2>/dev/null || warn "Failed to set GNOME idle-delay" # No automatic suspend on AC or battery gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing' 2>/dev/null || true gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-type 'nothing' 2>/dev/null || true # Optional: ensure screensaver idle-activation-enabled is false (for older setups) gsettings set org.gnome.desktop.screensaver idle-activation-enabled false 2>/dev/null || true fi fi } disable_kde_idle() { # Best-effort: turn off auto-locker; note: Plasma on Wayland still may rely on compositor-level settings if has_cmd kwriteconfig5; then log "Disabling KDE Plasma screen auto-lock (kscreenlockerrc)" kwriteconfig5 --file kscreenlockerrc --group Daemon --key Autolock false 2>/dev/null || true kwriteconfig5 --file kscreenlockerrc --group Daemon --key LockOnResume false 2>/dev/null || true kwriteconfig5 --file kscreenlockerrc --group Daemon --key Timeout 0 2>/dev/null || true fi } disable_sway_idle() { # Sway commonly uses swayidle for idle actions; killing it prevents screen blanking/locking if pgrep -x sway >/dev/null 2>&1; then if pgrep -x swayidle >/dev/null 2>&1; then log "Killing swayidle to prevent Wayland idle actions" pkill -x swayidle || true fi fi } disable_lock_daemons() { # Stop common screen lockers/idle helpers if running local daemons=(xss-lock light-locker xscreensaver gnome-screensaver) local found=false for d in "${daemons[@]}"; do if pgrep -x "$d" >/dev/null 2>&1; then found=true log "Stopping ${d}" pkill -x "$d" || true fi done if [[ "$found" == false ]]; then log "No known lock daemons running" fi } disable_tty_idle() { if has_cmd setterm; then log "Disabling TTY blanking and powersave" # Apply to the current TTY; also attempt to broadcast to common TTYs setterm -blank 0 -powersave off -powerdown 0 || true for tty in /dev/tty{1..12}; do [[ -e "$tty" ]] || continue setterm -blank 0 -powersave off -powerdown 0 <"$tty" >/dev/null 2>&1 || true done fi } reset_idle_activity() { # Trigger activity hints depending on environment if [[ -n "${DISPLAY:-}" ]]; then if has_cmd xset; then xset s reset || true xset -dpms || true xset s off || true xset s noblank || true fi if has_cmd xdotool; then # No-op mousemove to generate X11 activity without visible movement xdotool mousemove_relative -- 0 0 2>/dev/null || true fi fi } watch_js_device() { local dev="$1" log "Watching controller device: $dev" while :; do if [[ ! -e "$dev" ]]; then warn "Device disappeared: $dev" break fi # Joystick API event size is 8 bytes; block until an event arrives if dd if="$dev" bs=8 count=1 status=none of=/dev/null; then reset_idle_activity # Debounce bursts of events sleep 0.3 else # On read error (e.g., permission), backoff sleep 1 fi done } start_controller_watchers() { # Attempt to watch all /dev/input/js* devices; rescan periodically for new ones local seen="" declare -A pids # Initial permission check local any_js=false any_readable=false for dev in /dev/input/js*; do [[ -e "$dev" ]] || continue any_js=true if [[ -r "$dev" ]]; then any_readable=true; fi done if [[ "$any_js" == true && "$any_readable" == false ]]; then warn "No read permission to /dev/input/js*; add your user to the 'input' group or create udev rules." fi while :; do local found_any=false for dev in /dev/input/js*; do [[ -e "$dev" ]] || continue found_any=true if [[ -z "${pids[$dev]:-}" ]] || ! kill -0 "${pids[$dev]}" 2>/dev/null; then # Start a watcher for this device in background watch_js_device "$dev" & pids[$dev]=$! fi done if [[ "$found_any" == false ]]; then # No joystick devices; quiet rescan sleep 5 else # Rescan less frequently when active sleep 2 fi done } persist_with_systemd_logind() { # Set IdleAction=ignore in /etc/systemd/logind.conf and restart logind # Warning: restarting logind can affect user sessions (e.g., inhibit handling). Use with care. if [[ "$persist_systemd" != true ]]; then return 0 fi if ! has_cmd sudo; then warn "sudo not found; cannot persist systemd-logind setting" return 0 fi log "Persisting: setting systemd-logind IdleAction=ignore (requires sudo)" sudo sh -c ' set -e conf=/etc/systemd/logind.conf if [ ! -f "$conf" ]; then touch "$conf" fi # Backup once [ -f "${conf}.bak" ] || cp -a "$conf" "${conf}.bak" # Ensure the key exists and is set to ignore if grep -q "^#\?IdleAction=" "$conf"; then sed -i "s/^#\?IdleAction=.*/IdleAction=ignore/" "$conf" else printf "\nIdleAction=ignore\n" >> "$conf" fi ' log "Restarting systemd-logind to apply changes (may briefly affect session inhibitors)" sudo systemctl restart systemd-logind || warn "Failed to restart systemd-logind" } main() { log "Starting idle/lock disablement" # Environment-aware steps disable_x11_idle disable_gnome_idle disable_kde_idle disable_sway_idle # Generic steps disable_lock_daemons disable_tty_idle # Optional persistence persist_with_systemd_logind if [[ "$watch_controller" == true ]]; then log "Controller activity watcher enabled" # Keep the script alive to watch controllers start_controller_watchers & watcher_pid=$! log "Watcher PID: $watcher_pid" # Wait indefinitely and forward termination trap 'log "Stopping controller watcher"; kill "$watcher_pid" 2>/dev/null || true; exit 0' INT TERM wait "$watcher_pid" else log "Done. The screen should no longer blank, lock, or power down automatically." fi } main "$@"