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
|
# status
Desktop modes as state: `dnd`, `presentation` and `nolock`, owned by the
`Status` singleton and stored as files under `$XDG_RUNTIME_DIR`.
## The files are the interface
$XDG_RUNTIME_DIR/status.dnd
$XDG_RUNTIME_DIR/status.presentation
$XDG_RUNTIME_DIR/status.nolock
Each holds `0` or `1`; a missing file means off. That directory is tmpfs, so a
reboot resets every mode and there is no cleanup code. A shell restart does
not: the files outlive the process and the singleton reads them back.
`nolock` is stored as "auto-lock disabled", which is the inverse of the switch
the page shows. The file keeps the registry's "missing means off" rule, and the
page inverts it so the label reads as the default: screen lock on.
Anything can read a mode with `cat`. `statusctl` is the convenience, not the
mechanism, which is why it keeps working while quickshell is down.
## statusctl
statusctl <mode> get prints 0 or 1
statusctl <mode> set 0|1
statusctl <mode> toggle
statusctl <mode> watch waybar JSON on every change
The repo copy is the source; the user installs it to `~/bin`. `watch` watches
the directory rather than the file, because an atomic write replaces the file
and a watch on the old inode dies with it.
Setting a mode with `statusctl` records the state without firing its effects.
The shell sees the change through its own `FileView` watch and asserts them,
so the effects follow either way. If the shell is down, the state is recorded
and reasserted when it returns.
## Effects
`dnd` has none of its own. It is state the notification daemon reads.
`presentation` sets `dnd` and `nolock`, asserts a Wayland idle inhibitor, and
pauses breaktimer. Turning it off restores `dnd` and `nolock` to the values
they had before rather than clearing them, so hand-set DND or a hand-set
disable survives a presentation.
`nolock` disables auto-lock by holding the idle inhibitor. That is the only
thing that stops hypridle's `loginctl lock-session`, so the mode governs
idle-triggered locking and nothing else: the `SUPER+l` bind and the lock on
suspend are separate paths and stay live. The page can set it permanently or
for a number of minutes, in which case the singleton's timer re-enables it.
The timer is shell-lifetime: a restart during a timed disable leaves the lock
off until it is toggled, the same class of limit as `dndBeforePresentation`.
breaktimer owns `$XDG_RUNTIME_DIR/breaktimer.state`. This module calls
`breaktimer.sh pause|resume` and never writes that file: its daemon loop
rewrites it on every phase change, and two writers would race.
## Waybar
`custom/presentation` reads `statusctl presentation watch`. It replaces
waybar's built-in `idle_inhibitor`, which cannot be kept alongside it: that
module owns its own inhibitor object, so both would have to be released
before the screen could lock.
## The check
./test-statusctl.sh
Points `XDG_RUNTIME_DIR` at a temporary directory, so it never touches live
modes. Covers the file format, the atomic write, the toggle, the unknown-mode
error, both the activated report and the absent-file off report.
|