Two Resolve problems on Omarchy 4.x turned out to be bugs in Omarchy's own Hyprland rules rather than in this installer, so document them as ready-to-raise upstream patches: 001 the status bar covers Resolve's menu bar 002 Resolve's dialogs trap the pointer until Resolve is killed Each file is self-contained: symptom, root cause with captured command output, the exact patch in Omarchy's house style, verification performed, how to re-verify, and reviewer caveats. Both fixes are verified end-to-end on Hyprland 0.56.1 / Omarchy 4.0.0.r1440. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
238 lines
10 KiB
Markdown
238 lines
10 KiB
Markdown
# Fix 001 — DaVinci Resolve's main window is covered by the Omarchy bar
|
||
|
||
**Status:** ready to raise · **Target project:** [omarchy](https://github.com/basecamp/omarchy)
|
||
**Target file:** `default/hypr/apps/davinci-resolve.lua`
|
||
**Change type:** append one window rule + explanatory comment. No new deps, no other app affected.
|
||
|
||
> This file is a self-contained handoff. Everything needed to raise the PR —
|
||
> problem, root cause, exact patch, and reproduction/verification steps — is
|
||
> below. No other file in this repo is required.
|
||
|
||
---
|
||
|
||
## 1. Symptom
|
||
|
||
On Omarchy 4.x, launching DaVinci Resolve leaves Resolve's **own** menu bar
|
||
(File / Edit / Trim / Timeline / Clip / …) hidden underneath the Omarchy status
|
||
bar, so those menus cannot be clicked.
|
||
|
||
## 2. Root cause
|
||
|
||
`omarchy-bar` is a layer-shell surface on Hyprland's `top` layer with a 26px
|
||
exclusive zone:
|
||
|
||
```
|
||
$ hyprctl layers
|
||
Layer level 2 (top):
|
||
Layer ...: xywh: 0 0 2560 26, a: 1, namespace: omarchy-bar, pid: 1582
|
||
```
|
||
|
||
That reserved zone only constrains **tiled** windows. It is being honoured
|
||
correctly — `hyprctl monitors` reports `reserved: [0, 26, 0, 0]`, and tiled
|
||
windows start at y=38 as expected.
|
||
|
||
The problem is that Resolve is not tiled. `default/hypr/apps/davinci-resolve.lua`
|
||
floats every Resolve window, which is the right call — Resolve's many child
|
||
windows tile badly. But floating windows are positioned by the client, and
|
||
Resolve's XWayland main window places itself at **0,0 at the full monitor
|
||
size**, ignoring the reserved zone entirely:
|
||
|
||
```
|
||
class='resolve' title='DaVinci Resolve - New Project 2' at=[0, 0] size=[2560, 1440] float=True fs=0
|
||
```
|
||
|
||
So the bar, being on the `top` layer, draws over it.
|
||
|
||
## 3. Fix
|
||
|
||
Hyprland renders a fullscreen window **above** `top`-layer layer-shell surfaces.
|
||
Opening Resolve's main window fullscreen therefore puts Resolve over the bar
|
||
instead of under it. The bar is not modified, hidden, or killed — it behaves
|
||
normally again as soon as you leave fullscreen or focus another window.
|
||
|
||
### Why the title match must be narrow
|
||
|
||
Every Resolve window shares the same class, and only the main one may be
|
||
fullscreened. Windows observed during a cold start:
|
||
|
||
| window | title | size | fullscreened |
|
||
| --------------- | ---------------------------------- | --------- | ------------ |
|
||
| splash screen | `resolve` | 740×326 | no |
|
||
| project chooser | `Project Manager` | 900×512 | no |
|
||
| modal dialogs | e.g. `Preferences` | 630×534 | no |
|
||
| main window | `DaVinci Resolve - <project name>` | 2560×1440 | **yes** |
|
||
|
||
Requiring the `" - <project>"` suffix leaves the splash, the Project Manager and
|
||
Resolve's modal dialogs floating at their natural size. A class-only rule would
|
||
fullscreen all of them, which is why the rule is title-scoped.
|
||
|
||
The class pattern `.*[Rr]esolve.*` is kept byte-identical to the existing rule in
|
||
this file for consistency; the title is what does the scoping. Both patterns
|
||
were verified together as the exact string in the patch (see §5), not inferred
|
||
from testing the two halves separately.
|
||
|
||
## 4. The patch
|
||
|
||
Four lines: a blank, a three-line comment, and the rule. Apply with `git apply`:
|
||
|
||
```diff
|
||
--- a/default/hypr/apps/davinci-resolve.lua
|
||
+++ b/default/hypr/apps/davinci-resolve.lua
|
||
@@ -6,3 +6,9 @@
|
||
tag = "-default-opacity",
|
||
opacity = "1 1",
|
||
})
|
||
+
|
||
+-- Resolve's floating main window ignores the bar's reserved zone, so the bar
|
||
+-- covers its menu bar; fullscreen renders above top-layer surfaces. Scoped by
|
||
+-- title so the splash and Project Manager keep their natural size.
|
||
+o.window({ class = ".*[Rr]esolve.*", title = "^DaVinci Resolve - .+$" }, { fullscreen = true })
|
||
```
|
||
|
||
If the diff doesn't apply cleanly (upstream moved), the change is just
|
||
**append the comment and this line to the end of the file**:
|
||
|
||
```lua
|
||
o.window({ class = ".*[Rr]esolve.*", title = "^DaVinci Resolve - .+$" }, { fullscreen = true })
|
||
```
|
||
|
||
### Resulting complete file
|
||
|
||
```lua
|
||
-- DaVinci Resolve window focus handling. Kept fully opaque: the default
|
||
-- translucency distorts colour-critical grading work.
|
||
o.window(".*[Rr]esolve.*", {
|
||
float = true,
|
||
stay_focused = true,
|
||
tag = "-default-opacity",
|
||
opacity = "1 1",
|
||
})
|
||
|
||
-- Resolve's floating main window ignores the bar's reserved zone, so the bar
|
||
-- covers its menu bar; fullscreen renders above top-layer surfaces. Scoped by
|
||
-- title so the splash and Project Manager keep their natural size.
|
||
o.window({ class = ".*[Rr]esolve.*", title = "^DaVinci Resolve - .+$" }, { fullscreen = true })
|
||
```
|
||
|
||
### Optional, once the PR is open
|
||
|
||
`default/hypr/apps/jetbrains.lua` sets the precedent of keeping the code terse
|
||
and parking the deep rationale behind a link:
|
||
|
||
```lua
|
||
-- Disable mouse focus (see https://github.com/basecamp/omarchy/pull/5183#issuecomment-4189299971).
|
||
```
|
||
|
||
If a reviewer wants more detail inline than the three lines give, follow that
|
||
pattern — append `(see <this PR's URL>)` to the comment rather than expanding
|
||
the comment block.
|
||
|
||
## 5. Verification performed
|
||
|
||
Tested on Hyprland 0.56.1 / Omarchy 4.0.0.r1440, NVIDIA, 2560×1440 logical
|
||
(3840×2160 physical, scale 1.5).
|
||
|
||
Method: sample the top 26px strip with `grim`. Bar colour is `(26,27,38)`;
|
||
Resolve's UI chrome is `(23,24,26)`.
|
||
|
||
**Before** — bar covers Resolve:
|
||
|
||
```
|
||
y= 5 [(26, 27, 38), (26, 27, 38), (26, 27, 38)] <- bar
|
||
y= 20 [(26, 27, 38), (26, 27, 38), (26, 27, 38)] <- bar
|
||
y= 35 [(26, 27, 38), (26, 27, 38), (26, 27, 38)] <- bar
|
||
y= 45 [(23, 24, 26), (23, 24, 26), (23, 24, 26)] <- Resolve only starts here
|
||
```
|
||
|
||
**After** — Resolve renders over the bar, its menu text now visible at y=35:
|
||
|
||
```
|
||
y= 5 [(23, 24, 26), (23, 24, 26), (23, 24, 26)]
|
||
y= 20 [(23, 24, 26), (23, 24, 26), (23, 24, 26)]
|
||
y= 35 [(179, 180, 180), (23, 24, 26), (23, 24, 26)] <- menu text
|
||
y= 45 [(23, 24, 26), (23, 24, 26), (23, 24, 26)]
|
||
```
|
||
|
||
With the exact rule string above installed, a cold start produces precisely the
|
||
intended scoping — only the main window is fullscreened, and a modal dialog that
|
||
happened to open during the run was correctly left alone:
|
||
|
||
```
|
||
title='resolve' size=[740, 326] FULLSCREEN=0
|
||
title='Project Manager' size=[900, 512] FULLSCREEN=0
|
||
title='DaVinci Resolve - New Project 2' size=[2560, 1440] FULLSCREEN=2
|
||
title='Preferences' size=[630, 534] FULLSCREEN=0
|
||
```
|
||
|
||
That `Preferences` line is the important one: it is the failure mode a
|
||
class-only rule would produce (a 630×534 dialog blown up to fill the screen),
|
||
and it demonstrably does not happen.
|
||
|
||
Also confirmed visually by the reporting user.
|
||
|
||
### How to re-verify
|
||
|
||
```bash
|
||
# 1. Watch what Resolve opens, and at what size / fullscreen state
|
||
(while :; do
|
||
hyprctl clients -j | jq -r '.[] | select(.class=="resolve")
|
||
| "title=\(.title) size=\(.size) FULLSCREEN=\(.fullscreen)"'
|
||
sleep 2
|
||
done) | sort -u &
|
||
|
||
# 2. Launch Resolve, then SELECT A PROJECT in the Project Manager.
|
||
# Resolve never opens a project on its own, so an unattended launch stops
|
||
# at the chooser and the main window never appears.
|
||
# 3. Confirm the top strip belongs to Resolve, not the bar
|
||
grim -g "0,0 1200x60" /tmp/top.png
|
||
```
|
||
|
||
Expect the splash and Project Manager at `FULLSCREEN=0`, and only
|
||
`DaVinci Resolve - <project>` at `FULLSCREEN=2`.
|
||
|
||
## 6. Upstream conventions this follows
|
||
|
||
Checked against every file in `default/hypr/apps/` on omarchy 4.0.0.r1440, not
|
||
assumed. Keep these in mind if the patch is reworked.
|
||
|
||
| Convention | Evidence upstream | How this patch complies |
|
||
|---|---|---|
|
||
| Comments are terse — **3 lines is the maximum** anywhere in `apps/` | longest are `webcam-overlay.lua`, `system.lua`, `omarchy-shell.lua` at 3 lines; most files have 0–1 | 3-line comment |
|
||
| Deep rationale goes in the PR, linked from code — not expanded inline | `jetbrains.lua` links a PR comment for its one-line rule | full rationale lives in this file / the PR; optional link noted above |
|
||
| Class+title matching uses the table form `o.window({ class = …, title = … }, { … })` | `battlenet.lua`, `omarchy-shell.lua`, `system.lua` | same form |
|
||
| Single-property rules stay inline on one line; only multi-property rules break across lines | `moonlight.lua`, `geforce.lua`, `qemu.lua` inline vs `retroarch.lua`, `pip.lua` multi-line | one property (`fullscreen = true`), inline |
|
||
| `fullscreen = true` is the established idiom for this | `moonlight.lua`, `retroarch.lua`, `system.lua` (screensaver) | same property |
|
||
| Long lines are acceptable — no wrapping for its own sake | `omarchy-shell.lua` (~180 chars), `browser.lua` (~150) | rule line is ~95 chars |
|
||
| Regex metacharacters escaped as `\\.` in Lua strings | `battlenet.lua`: `"^Battle\\.net$"` | no literal dot in the title; `.+` is intentional |
|
||
| 2-space indent, double-quoted strings | throughout | matches |
|
||
| One app per file, named after the app | the whole directory | extends the existing `davinci-resolve.lua` rather than adding a file |
|
||
|
||
Note the packaged copy of Omarchy ships no `stylua.toml`, `.editorconfig` or
|
||
`CONTRIBUTING.md` (they aren't included in the package), so style here is
|
||
inferred from the source files themselves. Check the GitHub repo for a
|
||
formatter config before raising, and run it if one exists.
|
||
|
||
## 7. Suggested PR text
|
||
|
||
**Title**
|
||
|
||
```
|
||
hypr/apps: open DaVinci Resolve's main window fullscreen so it isn't covered by the bar
|
||
```
|
||
|
||
**Body** — sections 1, 2, 3 and 5 above, in that order.
|
||
|
||
## 8. Caveats for the reviewer
|
||
|
||
- Only the **main** window is fullscreened; splash, Project Manager and modal
|
||
dialogs are untouched. This is the whole point of the title scoping.
|
||
- If a user leaves fullscreen manually, the bar covers Resolve again — inherent
|
||
to the approach, and recoverable with `SUPER + F`.
|
||
- The title is matched at window-open time. If a future Resolve release changes
|
||
its main-window title format away from `DaVinci Resolve - <project>`, the rule
|
||
silently stops matching and the old behaviour returns. It fails safe: no
|
||
window gets wrongly fullscreened.
|
||
- An alternative considered and rejected: having Resolve's launcher run
|
||
`omarchy toggle bar off` and restore it on exit. It needs no window titles,
|
||
but hides the bar system-wide across all workspaces for as long as Resolve is
|
||
open, and leaves the bar hidden if the process is killed uncleanly.
|