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.
Bar: moduleClickTargetAt hit-tests a click against every monitor's click targets
Reported by jrmmhm · filed Aug 27, 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
shell/plugins/bar/Bar.qml::moduleClickTargetAt walks clickTargets — which
every WidgetButton on every bar surface registers into — and returns the first
target whose rectangle contains the mapped point. It never asks which window a
target belongs to.
Ui/KeyboardPanel.qml::pressTargetAt does the same job over the same array and
does ask, on its line if (root.bar.targetBelongsToWindow && !root.bar.targetBelongsToWindow(target, root.anchorWindow)) continue.targetBelongsToWindow is defined in Bar.qml itself and is used for tooltips
two more times in that file. The click path is the one place it is missing.
What happens
Where two outputs overlap in the compositor's global layout — mirrored, or
positioned by hand so their rectangles intersect — a left click on one bar
surface activates the widget occupying the same global point on the other
surface. It is not intermittent: every contested click goes to the same surface.registerClickTarget appends and the scan runs backwards, so the surface that
registered last wins all of them.
Only left clicks are affected. ModuleSlot's modulePointer declaresacceptedButtons: Qt.LeftButton, so right and middle clicks reach the widget's
own MouseArea directly.
Reproduction, without any third-party plugin
Mirror one output onto another, so both occupy the same logical position:
hyprctl keyword monitor DP-2,preferred,0x0,1
hyprctl keyword monitor eDP-1,preferred,0x0,1Left-click a right-section panel widget on one bar — the audio icon, say. The
panel opens against the other monitor's bar. Clicking the same icon on the
other monitor does nothing new, because both clicks resolve to the same target.
A deterministic version that needs no monitor reconfiguration: loadmoduleClickTargetAt, moduleTargetClickable, targetWindow andtargetBelongsToWindow verbatim into a Quickshell config that creates twoPanelWindows on one screen, registers stand-in click targets at the bar's real
widget offsets on each, and calls the function for the centre of every widget.
Measured
Environment: Omarchy 4.0.0.alpha (shell/plugins/bar/Bar.qml byte-identical tov4.0.1 and to quattro HEAD), Quickshell 0.3.1, Qt 6.11.2, Hyprland 0.56.2.
| Layout | clicks | resolved to the clicked surface | resolved to another surface |
|---|---|---|---|
| three outputs side by side (x = 0, 1152, 2752) | 27 | 27 | 0 |
| two surfaces sharing one origin | 18 | 9 | 9 |
Adding the targetBelongsToWindow filter: the side-by-side figures are
unchanged, and the shared-origin case goes to 18 and 0.
Why it does not show on an ordinary multi-monitor setup
QWaylandWindow::fixedToplevelPositions is true, so setGeometry moves every
non-popup toplevel to screen()->geometry().topLeft(). Each bar surface is
therefore mapped as though it sat at its own output's origin, and the
cross-window branch of QQuickItem::mapToItem (Qt 6.8.0, 06ace3e226b2)
returns the true distance between the outputs. Measured on three outputs, a mark
at local x=100 reports mapToGlobal values of 100, 1252 and 2852.
Two consequences worth stating, because they narrow the condition to the outputs
alone: a margin does not move what Qt believes the origin to be, and neither
does the layer-shell anchor — a bottom-anchored surface reports its items at its
screen's top edge. So the bar's position and margins are irrelevant, and the
test reduces to whether the two outputs' rectangles intersect.
Suggested fix
One line, matching what pressTargetAt already does:
function moduleClickTargetAt(slot, localX, localY) {
for (var i = clickTargets.length - 1; i >= 0; i--) {
var target = clickTargets[i]
if (!moduleTargetClickable(target)) continue
+ if (!targetBelongsToWindow(target, slotWindow(slot))) continueVerified by patching a scratch copy of the shell and loading the patched
functions verbatim: the shared-origin case goes from 9 wrong resolutions in 18
to none, and the side-by-side case is unchanged.
One trade-off, measured rather than assumed. With the filter in place, a slot
whose window is momentarily unknown — deleteOnInvisible destroys aPanelWindow's backing window, and Ui/ScreenMoveRemap.qml pulses that on every
monitor move — resolves to null, so the click does nothing instead of doing
something on the wrong surface. slotWindow() already falls back fromactiveItem to the slot itself, and targetBelongsToWindow opens with a null
check, so this is the existing contract rather than a new one.
View raw text
`shell/plugins/bar/Bar.qml::moduleClickTargetAt` walks `clickTargets` — which
every `WidgetButton` on every bar surface registers into — and returns the first
target whose rectangle contains the mapped point. It never asks which window a
target belongs to.
`Ui/KeyboardPanel.qml::pressTargetAt` does the same job over the same array and
does ask, on its line `if (root.bar.targetBelongsToWindow && !root.bar.targetBelongsToWindow(target, root.anchorWindow)) continue`.
`targetBelongsToWindow` is defined in `Bar.qml` itself and is used for tooltips
two more times in that file. The click path is the one place it is missing.
### What happens
Where two outputs overlap in the compositor's global layout — mirrored, or
positioned by hand so their rectangles intersect — a **left** click on one bar
surface activates the widget occupying the same global point on the other
surface. It is not intermittent: every contested click goes to the same surface.
`registerClickTarget` appends and the scan runs backwards, so the surface that
registered last wins all of them.
Only left clicks are affected. `ModuleSlot`'s `modulePointer` declares
`acceptedButtons: Qt.LeftButton`, so right and middle clicks reach the widget's
own `MouseArea` directly.
### Reproduction, without any third-party plugin
Mirror one output onto another, so both occupy the same logical position:
```
hyprctl keyword monitor DP-2,preferred,0x0,1
hyprctl keyword monitor eDP-1,preferred,0x0,1
```
Left-click a right-section panel widget on one bar — the audio icon, say. The
panel opens against the *other* monitor's bar. Clicking the same icon on the
other monitor does nothing new, because both clicks resolve to the same target.
A deterministic version that needs no monitor reconfiguration: load
`moduleClickTargetAt`, `moduleTargetClickable`, `targetWindow` and
`targetBelongsToWindow` verbatim into a Quickshell config that creates two
`PanelWindow`s on one screen, registers stand-in click targets at the bar's real
widget offsets on each, and calls the function for the centre of every widget.
### Measured
Environment: Omarchy 4.0.0.alpha (`shell/plugins/bar/Bar.qml` byte-identical to
`v4.0.1` and to `quattro` HEAD), Quickshell 0.3.1, Qt 6.11.2, Hyprland 0.56.2.
| Layout | clicks | resolved to the clicked surface | resolved to another surface |
| :--- | ---: | ---: | ---: |
| three outputs side by side (x = 0, 1152, 2752) | 27 | 27 | 0 |
| two surfaces sharing one origin | 18 | 9 | 9 |
Adding the `targetBelongsToWindow` filter: the side-by-side figures are
unchanged, and the shared-origin case goes to 18 and 0.
### Why it does not show on an ordinary multi-monitor setup
`QWaylandWindow::fixedToplevelPositions` is `true`, so `setGeometry` moves every
non-popup toplevel to `screen()->geometry().topLeft()`. Each bar surface is
therefore mapped as though it sat at its own output's origin, and the
cross-window branch of `QQuickItem::mapToItem` (Qt 6.8.0, `06ace3e226b2`)
returns the true distance between the outputs. Measured on three outputs, a mark
at local x=100 reports `mapToGlobal` values of 100, 1252 and 2852.
Two consequences worth stating, because they narrow the condition to the outputs
alone: a margin does not move what Qt believes the origin to be, and neither
does the layer-shell anchor — a bottom-anchored surface reports its items at its
screen's *top* edge. So the bar's position and margins are irrelevant, and the
test reduces to whether the two outputs' rectangles intersect.
### Suggested fix
One line, matching what `pressTargetAt` already does:
```qml
function moduleClickTargetAt(slot, localX, localY) {
for (var i = clickTargets.length - 1; i >= 0; i--) {
var target = clickTargets[i]
if (!moduleTargetClickable(target)) continue
+ if (!targetBelongsToWindow(target, slotWindow(slot))) continue
```
Verified by patching a scratch copy of the shell and loading the patched
functions verbatim: the shared-origin case goes from 9 wrong resolutions in 18
to none, and the side-by-side case is unchanged.
One trade-off, measured rather than assumed. With the filter in place, a slot
whose window is momentarily unknown — `deleteOnInvisible` destroys a
`PanelWindow`'s backing window, and `Ui/ScreenMoveRemap.qml` pulses that on every
monitor move — resolves to `null`, so the click does nothing instead of doing
something on the wrong surface. `slotWindow()` already falls back from
`activeItem` to the slot itself, and `targetBelongsToWindow` opens with a null
check, so this is the existing contract rather than a new one.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 09:38 UTC