Commit cfd4a1e

HPCesia <me@hpcesia.com>
2026-06-19 20:02:36
Add Niri Wayland compositor
1 parent 9dc71b7
modules/desktop/env/wm/niri/config/config.kdl
@@ -0,0 +1,11 @@
+include "nix/pre.kdl"
+
+include "inputs.kdl"
+include "keybinds.kdl"
+include "layout.kdl"
+include "misc.kdl"
+include "window-rules.kdl"
+include "workspaces.kdl"
+
+include "nix/post.kdl"
+
modules/desktop/env/wm/niri/config/inputs.kdl
@@ -0,0 +1,8 @@
+input {
+  touchpad {
+    tap
+    natural-scroll
+    dwt
+    drag true
+  }
+}
modules/desktop/env/wm/niri/config/keybinds.kdl
@@ -0,0 +1,129 @@
+binds {
+  // === Common Binds ===
+  Mod+Shift+Slash         { show-hotkey-overlay; }
+  Mod+Escape repeat=false { toggle-overview; }
+
+  Mod+Shift+E     { quit; }
+  Ctrl+Alt+Delete { quit; }
+
+  Print       { screenshot; }
+  Mod+Shift+S { screenshot; }
+  Ctrl+Print  { screenshot-screen; }
+  Alt+Print   { screenshot-window; }
+
+  // === Window and Column Actions ===
+  Mod+Q repeat=false { close-window; }
+
+  Mod+H     { focus-column-left; }
+  Mod+J     { focus-window-down; }
+  Mod+K     { focus-window-up; }
+  Mod+L     { focus-column-right; }
+  Mod+Left  { focus-column-left; }
+  Mod+Down  { focus-window-down; }
+  Mod+Up    { focus-window-up; }
+  Mod+Right { focus-column-right; }
+  Mod+Home  { focus-column-first; }
+  Mod+End   { focus-column-last; }
+  Mod+WheelScrollRight      { focus-column-right; }
+  Mod+WheelScrollLeft       { focus-column-left; }
+  Mod+Shift+WheelScrollDown { focus-column-right; }
+  Mod+Shift+WheelScrollUp   { focus-column-left; }
+
+  Mod+Ctrl+H     { move-column-left; }
+  Mod+Ctrl+J     { move-window-down; }
+  Mod+Ctrl+K     { move-window-up; }
+  Mod+Ctrl+L     { move-column-right; }
+  Mod+Ctrl+Left  { move-column-left; }
+  Mod+Ctrl+Down  { move-window-down; }
+  Mod+Ctrl+Up    { move-window-up; }
+  Mod+Ctrl+Right { move-column-right; }
+  Mod+Ctrl+Home  { move-column-to-first; }
+  Mod+Ctrl+End   { move-column-to-last; }
+  Mod+Ctrl+WheelScrollRight      { move-column-right; }
+  Mod+Ctrl+WheelScrollLeft       { move-column-left; }
+  Mod+Ctrl+Shift+WheelScrollDown { move-column-right; }
+  Mod+Ctrl+Shift+WheelScrollUp   { move-column-left; }
+
+  Mod+Minus       { set-column-width "-10%"; }
+  Mod+Equal       { set-column-width "+10%"; }
+  Mod+Shift+Minus { set-window-height "-10%"; }
+  Mod+Shift+Equal { set-window-height "+10%"; }
+
+  Mod+R       { switch-preset-column-width; }
+  Mod+Shift+R { switch-preset-window-height; }
+  Mod+Ctrl+R  { reset-window-height; }
+
+  Mod+F            { maximize-column; }
+  Mod+Shift+F      { fullscreen-window; }
+  Mod+Ctrl+F       { maximize-window-to-edges; }
+  Mod+Ctrl+Shift+F { toggle-windowed-fullscreen; }
+
+  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+Ctrl+W { toggle-window-floating; }
+  Mod+W      { switch-focus-between-floating-and-tiling; }
+
+  Mod+T { toggle-column-tabbed-display; }
+
+  // === Workspace Actions ===
+  Mod+Page_Down { focus-workspace-down; }
+  Mod+Page_Up   { focus-workspace-up; }
+  Mod+D { focus-workspace-down; } // Default is `U`, use Helix binding instead.
+  Mod+U { focus-workspace-up; }   // Default is `I`, use Helix binding instead.
+  Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
+  Mod+WheelScrollUp   cooldown-ms=150 { focus-workspace-up; }
+
+  Mod+Ctrl+Page_Down { move-column-to-workspace-down; }
+  Mod+Ctrl+Page_Up   { move-column-to-workspace-up; }
+  Mod+Ctrl+D { move-column-to-workspace-down; }
+  Mod+Ctrl+U { move-column-to-workspace-up; }
+  Mod+Ctrl+WheelScrollDown cooldown-ms=150 { move-column-to-workspace-down; }
+  Mod+Ctrl+WheelScrollUp   cooldown-ms=150 { move-column-to-workspace-up; }
+
+  Mod+Shift+Page_Down { move-workspace-down; }
+  Mod+Shift+Page_Up   { move-workspace-up; }
+  Mod+Shift+D { move-workspace-down; }
+  Mod+Shift+U { move-workspace-up; }
+
+  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; }
+
+  // === Monitor Actions ===
+  Mod+Shift+H     { focus-monitor-left; }
+  Mod+Shift+J     { focus-monitor-down; }
+  Mod+Shift+K     { focus-monitor-up; }
+  Mod+Shift+L     { focus-monitor-right; }
+  Mod+Shift+Left  { focus-monitor-left; }
+  Mod+Shift+Down  { focus-monitor-down; }
+  Mod+Shift+Up    { focus-monitor-up; }
+  Mod+Shift+Right { focus-monitor-right; }
+
+  Mod+Ctrl+Shift+H     { move-column-to-monitor-left; }
+  Mod+Ctrl+Shift+J     { move-column-to-monitor-down; }
+  Mod+Ctrl+Shift+K     { move-column-to-monitor-up; }
+  Mod+Ctrl+Shift+L     { move-column-to-monitor-right; }
+  Mod+Ctrl+Shift+Left  { move-column-to-monitor-left; }
+  Mod+Ctrl+Shift+Down  { move-column-to-monitor-down; }
+  Mod+Ctrl+Shift+Up    { move-column-to-monitor-up; }
+  Mod+Ctrl+Shift+Right { move-column-to-monitor-right; }
+}
modules/desktop/env/wm/niri/config/layout.kdl
@@ -0,0 +1,20 @@
+layout {
+  gaps 10
+  always-center-single-column
+  background-color "transparent"
+
+  focus-ring {
+    on
+    width 2
+  }
+  border {
+    off
+  }
+
+  preset-column-widths {
+    proportion 0.33333
+    proportion 0.5
+    proportion 0.75
+  }
+  default-column-width { proportion 0.5; }
+}
modules/desktop/env/wm/niri/config/misc.kdl
@@ -0,0 +1,27 @@
+hotkey-overlay {
+  skip-at-startup
+  hide-not-bound
+}
+
+prefer-no-csd
+
+recent-windows {
+  debounce-ms 750
+  open-delay-ms 150
+  highlight {
+    active-color "#cba6f7"
+    urgent-color "#f2cdcd"
+    padding 30
+    corner-radius 15.000000
+  }
+  previews {
+    max-height 480
+    max-scale 0.500000
+  }
+  binds {
+    Alt+Tab { next-window; }
+    Alt+Shift+Tab { previous-window; }
+    Mod+Tab { next-window; }
+    Mod+Shift+Tab { previous-window; }
+  }
+}
modules/desktop/env/wm/niri/config/window-rules.kdl
@@ -0,0 +1,111 @@
+// rules for all windows
+window-rule {
+  draw-border-with-background false
+  geometry-corner-radius 15.000000 15.000000 15.000000 15.000000
+  clip-to-geometry true
+  tiled-state true
+
+  opacity 0.9
+  background-effect {
+    blur true
+  }
+}
+
+
+// No opacity for a11y
+window-rule {
+  match is-window-cast-target=true
+
+  // Reader
+  match app-id="firefox"
+  match app-id="chromium-browser"
+  match app-id="floorp"
+  match app-id="thunderbird"
+
+  // Multi Media
+  match app-id="org.kde.kdenlive"
+  match app-id="gimp"
+  match app-id="org.inkscape.Inkscape"
+  match app-id="wpsoffice"
+  match app-id="blender"
+  match app-id="mpv"
+  match app-id="org.gnome.Loupe"
+  match app-id="atril"
+
+  opacity 1.0
+}
+
+
+// Maximize
+window-rule {
+  match app-id="code"
+  match app-id="dev.zed.Zed"
+  match app-id="firefox"
+  match app-id="floorp"
+  match app-id="chromium-browser"
+  match app-id="thunderbird"
+  match app-id="CherryStudio"
+  match app-id="deadbeef"
+  match app-id="mpv"
+  match app-id="steam" title="^Steam$"
+  match app-id="org.kde.kdenlive"
+  match app-id="gimp" is-floating=false
+  match app-id="wpsoffice" title="^WPS Office$"
+
+  open-maximized true
+}
+
+// Floating
+window-rule {
+  match app-id="QQ" title="^(图片查看器|文件管理器|收藏|聊天记录管理|设置|群相册 - .*?)$"
+
+  open-floating true
+}
+
+// === Workspaces ===
+window-rule {
+  match app-id="code"
+  match app-id="dev.zed.Zed"
+  match app-id="org.kde.kdenlive"
+  match app-id="gimp"
+  match app-id="wpsoffice"
+
+  open-on-workspace "1work"
+}
+
+window-rule {
+  match app-id="firefox"
+  match app-id="chromium-browser"
+  match app-id="floorp"
+
+  open-on-workspace "2web"
+}
+
+window-rule {
+  match app-id="org.telegram.desktop"
+  match app-id="wechat"
+  match app-id="QQ"
+  match app-id="thunderbird"
+  match app-id="CherryStudio"
+  match app-id="discord"
+  match app-id="vesktop"
+  match app-id="fluffychat"
+  match app-id="com.psyche.kelivo"
+
+  open-on-workspace "3chat"
+}
+
+window-rule {
+  match app-id="org.prismlauncher.PrismLauncher"
+  match app-id="steam"
+  match app-id="net.lutris.Lutris"
+  match app-id="heroic"
+  match app-id="moe.launcher.an-anime-game-launcher"
+  match app-id="moe.launcher.honkers-railway-launcher"
+  match app-id="moe.launcher.sleepy-launcher"
+  match app-id="yuanshen.exe"
+  match app-id="starrail.exe"
+  match app-id="zenlesszonezero.exe"
+
+  open-on-workspace "4game"
+}
modules/desktop/env/wm/niri/config/workspaces.kdl
@@ -0,0 +1,4 @@
+workspace "1work"
+workspace "2web"
+workspace "3chat"
+workspace "4game"
modules/desktop/env/wm/niri/default.nix
@@ -0,0 +1,84 @@
+{
+  den.aspects.desktop.env.wm.niri = {
+    nixos = {
+      # See https://github.com/NixOS/nixpkgs/blob/bcb52fa87abbc7ec046c4817d85950c35dae92b7/nixos/modules/services/misc/graphical-desktop.nix
+      services.graphical-desktop.enable = true;
+
+      programs.niri = {
+        enable = true;
+        useNautilus = true;
+      };
+    };
+
+    homeManager = {
+      lib,
+      config,
+      pkgs,
+      ...
+    }: let
+      cfg = config.programs.niri;
+      format = pkgs.formats.json {};
+    in {
+      options = {
+        programs.niri = {
+          extraConfig = {
+            pre = lib.mkOption {
+              inherit (format) type;
+              default = {
+              };
+              example = lib.literalExpression ''
+                {
+                  xwayland-satellite.path = lib.getExe pkgs.xwayland-satellite;
+                }
+              '';
+              description = ''
+                Extra configurations included in niri's configuration top.
+
+                Check Home Manager's `lib.hm.generators.toKDL` function
+                for more infomations.
+              '';
+            };
+            post = lib.mkOption {
+              inherit (format) type;
+              default = {};
+              example = lib.literalExpression ''
+                {
+                  bind."Mod+Space" = {
+                    _props = {
+                      repeat = false;
+                      hotkey-overlay-title = "Toggle Application Launcher";
+                    };
+                    spawn = ["vicinae" "toggle"];
+                  };
+                }
+              '';
+              description = ''
+                Extra configurations included in niri's configuration bottom.
+
+                Check Home Manager's `lib.hm.generators.toKDL` function
+                for more infomations.
+              '';
+            };
+          };
+        };
+      };
+
+      config = {
+        programs.niri.extraConfig = {
+          pre = {
+            xwayland-satellite.path = lib.getExe pkgs.xwayland-satellite;
+            screenshot-path = "${config.xdg.userDirs.pictures}/Screenshots/Screenshot_%Y-%m-%d_%H-%M-%S.png";
+          };
+        };
+
+        xdg.configFile."niri" = {
+          source = ./config;
+          recursive = true;
+        };
+
+        xdg.configFile."niri/nix/pre.kdl".text = lib.hm.generators.toKDL {} cfg.extraConfig.pre;
+        xdg.configFile."niri/nix/post.kdl".text = lib.hm.generators.toKDL {} cfg.extraConfig.post;
+      };
+    };
+  };
+}
modules/desktop/env/wm/niri/themes.nix
@@ -0,0 +1,15 @@
+{
+  den.aspects.desktop.env.wm.niri.themes = {
+    catppuccin = {
+      homeManager = {
+        programs.niri.extraConfig.pre = {
+          recent-windows.highlight = {
+            active-color = "#cba6f7"; # Mauve
+            urgent-color = "#f2cdcd"; # Flamingo
+          };
+          layout.focus-ring.active-color = "#cba6f7";
+        };
+      };
+    };
+  };
+}
modules/users/hpcesia/default.nix
@@ -13,6 +13,11 @@
           develop.editor.helix
           develop.editor.helix.lang.nix
           develop.jujutsu
+        ]))
+      ++ (den.lib.policy.when
+        ({host, ...}: host.hasAspect den.aspects.roles.desktop)
+        (with den.aspects; [
+          desktop.env.wm.niri
         ]));
   };