From d0c8e279caec60de129540aee55e702e44a398e9 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 1 Sep 2025 06:24:31 -0500 Subject: [PATCH 1/2] ugh --- cachix/cachix/niri.nix | 13 ++++ home/home.nix | 4 +- home/modules/niri.nix | 135 +++++++++++++++++++++++++++++--------- modules/desktop.nix | 112 ++++++++++++++++++++++++------- pkgs/desktop-packages.nix | 1 + scripts/nirilof | 15 +++++ 6 files changed, 226 insertions(+), 54 deletions(-) create mode 100644 cachix/cachix/niri.nix create mode 100755 scripts/nirilof diff --git a/cachix/cachix/niri.nix b/cachix/cachix/niri.nix new file mode 100644 index 0000000..08bca63 --- /dev/null +++ b/cachix/cachix/niri.nix @@ -0,0 +1,13 @@ + +{ + nix = { + settings = { + substituters = [ + "https://niri.cachix.org" + ]; + trusted-public-keys = [ + "niri.cachix.org-1:Wv0OmO7PsuocRKzfDoJ3mulSl7Z6oezYhGhR+3W2964=" + ]; + }; + }; +} diff --git a/home/home.nix b/home/home.nix index b0c4408..ca45aaa 100644 --- a/home/home.nix +++ b/home/home.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, inputs, ... }: +{ config, lib, pkgs, inputs, niri, ... }: let laptop = builtins.readFile "/etc/hostname" == '' @@ -1492,7 +1492,7 @@ in { padding.y = 10; dynamic_padding = true; }; - terminal.shell.program = "fish"; + terminal.shell.program = "nu"; font = { normal = { family = "VictorMono Nerd Font"; diff --git a/home/modules/niri.nix b/home/modules/niri.nix index 5ae5d7b..2c904df 100644 --- a/home/modules/niri.nix +++ b/home/modules/niri.nix @@ -1,25 +1,89 @@ -{ config, lib, pkgs, ... }: +{ config, lib, pkgs, niri, ... }: let laptop = builtins.readFile "/etc/hostname" == "syl\n"; + cosmic-extra-niri = pkgs.writeShellScriptBin "cosmic-extra-niri" '' +set -e + +# From: https://people.debian.org/~mpitt/systemd.conf-2016-graphical-session.pdf + +if command -v systemctl >/dev/null; then + # robustness: if the previous graphical session left some failed units, + # reset them so that they don't break this startup + for unit in $(systemctl --user --no-legend --state=failed --plain list-units | cut -f1 -d' '); do + partof="$(systemctl --user show -p PartOf --value "$unit")" + for target in cosmic-session.target graphical-session.target; do + if [ "$partof" = "$target" ]; then + systemctl --user reset-failed "$unit" + break + fi + done + done +fi + +# use the user's preferred shell to acquire environment variables +# see: https://github.com/pop-os/cosmic-session/issues/23 +if [ -n "''${SHELL}" ]; then + # --in-login-shell: our flag to indicate that we don't need to recurse any further + if [ "''${1}" != "--in-login-shell" ]; then + # `exec -l`: like `login`, prefixes $SHELL with a hyphen to start a login shell + exec bash -c "''${0} --in-login-shell" + fi +fi + +export XDG_CURRENT_DESKTOP="''${XDG_CURRENT_DESKTOP:=niri}" +export XDG_SESSION_TYPE="''${XDG_SESSION_TYPE:=wayland}" +export XCURSOR_THEME="''${XCURSOR_THEME:=Cosmic}" +export _JAVA_AWT_WM_NONREPARENTING=1 +export GDK_BACKEND=wayland,x11 +export MOZ_ENABLE_WAYLAND=1 +export QT_QPA_PLATFORM="wayland;xcb" +export QT_AUTO_SCREEN_SCALE_FACTOR=1 +export QT_ENABLE_HIGHDPI_SCALING=1 + +if command -v systemctl >/dev/null; then + # set environment variables for new units started by user service manager + systemctl --user import-environment XDG_SESSION_TYPE XDG_CURRENT_DESKTOP +fi +# Run cosmic-session +if [[ -z "''${DBUS_SESSION_BUS_ADDRESS}" ]]; then + exec dbus-run-session -- ${pkgs.cosmic-session}/bin/cosmic-session niri +else + exec ${pkgs.cosmic-session}/bin/cosmic-session niri +fi + ''; in { + home.packages = with pkgs; [ + cosmic-extra-niri + ]; programs.niri = { - enable = true; + # enable = true; settings = { - binds = { + prefer-no-csd = true; + binds = with config.lib.niri.actions; { "XF86AudioRaiseVolume".action.spawn = ["volup"]; "XF86AudioLowerVolume".action.spawn = ["voldown"]; - "Mod+E".action.spawn = "emacslof"; - "Mod+B".action.spawn = "qblof"; - "Mod+Shift+Q".action = quit; - "Mod+O".action = toggle-overview; - "Mod+F".action = fullscreen-window; - "Mod+M".action = toggle-windowed-fullscreen; - "Mod+C".action = close-window; - "Mod+Left".action = focus-column-left; - "Mod+Right".action = focus-column-right; + "Super+E".action.spawn = "nu nirilof emacs 'emacslient -c'"; + "Super+Return".action.spawn = "alacritty"; + "Super+B".action.spawn = "nu nirilof org.qutebrowser.qutebrowser qutebrowser"; + "Super+Space".action.spawn = "cosmic-launcher"; + "Super+Shift+Q".action = quit; + "Super+O".action = toggle-overview; + "Super+F".action = fullscreen-window; + "Super+Shift+F".action = toggle-windowed-fullscreen; + "Super+C".action = close-window; + "Super+P".action.spawn = "/home/chris/bin/rbw.sh"; + "Super+Left".action = focus-column-left; + "Super+H".action = focus-column-left; + "Super+Shift+H".action = move-column-left; + "Super+Right".action = focus-column-right; + "Super+L".action = focus-column-right; + "Super+Shift+L".action = move-column-right; + "Super+Ctrl+L".action = set-column-width "+10%"; + "Super+Ctrl+H".action = set-column-width "-10%"; + "Super+M".action = set-column-width "95%"; }; spawn-at-startup = [ { argv = ["waybar"]; } @@ -38,27 +102,29 @@ in }; }; window-rules = [ - all = { + { geometry-corner-radius = { - top-left = 18; - top-right = 18; - bottom-left = 18; - bottom-right = 18; + top-left = 16.0; + top-right = 16.0; + bottom-left = 16.0; + bottom-right = 16.0; }; - }; - emacs = { - matches.app-id = "emacs"; + clip-to-geometry = true; + draw-border-with-background = false; + } + { + matches = [ {app-id = "emacs";} ]; open-on-workspace = "main"; - }; - browser = { - matches.app-id = "org.qutebrowser.qutebrowser"; + } + { + matches = [{app-id = "org.qutebrowser.qutebrowser";}]; open-on-workspace = "main"; - }; - cosmic-files = { - matches.app-id = "com.system76.CosmicFiles"; + } + { + matches = [{app-id = "com.system76.CosmicFiles";}]; open-on-workspace = "main"; open-floating = true; - }; + } ]; layout = { gaps = 15; @@ -71,11 +137,20 @@ in shadow = { enable = true; draw-behind-window = false; + inactive-color = "#00000000"; + softness = 10; + spread = 15; }; border = { + enable = false; + width = 4; + active = { color = "#57c7ff"; }; + inactive = { color = "#5af78e"; }; + }; + focus-ring = { enable = true; width = 4; - + active = { color = "#5af78e"; }; }; }; screenshot-path = "~/pics/screenshot_%Y-%m-%d_%H-%M-%S.png"; @@ -87,11 +162,11 @@ in outputs = { "eDP-1" = { enable = true; + name = "A"; mode = { height = 1504; width = 2256; - refresh = 60; - name = "A"; + refresh = 60.0; }; }; }; diff --git a/modules/desktop.nix b/modules/desktop.nix index 1f124fc..0538dbd 100644 --- a/modules/desktop.nix +++ b/modules/desktop.nix @@ -77,30 +77,98 @@ in }; services.displayManager.cosmic-greeter = { - enable = false; + enable = true; }; - services.greetd = { - enable = true; - settings = rec { - initial_session = { - command = "uwsm start hyprland-uwsm.desktop"; - user = "chris"; - }; - default_session = { - command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time -r --window-padding 2 --cmd 'uwsm start hyprland-uwsm.desktop' -s /etc/greetd/environments"; - user = "greeter"; - }; - cosmic_session = { - command = "start-cosmic"; - user = "chris"; - }; - hyprland_session = { - command = "uwsm start hyprland-uwsm.desktop"; - user = "chris"; - }; - }; - }; + # services.greetd = { + # enable = true; + # settings = rec { + # initial_session = { + # command = "uwsm start hyprland-uwsm.desktop"; + # user = "chris"; + # }; + # default_session = { + # command = "${pkgs.greetd.tuigreet}/bin/tuigreet --time -r --window-padding 2 --cmd 'uwsm start hyprland-uwsm.desktop' -s /etc/greetd/environments"; + # user = "greeter"; + # }; + # cosmic_session = { + # command = "start-cosmic"; + # user = "chris"; + # }; + # hyprland_session = { + # command = "uwsm start hyprland-uwsm.desktop"; + # user = "chris"; + # }; + # }; + # }; + + services.displayManager.sessionPackages = [ + ((pkgs.writeTextFile { + name = "cosmic-on-niri"; + destination = "/share/wayland-sessions/COSMIC-on-niri.desktop"; + text = '' + [Desktop Entry] + Name=COSMIC-on-niri + Comment=This session logs you into the COSMIC desktop on niri + Type=Application + DesktopNames=niri + Exec=${pkgs.writeShellApplication { + name = "start-cosmic-ext-niri"; + runtimeInputs = [ pkgs.systemd pkgs.dbus pkgs.cosmic-session pkgs.bash pkgs.coreutils ]; + text = '' + set -e + # From: https://people.debian.org/~mpitt/systemd.conf-2016-graphical-session.pdf + if command -v systemctl >/dev/null; then + # robustness: if the previous graphical session left some failed units, + # reset them so that they don't break this startup + for unit in $(systemctl --user --no-legend --state=failed --plain list-units | cut -f1 -d' '); do + partof="$(systemctl --user show -p PartOf --value "$unit")" + for target in cosmic-session.target graphical-session.target; do + if [ "$partof" = "$target" ]; then + systemctl --user reset-failed "$unit" + break + fi + done + done + fi + # use the user's preferred shell to acquire environment variables + # see: https://github.com/pop-os/cosmic-session/issues/23 + if [ -n "''${SHELL:-}" ]; then + # --in-login-shell: our flag to indicate that we don't need to recurse any further + if [ "''${1:-}" != "--in-login-shell" ]; then + # `exec -l`: like `login`, prefixes $SHELL with a hyphen to start a login shell + exec bash -c "exec -l ${"'"}''${SHELL}' -c ${"'"}''${0} --in-login-shell'" + fi + fi + export XDG_CURRENT_DESKTOP="''${XDG_CURRENT_DESKTOP:=niri}" + export XDG_SESSION_TYPE="''${XDG_SESSION_TYPE:=wayland}" + export XCURSOR_THEME="''${XCURSOR_THEME:=Cosmic}" + export _JAVA_AWT_WM_NONREPARENTING=1 + export GDK_BACKEND=wayland,x11 + export MOZ_ENABLE_WAYLAND=1 + export QT_QPA_PLATFORM="wayland;xcb" + export QT_AUTO_SCREEN_SCALE_FACTOR=1 + export QT_ENABLE_HIGHDPI_SCALING=1 + if command -v systemctl >/dev/null; then + # set environment variables for new units started by user service manager + systemctl --user import-environment XDG_SESSION_TYPE XDG_CURRENT_DESKTOP + fi + # Run cosmic-session + if [[ -z "''${DBUS_SESSION_BUS_ADDRESS}" ]]; then + exec dbus-run-session -- cosmic-session niri + else + exec cosmic-session niri + fi + ''; + }}/bin/start-cosmic-ext-niri + ''; + } + + ).overrideAttrs + (old: { + passthru.providedSessions = [ "COSMIC-on-niri" ]; + })) + ]; programs.regreet = { enable = true; }; diff --git a/pkgs/desktop-packages.nix b/pkgs/desktop-packages.nix index 7d0ae73..4a4b6d4 100644 --- a/pkgs/desktop-packages.nix +++ b/pkgs/desktop-packages.nix @@ -173,6 +173,7 @@ esptool wireguard-tools # cosmic-ext-examine + cosmic-settings aider-chat wgsl-analyzer ]; diff --git a/scripts/nirilof b/scripts/nirilof new file mode 100755 index 0000000..7ee49ce --- /dev/null +++ b/scripts/nirilof @@ -0,0 +1,15 @@ +#/usr/bin/env nu + +def main [app: string, command: string] { + let open = try { + niri msg --json windows | from json | where app_id == $app | get id | first + } catch { + 0 + } + + if $open > 0 { + niri msg action focus-window --id $open + } else { + bash -c $"($command) &" + } +} From d6d16bfe7f54d341a618c23be218f45aed28e95a Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Tue, 2 Sep 2025 06:33:13 -0500 Subject: [PATCH 2/2] the core of niri is done --- home/home.nix | 12 ++++++------ home/modules/niri.nix | 40 ++++++++++++++++++++++++++++++++------- pkgs/desktop-packages.nix | 1 + 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/home/home.nix b/home/home.nix index ca45aaa..8f08377 100644 --- a/home/home.nix +++ b/home/home.nix @@ -669,9 +669,9 @@ in { output = [ "DP-1" "eDP-1" ]; position = if laptop then "bottom" else "top"; height = 15; - width = if laptop then 1400 else 2200; + width = if laptop then 1450 else 2200; # Choose the order of the modules "custom/wintitle", - modules-left = [ "hyprland/workspaces" "hyprland/window" ]; + modules-left = [ "niri/workspaces" "niri/window" ]; modules-center = [ "clock" ]; modules-right = [ "cpu" "memory" "pulseaudio" "backlight" "battery" "tray" ]; @@ -679,12 +679,12 @@ in { margin-bottom = if laptop then 4 else 0; margin-left = 6; margin-right = 6; - "hyprland/window" = { format = "{title}"; icon = true; }; + "niri/window" = { format = "{title}"; icon = true; }; workspaces = { format = " {name} "; }; - "hyprland/workspaces" = { + "niri/workspaces" = { format = "{icon}"; format-icons = { - "1" = ""; + "main" = ""; "2" = ""; "3" = "󰈙"; "4" = "󰭹"; @@ -825,7 +825,7 @@ in { padding-bottom: 2px; padding-left: 5px; padding-right: 5px; - margin-right: 50px; + margin-right: 0px; background: @backtransparent; box-shadow: 5px 5px 4px 4px #202020; border-radius: 20px; diff --git a/home/modules/niri.nix b/home/modules/niri.nix index 2c904df..d478029 100644 --- a/home/modules/niri.nix +++ b/home/modules/niri.nix @@ -62,18 +62,23 @@ in # enable = true; settings = { prefer-no-csd = true; - binds = with config.lib.niri.actions; { - "XF86AudioRaiseVolume".action.spawn = ["volup"]; - "XF86AudioLowerVolume".action.spawn = ["voldown"]; - "Super+E".action.spawn = "nu nirilof emacs 'emacslient -c'"; + binds = with config.lib.niri.actions; let + in { + "XF86AudioRaiseVolume".action.spawn = ["pamixer" "--allow-boost" "-i" "5"]; + "XF86AudioLowerVolume".action.spawn = ["pamixer" "--allow-boost" "-d" "5"]; + "Super+E".action.spawn = ["${pkgs.nushell}/bin/nu" "/home/chris/nirilof emacs 'emacslient -c'"]; "Super+Return".action.spawn = "alacritty"; - "Super+B".action.spawn = "nu nirilof org.qutebrowser.qutebrowser qutebrowser"; + "Super+B".action = spawn ["${pkgs.nushell}/bin/nu" "/home/chris/nirilof org.qutebrowser.qutebrowser qutebrowser"]; "Super+Space".action.spawn = "cosmic-launcher"; + "Super+V".action= spawn ["${pkgs.fish}/bin/fish" "-c" "${pkgs.cliphist}/bin/cliphist list | ${pkgs.rofi-wayland}/bin/rofi -p '󱃔 ' -dmenu | ${pkgs.cliphist}/bin/cliphist decode | ${pkgs.wl-clipboard}/bin/wl-copy"]; + "Super+I".action.spawn = ["alacritty" "--class" "btm" "-e" "btm"]; + "Super+A".action.spawn = ["alacritty" "--class" "pulsemixer" "-e" "pulsemixer"]; "Super+Shift+Q".action = quit; "Super+O".action = toggle-overview; "Super+F".action = fullscreen-window; "Super+Shift+F".action = toggle-windowed-fullscreen; "Super+C".action = close-window; + "Super+Shift+C".action = center-window; "Super+P".action.spawn = "/home/chris/bin/rbw.sh"; "Super+Left".action = focus-column-left; "Super+H".action = focus-column-left; @@ -83,10 +88,15 @@ in "Super+Shift+L".action = move-column-right; "Super+Ctrl+L".action = set-column-width "+10%"; "Super+Ctrl+H".action = set-column-width "-10%"; - "Super+M".action = set-column-width "95%"; + "Super+M".action = maximize-column; + "Super+W".action = switch-preset-column-width; + "Super+Comma".action = consume-or-expel-window-left; + "Super+Period".action = consume-or-expel-window-right; }; spawn-at-startup = [ + { argv = ["${pkgs.xwayland-satellite}/bin/xwayland-satellite"]; } { argv = ["waybar"]; } + { argv = ["cosmic-osd"]; } { argv = ["kwalled6"]; } { argv = ["swww-daemon"]; } { argv = ["rbw-agent"]; } @@ -122,11 +132,27 @@ in } { matches = [{app-id = "com.system76.CosmicFiles";}]; - open-on-workspace = "main"; + open-floating = true; + } + { + matches = [{app-id = "btm";}]; + open-floating = true; + default-column-width.proportion = 0.7; + default-window-height.proportion = 0.7; + } + { + matches = [{app-id = "pulsemixer";}]; open-floating = true; } ]; layout = { + center-focused-column = "never"; + preset-column-widths = [ + { proportion = 1. / 3.; } + { proportion = 1. / 2.; } + { proportion = 2. / 3.; } + { proportion = 1. / 1.; } + ]; gaps = 15; struts = { bottom = 5; diff --git a/pkgs/desktop-packages.nix b/pkgs/desktop-packages.nix index 4a4b6d4..8af0df5 100644 --- a/pkgs/desktop-packages.nix +++ b/pkgs/desktop-packages.nix @@ -174,6 +174,7 @@ wireguard-tools # cosmic-ext-examine cosmic-settings + xwayland-satellite aider-chat wgsl-analyzer ];