Install the lock screen PAM stack and replace the missing screensaver effects

This commit is contained in:
2026-09-21 01:07:34 +00:00
parent 64afc07250
commit d316308bf5
10 changed files with 70 additions and 10 deletions
+2 -1
View File
@@ -2,7 +2,8 @@
# blob:summary=Launch the Blob screensaver in the default terminal on the system with the correct font configuration. # blob:summary=Launch the Blob screensaver in the default terminal on the system with the correct font configuration.
if blob-cmd-missing ttfx; then if ! blob-screensaver-effect >/dev/null; then
blob-notify-send -g ✋ "Screensaver needs ttfx or tte" "Install python-terminaltexteffects."
exit 1 exit 1
fi fi
+28 -5
View File
@@ -2,13 +2,37 @@
# blob:summary=Run the Blob screensaver using random effects from TTE. # blob:summary=Run the Blob screensaver using random effects from TTE.
effect_command=$(blob-screensaver-effect) || exit 1
effect_args() {
local input="$HOME/.config/blob/branding/screensaver.txt"
if [[ $effect_command == "ttfx" ]]; then
printf '%s\n' -i "$input" --frame-rate 120 --canvas-width 0 --canvas-height 0 \
--reuse-canvas --anchor-canvas c --anchor-text c --random-effect --no-eol \
--no-restore-cursor
return 0
fi
local effects=(
beams binarypath blackhole bouncyballs bubbles burn colorshift crumble
decrypt errorcorrect expand fireworks middleout orbittingvolley overflow
pour print rain randomsequence rings scattered slice slide spotlights
spray swarm sweep synthgrid unstable vhstape waves wipe
)
printf '%s\n' -i "$input" --frame-rate 120 --canvas-width 0 --canvas-height 0 \
--anchor-canvas c --anchor-text c --no-color \
"${effects[RANDOM % ${#effects[@]}]}"
}
screensaver_in_focus() { screensaver_in_focus() {
hyprctl activewindow -j | jq -e '.class == "org.blob.screensaver"' >/dev/null 2>&1 hyprctl activewindow -j | jq -e '.class == "org.blob.screensaver"' >/dev/null 2>&1
} }
exit_screensaver() { exit_screensaver() {
hyprctl eval 'hl.config({ cursor = { invisible = false } })' &>/dev/null || hyprctl keyword cursor:invisible false &>/dev/null || true hyprctl eval 'hl.config({ cursor = { invisible = false } })' &>/dev/null || hyprctl keyword cursor:invisible false &>/dev/null || true
pkill -x ttfx 2>/dev/null pkill -x "$effect_command" 2>/dev/null
pkill -f '[o]rg.blob.screensaver' 2>/dev/null pkill -f '[o]rg.blob.screensaver' 2>/dev/null
exit 0 exit 0
} }
@@ -36,11 +60,10 @@ wait_for_terminal_resize() {
wait_for_terminal_resize wait_for_terminal_resize
while true; do while true; do
ttfx -i ~/.config/blob/branding/screensaver.txt \ mapfile -t effect_arguments < <(effect_args)
--frame-rate 120 --canvas-width 0 --canvas-height 0 --reuse-canvas --anchor-canvas c --anchor-text c\ "$effect_command" "${effect_arguments[@]}" &
--random-effect --no-eol --no-restore-cursor &
while pgrep -t "${tty#/dev/}" -x ttfx >/dev/null; do while pgrep -t "${tty#/dev/}" -x "$effect_command" >/dev/null; do
if read -n1 -t 1 || ! screensaver_in_focus; then if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver exit_screensaver
fi fi
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# blob:summary=Print the terminal text effects command the screensaver can use
# blob:hidden=true
for candidate in ttfx tte; do
if command -v "$candidate" &>/dev/null; then
printf '%s\n' "$candidate"
exit 0
fi
done
exit 1
+4 -3
View File
@@ -20,7 +20,8 @@ if pgrep -x "1password" >/dev/null && blob-cmd-present 1password; then
fi fi
# Avoid running screensaver when locked # Avoid running screensaver when locked
pkill -x ttfx 2>/dev/null || true effect_command=$(blob-screensaver-effect 2>/dev/null) && {
# ttfx handles SIGTERM asynchronously, so keep its terminal alive until it exits. pkill -x "$effect_command" 2>/dev/null || true
timeout 1s pidwait -x ttfx 2>/dev/null || true timeout 1s pidwait -x "$effect_command" 2>/dev/null || true
}
pkill -f '[o]rg.blob.screensaver' 2>/dev/null || true pkill -f '[o]rg.blob.screensaver' 2>/dev/null || true
+2
View File
@@ -0,0 +1,2 @@
#%PAM-1.0
auth include system-auth
+13
View File
@@ -97,6 +97,7 @@ with `--check`.
| `/etc/sddm.conf.d/zz-blob.conf` | Wayland greeter, run on Hyprland, stock theme, remember the last session | | `/etc/sddm.conf.d/zz-blob.conf` | Wayland greeter, run on Hyprland, stock theme, remember the last session |
| `/etc/sddm/hyprland-greeter.lua` | the greeter's own tiny Hyprland config | | `/etc/sddm/hyprland-greeter.lua` | the greeter's own tiny Hyprland config |
| `/usr/local/bin/blob-hw-gpu-accelerated` | the renderer check that config runs, where SDDM's user can read it | | `/usr/local/bin/blob-hw-gpu-accelerated` | the renderer check that config runs, where SDDM's user can read it |
| `/etc/pam.d/blob-lock-password` | the PAM stack the lock screen authenticates against |
The greeter config matters more than it looks: SDDM's stock Wayland greeter The greeter config matters more than it looks: SDDM's stock Wayland greeter
runs on `weston`, which Blob does not install, so a default SDDM would fail runs on `weston`, which Blob does not install, so a default SDDM would fail
@@ -145,6 +146,18 @@ with `--check`.
| `--autologin` | skip the SDDM prompt for this user | | `--autologin` | skip the SDDM prompt for this user |
| `--no-launch` | leave the login screen for the next reboot | | `--no-launch` | leave the login screen for the next reboot |
## The lock screen
The lock plugin watches `/etc/pam.d/blob-lock-password` and refuses to lock at
all when it is not there - `blob system lock` returns `missing-pam` and nothing
appears, which reads as a keybinding that does nothing. The installer writes it;
it is one line including `system-auth`, the same stack every other Wayland
locker on Arch authenticates against.
Fingerprint unlock is separate and opt-in: `blob setup-security-fingerprint`
writes `/etc/pam.d/blob-lock-fingerprint`, and the lock only offers fingerprint
when that file and a reader are both present.
## Choosing a renderer ## Choosing a renderer
Hyprland renders through Mesa, and on an adapter Mesa has no driver for it exits Hyprland renders through Mesa, and on an adapter Mesa has no driver for it exits
+2 -1
View File
@@ -70,7 +70,7 @@ Two are worth knowing about:
``` ```
packages/blob.packages 121 packages from core, extra, multilib packages/blob.packages 121 packages from core, extra, multilib
packages/blob-aur.packages 10 packages with no official equivalent packages/blob-aur.packages 11 packages with no official equivalent
``` ```
Only missing packages are touched, through `pacman -S --needed` and Only missing packages are touched, through `pacman -S --needed` and
@@ -127,6 +127,7 @@ Omarchy's own package list, because they were installed by hand on this machine:
| Package | Needed by | | Package | Needed by |
| --- | --- | | --- | --- |
| `python-pywal16` | `blob-wallpaper-set`, palette extraction | | `python-pywal16` | `blob-wallpaper-set`, palette extraction |
| `python-terminaltexteffects` | `blob-screensaver`, the effects it draws |
| `awww` | the wallpaper daemon `blob-wallpaper-set` and `blob-theme-menu` drive | | `awww` | the wallpaper daemon `blob-wallpaper-set` and `blob-theme-menu` drive |
| `playerctl` | the quick settings media row | | `playerctl` | the quick settings media row |
+2
View File
@@ -21,6 +21,8 @@ install_login_config() {
"$blob_greeter_conf" "sddm.conf.d/zz-blob.conf" "$blob_greeter_conf" "sddm.conf.d/zz-blob.conf"
install_root_file "$repo_dir/bin/blob-hw-gpu-accelerated" \ install_root_file "$repo_dir/bin/blob-hw-gpu-accelerated" \
"$greeter_gpu_detector" "blob-hw-gpu-accelerated" 0755 "$greeter_gpu_detector" "blob-hw-gpu-accelerated" 0755
install_root_file "$repo_dir/default/pam.d/blob-lock-password" \
/etc/pam.d/blob-lock-password "pam.d/blob-lock-password"
} }
install_session_entry() { install_session_entry() {
+3
View File
@@ -6,6 +6,9 @@
# Palette extraction behind blob-wallpaper-set; pywal16 is the maintained fork # Palette extraction behind blob-wallpaper-set; pywal16 is the maintained fork
python-pywal16|python-pywal python-pywal16|python-pywal
# Terminal text effects behind the screensaver; ttfx was the Omarchy build
python-terminaltexteffects
# Terminal dispatch; every TUI launcher's Exec= line calls it # Terminal dispatch; every TUI launcher's Exec= line calls it
xdg-terminal-exec xdg-terminal-exec
+1
View File
@@ -9,6 +9,7 @@ session_entry="/usr/local/share/wayland-sessions/blob.desktop"
root_files=( root_files=(
/etc/profile.d/blob.sh /etc/profile.d/blob.sh
/usr/local/bin/blob-hw-gpu-accelerated /usr/local/bin/blob-hw-gpu-accelerated
/etc/pam.d/blob-lock-password
/etc/sddm.conf.d/zz-blob.conf /etc/sddm.conf.d/zz-blob.conf
/etc/sddm.conf.d/zzz-blob-autologin.conf /etc/sddm.conf.d/zzz-blob-autologin.conf
/etc/sddm/hyprland-greeter.conf /etc/sddm/hyprland-greeter.conf