commit ebe89a8ca021d1c4769f066a99dd1ca6405643f5
Author: MrJensK <jens.se@icloud.com>
AuthorDate: Wed Aug 12 20:02:21 2026 +0200
Commit: MrJensK <jens.se@icloud.com>
CommitDate: Wed Aug 12 20:02:21 2026 +0200
updates
---
README.md | 20 +++++++++++++++++++-
screensaver-launch | 27 ++++++++++++++++++++-------
screensaver-toggle | 17 +++++++++++++++++
screensaverd | 23 +++++++++++++++++++++--
4 files changed, 77 insertions(+), 10 deletions(-)
diff --git a/README.md b/README.md
index 20c57cd..3695e6c 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,13 @@ istället för Hyprland.
- `screensaver-launch` – hittar alla anslutna skärmar (`xrandr`) och öppnar ett
fullskärms-kitty-fönster med `screensaver` på var och en.
- `screensaverd` – bevakar inaktivitet via `xssstate` och startar/dödar
- screensavern automatiskt.
+ screensavern automatiskt. Skjuter upp start (och avbryter en redan startad
+ screensaver) medan något spelar upp media, via `playerctl status` – kräver
+ `playerctl` (valfritt, hoppas bara över om det saknas) och stöd för MPRIS i
+ spelaren (mpv, VLC, Firefox/Chromium m.fl.).
+- `screensaver-toggle` – pausar/återupptar `screensaverd`. Kör en gång för att
+ pausa (avbryter screensavern direkt om den visas just då), kör igen för att
+ återuppta.
## Installation
@@ -61,6 +67,18 @@ Efter ändring i `sxwmrc`: logga ut och in igen (eller kör
`call : mod + r : reload_config` — observera att `reload_config` läser om
bindningar/inställningar men `exec`-raderna körs bara vid sxwm-start).
+### Pausa tillfälligt
+
+```sh
+screensaver-toggle # pausa; kör igen för att återuppta
+```
+
+Styr det med en tangent genom att lägga till i `~/.config/sxwmrc`:
+
+```
+bind : mod + shift + s : "screensaver-toggle"
+```
+
## Byta ASCII-konst
Peka `screensaver` mot en annan fil genom att sätta miljövariabeln innan start:
diff --git a/screensaver-launch b/screensaver-launch
index 7c4e5b4..7160c4d 100755
--- a/screensaver-launch
+++ b/screensaver-launch
@@ -28,6 +28,7 @@ for mon in $(xrandr --listmonitors | awk 'NR>1 {print $3}'); do
--override font_size=18 \
--override window_padding_width=0 \
--override background_opacity=1 \
+ --override mouse_hide_wait=0.1 \
-e "$SCRIPT_DIR/screensaver" &
kpid=$!
@@ -46,16 +47,28 @@ for mon in $(xrandr --listmonitors | awk 'NR>1 {print $3}'); do
if [[ -n "$newwin" ]]; then
# The window may not be fully mapped/reparented yet right after it
- # appears in `xdotool search`, so retry the placement a few times to
- # ride out the occasional BadWindow race with the window manager.
- for attempt in 1 2 3; do
+ # appears in `xdotool search`, so retry placement to ride out the
+ # occasional BadWindow race with the window manager. `wmctrl`
+ # returning success only means the fullscreen request was sent, not
+ # that the WM actually acted on it (e.g. it's silently dropped if the
+ # window isn't mapped yet in the WM's eyes) -- read the geometry back
+ # and keep retrying until it actually matches the monitor, instead of
+ # giving up after a fixed few tries and leaving it windowed.
+ for attempt in $(seq 1 30); do
xdotool windowactivate --sync "$newwin" 2>/dev/null
- if xdotool windowmove "$newwin" "$x" "$y" 2>/dev/null \
- && xdotool windowsize "$newwin" "$w" "$h" 2>/dev/null \
- && wmctrl -ir "$newwin" -b add,fullscreen 2>/dev/null; then
+ xdotool windowmove "$newwin" "$x" "$y" 2>/dev/null
+ xdotool windowsize "$newwin" "$w" "$h" 2>/dev/null
+ wmctrl -ir "$newwin" -b add,fullscreen 2>/dev/null
+
+ geo="$(xdotool getwindowgeometry --shell "$newwin" 2>/dev/null)"
+ gx="$(grep -m1 '^X=' <<<"$geo" | cut -d= -f2)"
+ gy="$(grep -m1 '^Y=' <<<"$geo" | cut -d= -f2)"
+ gw="$(grep -m1 '^WIDTH=' <<<"$geo" | cut -d= -f2)"
+ gh="$(grep -m1 '^HEIGHT=' <<<"$geo" | cut -d= -f2)"
+ if [[ "$gx" == "$x" && "$gy" == "$y" && "$gw" == "$w" && "$gh" == "$h" ]]; then
break
fi
- sleep 0.2
+ sleep 0.1
done
fi
done
diff --git a/screensaver-toggle b/screensaver-toggle
new file mode 100755
index 0000000..b0bd488
--- /dev/null
+++ b/screensaver-toggle
@@ -0,0 +1,17 @@
+#!/bin/bash
+# Pauses/resumes screensaverd's idle detection. Run once to pause (also
+# stops the screensaver immediately if it's showing right now), run again
+# to resume. State is a flag file screensaverd polls every second, so
+# toggling takes effect within ~1s regardless of what screensaverd is
+# doing at the time.
+set -u
+
+PAUSE_FILE="${XDG_RUNTIME_DIR:-/tmp}/screensaver-paused"
+
+if [[ -e "$PAUSE_FILE" ]]; then
+ rm -f "$PAUSE_FILE"
+ echo "screensaver: återupptagen"
+else
+ touch "$PAUSE_FILE"
+ echo "screensaver: pausad"
+fi
diff --git a/screensaverd b/screensaverd
index 0d20a4e..ec1edf2 100755
--- a/screensaverd
+++ b/screensaverd
@@ -11,11 +11,30 @@ export PATH="$HOME/.local/bin:$PATH"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
IDLE_SECONDS="${SCREENSAVER_IDLE_SECONDS:-150}"
WIN_CLASS="screensaver"
+PAUSE_FILE="${XDG_RUNTIME_DIR:-/tmp}/screensaver-paused"
is_running() {
xdotool search --class "^${WIN_CLASS}\$" >/dev/null 2>&1
}
+# Set by screensaver-toggle. Checked fresh every loop iteration (not just
+# at launch time) so toggling pause while the screensaver is already
+# showing kills it immediately, same as real input would.
+is_paused() {
+ [[ -e "$PAUSE_FILE" ]]
+}
+
+# xssstate only tracks keyboard/mouse input, so a video playing quietly
+# (no input for the whole runtime) still counts as "idle" and would get
+# covered by the screensaver. playerctl (already a dependency for the
+# media keybindings) reports MPRIS playback state for players that
+# support it (mpv, VLC, Firefox/Chromium, ...), so use that as an extra
+# "really idle" check.
+media_playing() {
+ command -v playerctl >/dev/null 2>&1 || return 1
+ [ "$(playerctl status 2>/dev/null)" = "Playing" ]
+}
+
stop_screensaver() {
pkill -f "$SCRIPT_DIR/screensaver\$" 2>/dev/null
pkill -x tte 2>/dev/null
@@ -28,9 +47,9 @@ while true; do
idle_ms=$(xssstate -i)
idle_s=$((idle_ms / 1000))
- if (( idle_s >= IDLE_SECONDS )) && ! is_running; then
+ if (( idle_s >= IDLE_SECONDS )) && ! is_running && ! media_playing && ! is_paused; then
"$SCRIPT_DIR/screensaver-launch"
- elif (( idle_s < 1 )) && is_running; then
+ elif is_running && { (( idle_s < 1 )) || media_playing || is_paused; }; then
stop_screensaver
fi