Bind the Stay Awake indicator to the idle service

The indicator polled omarchy-toggle-idle over a Process and re-ran it on
a timer to toggle, while the CLI called back into the shell over IPC to
apply and refresh the state it had just changed. Now the indicator binds
straight to the idle service's stayAwake property and flips it in
process. The CLI only touches the state file, which the service already
watches, so toggling from keybindings and scripts still reaches the
shell without any reentrant IPC.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-07-21 15:25:49 -07:00
co-authored by Claude Fable 5
parent 51d6d3c291
commit bee9ab476c
4 changed files with 35 additions and 42 deletions
-4
View File
@@ -33,15 +33,11 @@ apply_state() {
stay-awake)
mkdir -p "$STATE_DIR"
touch "$STATE_FILE"
omarchy-shell -q idle disable
;;
allow-idle)
rm -f "$STATE_FILE"
omarchy-shell -q idle enable
;;
esac
omarchy-shell -q omarchy.indicators refresh
}
case "${1:-toggle}" in
+4 -36
View File
@@ -1,51 +1,19 @@
import QtQuick
import Quickshell.Io
import qs.Ui
BarIndicator {
id: root
readonly property var idleService: bar?.shell?.firstPartyServiceFor("omarchy.idle")
active: idleService ? idleService.stayAwake : false
activeText: "󰅶"
inactiveText: "󰅶"
activeTooltipText: "Allow Idle Lock & Screensaver"
inactiveTooltipText: "Stay Awake"
function refresh() {
if (!statusProc.running) statusProc.running = true
}
function toggle() {
if (root.bar) root.bar.run("omarchy-toggle-idle")
refreshTimer.restart()
}
Component.onCompleted: refresh()
Connections {
target: root.indicatorHost
ignoreUnknownSignals: true
function onRefreshRequested() { root.refresh() }
}
Process {
id: statusProc
command: ["omarchy-toggle-idle", "--status"]
stdout: StdioCollector {
waitForEnd: true
onStreamFinished: {
var data = root.extractData(text)
root.active = data && data.enabled === true
}
}
onExited: function(exitCode) {
if (exitCode !== 0) root.active = false
}
}
Timer {
id: refreshTimer
interval: 1500
onTriggered: root.refresh()
if (root.idleService) root.idleService.setIdleEnabled(root.active)
}
onPressed: function() { root.toggle() }
@@ -24,10 +24,21 @@ ShellRoot {
}
}
QtObject {
id: idleService
property bool stayAwake: false
readonly property bool idleEnabled: !stayAwake
function setIdleEnabled(value) {
stayAwake = !value
}
}
QtObject {
id: mockShell
function firstPartyServiceFor(id) {
return id === "omarchy.notifications" ? notificationService : null
if (id === "omarchy.notifications") return notificationService
if (id === "omarchy.idle") return idleService
return null
}
}
@@ -151,7 +162,7 @@ ShellRoot {
stayAwake.moduleName = "StayAwake"
root.injectBar(stayAwake)
stayAwake.triggerPress(Qt.LeftButton)
root.assertTrue(root.commandCount("omarchy-toggle-idle") === 1, "Stay Awake left click runs idle toggle command")
root.assertTrue(idleService.stayAwake === true, "Stay Awake left click toggles the idle service")
}
root.writeResult()
+18
View File
@@ -34,3 +34,21 @@ assertDeepEqual(
'idle leaves screensaver windows unchanged without an address'
)
JS
test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT
test_home="$test_tmp/home"
mkdir -p "$test_home"
HOME="$test_home" "$ROOT/bin/omarchy-toggle-idle" stay-awake >/dev/null
[[ -f $test_home/.local/state/omarchy/indicators/stay-awake ]] || fail "Stay Awake toggle persists enabled state"
HOME="$test_home" "$ROOT/bin/omarchy-toggle-idle" allow-idle >/dev/null
[[ ! -f $test_home/.local/state/omarchy/indicators/stay-awake ]] || fail "Stay Awake toggle persists disabled state"
if rg -q 'omarchy-shell' "$ROOT/bin/omarchy-toggle-idle"; then
fail "Stay Awake toggle avoids reentrant shell IPC"
fi
pass "Stay Awake toggle persists state without reentrant shell IPC"