Unverified Commit f33f71f6 authored by Jörg Thalheim's avatar Jörg Thalheim Committed by GitHub
Browse files

Merge pull request #240989 from m-bdf/hyprland-wayland-session

nixos/{sway,river,hyprland}: improve common wayland-session module
parents 7173eb87 95674de3
Loading
Loading
Loading
Loading
+46 −54
Original line number Diff line number Diff line
{ config
, lib
, pkgs
, ...
}:
{ config, lib, pkgs, ... }:

let
  cfg = config.programs.hyprland;

  finalPortalPackage = cfg.portalPackage.override {
    hyprland = cfg.finalPackage;
  };
  wayland-lib = import ./lib.nix { inherit lib; };
in
{
  options.programs.hyprland = {
    enable = lib.mkEnableOption null // {
      description = ''
        Whether to enable Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.

    enable = lib.mkEnableOption ''
      Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks.
      You can manually launch Hyprland by executing {command}`Hyprland` on a TTY.

      A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`.
        See <https://wiki.hyprland.org> for more information.
      '';
    };

    package = lib.mkPackageOption pkgs "hyprland" { };
      See <https://wiki.hyprland.org> for more information'';

    finalPackage = lib.mkOption {
      type = lib.types.package;
      readOnly = true;
      default = cfg.package.override {
    package = lib.mkPackageOption pkgs "hyprland" {
      extraDescription = ''
        If the package is not overridable with `enableXWayland`, then the module option
        {option}`xwayland` will have no effect.
      '';
    } // {
      apply = p: wayland-lib.genFinalPackage p {
        enableXWayland = cfg.xwayland.enable;
      };
      defaultText = lib.literalExpression
        "`programs.hyprland.package` with applied configuration";
      description = ''
        The Hyprland package after applying configuration.
      '';
    };

    portalPackage = lib.mkPackageOption pkgs "xdg-desktop-portal-hyprland" { };
    portalPackage = lib.mkPackageOption pkgs "xdg-desktop-portal-hyprland" {
      extraDescription = ''
        If the package is not overridable with `hyprland`, then the Hyprland package
        used by the portal may differ from the one set in the module option {option}`package`.
      '';
    } // {
      apply = p: wayland-lib.genFinalPackage p {
        hyprland = cfg.package;
      };
    };

    xwayland.enable = lib.mkEnableOption ("XWayland") // { default = true; };
    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };

    systemd.setPath.enable = lib.mkEnableOption null // {
      default = true;
@@ -53,25 +48,16 @@ in
    };
  };

  config = lib.mkIf cfg.enable {
    environment.systemPackages = [ cfg.finalPackage ];

    fonts.enableDefaultPackages = lib.mkDefault true;
    hardware.opengl.enable = lib.mkDefault true;

    programs = {
      dconf.enable = lib.mkDefault true;
      xwayland.enable = lib.mkDefault cfg.xwayland.enable;
    };

    security.polkit.enable = true;
  config = lib.mkIf cfg.enable (lib.mkMerge [
    {
      environment.systemPackages = [ cfg.package ];

    services.displayManager.sessionPackages = [ cfg.finalPackage ];
      # To make a Hyprland session available if a display manager like SDDM is enabled:
      services.displayManager.sessionPackages = [ cfg.package ];

      xdg.portal = {
      enable = lib.mkDefault true;
      extraPortals = [ finalPortalPackage ];
      configPackages = lib.mkDefault [ cfg.finalPackage ];
        extraPortals = [ cfg.portalPackage ];
        configPackages = lib.mkDefault [ cfg.package ];
      };

      systemd = lib.mkIf cfg.systemd.setPath.enable {
@@ -79,7 +65,13 @@ in
          DefaultEnvironment="PATH=$PATH:/run/current-system/sw/bin:/etc/profiles/per-user/%u/bin:/run/wrappers/bin"
        '';
      };
  };
    }

    (import ./wayland-session.nix {
      inherit lib pkgs;
      xwayland = cfg.xwayland.enable;
    })
  ]);

  imports = [
    (lib.mkRemovedOptionModule
+12 −0
Original line number Diff line number Diff line
{ lib }:

{
  genFinalPackage = pkg: args:
    let
      expectedArgs = with lib;
        lib.naturalSort (lib.attrNames args);
      existingArgs = with lib;
        naturalSort (intersectLists expectedArgs (attrNames (functionArgs pkg.override)));
    in
      if existingArgs != expectedArgs then pkg else pkg.override args;
}
+32 −26
Original line number Diff line number Diff line
{
  config,
  pkgs,
  lib,
  ...
}:
{ config, lib, pkgs, ... }:

let
  cfg = config.programs.river;
in {

  wayland-lib = import ./lib.nix { inherit lib; };
in
{
  options.programs.river = {
    enable = lib.mkEnableOption "river, a dynamic tiling Wayland compositor";

    package = lib.mkPackageOption pkgs "river" {
      nullable = true;
      extraDescription = ''
        If the package is not overridable with `xwaylandSupport`, then the module option
        {option}`xwayland` will have no effect.

        Set to `null` to not add any River package to your path.
        This should be done if you want to use the Home Manager River module to install River.
      '';
    } // {
      apply = p: if p == null then null else
        wayland-lib.genFinalPackage p {
          xwaylandSupport = cfg.xwayland.enable;
        };
    };

    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };

    extraPackages = lib.mkOption {
      type = with lib.types; listOf package;
      default = with pkgs; [
        swaylock
        foot
        dmenu
      ];
      default = with pkgs; [ swaylock foot dmenu ];
      defaultText = lib.literalExpression ''
        with pkgs; [ swaylock foot dmenu ];
      '';
      example = lib.literalExpression ''
        with pkgs; [
          termite rofi light
        ]
        with pkgs; [ termite rofi light ]
      '';
      description = ''
        Extra packages to be installed system wide. See
@@ -41,18 +44,21 @@ in {
    };
  };

  config =
    lib.mkIf cfg.enable (lib.mkMerge [
  config = lib.mkIf cfg.enable (lib.mkMerge [
    {
      environment.systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;

      # To make a river session available if a display manager like SDDM is enabled:
        services.displayManager.sessionPackages = lib.optionals (cfg.package != null) [ cfg.package ];
      services.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;

      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
      xdg.portal.config.river.default = lib.mkDefault [ "wlr" "gtk" ];
    }
      (import ./wayland-session.nix { inherit lib pkgs; })

    (import ./wayland-session.nix {
      inherit lib pkgs;
      xwayland = cfg.xwayland.enable;
    })
  ]);

  meta.maintainers = with lib.maintainers; [ GaetanLepage ];
+73 −105
Original line number Diff line number Diff line
{ config, pkgs, lib, ... }:
{ config, lib, pkgs, ... }:

let
  cfg = config.programs.sway;

  wrapperOptions = lib.types.submodule {
    options =
      let
        mkWrapperFeature  = default: description: lib.mkOption {
          type = lib.types.bool;
          inherit default;
          example = !default;
          description = "Whether to make use of the ${description}";
        };
      in {
        base = mkWrapperFeature true ''
          base wrapper to execute extra session commands and prepend a
          dbus-run-session to the sway command.
        '';
        gtk = mkWrapperFeature false ''
          wrapGAppsHook wrapper to execute sway with required environment
          variables for GTK applications.
        '';
    };
  };

  genFinalPackage = pkg:
    let
      expectedArgs = lib.naturalSort [
        "extraSessionCommands"
        "extraOptions"
        "withBaseWrapper"
        "withGtkWrapper"
        "isNixOS"
      ];
      existedArgs = with lib;
        naturalSort
        (intersectLists expectedArgs (attrNames (functionArgs pkg.override)));
    in if existedArgs != expectedArgs then
      pkg
    else
      pkg.override {
        extraSessionCommands = cfg.extraSessionCommands;
        extraOptions = cfg.extraOptions;
        withBaseWrapper = cfg.wrapperFeatures.base;
        withGtkWrapper = cfg.wrapperFeatures.gtk;
        isNixOS = true;
      };
in {
  wayland-lib = import ./lib.nix { inherit lib; };
in
{
  options.programs.sway = {
    enable = lib.mkEnableOption ''
      Sway, the i3-compatible tiling Wayland compositor. You can manually launch
@@ -55,28 +14,36 @@ in {
      <https://github.com/swaywm/sway/wiki> and
      "man 5 sway" for more information'';

    package = lib.mkOption {
      type = with lib.types; nullOr package;
      default = pkgs.sway;
      apply = p: if p == null then null else genFinalPackage p;
      defaultText = lib.literalExpression "pkgs.sway";
      description = ''
        Sway package to use. If the package does not contain the override arguments
        `extraSessionCommands`, `extraOptions`, `withBaseWrapper`, `withGtkWrapper`,
        `isNixOS`, then the module options {option}`wrapperFeatures`,
        {option}`wrapperFeatures` and {option}`wrapperFeatures` will have no effect.
        Set to `null` to not add any Sway package to your path. This should be done if
        you want to use the Home Manager Sway module to install Sway.
    package = lib.mkPackageOption pkgs "sway" {
      nullable = true;
      extraDescription = ''
        If the package is not overridable with `extraSessionCommands`, `extraOptions`,
        `withBaseWrapper`, `withGtkWrapper`, `enableXWayland` and `isNixOS`,
        then the module options {option}`wrapperFeatures`, {option}`extraSessionCommands`,
        {option}`extraOptions` and {option}`xwayland` will have no effect.

        Set to `null` to not add any Sway package to your path.
        This should be done if you want to use the Home Manager Sway module to install Sway.
      '';
    } // {
      apply = p: if p == null then null else
        wayland-lib.genFinalPackage p {
          extraSessionCommands = cfg.extraSessionCommands;
          extraOptions = cfg.extraOptions;
          withBaseWrapper = cfg.wrapperFeatures.base;
          withGtkWrapper = cfg.wrapperFeatures.gtk;
          enableXWayland = cfg.xwayland.enable;
          isNixOS = true;
        };
    };

    wrapperFeatures = lib.mkOption {
      type = wrapperOptions;
      default = { };
      example = { gtk = true; };
      description = ''
        Attribute set of features to enable in the wrapper.
      '';
    wrapperFeatures = {
      base = lib.mkEnableOption ''
        the base wrapper to execute extra session commands and prepend a
        dbus-run-session to the sway command'' // { default = true; };
      gtk = lib.mkEnableOption ''
        the wrapGAppsHook wrapper to execute sway with required environment
        variables for GTK applications'';
    };

    extraSessionCommands = lib.mkOption {
@@ -114,19 +81,16 @@ in {
      '';
    };

    xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; };

    extraPackages = lib.mkOption {
      type = with lib.types; listOf package;
      default = with pkgs; [
        swaylock swayidle foot dmenu wmenu
      ];
      default = with pkgs; [ swaylock swayidle foot dmenu wmenu ];
      defaultText = lib.literalExpression ''
        with pkgs; [ swaylock swayidle foot dmenu wmenu ];
      '';
      example = lib.literalExpression ''
        with pkgs; [
          i3status i3status-rust
          termite rofi light
        ]
        with pkgs; [ i3status i3status-rust termite rofi light ]
      '';
      description = ''
        Extra packages to be installed system wide. See
@@ -135,26 +99,25 @@ in {
        for a list of useful software.
      '';
    };

  };

  config = lib.mkIf cfg.enable
    (lib.mkMerge [
  config = lib.mkIf cfg.enable (lib.mkMerge [
    {
      assertions = [
        {
          assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
          message = ''
              The extraSessionCommands for Sway will not be run if
              wrapperFeatures.base is disabled.
            The extraSessionCommands for Sway will not be run if wrapperFeatures.base is disabled.
          '';
        }
      ];

      environment = {
        systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;

        # Needed for the default wallpaper:
          pathsToLink = lib.optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
        pathsToLink = lib.optional (cfg.package != null) "/share/backgrounds/sway";

        etc = {
          "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
            # Import the most important environment variables into the D-Bus and systemd
@@ -168,12 +131,17 @@ in {

      programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;

      # To make a Sway session available if a display manager like SDDM is enabled:
      services.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;

      # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
      xdg.portal.config.sway.default = lib.mkDefault [ "wlr" "gtk" ];
    }

        # To make a Sway session available if a display manager like SDDM is enabled:
        services.displayManager.sessionPackages = lib.optionals (cfg.package != null) [ cfg.package ]; }
      (import ./wayland-session.nix { inherit lib pkgs; })
    (import ./wayland-session.nix {
      inherit lib pkgs;
      xwayland = cfg.xwayland.enable;
    })
  ]);

  meta.maintainers = with lib.maintainers; [ primeos colemickens ];
+13 −18
Original line number Diff line number Diff line
{ lib, pkgs, ... }: {
{ lib, pkgs, xwayland ? true }:

{
  security = {
    polkit.enable = true;
    pam.services.swaylock = {};
@@ -9,15 +11,8 @@

  programs = {
    dconf.enable = lib.mkDefault true;
      xwayland.enable = lib.mkDefault true;
    xwayland.enable = lib.mkDefault xwayland;
  };

    xdg.portal = {
      enable = lib.mkDefault true;

      extraPortals = [
        # For screen sharing
        pkgs.xdg-desktop-portal-wlr
      ];
    };
  xdg.portal.wlr.enable = lib.mkDefault true;
}