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-140GitHub issuePublicDecided· Out of scope

Background reveal never animates: revealMask is `visible: false` with `layer.enabled` used as MultiEffect maskSource

Reported by ScytheAkira · filed Sep 24, 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

Background reveal never animates: revealMask is `visible: false` with `layer.enabled` used as MultiEffect maskSourcerevision 1 · captured 2026-09-28 21:23 UTC via poll

What happens

The background reveal does not animate. Theme and wallpaper changes cut to the
new image in a single step instead of the centre-out reveal.

The NumberAnimation runs correctly for its full 420 ms — the new wallpaper
appears at ~550 ms (≈130 ms image load + 420 ms animation). Nothing is visible
until the animation finishes, which points at the mask rather than the
animation.

In shell/plugins/background/Background.qml:

Item {
  id: revealMask
  anchors.fill: parent
  visible: false        // hidden item...
  layer.enabled: true   // ...but used as a live maskSource
  ...
}

revealMask feeds MultiEffect { maskEnabled: true; maskSource: revealMask }.
With visible: false, the item's layer texture is not re-rendered as
revealProgress animates, so the mask stays frozen at progress 0. The incoming
wallpaper is fully masked out for the whole animation and only appears once
revealProgress >= 1 satisfies the other term of incomingLayer.visible.

What I expected

The centre-out wipe (theme change) and circle reveal (wallpaper change) to
sweep over 420 ms.

Steps to reproduce

  1. omarchy theme set <theme> (or change wallpaper).
  2. The wallpaper replaces itself in one step; no reveal is drawn.

Both reveal paths are affected — transition (circle) and themeTransition
(wipe).

Fix

One line in shell/plugins/background/Background.qml:

   Item {
     id: revealMask
     anchors.fill: parent
-    visible: false
+    opacity: 0
     layer.enabled: true

opacity: 0 keeps the item in the render graph so its layer texture updates
every frame, while remaining invisible.

Evidence

Sampling a strip of wallpaper below the tiled window with
grim -g "0,852 1536x12" at a measured 46 ms/frame (so a 420 ms animation spans
~9 frames). Counting frames in which the strip's colour changed — 1 means a hard
cut, many means a real sweep:

transitionbeforeafter the one-line change
bokeh → eyes-wide0–14
eyes-wide → blink16
blink → new-horizons16
real `omarchy theme set`114

Real theme change after the fix, strip red channel per frame:

71 ×13 · 68 59 58 57 55 58 61 67 85 104 115 118 118 120 121 · 121 ×14

a smooth sweep, including the mid-wipe dip as the band crosses the sample strip.

Note for anyone re-testing

Use a distinct incoming image for each transition. Repeating the same image
pair assigns incomingBackground a value it already holds, so
onIncomingBackgroundChanged never fires, maybeStartReveal() is never called
and the reveal genuinely cannot start — which reproduces the same visible
symptom for an unrelated reason and makes the bug look unfixable.

System

  • Omarchy 4.0.4-1, kernel 7.2.5-3-omarchy
  • quickshell 0.3.1-1, qt6-base 6.11.2-3, qt6-declarative 6.11.2-1
  • GPU: NVIDIA Quadro P620, driver 580.178.04 (rendering quickshell; Intel UHD also present)

I have only this machine to test on, so I can't say whether the stale hidden
layer is NVIDIA-specific or general to Qt 6.11. Happy to open a PR with the
one-line change if useful.

View raw text
### What happens

The background reveal does not animate. Theme and wallpaper changes cut to the
new image in a single step instead of the centre-out reveal.

The `NumberAnimation` runs correctly for its full 420 ms — the new wallpaper
appears at ~550 ms (≈130 ms image load + 420 ms animation). Nothing is visible
until the animation *finishes*, which points at the mask rather than the
animation.

In `shell/plugins/background/Background.qml`:

```qml
Item {
  id: revealMask
  anchors.fill: parent
  visible: false        // hidden item...
  layer.enabled: true   // ...but used as a live maskSource
  ...
}
```

`revealMask` feeds `MultiEffect { maskEnabled: true; maskSource: revealMask }`.
With `visible: false`, the item's layer texture is not re-rendered as
`revealProgress` animates, so the mask stays frozen at progress 0. The incoming
wallpaper is fully masked out for the whole animation and only appears once
`revealProgress >= 1` satisfies the other term of `incomingLayer.visible`.

### What I expected

The centre-out wipe (theme change) and circle reveal (wallpaper change) to
sweep over 420 ms.

### Steps to reproduce

1. `omarchy theme set <theme>` (or change wallpaper).
2. The wallpaper replaces itself in one step; no reveal is drawn.

Both reveal paths are affected — `transition` (circle) and `themeTransition`
(wipe).

### Fix

One line in `shell/plugins/background/Background.qml`:

```diff
   Item {
     id: revealMask
     anchors.fill: parent
-    visible: false
+    opacity: 0
     layer.enabled: true
```

`opacity: 0` keeps the item in the render graph so its layer texture updates
every frame, while remaining invisible.

### Evidence

Sampling a strip of wallpaper below the tiled window with
`grim -g "0,852 1536x12"` at a measured 46 ms/frame (so a 420 ms animation spans
~9 frames). Counting frames in which the strip's colour changed — 1 means a hard
cut, many means a real sweep:

| transition | before | after the one-line change |
|---|---|---|
| bokeh → eyes-wide | 0–1 | 4 |
| eyes-wide → blink | 1 | 6 |
| blink → new-horizons | 1 | 6 |
| **real `omarchy theme set`** | 1 | **14** |

Real theme change after the fix, strip red channel per frame:

```
71 ×13 · 68 59 58 57 55 58 61 67 85 104 115 118 118 120 121 · 121 ×14
```

a smooth sweep, including the mid-wipe dip as the band crosses the sample strip.

### Note for anyone re-testing

Use a **distinct** incoming image for each transition. Repeating the same image
pair assigns `incomingBackground` a value it already holds, so
`onIncomingBackgroundChanged` never fires, `maybeStartReveal()` is never called
and the reveal genuinely cannot start — which reproduces the same visible
symptom for an unrelated reason and makes the bug look unfixable.

### System

- Omarchy 4.0.4-1, kernel 7.2.5-3-omarchy
- quickshell 0.3.1-1, qt6-base 6.11.2-3, qt6-declarative 6.11.2-1
- GPU: NVIDIA Quadro P620, driver 580.178.04 (rendering quickshell; Intel UHD also present)

I have only this machine to test on, so I can't say whether the stale hidden
layer is NVIDIA-specific or general to Qt 6.11. Happy to open a PR with the
one-line change if useful.

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 17:52 UTC