nix/graphical/desktop/wm.nix
2026-03-09 14:06:12 +11:00

111 lines
2.8 KiB
Nix

{
inputs,
getFlakePkg',
lib,
pkgs,
config,
...
}:
let
inherit (config) rice;
niri = getFlakePkg' inputs.niri "niri-unstable";
xwayland-satellite = getFlakePkg' inputs.niri "xwayland-satellite-unstable";
niri-session-direct = pkgs.writeShellScript "niri-session-direct" ''
systemctl --user import-environment
dbus-update-activation-environment --all
systemctl --user start niri-session-bridge.service &
exec ${lib.getExe niri} --session
'';
in
{
imports = [
inputs.niri-tag.nixosModules.niri-tag
inputs.niri-s76.nixosModules.default
];
user.desktops.niri = {
enable = true;
config =
let
template = builtins.readFile ./niri.kdl;
baseConfig =
with rice;
lib.replaceStrings
[
"%CURSOR%"
"%ROUNDING%"
"%GAPS%"
"%BORDER%"
"%ACTIVE%"
"%INACTIVE%"
"%SATELLITE%"
]
[
cursor.name
(toString borders.rounding)
(toString borders.gaps)
(toString borders.thickness)
palette.shortHex.bright.yellow
palette.shortHex.normal.white
(lib.getExe xwayland-satellite)
]
template;
in
baseConfig;
};
environment.systemPackages = [
niri
xwayland-satellite
];
environment.etc."greetd/wayland-sessions/niri.desktop".text = ''
[Desktop Entry]
Name=Niri
Comment=A scrollable-tiling Wayland compositor
Exec=${niri-session-direct}
Type=Application
DesktopNames=niri
'';
programs.niri = {
enable = true;
package = niri;
};
services.niri-tag = {
enable = true;
prepopulate = 10;
strict = true;
scratchpads = {
"chrome-listen.lobotomise.me__-Default" = 99;
"Bitwarden" = 101;
};
};
services.niri-s76-bridge.enable = true;
# niri runs directly from greetd (not as a user service),
# so that it stays inside the logind session scope for proper polkit/dbus access.
systemd.user.services.niri.wantedBy = lib.mkForce [ ];
systemd.user.services.niri.enable = lib.mkForce false;
# bridge service to activate graphical-session.target for the direct-launched niri.
# waits for niri IPC readiness before pulling in the target.
systemd.user.services.niri-session-bridge = {
unitConfig = {
Description = "Activate graphical-session.target for direct-launched niri";
BindsTo = [ "graphical-session.target" ];
Before = [ "graphical-session.target" ];
Wants = [ "graphical-session-pre.target" ];
After = [ "graphical-session-pre.target" ];
};
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStart = "${lib.getExe niri} msg version";
};
};
}