213 lines
8.4 KiB
Nix
213 lines
8.4 KiB
Nix
{ self, inputs, ... }:
|
|
let
|
|
# Keep defaults in this let — a bare niri-settings.nix next to this file would get picked up by import-tree.
|
|
niriBaseSettings =
|
|
pkgs:
|
|
{
|
|
input.keyboard = {
|
|
xkb.layout = "ca";
|
|
xkb.variant = "";
|
|
};
|
|
input."focus-follows-mouse" = _: {
|
|
props."max-scroll-amount" = "45%";
|
|
content = { };
|
|
};
|
|
input."warp-mouse-to-focus" = _: { };
|
|
layout.gaps = 5;
|
|
|
|
window-rules = [
|
|
{
|
|
matches = [
|
|
{
|
|
app-id = "^$";
|
|
title = "^$";
|
|
}
|
|
];
|
|
open-floating = true;
|
|
open-focused = false;
|
|
}
|
|
];
|
|
#TODO[epic=Binds] Go over binds again
|
|
binds = {
|
|
"Mod+T"."spawn-sh" = "${pkgs.lib.getExe pkgs.kitty} -e fish"; #TODO[epic=Binds] This should only be set if having kitty
|
|
"Mod+Control+T"."spawn-sh" = "konsole"; #TODO[epic=Binds] This should only be set if having konsole
|
|
"Mod+D"."spawn-sh" = "rofi -show drun"; #TODO[epic=Binds] This should only be set if having rofi
|
|
"Mod+Space"."spawn-sh" = "dms ipc call spotlight toggle"; #TODO[epic=Binds] This should only be set if having dms
|
|
"Mod+E"."spawn-sh" = "dolphin"; #TODO[epic=Binds] This should only be set if having dolphin
|
|
"Mod+Control+O"."spawn-sh" = "rofi -show window"; #TODO[epic=Binds] This should only be set if having rofi
|
|
"Mod+V"."spawn-sh" = "dms ipc call clipboard toggle"; #TODO[epic=Binds] This should only be set if having dms
|
|
"Mod+N"."spawn-sh" = "dms ipc call notepad toggle"; #TODO[epic=Binds] This should only be set if having dms
|
|
"Mod+Shift+N"."spawn-sh" = "dms ipc call notifications toggle"; #TODO[epic=Binds] This should only be set if having dms
|
|
"Mod+M"."spawn-sh" = "dms ipc call processlist toggle"; #TODO[epic=Binds] This should only be set if having dms
|
|
"Mod+L"."spawn-sh" = "dms ipc call lock lock"; #TODO[epic=Binds] This should only be set if having dms
|
|
|
|
"Mod+Q"."close-window" = _: { };
|
|
"Mod+F"."maximize-column" = _: { };
|
|
"Mod+Shift+F"."fullscreen-window" = _: { };
|
|
"Mod+O"."toggle-overview" = _: { };
|
|
"Mod+Shift+NumberSign"."show-hotkey-overlay" = _: { };
|
|
"Mod+Shift+E".quit = _: { };
|
|
|
|
"Mod+Left"."focus-column-or-monitor-left" = _: { };
|
|
"Mod+Down"."focus-window-or-monitor-down" = _: { };
|
|
"Mod+Up"."focus-window-or-monitor-up" = _: { };
|
|
"Mod+Right"."focus-column-or-monitor-right" = _: { };
|
|
|
|
"Mod+Shift+WheelScrollDown"."focus-workspace-down" = _: { };
|
|
"Mod+Shift+WheelScrollUp"."focus-workspace-up" = _: { };
|
|
|
|
"Mod+WheelScrollDown"."focus-column-or-monitor-right" = _: { };
|
|
"Mod+WheelScrollUp"."focus-column-or-monitor-left" = _: { };
|
|
|
|
"Mod+Shift+Left"."move-column-left-or-to-monitor-left" = _: { };
|
|
"Mod+Shift+Down"."move-window-down" = _: { };
|
|
"Mod+Shift+Up"."move-window-up" = _: { };
|
|
"Mod+Shift+Right"."move-column-right-or-to-monitor-right" = _: { };
|
|
"Mod+Page_Up"."focus-workspace-up" = _: { };
|
|
"Mod+Page_Down"."focus-workspace-down" = _: { };
|
|
"Mod+Shift+Page_Up"."move-column-to-workspace-up" = _: { };
|
|
"Mod+Shift+Page_Down"."move-column-to-workspace-down" = _: { };
|
|
"Mod+R"."switch-preset-column-width" = _: { };
|
|
"Mod+BracketLeft"."consume-or-expel-window-left" = _: { };
|
|
"Mod+BracketRight"."consume-or-expel-window-right" = _: { };
|
|
"Mod+Comma"."consume-window-into-column" = _: { };
|
|
"Mod+Period"."expel-window-from-column" = _: { };
|
|
"Mod+Alt+Space"."toggle-window-floating" = _: { };
|
|
#"Mod+Shift+V"."switch-focus-between-floating-and-tiling" = _: { }; #TODO[epic=Binds] Find free bind that is not in the way and not overcomplicated to remember
|
|
|
|
"Mod+1"."focus-workspace" = 1;
|
|
"Mod+2"."focus-workspace" = 2;
|
|
"Mod+3"."focus-workspace" = 3;
|
|
"Mod+4"."focus-workspace" = 4;
|
|
"Mod+5"."focus-workspace" = 5;
|
|
"Mod+6"."focus-workspace" = 6;
|
|
"Mod+7"."focus-workspace" = 7;
|
|
"Mod+8"."focus-workspace" = 8;
|
|
"Mod+9"."focus-workspace" = 9;
|
|
"Mod+Ctrl+1"."move-column-to-workspace" = 1;
|
|
"Mod+Ctrl+2"."move-column-to-workspace" = 2;
|
|
"Mod+Ctrl+3"."move-column-to-workspace" = 3;
|
|
"Mod+Ctrl+4"."move-column-to-workspace" = 4;
|
|
"Mod+Ctrl+5"."move-column-to-workspace" = 5;
|
|
"Mod+Ctrl+6"."move-column-to-workspace" = 6;
|
|
"Mod+Ctrl+7"."move-column-to-workspace" = 7;
|
|
"Mod+Ctrl+8"."move-column-to-workspace" = 8;
|
|
"Mod+Ctrl+9"."move-column-to-workspace" = 9;
|
|
|
|
"XF86AudioRaiseVolume".spawn = [
|
|
"wpctl"
|
|
"set-volume"
|
|
"@DEFAULT_AUDIO_SINK@"
|
|
"0.05+"
|
|
];
|
|
"XF86AudioLowerVolume".spawn = [
|
|
"wpctl"
|
|
"set-volume"
|
|
"@DEFAULT_AUDIO_SINK@"
|
|
"0.05-"
|
|
];
|
|
"XF86AudioMute".spawn = [
|
|
"wpctl"
|
|
"set-mute"
|
|
"@DEFAULT_AUDIO_SINK@"
|
|
"toggle"
|
|
];
|
|
|
|
# Backlight: relies on `pkgs.brightnessctl` being on PATH (provided by `desktopGui` when
|
|
# any GUI session is enabled) and the user being in the `video` group (catalog default).
|
|
"XF86MonBrightnessUp".spawn = [ "brightnessctl" "set" "+5%" ];
|
|
"XF86MonBrightnessDown".spawn = [ "brightnessctl" "set" "5%-" ];
|
|
|
|
Print.screenshot = _: { };
|
|
"Ctrl+Print"."screenshot-screen" = _: { };
|
|
"Alt+Print"."screenshot-window" = _: { };
|
|
};
|
|
};
|
|
|
|
mergeNiriSettings =
|
|
pkgs: niriCfg:
|
|
let
|
|
lib = pkgs.lib;
|
|
pi5 = self.lib.pi5NiriKdl;
|
|
rpi5Extra = lib.optionalString (niriCfg.raspberryPi5DrmWorkaround or false) pi5.drmExtraConfig;
|
|
userExtra = niriCfg.extraSettings or { };
|
|
extraConfigMerged = rpi5Extra + (userExtra.extraConfig or "");
|
|
in
|
|
lib.recursiveUpdate (niriBaseSettings pkgs) (
|
|
userExtra
|
|
// lib.optionalAttrs (rpi5Extra != "" || (userExtra.extraConfig or "") != "") {
|
|
extraConfig = extraConfigMerged;
|
|
}
|
|
);
|
|
in
|
|
{
|
|
flake.homeManagerModules.desktopNiri =
|
|
{ lib, pkgs, osConfig ? { }, ... }:
|
|
let
|
|
niriOs = osConfig.chiasson.desktop.niri or { };
|
|
niriEnabled = osConfig.chiasson.desktop.niri.enable or false;
|
|
mergedSettings = mergeNiriSettings pkgs niriOs;
|
|
niriConfigPkg = inputs.wrapper-modules.wrappers.niri.wrap {
|
|
inherit pkgs;
|
|
settings = mergedSettings;
|
|
};
|
|
in
|
|
{
|
|
config = lib.mkIf niriEnabled {
|
|
xdg.configFile."niri/config.kdl".source = "${niriConfigPkg}/niri-config.kdl";
|
|
};
|
|
};
|
|
|
|
flake.nixosModules.desktopNiri =
|
|
{ config, options, lib, pkgs, self, ... }:
|
|
let
|
|
cfg = config.chiasson.desktop;
|
|
hmAvailable = lib.hasAttrByPath [ "home-manager" "sharedModules" ] options;
|
|
in
|
|
{
|
|
options.chiasson.desktop.niri = {
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Niri compositor session + NixOS packages.";
|
|
};
|
|
|
|
raspberryPi5DrmWorkaround = lib.mkEnableOption ''
|
|
Pi 5 + RP1 DSI: Niri DRM debug rules (renderD128, ignore card1/2) + matching DankGreeter niri config.
|
|
Opt-in only — HDMI-only / other Pi setups do not need this.
|
|
'';
|
|
|
|
extraSettings = lib.mkOption {
|
|
type = lib.types.attrs;
|
|
default = { };
|
|
description = ''
|
|
Merged into shared defaults → `config.kdl` via wrapper-modules. Put raw KDL in `extraConfig`.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = lib.mkMerge [
|
|
{
|
|
assertions = [
|
|
{
|
|
assertion = !cfg.niri.raspberryPi5DrmWorkaround || cfg.niri.enable;
|
|
message = "chiasson.desktop.niri.raspberryPi5DrmWorkaround requires chiasson.desktop.niri.enable.";
|
|
}
|
|
];
|
|
}
|
|
(lib.mkIf cfg.niri.enable {
|
|
programs.niri.enable = true;
|
|
programs.niri.package = pkgs.niri;
|
|
programs.xwayland.enable = true;
|
|
xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gnome ];
|
|
# Niri resolves `xwayland-satellite` from PATH to provide XWayland + `$DISPLAY` for X11
|
|
# clients (Steam, etc.). See https://github.com/YaLTeR/niri/issues/452
|
|
environment.systemPackages = [ pkgs.xwayland-satellite ];
|
|
})
|
|
(lib.mkIf (cfg.niri.enable && hmAvailable) {
|
|
"home-manager".sharedModules = [ self.homeManagerModules.desktopNiri ];
|
|
})
|
|
];
|
|
};
|
|
}
|