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.
Media bar widget marquee freezes mid-scroll, showing only a few leading characters
Reported by schotime · filed Aug 16, 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
What happened
The omarchy.media bar widget's marquee (the scrolling now-playing label) gets
permanently stuck showing only the first few characters of the track title —
e.g. ⏸ For instead of ⏸ For Evigt · Volbeat, or ⏸ Giv instead of⏸ Give It Up · Midtown — with no scrolling motion at all, sometimes for the
lifetime of the shell process.
Expected behavior
When the combined "title · artist" label is wider than the widget'smaxLabelWidth (180px), it should marquee-scroll continuously. When it's
narrower, it should just display in full, static, left-aligned.
Root cause
BarWidget.qml drives the label's horizontal position with a property-value-
source animation:
NumberAnimation on x {
id: scrollAnim
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical
loops: Animation.Infinite
duration: Math.max(6000, labelText.implicitWidth * 25)
from: scrollClip.width
to: -labelText.implicitWidth
easing.type: Easing.Linear
}A NumberAnimation on <property> is a value source: while running istrue it owns x outright, but the instant running flips to false —
because the track changed to something short enough that needsScroll goes
false, the popup opened, or the bar rotated to vertical — it simply **freezesx at whatever mid-scroll offset it happened to be at**. Nothing ever resets
it back to 0.
Since scrollClip clips its contents (clip: true) and the label's x is
left sitting at some large offset (observed live via a temporary IPC probe:x=130 inside a 165px-wide clip, for a 165px-wide label — i.e. it should
never have been scrolling in the first place, needsScroll was correctlyfalse, but x was stale from an earlier scroll cycle), only the lastclipWidth - x pixels of the clip are visible, which land on the very
leftmost glyphs of the label — a thin sliver of the string's start, not the
full text and not a scroll.
This reproduces reliably any time the active/selected MPRIS source changes
between tracks of different lengths, or the popup is opened/closed while the
label is mid-animation. It survives omarchy restart shell because it's
deterministic given the metadata at hand — a fresh process ends up in the
same stuck state on its own once a track transitions from
needing-to-scroll to not.
Proposed fix
Reset x explicitly whenever the animation stops, so the label always
returns to a clean left-aligned resting position:
NumberAnimation on x {
id: scrollAnim
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical
loops: Animation.Infinite
duration: Math.max(6000, labelText.implicitWidth * 25)
from: scrollClip.width
to: -labelText.implicitWidth
easing.type: Easing.Linear
+ onRunningChanged: if (!running) labelText.x = 0
}Verified fix in a local plugin clone (omarchy plugin clone omarchy.media)
— confirmed via screenshots taken a few seconds apart that after the patch
the label reliably shows the full static text when short, and genuinely
scrolls (not frozen) through the whole "title · artist" string when long.
File: shell/plugins/services/media/BarWidget.qml
Steps to reproduce
- Have two MPRIS sources active at once (e.g. a browser tab playing audio +
a Deezer/Spotify client), or just let a single source's track change.
2. Let the bar's media widget scroll through a title/artist combo longer than
180px.
3. Let the track change to something shorter (or open/close the widget's
popup) while it's mid-scroll.
4. The label freezes, showing only a few leading characters of the new
title, and never scrolls or corrects itself again.
System details
- Omarchy: 4.0.0-1 (stable channel)
- Hyprland: 0.56.2 (Wayland)
- Kernel: Linux 7.1.8-arch1-3
- Hardware: Dell XPS 15 9560, i7-7700HQ, GTX 1050 Mobile / HD Graphics 630 (hybrid GPU)
- Display: 3840x2160 @ 2x, 16", 60Hz
Attachments
Screenshots showing the stuck state and the working scroll after the fix are
available locally and will be attached to the issue.
View raw text
## What happened
The `omarchy.media` bar widget's marquee (the scrolling now-playing label) gets
permanently stuck showing only the first few characters of the track title —
e.g. `⏸ For` instead of `⏸ For Evigt · Volbeat`, or `⏸ Giv` instead of
`⏸ Give It Up · Midtown` — with no scrolling motion at all, sometimes for the
lifetime of the shell process.
## Expected behavior
When the combined "title · artist" label is wider than the widget's
`maxLabelWidth` (180px), it should marquee-scroll continuously. When it's
narrower, it should just display in full, static, left-aligned.
## Root cause
`BarWidget.qml` drives the label's horizontal position with a property-value-
source animation:
```qml
NumberAnimation on x {
id: scrollAnim
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical
loops: Animation.Infinite
duration: Math.max(6000, labelText.implicitWidth * 25)
from: scrollClip.width
to: -labelText.implicitWidth
easing.type: Easing.Linear
}
```
A `NumberAnimation on <property>` is a value source: while `running` is
`true` it owns `x` outright, but the instant `running` flips to `false` —
because the track changed to something short enough that `needsScroll` goes
false, the popup opened, or the bar rotated to vertical — it simply **freezes
`x` at whatever mid-scroll offset it happened to be at**. Nothing ever resets
it back to `0`.
Since `scrollClip` clips its contents (`clip: true`) and the label's `x` is
left sitting at some large offset (observed live via a temporary IPC probe:
`x=130` inside a `165`px-wide clip, for a 165px-wide label — i.e. it should
never have been scrolling in the first place, `needsScroll` was correctly
`false`, but `x` was stale from an earlier scroll cycle), only the last
`clipWidth - x` pixels of the clip are visible, which land on the very
leftmost glyphs of the label — a thin sliver of the string's start, not the
full text and not a scroll.
This reproduces reliably any time the active/selected MPRIS source changes
between tracks of different lengths, or the popup is opened/closed while the
label is mid-animation. It survives `omarchy restart shell` because it's
deterministic given the metadata at hand — a fresh process ends up in the
same stuck state on its own once a track transitions from
needing-to-scroll to not.
## Proposed fix
Reset `x` explicitly whenever the animation stops, so the label always
returns to a clean left-aligned resting position:
```diff
NumberAnimation on x {
id: scrollAnim
running: labelText.needsScroll && !root.popupOpen && !root.bar.vertical
loops: Animation.Infinite
duration: Math.max(6000, labelText.implicitWidth * 25)
from: scrollClip.width
to: -labelText.implicitWidth
easing.type: Easing.Linear
+ onRunningChanged: if (!running) labelText.x = 0
}
```
Verified fix in a local plugin clone (`omarchy plugin clone omarchy.media`)
— confirmed via screenshots taken a few seconds apart that after the patch
the label reliably shows the full static text when short, and genuinely
scrolls (not frozen) through the whole "title · artist" string when long.
File: `shell/plugins/services/media/BarWidget.qml`
## Steps to reproduce
1. Have two MPRIS sources active at once (e.g. a browser tab playing audio +
a Deezer/Spotify client), or just let a single source's track change.
2. Let the bar's media widget scroll through a title/artist combo longer than
180px.
3. Let the track change to something shorter (or open/close the widget's
popup) while it's mid-scroll.
4. The label freezes, showing only a few leading characters of the new
title, and never scrolls or corrects itself again.
## System details
- Omarchy: 4.0.0-1 (stable channel)
- Hyprland: 0.56.2 (Wayland)
- Kernel: Linux 7.1.8-arch1-3
- Hardware: Dell XPS 15 9560, i7-7700HQ, GTX 1050 Mobile / HD Graphics 630 (hybrid GPU)
- Display: 3840x2160 @ 2x, 16", 60Hz
## Attachments
Screenshots showing the stuck state and the working scroll after the fix are
available locally and will be attached to the issue.
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 04:17 UTC