# # Configure Niri, our wayland compositor. # # vim: et:ts=2:sw=2: { lib, pkgs, niri, ... }: let niri-flake = niri; in { # Add in some basic control utilities to our system config. environment.systemPackages = [ pkgs.wlrctl ]; # Don't let the niri-flake fuck with our secret provider, kwallet. services.gnome.gnome-keyring.enable = lib.mkForce false; # # Niri configuration. # home-manager.users.deprekated = { pkgs, config, niri, ... }: with lib; let binds = { suffixes, prefixes, substitutions ? { }, }: # # This quite-useful monstrosity stolen from @sodiboo. # let replacer = replaceStrings (attrNames substitutions) (attrValues substitutions); format = prefix: suffix: let actual-suffix = if isList suffix.action then { action = head suffix.action; args = tail suffix.action; } else { inherit (suffix) action; args = [ ]; }; action = replacer "${prefix.action}-${actual-suffix.action}"; in { name = "${prefix.key}+${suffix.key}"; value.action.${action} = actual-suffix.args; }; pairs = attrs: fn: concatMap ( key: fn { inherit key; action = attrs.${key}; } ) (attrNames attrs); in listToAttrs (pairs prefixes (prefix: pairs suffixes (suffix: [ (format prefix suffix) ]))); xwayland-satellite-loop = pkgs.writeScriptBin "xwayland-satellite-loop" '' #!${pkgs.bash}/bin/bash while true; do ${pkgs.xwayland-satellite}/bin/xwayland-satellite done ''; in { # Don't let the niri-flake fuck with our secret provider, kwallet. services.gnome-keyring.enable = lib.mkForce false; # # Core Niri settings. # programs.niri.settings = { # Use Wayland programs when possible. environment = { NIXOS_OZONE_WL = "1"; SHELL_TYPE = "prompt_toolkit"; XDG_DATA_DIRS = "/var/lib/flatpak/exports/share:/home/deprekated/.nix-profile/share:/nix/profile/share:/home/deprekated/.local/state/nix/profile/share:/etc/profiles/per-user/deprekated/share:/nix/var/nix/profiles/default/share:/run/current-system/sw/share"; # Provided by xwayland-satellite below. DISPLAY = ":0"; }; # Avoid client-side decorations, when possible. prefer-no-csd = true; # Don't show our hotkeys on startup. hotkey-overlay.skip-at-startup = true; # # Adjust our layouts. # layout = { # No wasted space between windows. gaps = 0; # Default to half the screen. default-column-width = { proportion = 1.0 / 2.0; }; # Set up the column widths for Meta+R. preset-column-widths = [ { proportion = 1.0 / 2.0; } { proportion = 2.0 / 3.0; } { proportion = 1.0 / 3.0; } ]; # Improve the color of focused windows. border = { active = { color = "#268BD2"; }; }; }; # # Keyboard, mouse, etc. settings. # input = { # Moving focus with the keyboard should move the mouse. warp-mouse-to-focus = true; touchpad = { # No tap to click, but use the number of fingers to press # multiple buttons. tap = false; tap-button-map = "left-right-middle"; click-method = "clickfinger"; # Disable while typing. dwt = true; # Use natural scrolling. natural-scroll = true; }; trackpoint = { accel-speed = 0.2; accel-profile = "flat"; }; keyboard = { # Make caps lock a second escape, and ralt a compose. xkb.options = "caps:escape,compose:ralt"; }; }; # # Per-application settings. # window-rules = [ # Wezterm workaround: wezterm gets sad when it # doesn't get to set its own width, so let it. { matches = [ { app-id = "^org.wezfurlong.wezterm$"; } ]; default-column-width = { }; } # Make anki flashcard windows modal floats. { matches = [{ app-id = "^anki$"; title = "Add"; }]; open-floating = true; default-floating-position = { x = 0; y = 0; relative-to = "top-right"; }; } # Talon windows should show over other ones. { matches = [ { app-id = "talon"; } ]; } # Bitwig needs to set its own width. { matches = [ { app-id = "^com.bitwig.BitwigStudio$"; } ]; default-column-width = { }; } # Let gamescope be fullscreen, by default. { matches = [ { app-id = "^gamescope$"; } ]; default-column-width = { proportion = 1.0; }; } # Keep our system monitor on the monitoring screen. { matches = [ { app-id = "io.missioncenter.MissionCenter"; } ]; open-on-output = "Shenzhen Soogeen Electronics Co., LTD. L01N8A 0x01348C5C"; open-fullscreen = true; open-focused = false; } ]; # # Key bindings. # binds = with config.lib.niri.actions; let sh = spawn "sh" "-c"; in lib.attrsets.mergeAttrsList [ { # Kate keys. "Mod+O".action = sh "haxtype '⚪O>'"; "Mod+T".action = sh "haxtype '🔵T>'"; "Mod+K".action = sh "haxtype '🟣K>'"; "Mod+W".action = sh "haxtype '🟢W>'"; "Mod+S".action = sh "haxtype '🔴S>'"; "Mod+E".action = sh "haxtype '⚫E>'"; # Kate keys. "Mod+F1".action = sh "haxtype ⑴"; "Mod+F2".action = sh "haxtype ⑵"; "Mod+F3".action = sh "haxtype ⑶"; "Print".action = screenshot; "Mod+Return".action = spawn "wezterm"; "Mod+D".action = spawn "fuzzel"; "Mod+Space".action = spawn "fuzzel"; "XF86AudioRaiseVolume".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 0.1+"; "XF86AudioLowerVolume".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 0.1-"; "XF86Launch6".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 0.1-"; "XF86Tools".action = sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 0.1+"; "XF86AudioMute".action = sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; "XF86AudioMicMute".action = sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; "XF86MonBrightnessDown".action = sh "brightnessctl set 10%-"; "XF86MonBrightnessUp".action = sh "brightnessctl set 10%+"; "XF86Messenger".action = sh "rfkill toggle bluetooth"; "XF86Go".action = sh "rfkill toggle wwan"; "Cancel".action = sh "rfkill block nfc"; "XF86Favorites".action = sh "mpc toggle"; # Lenovo buttons. "0x47".action = sh "brightnessctl set 10%-"; "0x48".action = sh "brightnessctl set 10%+"; "Mod+Q".action = close-window; "XF86AudioPrev".action = sh "mpc prev"; "XF86AudioNext".action = sh "mpc next"; "XF86AudioPlay".action = sh "mpc toggle"; "XF86Launch5".action = sh "mpc toggle"; } (binds { suffixes."Left" = "column-left"; suffixes."Down" = "window-down"; suffixes."Up" = "window-up"; suffixes."Right" = "column-right"; prefixes."Mod" = "focus"; prefixes."Mod+Ctrl" = "move"; prefixes."Mod+Shift" = "focus-monitor"; prefixes."Mod+Shift+Ctrl" = "move-window-to-monitor"; substitutions."monitor-column" = "monitor"; substitutions."monitor-window" = "monitor"; }) (binds { suffixes."Home" = "first"; suffixes."End" = "last"; prefixes."Mod" = "focus-column"; prefixes."Mod+Ctrl" = "move-column-to"; }) (binds { suffixes."U" = "workspace-down"; suffixes."I" = "workspace-up"; prefixes."Mod" = "focus"; prefixes."Mod+Ctrl" = "move-window-to"; prefixes."Mod+Shift" = "move"; }) (binds { suffixes = builtins.listToAttrs ( map (n: { name = toString n; value = [ "workspace" n ]; }) (range 1 9) ); prefixes."Mod" = "focus"; prefixes."Mod+Ctrl" = "move-window-to"; }) { "Mod+Comma".action = consume-window-into-column; "Mod+Period".action = expel-window-from-column; "Mod+R".action = switch-preset-column-width; "Mod+F".action = maximize-column; "Mod+Shift+F".action = fullscreen-window; "Mod+C".action = center-column; "Mod+L".action = switch-focus-between-floating-and-tiling; "Mod+Shift+L".action = toggle-window-floating; "Mod+Minus".action = set-column-width "-10%"; "Mod+Plus".action = set-column-width "+10%"; "Mod+Shift+Minus".action = set-window-height "-10%"; "Mod+Shift+Plus".action = set-window-height "+10%"; "Mod+Print".action = screenshot-window; "Mod+Shift+E".action = quit; "Mod+Shift+P".action = power-off-monitors; "Mod+Shift+Ctrl+T".action = toggle-debug-tint; } ]; # Startup our wallpaper and our credential manager. spawn-at-startup = let niri-init = pkgs.writeScriptBin "niri-init" '' #!${pkgs.bash}/bin/bash systemctl --user restart swaybg sleep 2 systemctl --user stop waybar niri msg action spawn -- waybar sleep 2 niri msg action spawn -- ${xwayland-satellite-loop}/bin/xwayland-satellite-loop niri msg action spawn -- home-assistant-desktop niri msg action spawn -- ${pkgs.mission-center}/bin/missioncenter sleep 10 niri msg action spawn -- kdeconnect-cli -l ''; in [ { command = [ "${niri-init}/bin/niri-init" ]; } ]; }; }; }