Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Screensaver opens as a small floating window and self-terminates after 1s when a bar panel is open
Reported by echelonzero · filed Aug 15, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
Screensaver opens as a small floating window and self-terminates after 1s when a bar panel is open
Summary
When any bar widget panel (e.g. the power/battery dropdown) is open at the moment the idle
timer fires, the screensaver misbehaves in two ways at once:
- It does not go fullscreen — it appears as a small floating terminal window in the
middle of the screen, at foot's default 700x500.
2. It kills itself after ~1.05 seconds, without any user input.
The visible result is a small box that pops up, animates briefly, and disappears on its own.
The idle service logs this as screensaver-dismissed and cancels the pending lock, so **the
session also fails to lock** on that cycle.
Both symptoms trace to the panel holding layer-shell keyboard focus.
Environment
| Omarchy | 4.0.0-1 |
| Hyprland | v0.56.2 |
| Quickshell | 0.3.0 (28771c7c, AUR quickshell-git) |
| foot | 1.27.0 |
| ttfx | 0.3.1 |
| Kernel | 6.19.8-arch1-3-surface |
| CPU | Intel i7-1185G7 (Tiger Lake) |
| GPU | Intel Iris Xe (TigerLake-LP GT2) |
| Display | single eDP-1, 2880x1920, scale = 2 |
| Terminal | foot (xdg-terminal-exec --print-id → foot.desktop) |
idle.screensaver = 150, idle.lock = 300 in ~/.config/omarchy/shell.json.
Steps to reproduce
Deterministic, no waiting for the idle timer:
# 1. Open any bar panel built on KeyboardPanel
omarchy-shell omarchy.power open
# 2. Launch the screensaver the same way the idle service does
omarchy-launch-screensaver forceResult: a small floating terminal appears centered, runs the ttfx animation, and exits by
itself after about one second.
Control — the identical command with the panel closed produces a correct fullscreen
screensaver that persists:
omarchy-shell omarchy.power close
omarchy-launch-screensaver forceIn normal use this happens whenever you leave the battery/power dropdown open and walk away.
Expected vs actual
Expected: the screensaver covers the screen and stays up until real user input, then the
lock fires at idle.lock.
Actual: a small floating box appears for ~1s and self-terminates. The idle service reads
the window closing as a user dismissal, cancels the cycle, and the machine never locks.
Evidence
Window state sampled every 100ms via hyprctl clients -j, same command, only the panel state
differs:
| panel closed (control) | panel open | |
|---|---|---|
fullscreen | 2 | `0` |
size | [1440, 960] (full screen) | `[700, 500]` (foot default) |
floating | true | true |
| lifetime | persisted past 2.6s | 1.08s, exited on its own |
Focus sampled every 50ms across a naturally-occurring failure (window opened 22:40:34.937):
34.944 NOTFOCUS class=foot <- 7ms after map; screensaver never got focus
... (167/167 samples NOTFOCUS class=foot)
35.982 idle-cycle-cancel: screensaver-dismissedLifetime 34.937 → 35.982 = 1.045s.
Across five separate naturally-occurring failures, window-open → dismissal was
1.046, 1.044, 1.228, 1.235, 1.235s — each one exactly 1.000s (the read -n1 -t 1
timeout) plus a short wait_for_terminal_resize prefix. No human input was involved.
Root cause
Bar panels are built on KeyboardPanel, which takes layer-shell keyboard focus while open
(shell/Ui/KeyboardPanel.qml:98; the power panel instantiates it atshell/plugins/panels/power/Panel.qml:292):
WlrLayershell.keyboardFocus: open
? (focusPrimed ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive)
: WlrKeyboardFocus.NoneThat single condition breaks the screensaver twice.
1. The fullscreen window rule never applies
With the panel holding focus, the newly mapped screensaver window does not become the active
toplevel, so fullscreen = true (default/hypr/apps/system.lua:35) does not take effect. The
adjacent float = true (line 36) does, leaving a floating window at foot's default 700x500 —
the small centered box.
2. The watchdog mistakes "never had focus" for "user dismissed me"
bin/omarchy-screensaver:5:
screensaver_in_focus() {
hyprctl activewindow -j | jq -e '.class == "org.omarchy.screensaver"' >/dev/null 2>&1
}hyprctl activewindow only reports toplevel windows — layer surfaces are invisible to it.
With the panel focused it returns the last focused toplevel (here foot), so the check returns
false even though nothing the user did caused it.
At the first tick of the watch loop (bin/omarchy-screensaver:44):
if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver
firead times out at 1.000s, screensaver_in_focus is false, and the screensaver pkills
itself (bin/omarchy-screensaver:12). The idle service then observes closewindow, treats it
as screensaver-dismissed, and cancels the pending lock.
The check has no way to distinguish lost focus from never acquired focus, and no awareness
of layer-shell focus.
Suggested fixes
Any one of these addresses it; the first two are the smallest:
- Close open bar panels before launching the screensaver, or skip the launch while a
keyboard-focus panel is open (the idle service already shells out, so this is one more call).
- Don't run the focus check until the screensaver has been focused at least once. Latch a
"was focused" flag and only treat focus loss as dismissal after that, which also removes the
fixed 1s window where a slow-mapping window can be killed.
- Make the focus check layer-aware, e.g. treat "no active toplevel / a layer surface holds
focus" as not-a-dismissal rather than as a dismissal.
- Consider making the screensaver a layer-shell overlay rather than a toplevel terminal window,
which sidesteps both the fullscreen-rule race and the focus check entirely.
Additional note
exit_screensaver uses pkill -f '[o]rg.omarchy.screensaver' (bin/omarchy-screensaver:12).
The [o] guard only protects against matching the pgrep/pkill process itself — it still
matches any process whose command line contains that string. Scripts or tooling that mention
the class by name (including diagnostics for this very bug) get killed as collateral. Matching
on PID or window address would be safer.
View raw text
# Screensaver opens as a small floating window and self-terminates after 1s when a bar panel is open
## Summary
When any bar widget panel (e.g. the power/battery dropdown) is open at the moment the idle
timer fires, the screensaver misbehaves in two ways at once:
1. It does **not** go fullscreen — it appears as a small floating terminal window in the
middle of the screen, at foot's default 700x500.
2. It **kills itself after ~1.05 seconds**, without any user input.
The visible result is a small box that pops up, animates briefly, and disappears on its own.
The idle service logs this as `screensaver-dismissed` and cancels the pending lock, so **the
session also fails to lock** on that cycle.
Both symptoms trace to the panel holding layer-shell keyboard focus.
## Environment
| | |
|---|---|
| Omarchy | 4.0.0-1 |
| Hyprland | v0.56.2 |
| Quickshell | 0.3.0 (`28771c7c`, AUR `quickshell-git`) |
| foot | 1.27.0 |
| ttfx | 0.3.1 |
| Kernel | 6.19.8-arch1-3-surface |
| CPU | Intel i7-1185G7 (Tiger Lake) |
| GPU | Intel Iris Xe (TigerLake-LP GT2) |
| Display | single eDP-1, 2880x1920, `scale = 2` |
| Terminal | foot (`xdg-terminal-exec --print-id` → `foot.desktop`) |
`idle.screensaver = 150`, `idle.lock = 300` in `~/.config/omarchy/shell.json`.
## Steps to reproduce
Deterministic, no waiting for the idle timer:
```bash
# 1. Open any bar panel built on KeyboardPanel
omarchy-shell omarchy.power open
# 2. Launch the screensaver the same way the idle service does
omarchy-launch-screensaver force
```
**Result:** a small floating terminal appears centered, runs the ttfx animation, and exits by
itself after about one second.
**Control** — the identical command with the panel closed produces a correct fullscreen
screensaver that persists:
```bash
omarchy-shell omarchy.power close
omarchy-launch-screensaver force
```
In normal use this happens whenever you leave the battery/power dropdown open and walk away.
## Expected vs actual
**Expected:** the screensaver covers the screen and stays up until real user input, then the
lock fires at `idle.lock`.
**Actual:** a small floating box appears for ~1s and self-terminates. The idle service reads
the window closing as a user dismissal, cancels the cycle, and the machine never locks.
## Evidence
Window state sampled every 100ms via `hyprctl clients -j`, same command, only the panel state
differs:
| | panel closed (control) | panel open |
|---|---|---|
| `fullscreen` | `2` | **`0`** |
| `size` | `[1440, 960]` (full screen) | **`[700, 500]`** (foot default) |
| `floating` | `true` | `true` |
| lifetime | persisted past 2.6s | **1.08s**, exited on its own |
Focus sampled every 50ms across a naturally-occurring failure (window opened 22:40:34.937):
```
34.944 NOTFOCUS class=foot <- 7ms after map; screensaver never got focus
... (167/167 samples NOTFOCUS class=foot)
35.982 idle-cycle-cancel: screensaver-dismissed
```
Lifetime 34.937 → 35.982 = **1.045s**.
Across five separate naturally-occurring failures, window-open → dismissal was
**1.046, 1.044, 1.228, 1.235, 1.235s** — each one exactly 1.000s (the `read -n1 -t 1`
timeout) plus a short `wait_for_terminal_resize` prefix. No human input was involved.
## Root cause
Bar panels are built on `KeyboardPanel`, which takes layer-shell keyboard focus while open
(`shell/Ui/KeyboardPanel.qml:98`; the power panel instantiates it at
`shell/plugins/panels/power/Panel.qml:292`):
```qml
WlrLayershell.keyboardFocus: open
? (focusPrimed ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive)
: WlrKeyboardFocus.None
```
That single condition breaks the screensaver twice.
### 1. The fullscreen window rule never applies
With the panel holding focus, the newly mapped screensaver window does not become the active
toplevel, so `fullscreen = true` (`default/hypr/apps/system.lua:35`) does not take effect. The
adjacent `float = true` (line 36) *does*, leaving a floating window at foot's default 700x500 —
the small centered box.
### 2. The watchdog mistakes "never had focus" for "user dismissed me"
`bin/omarchy-screensaver:5`:
```bash
screensaver_in_focus() {
hyprctl activewindow -j | jq -e '.class == "org.omarchy.screensaver"' >/dev/null 2>&1
}
```
`hyprctl activewindow` only reports **toplevel** windows — layer surfaces are invisible to it.
With the panel focused it returns the last focused toplevel (here `foot`), so the check returns
false even though nothing the user did caused it.
At the first tick of the watch loop (`bin/omarchy-screensaver:44`):
```bash
if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver
fi
```
`read` times out at 1.000s, `screensaver_in_focus` is false, and the screensaver `pkill`s
itself (`bin/omarchy-screensaver:12`). The idle service then observes `closewindow`, treats it
as `screensaver-dismissed`, and cancels the pending lock.
The check has no way to distinguish *lost* focus from *never acquired* focus, and no awareness
of layer-shell focus.
## Suggested fixes
Any one of these addresses it; the first two are the smallest:
- **Close open bar panels before launching the screensaver**, or skip the launch while a
keyboard-focus panel is open (the idle service already shells out, so this is one more call).
- **Don't run the focus check until the screensaver has been focused at least once.** Latch a
"was focused" flag and only treat focus loss as dismissal after that, which also removes the
fixed 1s window where a slow-mapping window can be killed.
- **Make the focus check layer-aware**, e.g. treat "no active toplevel / a layer surface holds
focus" as not-a-dismissal rather than as a dismissal.
- Consider making the screensaver a layer-shell overlay rather than a toplevel terminal window,
which sidesteps both the fullscreen-rule race and the focus check entirely.
## Additional note
`exit_screensaver` uses `pkill -f '[o]rg.omarchy.screensaver'` (`bin/omarchy-screensaver:12`).
The `[o]` guard only protects against matching the `pgrep`/`pkill` process itself — it still
matches *any* process whose command line contains that string. Scripts or tooling that mention
the class by name (including diagnostics for this very bug) get killed as collateral. Matching
on PID or window address would be safer.
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 02:26 UTC