{ config, lib, pkgs, ... }: { # Note: `config` here is HM config config = lib.mkIf config.desktop.enable { home.packages = [ pkgs.nautilus ]; # xdg-desktop-portal-gnome wants it programs.niri = { settings = { environment = { NIXOS_OZONE_WL = "1"; ELECTRON_OZONE_PLATFORM_HINT = "auto"; QT_QPA_PLATFORMTHEME = "qt5ct"; QT_QPA_PLATFORM = "wayland"; DISPLAY = ":0"; GTK_IM_MODULE = "simple"; }; screenshot-path = null; prefer-no-csd = true; hotkey-overlay = { skip-at-startup = true; hide-not-bound = true; }; input = { focus-follows-mouse = { enable = true; max-scroll-amount = "80%"; }; keyboard = { repeat-delay = 300; repeat-rate = 5; xkb = { layout = "us"; variant = "intl"; }; }; mouse = { accel-profile = "flat"; accel-speed = 0.5; }; touchpad = { tap = true; dwt = true; natural-scroll = true; click-method = "clickfinger"; }; }; layout = { gaps = 16; always-center-single-column = true; empty-workspace-above-first = true; default-column-width = { proportion = 0.5; }; }; window-rules = [ { geometry-corner-radius = let radius = 8.0; in { bottom-left = radius; bottom-right = radius; top-left = radius; top-right = radius; }; clip-to-geometry = true; } { matches = [ { title = "Picture-in-Picture"; } ]; open-floating = true; default-floating-position = { x = 16; y = 16; relative-to = "bottom-right"; }; } ]; # The shared desk: both laptops dock here. eDP-1 mode differs # per machine and is overridden in systems//home.nix # (belaf: 2560x1600); absent outputs are ignored by niri. outputs = let lg = { width = 2560; height = 1440; }; benq = { width = 2560; height = 1440; }; edp = { width = 1920; height = 1200; }; in { "LG Electronics LG ULTRAGEAR 511NTCZHB395" = { mode = lg; transform = { rotation = 90; }; position = { x = 0; y = 0; }; }; "PNP(BNQ) BenQ EX2710R ETF9M01632SL0" = { mode = benq; position = { x = lg.height; y = 0; }; }; eDP-1 = { mode = lib.mkDefault edp; position = { x = lg.height; y = benq.height; }; }; }; binds = with config.lib.niri.actions; let toAction = act: dir: (lib.mapAttrs' ( argName: argValue: lib.nameValuePair "${argName}+${dir.name}" { action = { "${argValue}-${dir.value}" = [ ]; }; } ) act); windowMoves = lib.mergeAttrsList ( (map (toAction { "Mod" = "focus"; "Mod+Ctrl" = "move"; }) ( lib.attrsToList { "Up" = "window-up"; "k" = "window-up"; "Down" = "window-down"; "j" = "window-down"; "Left" = "column-left"; "h" = "column-left"; "Right" = "column-right"; "l" = "column-right"; "I" = "workspace-down"; "U" = "workspace-up"; } ) ) ++ (map (toAction { "Mod+Shift" = "focus"; "Mod+Ctrl+Shift" = "move-window-to"; }) ( lib.attrsToList { "Up" = "monitor-up"; "K" = "monitor-up"; "Down" = "monitor-down"; "J" = "monitor-down"; "Left" = "monitor-left"; "H" = "monitor-left"; "Right" = "monitor-right"; "L" = "monitor-right"; "I" = "workspace-down"; "U" = "workspace-up"; } ) ) ); in { "Mod+O".action = show-hotkey-overlay; "Mod+Q".action.spawn = "${lib.getExe pkgs.ghostty}"; "Mod+C".action.close-window = [ ]; "Mod+Comma".action = consume-window-into-column; "Mod+Period".action = expel-window-from-column; "Mod+T".action = switch-preset-column-width; "Mod+F".action = maximize-column; "Mod+Shift+F".action = fullscreen-window; "Mod+D".action = center-column; "Mod+B".action = toggle-window-floating; "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+Shift+Escape".action = toggle-keyboard-shortcuts-inhibit; "Mod+Shift+E".action = quit; "Mod+Shift+P".action = power-off-monitors; "Mod+Shift+Ctrl+T".action = toggle-debug-tint; "Mod+Shift+WheelScrollDown".action = focus-workspace-down; "Mod+Shift+WheelScrollUp".action = focus-workspace-up; "Mod+WheelScrollDown".action = focus-column-right; "Mod+WheelScrollUp".action = focus-column-left; "Mod+Shift+S".action.spawn = [ (lib.getExe pkgs.bash) "-c" ''${lib.getExe pkgs.slurp} -d | ${lib.getExe pkgs.grim} -t ppm -g - - | ${lib.getExe pkgs.satty} -f - --copy-command=${lib.getExe' pkgs.wl-clipboard "wl-copy"} --actions-on-escape="save-to-clipboard,exit"'' ]; "Mod+S".action.screenshot = { }; "XF86MonBrightnessDown".action.spawn = [ (lib.getExe pkgs.brightnessctl) "set" "5%-" ]; "XF86MonBrightnessUp".action.spawn = [ (lib.getExe pkgs.brightnessctl) "set" "+5%" ]; "XF86AudioLowerVolume".action.spawn = [ (lib.getExe' pkgs.wireplumber "wpctl") "set-volume" "@DEFAULT_AUDIO_SINK@" "2%-" ]; "XF86AudioRaiseVolume".action.spawn = [ (lib.getExe' pkgs.wireplumber "wpctl") "set-volume" "@DEFAULT_AUDIO_SINK@" "2%+" ]; } // windowMoves; animations = let vm = { kind.spring = { damping-ratio = 0.75; stiffness = 200; epsilon = 0.0001; }; }; in { horizontal-view-movement = vm; workspace-switch = vm; window-resize = vm; window-open = { kind.easing = { duration-ms = 200; curve = "linear"; }; custom-shader = '' vec4 open_color(vec3 coords_geo, vec3 size_geo) { vec3 coords_tex = niri_geo_to_tex * coords_geo; vec4 color = texture2D(niri_tex, coords_tex.st); vec2 coords = (coords_geo.xy - vec2(0.5, 0.5)) * size_geo.xy * 2.0; coords = coords / length(size_geo.xy); float p = niri_clamped_progress; if (p * p <= dot(coords, coords)) color = vec4(0.0); return color; } ''; }; }; }; }; }; }