diff --git a/modules/desktop/hyprland/binds.nix b/modules/desktop/hyprland/binds.nix new file mode 100644 index 0000000..1eba0a9 --- /dev/null +++ b/modules/desktop/hyprland/binds.nix @@ -0,0 +1,77 @@ +{ ... }: { + flake.lib.hyprlandBinds = + { lib, dmsEnabled ? false }: + let + workspaceBinds = + (builtins.map (i: "Super, ${toString i}, workspace, ${toString i}") (builtins.genList (n: n + 1) 9)) + ++ (builtins.map ( + i: "ControlSuper, ${toString i}, focusworkspaceoncurrentmonitor, ${toString i}" + ) (builtins.genList (n: n + 1) 9)) + ++ (builtins.map (i: "ShiftSuper, ${toString i}, movetoworkspacesilent, ${toString i}") ( + builtins.genList (n: n + 1) 9 + )); + in + { + bind = + [ + "SUPER,T,exec,kitty" + "ControlSuper,T,exec,konsole" + "SUPER,D,exec,rofi -show drun" + "ControlSuper,D,exec,rofi -show window" + "SUPER,E,exec,nemo" + "Super, Q, killactive" + "ControlSuper, Q, exec, hyprctl kill" + "Super, F, fullscreen, 0" + "Super, G, fullscreen, 1" + "ShiftSuper, F, fullscreenstate, 0 3" + "Super, Minus, splitratio, -0.1" + "Super, Equal, splitratio, 0.1" + "AltSuper, Space, togglefloating" + "Super, P, pin" + ] + ++ lib.optionals dmsEnabled [ + "Super, Space, exec, dms ipc call spotlight toggle" + "Super, I, exec, dms ipc call settings focusOrToggle" + "Super, N, exec, dms ipc call notepad toggle" + "ShiftSuper, N, exec, dms ipc call notifications toggle" + "Super, M, exec, dms ipc call processlist focusOrToggle" + "Super, L, exec, dms ipc call lock lock" + "ShiftSuper, V, exec, dms ipc call clipboard toggle" + ] + ++ [ + "Super, Tab, cyclenext" + "Super, Tab, bringactivetotop" + "Super, left, movefocus, l" + "Super, right, movefocus, r" + "Super, up, movefocus, u" + "Super, down, movefocus, d" + "ShiftSuper, left, movewindow, l" + "ShiftSuper, right, movewindow, r" + "ShiftSuper, up, movewindow, u" + "ShiftSuper, down, movewindow, d" + ] + ++ workspaceBinds; + + bindm = [ + " , mouse:282, movewindow" + "Super, mouse:272, movewindow" + "Super, mouse:273, resizewindow" + ]; + + bindl = [ + "Super, mouse_up, splitratio, -0.1" + "Super, mouse_down, splitratio, 0.1" + " , XF86AudioPlay, exec, playerctl play-pause" + " , XF86AudioPrev, exec, playerctl previous" + " , XF86AudioNext, exec, playerctl next" + " , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" + " , XF86MonBrightnessDown, exec, brightnessctl s 10%-" + " , XF86MonBrightnessUp, exec, brightnessctl s +10%" + ]; + + bindel = [ + " , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+" + " , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" + ]; + }; +} diff --git a/modules/desktop/hyprland/default.nix b/modules/desktop/hyprland/default.nix index aca2e9a..12b1d92 100644 --- a/modules/desktop/hyprland/default.nix +++ b/modules/desktop/hyprland/default.nix @@ -1,4 +1,8 @@ { self, ... }: { + imports = [ + ./binds.nix + ]; + flake.nixosModules.desktopHyprland = { config, options, lib, pkgs, ... }: let @@ -38,6 +42,7 @@ }: let hyprlandEnabled = osConfig.chiasson.desktop.hyprland.enable or false; + dmsEnabled = (osConfig.chiasson.desktop.shell or null) == "dms"; keyringEnabled = osConfig.chiasson.desktop.keyring.enable or false; # nixpkgs hyprland-plugins pin is stale for current Hyprland — override to a known-good rev. hyprbarsPatched = @@ -95,69 +100,9 @@ "nm-applet --indicator &" "sleep 1 && hyprctl reload" ]; - - # Default keybinds - bind = - [ - "SUPER,T,exec,kitty" - "ControlSuper,T,exec,konsole" - "SUPER,D,exec,rofi -show drun" - "ControlSuper,D,exec,rofi -show window" - "SUPER,E,exec,nemo" - "Super, Q, killactive" - "ControlSuper, Q, exec, hyprctl kill" - "Super, F, fullscreen, 0" - "Super, G, fullscreen, 1" - "ShiftSuper, F, fullscreenstate, 0 3" - "Super, Minus, splitratio, -0.1" - "Super, Equal, splitratio, 0.1" - "AltSuper, Space, togglefloating" - "Super, P, pin" - "Super, Space, exec, dms ipc call spotlight toggle" - "Super, I, exec, dms ipc call settings focusOrToggle" - "Super, N, exec, dms ipc call notepad toggle" - "ShiftSuper, N, exec, dms ipc call notifications toggle" - "Super, M, exec, dms ipc call processlist focusOrToggle" - "Super, L, exec, dms ipc call lock lock" - "ShiftSuper, V, exec, dms ipc call clipboard toggle" - "Super, Tab, cyclenext" - "Super, Tab, bringactivetotop" - "Super, left, movefocus, l" - "Super, right, movefocus, r" - "Super, up, movefocus, u" - "Super, down, movefocus, d" - "ShiftSuper, left, movewindow, l" - "ShiftSuper, right, movewindow, r" - "ShiftSuper, up, movewindow, u" - "ShiftSuper, down, movewindow, d" - ] - ++ (builtins.map (i: "Super, ${toString i}, workspace, ${toString i}") (builtins.genList (n: n + 1) 9)) - ++ (builtins.map (i: "ControlSuper, ${toString i}, focusworkspaceoncurrentmonitor, ${toString i}") (builtins.genList (n: n + 1) 9)) - ++ (builtins.map (i: "ShiftSuper, ${toString i}, movetoworkspacesilent, ${toString i}") (builtins.genList (n: n + 1) 9)); - - bindm = [ - " , mouse:282, movewindow" - "Super, mouse:272, movewindow" - "Super, mouse:273, resizewindow" - ]; - - bindl = [ - "Super, mouse_up, splitratio, -0.1" - "Super, mouse_down, splitratio, 0.1" - " , XF86AudioPlay, exec, playerctl play-pause" - " , XF86AudioPrev, exec, playerctl previous" - " , XF86AudioNext, exec, playerctl next" - " , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" - " , XF86MonBrightnessDown, exec, brightnessctl s 10%-" - " , XF86MonBrightnessUp, exec, brightnessctl s +10%" - ]; - - bindel = [ - " , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+" - " , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" - ]; - - # Decoration / blur + } + (self.lib.hyprlandBinds { inherit lib dmsEnabled; }) + { decoration = { rounding = 10; active_opacity = 0.95; diff --git a/modules/desktop/niri/base-settings.nix b/modules/desktop/niri/base-settings.nix new file mode 100644 index 0000000..15fa8ce --- /dev/null +++ b/modules/desktop/niri/base-settings.nix @@ -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; + }; +} diff --git a/modules/desktop/niri/binds.nix b/modules/desktop/niri/binds.nix new file mode 100644 index 0000000..66d79cc --- /dev/null +++ b/modules/desktop/niri/binds.nix @@ -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" = _: { }; + }; +} diff --git a/modules/desktop/niri/default.nix b/modules/desktop/niri/default.nix index 1200c2f..ebcd9b8 100644 --- a/modules/desktop/niri/default.nix +++ b/modules/desktop/niri/default.nix @@ -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) { diff --git a/modules/desktop/niri/window-rules.nix b/modules/desktop/niri/window-rules.nix new file mode 100644 index 0000000..7be93b6 --- /dev/null +++ b/modules/desktop/niri/window-rules.nix @@ -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; + } + ]; +}