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-943GitHub issuePublicFixed

Lock screen flickers on every keystroke: each wake re-applies a monitor scale from monitors.lua that the compositor doesn't use, with no backoff

Reported by tallsam · filed Sep 5, 2026 · open at source

In the audited area (lock) — decided by agents · verified. Not validated 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?
AreaIn the audited arealock· 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?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. So far: in the audited area (lock) — decided by agents · verified; matches no known issue — decided by agents · verified. The outcome (valid, duplicate, not a bug, …) is not decided yet. See the decision.

Original report

Lock screen flickers on every keystroke: each wake re-applies a monitor scale from monitors.lua that the compositor doesn't use, with no backoffrevision 1 · captured 2026-09-28 21:23 UTC via poll

Environment

  • Omarchy 4.0.1-1, Hyprland 0.56.2, kernel 7.1.9-arch1-2
  • Lenovo Legion, 13th Gen Intel i9-13900HX, hybrid Intel UHD (Raptor Lake-S) + NVIDIA RTX 4070 Mobile
  • Single internal panel eDP-2 — 2560x1600@240, applied scale 1.6
  • Per-output scale is applied by a third-party tool (hyprmoncfg / hyprmoncfgd) that writes its

own ~/.config/hypr/hyprmoncfg-monitors.lua, loaded last from hyprland.lua. The mechanism below
does not depend on that specific tool — see "This is not hyprmoncfg-specific".

What happens

Typing a password at the lock screen makes the display flicker on every keystroke. Each keystroke
causes two full modesets: one from Omarchy forcing a scale the panel isn't using, and one from the
scale being put back.

Why

plugins/lock/LockView.qml emits wakeRequested on every keypress — once from onTextChanged
and once from Keys.onPressed:

onTextChanged: {
  ...
  if (text.length > 0) {
    root.wakeRequested()          // LockView.qml:166
  }
Keys.onPressed: function(event) {
  root.wakeRequested()            // LockView.qml:178

plugins/lock/Service.qml turns that into runWake() → omarchy-system-wake, whose third step is
a full omarchy-hyprland-monitor-clamshell run:

omarchy-brightness-display on
omarchy-brightness-keyboard restore
omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true

omarchy-hyprland-monitor-clamshell reads the desired internal scale from **~/.config/hypr/monitors.lua
only** (MONITOR_LUA is hardcoded). It cannot see a scale applied from anywhere else, so on this machine
it reads the stock catch-all local omarchy_monitor_scale = 2, compares it to the live 1.6, and re-applies:

$ bash -x $(which omarchy-hyprland-monitor-clamshell)
+ enable_internal
+ sync_internal_scale
+ configured_scale=2
+ active_scale=1.6
+ scales_match 1.6 2
+ enable_internal_output 2
+ hyprctl eval 'hl.monitor({ output = "eDP-2", mode = "preferred", position = "auto", scale = 2 })'

That hyprctl eval genuinely changes the scale (verified: 1.6 → 2), which is a modeset. The tool that
owns the layout then puts it back to 1.6 — a second modeset. Because neither side yields, the mismatch
never resolves, so the whole sequence repeats on every single keystroke:

$ hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
1.6
$ hyprctl eval 'hl.monitor({ output = "eDP-2", mode = "preferred", position = "auto", scale = 2 })'
ok
$ hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
2
$ sleep 2; hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
1.6

Steps to reproduce

  1. On a laptop, arrange for the internal panel's applied scale to differ from what monitors.lua

resolves to, in a way monitors.lua parsing cannot see. Either:
- have any external tool/daemon own the per-output scale (a desc:-form rule in a separate
dofiled config, as hyprmoncfg does), or
- simulate it by hand: hyprctl eval 'hl.monitor({ output = "<internal>", scale = 1.6 })' while
monitors.lua still resolves to 2.
2. Lock the screen (omarchy system lock).
3. Type in the password field.
4. The display flickers per keystroke. bash -x $(which omarchy-hyprland-monitor-clamshell) shows
the hyprctl eval ... hl.monitor firing every time.

Expected

Typing at the lock screen should not reconfigure displays. A wake should not re-apply a monitor rule
that a previous wake already failed to make stick.

This is not hyprmoncfg-specific

sync_internal_scale already has a guard for "the config delegates the scale to the compositor":

# ... substituting one makes the scale flap between that number and the compositor's own value
# on every idle-wake.
if ! valid_scale "$configured_scale" && valid_scale "$active_scale"; then
  return 0
fi

The comment describes exactly this failure mode, but the guard only catches it when monitors.lua
carries no usable number. Any case where monitors.lua carries a number that is not what's actually
applied — a desc:-form rule in an included file, a per-output rule the sed-based parser can't match,
another tool, a compositor-side clamp — produces an unbounded re-apply loop instead. There is no
"I already tried this and it didn't take" state and no backoff.

Note also that omarchy-brightness-display on in the same script already guards against a sibling
symptom, with a comment naming this exact user-visible effect:

# Skip the dispatch when every active display is already lit: a redundant
# DPMS enable right after system resume forces another modeset, which blanks
# the panel for a beat (visible flash at the unlock screen).

So the DPMS half of the wake is protected; the monitor-rule half is not.

Suggested fixes

Any one of these would stop the flicker; the first two seem most valuable:

  1. Don't do monitor reconciliation on every keystroke. Each wake that does get through spawns bash
  • jq + several hyprctl calls. (runWake()'s if (!wakeProcess.running) guard drops keystrokes that

overlap an in-flight wake, so it isn't strictly one run per keypress — but it is one run as often as
the previous one finishes, which while typing is often enough to flicker continuously.) Debounce it,
or split "restore brightness/DPMS" (cheap, wants to be responsive) from "reconcile clamshell monitor
layout" (expensive, only wants to run on lid/output events).
2. Make `sync_internal_scale` give up after a failed attempt. If the eval didn't achieve the desired
scale, stop re-issuing it for this session rather than retrying forever. That bounds the damage for
every unparseable-config case, not just this one.
3. Widen what counts as "the configured scale." Consider rules from every config Hyprland actually
loads, and match desc: forms — or read the desired scale back from the compositor instead of
re-deriving it from a single file by sed.

Workaround

Set the catch-all scale to a non-numeric value so the existing guard engages and Omarchy defers to the
compositor:

-- ~/.config/hypr/monitors.lua
local omarchy_monitor_scale = "auto"

Verified: no config errors, applied scale unchanged, 30 simulated wakes produce zero monitor re-applies
and zero new lines in the Hyprland log. The lid-reopen path still works, falling back to the remembered
~/.local/state/omarchy/toggles/hypr/internal-monitor-scale.

Caveat: per #9950, omarchy-hyprland-monitor-scaling persists scale changes by sed-rewriting
^local omarchy_monitor_scale = .* with a bare number, so using the bar's Display-panel scale presets
replaces "auto" and the flicker returns.

Possibly related

  • #9950 — monitors.lua's single global omarchy_monitor_scale vs. per-output scaling; same

single-file-as-source-of-truth assumption, different symptom.
- #10266 — clamshell monitor reconfiguration ignoring configured mode.
- #10170, #9753 — other clamshell/lid state reconciliation issues.

Happy to attach omarchy debug output or a screen recording of the flicker if useful.

View raw text
### Environment

- Omarchy 4.0.1-1, Hyprland 0.56.2, kernel 7.1.9-arch1-2
- Lenovo Legion, 13th Gen Intel i9-13900HX, hybrid Intel UHD (Raptor Lake-S) + NVIDIA RTX 4070 Mobile
- Single internal panel `eDP-2` — 2560x1600@240, applied scale **1.6**
- Per-output scale is applied by a third-party tool (`hyprmoncfg` / `hyprmoncfgd`) that writes its
  own `~/.config/hypr/hyprmoncfg-monitors.lua`, loaded last from `hyprland.lua`. The mechanism below
  does not depend on that specific tool — see "This is not hyprmoncfg-specific".

### What happens

Typing a password at the lock screen makes the display flicker on **every keystroke**. Each keystroke
causes two full modesets: one from Omarchy forcing a scale the panel isn't using, and one from the
scale being put back.

### Why

`plugins/lock/LockView.qml` emits `wakeRequested` on every keypress — once from `onTextChanged`
and once from `Keys.onPressed`:

```qml
onTextChanged: {
  ...
  if (text.length > 0) {
    root.wakeRequested()          // LockView.qml:166
  }
Keys.onPressed: function(event) {
  root.wakeRequested()            // LockView.qml:178
```

`plugins/lock/Service.qml` turns that into `runWake()` → `omarchy-system-wake`, whose third step is
a full `omarchy-hyprland-monitor-clamshell` run:

```bash
omarchy-brightness-display on
omarchy-brightness-keyboard restore
omarchy-hyprland-monitor-clamshell >/dev/null 2>&1 || true
```

`omarchy-hyprland-monitor-clamshell` reads the desired internal scale from **`~/.config/hypr/monitors.lua`
only** (`MONITOR_LUA` is hardcoded). It cannot see a scale applied from anywhere else, so on this machine
it reads the stock catch-all `local omarchy_monitor_scale = 2`, compares it to the live 1.6, and re-applies:

```
$ bash -x $(which omarchy-hyprland-monitor-clamshell)
+ enable_internal
+ sync_internal_scale
+ configured_scale=2
+ active_scale=1.6
+ scales_match 1.6 2
+ enable_internal_output 2
+ hyprctl eval 'hl.monitor({ output = "eDP-2", mode = "preferred", position = "auto", scale = 2 })'
```

That `hyprctl eval` genuinely changes the scale (verified: 1.6 → 2), which is a modeset. The tool that
owns the layout then puts it back to 1.6 — a second modeset. Because neither side yields, the mismatch
**never resolves**, so the whole sequence repeats on every single keystroke:

```
$ hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
1.6
$ hyprctl eval 'hl.monitor({ output = "eDP-2", mode = "preferred", position = "auto", scale = 2 })'
ok
$ hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
2
$ sleep 2; hyprctl monitors all -j | jq -r '.[]|select(.name=="eDP-2")|.scale'
1.6
```

### Steps to reproduce

1. On a laptop, arrange for the internal panel's applied scale to differ from what `monitors.lua`
   resolves to, in a way `monitors.lua` parsing cannot see. Either:
   - have any external tool/daemon own the per-output scale (a `desc:`-form rule in a separate
     `dofile`d config, as `hyprmoncfg` does), or
   - simulate it by hand: `hyprctl eval 'hl.monitor({ output = "<internal>", scale = 1.6 })'` while
     `monitors.lua` still resolves to `2`.
2. Lock the screen (`omarchy system lock`).
3. Type in the password field.
4. The display flickers per keystroke. `bash -x $(which omarchy-hyprland-monitor-clamshell)` shows
   the `hyprctl eval ... hl.monitor` firing every time.

### Expected

Typing at the lock screen should not reconfigure displays. A wake should not re-apply a monitor rule
that a previous wake already failed to make stick.

### This is not hyprmoncfg-specific

`sync_internal_scale` already has a guard for "the config delegates the scale to the compositor":

```bash
# ... substituting one makes the scale flap between that number and the compositor's own value
# on every idle-wake.
if ! valid_scale "$configured_scale" && valid_scale "$active_scale"; then
  return 0
fi
```

The comment describes exactly this failure mode, but the guard only catches it when `monitors.lua`
carries *no usable number*. Any case where `monitors.lua` carries a number that is not what's actually
applied — a `desc:`-form rule in an included file, a per-output rule the sed-based parser can't match,
another tool, a compositor-side clamp — produces an unbounded re-apply loop instead. There is no
"I already tried this and it didn't take" state and no backoff.

Note also that `omarchy-brightness-display on` in the same script already guards against a sibling
symptom, with a comment naming this exact user-visible effect:

```bash
# Skip the dispatch when every active display is already lit: a redundant
# DPMS enable right after system resume forces another modeset, which blanks
# the panel for a beat (visible flash at the unlock screen).
```

So the DPMS half of the wake is protected; the monitor-rule half is not.

### Suggested fixes

Any one of these would stop the flicker; the first two seem most valuable:

1. **Don't do monitor reconciliation on every keystroke.** Each wake that does get through spawns bash
   + jq + several `hyprctl` calls. (`runWake()`'s `if (!wakeProcess.running)` guard drops keystrokes that
   overlap an in-flight wake, so it isn't strictly one run per keypress — but it is one run as often as
   the previous one finishes, which while typing is often enough to flicker continuously.) Debounce it,
   or split "restore brightness/DPMS" (cheap, wants to be responsive) from "reconcile clamshell monitor
   layout" (expensive, only wants to run on lid/output events).
2. **Make `sync_internal_scale` give up after a failed attempt.** If the eval didn't achieve the desired
   scale, stop re-issuing it for this session rather than retrying forever. That bounds the damage for
   every unparseable-config case, not just this one.
3. **Widen what counts as "the configured scale."** Consider rules from every config Hyprland actually
   loads, and match `desc:` forms — or read the desired scale back from the compositor instead of
   re-deriving it from a single file by `sed`.

### Workaround

Set the catch-all scale to a non-numeric value so the existing guard engages and Omarchy defers to the
compositor:

```lua
-- ~/.config/hypr/monitors.lua
local omarchy_monitor_scale = "auto"
```

Verified: no config errors, applied scale unchanged, 30 simulated wakes produce zero monitor re-applies
and zero new lines in the Hyprland log. The lid-reopen path still works, falling back to the remembered
`~/.local/state/omarchy/toggles/hypr/internal-monitor-scale`.

Caveat: per #9950, `omarchy-hyprland-monitor-scaling` persists scale changes by `sed`-rewriting
`^local omarchy_monitor_scale = .*` with a bare number, so using the bar's Display-panel scale presets
replaces `"auto"` and the flicker returns.

### Possibly related

- #9950 — `monitors.lua`'s single global `omarchy_monitor_scale` vs. per-output scaling; same
  single-file-as-source-of-truth assumption, different symptom.
- #10266 — clamshell monitor reconfiguration ignoring configured mode.
- #10170, #9753 — other clamshell/lid state reconciliation issues.

Happy to attach `omarchy debug` output or a screen recording of the flicker if useful.

Also reported as

This defect is tracked under R-943 (filed Sep 5, 2026). 1 other report describes the same defect.

Earliest report of this defect: R-1655 (filed Aug 19, 2026).

  1. Sep 5, 2026R-943 · this report— tracked here
  2. ·Decided by agents · verified

    Open upstream.

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

  • Related PRpr/10747· confirmed
  • Fixed bypr/7146· confirmed
  • Related PRpr/14583· confirmed

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.

  • Decided by agents · verified: in the audited area (lock)
  • Decided by agents · verified: matches no known issue

The outcome (valid, duplicate, not a bug, …) is not decided yet.