merge main incl conflict resolution
This commit is contained in:
@@ -0,0 +1,32 @@
|
|||||||
|
# hypridle.conf — idle stages: screensaver (300s, backend in modules/screensaver.lua) -> Noctalia lock (10min) -> DPMS off.
|
||||||
|
# Managed by dotfiles (stow hypr).
|
||||||
|
#
|
||||||
|
# NOTE: this Hyprland (hyprmod Lua runtime, 0.56.x) evaluates `hyprctl dispatch`
|
||||||
|
# args as Lua — classic `dispatch dpms off` syntax fails. Dispatchers must be
|
||||||
|
# hl.dsp.* expressions (e.g. hl.dsp.dpms(false)).
|
||||||
|
|
||||||
|
general {
|
||||||
|
lock_cmd = pidof -q noctalia || noctalia msg session lock
|
||||||
|
before_sleep_cmd = loginctl lock-session
|
||||||
|
after_sleep_cmd = hyprctl dispatch 'hl.dsp.dpms(true)'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Screensaver via backend wrappers (switch backend in modules/screensaver.lua).
|
||||||
|
listener {
|
||||||
|
timeout = 300
|
||||||
|
on-timeout = ~/.config/hypr/scripts/screensaver-start.sh
|
||||||
|
on-resume = ~/.config/hypr/scripts/screensaver-stop.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
# 10min: lock via Noctalia (SUPER+L runs the same command).
|
||||||
|
listener {
|
||||||
|
timeout = 600
|
||||||
|
on-timeout = loginctl lock-session
|
||||||
|
}
|
||||||
|
|
||||||
|
# 10m30s: power off displays.
|
||||||
|
listener {
|
||||||
|
timeout = 630
|
||||||
|
on-timeout = hyprctl dispatch 'hl.dsp.dpms(false)'
|
||||||
|
on-resume = hyprctl dispatch 'hl.dsp.dpms(true)'
|
||||||
|
}
|
||||||
@@ -32,6 +32,10 @@ hl.on("hyprland.start", function()
|
|||||||
hl.exec_cmd("caelestia shell -d")
|
hl.exec_cmd("caelestia shell -d")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
hl.on("hyprland.start", function()
|
||||||
|
hl.exec_cmd("hypridle &")
|
||||||
|
end)
|
||||||
|
|
||||||
hl.on("hyprland.start", function()
|
hl.on("hyprland.start", function()
|
||||||
hl.exec_cmd("sh ~/.config/hypr/scripts/portal-host-override.sh")
|
hl.exec_cmd("sh ~/.config/hypr/scripts/portal-host-override.sh")
|
||||||
hl.exec_cmd("sh ~/.config/hypr/scripts/ensure-mime-defaults.sh")
|
hl.exec_cmd("sh ~/.config/hypr/scripts/ensure-mime-defaults.sh")
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# hyprsaver.toml — chill playlist: calm shaders + cool palettes, cycling.
|
||||||
|
# Location: ~/.config/hypr/hyprsaver.toml (stowed from dotfiles).
|
||||||
|
# Names verified against `hyprsaver --list-shaders` / `--list-palettes`.
|
||||||
|
# Everything else uses hyprsaver's built-in defaults (see
|
||||||
|
# /usr/share/hyprsaver/examples/config.toml for the full reference).
|
||||||
|
|
||||||
|
[general]
|
||||||
|
fps = 30
|
||||||
|
shader = "cycle"
|
||||||
|
palette = "cycle"
|
||||||
|
shader_cycle_interval = 300
|
||||||
|
palette_cycle_interval = 60
|
||||||
|
cycle_order = "random"
|
||||||
|
synced = true
|
||||||
|
shader_playlist = "chill"
|
||||||
|
palette_playlist = "chill"
|
||||||
|
|
||||||
|
[playlists.chill]
|
||||||
|
shaders = [
|
||||||
|
"plasma",
|
||||||
|
"marble",
|
||||||
|
"snowfall",
|
||||||
|
"aurora",
|
||||||
|
"clouds",
|
||||||
|
"planet",
|
||||||
|
"starfield",
|
||||||
|
"fireflies",
|
||||||
|
]
|
||||||
|
palettes = [
|
||||||
|
"vaporwave",
|
||||||
|
"frost",
|
||||||
|
"ocean",
|
||||||
|
"aurora",
|
||||||
|
]
|
||||||
|
|
||||||
|
[behavior]
|
||||||
|
fade_in_ms = 800
|
||||||
|
fade_out_ms = 400
|
||||||
|
dismiss_on = ["key", "mouse_move", "mouse_click", "touch"]
|
||||||
|
exclusive_keyboard = true
|
||||||
@@ -226,6 +226,7 @@ hl.bind("SHIFT + PRINT", hl.dsp.exec_cmd("hyprshot -m active --output-folder " .
|
|||||||
})
|
})
|
||||||
|
|
||||||
hl.bind(var.mainMod .. " + L", hl.dsp.exec_cmd(command.lock), { locked = true, description = "Lock screen" })
|
hl.bind(var.mainMod .. " + L", hl.dsp.exec_cmd(command.lock), { locked = true, description = "Lock screen" })
|
||||||
|
hl.bind(var.mainMod .. " + SHIFT + L", hl.dsp.exec_cmd(command.screensaver), { description = "Start screensaver (any key quits)" })
|
||||||
hl.bind(var.mainMod .. " + K", hl.dsp.exec_cmd(command.keybinds_show), { description = "Show keybind overview" })
|
hl.bind(var.mainMod .. " + K", hl.dsp.exec_cmd(command.keybinds_show), { description = "Show keybind overview" })
|
||||||
hl.bind(var.mainMod .. " + W", hl.dsp.exec_cmd(command.wallpaper_select), { description = "Wallpaper select" })
|
hl.bind(var.mainMod .. " + W", hl.dsp.exec_cmd(command.wallpaper_select), { description = "Wallpaper select" })
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
-- Screensaver commands for idle (hypridle on-timeout/on-resume) and manual
|
||||||
|
-- (SUPER+SHIFT+L) use. scripts/screensaver-start.sh and
|
||||||
|
-- scripts/screensaver-stop.sh exec the .start / .stop command below.
|
||||||
|
--
|
||||||
|
-- Active backend: tte (fullscreen kitty + terminal-text-effects).
|
||||||
|
return {
|
||||||
|
start = "~/.config/hypr/scripts/launch-screensaver.sh",
|
||||||
|
stop = "~/.config/hypr/scripts/screensaver-stop.sh",
|
||||||
|
-- Alternative backend: hyprsaver (GPU fractal shaders, wlr-layer-shell).
|
||||||
|
-- Swap the commented pair in to switch (no other file changes needed).
|
||||||
|
-- start = "hyprsaver",
|
||||||
|
-- stop = "hyprsaver --quit",
|
||||||
|
}
|
||||||
@@ -20,4 +20,5 @@ return {
|
|||||||
show_all = "caelestia shell drawers toggle utilities",
|
show_all = "caelestia shell drawers toggle utilities",
|
||||||
clear_notifications = "caelestia shell notifs clear",
|
clear_notifications = "caelestia shell notifs clear",
|
||||||
keybinds_show = "sh ~/.config/hypr/scripts/show-keybinds.sh",
|
keybinds_show = "sh ~/.config/hypr/scripts/show-keybinds.sh",
|
||||||
|
screensaver = "sh ~/.config/hypr/scripts/screensaver-start.sh force",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,6 +103,16 @@ hl.window_rule({
|
|||||||
border_size = 0,
|
border_size = 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Manual tte screensaver preview (SUPER+SHIFT+L): fullscreen kitty.
|
||||||
|
hl.window_rule({
|
||||||
|
name = "screensaver-fullscreen",
|
||||||
|
match = {
|
||||||
|
class = "org.screensaver",
|
||||||
|
},
|
||||||
|
fullscreen = true,
|
||||||
|
float = true,
|
||||||
|
})
|
||||||
|
|
||||||
-- windowrule {
|
-- windowrule {
|
||||||
|
|
||||||
-- name = no-rounding-steam-games
|
-- name = no-rounding-steam-games
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
hyprland
|
||||||
|
// idle looks good on you
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# launch-screensaver.sh — idle-triggered tte screensaver (hypridle on-timeout).
|
||||||
|
# Spawns one fullscreen kitty running screensaver-tte.sh per monitor.
|
||||||
|
# Usage: launch-screensaver.sh [force]
|
||||||
|
# force ignore the screensaver-off toggle file.
|
||||||
|
# Toggle off: touch ~/.local/state/hypr/screensaver-off
|
||||||
|
#
|
||||||
|
# Lessons baked in: no focus-restore after spawn (it raced the new window and
|
||||||
|
# caused flash-then-nothing), no pkill -f patterns anywhere (teardown is done
|
||||||
|
# by screensaver-stop.sh via exact client PIDs).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCREENSAVER_CLASS="org.screensaver"
|
||||||
|
TOGGLE_FILE="$HOME/.local/state/hypr/screensaver-off"
|
||||||
|
|
||||||
|
command -v tte >/dev/null 2>&1 || exit 1
|
||||||
|
command -v kitty >/dev/null 2>&1 || exit 1
|
||||||
|
|
||||||
|
# Already running (precise client check).
|
||||||
|
if hyprctl clients -j 2>/dev/null | jq -e '.[] | select(.class=="org.screensaver")' >/dev/null 2>&1; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Opt-out toggle (unless forced, e.g. manual invocation).
|
||||||
|
if [[ -f "$TOGGLE_FILE" ]] && [[ "${1:-}" != "force" ]]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
# hyprctl prints plain-text errors (not JSON) when HYPRLAND_INSTANCE_SIGNATURE
|
||||||
|
# is stale (e.g. shell/tmux predates the current compositor). Fail clearly
|
||||||
|
# instead of dumping a jq parse error.
|
||||||
|
monitors_json="$(hyprctl monitors -j 2>/dev/null)" || {
|
||||||
|
echo "launch-screensaver: hyprctl failed - is HYPRLAND_INSTANCE_SIGNATURE stale? (try a fresh terminal)" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
echo "$monitors_json" | jq -e . >/dev/null 2>&1 || {
|
||||||
|
echo "launch-screensaver: hyprctl did not return JSON - stale HYPRLAND_INSTANCE_SIGNATURE?" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE: hyprmod Lua runtime (Hyprland 0.56.x) evaluates `hyprctl dispatch` args
|
||||||
|
# as Lua — classic `dispatch focusmonitor eDP-1` fails. Dispatchers must be
|
||||||
|
# hl.dsp.* expressions. Focus each monitor before exec so the saver kitty
|
||||||
|
# spawns there; deliberately no focus-restore afterwards (spawn race).
|
||||||
|
for m in $(echo "$monitors_json" | jq -r '.[] | .name'); do
|
||||||
|
hyprctl dispatch "hl.dsp.focus({monitor=\"$m\"})" >/dev/null 2>&1
|
||||||
|
hyprctl dispatch "hl.dsp.exec_cmd('kitty --class=\"$SCREENSAVER_CLASS\" --override font_size=18 --override window_padding_width=0 --override background_opacity=1 --override mouse_hide_wait=1.0 -e \"$SCRIPT_DIR/screensaver-tte.sh\"')" >/dev/null 2>&1
|
||||||
|
done
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# screensaver-start.sh — exec the start command from modules/screensaver.lua.
|
||||||
|
# Usage: screensaver-start.sh [force] (forwarded to .sh targets, e.g. the tte
|
||||||
|
# launcher's toggle bypass; dropped for bare commands like `hyprsaver`).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
CMD="$(lua -e 'print(dofile(os.getenv("HOME").."/.config/hypr/modules/screensaver.lua").start)' 2>/dev/null)" || {
|
||||||
|
echo "screensaver-start: cannot read modules/screensaver.lua" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
CMD="${CMD/#\~/$HOME}"
|
||||||
|
[[ -n "$CMD" ]] || {
|
||||||
|
echo "screensaver-start: empty start command" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$CMD" == *.sh ]]; then
|
||||||
|
exec "$CMD" "$@"
|
||||||
|
else
|
||||||
|
# Bare command, may carry flags (e.g. "hyprsaver --quit").
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
exec $CMD
|
||||||
|
fi
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# screensaver-stop.sh — exec the stop command from modules/screensaver.lua.
|
||||||
|
# When it points back here (tte backend), run the built-in teardown below:
|
||||||
|
# kill saver windows by Hyprland client PID (class org.screensaver) plus
|
||||||
|
# stray tte processes (exact comm match). Never `pkill -f <pattern>`: a
|
||||||
|
# full-cmdline pattern also matches bystander shells merely mentioning it.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
ME="$(realpath "$SCRIPT_DIR/screensaver-stop.sh")"
|
||||||
|
|
||||||
|
WANT="$(lua -e 'print(dofile(os.getenv("HOME").."/.config/hypr/modules/screensaver.lua").stop)' 2>/dev/null)" || {
|
||||||
|
echo "screensaver-stop: cannot read modules/screensaver.lua" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
WANT="${WANT/#\~/$HOME}"
|
||||||
|
|
||||||
|
# Alternative backend configured (e.g. "hyprsaver --quit"): run it instead.
|
||||||
|
if [[ "$(realpath -m "$WANT")" != "$ME" ]]; then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
exec $WANT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- tte teardown ---
|
||||||
|
pids="$(hyprctl clients -j 2>/dev/null | jq -r '.[] | select(.class=="org.screensaver") | .pid' 2>/dev/null)" || pids=""
|
||||||
|
if [[ -n "${pids:-}" ]]; then
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
kill $pids 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# tte runs under comm "tte" (verified); -x matches the comm only, so this
|
||||||
|
# cannot hit bystander shells.
|
||||||
|
pkill -x tte 2>/dev/null || true
|
||||||
|
|
||||||
|
exit 0
|
||||||
Executable
+41
@@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# screensaver-tte.sh — runs inside each fullscreen tte kitty.
|
||||||
|
# Loops random tte effects until any keypress, then exits (kitty closes).
|
||||||
|
# Child teardown uses the exact PID ($!) — never pkill -f patterns, which
|
||||||
|
# would also match bystander shells mentioning the class name.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCREENSAVER_TEXT="$HOME/.config/hypr/screensaver.txt"
|
||||||
|
|
||||||
|
trap 'exit 0' SIGINT SIGTERM SIGHUP SIGQUIT
|
||||||
|
|
||||||
|
printf '\033]11;rgb:00/00/00\007' # black background
|
||||||
|
|
||||||
|
input="$SCREENSAVER_TEXT"
|
||||||
|
[[ -f "$input" ]] || input="/etc/hostname"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
tte -i "$input" \
|
||||||
|
--frame-rate 60 --canvas-width 0 --canvas-height 0 \
|
||||||
|
--anchor-canvas c --anchor-text c \
|
||||||
|
--random-effect --exclude-effects dev_worm \
|
||||||
|
--no-eol --no-restore-cursor &
|
||||||
|
TPID=$!
|
||||||
|
# Wait for tte to appear (Python startup) before polling it.
|
||||||
|
for _ in $(seq 1 10); do
|
||||||
|
kill -0 "$TPID" 2>/dev/null || break
|
||||||
|
pgrep -x tte >/dev/null 2>&1 && break
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
while kill -0 "$TPID" 2>/dev/null; do
|
||||||
|
if read -r -n1 -t 1; then
|
||||||
|
kill "$TPID" 2>/dev/null || true
|
||||||
|
wait "$TPID" 2>/dev/null || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
wait "$TPID" 2>/dev/null || true
|
||||||
|
# Throttle respawn if tte exits instantly (e.g. a sub-second effect).
|
||||||
|
sleep 0.2
|
||||||
|
done
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
@pacman
|
@pacman
|
||||||
hyprland
|
hyprland
|
||||||
|
hypridle
|
||||||
xdg-desktop-portal-hyprland
|
xdg-desktop-portal-hyprland
|
||||||
hyprpolkitagent
|
hyprpolkitagent
|
||||||
pantheon-shortcut-overlay
|
pantheon-shortcut-overlay
|
||||||
@@ -27,3 +28,5 @@ hyprmod
|
|||||||
caelestia-shell
|
caelestia-shell
|
||||||
caelestia-cli
|
caelestia-cli
|
||||||
quickshell-git
|
quickshell-git
|
||||||
|
hyprsaver
|
||||||
|
python-terminaltexteffects
|
||||||
|
|||||||
Reference in New Issue
Block a user