Add Hyprland and Niri configuration files
- Introduced `binds.nix` for Hyprland, defining keybindings for various applications and workspace management. - Added `base-settings.nix` and `window-rules.nix` for Niri, establishing keyboard input settings and window management rules. - Updated `default.nix` for both Hyprland and Niri to import new configuration files, enhancing modularity and maintainability.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
{ self, ... }: {
|
||||
flake.lib.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;
|
||||
prefer-no-csd = true;
|
||||
window-rules = self.lib.niriWindowRules;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
{ ... }: {
|
||||
flake.lib.niriBinds =
|
||||
{ pkgs, dmsEnabled ? false }:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
in
|
||||
{
|
||||
"Mod+T"."spawn-sh" = lib.getExe pkgs.kitty;
|
||||
"Mod+Control+T"."spawn-sh" = "konsole";
|
||||
"Mod+D"."spawn-sh" = "rofi -show drun";
|
||||
"Mod+Control+O"."spawn-sh" = "rofi -show window";
|
||||
"Mod+E"."spawn-sh" = "nemo";
|
||||
}
|
||||
// lib.optionalAttrs dmsEnabled {
|
||||
"Mod+Space"."spawn-sh" = "dms ipc call spotlight toggle";
|
||||
"Mod+V"."spawn-sh" = "dms ipc call clipboard toggle";
|
||||
"Mod+N"."spawn-sh" = "dms ipc call notepad toggle";
|
||||
"Mod+Shift+N"."spawn-sh" = "dms ipc call notifications toggle";
|
||||
"Mod+M"."spawn-sh" = "dms ipc call processlist toggle";
|
||||
"Mod+B"."spawn-sh" = ''dms ipc call bar toggle name "Main Bar"; dms ipc call bar toggle name "Bar 2"'';
|
||||
"Mod+Shift+B"."spawn-sh" = ''dms ipc call bar toggle name "Bar 2"'';
|
||||
"Mod+A"."spawn-sh" = "dms ipc call ephemera toggle";
|
||||
"Mod+numbersign"."spawn-sh" = "dms ipc call wallpaperCarousel toggle";
|
||||
"Mod+L"."spawn-sh" = "dms ipc call lock lock";
|
||||
}
|
||||
// {
|
||||
"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+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"
|
||||
];
|
||||
"XF86MonBrightnessUp".spawn = [ "brightnessctl" "set" "+5%" ];
|
||||
"XF86MonBrightnessDown".spawn = [ "brightnessctl" "set" "5%-" ];
|
||||
|
||||
Print.screenshot = _: { };
|
||||
"Ctrl+Print"."screenshot-screen" = _: { };
|
||||
"Alt+Print"."screenshot-window" = _: { };
|
||||
};
|
||||
}
|
||||
@@ -1,192 +1,10 @@
|
||||
{ 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;
|
||||
prefer-no-csd = true;
|
||||
{ self, inputs, ... }: {
|
||||
imports = [
|
||||
./window-rules.nix
|
||||
./base-settings.nix
|
||||
./binds.nix
|
||||
];
|
||||
|
||||
window-rules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
app-id = "^$";
|
||||
title = "^$";
|
||||
}
|
||||
];
|
||||
open-floating = true;
|
||||
open-focused = false;
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ title = "^(Picture-in-Picture|Picture in picture)$"; }
|
||||
];
|
||||
open-floating = true;
|
||||
open-focused = false;
|
||||
default-column-width = { fixed = 640; };
|
||||
default-window-height = { fixed = 360; };
|
||||
default-floating-position = _: {
|
||||
props = {
|
||||
x = 32;
|
||||
y = 32;
|
||||
relative-to = "bottom-right";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ app-id = "^Minecraft\\*"; }
|
||||
{ app-id = "^Minecraft$"; }
|
||||
];
|
||||
tiled-state = true;
|
||||
}
|
||||
];
|
||||
#TODO[epic=Binds] Go over binds again
|
||||
binds = {
|
||||
"Mod+T"."spawn-sh" = pkgs.lib.getExe pkgs.kitty; # shell from kitty HM config
|
||||
"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" = "nemo"; #TODO[epic=Binds] This should only be set if having nemo
|
||||
"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+B"."spawn-sh" = "dms ipc call bar toggle name \"Main Bar\"; dms ipc call bar toggle name \"Bar 2\""; #TODO[epic=Binds] This should only be set if having dms
|
||||
"Mod+Shift+B"."spawn-sh" = "dms ipc call bar toggle name \"Bar 2\""; #TODO[epic=Binds] This should only be set if having dms
|
||||
"Mod+A"."spawn-sh" = "dms ipc call ephemera toggle"; #TODO[epic=Binds] This should only be set if having dms
|
||||
"Mod+numbersign"."spawn-sh" = "dms ipc call wallpaperCarousel toggle"; # Mod+# — 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" = _: { };
|
||||
};
|
||||
};
|
||||
|
||||
keyringNiriStartupKdl = ''
|
||||
spawn-at-startup "dbus-update-activation-environment" "--systemd" "--all"
|
||||
'';
|
||||
|
||||
mergeNiriSettings =
|
||||
pkgs: niriCfg: keyringEnable:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
pi5 = self.lib.pi5NiriKdl;
|
||||
rpi5Extra = lib.optionalString (niriCfg.raspberryPi5DrmWorkaround or false) pi5.drmExtraConfig;
|
||||
base = niriBaseSettings pkgs;
|
||||
userExtra = niriCfg.extraSettings or { };
|
||||
keyringExtra = lib.optionalString keyringEnable keyringNiriStartupKdl;
|
||||
extraConfigMerged = keyringExtra + rpi5Extra + (userExtra.extraConfig or "");
|
||||
windowRules = (base.window-rules or [ ]) ++ (userExtra.window-rules or [ ]);
|
||||
userExtraNoSpecial = lib.removeAttrs userExtra [ "window-rules" "extraConfig" "binds" ];
|
||||
mergedBinds =
|
||||
(base.binds or { })
|
||||
// (userExtra.binds or { })
|
||||
// (niriCfg.extraBinds or { });
|
||||
in
|
||||
lib.recursiveUpdate base (
|
||||
userExtraNoSpecial
|
||||
// {
|
||||
binds = mergedBinds;
|
||||
}
|
||||
// lib.optionalAttrs (windowRules != [ ]) {
|
||||
window-rules = windowRules;
|
||||
}
|
||||
// lib.optionalAttrs (extraConfigMerged != "") {
|
||||
extraConfig = extraConfigMerged;
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
flake.homeManagerModules.desktopNiri =
|
||||
{ config, lib, pkgs, osConfig ? { }, ... }:
|
||||
let
|
||||
@@ -195,21 +13,58 @@ in
|
||||
niriEnabled = osConfig.chiasson.desktop.niri.enable or false;
|
||||
keyringEnabled = osConfig.chiasson.desktop.keyring.enable or false;
|
||||
dmsEnabled = (osConfig.chiasson.desktop.shell or null) == "dms";
|
||||
|
||||
keyringNiriStartupKdl = ''
|
||||
spawn-at-startup "dbus-update-activation-environment" "--systemd" "--all"
|
||||
'';
|
||||
|
||||
niriBaseSettings =
|
||||
pkgs: dmsEnabled:
|
||||
self.lib.niriBaseSettings pkgs // {
|
||||
binds = self.lib.niriBinds { inherit pkgs dmsEnabled; };
|
||||
};
|
||||
|
||||
mergeNiriSettings =
|
||||
pkgs: niriCfg: keyringEnable: dmsEnabled:
|
||||
let
|
||||
lib = pkgs.lib;
|
||||
pi5 = self.lib.pi5NiriKdl;
|
||||
rpi5Extra = lib.optionalString (niriCfg.raspberryPi5DrmWorkaround or false) pi5.drmExtraConfig;
|
||||
base = niriBaseSettings pkgs dmsEnabled;
|
||||
userExtra = niriCfg.extraSettings or { };
|
||||
keyringExtra = lib.optionalString keyringEnable keyringNiriStartupKdl;
|
||||
extraConfigMerged = keyringExtra + rpi5Extra + (userExtra.extraConfig or "");
|
||||
windowRules = (base.window-rules or [ ]) ++ (userExtra.window-rules or [ ]);
|
||||
userExtraNoSpecial = lib.removeAttrs userExtra [ "window-rules" "extraConfig" "binds" ];
|
||||
mergedBinds =
|
||||
(base.binds or { })
|
||||
// (userExtra.binds or { })
|
||||
// (niriCfg.extraBinds or { });
|
||||
in
|
||||
lib.recursiveUpdate base (
|
||||
userExtraNoSpecial
|
||||
// {
|
||||
binds = mergedBinds;
|
||||
}
|
||||
// lib.optionalAttrs (windowRules != [ ]) {
|
||||
window-rules = windowRules;
|
||||
}
|
||||
// lib.optionalAttrs (extraConfigMerged != "") {
|
||||
extraConfig = extraConfigMerged;
|
||||
}
|
||||
);
|
||||
|
||||
dmsWindowRulesPath = "${home}/.config/niri/dms/windowrules.kdl";
|
||||
# wrapper-modules emits quoted KDL (`"include" "…"`) which DMS's parser ignores.
|
||||
# config.kdl is a store symlink, so a relative include would not resolve to the real
|
||||
# ~/.config/niri/dms/windowrules.kdl that DMS writes at runtime.
|
||||
dmsWindowRulesInclude = lib.optionalString dmsEnabled ''
|
||||
include "${dmsWindowRulesPath}"
|
||||
'';
|
||||
baseMergedSettings = mergeNiriSettings pkgs niriOs keyringEnabled;
|
||||
baseMergedSettings = mergeNiriSettings pkgs niriOs keyringEnabled dmsEnabled;
|
||||
mergedSettings = lib.recursiveUpdate baseMergedSettings {
|
||||
extraConfig = dmsWindowRulesInclude + (baseMergedSettings.extraConfig or "");
|
||||
};
|
||||
niriConfigPkg = inputs.wrapper-modules.wrappers.niri.wrap {
|
||||
inherit pkgs;
|
||||
settings = mergedSettings;
|
||||
# User-owned rules path is not available during the Nix build.
|
||||
disableConfigValidation = dmsEnabled;
|
||||
};
|
||||
in
|
||||
@@ -219,7 +74,6 @@ in
|
||||
xdg.configFile."niri/config.kdl".source = "${niriConfigPkg}/niri-config.kdl";
|
||||
}
|
||||
(lib.mkIf dmsEnabled {
|
||||
# Seed empty rules file so niri can load the include before DMS first deploy.
|
||||
home.activation.dmsNiriWindowRulesSeed = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
rulesDir="$HOME/.config/niri/dms"
|
||||
rulesFile="$rulesDir/windowrules.kdl"
|
||||
@@ -283,8 +137,6 @@ in
|
||||
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) {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
{ ... }: {
|
||||
flake.lib.niriWindowRules = [
|
||||
{
|
||||
matches = [
|
||||
{
|
||||
app-id = "^$";
|
||||
title = "^$";
|
||||
}
|
||||
];
|
||||
open-floating = true;
|
||||
open-focused = false;
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ title = "^(Picture-in-Picture|Picture in picture)$"; }
|
||||
];
|
||||
open-floating = true;
|
||||
open-focused = false;
|
||||
default-column-width = { fixed = 640; };
|
||||
default-window-height = { fixed = 360; };
|
||||
default-floating-position = _: {
|
||||
props = {
|
||||
x = 32;
|
||||
y = 32;
|
||||
relative-to = "bottom-right";
|
||||
};
|
||||
};
|
||||
}
|
||||
{
|
||||
matches = [
|
||||
{ app-id = "^Minecraft\\*"; }
|
||||
{ app-id = "^Minecraft$"; }
|
||||
];
|
||||
tiled-state = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user