diff --git a/flake.nix b/flake.nix index dabb072d..54381f04 100644 --- a/flake.nix +++ b/flake.nix @@ -11,284 +11,47 @@ }; }; - outputs = - { - self, - nixpkgs, - systems, - quickshell, - ... - }: - let - eachSystem = nixpkgs.lib.genAttrs (import systems); - in - { - formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); + outputs = { + self, + nixpkgs, + systems, + quickshell, + ... + }: let + eachSystem = nixpkgs.lib.genAttrs (import systems); + in { + formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); - packages = eachSystem ( - system: - let - pkgs = nixpkgs.legacyPackages.${system}; - qs = quickshell.packages.${system}.default.override { + packages = eachSystem ( + system: let + pkgs = nixpkgs.legacyPackages.${system}; + in { + default = pkgs.callPackage ./nix/package.nix { + version = self.rev or self.dirtyRev or "dirty"; + quickshell = quickshell.packages.${system}.default.override { withX11 = false; withI3 = true; }; - - runtimeDeps = - with pkgs; - [ - bash - bluez - brightnessctl - cava - cliphist - coreutils - ddcutil - file - findutils - libnotify - matugen - networkmanager - wlsunset - wl-clipboard - ] - ++ lib.optionals (pkgs.stdenv.hostPlatform.isx86_64) [ gpu-screen-recorder ]; - - fontconfig = pkgs.makeFontsConf { - fontDirectories = [ - pkgs.roboto - pkgs.inter-nerdfont - ]; - }; - in - { - default = pkgs.stdenv.mkDerivation { - pname = "noctalia-shell"; - version = self.rev or self.dirtyRev or "dirty"; - src = ./.; - - nativeBuildInputs = [ - pkgs.gcc - pkgs.makeWrapper - pkgs.qt6.wrapQtAppsHook - ]; - buildInputs = [ - qs - pkgs.xkeyboard_config - pkgs.qt6.qtbase - ]; - propagatedBuildInputs = runtimeDeps; - - installPhase = '' - mkdir -p $out/share/noctalia-shell - cp -r ./* $out/share/noctalia-shell - - makeWrapper ${qs}/bin/qs $out/bin/noctalia-shell \ - --prefix PATH : "${pkgs.lib.makeBinPath runtimeDeps}" \ - --set FONTCONFIG_FILE "${fontconfig}" \ - --add-flags "-p $out/share/noctalia-shell" - ''; - - meta = { - description = "A sleek and minimal desktop shell thoughtfully crafted for Wayland, built with Quickshell."; - homepage = "https://github.com/noctalia-dev/noctalia-shell"; - license = pkgs.lib.licenses.mit; - mainProgram = "noctalia-shell"; - }; - }; - } - ); - - defaultPackage = eachSystem (system: self.packages.${system}.default); - - homeModules.default = - { - config, - lib, - pkgs, - ... - }: - let - cfg = config.programs.noctalia-shell; - defaultSettings = builtins.fromJSON (builtins.readFile ./Assets/settings-default.json); - - # Deep merge user settings with defaults - mergedSettings = - if cfg.settings == null then - defaultSettings - else if builtins.isAttrs cfg.settings then - lib.recursiveUpdate defaultSettings cfg.settings - else - cfg.settings; # Pass through strings/paths as-is - in - { - options.programs.noctalia-shell = { - enable = lib.mkEnableOption "Noctalia shell configuration"; - - settings = lib.mkOption { - type = - with lib.types; - nullOr (oneOf [ - attrs - str - path - ]); - default = null; - example = lib.literalExpression '' - { - bar = { - position = "bottom"; - floating = true; - backgroundOpacity = 0.95; - }; - general = { - animationSpeed = 1.5; - radiusRatio = 1.2; - }; - colorSchemes = { - darkMode = true; - useWallpaperColors = true; - }; - } - ''; - description = '' - Noctalia shell configuration settings as an attribute set, string - or filepath, to be written to ~/.config/noctalia/settings.json. - When provided as an attribute set, it will be deep-merged with - the default settings. - ''; - }; - - colors = lib.mkOption { - type = - with lib.types; - nullOr (oneOf [ - attrs - str - path - ]); - default = null; - example = lib.literalExpression '' - { - mError = "#dddddd"; - mOnError = "#111111"; - mOnPrimary = "#111111"; - mOnSecondary = "#111111"; - mOnSurface = "#828282"; - mOnSurfaceVariant = "#5d5d5d"; - mOnTertiary = "#111111"; - mOutline = "#3c3c3c"; - mPrimary = "#aaaaaa"; - mSecondary = "#a7a7a7"; - mShadow = "#000000"; - mSurface = "#111111"; - mSurfaceVariant = "#191919"; - mTertiary = "#cccccc"; - } - ''; - description = '' - Noctalia shell color configuration as an attribute set, string - or filepath, to be written to ~/.config/noctalia/colors.json. - ''; - }; - }; - - config = - let - restart = '' - ${pkgs.systemd}/bin/systemctl --user try-restart noctalia-shell.service 2>/dev/null || true - ''; - in - lib.mkIf cfg.enable { - xdg.configFile = { - "noctalia/settings.json" = { - onChange = restart; - } - // ( - if builtins.isAttrs mergedSettings then - { text = builtins.toJSON mergedSettings + "\n"; } - else if builtins.isString mergedSettings then - { text = mergedSettings; } - else - { source = mergedSettings; } - ); - "noctalia/colors.json" = lib.mkIf (cfg.colors != null) ( - { - onChange = restart; - } - // ( - if builtins.isAttrs cfg.colors then - { text = builtins.toJSON cfg.colors; } - else if builtins.isString cfg.colors then - { text = cfg.colors; } - else - { source = cfg.colors; } - ) - ); - }; - }; }; + } + ); - nixosModules.default = - { - config, - lib, - pkgs, - ... - }: - let - cfg = config.services.noctalia-shell; - in - { - options.services.noctalia-shell = { - enable = lib.mkEnableOption "Noctalia shell systemd service"; + defaultPackage = eachSystem (system: self.packages.${system}.default); - package = lib.mkOption { - type = lib.types.package; - default = self.packages.${pkgs.system}.default; - description = "The noctalia-shell package to use"; - }; - - target = lib.mkOption { - type = lib.types.str; - default = "graphical-session.target"; - example = "hyprland-session.target"; - description = "The systemd target for the noctalia-shell service."; - }; - }; - - config = lib.mkIf cfg.enable { - systemd.user.services.noctalia-shell = { - description = "Noctalia Shell - Wayland desktop shell"; - documentation = [ "https://github.com/noctalia-dev/noctalia-shell" ]; - after = [ cfg.target ]; - partOf = [ cfg.target ]; - wantedBy = [ cfg.target ]; - restartTriggers = [ cfg.package ]; - - environment = { - PATH = lib.mkForce null; - }; - - unitConfig = { - StartLimitIntervalSec = 60; - StartLimitBurst = 3; - }; - - serviceConfig = { - ExecStart = "${cfg.package}/bin/noctalia-shell"; - Restart = "on-failure"; - RestartSec = 3; - TimeoutStartSec = 10; - TimeoutStopSec = 5; - Environment = [ - "NOCTALIA_SETTINGS_FALLBACK=%h/.config/noctalia/gui-settings.json" - ]; - }; - }; - - environment.systemPackages = [ cfg.package ]; - }; - }; + homeModules.default = { + pkgs, + lib, + ... + }: { + imports = [./nix/home-module.nix]; + programs.noctalia-shell.app2unit.package = + lib.mkDefault + nixpkgs.legacyPackages.${pkgs.system}.app2unit; }; + + nixosModules.default = {pkgs, ...}: { + imports = [./nix/nixos-module.nix]; + services.noctalia-shell.package = self.packages.${pkgs.system}.default; + }; + }; } diff --git a/nix/home-module.nix b/nix/home-module.nix new file mode 100644 index 00000000..08410911 --- /dev/null +++ b/nix/home-module.nix @@ -0,0 +1,114 @@ +{ + config, + lib, + pkgs, + ... +}: let + cfg = config.programs.noctalia-shell; + defaultSettings = builtins.fromJSON (builtins.readFile ../Assets/settings-default.json); + extractAttrs = x: + if builtins.isAttrs x + then x + else if builtins.isString x + then builtins.fromJson x + else builtins.fromJson (builtins.readFile x); +in { + options.programs.noctalia-shell = { + enable = lib.mkEnableOption "Noctalia shell configuration"; + + settings = lib.mkOption { + type = with lib.types; + nullOr (oneOf [ + attrs + str + path + ]); + default = {}; + apply = x: lib.recursiveUpdate defaultSettings (extractAttrs x); + example = lib.literalExpression '' + { + bar = { + position = "bottom"; + floating = true; + backgroundOpacity = 0.95; + }; + general = { + animationSpeed = 1.5; + radiusRatio = 1.2; + }; + colorSchemes = { + darkMode = true; + useWallpaperColors = true; + }; + } + ''; + description = '' + Noctalia shell configuration settings as an attribute set, string + or filepath, to be written to ~/.config/noctalia/settings.json. + When provided as an attribute set, it will be deep-merged with + the default settings. + ''; + }; + + colors = lib.mkOption { + type = with lib.types; + nullOr (oneOf [ + attrs + str + path + ]); + default = {}; + apply = extractAttrs; + example = lib.literalExpression '' + { + mError = "#dddddd"; + mOnError = "#111111"; + mOnPrimary = "#111111"; + mOnSecondary = "#111111"; + mOnSurface = "#828282"; + mOnSurfaceVariant = "#5d5d5d"; + mOnTertiary = "#111111"; + mOutline = "#3c3c3c"; + mPrimary = "#aaaaaa"; + mSecondary = "#a7a7a7"; + mShadow = "#000000"; + mSurface = "#111111"; + mSurfaceVariant = "#191919"; + mTertiary = "#cccccc"; + } + ''; + description = '' + Noctalia shell color configuration as an attribute set, string + or filepath, to be written to ~/.config/noctalia/colors.json. + ''; + }; + + app2unit.package = lib.mkOption { + type = lib.types.package; + description = '' + The app2unit package to use when appLauncher.useApp2Unit is enabled. + ''; + }; + }; + + config = let + restart = '' + ${pkgs.systemd}/bin/systemctl --user try-restart noctalia-shell.service 2>/dev/null || true + ''; + useApp2Unit = cfg.settings.appLauncher.useApp2Unit or false; + in + lib.mkIf cfg.enable { + home.packages = lib.optional useApp2Unit cfg.app2unit.package; + + xdg.configFile = { + "noctalia/settings.json" = { + onChange = restart; + text = builtins.toJSON cfg.settings; + }; + "noctalia/colors.json" = lib.mkIf (cfg.colors != {}) { + onChange = restart; + text = builtins.toJSON cfg.colors; + }; + }; + }; +} diff --git a/nix/nixos-module.nix b/nix/nixos-module.nix new file mode 100644 index 00000000..bbab247c --- /dev/null +++ b/nix/nixos-module.nix @@ -0,0 +1,56 @@ +{ + config, + lib, + ... +}: let + cfg = config.services.noctalia-shell; +in { + options.services.noctalia-shell = { + enable = lib.mkEnableOption "Noctalia shell systemd service"; + + package = lib.mkOption { + type = lib.types.package; + description = "The noctalia-shell package to use"; + }; + + target = lib.mkOption { + type = lib.types.str; + default = "graphical-session.target"; + example = "hyprland-session.target"; + description = "The systemd target for the noctalia-shell service."; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.user.services.noctalia-shell = { + description = "Noctalia Shell - Wayland desktop shell"; + documentation = ["https://github.com/noctalia-dev/noctalia-shell"]; + after = [cfg.target]; + partOf = [cfg.target]; + wantedBy = [cfg.target]; + restartTriggers = [cfg.package]; + + environment = { + PATH = lib.mkForce null; + }; + + unitConfig = { + StartLimitIntervalSec = 60; + StartLimitBurst = 3; + }; + + serviceConfig = { + ExecStart = "${cfg.package}/bin/noctalia-shell"; + Restart = "on-failure"; + RestartSec = 3; + TimeoutStartSec = 10; + TimeoutStopSec = 5; + Environment = [ + "NOCTALIA_SETTINGS_FALLBACK=%h/.config/noctalia/gui-settings.json" + ]; + }; + }; + + environment.systemPackages = [cfg.package]; + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 00000000..a5d07917 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,108 @@ +{ + version ? "dirty", + lib, + stdenv, + # build + gcc, + qt6, + quickshell, + xkeyboard_config, + # runtime deps + bash, + bluez, + brightnessctl, + cava, + cliphist, + coreutils, + ddcutil, + file, + findutils, + libnotify, + matugen, + networkmanager, + wlsunset, + wl-clipboard, + gpu-screen-recorder, # optional + # fonts + makeFontsConf, + roboto, + inter-nerdfont, +}: let + src = lib.cleanSourceWith { + src = ../.; + filter = path: type: + !(builtins.any (prefix: lib.path.hasPrefix (../. + prefix) (/. + path)) [ + /.github + /Assets/Screenshots + /Assets/Wallpaper + /Bin/dev + /nix + /LICENSE + /README.md + /flake.nix + /flake.lock + ]); + }; + + runtimeDeps = + [ + bash + bluez + brightnessctl + cava + cliphist + coreutils + ddcutil + file + findutils + libnotify + matugen + networkmanager + wlsunset + wl-clipboard + ] + ++ lib.optionals (stdenv.hostPlatform.isx86_64) [gpu-screen-recorder]; + + fontconfig = makeFontsConf { + fontDirectories = [ + roboto + inter-nerdfont + ]; + }; +in + stdenv.mkDerivation { + pname = "noctalia-shell"; + inherit version src; + + nativeBuildInputs = [ + gcc + qt6.wrapQtAppsHook + ]; + buildInputs = [ + quickshell + xkeyboard_config + qt6.qtbase + ]; + propagatedBuildInputs = runtimeDeps; + + installPhase = '' + mkdir -p $out/share/noctalia-shell $out/bin + cp -r ./* $out/share/noctalia-shell + cp ${quickshell}/bin/qs $out/bin/noctalia-shell + ''; + + preFixup = '' + qtWrapperArgs+=( + --prefix PATH : ${lib.makeBinPath runtimeDeps} + --set FONTCONFIG_FILE ${fontconfig} + --add-flags "-p $out/share/noctalia-shell" + ) + ''; + + meta = { + description = "A sleek and minimal desktop shell thoughtfully crafted for Wayland, built with Quickshell."; + homepage = "https://github.com/noctalia-dev/noctalia-shell"; + license = lib.licenses.mit; + mainProgram = "noctalia-shell"; + }; + }