swadhinbiswas Initial de-omarchy: Omarchy UI layer for Arch-based distros · 8/22/2026
9f393b2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/bash
# omarchy:summary=Lock before suspend and wait for the session lock to become secure
# omarchy:group=system
# omarchy:hidden=true
# Overrunning the budget is the failure this whole path exists to prevent:
# logind stops honouring the inhibitor and suspends mid-lock. Every call below
# is bounded by what is left of the budget, so the deadline enforces itself
# rather than depending on an estimate of how long a step ought to take.
budget_cap_ms=12000
lock_timeout_ms=1000
status_timeout_ms=500
poll_interval=0.1
# logind decides how long a delay inhibitor may hold the machine, and the
# shipped drop-in only counts once logind has reloaded it, so ask rather than
# assume. Leaving logind a fifth of its own window to deliver PrepareForSleep
# and act on the release gives 4s at the 5s default and 12s at the shipped 15s.
# The cap keeps a hand-raised window from stranding a closed laptop in a bag.
derive_budget_ms() {
local window
window=$(timeout --kill-after=0.1s 1s busctl get-property \
org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager InhibitDelayMaxUSec 2>/dev/null)
window=${window##* }
# An unreadable window means we cannot know, so assume logind's own default.
[[ $window =~ ^[0-9]+$ ]] && (( window > 0 )) || window=5000000
window=$((window / 1000))
# Never leave logind less than a second, however small its window is.
window=$((window - (window / 5 > 1000 ? window / 5 : 1000)))
(( window < budget_cap_ms )) && echo "$window" || echo "$budget_cap_ms"
}
budget_ms=${1:-$(derive_budget_ms)}
if [[ ! $budget_ms =~ ^[0-9]+$ ]] || (( budget_ms < 1 || budget_ms > budget_cap_ms )); then
budget_ms=$(derive_budget_ms)
fi
# EPOCHREALTIME renders with the locale's decimal separator, so drop every
# non-digit rather than assuming a period. A comma would otherwise read as
# bash's comma operator and silently void the deadline.
deadline_ms=$((10#${EPOCHREALTIME//[!0-9]/} / 1000 + budget_ms))
remaining_ms() {
echo $((deadline_ms - 10#${EPOCHREALTIME//[!0-9]/} / 1000))
}
# Clamping to what is left as well as to the call's own limit is what lets the
# loop below stay a plain "while there is time" without predicting step costs.
lock_ipc() {
local limit=$1 remaining seconds
shift
remaining=$(remaining_ms)
(( remaining > 0 )) || return 1
(( limit < remaining )) || limit=$remaining
printf -v seconds '%d.%03d' $((limit / 1000)) $((limit % 1000))
OMARCHY_SHELL_IPC_TIMEOUT="$seconds" \
timeout --kill-after=0.1s "$seconds" omarchy-shell "$@"
}
# The shell answers refusals on stdout with a zero exit, so the reply is the
# only way to spot a lock it can never perform. Nothing else needs inspecting:
# the status poll is what confirms success, and re-requesting is idempotent, so
# a request that may not have landed costs nothing to repeat.
request_lock() {
case $(lock_ipc "$lock_timeout_ms" lock lock 2>/dev/null) in
missing-pam) report_unsecured "no lock screen is configured" ;;
esac
}
# secure: done. locking: the shell has the request and is working on it, so
# leave it alone. Anything else, unreadable replies included, means ask again.
lock_state() {
jq -r 'if .secure == true then "secure"
elif .requested == true then "locking"
else "idle" end' \
<<<"$(lock_ipc "$status_timeout_ms" lock status 2>/dev/null)" 2>/dev/null
}
sync_clamshell() {
# Lid transitions can temporarily stall Hyprland IPC. This is best-effort:
# the lid binding and monitor watcher also reconcile clamshell state.
timeout --kill-after=0.1s 0.4s \
omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true
}
# logind suspends whether or not this wait succeeded, so a failure here means
# the machine slept with the session exposed. The notification is the only way
# anyone finds out, and it lands on the screen they unlock into.
report_unsecured() {
printf 'omarchy-system-sleep-lock: suspending without a secure lock (%s)\n' \
"$1" >&2
omarchy-notification-send -u critical -g \
"Screen did not lock before suspend" \
"The session was left unlocked ($1)." >/dev/null 2>&1 || true
exit 1
}
# Request the lock before touching monitor state, so a stuck Hyprland IPC call
# cannot consume the window before Quickshell has begun securing the session.
request_lock
sync_clamshell
# The trailing sleep can overshoot the deadline by one interval, which is well
# inside the reserve derive_budget_ms already held back for logind.
while (( $(remaining_ms) > 0 )); do
case $(lock_state) in
secure) exit 0 ;;
locking) ;;
*) request_lock ;;
esac
sleep "$poll_interval"
done
report_unsecured "the shell did not secure the session within ${budget_ms}ms"