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-4702GitHub issuePublicReceived

Tray: symbolic icon renders blank after the item switches icons and back

Reported by freeyoung · filed Aug 26, 2026Closed upstream on 2026-08-26 by its own reporter freeyoung, as a duplicate of #7288 (R-1717). GitHub close reason: duplicate.

Received and recorded verbatim. Nothing has been checked yet.

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?
Not yet mapped to any requirement or component.
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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

Tray: symbolic icon renders blank after the item switches icons and backrevision 1 · captured 2026-10-04 12:03 UTC via poll

Summary

A omarchy.tray item whose icon is symbolic at the moment the widget is built
renders nothing the first time its icon turns symbolic again after having been
non-symbolic. The item is still there — it keeps its slot and its menu still
opens — but the glyph is gone until the shell is restarted.

The trigger is the icon type at widget construction, not the icon itself:

Icon type when the shell startsBehaviour on subsequent icon changes
symbolic (layer.enabled starts true)first return to a symbolic icon renders blank
non-symbolic (layer.enabled starts false)correct, indefinitely

Steps to reproduce

Any SNI item that alternates between a symbolic and a non-symbolic icon will do.
fcitx5 is a convenient one: its keyboard-us input method uses
input-keyboard-symbolic and any real IM uses a plain PNG (fcitx-wubi here).

  1. Have fcitx5 running with two input methods, so the tray icon alternates

between input-keyboard-symbolic and a non-symbolic icon.
2. Put fcitx5 on the symbolic one (the plain keyboard layout).
3. omarchy restart shell — the keyboard icon renders correctly.
4. Switch input method (Alt+Space). The non-symbolic icon renders correctly.
5. Switch back. The icon is now blank.

Starting from step 2 on the non-symbolic icon instead makes every later switch
render correctly, which is what makes this look intermittent.

Expected vs actual

Expected: the icon re-renders on every NewIcon.

Actual: blank. The SNI properties are identical to the working startup state, so
nothing is wrong on the fcitx5 side:

$ busctl --user get-property :1.7146 /StatusNotifierItem org.kde.StatusNotifierItem \
    IconName IconThemePath Status Id
IconName       s "input-keyboard-symbolic"
IconThemePath  s ""
Status         s "Active"
Id             s "Fcitx"

Root cause

shell/plugins/bar/widgets/Tray.qml, the TrayIcon component:

Image {
  id: trayIconImage
  ...
  visible: !trayIconRoot.symbolic
  layer.enabled: trayIconRoot.symbolic
}

MultiEffect {
  anchors.fill: trayIconImage
  source: trayIconImage
  visible: trayIconRoot.symbolic
  colorization: 1.0
  colorizationColor: root.foreground
}

layer.enabled is toggled at runtime. When the item is constructed with
symbolic == true, the layer exists from the start; turning it off (icon becomes
non-symbolic) and on again (icon becomes symbolic) leaves MultiEffect sampling
an empty texture, so nothing is drawn. When the item is constructed with
symbolic == false, the layer is created on the first flip and behaves.

Ruled out

  • Not the tray drawer. Reproduces identically for pinned items and for items

in the drawer.
- Not `layer.enabled: true` on the drawer `Row` (Tray.qml:291). Removing it
leaves all three frames of the repro byte-identical to the baseline.
- Not icon-theme resolution. input-keyboard-symbolic resolves fine
(/usr/share/icons/Yaru/scalable/devices/input-keyboard-symbolic.svg), and it
renders correctly at startup and in the non-failing ordering.

Suggested fix

Stop toggling the layer; keep the image layered and always draw it through the
effect, letting colorization decide whether to recolor.

-      visible: !trayIconRoot.symbolic
-      layer.enabled: trayIconRoot.symbolic
+      visible: false
+      layer.enabled: true
     }

     MultiEffect {
       anchors.fill: trayIconImage
       source: trayIconImage
-      visible: trayIconRoot.symbolic
-      colorization: 1.0
+      colorization: trayIconRoot.symbolic ? 1.0 : 0.0
       colorizationColor: root.foreground
     }

Verification

Patched via omarchy plugin clone omarchy.tray, then screenshotted the bar with
grim after each switch and compared checksums against known-good frames.

In the startup state that previously always failed, four consecutive switches
were byte-identical to the correct references (symbolic 3091c32e,
non-symbolic e69464fd); the blank frame (1e8269ca) no longer occurs.
Non-symbolic icons now pass through MultiEffect with colorization: 0 and
render pixel-identically to before, so there is no visual regression.

System details

Omarchy    4.0.1-1
Hyprland   0.56.2
quickshell 0.3.1-1
qt6-base   6.11.2-2
fcitx5     5.1.21-1
Kernel     7.1.9-arch1-2
CPU        11th Gen Intel Core i7-1185G7
GPU        Intel TigerLake-LP GT2 [Iris Xe Graphics]
View raw text
## Summary

A `omarchy.tray` item whose icon is **symbolic at the moment the widget is built**
renders nothing the first time its icon turns symbolic again after having been
non-symbolic. The item is still there — it keeps its slot and its menu still
opens — but the glyph is gone until the shell is restarted.

The trigger is the icon type at widget construction, not the icon itself:

| Icon type when the shell starts | Behaviour on subsequent icon changes |
| --- | --- |
| symbolic (`layer.enabled` starts `true`) | first return to a symbolic icon renders blank |
| non-symbolic (`layer.enabled` starts `false`) | correct, indefinitely |

## Steps to reproduce

Any SNI item that alternates between a symbolic and a non-symbolic icon will do.
fcitx5 is a convenient one: its `keyboard-us` input method uses
`input-keyboard-symbolic` and any real IM uses a plain PNG (`fcitx-wubi` here).

1. Have fcitx5 running with two input methods, so the tray icon alternates
   between `input-keyboard-symbolic` and a non-symbolic icon.
2. Put fcitx5 on the **symbolic** one (the plain keyboard layout).
3. `omarchy restart shell` — the keyboard icon renders correctly.
4. Switch input method (Alt+Space). The non-symbolic icon renders correctly.
5. Switch back. **The icon is now blank.**

Starting from step 2 on the *non-symbolic* icon instead makes every later switch
render correctly, which is what makes this look intermittent.

## Expected vs actual

Expected: the icon re-renders on every `NewIcon`.

Actual: blank. The SNI properties are identical to the working startup state, so
nothing is wrong on the fcitx5 side:

```
$ busctl --user get-property :1.7146 /StatusNotifierItem org.kde.StatusNotifierItem \
    IconName IconThemePath Status Id
IconName       s "input-keyboard-symbolic"
IconThemePath  s ""
Status         s "Active"
Id             s "Fcitx"
```

## Root cause

`shell/plugins/bar/widgets/Tray.qml`, the `TrayIcon` component:

```qml
Image {
  id: trayIconImage
  ...
  visible: !trayIconRoot.symbolic
  layer.enabled: trayIconRoot.symbolic
}

MultiEffect {
  anchors.fill: trayIconImage
  source: trayIconImage
  visible: trayIconRoot.symbolic
  colorization: 1.0
  colorizationColor: root.foreground
}
```

`layer.enabled` is toggled at runtime. When the item is constructed with
`symbolic == true`, the layer exists from the start; turning it off (icon becomes
non-symbolic) and on again (icon becomes symbolic) leaves `MultiEffect` sampling
an empty texture, so nothing is drawn. When the item is constructed with
`symbolic == false`, the layer is created on the first flip and behaves.

## Ruled out

- **Not the tray drawer.** Reproduces identically for pinned items and for items
  in the drawer.
- **Not `layer.enabled: true` on the drawer `Row`** (`Tray.qml:291`). Removing it
  leaves all three frames of the repro byte-identical to the baseline.
- **Not icon-theme resolution.** `input-keyboard-symbolic` resolves fine
  (`/usr/share/icons/Yaru/scalable/devices/input-keyboard-symbolic.svg`), and it
  renders correctly at startup and in the non-failing ordering.

## Suggested fix

Stop toggling the layer; keep the image layered and always draw it through the
effect, letting `colorization` decide whether to recolor.

```diff
-      visible: !trayIconRoot.symbolic
-      layer.enabled: trayIconRoot.symbolic
+      visible: false
+      layer.enabled: true
     }

     MultiEffect {
       anchors.fill: trayIconImage
       source: trayIconImage
-      visible: trayIconRoot.symbolic
-      colorization: 1.0
+      colorization: trayIconRoot.symbolic ? 1.0 : 0.0
       colorizationColor: root.foreground
     }
```

## Verification

Patched via `omarchy plugin clone omarchy.tray`, then screenshotted the bar with
`grim` after each switch and compared checksums against known-good frames.

In the startup state that previously always failed, four consecutive switches
were byte-identical to the correct references (symbolic `3091c32e`,
non-symbolic `e69464fd`); the blank frame (`1e8269ca`) no longer occurs.
Non-symbolic icons now pass through `MultiEffect` with `colorization: 0` and
render pixel-identically to before, so there is no visual regression.

## System details

```
Omarchy    4.0.1-1
Hyprland   0.56.2
quickshell 0.3.1-1
qt6-base   6.11.2-2
fcitx5     5.1.21-1
Kernel     7.1.9-arch1-2
CPU        11th Gen Intel Core i7-1185G7
GPU        Intel TigerLake-LP GT2 [Iris Xe Graphics]
```

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.

No decision has been recorded yet.