Compare commits

..

3 commits

Author SHA1 Message Date
eb019dc369 Install Hyprland window rules for bar overlap and dialog pointer trap
Rebased onto the Omarchy 4 update (4857667), which the branch these commits
came from predated. Kept both sides:

- the O4 fixes stay (per-package pacman installs, gtk2 dropped, wrapper
  unsets QT_STYLE_OVERRIDE/QT_QPA_PLATFORMTHEME)
- the full-opacity block stays alongside the new rules, noted as redundant
  on Omarchy >= basecamp/omarchy#6382 but still needed on older 4.x builds

README renumbered accordingly and the "002 not fully verified" note dropped,
since both fixes are now verified end-to-end.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:59:02 +01:00
c186dbbceb Add upstream fix handoffs for Omarchy window-rule bugs
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>
2026-07-29 16:56:41 +01:00
48576676ac Update for Omarchy 4: drop gtk2, full-opacity rule, wrapper env cleanup
- Remove gtk2 from deps (dropped from Arch repos; Resolve 21 no longer
  needs it) and install packages individually so one missing target
  can't abort the whole pacman transaction
- Append a resolve-full-opacity rule to ~/.config/hypr/hyprland.lua on
  Omarchy 4, overriding the new global 0.985/0.96 window translucency
  (wrong for colour-critical grading); idempotent, skipped pre-4
- Unset Omarchy's global QT_STYLE_OVERRIDE/QT_QPA_PLATFORMTHEME in the
  wrapper (Resolve's bundled Qt lacks the kvantum/gtk3 plugins)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-26 15:59:10 +01:00
5 changed files with 855 additions and 9 deletions

View file

@ -24,6 +24,8 @@
# 7. Ensures legacy libcrypt.so.1 is available (Arch dropped it)
# 8. Installs desktop entries, icons, and udev rules
# 9. Creates an XWayland wrapper script for Hyprland compatibility
# 10. Installs Hyprland window rules so the Omarchy bar doesn't cover Resolve's
# menu bar, and Resolve's dialogs don't trap the pointer
#
# Prerequisites:
# - Omarchy (Arch Linux) with NVIDIA drivers installed and working
@ -77,25 +79,36 @@ fi
# desktop-file-utils: Provides update-desktop-database for app menu integration
# file: Identifies file types (used to find ELF binaries for patching)
# gtk-update-icon-cache: Refreshes the icon cache so Resolve's icon appears
# Packages are installed one at a time: pacman aborts the ENTIRE transaction
# if any single target is missing from the repos, which would silently leave
# every other dependency uninstalled (this is exactly what happened when Arch
# dropped gtk2 from the official repos).
log "Installing required tools..."
if ! sudo pacman -S --needed --noconfirm unzip patchelf libarchive xdg-user-dirs desktop-file-utils file gtk-update-icon-cache; then
warn "Some optional tools failed to install, continuing anyway..."
fi
for pkg in unzip patchelf libarchive xdg-user-dirs desktop-file-utils file gtk-update-icon-cache; do
if ! sudo pacman -S --needed --noconfirm "${pkg}"; then
warn "Failed to install ${pkg}, continuing anyway..."
fi
done
# Runtime dependencies that Resolve needs but doesn't bundle:
# libxcrypt-compat: Provides legacy libcrypt.so.1 (Arch moved to libxcrypt v2)
# ffmpeg4.4: Older FFmpeg version that Resolve links against
# glu: OpenGL Utility Library (3D rendering support)
# gtk2: GTK2 toolkit (Resolve's UI uses some GTK2 components)
# fuse2: Filesystem in Userspace v2 (for AppImage compatibility)
#
# gtk2 used to be on this list but is gone: Arch removed it from the official
# repos (AUR-only now) and Resolve no longer needs it — the AUR davinci-resolve
# package (21.x) dropped the dependency as well.
#
# IMPORTANT: We deliberately do NOT replace Resolve's bundled libc++/libc++abi
# with system versions. Resolve was compiled against specific C++ ABI versions
# and swapping them causes crashes. Only glib/gio/gmodule get replaced (later).
log "Installing runtime dependencies..."
if ! sudo pacman -S --needed --noconfirm libxcrypt-compat ffmpeg4.4 glu gtk2 fuse2; then
warn "Some runtime dependencies failed to install (may affect functionality)"
fi
for pkg in libxcrypt-compat ffmpeg4.4 glu fuse2; do
if ! sudo pacman -S --needed --noconfirm "${pkg}"; then
warn "Failed to install ${pkg} (may affect functionality)"
fi
done
# Resolve's built-in extras downloader expects TLS certificates at the
# Red Hat/CentOS path (/etc/pki/tls) rather than the Arch path (/etc/ssl).
@ -378,6 +391,10 @@ fi
# Force XWayland under Hyprland/Wayland
export QT_QPA_PLATFORM=xcb
export QT_AUTO_SCREEN_SCALE_FACTOR=1
# Omarchy sets QT_STYLE_OVERRIDE=kvantum and QT_QPA_PLATFORMTHEME=gtk3
# globally (Omarchy 4 envs.lua). Resolve's bundled Qt has neither plugin —
# harmless, but unset them so startup stays free of Qt style warnings.
unset QT_STYLE_OVERRIDE QT_QPA_PLATFORMTHEME
# For hybrid laptops, optionally force dGPU:
# export __NV_PRIME_RENDER_OFFLOAD=1
# export __GLX_VENDOR_LIBRARY_NAME=nvidia
@ -432,6 +449,171 @@ EOF
update-desktop-database "${HOME}/.local/share/applications" >/dev/null 2>&1 || true
sudo gtk-update-icon-cache -f /usr/share/icons/hicolor >/dev/null 2>&1 || true
# ==================== Omarchy 4 full-opacity window rule ====================
#
# Omarchy 4 applies a default translucency to EVERY window (0.985 focused /
# 0.96 unfocused, via a "default-opacity" tag in its Hyprland Lua config).
# Its built-in Resolve rule (default/hypr/apps/davinci-resolve.lua) handles
# dialog focus but does NOT opt out of the translucency — and a translucent
# window is simply wrong for colour-critical grading work.
#
# Fix: append an opacity override to the user's ~/.config/hypr/hyprland.lua.
# That file loads AFTER Omarchy's defaults, and Hyprland applies matching
# window rules in order (last write to a property wins), so this forces
# Resolve back to full opacity without touching Omarchy's own files.
#
# Only runs when an Omarchy 4 Lua config is detected; pre-4 installs never
# applied global translucency, so they need nothing. Idempotent via the
# "resolve-full-opacity" marker.
#
# UPSTREAM: fixed in Omarchy by basecamp/omarchy#6382, which added
# opacity = "1 1" to its own davinci-resolve.lua. This block is therefore
# redundant on current Omarchy and only still matters on Omarchy 4 builds
# predating that PR. Harmless either way — same rule, same value.
HYPR_LUA="${HOME}/.config/hypr/hyprland.lua"
if [[ -f "${HYPR_LUA}" ]] && grep -q 'default\.hypr\.omarchy' "${HYPR_LUA}"; then
if grep -q 'resolve-full-opacity' "${HYPR_LUA}"; then
log "Omarchy 4 opacity rule already present in ${HYPR_LUA}"
else
log "Adding full-opacity window rule for Resolve to ${HYPR_LUA}..."
cat >> "${HYPR_LUA}" <<'EOF'
-- resolve-full-opacity (added by Omarchy_resolve_v2.sh): Omarchy's default
-- window translucency is wrong for colour-critical work; keep DaVinci
-- Resolve fully opaque. Loaded after Omarchy defaults, so this rule wins.
o.window(".*[Rr]esolve.*", { opacity = "1 1" })
EOF
# Reload Hyprland so the rule takes effect now (no-op outside a session)
command -v hyprctl >/dev/null 2>&1 && hyprctl reload >/dev/null 2>&1 || true
fi
else
log "No Omarchy 4 Lua config detected, skipping opacity rule (not needed pre-4)"
fi
# ==================== Hyprland window rules ====================
#
# Two Omarchy-specific Resolve problems are fixed here, both by installing
# Hyprland window rules:
# 1. the status bar covers Resolve's menu bar (omarchy-upstream-fixes/001)
# 2. dialogs trap the pointer until Resolve dies (omarchy-upstream-fixes/002)
#
# UPSTREAM: both are local workarounds. If they land in Omarchy itself this
# block becomes redundant (harmless — the rules are byte-identical to the ones
# proposed upstream — but it can then be dropped).
#
# ---- 1. Bar overlap ----
#
# On Omarchy 4.x the status bar is a Quickshell layer-shell surface (namespace
# "omarchy-bar") sitting on Hyprland's "top" layer. It reserves a 26px
# exclusive zone at the top of the screen, which correctly pushes *tiled*
# windows down.
#
# Resolve is not tiled. Omarchy floats every Resolve window on purpose (see
# /usr/share/omarchy/default/hypr/apps/davinci-resolve.lua) because Resolve's
# many child windows tile badly. 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. The bar then draws on top of
# Resolve's own menu bar (File / Edit / Trim / Timeline / Clip / ...), making
# it unclickable.
#
# THE FIX: Hyprland renders a fullscreen window ABOVE "top"-layer layer-shell
# surfaces, so opening Resolve's main window fullscreen puts it over the bar
# instead of under it. We install a Hyprland window rule that does exactly that.
#
# The rule is deliberately scoped by title. Every Resolve window shares the
# class "resolve", and only the main one may be fullscreened:
# splash screen -> title "resolve"
# project chooser -> title "Project Manager"
# main window -> title "DaVinci Resolve - <project name>"
# Requiring the " - <project>" suffix leaves the splash, the Project Manager
# and Resolve's modal dialogs floating at their natural size.
#
# ---- 2. Dialogs trapping the pointer ----
#
# Omarchy sets `stay_focused = true` on ".*[Rr]esolve.*" — every Resolve window.
# That rule exists for a good reason: Resolve is not Wayland-native, and its
# transient popups (Change Clip Duration, Normalize Audio Levels, ...) close as
# soon as the pointer leaves them unless focus is pinned. See
# https://github.com/hyprwm/Hyprland/discussions/12235
#
# But pinning EVERY Resolve window means that whenever two are visible at once,
# both demand focus and neither yields. Hyprland then flips focus back and
# forth between them and the dialog can't be dismissed — the pointer is stuck
# until Resolve is killed. Observed live, flipping between two windows:
# ACTIVE='Create New Project' windows=['Project Manager','Create New Project']
# ACTIVE='Project Manager' windows=['Project Manager','Create New Project']
# ACTIVE='Create New Project' windows=['Project Manager','Create New Project']
#
# THE FIX: keep the pin on the transient popups, but remove it from the two
# windows those popups open *over* — the main window and the Project Manager.
# At most one pinned window is then ever visible, so nothing can fight. A later,
# more specific rule overrides an earlier one (verified on Hyprland 0.56.1).
#
# Skipped if RESOLVE_NO_HYPR_RULES=1 (e.g. you prefer Resolve windowed, or you
# don't want the installer touching your Hyprland config at all).
if [[ "${RESOLVE_NO_HYPR_RULES:-0}" == "1" ]]; then
log "Skipping Hyprland window rules (RESOLVE_NO_HYPR_RULES=1)"
elif [[ ! -f "${HOME}/.config/hypr/hyprland.lua" ]]; then
# Omarchy 4.x configures Hyprland in Lua. Older Hyprland setups use
# hyprland.conf with a different, version-dependent rule syntax, so rather
# than write something unverified we tell the user what to add.
warn "No ${HOME}/.config/hypr/hyprland.lua found — skipping the Hyprland rules."
warn "If the bar covers Resolve's menu bar, or dialogs trap the pointer, add:"
warn " windowrulev2 = fullscreen, class:^(resolve)\$, title:^(DaVinci Resolve - .+)\$"
warn " windowrulev2 = stayfocused off, class:^(resolve)\$, title:^(DaVinci Resolve - .+|Project Manager)\$"
else
log "Installing Hyprland rules (bar overlap + dialog pointer trap)..."
RESOLVE_HYPR_MODULE="${HOME}/.config/hypr/davinci-resolve.lua"
# Kept byte-identical to the rules proposed upstream in
# omarchy-upstream-fixes/001 and /002, including comment wording and Omarchy's
# house style (max 3-line comments in default/hypr/apps/), so that if they land
# upstream this file is a redundant duplicate rather than a divergent rule.
cat > "${RESOLVE_HYPR_MODULE}" <<'EOF'
-- DaVinci Resolve — installed by Omarchy_resolve_v2.sh.
-- Delete this file and the require() line in hyprland.lua to revert.
-- 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 })
-- Resolve's transient popups close on mouse-out unless focus is pinned, but
-- pinning the windows they open *over* makes two stay_focused windows fight
-- and traps the pointer until Resolve is killed. Unpin the parents only.
o.window({ class = ".*[Rr]esolve.*", title = "^(DaVinci Resolve - .+|Project Manager)$" }, { stay_focused = false })
EOF
# Omarchy's hyprland.lua require()s each user module explicitly — there is no
# auto-loaded drop-in directory. package.path includes ~/.config/?.lua, so
# "hypr.davinci-resolve" resolves to the file written above. Only append the
# require if it isn't already there, so re-running this installer is safe.
RESOLVE_HYPR_MAIN="${HOME}/.config/hypr/hyprland.lua"
if grep -q 'require("hypr.davinci-resolve")' "${RESOLVE_HYPR_MAIN}"; then
log " require(\"hypr.davinci-resolve\") already present in hyprland.lua"
else
cp "${RESOLVE_HYPR_MAIN}" "${RESOLVE_HYPR_MAIN}.bak.$(date +%s)"
cat >> "${RESOLVE_HYPR_MAIN}" <<'EOF'
-- Open DaVinci Resolve's main window over the Omarchy bar instead of under it.
require("hypr.davinci-resolve")
EOF
log " Added require to hyprland.lua (backup .bak.<timestamp> created)"
fi
# Apply immediately if Hyprland is running, and surface any config error
# rather than letting it fail silently until the next login.
if command -v hyprctl >/dev/null 2>&1 && hyprctl version >/dev/null 2>&1; then
hyprctl reload >/dev/null 2>&1 || true
HYPR_ERRORS="$(hyprctl configerrors 2>/dev/null || true)"
if [[ -n "${HYPR_ERRORS}" && "${HYPR_ERRORS}" != "no errors" ]]; then
warn " Hyprland reported config errors after reload:"
warn "${HYPR_ERRORS}"
else
log " Reloaded Hyprland (no config errors)"
fi
fi
fi
# ==================== Audio backend fix (DeckLink → ALSA) ====================
#
# Resolve ships with `Local.Audio.Type = DeckLink` as the default in its
@ -592,7 +774,10 @@ fi
echo
echo "✅ DaVinci Resolve installed to /opt/resolve"
echo " (vendor libc++ kept; libcrypt.so.1 ensured; audio backend → ALSA + snd-aloop)"
echo " (Omarchy 4: full-opacity window rule added — grading needs opaque windows)"
echo " Hyprland rules installed: Resolve sits over the bar; dialogs no longer trap the pointer"
echo " Launch from your app menu, or run: resolve-nvidia-open"
echo " Skip snd-aloop module setup: RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh"
echo " Skip the Hyprland window rules: RESOLVE_NO_HYPR_RULES=1 ./Omarchy_resolve_v2.sh"
echo " Logs: ~/.local/share/DaVinciResolve/logs/ResolveDebug.txt"
echo

123
README.md
View file

@ -61,9 +61,12 @@ chmod +x Omarchy_resolve_v2.sh
| `libxcrypt-compat` | Provides legacy `libcrypt.so.1` (Arch dropped it) |
| `ffmpeg4.4` | Older FFmpeg version that Resolve links against |
| `glu` | OpenGL Utility Library for 3D rendering |
| `gtk2` | GTK2 toolkit (some Resolve UI components use it) |
| `fuse2` | AppImage compatibility layer |
Packages are installed individually so one unavailable package can't abort
the rest. (`gtk2` used to be on this list — Arch moved it to the AUR and
Resolve 19+ no longer needs it, so it was dropped.)
### 2. Extracts Resolve
The download is a ZIP containing a `.run` file (self-extracting AppImage). The script unpacks it in stages:
@ -92,7 +95,7 @@ Every ELF binary in Resolve gets its RPATH patched to point to `/opt/resolve/lib
### 5. Creates XWayland Wrapper
Resolve doesn't support native Wayland. The wrapper script (`resolve-nvidia-open`) forces XWayland mode by setting `QT_QPA_PLATFORM=xcb`, and also clears stale Qt lockfiles that can prevent Resolve from starting after a crash.
Resolve doesn't support native Wayland. The wrapper script (`resolve-nvidia-open`) forces XWayland mode by setting `QT_QPA_PLATFORM=xcb`, and also clears stale Qt lockfiles that can prevent Resolve from starting after a crash. It additionally unsets Omarchy's global `QT_STYLE_OVERRIDE=kvantum` / `QT_QPA_PLATFORMTHEME=gtk3` — Resolve's bundled Qt has neither plugin, so this just silences Qt style warnings.
### 6. Desktop Integration
@ -146,6 +149,90 @@ proceeds normally. The script:
Set `RESOLVE_NO_ALOOP=1` to skip this entirely (useful if you have a
dedicated audio interface Resolve already uses cleanly).
### 8. Full Opacity for Grading (Omarchy 4)
Omarchy 4 applies a default translucency (0.985 focused / 0.96 unfocused) to
every window via its Hyprland Lua config, and its built-in Resolve rule
doesn't opt out — a translucent window is wrong for colour-critical work.
When an Omarchy 4 Lua config is detected, the installer appends a
`resolve-full-opacity` rule to `~/.config/hypr/hyprland.lua` (loaded after
Omarchy's defaults, so it wins) forcing Resolve back to `opacity 1 1`.
Idempotent; skipped entirely on pre-4 installs, which never applied global
translucency. To remove it, delete the `resolve-full-opacity` block from
`~/.config/hypr/hyprland.lua`.
This one has since landed upstream ([basecamp/omarchy#6382](https://github.com/basecamp/omarchy/pull/6382)),
so on current Omarchy the rule is a harmless duplicate of Omarchy's own; it
still matters on Omarchy 4 builds predating that PR.
### 9. Omarchy Bar Overlap Fix
On Omarchy 4.x, Resolve launches with its own menu bar (File / Edit / Trim /
Timeline / …) hidden underneath the Omarchy status bar, so those menus can't be
clicked.
The Omarchy bar is a layer-shell surface on Hyprland's `top` layer that reserves
26px at the top of the screen. That reserved space only constrains *tiled*
windows — and Omarchy deliberately floats every Resolve window, because
Resolve's many child windows tile badly. 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. The bar then draws on top of it.
Hyprland renders a fullscreen window *above* `top`-layer surfaces, so the script
installs a Hyprland rule that opens Resolve's main window fullscreen — putting
Resolve over the bar instead of under it. The bar isn't hidden or killed, and
behaves normally again as soon as you leave fullscreen or focus another window.
The rule is scoped by window title, because every Resolve window shares the same
class and only the main one may be fullscreened:
| window | title | fullscreened? |
|-----------------|------------------------------------|---------------|
| splash screen | `resolve` | no |
| project chooser | `Project Manager` | no |
| modal dialogs | e.g. `Preferences` | no |
| main window | `DaVinci Resolve - <project name>` | yes |
Two files are written (`~/.config/hypr/davinci-resolve.lua` and one `require`
line appended to `~/.config/hypr/hyprland.lua`), then Hyprland is reloaded.
Re-running the installer won't duplicate the `require`, and `hyprland.lua` is
backed up before it's touched.
### 10. Dialog Pointer Trap Fix
Opening Resolve's **Preferences** or **Project Manager** could trap the pointer:
the dialog couldn't be dismissed, nothing else could be clicked, and quitting
Resolve was the only way out.
Omarchy sets `stay_focused = true` on every Resolve window. That rule exists for
a good reason — Resolve isn't Wayland-native, so its transient popups (Change
Clip Duration, Normalize Audio Levels…) close as soon as the pointer leaves them
unless focus is pinned ([Hyprland #12235](https://github.com/hyprwm/Hyprland/discussions/12235)).
Deleting it outright would bring that problem back.
The trouble is it's applied to *all* Resolve windows. When two are visible at
once, both demand focus and neither yields, so Hyprland flips between them
forever. Captured live:
```
ACTIVE='Create New Project' windows=['Project Manager', 'Create New Project']
ACTIVE='Project Manager' windows=['Project Manager', 'Create New Project']
ACTIVE='Create New Project' windows=['Project Manager', 'Create New Project']
```
The script narrows the rule instead of removing it: the pin stays on the
transient popups, and comes off the two windows those popups open *over* — the
main window and the Project Manager. At most one pinned window is ever visible,
so nothing can fight, and every window that relied on the pin still has it.
Set `RESOLVE_NO_HYPR_RULES=1` to skip both Hyprland rules entirely.
> Both of these belong upstream in Omarchy rather than in this installer — see
> [`omarchy-upstream-fixes/`](omarchy-upstream-fixes/) for the ready-to-raise
> patches. Both are verified end-to-end; fix 002's caveats section lists the
> known limitation (its parent list is a blocklist) and an open design question
> for a maintainer.
## Files Installed
### Application
@ -163,6 +250,13 @@ dedicated audio interface Resolve already uses cleanly).
| `/usr/local/bin/resolve-nvidia-open` | XWayland wrapper (main launcher) |
| `/usr/bin/davinci-resolve` | Convenience symlink to wrapper |
### Hyprland Rules
| Path | Purpose |
|------|---------|
| `~/.config/hypr/davinci-resolve.lua` | Opens Resolve's main window over the Omarchy bar; stops dialogs trapping the pointer |
| `~/.config/hypr/hyprland.lua` | One `require("hypr.davinci-resolve")` line appended, plus the `resolve-full-opacity` rule (§8) |
### Desktop Entries
| Path | Purpose |
@ -206,6 +300,22 @@ RESOLVE_NO_ALOOP=1 ./Omarchy_resolve_v2.sh
This skips the `modprobe snd-aloop`, the `/etc/modules-load.d/` entry, and
the PipeWire loopback bridge. The DeckLink → ALSA config patch still runs.
### Skip the Hyprland Window Rules
If you would rather the installer left your Hyprland config alone entirely:
```bash
RESOLVE_NO_HYPR_RULES=1 ./Omarchy_resolve_v2.sh
```
Neither `~/.config/hypr/davinci-resolve.lua` nor the `require` line is written.
The separate full-opacity rule (§8) is not covered by this switch — remove its
`resolve-full-opacity` block from `hyprland.lua` if you don't want it either.
The installer also skips the rules
automatically (with a warning showing the equivalent `windowrulev2` line) if
`~/.config/hypr/hyprland.lua` doesn't exist — i.e. on non-Omarchy-4.x setups
that still use `hyprland.conf`.
### Hybrid GPU Laptops (Optimus)
If you have an Intel iGPU + NVIDIA dGPU, edit the wrapper to force Resolve onto the NVIDIA GPU:
@ -335,6 +445,12 @@ sudo rm -rf /opt/resolve
sudo rm -f /usr/local/bin/resolve-nvidia-open
sudo rm -f /usr/bin/davinci-resolve
# Remove the Hyprland window rules (bar overlap + pointer trap), then reload
rm -f ~/.config/hypr/davinci-resolve.lua
sed -i '/require("hypr.davinci-resolve")/d' ~/.config/hypr/hyprland.lua
sed -i '/Open DaVinci Resolve.s main window over the Omarchy bar/d' ~/.config/hypr/hyprland.lua
hyprctl reload
# Remove desktop entries
sudo rm -f /usr/share/applications/DaVinciResolve.desktop
sudo rm -f /usr/share/applications/DaVinciControlPanelsSetup.desktop
@ -353,6 +469,9 @@ sudo rm -f /usr/lib/udev/rules.d/99-BlackmagicDevices.rules
sudo rm -f /usr/lib/udev/rules.d/99-ResolveKeyboardHID.rules
sudo rm -f /usr/lib/udev/rules.d/99-DavinciPanel.rules
# Remove the Omarchy 4 opacity rule: delete the "resolve-full-opacity" block
# from ~/.config/hypr/hyprland.lua, then: hyprctl reload
# Remove the snd-aloop autoload entry + PipeWire bridge + wireplumber rule
sudo rm -f /etc/modules-load.d/snd-aloop.conf
rm -f ~/.config/pipewire/pipewire.conf.d/50-resolve-aloop-bridge.conf

View file

@ -0,0 +1,238 @@
# 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 01 | 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.

View file

@ -0,0 +1,199 @@
# Fix 002 — DaVinci Resolve's dialogs trap the pointer until Resolve is killed
**Status:** ready to raise — fully verified (§5) · **Target project:** [omarchy](https://github.com/basecamp/omarchy)
**Target file:** `default/hypr/apps/davinci-resolve.lua`
**Change type:** append one window rule + comment. Narrows an existing rule; removes nothing.
> Self-contained handoff. Problem, root cause, patch and verification are all
> below. No other file in this repo is required.
> Both halves are verified: the trap is measurably gone, and the popup
> behaviour `stay_focused` protects is confirmed intact. See §7 for the one
> remaining known limitation and an open design question for the maintainer.
---
## 1. Symptom
Opening certain DaVinci Resolve windows — confirmed with **Preferences** and
**Project Manager** — traps the pointer. The dialog cannot be dismissed and no
other window can be clicked. **Quitting Resolve entirely is the only way out.**
## 2. Root cause
`default/hypr/apps/davinci-resolve.lua` sets `stay_focused = true` on
`.*[Rr]esolve.*` — that is, on *every* Resolve window.
That rule is there for a real reason and **must not simply be deleted**.
Resolve is not Wayland-native, so Hyprland misreads its transient popups
(Change Clip Duration, Normalize Audio Levels, …) and they close the moment the
pointer leaves them unless focus is pinned. See
[hyprwm/Hyprland#12235](https://github.com/hyprwm/Hyprland/discussions/12235),
which is where the `stayfocused` workaround originates.
The bug is that it is applied **too broadly**. `stayfocused` forces focus onto a
window while it is visible. When two Resolve windows are visible at once, both
demand focus and neither yields, so Hyprland flips between them indefinitely.
Captured live, sampling `hyprctl activewindow` every 0.4s, with the Project
Manager and its own child dialog both open:
```
t=361.7 ACTIVE='resolve'|'Create New Project' resolve_windows=['Project Manager', 'Create New Project']
t=365.4 ACTIVE='resolve'|'Project Manager' resolve_windows=['Project Manager', 'Create New Project']
t=365.8 ACTIVE='resolve'|'Create New Project' resolve_windows=['Project Manager', 'Create New Project']
```
Focus oscillates between the two. Neither can be acted on, which is exactly what
"the mouse is captured" looks like from the user's side.
## 3. Fix
Keep the pin where it is needed — the transient popups — and remove it from the
windows those popups open *over*. At most one pinned window is then ever
visible, so nothing can fight.
The two parent windows are the main window and the Project Manager:
| window | role | pinned after fix |
|---|---|---|
| `DaVinci Resolve - <project>` | parent of Preferences, Change Clip Duration, … | no |
| `Project Manager` | parent of Create New Project | no |
| `Preferences`, `Create New Project`, transient popups | children | yes |
This is a narrowing, not a removal: every window that previously relied on
`stay_focused` to stay open still has it.
## 4. The patch
```diff
--- a/default/hypr/apps/davinci-resolve.lua
+++ b/default/hypr/apps/davinci-resolve.lua
@@ -6,3 +6,8 @@
tag = "-default-opacity",
opacity = "1 1",
})
+
+-- stay_focused above stops Resolve's transient popups closing on mouse-out
+-- (hyprwm/Hyprland#12235), but pinning the windows they open over makes two
+-- windows fight for focus and traps the pointer. Unpin the parents only.
+o.window({ class = ".*[Rr]esolve.*", title = "^(DaVinci Resolve - .+|Project Manager)$" }, { stay_focused = false })
```
Independent of fix 001 — different property, order between them doesn't matter.
## 5. Verification performed
Hyprland 0.56.1 / Omarchy 4.0.0.r1440, NVIDIA, 2560×1440 logical.
**The override mechanism is confirmed.** A later, more specific rule does beat
an earlier blanket one, tested in isolation with a throwaway class so nothing
about Resolve could confound it:
```lua
o.window("^(OVERRIDETEST)$", { float = true })
o.window({ class = "^(OVERRIDETEST)$", title = "^nofloat$" }, { float = false })
```
```
title='nofloat' floating=False <- later specific rule wins
title='yesfloat' floating=True <- blanket rule still applies
```
**The oscillation is confirmed** — see the focus log in §2.
**The trap is confirmed removed, by cold-start A/B.** Resolve was started fresh
twice — once with the fix, once with *only* the `stay_focused` exclusion removed
(fix 001 left in place, so the exclusion was the sole variable). In each run
Resolve was focused, focus was then dispatched to another window, and the actual
focus owner sampled 12 times at 0.5s intervals:
| run | config | samples where Resolve held focus | verdict |
|---|---|---|---|
| A | with fix | **0 / 12** | focus sticks elsewhere — not trapped |
| B | control, exclusion removed | **11 / 12** | snaps back to Resolve — trapped |
The control matters: it demonstrates the test can actually detect the trap, so
run A's result is meaningful rather than vacuous.
Both runs exercised the **Project Manager**, one of the two windows the rule
excludes and one of the two originally reported.
**The main window and the popups were then confirmed by hand.** Resolve always
requires a project to be selected from the Project Manager before the main
window opens — it never opens one on its own — so these two checks cannot be
automated and were driven manually by the reporting user:
| check | procedure | result |
|---|---|---|
| Main window no longer traps | Open a project, open **Preferences** from the main window | **Pass** — dismissable, and other applications remain clickable while it is open |
| Popups do not regress | Edit page → right-click clip → **Change Clip Duration**, move pointer off the popup onto the main window | **Pass** — popup stays open |
The second row is the one that matters most: it is the behaviour
`stay_focused` exists to protect, and it survives the narrowing intact.
## 6. How to verify properly
Both halves must be checked — the fix is only correct if it fixes the trap
**and** leaves the popups alone.
```bash
# Log every focus transition while you drive Resolve by hand
while :; do
hyprctl activewindow -j | jq -r '"ACTIVE=\(.class)|\(.title)"'
sleep 0.4
done | uniq
```
Note: Resolve never opens a project on its own — you must select one in the
Project Manager before the main window appears. Both checks below therefore have
to be driven by hand; an unattended launch stops at the chooser.
1. **The trap is gone** — cold-start Resolve, open Project Manager → Create New
Project, then select a project and open Preferences from the main window.
Each dialog should take focus and stay there; you should be able to dismiss
it and click other apps. The log must show no rapid flip-flopping between two
`resolve` windows.
2. **No popup regression** — in the edit page, open a transient popup (right-click
a clip → Change Clip Duration, or Normalize Audio Levels) and move the pointer
off it onto the main window. It must **not** vanish. This is the behaviour
`stay_focused` exists to protect.
## 7. Caveats for the reviewer
- **The parent list is a blocklist and will need extending.** Only
`DaVinci Resolve - <project>` and `Project Manager` are excluded. If another
Resolve window can itself parent a dialog (Project Settings and the Deliver
page are the likely candidates), it will reintroduce the trap and must be
added to the alternation.
- **A cleaner long-term fix may exist.** Hyprland 0.53.3+ added
`input:mouse_refocus`, and [#12235](https://github.com/hyprwm/Hyprland/discussions/12235)
notes `mouse_refocus = 0` as an alternative to `stayfocused` entirely. On
0.56.1 the underlying popup bug may even be fixed, which would make the whole
`stay_focused` rule obsolete. That was not tested here because
`mouse_refocus` is a **global** input setting, not a per-window rule, so
flipping it for every Omarchy user is a much larger decision than this
narrowing. Worth a maintainer's opinion.
- Related open issue: [basecamp/omarchy#5887](https://github.com/basecamp/omarchy/issues/5887)
reports Resolve child windows becoming inaccessible on Omarchy 4.0.0.alpha.
It doesn't mention `stayfocused`, but "child windows become inaccessible when
the main panel is clicked" is consistent with this root cause, and this fix
may resolve it. Worth linking in the PR.
## 8. Upstream conventions this follows
Same set verified for fix 001 — see
[`001-resolve-bar-overlap.md`](001-resolve-bar-overlap.md) §6. Specifically:
3-line comment (house max), table-match form for class+title, single-property
rule inline on one line, 2-space indent, extends the existing app file rather
than adding a new one.
## 9. Suggested PR text
**Title**
```
hypr/apps: stop DaVinci Resolve's dialogs trapping the pointer
```
**Body** — sections 1, 2 and 3 above, then the §5 evidence, then the §7 bullets
stated as known limitations.

View file

@ -0,0 +1,105 @@
# Upstream fixes for Omarchy
Fixes found while getting DaVinci Resolve working on Omarchy that belong
**upstream in [omarchy](https://github.com/basecamp/omarchy)** rather than in
this installer script.
Each file here is a **self-contained handoff**: one numbered Markdown file per
fix, containing everything needed to raise the PR with no other context —
symptom, root cause with evidence, the exact patch, verification already
performed, how to re-verify, and reviewer caveats. Hand one file to a person or
an AI and they can open the PR from it alone.
| # | Fix | Target file | Status |
| --- | ---------------------------------------------------------------- | ------------------------------------------ | -------------- |
| 001 | [Resolve's main window is covered by the bar](001-resolve-bar-overlap.md) | `default/hypr/apps/davinci-resolve.lua` | ready to raise |
| 002 | [Resolve's dialogs trap the pointer](002-resolve-dialog-focus-trap.md) | `default/hypr/apps/davinci-resolve.lua` | ready to raise |
## Raising 001 and 002 — read first
Both fixes append to the **same file**, `default/hypr/apps/davinci-resolve.lua`,
and both diffs are anchored on the same context (`@@ -6,3 @@`, the end of the
original 8-line file). **Whichever lands first will make the other's patch fail
to apply.** They are otherwise independent — different properties, order between
them doesn't matter.
**Raise them as two PRs, 001 first. Do not combine them.**
Combining is tempting — same file, both small — and it does sidestep the patch
conflict. That's the weakest consideration: rebasing 002 after 001 lands means
appending two rules to the end of a file, with no semantic conflict.
The reason to keep them apart is that they carry very different risk:
| | 001 (bar overlap) | 002 (focus trap) |
|---|---|---|
| Nature | purely additive — a new rule for a window that had none | **narrows a rule a maintainer added deliberately** |
| Verified | end-to-end, including negative cases | end-to-end — cold-start A/B, plus hands-on main-window and popup checks |
| If wrong | fails safe — rule stops matching, old behaviour returns | popups vanish on mouse-out: worse than the bug being fixed |
| Likely review | uncontroversial | may attract debate (`mouse_refocus`, blocklist fragility) |
002 touches `stay_focused`, which exists for a documented reason, and carries an
open design question for a maintainer (see its §7). Coupling them makes the
clean, low-risk fix wait on the more debatable one for no benefit.
Both are now fully verified, so 002 no longer needs holding — raise them in
close succession, 001 first.
If a maintainer explicitly asks for them together, use the combined end state
below as the target — one PR, two commits.
### Combined end state (both fixes applied)
```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 })
-- stay_focused above stops Resolve's transient popups closing on mouse-out
-- (hyprwm/Hyprland#12235), but pinning the windows they open over makes two
-- windows fight for focus and traps the pointer. Unpin the parents only.
o.window({ class = ".*[Rr]esolve.*", title = "^(DaVinci Resolve - .+|Project Manager)$" }, { stay_focused = false })
```
### State the testing accurately
Both fixes are verified end-to-end; each file's §5 lists exactly what was
measured and what was checked by hand. Two things are worth carrying into the
PR bodies rather than quietly dropping:
- 002's parent list is a **blocklist** that may need extending (its §7).
- 002 has an **open design question** — whether `input:mouse_refocus` makes the
whole `stay_focused` rule obsolete on Hyprland 0.56.1. Not tested, because it
is a global setting and that is a maintainer's call.
## Conventions
- **Filename:** `NNN-short-slug.md`, numbered in the order found.
- **Status:** `ready to raise``raised (#PR)``merged` / `rejected`. Update
the table above when it changes.
- **Evidence over assertion.** Every claim about behaviour should be backed by
command output pasted into the file (`hyprctl`, `grim` pixel samples, logs),
so a reviewer can judge it without reproducing the setup.
- **State what was actually tested**, including the environment (Hyprland and
Omarchy versions, GPU, resolution/scale). If something was reasoned about but
not run, say so explicitly.
- **Record rejected alternatives** and why, in the caveats section — it saves
the reviewer re-proposing them.
## Relationship to the installer
Until a fix lands upstream, `Omarchy_resolve_v2.sh` applies its own local
equivalent so the installer works today. Those local workarounds are marked in
the script with a comment pointing back to the fix number here. Once a fix is
merged upstream the local workaround becomes redundant — harmless, but it can
then be dropped.