{ ... }: { flake.nixosModules.desktopGui = { config, lib, pkgs, self, inputs, options, ... }: let pi5Greeter = self.lib.pi5NiriKdl; cfg = config.chiasson.desktop; guiEnabled = cfg.hyprland.enable || cfg.niri.enable || cfg.plasma.enable; hmAvailable = lib.hasAttrByPath [ "home-manager" "sharedModules" ] options; dm = cfg.displayManager; variant = dm.variant or "sddm"; useGreeter = variant == "dankgreeter"; sddmTheme = if dm.sddm.theme.package == null then "breeze" else "${dm.sddm.theme.package}/share/sddm/themes/${dm.sddm.theme.id}"; effectiveDefaultSession = if cfg.defaultSession != null then cfg.defaultSession else if cfg.hyprland.enable then "hyprland" else if cfg.niri.enable then "niri" else "plasma"; greeterCompositor = if effectiveDefaultSession == "niri" then "niri" else if effectiveDefaultSession == "hyprland" then "hyprland" else "niri"; enabledUsers = config.chiasson.users.enabled or [ ]; greeterConfigHome = if dm.greeter.configHome != null then dm.greeter.configHome else if enabledUsers != [ ] then "/home/${builtins.head enabledUsers}" else null; in { # Unconditional imports only — conditional imports that peek at `config` recurse during merge. imports = [ inputs.dms.nixosModules.greeter ]; config = lib.mkMerge [ (lib.mkIf guiEnabled { services.xserver.enable = true; # Chromium/Electron (Edge, Vesktop, etc.) only add native Wayland + IME flags when this is # set; nixpkgs wrappers gate on NIXOS_OZONE_WL and WAYLAND_DISPLAY. Helps PipeWire/desktop # portal screen capture on wlroots-like sessions. Harmless on X11 (flags stay off). environment.sessionVariables.NIXOS_OZONE_WL = lib.mkDefault "1"; xdg.portal.enable = true; xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ] ++ lib.optionals cfg.plasma.enable [ pkgs.kdePackages.xdg-desktop-portal-kde ]; # Backlight control: `brightnessctl` + its udev rule (auto-loaded from the package's # `lib/udev/rules.d`). The rule grants the `video` group write access to # `/sys/class/backlight/*/brightness`; the user catalog adds desktop users to `video`. # The Hyprland defaults already bind XF86MonBrightness* to brightnessctl, and the Niri # base config does the same — this guarantees the binary is actually present. environment.systemPackages = [ pkgs.brightnessctl ]; services.udev.packages = [ pkgs.brightnessctl ]; }) (lib.mkIf (guiEnabled && !useGreeter) { services.displayManager.sddm = { enable = true; wayland.enable = dm.sddm.wayland.enable; theme = sddmTheme; inherit (dm.sddm) enableHidpi settings; extraPackages = lib.optionals (dm.sddm.theme.package != null) ( with pkgs.kdePackages; [ qtdeclarative qtsvg ] ); }; services.displayManager.defaultSession = effectiveDefaultSession; }) (lib.mkIf (guiEnabled && useGreeter) { assertions = [ { assertion = greeterConfigHome != null; message = "DankGreeter needs chiasson.desktop.displayManager.greeter.configHome or a non-empty chiasson.users.enabled list."; } ]; services.displayManager.defaultSession = effectiveDefaultSession; programs.dank-material-shell.greeter = { enable = true; compositor = { name = greeterCompositor; } // lib.optionalAttrs (cfg.niri.raspberryPi5DrmWorkaround && greeterCompositor == "niri") { customConfig = lib.mkDefault pi5Greeter.dankGreeterCompositorConfig; }; configHome = greeterConfigHome; }; }) (lib.mkIf (cfg.defaultPackages.enabled && guiEnabled) { environment.systemPackages = cfg.defaultPackages.packages; }) (lib.mkIf (cfg.extraPackages != [ ] && guiEnabled) { environment.systemPackages = cfg.extraPackages; }) (lib.mkIf (guiEnabled && cfg.keyring.enable) { services.gnome.gnome-keyring.enable = true; security.pam.services.login.enableGnomeKeyring = true; services.xserver.updateDbusEnvironment = lib.mkDefault true; # Electron apps (Element, Slack, etc.) use libsecret via keytar; without it they report # "unsupported keyring" even if gnome-keyring is enabled. environment.systemPackages = [ pkgs.libsecret ]; }) (lib.mkIf (guiEnabled && cfg.keyring.enable && !useGreeter) { security.pam.services.sddm.enableGnomeKeyring = true; }) (lib.mkIf (guiEnabled && cfg.keyring.enable && useGreeter) { security.pam.services.greetd.enableGnomeKeyring = true; }) (lib.mkIf (guiEnabled && cfg.keyring.enable && hmAvailable) { "home-manager".sharedModules = [ ({ lib, pkgs, ... }: { services.gnome-keyring.enable = lib.mkDefault true; home.packages = [ pkgs.gcr ]; }) ]; }) ]; }; }