From 28705314a42e6e98195b8aa5efb8c41f200df4ae Mon Sep 17 00:00:00 2001 From: "molly.computer" Date: Wed, 12 Aug 2026 15:40:28 -0400 Subject: [PATCH] replace desktop shell with Noctalia --- flake.lock | 33 ++++ flake.nix | 7 + home/apps.nix | 18 --- home/default.nix | 9 +- home/ironbar.nix | 297 ------------------------------------ home/niri.nix | 57 +++++-- home/noctalia.nix | 111 ++++++++++++++ home/satty.nix | 42 +++++ home/stylix.nix | 18 ++- home/swayidle.nix | 2 +- home/swayosd.nix | 29 ++++ home/wlsunset.nix | 24 +++ hosts/chi/configuration.nix | 2 +- modules/common.nix | 2 + 14 files changed, 314 insertions(+), 337 deletions(-) delete mode 100644 home/ironbar.nix create mode 100644 home/noctalia.nix create mode 100644 home/satty.nix create mode 100644 home/swayosd.nix create mode 100644 home/wlsunset.nix diff --git a/flake.lock b/flake.lock index bedaf2a..e79d28a 100644 --- a/flake.lock +++ b/flake.lock @@ -498,6 +498,38 @@ "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1786106723, + "narHash": "sha256-CgKDSHL6rqAAQkkvg1xaZDQXb77+4XW73iGcUMJ+2w0=", + "rev": "f13ff45afd1bb73e640eaa08a7066dbed07e3238", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/unstable/nixos-26.11pre1049422.f13ff45afd1b/nixexprs.tar.zst" + }, + "original": { + "type": "tarball", + "url": "https://channels.nixos.org/nixos-unstable/nixexprs.tar.zst" + } + }, + "noctalia": { + "inputs": { + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1786546835, + "narHash": "sha256-w1LREBMogQKZnSUN+zFjRm+vhFnPNepCMzo5Kee4f0M=", + "owner": "noctalia-dev", + "repo": "noctalia", + "rev": "8403cb987adfb9d334b0c4d7e46a988d98ee3aa3", + "type": "github" + }, + "original": { + "owner": "noctalia-dev", + "ref": "cachix", + "repo": "noctalia", + "type": "github" + } + }, "nur": { "inputs": { "flake-parts": [ @@ -532,6 +564,7 @@ "nix-doom-emacs-unstraightened": "nix-doom-emacs-unstraightened", "nixos-hardware": "nixos-hardware", "nixpkgs": "nixpkgs_2", + "noctalia": "noctalia", "stylix": "stylix", "treefmt-nix": "treefmt-nix_2" } diff --git a/flake.nix b/flake.nix index 39d6610..24df3fa 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,11 @@ { description = "NixOS configuration for chi"; + nixConfig = { + extra-substituters = ["https://noctalia.cachix.org"]; + extra-trusted-public-keys = ["noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="]; + }; + inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; home-manager = { @@ -30,6 +35,7 @@ url = "github:danth/stylix"; inputs.nixpkgs.follows = "nixpkgs"; }; + noctalia.url = "github:noctalia-dev/noctalia/cachix"; hunk = { url = "github:modem-dev/hunk"; inputs.nixpkgs.follows = "nixpkgs"; @@ -67,6 +73,7 @@ home-manager.sharedModules = [ stylix.homeModules.stylix niri.homeModules.stylix + inputs.noctalia.homeModules.default inputs.hunk.homeManagerModules.default ]; home-manager.users.mollyw = import ./home; diff --git a/home/apps.nix b/home/apps.nix index 42ff016..63c5170 100644 --- a/home/apps.nix +++ b/home/apps.nix @@ -166,24 +166,6 @@ in { }; btop.enable = true; - - # Application launcher - vicinae = { - enable = true; - systemd = { - enable = true; - autoStart = true; - }; - settings = { - close_on_focus_loss = true; - pop_to_root_on_close = true; - launcher_window = { - layer_shell = { - enabled = true; - }; - }; - }; - }; }; home.packages = [pkgs.difftastic]; diff --git a/home/default.nix b/home/default.nix index be77e58..5721def 100644 --- a/home/default.nix +++ b/home/default.nix @@ -5,14 +5,17 @@ ./foot.nix ./khal.nix ./niri.nix + ./noctalia.nix ./oh-my-pi.nix ./opencode.nix ./scripts.nix ./shell.nix + ./satty.nix ./swayidle.nix + ./swayosd.nix ./stylix.nix ./tablet.nix - ./ironbar.nix + ./wlsunset.nix ]; _module.args.wallpaper = ../wallpapers/wp2002041.jpg; @@ -23,11 +26,7 @@ packages = with pkgs; [ # Niri ecosystem - mako - swaylock xwayland-satellite - swaybg - brightnessctl playerctl equibop diff --git a/home/ironbar.nix b/home/ironbar.nix deleted file mode 100644 index 3dc56a6..0000000 --- a/home/ironbar.nix +++ /dev/null @@ -1,297 +0,0 @@ -{ - config, - pkgs, - khalNextEventRead, - weatherDc, - ... -}: let - colors = config.lib.stylix.colors; -in { - home.packages = [pkgs.ironbar]; - - xdg.configFile."ironbar/config.json".text = builtins.toJSON { - position = "top"; - anchor_to_edges = true; - height = 44; - start = [ - { - type = "custom"; - class = "tablet-controls"; - bar = [ - { - type = "button"; - label = "󰀻"; - tooltip = "Applications"; - on_click = "!vicinae vicinae://toggle"; - } - { - type = "button"; - label = "󰕰"; - tooltip = "Overview"; - on_click = "!niri msg action toggle-overview"; - } - { - type = "button"; - label = "󰌌"; - tooltip = "On-screen keyboard"; - on_click = "!systemctl --user kill --signal=RTMIN tablet-keyboard.service"; - } - { - type = "button"; - label = "󰅖"; - tooltip = "Close window"; - on_click = "!niri msg action close-window"; - } - { - type = "button"; - label = "󰌾"; - tooltip = "Lock"; - on_click = "!swaylock"; - } - ]; - } - { - type = "workspaces"; - format = "{index}"; - sort = "index"; - on_scroll_up = "niri msg action focus-workspace-up"; - on_scroll_down = "niri msg action focus-workspace-down"; - } - { - type = "focused"; - show_icon = false; - truncate = { - mode = "end"; - max_length = 25; - }; - } - { - type = "music"; - format = "{title} / {artist}"; - show_status_icon = true; - icon_size = 16; - cover_image_size = 128; - marquee = { - enable = true; - max_length = 40; - scroll_speed = 0.5; - on_hover = "pause"; - }; - truncate_popup_title = { - mode = "end"; - max_length = 60; - }; - icons = { - play = ""; - pause = ""; - prev = "󰒮"; - next = "󰒭"; - volume = "󰕾"; - track = "󰎈"; - album = "󰀥"; - artist = "󰠃"; - }; - } - ]; - center = [ - { - type = "clock"; - format = "%m/%d %I:%M %p"; - } - { - type = "script"; - name = "khal"; - cmd = "${khalNextEventRead}"; - mode = "poll"; - interval = 60000; - tooltip = "Next upcoming event from khal"; - on_click_left = "foot -e ikhal"; - } - ]; - end = [ - { - type = "volume"; - name = "mic"; - show_sinks = false; - format = "{icon} {percentage}%"; - mute_format = "󰍭 muted"; - icons.mic_volume = "󰍬"; - icons.mic_muted = "󰍭"; - on_click_middle = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; - } - { - type = "volume"; - show_sources = false; - format = "{icon} {percentage}%"; - mute_format = "󰖁 muted"; - icons.muted = "󰖁"; - on_click_middle = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; - } - { - type = "battery"; - show_icon = false; - format = "󰁹"; - tooltip = "{{30000:echo \"$(cat /sys/class/power_supply/BAT1/capacity)% ($(cat /sys/class/power_supply/BAT1/status))\"}}"; - profiles = { - charging = { - when = { - percent = 100; - charging = true; - }; - format = "󰂄"; - }; - p90 = { - when = { - percent = 90; - charging = false; - }; - format = "󰂂"; - }; - p70 = { - when = { - percent = 70; - charging = false; - }; - format = "󰂀"; - }; - p50 = { - when = { - percent = 50; - charging = false; - }; - format = "󰁾"; - }; - warning = { - when = { - percent = 30; - charging = false; - }; - format = "󰁼"; - }; - critical = { - when = { - percent = 15; - charging = false; - }; - format = "󰁺"; - }; - }; - } - { - type = "script"; - name = "weather"; - cmd = "${weatherDc}/bin/weather-dc"; - mode = "poll"; - interval = 600000; - tooltip = "Washington, DC"; - } - { - type = "tray"; - icon_size = 18; - } - ]; - }; - - xdg.configFile."ironbar/style.css".text = '' - * { - font-family: "${config.stylix.fonts.monospace.name}"; - font-size: 13px; - } - - .bar { - background-color: #${colors.base00}; - color: #${colors.base05}; - } - - #bar button { - background: none; - border: none; - border-radius: 0; - box-shadow: none; - min-width: 0; - min-height: 0; - padding: 0 12px; - } - - .tablet-controls button { - min-width: 44px; - min-height: 44px; - padding: 0; - font-size: 18px; - } - - .workspaces .item.focused { - color: #${colors.base0D}; - } - - .music .contents .icon { - color: #${colors.base0B}; - padding-right: 4px; - } - - .popup-music { - background-color: #${colors.base00}; - border: 1px solid #${colors.base02}; - border-radius: 8px; - padding: 12px; - } - - .popup-music .album-art { - border-radius: 4px; - margin-right: 12px; - } - - .popup-music .title .label { - color: #${colors.base05}; - font-weight: bold; - } - - .popup-music .album .label, - .popup-music .artist .label { - color: #${colors.base04}; - } - - .popup-music .controls button { - background: none; - border: none; - box-shadow: none; - color: #${colors.base05}; - padding: 4px 10px; - } - - .popup-music .controls button:hover { - color: #${colors.base0D}; - } - - .popup-music .volume .slider, - .popup-music .progress .slider { - min-height: 4px; - } - - .popup-music .volume .slider trough, - .popup-music .progress .slider trough { - background-color: #${colors.base02}; - border-radius: 2px; - } - - .popup-music .volume .slider highlight, - .popup-music .progress .slider highlight { - background-color: #${colors.base0D}; - border-radius: 2px; - } - - .popup-music .progress .label { - color: #${colors.base04}; - } - - .battery.warning, - .battery.profile-warning { - color: #${colors.base0A}; - } - - .battery.critical, - .battery.profile-critical { - color: #${colors.base08}; - } - ''; -} diff --git a/home/niri.nix b/home/niri.nix index 60e91c5..baf7ac4 100644 --- a/home/niri.nix +++ b/home/niri.nix @@ -1,6 +1,6 @@ { config, - wallpaper, + pkgs, ... }: { programs.niri.settings = { @@ -31,6 +31,7 @@ inactive.color = "#${config.lib.stylix.colors.base03}"; }; border.enable = false; + background-color = "transparent"; }; window-rules = [ @@ -54,13 +55,25 @@ matches = [{app-id = "net-runelite-launcher-Launcher";}]; open-floating = true; } + { + matches = [{app-id = "dev.noctalia.Noctalia";}]; + open-floating = true; + default-column-width.fixed = 1080; + default-window-height.fixed = 920; + } + ]; + + layer-rules = [ + { + matches = [{namespace = "^noctalia-wallpaper";}]; + place-within-backdrop = true; + } ]; + debug.honor-xdg-activation-with-invalid-serial = []; + spawn-at-startup = [ - {argv = ["swaybg" "--image" "${wallpaper}"];} - {argv = ["mako"];} {argv = ["xwayland-satellite"];} - {argv = ["ironbar"];} ]; screenshot-path = "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"; @@ -73,8 +86,24 @@ action.spawn = "foot"; }; "Mod+D" = { - hotkey-overlay.title = "Run Application: vicinae"; - action.spawn = ["vicinae" "vicinae://toggle"]; + repeat = false; + hotkey-overlay.title = "Open Noctalia Launcher"; + action.spawn = ["noctalia" "msg" "panel-toggle" "launcher"]; + }; + "Mod+S" = { + repeat = false; + hotkey-overlay.title = "Open Noctalia Control Center"; + action.spawn = ["noctalia" "msg" "panel-toggle" "control-center"]; + }; + "Mod+Shift+Comma" = { + repeat = false; + hotkey-overlay.title = "Open Noctalia Settings"; + action.spawn = ["noctalia" "msg" "settings-toggle"]; + }; + "Alt+Tab" = { + repeat = false; + hotkey-overlay.title = "Open Noctalia Window Switcher"; + action.spawn = ["noctalia" "msg" "window-switcher"]; }; "Mod+O" = { repeat = false; @@ -93,8 +122,8 @@ "Super+Alt+L" = { repeat = false; allow-inhibiting = false; - hotkey-overlay.title = "Lock Screen: swaylock"; - action.spawn = "swaylock"; + hotkey-overlay.title = "Lock Screen: Noctalia"; + action.spawn-sh = "${pkgs.systemd}/bin/systemctl --user start noctalia.service && ${config.programs.noctalia.package}/bin/noctalia msg session lock"; }; "Mod+Q" = { @@ -176,19 +205,19 @@ "XF86AudioRaiseVolume" = { allow-when-locked = true; - action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+ -l 1.0"; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--output-volume" "raise"]; }; "XF86AudioLowerVolume" = { allow-when-locked = true; - action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--output-volume" "lower"]; }; "XF86AudioMute" = { allow-when-locked = true; - action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--output-volume" "mute-toggle"]; }; "XF86AudioMicMute" = { allow-when-locked = true; - action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--input-volume" "mute-toggle"]; }; "XF86AudioPlay" = { @@ -210,11 +239,11 @@ "XF86MonBrightnessUp" = { allow-when-locked = true; - action.spawn = ["brightnessctl" "--class=backlight" "set" "+10%"]; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--brightness" "raise"]; }; "XF86MonBrightnessDown" = { allow-when-locked = true; - action.spawn = ["brightnessctl" "--class=backlight" "set" "10%-"]; + action.spawn = ["${pkgs.swayosd}/bin/swayosd-client" "--brightness" "lower"]; }; "Print".action.screenshot = []; diff --git a/home/noctalia.nix b/home/noctalia.nix new file mode 100644 index 0000000..20ca73a --- /dev/null +++ b/home/noctalia.nix @@ -0,0 +1,111 @@ +{ + config, + lib, + wallpaper, + ... +}: { + programs.noctalia = { + enable = true; + systemd.enable = true; + settings = { + shell = { + font_family = config.stylix.fonts.sansSerif.name; + telemetry_enabled = false; + panel = { + transparency_mode = "soft"; + borders = true; + shadow = true; + launcher_placement = "floating"; + clipboard_placement = "floating"; + launcher_position = "center"; + clipboard_position = "center"; + }; + }; + + theme.mode = "dark"; + + wallpaper = { + enabled = true; + fill_mode = "crop"; + default.path = "${wallpaper}"; + automation.enabled = false; + }; + + notification.enable_daemon = true; + + osd.kinds = { + volume = false; + brightness = false; + wifi = false; + bluetooth = false; + power_profile = false; + caffeine = false; + nightlight = false; + dnd = false; + lock_keys = false; + keyboard_layout = false; + privacy = false; + }; + + lockscreen = { + enabled = true; + blurred_desktop = true; + }; + + nightlight.enabled = false; + idle.behavior = { + lock.enabled = false; + screen-off.enabled = false; + }; + + location = { + latitude = 38.9072; + longitude = -77.0369; + }; + weather = { + enabled = true; + unit = "fahrenheit"; + }; + + bar.main = { + position = "top"; + thickness = 44; + margin_ends = 12; + margin_edge = 8; + padding = 12; + widget_spacing = 6; + reserve_space = true; + start = [ + "launcher" + "workspaces" + ]; + center = ["clock"]; + end = [ + "media" + "tray" + "notifications" + "clipboard" + "network" + "bluetooth" + "volume" + "brightness" + "battery" + "control-center" + "session" + ]; + }; + + dock.enabled = false; + desktop_widgets.enabled = false; + }; + }; + + systemd.user.services.noctalia = { + Unit = { + After = lib.mkForce ["niri.service"]; + PartOf = lib.mkForce ["niri.service"]; + ConditionEnvironment = "WAYLAND_DISPLAY"; + }; + Install.WantedBy = lib.mkForce ["niri.service"]; + }; +} diff --git a/home/satty.nix b/home/satty.nix new file mode 100644 index 0000000..4d5979a --- /dev/null +++ b/home/satty.nix @@ -0,0 +1,42 @@ +{ + config, + pkgs, + ... +}: { + programs.satty = { + enable = true; + settings = { + general = { + corner-roundness = 12; + initial-tool = "brush"; + copy-command = "${pkgs.wl-clipboard}/bin/wl-copy"; + output-filename = "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"; + early-exit = true; + }; + color-palette.palette = map (color: "#${color}") (with config.lib.stylix.colors; [ + base08 + base09 + base0A + base0B + base0C + base0D + base0E + ]); + }; + }; + + home.packages = with pkgs; [ + grim + slurp + wl-clipboard + ]; + + programs.niri.settings.binds."Mod+Print" = { + repeat = false; + hotkey-overlay.title = "Annotate Screenshot Region"; + action.spawn-sh = '' + geometry="$(${pkgs.slurp}/bin/slurp)" || exit 0 + ${pkgs.grim}/bin/grim -g "$geometry" - | ${pkgs.satty}/bin/satty --filename - + ''; + }; +} diff --git a/home/stylix.nix b/home/stylix.nix index 62d8855..666007a 100644 --- a/home/stylix.nix +++ b/home/stylix.nix @@ -12,6 +12,7 @@ in { # useGlobalPkgs forbids HM-level nixpkgs.overlays; stylix's overlays only # patch the nixos-icons and gtksourceview packages, which are unused here overlays.enable = false; + autoEnable = false; polarity = "dark"; image = wallpaper; fonts = { @@ -31,17 +32,32 @@ in { package = pkgs.noto-fonts-color-emoji; name = "Noto Color Emoji"; }; + sizes = { + applications = 12; + desktop = 10; + popups = 10; + terminal = 12; + }; }; targets = { + bat.enable = true; helix.enable = true; foot.enable = true; btop.enable = true; - vscode.enable = true; + emacs.enable = true; + fish.enable = true; + fontconfig.enable = true; + fzf.enable = true; + opencode.enable = true; + qt.enable = true; + starship.enable = true; + vscodium.enable = true; firefox = { enable = true; profileNames = ["mollyw"]; }; niri.enable = true; + noctalia.enable = true; gtk.enable = true; }; }; diff --git a/home/swayidle.nix b/home/swayidle.nix index cf062e3..e771436 100644 --- a/home/swayidle.nix +++ b/home/swayidle.nix @@ -3,7 +3,7 @@ pkgs, ... }: let - lock = "${pkgs.swaylock}/bin/swaylock -f"; + lock = "${pkgs.systemd}/bin/systemctl --user start noctalia.service && ${config.programs.noctalia.package}/bin/noctalia msg session lock"; niri = "${config.programs.niri.package}/bin/niri msg action"; in { services.swayidle = { diff --git a/home/swayosd.nix b/home/swayosd.nix new file mode 100644 index 0000000..b1f3baa --- /dev/null +++ b/home/swayosd.nix @@ -0,0 +1,29 @@ +{ + config, + pkgs, + ... +}: let + colors = config.lib.stylix.colors; + style = pkgs.writeText "swayosd.css" '' + window { + border-radius: 12px; + border: 2px solid #${colors.base0D}; + background: #${colors.base00}; + color: #${colors.base05}; + font-family: "${config.stylix.fonts.sansSerif.name}"; + } + + progressbar trough { + background: #${colors.base02}; + } + + progressbar progress { + background: #${colors.base0D}; + } + ''; +in { + services.swayosd = { + enable = true; + stylePath = style; + }; +} diff --git a/home/wlsunset.nix b/home/wlsunset.nix new file mode 100644 index 0000000..87d20aa --- /dev/null +++ b/home/wlsunset.nix @@ -0,0 +1,24 @@ +{pkgs, ...}: { + services.wlsunset = { + enable = true; + latitude = 38.9072; + longitude = -77.0369; + temperature = { + day = 6500; + night = 4000; + }; + systemdTarget = "niri.service"; + }; + + programs.niri.settings.binds."Mod+Shift+N" = { + repeat = false; + hotkey-overlay.title = "Cycle Night Light Mode"; + action.spawn = [ + "${pkgs.systemd}/bin/systemctl" + "--user" + "kill" + "--signal=USR1" + "wlsunset.service" + ]; + }; +} diff --git a/hosts/chi/configuration.nix b/hosts/chi/configuration.nix index 1b21138..0b652d2 100644 --- a/hosts/chi/configuration.nix +++ b/hosts/chi/configuration.nix @@ -124,7 +124,7 @@ powerManagement.powertop.enable = true; services.thermald.enable = true; services.fwupd.enable = true; - # UPower daemon — ironbar's battery module reads battery state over zbus + # UPower supplies battery state to the desktop shell. services.upower.enable = true; # Nix Helper (nh) — readable rebuild diffs + scheduled cleanup diff --git a/modules/common.nix b/modules/common.nix index 347dd28..42297ab 100644 --- a/modules/common.nix +++ b/modules/common.nix @@ -2,6 +2,8 @@ # Nix settings nix.settings.experimental-features = ["nix-command" "flakes"]; nix.settings.auto-optimise-store = true; + nix.settings.extra-substituters = ["https://noctalia.cachix.org"]; + nix.settings.extra-trusted-public-keys = ["noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="]; # 256 MiB download buffer: fewer stalls on large fetches (games, toolchains) nix.settings.download-buffer-size = 268435456; -- 2.51.2