Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-700GitHub issuePublicDecided· Out of scope

Bar panels stay open and render above the fullscreen screensaver when the session goes idle

Reported by ninepointlabs · filed Sep 10, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

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

Bar panels stay open and render above the fullscreen screensaver when the session goes idlerevision 1 · captured 2026-09-28 21:23 UTC via poll

System details

Omarchy 4.0.3-1, Hyprland 0.56.2, foot 1.28.0 (screensaver terminal), AMD Ryzen 7 7735HS
with Radeon RX 7600M XT + Radeon 680M, two outputs (eDP-2 1920x1200, DP-2 2560x1440).
idle.screensaver = 150, idle.lock = 300 in ~/.config/omarchy/shell.json.

Problem

A bar widget panel left open when the session goes idle is never closed. The screensaver
opens fullscreen underneath it and the panel keeps rendering on top, fully opaque, showing
whatever the plugin was displaying — on the one screen that exists to conceal the session.

This is the same class of bug as #9623 (notifications rendering above the screensaver), but
for bar panel popups rather than notification toasts.

For first-party panels the exposure is brightness/volume/network state. For third-party
plugin panels it can be private content: a mail panel keeps unread senders and subject lines
on display, a calendar panel keeps the day's events on display. The panel also survives the
whole screensaver-to-lock window — 2.5 minutes on the default 150s/300s config — so it is
still on screen right up to the lock.

Steps to reproduce

  1. Click any bar widget that opens a panel (e.g. the Display/monitor panel).
  2. Leave it open and don't touch the keyboard or mouse.
  3. Wait for idle.screensaver to elapse, or force it: omarchy-launch-screensaver force.

The screensaver fills the screen; the panel is still drawn over it.

Evidence

Screenshot: the screensaver running fullscreen on DP-2 with the Display panel still drawn
over it, at full opacity. Control screenshot: the same command with no panel open, where the
screensaver covers everything including the bar.

Sampled with hyprctl clients -j, the screensaver window is fullscreen, floating: true,
and persists normally — the panel is simply drawn above it.

Cause

Same mechanism as #9623: the terminal screensaver is an ordinary fullscreen Wayland client,
while shell panels are layer-shell surfaces anchored to the bar (WlrLayer.Top), so the
compositor draws them above it. Nothing unmaps them.

Nothing on the idle path closes panels. shell/plugins/services/idle/Service.qml runs
startIdleCycle() → launchScreensaver() → lockSystem() without ever telling the bar to
close anything.

Suggested fix

PR #9629 already established the pattern for notifications: hide the popup surfaces while the
enabled idle service reports a live screensaver window, resolving the idle service through the
plugin registry so cloned implementations still work. The same treatment applied to bar panel
popups would cover this.

If a simple close is preferred over hide/restore, the bar already tracks the open popup as
Bar.activePopout with requestPopout() / releasePopout() (shell/plugins/bar/Bar.qml),
and requestPopout() already closes the previous popout when another opens. The shell tracks
floating panels separately in shell.openPanelIds with shell.hide(pluginId). So closing the
active popout from startIdleCycle() — and again in lockSystem(), for the case where
idle.lock fires without a screensaver step — is a small change.

Not the same as #6917

#6917 covers a different failure mode with the same trigger: there, a panel holding layer-shell
keyboard focus prevents the screensaver from ever becoming the active toplevel, so the
fullscreen rule doesn't apply, the focus watchdog reads "never focused" as "user dismissed me",
and the screensaver self-terminates after ~1s (cancelling the pending lock). In the case
reported here the screensaver does go fullscreen and does persist — it is only the panel
drawing on top of it that is wrong. Both were reproducible on this machine depending on how
the panel was opened; fixing the panel-visibility problem would also avoid #6917's path.

View raw text
### System details

Omarchy 4.0.3-1, Hyprland 0.56.2, foot 1.28.0 (screensaver terminal), AMD Ryzen 7 7735HS
with Radeon RX 7600M XT + Radeon 680M, two outputs (eDP-2 1920x1200, DP-2 2560x1440).
`idle.screensaver = 150`, `idle.lock = 300` in `~/.config/omarchy/shell.json`.

### Problem

A bar widget panel left open when the session goes idle is never closed. The screensaver
opens fullscreen underneath it and the panel keeps rendering on top, fully opaque, showing
whatever the plugin was displaying — on the one screen that exists to conceal the session.

This is the same class of bug as #9623 (notifications rendering above the screensaver), but
for bar panel popups rather than notification toasts.

For first-party panels the exposure is brightness/volume/network state. For third-party
plugin panels it can be private content: a mail panel keeps unread senders and subject lines
on display, a calendar panel keeps the day's events on display. The panel also survives the
whole screensaver-to-lock window — 2.5 minutes on the default 150s/300s config — so it is
still on screen right up to the lock.

### Steps to reproduce

1. Click any bar widget that opens a panel (e.g. the Display/monitor panel).
2. Leave it open and don't touch the keyboard or mouse.
3. Wait for `idle.screensaver` to elapse, or force it: `omarchy-launch-screensaver force`.

The screensaver fills the screen; the panel is still drawn over it.

### Evidence

Screenshot: the screensaver running fullscreen on DP-2 with the Display panel still drawn
over it, at full opacity. Control screenshot: the same command with no panel open, where the
screensaver covers everything including the bar.

Sampled with `hyprctl clients -j`, the screensaver window is `fullscreen`, `floating: true`,
and persists normally — the panel is simply drawn above it.

### Cause

Same mechanism as #9623: the terminal screensaver is an ordinary fullscreen Wayland client,
while shell panels are layer-shell surfaces anchored to the bar (`WlrLayer.Top`), so the
compositor draws them above it. Nothing unmaps them.

Nothing on the idle path closes panels. `shell/plugins/services/idle/Service.qml` runs
`startIdleCycle()` → `launchScreensaver()` → `lockSystem()` without ever telling the bar to
close anything.

### Suggested fix

PR #9629 already established the pattern for notifications: hide the popup surfaces while the
enabled idle service reports a live screensaver window, resolving the idle service through the
plugin registry so cloned implementations still work. The same treatment applied to bar panel
popups would cover this.

If a simple close is preferred over hide/restore, the bar already tracks the open popup as
`Bar.activePopout` with `requestPopout()` / `releasePopout()` (`shell/plugins/bar/Bar.qml`),
and `requestPopout()` already closes the previous popout when another opens. The shell tracks
floating panels separately in `shell.openPanelIds` with `shell.hide(pluginId)`. So closing the
active popout from `startIdleCycle()` — and again in `lockSystem()`, for the case where
`idle.lock` fires without a screensaver step — is a small change.

### Not the same as #6917

#6917 covers a different failure mode with the same trigger: there, a panel holding layer-shell
keyboard focus prevents the screensaver from ever becoming the active toplevel, so the
fullscreen rule doesn't apply, the focus watchdog reads "never focused" as "user dismissed me",
and the screensaver self-terminates after ~1s (cancelling the pending lock). In the case
reported here the screensaver does go fullscreen and does persist — it is only the panel
drawing on top of it that is wrong. Both were reproducible on this machine depending on how
the panel was opened; fixing the panel-visibility problem would also avoid #6917's path.

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 11:40 UTC