feat(home): mkDefault behaviour settings so downstream can plain-override

Nomarchy's Hyprland/Ghostty/Waybar settings were set at normal priority,
so a downstream `home.nix` setting any value Nomarchy already set threw a
"conflicting definition values" error — overriding required lib.mkForce,
contradicting the README's "mkDefault throughout" claim.

Now: behaviour/chrome leaves (input, misc, monitor, animations, dwindle,
gesture, decoration.blur sizing, ghostty padding/decoration, waybar
settings+style) are lib.mkDefault — a plain home.nix assignment wins.
Appearance values that flow from theme-state.json (gaps, colors,
rounding, opacity, fonts) stay at normal priority on purpose: change them
via nomarchy-theme-sync (their source of truth) or lib.mkForce to
hardcode. bind/exec-once lists stay normal priority so additions
concatenate rather than replace.

Verified: behaviour/ghostty plain overrides build; theme values still
conflict (steering to the CLI); default rendered config is byte-identical.

New docs/OVERRIDES.md with the appearance→CLI / behaviour→home.nix /
component→toggle model and worked examples; linked from the README.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Bernardo Magri
2026-06-13 14:05:59 +01:00
parent bd42462291
commit d06373b155
5 changed files with 202 additions and 30 deletions

View File

@@ -30,12 +30,14 @@ in
palette = lib.imap0 (i: color: "${toString i}=${color}") t.ansi;
# ── Chrome ────────────────────────────────────────────────────
# background-opacity is theme-driven (normal priority — use the
# CLI); the rest are mkDefault so a plain home.nix value wins.
background-opacity = t.ui.terminalOpacity;
window-padding-x = 12;
window-padding-y = 12;
window-decoration = false;
gtk-single-instance = true;
confirm-close-surface = false;
window-padding-x = lib.mkDefault 12;
window-padding-y = lib.mkDefault 12;
window-decoration = lib.mkDefault false;
gtk-single-instance = lib.mkDefault true;
confirm-close-surface = lib.mkDefault false;
};
};
}

View File

@@ -35,8 +35,13 @@ in
"$mod" = "SUPER";
"$terminal" = config.nomarchy.terminal;
monitor = [ ",preferred,auto,1" ];
# mkDefault so a downstream `monitor = [...]` replaces it with a
# plain assignment (the live ISO uses mkForce for the same reason).
monitor = lib.mkDefault [ ",preferred,auto,1" ];
# exec-once is a list at normal priority, so downstream additions
# CONCATENATE (your autostart runs alongside ours) rather than
# replace. Same for the bind* lists below.
exec-once = [
# nixpkgs' swww is awww (renamed fork); the binary is awww-daemon.
"awww-daemon"
@@ -46,14 +51,19 @@ in
];
# ── Theme-driven look ──────────────────────────────────────────
# These flow from theme-state.json and stay at NORMAL priority:
# change them with `nomarchy-theme-sync set ui.<key>` (the intended
# path), or lib.mkForce in home.nix to hardcode against the theme.
# The non-theme knobs around them are lib.mkDefault — override
# those with a plain home.nix assignment. See docs/OVERRIDES.md.
general = {
gaps_in = t.ui.gapsIn;
gaps_out = t.ui.gapsOut;
border_size = t.ui.borderSize;
"col.active_border" = "${rgb c.accent} ${rgb c.accentAlt} 45deg";
"col.inactive_border" = rgb c.overlay;
layout = "dwindle";
resize_on_border = true;
layout = lib.mkDefault "dwindle";
resize_on_border = lib.mkDefault true;
};
decoration = {
@@ -62,25 +72,26 @@ in
inactive_opacity = t.ui.inactiveOpacity;
blur = {
enabled = t.ui.blur;
size = 8;
passes = 2;
popups = true;
size = lib.mkDefault 8;
passes = lib.mkDefault 2;
popups = lib.mkDefault true;
};
shadow = {
enabled = t.ui.shadow;
range = 20;
render_power = 3;
range = lib.mkDefault 20;
render_power = lib.mkDefault 3;
color = rgba c.mantle "aa";
};
};
# ── Behaviour (mkDefault → plain home.nix assignment overrides) ──
animations = {
enabled = true;
bezier = [
enabled = lib.mkDefault true;
bezier = lib.mkDefault [
"smooth, 0.25, 0.1, 0.25, 1.0"
"snappy, 0.6, 0.0, 0.1, 1.0"
];
animation = [
animation = lib.mkDefault [
"windows, 1, 4, snappy, popin 85%"
"border, 1, 8, smooth"
"fade, 1, 5, smooth"
@@ -88,29 +99,30 @@ in
];
};
# ── Behaviour ──────────────────────────────────────────────────
input = {
# kb_layout/variant come from nomarchy.keyboard.* — set that
# option (the installer writes it; it also drives tty/LUKS).
kb_layout = config.nomarchy.keyboard.layout;
kb_variant = config.nomarchy.keyboard.variant;
follow_mouse = 1;
touchpad.natural_scroll = true;
follow_mouse = lib.mkDefault 1;
touchpad.natural_scroll = lib.mkDefault true;
};
# dwindle:pseudotile was removed in Hyprland 0.55 (the `pseudo`
# dispatcher still exists); setting it aborts config parsing.
dwindle.preserve_split = true;
dwindle.preserve_split = lib.mkDefault true;
# Hyprland 0.51+ replaced gestures:workspace_swipe with the
# gesture keyword — without this, touchpads have NO gestures.
gesture = [
gesture = lib.mkDefault [
"3, horizontal, workspace"
"4, pinch, fullscreen"
];
misc = {
disable_hyprland_logo = true;
disable_splash_rendering = true;
force_default_wallpaper = 0;
disable_hyprland_logo = lib.mkDefault true;
disable_splash_rendering = lib.mkDefault true;
force_default_wallpaper = lib.mkDefault 0;
};
bind = [

View File

@@ -145,14 +145,21 @@ in
enable = true;
systemd.enable = true; # started/stopped with graphical-session.target
settings.mainBar =
# mkDefault so downstream can replace the whole bar config/style with
# a plain home.nix assignment. For per-theme identity, prefer the
# whole-swap assets (themes/<slug>/waybar.{jsonc,css}); for one-off
# tweaks of the generated bar, lib.mkForce a sub-key. See
# docs/OVERRIDES.md.
settings.mainBar = lib.mkDefault (
if hasConfigOverride
then builtins.fromJSON (builtins.readFile configOverride)
else generatedSettings;
else generatedSettings
);
style =
style = lib.mkDefault (
if hasStyleOverride
then builtins.readFile styleOverride
else generatedStyle;
else generatedStyle
);
};
}