hyprlock: disable fingerprint, add battery/weather/notifications

- Disable fingerprint auth (GDM holds the device; hyprlock can't
  claim it, blocking the auth thread).
- Fix date format escaping (single quotes).
- Add battery, weather, and latest mako notification labels.
- Add hyprlock wrapper (crash guard), battery script, notifications
  script, and weather script.
This commit is contained in:
2026-08-18 08:02:50 -06:00
parent 9e310d2f58
commit 1755d17558
5 changed files with 161 additions and 3 deletions
+34
View File
@@ -0,0 +1,34 @@
#!/usr/bin/env bash
# Print the current weather as a short icon+temp string, e.g. "🌦️ +83°F".
# Caches the wttr.in response for CACHE_MAX_AGE seconds so the lock screen and
# waybar don't hit the network on every refresh. Override the location with
# WEATHER_CITY or edit CITY below.
set -u
CITY="${WEATHER_CITY:-Denver}"
CACHE_DIR="${XDG_RUNTIME_DIR:-/tmp}"
CACHE="${CACHE_DIR}/wttr.cache"
CACHE_MAX_AGE=1800 # 30 minutes
URL="https://wttr.in/${CITY}?format=%c+%t"
cache_age() {
[ -f "${CACHE}" ] || return 1
now=$(date +%s)
mtime=$(stat -c %Y "${CACHE}")
[ "$(( now - mtime ))" -lt "${CACHE_MAX_AGE}" ]
}
if cache_age; then
cat "${CACHE}"
exit 0
fi
TMP="${CACHE}.tmp.$$"
if curl -fsS --max-time 10 "${URL}" > "${TMP}" 2>/dev/null; then
mv "${TMP}" "${CACHE}"
cat "${CACHE}"
else
rm -f "${TMP}" || true
# Offline: fall back to whatever we cached last, even if stale.
[ -f "${CACHE}" ] && cat "${CACHE}"
fi
+42 -3
View File
@@ -7,14 +7,17 @@ $font = JetBrainsMono Nerd Font
# General
general {
disable_loading_bar = false
hide_cursor = false
}
# Authentication
# Fingerprint is disabled: GDM's login worker (pam/gdm-fingerprint) holds the
# device for the whole session, so hyprlock can never claim it -- the failed
# claim blocked the auth thread and made unlocks appear stuck. Fingerprint is
# still available at the GDM login screen; hyprlock is password-only.
auth {
fingerprint {
enabled = true
enabled = false
ready_message = Scan fingerprint to unlock
present_message = Scanning...
retry_delay = 250 # in milliseconds
@@ -45,7 +48,7 @@ label {
# Date
label {
monitor =
text = cmd[update:43200000] echo "$(date + "%A, %d %B %Y")"
text = cmd[update:43200000] echo "$(date +'%A, %d %B %Y')"
color = $text
font_size = 25
font_family = $font
@@ -54,6 +57,30 @@ label {
valign = top
}
# Battery
label {
monitor =
text = cmd[update:60000] $HOME/.local/bin/hyprlock-battery.sh
color = $subtext1
font_size = 20
font_family = $font
position = -30, -190
halign = right
valign = top
}
# Weather
label {
monitor =
text = cmd[update:600000] $HOME/.local/bin/weather.sh
color = $subtext1
font_size = 20
font_family = $font
position = -30, -215
halign = right
valign = top
}
# User Avatar
image {
monitor =
@@ -66,6 +93,18 @@ image {
valign = center
}
# Notifications (latest mako notification; empty when none)
label {
monitor =
text = cmd[update:5000] $HOME/.local/bin/hyprlock-notifications.sh
color = $subtext0
font_size = 16
font_family = $font
position = 0, 60
halign = center
valign = bottom
}
# Input Field
input-field {
monitor =
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Guard wrapper for hyprlock (0.9.x): upstream has crashes on DPMS-off / monitor
# power transitions while the lock screen is running (hyprlock#991, #953, #695).
# If the real hyprlock dies, this restarts it so the session doesn't end up in a
# "lockscreen app died" state. Requires misc:allow_session_lock_restore = true
# in Hyprland config for the replacement lock to be accepted.
set -u
REAL_HYPRLOCK=/usr/bin/hyprlock
MAX_RESTARTS=20
restart=0
while true; do
"$REAL_HYPRLOCK" "$@"
code=$?
# 0: exited cleanly (e.g. unlocked) -- done.
# 1: auth failed, retry -- let the loop back off and try again.
if [ "$code" -eq 0 ]; then
exit 0
fi
restart=$((restart + 1))
if [ "$restart" -ge "$MAX_RESTARTS" ]; then
exit "$code"
fi
# Brief pause so a crash loop doesn't burn CPU (fade back in quickly).
sleep 0.5
done
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Battery status for the hyprlock screen, e.g. " 18%".
# Uses the first battery found under /sys/class/power_supply (BAT0/BAT1, ...);
# prints nothing on desktops without a battery.
set -u
bat=""
for b in /sys/class/power_supply/BAT*; do
if [ -r "${b}/capacity" ]; then
bat="${b}"
break
fi
done
[ -z "${bat}" ] && exit 0
cap="$(cat "${bat}/capacity" 2>/dev/null || echo 0)"
status="$(cat "${bat}/status" 2>/dev/null || echo Unknown)"
case "${status}" in
Charging|Full)
icon=""
;;
*)
if [ "${cap}" -ge 80 ]; then
icon=""
elif [ "${cap}" -ge 60 ]; then
icon=""
elif [ "${cap}" -ge 40 ]; then
icon=""
elif [ "${cap}" -ge 20 ]; then
icon=""
else
icon=""
fi
;;
esac
printf '%s %s%%' "${icon}" "${cap}"
+15
View File
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# Latest mako notification for the hyprlock screen, Pango-escaped, e.g.
# "Battery test: Battery at 18%". Prints nothing when there are no
# notifications, so the label renders empty.
set -u
makoctl list -j 2>/dev/null | jq -r '
if length == 0 then
empty
else
.[-1] as $n |
(if $n.app_name != null and $n.app_name != "" then $n.app_name + ": " else "" end) +
($n.summary // "") +
(if $n.body != null and $n.body != "" then " — " + $n.body[0:80] else "" end)
end' 2>/dev/null | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g'