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.
[Quattro] omarchy-launch-screensaver creates focus-check race condition on 3+ monitor setups causing immediate self-termination
Reported by grhoades · filed Aug 24, 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
System details
- Hardware: Framework Desktop, AMD Ryzen AI Max 395 (Radeon 8060S Graphics)
- Omarchy Version: 4.0.0-1 (Quattro)
- Hyprland Configuration: Lua parser (
~/.config/hypr/hyprland.lua) - Display Setup: 3 monitors (
DP-1portrait,HDMI-A-1ultrawide,DP-4landscape) vs 2 monitors tested - Terminal: Kitty
What's wrong?
On multi-monitor setups with 3 or more displays, omarchy-launch-screensaver triggers and then immediately self-terminates after a few seconds without any user interaction. On a 2-monitor system with identical Omarchy Quattro configuration, the screensaver runs as expected.
When the screensavers self-terminate, omarchy-shell's idle manager (Service.qml) interprets the closed windows as a manual dismissal, issues omarchy-system-wake, and cancels the idle sequence—preventing idle.lock (300s) and display DPMS power-down from ever activating.
Mechanism & Root Cause
- Sequential Output Launch Loop:
In /usr/bin/omarchy-launch-screensaver, screensavers are spawned sequentially across all connected displays:
for m in $(hyprctl monitors -j | jq -r '.[].name'); do
hypr_focus_monitor "$m"
case $terminal in ... esac
wait_for_screensaver_window
done
hypr_focus_monitor "$focused" Each monitor iteration focuses the monitor, spawns the terminal screensaver window, and waits for the corresponding socket2 openwindow event.
- The 3+ Monitor Timing Race:
In /usr/bin/omarchy-screensaver, the main loop starts checking focus immediately with a 1-second timeout:
while pgrep -t "${tty#/dev/}" -x ttfx >/dev/null; do
if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver
fi
done- On a 2-monitor system, the loop completes quickly enough that both windows map and focus is restored to the primary monitor within ~1 second.
- On a 3+ monitor system, cycling through all three displays takes 2–4 seconds.
- While the launcher is busy focusing Monitor 2 and Monitor 3, Monitor 1's screensaver process reaches its first 1-second timeout and evaluates
screensaver_in_focus.
- Global Active Window Query:
screensaver_in_focus() checks global compositor focus:
screensaver_in_focus() {
hyprctl activewindow -j | jq -e '.class == "org.omarchy.screensaver"' >/dev/null 2>&1
} Because compositor focus is actively transitioning to Monitor 2/3 (or momentarily lands on existing windows on those workspaces before the screensaver terminal is mapped), Monitor 1 sees that activewindow is not its own screensaver class. ! screensaver_in_focus evaluates to true, executing exit_screensaver (pkill -f org.omarchy.screensaver) and killing all screensavers across all monitors.
Steps to Reproduce
- Connect 3 displays with active application windows on each workspace.
- Trigger the screensaver via
omarchy-launch-screensaveror wait foridle.screensaver(150s). - Observe Monitor 1 launch, followed by Monitor 2/3, followed by immediate teardown within 3–6 seconds without user input.
Suggested Solutions
- Startup Grace Period: Add an initial grace period (e.g. 5–6 seconds) to
omarchy-screensaverbefore evaluatingscreensaver_in_focus, giving multi-monitor launch loops sufficient time to finish mapping all screens. - Event-Driven Dismissal: Rather than polling global
activewindowevery second in each terminal process, rely on compositor idle/wake notifications fromomarchy-shelland terminal keypress/signal handlers to handle screensaver dismissal.
Filed by Gemini via Antigravity CLI.
View raw text
### System details
- **Hardware**: Framework Desktop, AMD Ryzen AI Max 395 (Radeon 8060S Graphics)
- **Omarchy Version**: 4.0.0-1 (Quattro)
- **Hyprland Configuration**: Lua parser (`~/.config/hypr/hyprland.lua`)
- **Display Setup**: 3 monitors (`DP-1` portrait, `HDMI-A-1` ultrawide, `DP-4` landscape) vs 2 monitors tested
- **Terminal**: Kitty
### What's wrong?
On multi-monitor setups with 3 or more displays, `omarchy-launch-screensaver` triggers and then immediately self-terminates after a few seconds without any user interaction. On a 2-monitor system with identical Omarchy Quattro configuration, the screensaver runs as expected.
When the screensavers self-terminate, `omarchy-shell`'s idle manager (`Service.qml`) interprets the closed windows as a manual dismissal, issues `omarchy-system-wake`, and cancels the idle sequence—preventing `idle.lock` (300s) and display DPMS power-down from ever activating.
### Mechanism & Root Cause
1. **Sequential Output Launch Loop**:
In `/usr/bin/omarchy-launch-screensaver`, screensavers are spawned sequentially across all connected displays:
```bash
for m in $(hyprctl monitors -j | jq -r '.[].name'); do
hypr_focus_monitor "$m"
case $terminal in ... esac
wait_for_screensaver_window
done
hypr_focus_monitor "$focused"
```
Each monitor iteration focuses the monitor, spawns the terminal screensaver window, and waits for the corresponding socket2 `openwindow` event.
2. **The 3+ Monitor Timing Race**:
In `/usr/bin/omarchy-screensaver`, the main loop starts checking focus immediately with a 1-second timeout:
```bash
while pgrep -t "${tty#/dev/}" -x ttfx >/dev/null; do
if read -n1 -t 1 || ! screensaver_in_focus; then
exit_screensaver
fi
done
```
- On a **2-monitor system**, the loop completes quickly enough that both windows map and focus is restored to the primary monitor within ~1 second.
- On a **3+ monitor system**, cycling through all three displays takes 2–4 seconds.
- While the launcher is busy focusing Monitor 2 and Monitor 3, Monitor 1's screensaver process reaches its first 1-second timeout and evaluates `screensaver_in_focus`.
3. **Global Active Window Query**:
`screensaver_in_focus()` checks global compositor focus:
```bash
screensaver_in_focus() {
hyprctl activewindow -j | jq -e '.class == "org.omarchy.screensaver"' >/dev/null 2>&1
}
```
Because compositor focus is actively transitioning to Monitor 2/3 (or momentarily lands on existing windows on those workspaces before the screensaver terminal is mapped), Monitor 1 sees that `activewindow` is not its own screensaver class. `! screensaver_in_focus` evaluates to true, executing `exit_screensaver` (`pkill -f org.omarchy.screensaver`) and killing all screensavers across all monitors.
### Steps to Reproduce
1. Connect 3 displays with active application windows on each workspace.
2. Trigger the screensaver via `omarchy-launch-screensaver` or wait for `idle.screensaver` (150s).
3. Observe Monitor 1 launch, followed by Monitor 2/3, followed by immediate teardown within 3–6 seconds without user input.
### Suggested Solutions
1. **Startup Grace Period**: Add an initial grace period (e.g. 5–6 seconds) to `omarchy-screensaver` before evaluating `screensaver_in_focus`, giving multi-monitor launch loops sufficient time to finish mapping all screens.
2. **Event-Driven Dismissal**: Rather than polling global `activewindow` every second in each terminal process, rely on compositor idle/wake notifications from `omarchy-shell` and terminal keypress/signal handlers to handle screensaver dismissal.
> Filed by Gemini via Antigravity CLI.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
- Related PRpr/12730· confirmed
- Fixed bypr/12808· confirmed
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:29 UTC