feat(qt): theme Qt apps with Catppuccin via Kvantum

Qt apps (e.g. VLC) rendered in the default Fusion style — GTK theming
does not cover Qt. Add the Kvantum style engine + Catppuccin Mocha
Lavender theme, wired via QT_STYLE_OVERRIDE, which covers both Qt5 and
Qt6 (QT_QPA_PLATFORMTHEME can select only one plugin at a time).

Also move all GUI-toolkit env vars (QT_*/GDK/SDL/CLUTTER) from zshrc to
niri's environment{} block: niri is systemd-started, so zsh exports
never reached niri-spawned GUI apps (verified via /proc/environ), only
terminal-launched ones — the app launcher included.

- packages: kvantum, kvantum-qt5, qt6ct + kvantum-theme-catppuccin-git (AUR)
- niri config.kdl: environment{} block; zshrc: GUI-toolkit vars removed
- qt6ct.conf (style=kvantum, icon_theme=Colloid), Kvantum/kvantum.kvconfig
  (theme=catppuccin-mocha-lavender, the Lavender accent)
- CLAUDE.md + DECISIONS.md
This commit is contained in:
2026-07-15 15:20:21 +02:00
parent de44949c0c
commit 5fe7d2aaeb
8 changed files with 52 additions and 7 deletions
+12
View File
@@ -114,6 +114,18 @@ System-wide generic-family defaults via `defaults/etc/fonts/conf.d/65-moonarch-f
- Aliases need `binding="strong"` — a weak `<prefer>` (fontconfig default) ranks behind the effective generic fallback and does not take effect.
- Only applies to apps that use generic families (e.g. Firefox web fallback). moonarch apps (Waybar, foot, GTK, walker, swaync) set the font explicitly.
## Qt Theming (Catppuccin via Kvantum)
Qt apps (e.g. VLC) get the Catppuccin Mocha look via the **Kvantum** style engine — GTK theming (Colloid) does not cover Qt, and the Qt5 GTK-follow path (`qt5-styleplugins`) is unmaintained and not in the official repos.
- **Style — `QT_STYLE_OVERRIDE=kvantum` is the workhorse.** A single value themes **both Qt5 (VLC 3) and Qt6**. `QT_QPA_PLATFORMTHEME` cannot: one value selects either the Qt5 `qt5ct` plugin or the Qt6 `qt6ct` plugin, never both. The style override sidesteps that, so we ship `kvantum` + `kvantum-qt5` (Qt6 + Qt5 style plugins) and **skip `qt5ct`**.
- **Theme:** `kvantum-theme-catppuccin-git` (AUR) installs all flavors to `/usr/share/Kvantum/`; `defaults/xdg/Kvantum/kvantum.kvconfig` selects `catppuccin-mocha-lavender` (matches the ecosystem Lavender accent `#b4befe`).
- **Qt6 icons/palette:** `QT_QPA_PLATFORMTHEME=qt6ct` + `defaults/xdg/qt6ct/qt6ct.conf` (`icon_theme=Colloid-Grey-Catppuccin-Dark`). Qt5/VLC relies on the style override alone (no platform theme).
- **Env location — must be niri, not zshrc.** niri is started by systemd, so niri-spawned GUI apps (app launcher, `spawn`, `spawn-at-startup`) never inherit zsh exports — only terminal-launched apps would (verified via `/proc/<pid>/environ`). All GUI-toolkit vars therefore live in niri's `environment {}` block (`defaults/xdg/niri/config.kdl`), not `defaults/shell/zshrc`; zshrc keeps only shell-oriented (`TERMINAL`/`EDITOR`) + `XDG_*` session vars.
- **Fonts** come from the fontconfig generic-family defaults (see below); qt6ct leaves fonts unset so they resolve through fontconfig.
Rationale + rejected alternatives: `DECISIONS.md` (2026-07-15).
## Browser Idle-Inhibit (xdg-desktop-portal)
So that windowed browser video (Firefox/Waterfox) keeps the screen awake, via `defaults/etc/xdg-desktop-portal/niri-portals.conf` (owned by moonarch-git, higher priority than niri's `/usr/share/xdg-desktop-portal/niri-portals.conf`):
+6
View File
@@ -242,3 +242,9 @@
- **Why**: A popout action that triggers an external auth toplevel left focus stuck on quickshell — reproduced with the network popout: select a VPN → Enter → `nmcli connection up` fires nm-applet's secret agent → gnome-keyring/gcr shows a GTK unlock prompt, but keyboard focus stayed on the popout, so the prompt was untypeable. Same class for Wi-Fi PSK, polkit, any dialog spawned by any popout. Not VPN-specific — the cause is the popout's keyboard-focus grab.
- **Tradeoffs**: Root cause is `PopoutHost`'s `WlrKeyboardFocus.Exclusive` while open. Per wlr-layer-shell, Exclusive on the overlay layer sits above all normal windows, so the compositor never focuses a newly-mapped toplevel while it holds. Empirically verified on niri 26.04 (`niri msg focused-window`): under **Exclusive**, a prompt maps with `is_focused=false` and `focused-window` stays `null` — no `WindowFocusChanged` fires, so a listen-and-close approach is impossible (there is no focus event to react to). Under **OnDemand**, a keybind-opened popout *still* grabs the keyboard on open (`focused-window: null` → Escape/Tab/arrow nav preserved) **and** an externally-mapped toplevel takes focus (`nm-connection-editor is_focused=true`). So OnDemand fixes it with no loss of the keyboard-nav feature and no per-action handler code. Rejected: closing the popout on the VPN toggle (symptom fix, per-action, doesn't generalise).
- **How**: `PopoutHost.qml``keyboardFocus: root.wantOpen ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.None` (was `Exclusive`), comment updated with the verified niri behaviour. One line; covers every popout and every prompt type.
## 2026-07-15 Qt apps get the Catppuccin look via Kvantum; GUI-toolkit env moved to niri
- **Who**: Dominik, ClaudeCode
- **Why**: Qt apps (concretely VLC 3) ignored the system theme — they rendered in the default Fusion style while everything else is Catppuccin Mocha. moonarch themes GTK system-wide (Colloid) but had no Qt story. Diagnosis found the existing setup half-wired: `QT_QPA_PLATFORMTHEME=qt6ct` was exported but `qt6ct` was never installed, so the variable pointed at nothing.
- **Tradeoffs**: (1) **Approach** — Qt-follows-GTK (`QT_QPA_PLATFORMTHEME=gtk3` / qgnomeplatform) vs. a native Qt Catppuccin theme. GTK-follow was rejected: it fails on the reported app — VLC is Qt5, and the Qt5 GTK-style plugin (`qt5-styleplugins`) is unmaintained and absent from the official repos; GTK-follow is also unreliable on non-GNOME Wayland. Picked **Kvantum** — a maintained Catppuccin theme, best visual match, covers Qt5 + Qt6. (2) **Style wiring**`QT_QPA_PLATFORMTHEME` cannot theme both Qt versions at once (one value selects either the Qt5 `qt5ct` plugin or the Qt6 `qt6ct` plugin, never both). `QT_STYLE_OVERRIDE=kvantum` is honoured by **both** Qt5 and Qt6, so it is the primary mechanism; `qt6ct` is kept only as a Qt6 bonus for icons/palette, and `qt5ct` is skipped (the style override covers the Qt5 look; qt5ct would add only Qt5 icon control). (3) **Env location** — the Qt/GTK/SDL/Clutter vars lived in `defaults/shell/zshrc`. Verified empirically (`/proc/<pid>/environ` of niri and a niri-spawned quickshell) that **niri is systemd-started and its children never inherit zsh exports** — so those vars only ever reached terminal-launched apps, never the app launcher / `spawn`. Rejected keeping them in zshrc (would not fix VLC). Moved all GUI-toolkit vars to niri's `environment {}` block; `TERMINAL`/`EDITOR`/`XDG_*` stay in zshrc. (4) **Theme delivery** — vendor the one Mocha-Lavender theme into `defaults/` vs. the AUR package. Picked the AUR package `kvantum-theme-catppuccin-git` for consistency with how the GTK theme ships (`colloid-catppuccin-theme-git`); it installs to `/usr/share/Kvantum/`, a Kvantum search path.
- **How**: `packages/official.txt` += `kvantum kvantum-qt5 qt6ct`; `packages/aur.txt` += `kvantum-theme-catppuccin-git`. New `environment {}` block in `defaults/xdg/niri/config.kdl` (QT_QPA_PLATFORM, QT_QPA_PLATFORMTHEME=qt6ct, QT_STYLE_OVERRIDE=kvantum, QT_AUTO_SCREEN_SCALE_FACTOR, QT_WAYLAND_DISABLE_WINDOWDECORATION, GDK_BACKEND, SDL_VIDEODRIVER, CLUTTER_BACKEND); the same GUI vars removed from `defaults/shell/zshrc`. New `defaults/xdg/qt6ct/qt6ct.conf` (style=kvantum, icon_theme=Colloid-Grey-Catppuccin-Dark) and `defaults/xdg/Kvantum/kvantum.kvconfig` (theme=catppuccin-mocha-lavender, matching the Lavender accent `#b4befe`). Both deploy to `/etc/xdg/` automatically via the moonarch-git PKGBUILD's `defaults/xdg` glob (no PKGBUILD change); not added to `moonarch-doctor` — like `niri/config.kdl` and the GTK `settings.ini`, owned `/etc/xdg` configs have no `/usr/share/moonarch` reference copy to compare against. Open item at commit time: verify Kvantum reads `kvantum.kvconfig` from `/etc/xdg/Kvantum/`; if not, seed `~/.config/Kvantum/` from post-install (as done for the GTK theme via gsettings).
+3 -7
View File
@@ -125,14 +125,10 @@ if [[ -f /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]];
fi
# --- Wayland environment ---
# GUI-toolkit vars (QT_*/GDK/SDL/CLUTTER) live in niri's environment {} block, not here:
# niri is systemd-started, so a zsh export only reaches terminal-launched apps, never
# niri-spawned GUI apps. Kept here: shell-oriented + XDG session identity.
export TERMINAL="footclient"
export GDK_BACKEND="wayland,x11,*"
export QT_QPA_PLATFORM="wayland;xcb"
export QT_QPA_PLATFORMTHEME="qt6ct"
export QT_AUTO_SCREEN_SCALE_FACTOR="1"
export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
export SDL_VIDEODRIVER="wayland"
export CLUTTER_BACKEND="wayland"
export XDG_CURRENT_DESKTOP="niri"
export XDG_SESSION_DESKTOP="niri"
export XDG_SESSION_TYPE="wayland"
+4
View File
@@ -0,0 +1,4 @@
# ABOUTME: System Kvantum config — selects the Catppuccin Mocha Lavender theme (moonarch accent).
# ABOUTME: Deployed to /etc/xdg/Kvantum/kvantum.kvconfig; a user copy in ~/.config/Kvantum wins by XDG precedence.
[General]
theme=catppuccin-mocha-lavender
+15
View File
@@ -1,6 +1,21 @@
// ABOUTME: Moonarch default Niri compositor configuration.
// ABOUTME: User overrides go in ~/.config/niri/config.kdl
// GUI-toolkit environment for every niri-spawned app (launcher, spawn, spawn-at-startup).
// These must live here, not in zshrc: niri is started by systemd, so a zsh export only
// reaches terminal-launched apps — niri's children never see it. QT_QPA_PLATFORMTHEME +
// QT_STYLE_OVERRIDE give Qt apps (e.g. VLC) the Catppuccin look via qt6ct + Kvantum.
environment {
QT_QPA_PLATFORM "wayland;xcb"
QT_QPA_PLATFORMTHEME "qt6ct"
QT_STYLE_OVERRIDE "kvantum"
QT_AUTO_SCREEN_SCALE_FACTOR "1"
QT_WAYLAND_DISABLE_WINDOWDECORATION "1"
GDK_BACKEND "wayland,x11,*"
SDL_VIDEODRIVER "wayland"
CLUTTER_BACKEND "wayland"
}
cursor {
xcursor-theme "Sweet-cursors"
hide-when-typing
+6
View File
@@ -0,0 +1,6 @@
# ABOUTME: System qt6ct config — Qt6 icon theme + Kvantum style for Catppuccin consistency.
# ABOUTME: Deployed to /etc/xdg/qt6ct/qt6ct.conf; a user copy in ~/.config/qt6ct wins by XDG precedence.
[Appearance]
style=kvantum
icon_theme=Colloid-Grey-Catppuccin-Dark
standard_dialogs=default
+1
View File
@@ -6,6 +6,7 @@
# Theming
colloid-catppuccin-theme-git
kvantum-theme-catppuccin-git
# Fonts
otf-openmoji
+5
View File
@@ -87,6 +87,11 @@ qt6-5compat
# Themes & Fonts
ttf-ubuntusans-nerd
# Qt Theming (Catppuccin via Kvantum — see CLAUDE.md "Qt Theming")
kvantum
kvantum-qt5
qt6ct
# Applications
viewnior