diff --git a/CLAUDE.md b/CLAUDE.md index 8fefe9f..5dd38e8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -9,6 +9,13 @@ Reproducible Arch Linux setup based on archinstall + post-install automation. - `packages/` — package lists (official + AUR), maintained separately - `defaults/` — XDG configs, shell config, helper binaries, systemd services, udev rules, greetd/regreet config, swaylock config, wallpaper +## Lock Screen (swaylock) + +- **Config path is not XDG.** swaylock searches `~/.swaylock/config`, `$XDG_CONFIG_HOME/swaylock/config` and `SYSCONFDIR/swaylock/config` (`/etc/swaylock/config` on Arch) — **never `/etc/xdg/`**. Verified by running swaylock against a throwaway `HOME` containing an invalid option: it rejects the option before it even connects to the compositor, and reports nothing at all when the file sits in `/etc/xdg/`. The config therefore lives in `defaults/etc/swaylock/config` and is installed by an explicit `install` line in the PKGBUILD, deliberately **outside** the generic `defaults/xdg/` → `/etc/xdg/` sweep. +- **No home seeding.** Owning `/etc/swaylock/config` makes the config effective through the package alone. The earlier approach seeded it into `/etc/skel` and existing homes from the `.install` hook; that hook only fires on a moonarch-git install/upgrade and only under `[ ! -f ]`, so a machine that pulled no update since swaylock arrived ran entirely unconfigured — no wallpaper, no Catppuccin ring. `pre_upgrade` retires those copies, but only the pristine ones (`cmp` against the still-old `/etc/xdg/swaylock/config`); an edited copy stays and keeps winning, which is what the home path is for. `moonarch-doctor` reports which file actually wins. +- **Blur is baked into the image.** Upstream swaylock has no blur — `effect-blur` exists only in the `swaylock-effects` fork, which is stuck on 1.7 upstream. So `defaults/backgrounds/wallpaper-blur.jpg` ships next to the plain wallpaper, generated once with `magick wallpaper.jpg -resize 25% -blur 0x12 -resize 4717x2984! -quality 88 -strip wallpaper-blur.jpg`. Downsample-blur-upsample rather than a large-radius blur at full resolution: same look, and the file compresses to 167 KB against the original's 374 KB. Regenerate it whenever the wallpaper changes — nothing derives it automatically. +- **NixOS reads a different path.** nixpkgs leaves meson's `sysconfdir` at `$out/etc`, so `/etc/swaylock/config` is never consulted there. moonix keeps its own `systemd.user.tmpfiles` seed into `~/.config/swaylock/config` (`moonix/modules/desktop.nix`) and substitutes the wallpaper path for a store path — that seed is why moonix is unaffected by the change above. + ## Battery Conservation Mode Laptops with `charge_control_end_threshold` support (ThinkPad, Framework, etc.) get a Waybar toggle: diff --git a/DECISIONS.md b/DECISIONS.md index 784b1df..6397a0b 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -1,5 +1,11 @@ # Decisions +## 2026-08-18 – swaylock config moves to /etc/swaylock, background is pre-blurred +- **Who**: Dominik, ClaudeCode +- **Why**: A second machine showed no lock screen background. The config was installed to `/etc/xdg/swaylock/config`, which swaylock never reads (only `~/.swaylock/config`, `$XDG_CONFIG_HOME/swaylock/config`, `SYSCONFDIR/swaylock/config`), and was made effective by seeding it into user homes from `post-install.sh` and the `.install` hook. Both seeds are conditional — the hook fires only on a moonarch-git install/upgrade and only under `[ ! -f ]` — so a machine that pulled no update since swaylock arrived (2026-08-14) ran with no config at all. Verified by running swaylock against a throwaway `HOME`: it rejects an invalid option from `~/.config/swaylock/config` before connecting to the compositor, and reports nothing when the same file sits in `/etc/xdg/`. The machine this was investigated on had the same gap unnoticed — its home copy had been renamed to `config.bak`, so neither machine was actually reading a config. Second request: the background should be blurred. +- **Tradeoffs**: (1) **Where the config lives** — owning `/etc/swaylock/config` was chosen over keeping the seed. It takes effect through the package alone, with no home state and no `[ ! -f ]` window to miss. Keeping both paths was rejected as redundant, and repairing only the seeding was rejected because it needs a manual step per machine and repeats on the next one. The original reason for seeding (`DECISIONS.md` 2026-08-14, tradeoff 4) was NixOS, where nixpkgs leaves meson's `sysconfdir` at `$out/etc` — but moonix runs its own tmpfiles seed anyway, so the Arch path does not have to carry that constraint. (2) **The shadowing problem** — home paths are searched first, so every already-seeded copy would hide the new system config forever, blur included. `pre_upgrade` deletes those copies, but only where `cmp` against the still-old `/etc/xdg/swaylock/config` proves them pristine; an edited copy stays and keeps winning. Only one config version was ever shipped (`a17474f`), so that comparison is unambiguous. (3) **How to blur** — `swaylock-effects` would blur the live screen contents (`screenshots` + `effect-blur`, as an older config of Dominik's did), but the fork replaces the swaylock package and its AUR release sits on 1.7 while upstream is at 1.8.6. A `grim` + ImageMagick wrapper would blur the real screen without a fork, at the price of lock latency and a blurred copy of the screen briefly on disk. Dominik chose the third option: a blurred copy of the wallpaper, shipped as an image. No fork, no wrapper, identical on Arch and NixOS — the price is that it blurs the wallpaper, not what is on screen. (4) **Blur method** — downsample, blur, upsample instead of a large-radius blur at full resolution. Same result to the eye, and the file compresses to 167 KB against the plain wallpaper's 374 KB. +- **How**: `defaults/xdg/swaylock/config` → `defaults/etc/swaylock/config`, `image=` pointing at the new `defaults/backgrounds/wallpaper-blur.jpg` (`magick wallpaper.jpg -resize 25% -blur 0x12 -resize 4717x2984! -quality 88 -strip`). The PKGBUILD installs both with explicit `install` lines — the config deliberately outside the generic `defaults/xdg/` → `/etc/xdg/` sweep that caused the wrong path in the first place. `moonarch.install` loses its swaylock seeding block and gains the `pre_upgrade` retirement of the home copies; `post-install.sh` loses its seeding block. New `check_swaylock_config` in `moonarch-doctor` names the file that actually wins and fails when none exists. `moonix/modules/desktop.nix` substitutes from the new source path and points at the blurred wallpaper; its tmpfiles seed stays, since `/etc/swaylock/config` is not read there. + ## 2026-08-18 – Popouts close when the focus leaves them - **Who**: Dominik, ClaudeCode - **Why**: An open popout only closed on a backdrop click, Escape, a toggle, or another screen claiming the system-wide slot. Anything that moved the focus without a click — Alt+Tab, a focus keybind, a workspace switch, a newly mapped window — left the popout standing over the desktop. diff --git a/README.md b/README.md index 9c92710..452284e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ desktop that can be rebuilt from scratch in minutes. |-----------|--------|-----| | **Compositor** | [Niri](https://github.com/YaLTeR/niri) | Scrollable tiling — no fixed grid, infinite horizontal workspace. Purpose-built Wayland compositor, not an X11 port. | | **Greeter** | [greetd](https://sr.ht/~kennylevinsen/greetd/) + [ReGreet](https://github.com/rharish101/ReGreet) | Minimal, Wayland-native login. ReGreet is a GTK4 greeter from the official repos, running inside its own Niri instance and inheriting the system GTK theme. | -| **Lock Screen** | [swaylock](https://github.com/swaywm/swaylock) | ext-session-lock-v1 protocol — compositor guarantees lock on crash. PAM authentication, one Wayland protocol, no toolkit. | +| **Lock Screen** | [swaylock](https://github.com/swaywm/swaylock) | ext-session-lock-v1 protocol — compositor guarantees lock on crash. PAM authentication, one Wayland protocol, no toolkit. Background is a blurred copy of the default wallpaper, blurred at build time because upstream swaylock has no blur effect. | | **Power Menu** | Quickshell popout (`PowerPopout.qml`) | Lock, logout, hibernate, reboot, shutdown; every action except lock needs a second click. Part of the bar, so it needs no own package. | | **Idle Manager** | [stasis](https://aur.archlinux.org/packages/stasis) + [wayland-pipewire-idle-inhibit](https://github.com/rafaelrc7/wayland-pipewire-idle-inhibit) | Separate AC/battery power plans. Brightness dimming, DPMS, lock (via swaylock), and suspend on configurable timeouts. The companion inhibitor holds a Wayland idle-inhibitor while audio plays — keeps the screen awake during windowed browser video, which stasis' pactl detection skips by design. | | **Bar** | [Waybar](https://github.com/Alexays/Waybar) | Wayland-native, highly customizable. Niri workspace/window modules via community plugins. | diff --git a/defaults/backgrounds/wallpaper-blur.jpg b/defaults/backgrounds/wallpaper-blur.jpg new file mode 100644 index 0000000..0125dc6 Binary files /dev/null and b/defaults/backgrounds/wallpaper-blur.jpg differ diff --git a/defaults/xdg/swaylock/config b/defaults/etc/swaylock/config similarity index 62% rename from defaults/xdg/swaylock/config rename to defaults/etc/swaylock/config index 634e061..bf433ff 100644 --- a/defaults/xdg/swaylock/config +++ b/defaults/etc/swaylock/config @@ -1,10 +1,18 @@ # ABOUTME: Moonarch default swaylock configuration, Catppuccin Mocha. -# ABOUTME: Seeded to ~/.config/swaylock/config; callers pass -f themselves. +# ABOUTME: Installed to /etc/swaylock/config; callers pass -f themselves. # # Each line is turned into a --long-option by swaylock, so key=value applies. # Colors are rrggbb[aa] without a leading '#'. +# +# swaylock searches ~/.swaylock/config, $XDG_CONFIG_HOME/swaylock/config and +# SYSCONFDIR/swaylock/config (= /etc/swaylock/config) — never /etc/xdg/. This +# file therefore ships to /etc/swaylock/, not to /etc/xdg/swaylock/. A user copy +# in ~/.config/swaylock/config still wins, since the home paths are searched first. -image=/usr/share/moonarch/wallpaper.jpg +# Blurred variant of the default wallpaper. swaylock has no blur of its own — +# effect-blur exists only in the swaylock-effects fork — so the blur is baked +# into the image at build time. +image=/usr/share/moonarch/wallpaper-blur.jpg scaling=fill font=UbuntuSans Nerd Font diff --git a/scripts/moonarch-doctor b/scripts/moonarch-doctor index c3d36cb..261f20d 100755 --- a/scripts/moonarch-doctor +++ b/scripts/moonarch-doctor @@ -71,6 +71,27 @@ check_user_service() { fi } +# swaylock reads ~/.swaylock/config, $XDG_CONFIG_HOME/swaylock/config and +# /etc/swaylock/config, in that order. Moonarch owns the last one, so a copy in +# the home shadows it — silently, and a stale one from the retired seeding drops +# the blurred wallpaper. Report the file that actually wins. +check_swaylock_config() { + local system="/etc/swaylock/config" + local home_cfg + for home_cfg in "$HOME/.swaylock/config" "${XDG_CONFIG_HOME:-$HOME/.config}/swaylock/config"; do + if [[ -f "$home_cfg" ]]; then + warn "swaylock config: $home_cfg shadows $system" + return + fi + done + + if [[ -f "$system" ]]; then + pass "swaylock config: $system" + else + fail "swaylock config: $system (missing — swaylock starts unconfigured)" + fi +} + check_config_match() { local deployed="$1" local source="$2" @@ -217,6 +238,8 @@ check_config_match "/etc/greetd/niri-greeter.kdl" "$SRC/greetd/niri-greeter.k check_config_match "/etc/greetd/regreet.toml" "$SRC/greetd/regreet.toml" check_config_match "/etc/greetd/regreet.css" "$SRC/greetd/regreet.css" +check_swaylock_config + # --- 5. Helper Scripts --- section "Helper Scripts" diff --git a/scripts/post-install.sh b/scripts/post-install.sh index 9dcb24d..052ecf0 100755 --- a/scripts/post-install.sh +++ b/scripts/post-install.sh @@ -128,15 +128,8 @@ if [[ ! -f "$HOME/.config/stasis/stasis.rune" && -f /etc/xdg/stasis/stasis.rune install -Dm644 /etc/xdg/stasis/stasis.rune "$HOME/.config/stasis/stasis.rune" fi -# --- Seed swaylock user config --- -# -# swaylock searches ~/.swaylock/config, $XDG_CONFIG_HOME/swaylock/config and -# SYSCONFDIR/swaylock/config, but never /etc/xdg/. Seed Moonarch's template to -# the user home. Never overwrite an existing user config. -if [[ ! -f "$HOME/.config/swaylock/config" && -f /etc/xdg/swaylock/config ]]; then - log "Seeding Moonarch swaylock config to user home." - install -Dm644 /etc/xdg/swaylock/config "$HOME/.config/swaylock/config" -fi +# swaylock needs no seeding: its config ships to /etc/swaylock/config, which is +# swaylock's own SYSCONFDIR path, so the package alone makes it effective. # --- Enable systemd user services ---