142 lines
4.5 KiB
Nix
142 lines
4.5 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
let
|
|
# Extend lib with play utilities
|
|
playLib = import ../../lib { inherit lib; };
|
|
|
|
cfg = config.play.wrappers;
|
|
|
|
# Use shared lib function
|
|
inherit (playLib) toCliArgs;
|
|
|
|
# Function to create a wrapper for an application
|
|
mkWrapper =
|
|
name: wrapperCfg:
|
|
let
|
|
# Determine the command to execute
|
|
baseCommand =
|
|
if wrapperCfg.command != null then wrapperCfg.command else lib.getExe wrapperCfg.package;
|
|
|
|
# Convert wrapper-specific environment to a single string for gamescoperun
|
|
gamescopeWrapperEnv = lib.optionalString (wrapperCfg.environment != { }) (
|
|
let
|
|
envList = lib.mapAttrsToList (name: value: "${name}=${toString value}") wrapperCfg.environment;
|
|
in
|
|
# Set as a global exported variable so gamescoperun can see it
|
|
"set -gx GAMESCOPE_WRAPPER_ENV '${lib.concatStringsSep ";" envList}'"
|
|
);
|
|
|
|
# Convert extraOptions to CLI args
|
|
extraArgs = lib.optionalString (
|
|
wrapperCfg.extraOptions != { }
|
|
) "-x \"${toCliArgs wrapperCfg.extraOptions}\"";
|
|
|
|
wrapperScript = pkgs.writeScriptBin name ''
|
|
#!${lib.getExe pkgs.fish}
|
|
|
|
# Set environment for gamescoperun to consume
|
|
${gamescopeWrapperEnv}
|
|
|
|
# Execute with gamescoperun
|
|
exec ${lib.getExe config.play.gamescoperun.package} ${extraArgs} ${baseCommand} $argv
|
|
'';
|
|
|
|
in
|
|
wrapperScript;
|
|
in
|
|
{
|
|
options.play.wrappers = lib.mkOption {
|
|
type = lib.types.attrsOf (
|
|
lib.types.submodule (
|
|
{ name, ... }:
|
|
{
|
|
options = {
|
|
enable = lib.mkEnableOption "wrapper for this application";
|
|
|
|
package = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.package;
|
|
default = null;
|
|
description = "The package to wrap (used with lib.getExe if command is not specified)";
|
|
};
|
|
|
|
command = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = null;
|
|
example = "\${lib.getExe osConfig.programs.steam.package} -tenfoot -bigpicture";
|
|
description = ''
|
|
The exact command to execute after gamescoperun and its options.
|
|
If specified, this takes precedence over the package option.
|
|
Can include arguments and flags.
|
|
'';
|
|
};
|
|
|
|
extraOptions = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (oneOf [
|
|
str
|
|
int
|
|
bool
|
|
]);
|
|
default = { };
|
|
example = {
|
|
"fsr-upscaling" = true;
|
|
"force-windows-fullscreen" = true;
|
|
"fsr-upscaling-sharpness" = 5;
|
|
};
|
|
description = ''
|
|
Additional gamescope command-line options for this specific wrapper.
|
|
Option names must match gamescope's flags exactly (e.g., "hdr-enabled").
|
|
These will be passed via the -x flag to gamescoperun.
|
|
'';
|
|
};
|
|
|
|
environment = lib.mkOption {
|
|
type =
|
|
with lib.types;
|
|
attrsOf (oneOf [
|
|
str
|
|
int
|
|
]);
|
|
default = { };
|
|
example = {
|
|
STEAM_FORCE_DESKTOPUI_SCALING = 1;
|
|
STEAM_GAMEPADUI = 1;
|
|
};
|
|
description = "Additional environment variables for this specific wrapper";
|
|
};
|
|
|
|
# Readonly package option that exposes the configured wrapper
|
|
wrappedPackage = lib.mkOption {
|
|
type = lib.types.package;
|
|
readOnly = true;
|
|
default = mkWrapper name config.play.wrappers.${name};
|
|
description = "The configured wrapper package for this application";
|
|
};
|
|
};
|
|
}
|
|
)
|
|
);
|
|
default = { };
|
|
description = "Application wrappers that run through gamescoperun";
|
|
};
|
|
|
|
config = {
|
|
home.packages = lib.mapAttrsToList mkWrapper (
|
|
lib.filterAttrs (name: wrapperCfg: wrapperCfg.enable) cfg
|
|
);
|
|
|
|
# Ensure gamescoperun is enabled if any wrappers are enabled
|
|
play.gamescoperun.enable = lib.mkIf (lib.length (lib.attrNames cfg) > 0) true;
|
|
|
|
assertions = lib.mapAttrsToList (name: wrapperCfg: {
|
|
assertion = wrapperCfg.enable -> (wrapperCfg.command != null || wrapperCfg.package != null);
|
|
message = "play.wrappers.${name}: Either 'command' or 'package' must be specified when enabled";
|
|
}) cfg;
|
|
};
|
|
}
|