Files
Nomarchy/modules/home/default.nix
Bernardo Magri 6439105d38
Some checks failed
Check / eval (push) Failing after 1m41s
feat(audio,menu): dock audio auto-follow watcher + docked Display/Audio menu rows
Bernardo's dock test (the #87 V3): audio stayed on EasyEffects→speakers.
Root cause, established live: WirePlumber's stored default
(default-nodes state, written by any past explicit pick) outranks the
priority.session rules, so #87 alone can never move the default on a
real machine; EasyEffects 8 follows the default device (kcfg default
true, verified by watching its output links). Fix: nomarchy-dock-audio
(modules/home/dock-audio.nix, nomarchy.dockAudio.enable, default on) —
a pactl-subscribe watcher that set-default-sinks new dock-class sinks
(regex data imported from modules/nixos/dock-audio-rules.nix, single
source) with a toast, plus a startup sweep for login-while-docked that
never overrides a manual in-dock pick. Unplug falls back by priority.

Menus: Display gains docked rows — "Laptop screen off · everything →
<ext>" (live-only disable; a persisted one could black-screen an
undocked boot), "Screen on · <name>", "Move workspace · → next
monitor", "Swap workspaces" (exactly-2 gate); Audio gains a self-gated
"Send output → <dock sink>" quick row. All self-gate on real outputs.

Verified: V2-equivalent on live hardware (no dock available) — watcher
followed a fake dock-named null sink and fell back on unload, control
run without the watcher stayed pinned (proving the stored-default
diagnosis), EE output links moved mid-playback; generated menu bash -n
green, dock-row jq exercised on real pactl JSON, dispatchers probed on
live Hyprland; flake check + option-docs + template-sot green.
V3 pending: real-dock retest ×2 in HARDWARE-QUEUE (watcher keys on
new-sink events; pre-existing nodes that only flip route availability
would need the queued diagnosis data).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 14:22:49 +01:00

124 lines
5.6 KiB
Nix

# Nomarchy — Home Manager entry point.
# Consume this via homeModules.nomarchy (flake.nix), which also pulls in
# the stylix home module that stylix.nix configures.
{ config, lib, pkgs, ... }:
{
imports = [
./options.nix # the nomarchy.* option surface
./theme.nix # ingests theme-state.json, owns the live-sync hooks
./stylix.nix # GTK/Qt/cursor/fonts from the same JSON
./hyprland.nix
./waybar.nix
./ghostty.nix
./btop.nix
./rofi.nix # launcher theming + the nomarchy-menu dispatcher
./swaync.nix # notification daemon, themed from the same JSON
./idle.nix # hyprlock + hypridle, themed from the same JSON
./yazi.nix # flagship TUI file manager, themed + plugins
./osd.nix # swayosd volume/brightness OSD, themed
./nightlight.nix # scheduled blue-light filter (hyprsunset), opt-in
./autotheme.nix # auto day/night theme switch (settings.autoTheme), opt-in
./timezone.nix # keep the Waybar clock in step with auto-timezone changes
./updates.nix # passive update-awareness indicator + notification, opt-in
./shell.nix # zsh + starship + bat/eza/zoxide, themed
./keys.nix # gpg-agent (fronts SSH) + pinentry-qt
./fastfetch.nix # system info with the themed Nomarchy logo
./viewers.nix # zathura (Stylix-themed) + imv — PDF/image viewing
./mime.nix # default applications (mimeapps.list), degrades with the suite
./recording.nix # nomarchy-record: screen recording behind Capture + the bar ⏺
./battery-notify.nix # low-battery toasts at the bar's 25/10% thresholds
./dock-audio.nix # default sink follows dock/monitor audio on hotplug (#87)
./first-boot.nix # one-shot "you're set" toast on first session (#81)
./satty.nix # satty screenshot annotation tool, themed
];
# Clipboard history (wl-paste watcher); browsed via the SUPER+CTRL+V
# menu module.
services.cliphist.enable = true;
# Automount removable media (USB drives) and provide safe-removal notifications.
services.udiskie.enable = true;
# Microphone noise cancellation (rnnoise) and audio EQ.
# Tray icon is built into EasyEffects 8 (Qt StatusNotifierItem); the
# daemon must start after a tray HOST is live or the icon is missing
# for the whole session (wwmm/easyeffects#4636). After=waybar.service
# was inert — Nomarchy's waybar runs from the nomarchy-waybar
# supervisor (Hyprland exec-once), not a systemd unit, so the race was
# a boot-order coin flip (lost on TuringMachine 2026-07-11). Gate on
# the watcher's IsStatusNotifierHostRegistered instead; the `-` prefix
# lets EasyEffects still start after the timeout on tray-less setups —
# audio processing must not hinge on an icon.
services.easyeffects.enable = true;
systemd.user.services.easyeffects = {
Unit = {
After = [ "graphical-session.target" "tray.target" ];
Wants = [ "tray.target" ];
};
Service.ExecStartPre = "-${pkgs.writeShellScript "wait-for-tray-host" ''
timeout 30 ${pkgs.bash}/bin/sh -c '
until ${pkgs.systemd}/bin/busctl --user get-property \
org.kde.StatusNotifierWatcher /StatusNotifierWatcher \
org.kde.StatusNotifierWatcher IsStatusNotifierHostRegistered \
2>/dev/null | ${pkgs.gnugrep}/bin/grep -q true; do
sleep 0.5
done'
''}";
};
# Wifi from the bar: nm-applet lives in waybar's tray (SNI flag via
# preferStatusNotifierItems — without it there is no tray icon).
services.network-manager-applet.enable = true;
xsession.preferStatusNotifierItems = true;
# Standard XDG user directories (Downloads, Documents, Pictures, Music,
# Videos, Desktop, Public, Templates): written to user-dirs.dirs so file
# pickers/browsers resolve them, and created on activation so a fresh
# install lands with them present (not just on first app use). mkDefault
# so a downstream home.nix can flip it off or remap individual paths.
xdg.userDirs = {
enable = lib.mkDefault true;
createDirectories = lib.mkDefault true;
# Pinned: HM 26.05 flips the default to false (and warns on every eval
# for older stateVersions). Keep exporting XDG_*_DIR into the session —
# scripts and non-glib apps read the vars, and pinning gives every
# downstream the same behavior regardless of its stateVersion.
setSessionVariables = lib.mkDefault true;
};
home.stateVersion = lib.mkDefault "26.05";
home.packages = with pkgs; [
awww # wallpaper daemon with animated transitions (the swww fork)
libnotify
hyprpicker
# Lifecycle CLIs (pull/rebuild/home). HM profile usually precedes
# /run/current-system on PATH, so nomarchy-home can replace a broken
# system-generation nomarchy-pull without a full sys rebuild.
nomarchy-lifecycle
];
home.sessionVariables = {
TERMINAL = config.nomarchy.terminal;
NIXOS_OZONE_WL = "1"; # Electron/Chromium native Wayland
# Same gate as modules/nixos: CLI nix-shell/shell/run for unfree pkgs
# (system nixpkgs.config alone does not cover those entry points).
NIXPKGS_ALLOW_UNFREE = "1";
# Where the Nomarchy flake (and therefore theme-state.json) lives on
# disk. nomarchy-theme-sync writes its state here; rebuilds read from
# here. Clone/symlink your flake to this path.
NOMARCHY_PATH = "$HOME/.nomarchy";
};
# Classic nix-shell / nix-env read this; pairs with NIXPKGS_ALLOW_UNFREE
# above so "allow unfree" is the default desktop experience, not a
# per-command export the user has to remember.
xdg.configFile."nixpkgs/config.nix".text = ''
{ allowUnfree = true; }
'';
programs.home-manager.enable = true;
}