Commit 5383250

HPCesia <me@hpcesia.com>
2026-04-16 11:41:44
refactor: niri settings
Using original KDL instead of Nix modules since niri-flake is out-dated.
1 parent 89ea20a
modules/desktop/de/custom/shell/noctalia/keybindings/niri.nix
@@ -5,55 +5,50 @@
     ...
   }:
     lib.mkIf osConfig.programs.niri.enable {
-      programs.niri.settings.binds = with config.lib.niri.actions; let
-        noctalia = spawn "noctalia-shell" "ipc" "call";
-      in {
-        "Mod+Shift+Slash" = {
-          action = noctalia "plugin:keybind-cheatsheet" "toggle";
-          hotkey-overlay.title = "Toggle Hotkey Cheatsheet";
-        };
-        "Mod+Space" = lib.mkIf (!(config.services.vicinae.enable or false)) {
-          action = noctalia "launcher" "toggle";
-          hotkey-overlay.title = "Toggle Application Launcher";
-        };
-        "Mod+V" = lib.mkIf (!(config.services.vicinae.enable or false)) {
-          action = noctalia "launcher" "clipboard";
-          hotkey-overlay.title = "Open Clipboard History";
-        };
-        "Super+Alt+L" = {
-          action = noctalia "lockScreen" "lock";
-          hotkey-overlay.title = "Toggle Lock Screen";
-        };
-        "Mod+X" = {
-          action = noctalia "controlCenter" "toggle";
-          hotkey-overlay.title = "Toggle Control Center";
-        };
+      programs.niri.extraKeybinds = let
+        noctalia = ''spawn "noctalia-shell" "ipc" "call"'';
+      in ''
+        Mod+Shift+Slash hotkey-overlay-title="Toggle Hotkey Cheatsheet" {
+          ${noctalia} "plugin:keybind-cheatsheet" "toggle";
+        }
+        ${
+          if !(config.services.vicinae.enable or false)
+          then ''
+            Mod+Space hotkey-overlay-title="Toggle Application Launcher" {
+              ${noctalia} "launcher" "toggle";
+            }
+            Mod+V hotkey-overlay-title="Open Clipboard History" {
+              ${noctalia} "launcher" "clipboard";
+            }
+          ''
+          else ""
+        }
+        Super+Alt+L hotkey-overlay-title="Toggle Lock Screen" {
+          ${noctalia} "lockScreen" "lock";
+        }
+        Mod+X hotkey-overlay-title="Toggle Control Center" {
+          ${noctalia} "controlCenter" "toggle";
+        }
 
-        "XF86AudioRaiseVolume" = {
-          allow-when-locked = true;
-          action = noctalia "volume" "increase";
-        };
-        "XF86AudioLowerVolume" = {
-          allow-when-locked = true;
-          action = noctalia "volume" "decrease";
-        };
-        "XF86AudioMute" = {
-          allow-when-locked = true;
-          action = noctalia "volume" "muteOutput";
-        };
-        "XF86AudioMicMute" = {
-          allow-when-locked = true;
-          action = noctalia "volume" "muteInput";
-        };
+        XF86AudioRaiseVolume allow-when-locked=true {
+          ${noctalia} "volume" "increase";
+        }
+        XF86AudioLowerVolume allow-when-locked=true {
+          ${noctalia} "volume" "decrease";
+        }
+        XF86AudioMute allow-when-locked=true {
+          ${noctalia} "volume" "muteOutput";
+        }
+        XF86AudioMicMute allow-when-locked=true {
+          ${noctalia} "volume" "muteInput";
+        }
 
-        "XF86MonBrightnessUp" = {
-          allow-when-locked = true;
-          action = noctalia "brightness" "increase";
-        };
-        "XF86MonBrightnessDown" = {
-          allow-when-locked = true;
-          action = noctalia "brightness" "decrease";
-        };
-      };
+        XF86MonBrightnessUp allow-when-locked=true {
+          ${noctalia} "brightness" "increase";
+        }
+        XF86MonBrightnessDown allow-when-locked=true {
+          ${noctalia} "brightness" "decrease";
+        }
+      '';
     };
 }
modules/desktop/de/custom/wm/niri/config/config.kdl
@@ -0,0 +1,16 @@
+// Niri configuration file
+
+// Workspaces
+workspace "1work"
+workspace "2web"
+workspace "3chat"
+workspace "4game"
+
+include "keybinding.kdl"
+include "layout.kdl"
+include "recent-windows.kdl"
+include "window-rules.kdl"
+
+// KDL config generated by Nix
+include "nix/misc.kdl"
+include "nix/extra.kdl"
modules/desktop/de/custom/wm/niri/config/keybinding.kdl
@@ -0,0 +1,131 @@
+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; }
+
+  Mod+Grave hotkey-overlay-title="Open a Terminal: Ghostty" { spawn "ghostty"; }
+
+  // === 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/de/custom/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.66667
+  }
+  default-column-width { proportion 0.5; }
+}
modules/desktop/de/custom/wm/niri/config/recent-windows.kdl
@@ -0,0 +1,20 @@
+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/de/custom/wm/niri/config/window-rules.kdl
@@ -0,0 +1,80 @@
+// 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
+}
+
+// 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"
+
+  open-on-workspace "3chat"
+}
+
+window-rule {
+  match app-id="org.prismlauncher.PrismLauncher"
+  match app-id="^Minecraft\\* 1\\.[0-9]*\\.[0-9]*$"
+  match app-id="steam"
+  match app-id="net.lutris.Lutris"
+  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/de/custom/wm/niri/default.nix
@@ -1,32 +1,70 @@
-{inputs, ...}: {
-  flake-file.inputs.niri-flake = {
-    url = "github:sodiboo/niri-flake";
+{
+  inputs,
+  lib,
+  ...
+}: {
+  flake-file.inputs.niri-unstable = {
+    url = "github:niri-wm/niri";
     inputs.nixpkgs.follows = "nixpkgs";
   };
 
   flake.modules.nixos.wm-niri = {pkgs, ...}: {
-    nixpkgs.overlays = [
-      inputs.niri-flake.overlays.niri
-    ];
-
     programs.niri = {
       enable = true;
-      package = pkgs.niri-unstable;
+      package = inputs.niri-unstable.packages.${pkgs.stdenv.system}.default;
+      useNautilus = true;
     };
   };
 
   flake.modules.homeManager.wm-niri = {
-    osConfig,
     config,
     pkgs,
     ...
   }: {
-    imports = [inputs.niri-flake.homeModules.niri];
+    options = {
+      programs.niri = {
+        extraConfig = lib.mkOption {
+          type = lib.types.lines;
+          description = "Extra configuration for Niri, in KDL format.";
+        };
+        extraKeybinds = lib.mkOption {
+          type = lib.types.lines;
+          description = "Extra keybindings for Niri, in KDL format.";
+        };
+      };
+    };
+    config = {
+      xdg.configFile."niri" = {
+        source = ./config;
+        recursive = true;
+      };
+      xdg.configFile."niri/nix/misc.kdl".text = ''
+        screenshot-path "${config.xdg.userDirs.pictures}/Screenshots/Screenshot_%Y-%m-%d_%H-%M-%S.png";
+        hotkey-overlay {
+          skip-at-startup
+          hide-not-bound
+        }
+        xwayland-satellite { path "${lib.getExe pkgs.xwayland-satellite}"; }
+        prefer-no-csd
+        layout {
+          focus-ring {
+            active-color "#${config.lib.stylix.colors.base0E}"
+          }
+        }
+        window-rule {
+          opacity ${toString config.stylix.opacity.applications}
+        }
+      '';
+      services.xsettingsd = {
+        enable = true;
+      };
 
-    programs.niri.package = osConfig.programs.niri.package;
-    programs.niri.settings = {
-      screenshot-path = "${config.xdg.userDirs.pictures}/Screenshots/Screenshot_%Y-%m-%d_%H-%M-%S.png";
-      hotkey-overlay.skip-at-startup = true;
+      programs.niri.extraConfig = ''
+        binds {
+          ${config.programs.niri.extraKeybinds}
+        }
+      '';
+      xdg.configFile."niri/nix/extra.kdl".text = config.programs.niri.extraConfig;
     };
   };
 }
modules/desktop/de/custom/wm/niri/keybinding.nix
@@ -1,147 +0,0 @@
-{lib, ...}: {
-  flake.modules.homeManager.wm-niri = {config, ...}: {
-    programs.niri.settings.binds = with config.lib.niri.actions; {
-      # Mod-Shift-/, which is usually the same as Mod-?,
-      # shows a list of important hotkeys.
-      "Mod+Shift+Slash" =
-        lib.mkIf (!config.services.noctalia-shell.enable or true)
-        {action = show-hotkey-overlay;};
-      "Mod+Escape".action = toggle-overview;
-
-      "Mod+Shift+E".action = quit;
-      "Ctrl+Alt+Delete".action = quit;
-
-      "Print".action = {screenshot = [];};
-      "Mod+Shift+S".action = {screenshot = [];};
-      "Alt+Print".action = {screenshot-window = [];};
-
-      "Mod+Grave".action = spawn "ghostty";
-
-      "Mod+Space" = lib.mkIf (config.services.vicinae.enable or false) {
-        action = spawn "vicinae" "toggle";
-        hotkey-overlay.title = "Toggle Application Launcher";
-        repeat = false;
-      };
-
-      # === Window and Column Actions ===
-      "Mod+Q".action = close-window;
-
-      "Mod+H".action = focus-column-left;
-      "Mod+J".action = focus-window-down;
-      "Mod+K".action = focus-window-up;
-      "Mod+L".action = focus-column-right;
-      "Mod+Left".action = focus-column-left;
-      "Mod+Down".action = focus-window-down;
-      "Mod+Up".action = focus-window-up;
-      "Mod+Right".action = focus-column-right;
-      "Mod+Home".action = focus-column-first;
-      "Mod+End".action = focus-column-last;
-      "Mod+WheelScrollRight".action = focus-column-right;
-      "Mod+WheelScrollLeft".action = focus-column-left;
-      "Mod+Shift+WheelScrollDown".action = focus-column-right;
-      "Mod+Shift+WheelScrollUp".action = focus-column-left;
-
-      "Mod+Ctrl+H".action = move-column-left;
-      "Mod+Ctrl+J".action = move-window-down;
-      "Mod+Ctrl+K".action = move-window-up;
-      "Mod+Ctrl+L".action = move-column-right;
-      "Mod+Ctrl+Left".action = move-column-left;
-      "Mod+Ctrl+Down".action = move-window-down;
-      "Mod+Ctrl+Up".action = move-window-up;
-      "Mod+Ctrl+Right".action = move-column-right;
-      "Mod+Ctrl+Home".action = move-column-to-first;
-      "Mod+Ctrl+End".action = move-column-to-last;
-      "Mod+Ctrl+WheelScrollRight".action = move-column-right;
-      "Mod+Ctrl+WheelScrollLeft".action = move-column-left;
-      "Mod+Ctrl+Shift+WheelScrollDown".action = move-column-right;
-      "Mod+Ctrl+Shift+WheelScrollUp".action = move-column-left;
-
-      "Mod+Minus".action = set-column-width "-10%";
-      "Mod+Equal".action = set-column-width "+10%";
-      "Mod+Shift+Minus".action = set-window-height "-10%";
-      "Mod+Shift+Equal".action = set-window-height "+10%";
-
-      "Mod+R".action = switch-preset-column-width;
-      "Mod+Shift+R".action = switch-preset-window-height;
-      "Mod+Ctrl+R".action = reset-window-height;
-
-      "Mod+F".action = maximize-column;
-      "Mod+Shift+F".action = fullscreen-window;
-      "Mod+Ctrl+F".action = {maximize-window-to-edges = [];};
-      "Mod+Ctrl+Shift+F".action = {toggle-windowed-fullscreen = [];};
-
-      "Mod+BracketLeft".action = consume-or-expel-window-left;
-      "Mod+BracketRight".action = consume-or-expel-window-right;
-      "Mod+Comma".action = consume-window-into-column;
-      "Mod+Period".action = expel-window-from-column;
-
-      "Mod+Ctrl+W".action = toggle-window-floating;
-      "Mod+W".action = switch-focus-between-floating-and-tiling;
-
-      "Mod+T".action = toggle-column-tabbed-display;
-
-      # === Workspace Actions ===
-      "Mod+Page_Down".action = focus-workspace-down;
-      "Mod+Page_Up".action = focus-workspace-up;
-      "Mod+D".action = focus-workspace-down; # Default is `U`, use Helix binding instead.
-      "Mod+U".action = focus-workspace-up; # Default is `I`, use Helix binding instead.
-      "Mod+WheelScrollDown".action = focus-workspace-down;
-      "Mod+WheelScrollDown".cooldown-ms = 150;
-      "Mod+WheelScrollUp".action = focus-workspace-up;
-      "Mod+WheelScrollUp".cooldown-ms = 150;
-
-      "Mod+Ctrl+Page_Down".action = move-column-to-workspace-down;
-      "Mod+Ctrl+Page_Up".action = move-column-to-workspace-up;
-      "Mod+Ctrl+D".action = move-column-to-workspace-down;
-      "Mod+Ctrl+U".action = move-column-to-workspace-up;
-      "Mod+Ctrl+WheelScrollDown".action = move-column-to-workspace-down;
-      "Mod+Ctrl+WheelScrollDown".cooldown-ms = 150;
-      "Mod+Ctrl+WheelScrollUp".action = move-column-to-workspace-up;
-      "Mod+Ctrl+WheelScrollUp".cooldown-ms = 150;
-
-      "Mod+Shift+Page_Down".action = move-workspace-down;
-      "Mod+Shift+Page_Up".action = move-workspace-up;
-      "Mod+Shift+D".action = move-workspace-down;
-      "Mod+Shift+U".action = move-workspace-up;
-
-      "Mod+1".action = focus-workspace 1;
-      "Mod+2".action = focus-workspace 2;
-      "Mod+3".action = focus-workspace 3;
-      "Mod+4".action = focus-workspace 4;
-      "Mod+5".action = focus-workspace 5;
-      "Mod+6".action = focus-workspace 6;
-      "Mod+7".action = focus-workspace 7;
-      "Mod+8".action = focus-workspace 8;
-      "Mod+9".action = focus-workspace 9;
-
-      "Mod+Ctrl+1".action = {move-column-to-workspace = [1];};
-      "Mod+Ctrl+2".action = {move-column-to-workspace = [2];};
-      "Mod+Ctrl+3".action = {move-column-to-workspace = [3];};
-      "Mod+Ctrl+4".action = {move-column-to-workspace = [4];};
-      "Mod+Ctrl+5".action = {move-column-to-workspace = [5];};
-      "Mod+Ctrl+6".action = {move-column-to-workspace = [6];};
-      "Mod+Ctrl+7".action = {move-column-to-workspace = [7];};
-      "Mod+Ctrl+8".action = {move-column-to-workspace = [8];};
-      "Mod+Ctrl+9".action = {move-column-to-workspace = [9];};
-
-      # === Monitor Actions ===
-      "Mod+Shift+Left".action = focus-monitor-left;
-      "Mod+Shift+Down".action = focus-monitor-down;
-      "Mod+Shift+Up".action = focus-monitor-up;
-      "Mod+Shift+Right".action = focus-monitor-right;
-      "Mod+Shift+H".action = focus-monitor-left;
-      "Mod+Shift+J".action = focus-monitor-down;
-      "Mod+Shift+K".action = focus-monitor-up;
-      "Mod+Shift+L".action = focus-monitor-right;
-
-      "Mod+Shift+Ctrl+Left".action = move-column-to-monitor-left;
-      "Mod+Shift+Ctrl+Down".action = move-column-to-monitor-down;
-      "Mod+Shift+Ctrl+Up".action = move-column-to-monitor-up;
-      "Mod+Shift+Ctrl+Right".action = move-column-to-monitor-right;
-      "Mod+Shift+Ctrl+H".action = move-column-to-monitor-left;
-      "Mod+Shift+Ctrl+J".action = move-column-to-monitor-down;
-      "Mod+Shift+Ctrl+K".action = move-column-to-monitor-up;
-      "Mod+Shift+Ctrl+L".action = move-column-to-monitor-right;
-    };
-  };
-}
modules/desktop/de/custom/wm/niri/layer-rules.nix
@@ -1,10 +1,10 @@
 {lib, ...}: {
   flake.modules.homeManager.wm-niri = {config, ...}: {
-    programs.niri.settings.layer-rules = lib.optionals (config.programs.noctalia-shell.enable or false) [
-      {
-        matches = [{namespace = "^noctalia-overview*";}];
-        place-within-backdrop = true;
+    programs.niri.extraConfig = lib.mkIf (config.programs.noctalia-shell.enable) ''
+      layer-rule {
+        match namespace="^noctalia-overview*"
+        place-within-backdrop true
       }
-    ];
+    '';
   };
 }
modules/desktop/de/custom/wm/niri/layout.nix
@@ -1,24 +0,0 @@
-{
-  flake.modules.homeManager.wm-niri = {config, ...}: let
-  in {
-    programs.niri.settings.prefer-no-csd = true;
-
-    programs.niri.settings.layout = {
-      gaps = 10;
-      focus-ring = {
-        enable = true;
-        width = 2;
-        active.color = config.lib.stylix.colors.base0E;
-      };
-      border.enable = false;
-      preset-column-widths = [
-        {proportion = 1.0 / 3.0;}
-        {proportion = 1.0 / 2.0;}
-        {proportion = 2.0 / 3.0;}
-      ];
-      default-column-width.proportion = 1.0 / 2.0;
-      always-center-single-column = true;
-      background-color = "transparent";
-    };
-  };
-}
modules/desktop/de/custom/wm/niri/recent-windows.nix
@@ -1,40 +0,0 @@
-{inputs, ...}: {
-  flake.modules.homeManager.wm-niri = {
-    options,
-    config,
-    ...
-  }: {
-    # TODO: Use niri-flake's recent windows option after https://github.com/sodiboo/niri-flake/issues/1446 solved.
-    config.programs.niri.config =
-      options.programs.niri.config.default
-      ++ (let
-        inherit (inputs.niri-flake.lib.kdl) node plain leaf flag;
-      in [
-        (plain "recent-windows" [
-          # (flag "off") # Disables the recent windows switcher altogether.
-
-          (leaf "debounce-ms" 750)
-          (leaf "open-delay-ms" 150)
-
-          (plain "highlight" [
-            (leaf "active-color" config.lib.stylix.colors.withHashtag.base0E)
-            (leaf "urgent-color" config.lib.stylix.colors.withHashtag.base0F)
-            (leaf "padding" 30)
-            (leaf "corner-radius" 15.0)
-          ])
-
-          (plain "previews" [
-            (leaf "max-height" 480)
-            (leaf "max-scale" 0.5)
-          ])
-
-          (plain "binds" [
-            (plain "Alt+Tab" [(flag "next-window")])
-            (plain "Alt+Shift+Tab" [(flag "previous-window")])
-            (plain "Mod+Tab" [(flag "next-window")])
-            (plain "Mod+Shift+Tab" [(flag "previous-window")])
-          ])
-        ])
-      ]);
-  };
-}
modules/desktop/de/custom/wm/niri/window-rules.nix
@@ -1,110 +0,0 @@
-{lib, ...}: {
-  flake.modules.homeManager.wm-niri = {config, ...}: {
-    programs.niri.settings.window-rules = [
-      {
-        # rules for all windows
-        clip-to-geometry = true;
-        geometry-corner-radius = lib.genAttrs ["bottom-left" "bottom-right" "top-left" "top-right"] (_: 15.0);
-        tiled-state = true;
-        draw-border-with-background = false;
-        opacity = config.stylix.opacity.applications;
-      }
-
-      {
-        # Maximize
-        matches = [
-          {app-id = "code";}
-          {app-id = "dev.zed.Zed";}
-
-          {app-id = "firefox";}
-          {app-id = "floorp";}
-          {app-id = "chromium-browser";}
-
-          {app-id = "thunderbird";}
-          {app-id = "CherryStudio";} # Maximize Cherry Studio because default half-size is too small to it's minimum usable size
-
-          {app-id = "deadbeef";}
-          {app-id = "mpv";}
-
-          {
-            title = "^Steam$"; # Only match the main Steam window
-            app-id = "steam";
-          }
-
-          {app-id = "org.kde.kdenlive";}
-          {
-            app-id = "gimp";
-            is-floating = false;
-          }
-          {
-            title = "^WPS Office$"; # Only match the main WPS Office window
-            app-id = "wpsoffice";
-          }
-        ];
-        open-maximized = true;
-      }
-
-      {
-        # Floating
-        matches = [
-          {
-            app-id = "QQ";
-            title = "^(图片查看器|文件管理器|收藏|聊天记录管理|设置|群相册 - .*?)$";
-          }
-        ];
-        open-floating = true;
-      }
-
-      # === Workspaces ===
-      {
-        matches = [
-          # Development
-          {app-id = "code";}
-          {app-id = "dev.zed.Zed";}
-
-          # Multimedia
-          {app-id = "org.kde.kdenlive";}
-          {app-id = "gimp";}
-          {app-id = "wpsoffice";}
-        ];
-        open-on-workspace = "1work";
-      }
-      {
-        matches = [
-          {app-id = "firefox";}
-          {app-id = "chromium-browser";}
-          {app-id = "floorp";}
-        ];
-        open-on-workspace = "2web";
-      }
-      {
-        matches = [
-          {app-id = "org.telegram.desktop";}
-          {app-id = "wechat";}
-          {app-id = "QQ";}
-          {app-id = "thunderbird";}
-          {app-id = "CherryStudio";} # AI Chat is also a chat app :)
-          {app-id = "discord";}
-          {app-id = "vesktop";}
-          {app-id = "fluffychat";}
-        ];
-        open-on-workspace = "3chat";
-      }
-      {
-        matches = [
-          {app-id = "org.prismlauncher.PrismLauncher";}
-          {app-id = "^Minecraft\\* 1\\.[0-9]*\\.[0-9]*$";}
-          {app-id = "steam";}
-          {app-id = "net.lutris.Lutris";}
-          {app-id = "moe.launcher.an-anime-game-launcher";}
-          {app-id = "moe.launcher.honkers-railway-launcher";}
-          {app-id = "moe.launcher.sleepy-launcher";}
-          {app-id = "yuanshen.exe";}
-          {app-id = "starrail.exe";}
-          {app-id = "zenlesszonezero.exe";}
-        ];
-        open-on-workspace = "4game";
-      }
-    ];
-  };
-}
modules/desktop/de/custom/wm/niri/workspaces.nix
@@ -1,10 +0,0 @@
-{
-  flake.modules.homeManager.wm-niri = _: {
-    programs.niri.settings.workspaces = {
-      "1work" = {};
-      "2web" = {};
-      "3chat" = {};
-      "4game" = {};
-    };
-  };
-}
modules/desktop/de/custom/wm/niri/xwayland.nix
@@ -1,14 +0,0 @@
-{lib, ...}: {
-  flake.modules.homeManager.wm-niri = {pkgs, ...}: {
-    services.xsettingsd = {
-      enable = true;
-    };
-
-    programs.niri.settings = {
-      xwayland-satellite = {
-        enable = true;
-        path = lib.getExe pkgs.xwayland-satellite;
-      };
-    };
-  };
-}
modules/hosts/kevin/hardware/screen.nix
@@ -17,14 +17,13 @@
     hasNiri = osConfig.programs.niri.enable;
   in
     lib.optionalAttrs hasNiri {
-      programs.niri.settings.outputs."eDP-1" = {
-        mode = {
-          height = 2000;
-          width = 3200;
-          refresh = 165.002;
-        };
-        scale = 2.0;
-      };
+      programs.niri.extraConfig = ''
+        output "eDP-1" {
+          scale 2.000000
+          transform "normal"
+          mode "3200x2000@165.002000"
+        }
+      '';
 
       services.xsettingsd.settings."Xft/DPI" = 96 * 2 * 1024;
     };
flake.lock
@@ -624,60 +624,23 @@
         "type": "github"
       }
     },
-    "niri-flake": {
+    "niri-unstable": {
       "inputs": {
-        "niri-stable": "niri-stable",
-        "niri-unstable": "niri-unstable",
         "nixpkgs": [
           "nixpkgs"
         ],
-        "nixpkgs-stable": "nixpkgs-stable",
-        "xwayland-satellite-stable": "xwayland-satellite-stable",
-        "xwayland-satellite-unstable": "xwayland-satellite-unstable"
-      },
-      "locked": {
-        "lastModified": 1775877135,
-        "narHash": "sha256-nAqtUMy22olwyiOJB0CASVrbu5XB5+43GjlbIJ1KuvQ=",
-        "owner": "sodiboo",
-        "repo": "niri-flake",
-        "rev": "f943da038fd668d435c2d17916577f295faa8839",
-        "type": "github"
-      },
-      "original": {
-        "owner": "sodiboo",
-        "repo": "niri-flake",
-        "type": "github"
-      }
-    },
-    "niri-stable": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1756556321,
-        "narHash": "sha256-RLD89dfjN0RVO86C/Mot0T7aduCygPGaYbog566F0Qo=",
-        "owner": "YaLTeR",
-        "repo": "niri",
-        "rev": "01be0e65f4eb91a9cd624ac0b76aaeab765c7294",
-        "type": "github"
+        "rust-overlay": "rust-overlay_2"
       },
-      "original": {
-        "owner": "YaLTeR",
-        "ref": "v25.08",
-        "repo": "niri",
-        "type": "github"
-      }
-    },
-    "niri-unstable": {
-      "flake": false,
       "locked": {
-        "lastModified": 1775561155,
-        "narHash": "sha256-TK2IrqQivRcwqJa0suZMbcsN17CtA8Uu0v7CDnLATb0=",
-        "owner": "YaLTeR",
+        "lastModified": 1776332135,
+        "narHash": "sha256-7cKy5sGmN4Yt47Op0+A/b3iEMk/E2Ru+UiI42KfiEPc=",
+        "owner": "niri-wm",
         "repo": "niri",
-        "rev": "599db847f857b8a7ff78ce02f15acab5d5d9fee1",
+        "rev": "892470afd3dce5396828dd9b211b19210a16eaeb",
         "type": "github"
       },
       "original": {
-        "owner": "YaLTeR",
+        "owner": "niri-wm",
         "repo": "niri",
         "type": "github"
       }
@@ -875,22 +838,6 @@
         "type": "github"
       }
     },
-    "nixpkgs-stable": {
-      "locked": {
-        "lastModified": 1775811116,
-        "narHash": "sha256-t+HZK42pB6N+i5RGbuy7Xluez/VvWbembBdvzsc23Ss=",
-        "owner": "NixOS",
-        "repo": "nixpkgs",
-        "rev": "54170c54449ea4d6725efd30d719c5e505f1c10e",
-        "type": "github"
-      },
-      "original": {
-        "owner": "NixOS",
-        "ref": "nixos-25.11",
-        "repo": "nixpkgs",
-        "type": "github"
-      }
-    },
     "nixpkgs_2": {
       "locked": {
         "lastModified": 1743014863,
@@ -1202,7 +1149,7 @@
         "flake-parts": "flake-parts",
         "home-manager": "home-manager",
         "import-tree": "import-tree",
-        "niri-flake": "niri-flake",
+        "niri-unstable": "niri-unstable",
         "nix-cachyos-kernel": "nix-cachyos-kernel",
         "nix-gaming": "nix-gaming",
         "nixcord": "nixcord",
@@ -1242,6 +1189,27 @@
       }
     },
     "rust-overlay_2": {
+      "inputs": {
+        "nixpkgs": [
+          "niri-unstable",
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1757989933,
+        "narHash": "sha256-9cpKYWWPCFhgwQTww8S94rTXgg8Q8ydFv9fXM6I8xQM=",
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "rev": "8249aa3442fb9b45e615a35f39eca2fe5510d7c3",
+        "type": "github"
+      },
+      "original": {
+        "owner": "oxalica",
+        "repo": "rust-overlay",
+        "type": "github"
+      }
+    },
+    "rust-overlay_3": {
       "inputs": {
         "nixpkgs": [
           "vaultix",
@@ -1513,7 +1481,7 @@
         "flake-parts": "flake-parts_7",
         "nixpkgs": "nixpkgs_9",
         "pre-commit-hooks": "pre-commit-hooks",
-        "rust-overlay": "rust-overlay_2"
+        "rust-overlay": "rust-overlay_3"
       },
       "locked": {
         "lastModified": 1770047974,
@@ -1545,39 +1513,6 @@
         "type": "git",
         "url": "https://repo.hpcesia.com/HPCesia/Wallpapers"
       }
-    },
-    "xwayland-satellite-stable": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1755491097,
-        "narHash": "sha256-m+9tUfsmBeF2Gn4HWa6vSITZ4Gz1eA1F5Kh62B0N4oE=",
-        "owner": "Supreeeme",
-        "repo": "xwayland-satellite",
-        "rev": "388d291e82ffbc73be18169d39470f340707edaa",
-        "type": "github"
-      },
-      "original": {
-        "owner": "Supreeeme",
-        "ref": "v0.7",
-        "repo": "xwayland-satellite",
-        "type": "github"
-      }
-    },
-    "xwayland-satellite-unstable": {
-      "flake": false,
-      "locked": {
-        "lastModified": 1773622265,
-        "narHash": "sha256-wToKwH7IgWdGLMSIWksEDs4eumR6UbbsuPQ42r0oTXQ=",
-        "owner": "Supreeeme",
-        "repo": "xwayland-satellite",
-        "rev": "a879e5e0896a326adc79c474bf457b8b99011027",
-        "type": "github"
-      },
-      "original": {
-        "owner": "Supreeeme",
-        "repo": "xwayland-satellite",
-        "type": "github"
-      }
     }
   },
   "root": "root",
flake.nix
@@ -23,8 +23,8 @@
       inputs.nixpkgs.follows = "nixpkgs";
     };
     import-tree.url = "github:vic/import-tree";
-    niri-flake = {
-      url = "github:sodiboo/niri-flake";
+    niri-unstable = {
+      url = "github:niri-wm/niri";
       inputs.nixpkgs.follows = "nixpkgs";
     };
     nix-cachyos-kernel = {