Enhance gamescoperun and wrappers with improved environment handling and display features

This commit is contained in:
Chris Toph 2025-07-10 14:07:31 -04:00
parent 3f904de4da
commit ad7b15580a
3 changed files with 152 additions and 82 deletions

View file

@ -81,18 +81,54 @@ let
# Merge user environment with defaults # Merge user environment with defaults
finalEnvironment = defaultEnvironment // cfg.environment; finalEnvironment = defaultEnvironment // cfg.environment;
toEchoCommands =
env:
lib.concatStringsSep "\n" (
lib.mapAttrsToList (name: value: ''
echo -e " \033[1;33m${name}\033[0m=\033[0;35m${toString value}\033[0m"
'') env
);
gamescoperun = pkgs.writeScriptBin "gamescoperun" '' gamescoperun = pkgs.writeScriptBin "gamescoperun" ''
#!${lib.getExe pkgs.fish} #!${lib.getExe pkgs.fish}
# Function to display the wrapper environment state
function show_environment
echo -e "\033[1;36m[gamescoperun]\033[0m Environment:"
# Display environment from the module
${toEchoCommands finalEnvironment}
# Display environment from the calling wrapper, if any
if set -q GAMESCOPE_WRAPPER_ENV
echo -e " \033[1;36m(from wrapper)\033[0m"
for pair in (string split ';' -- "$GAMESCOPE_WRAPPER_ENV")
set parts (string split -m 1 '=' -- "$pair")
if test (count $parts) -eq 2
echo -e " \033[1;33m$parts[1]\033[0m=\033[0;35m$parts[2]\033[0m"
end
end
end
end
# Check if we're already inside a Gamescope session # Check if we're already inside a Gamescope session
if set -q GAMESCOPE_WAYLAND_DISPLAY if set -q GAMESCOPE_WAYLAND_DISPLAY
echo "Already inside Gamescope session ($GAMESCOPE_WAYLAND_DISPLAY), running command directly..." echo "Already inside Gamescope session ($GAMESCOPE_WAYLAND_DISPLAY), running command directly..."
exec $argv exec $argv
end end
# Set environment variables for the gamescope session # Set base environment variables from the module
${toEnvCommands finalEnvironment} ${toEnvCommands finalEnvironment}
# Set environment variables from the calling wrapper, overriding if necessary
if set -q GAMESCOPE_WRAPPER_ENV
for pair in (string split ';' -- "$GAMESCOPE_WRAPPER_ENV")
set parts (string split -m 1 '=' -- "$pair")
if test (count $parts) -eq 2
set -gx $parts[1] "$parts[2]"
end
end
end
# Define and parse arguments using fish's built-in argparse # Define and parse arguments using fish's built-in argparse
argparse -i 'x/extra-args=' -- $argv argparse -i 'x/extra-args=' -- $argv
if test $status -ne 0 if test $status -ne 0
@ -123,7 +159,8 @@ let
set -a final_args (string split ' ' -- $GAMESCOPE_EXTRA_OPTS) set -a final_args (string split ' ' -- $GAMESCOPE_EXTRA_OPTS)
end end
# Show the command being executed # Show the environment and command being executed
show_environment
echo -e "\033[1;36m[gamescoperun]\033[0m Running: \033[1;34m${lib.getExe gamescopePackages.gamescope}\033[0m $final_args \033[1;32m--\033[0m $argv" echo -e "\033[1;36m[gamescoperun]\033[0m Running: \033[1;34m${lib.getExe gamescopePackages.gamescope}\033[0m $final_args \033[1;32m--\033[0m $argv"
# Execute gamescope with the final arguments and the command # Execute gamescope with the final arguments and the command

View file

@ -22,9 +22,13 @@ let
baseCommand = baseCommand =
if wrapperCfg.command != null then wrapperCfg.command else lib.getExe wrapperCfg.package; if wrapperCfg.command != null then wrapperCfg.command else lib.getExe wrapperCfg.package;
# Create environment variable exports # Convert wrapper-specific environment to a single string for gamescoperun
envExports = lib.concatStringsSep "\n" ( gamescopeWrapperEnv = lib.optionalString (wrapperCfg.environment != { }) (
lib.mapAttrsToList (name: value: "set -x ${name} '${toString value}'") 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 # Convert extraOptions to CLI args
@ -35,8 +39,8 @@ let
wrapperScript = pkgs.writeScriptBin name '' wrapperScript = pkgs.writeScriptBin name ''
#!${lib.getExe pkgs.fish} #!${lib.getExe pkgs.fish}
# Set additional environment variables # Set environment for gamescoperun to consume
${envExports} ${gamescopeWrapperEnv}
# Execute with gamescoperun # Execute with gamescoperun
exec ${lib.getExe config.play.gamescoperun.package} ${extraArgs} ${baseCommand} $argv exec ${lib.getExe config.play.gamescoperun.package} ${extraArgs} ${baseCommand} $argv

177
readme.md
View file

@ -48,87 +48,116 @@ play = {
### Home Manager Configuration ### Home Manager Configuration
```nix ```nix
play = { {
# Configure monitors for automatic gamescope settings config,
monitors = [{ osConfig, # This config only works with home-manager as a nixos module
name = "DP-1"; lib,
primary = true; pkgs,
width = 2560; inputs, # Ensure inputs is available to your home-manager configuration
height = 1440; ...
refreshRate = 165; }:
hdr = true; {
vrr = true; imports = [
}]; inputs.play.homeManagerModules.play
];
# Enable gamescope wrapper play = {
gamescoperun.enable = true; # Configure monitors for automatic gamescope settings
monitors = [
# Create application wrappers {
wrappers = { name = "DP-1";
# If you wish to override the "steam" command/bin, remove "-gamescope" primary = true;
# Overriding the executables makes it so already existing .desktop launchers use the new wrapper width = 2560;
steam-gamescope = { height = 1440;
enable = true; refreshRate = 144;
# Note: Special case for steam, this is the pkg you should use hdr = true;
# Also sas of 06/25, steam does not open in normal "desktop mode" with gamescope vrr = true;
# You can however exit big picture mode once already open to access the normal ui }
command = "${lib.getExe osConfig.programs.steam.package} -tenfoot -bigpicture";
extraOptions = {
"steam" = true;
};
};
lutris-gamescope = {
enable = true;
package = osConfig.play.lutris.package; # play.nix provides readonly packages
extraOptions."force-windows-fullscreen" = true;
};
heroic-gamescope = {
enable = true;
package = pkgs.heroic;
extraOptions."fsr-upscaling" = true;
};
};
};
# Recomendation: Override desktop entries to use gamescope wrappers
xdg.desktopEntries = {
steam = {
name = "Steam";
comment = "Steam Big Picture (Gamescope Session)";
exec = "${lib.getExe config.play.wrappers.steam.wrappedPackage}";
icon = "steam";
type = "Application";
terminal = false;
categories = [ "Game" ];
mimeType = [
"x-scheme-handler/steam"
"x-scheme-handler/steamlink"
]; ];
settings = {
StartupNotify = "true"; # Enable gamescope wrapper
StartupWMClass = "Steam"; gamescoperun.enable = true;
PrefersNonDefaultGPU = "true";
X-KDE-RunOnDiscreteGpu = "true"; # Create application wrappers
Keywords = "gaming;"; wrappers = {
}; # If you wish to override the "steam" command/bin, remove "-gamescope"
actions = { # Overriding the executables makes it so already existing .desktop launchers use the new wrapper
bigpicture = { steam-gamescope = {
name = "Steam Client (No Gamescope)"; enable = true;
exec = "${lib.getExe (config.play.steam.package or pkgs.steam)}"; # Note: Special case for steam, this is the pkg you should use
# Also sas of 06/25, steam does not open in normal "desktop mode" with gamescope
# You can however exit big picture mode once already open to access the normal ui
command = "${lib.getExe osConfig.programs.steam.package} -bigpicture -tenfoot";
extraOptions = {
"steam" = true; # equivalent to --steam flag
};
environment = {
STEAM_FORCE_DESKTOPUI_SCALING = 1;
STEAM_GAMEPADUI = 1;
};
};
lutris-gamescope = {
enable = true;
package = osConfig.play.lutris.package; # play.nix provides readonly packages
extraOptions = {
"force-windows-fullscreen" = true;
};
environment = {
LUTRIS_SKIP_INIT = 1;
};
};
heroic-gamescope = {
enable = true;
package = pkgs.heroic;
extraOptions."fsr-upscaling" = true;
}; };
}; };
}; };
heroic = { # Recomendation: Override desktop entries to use gamescope wrappers
name = "Heroic (Gamescope)"; xdg.desktopEntries = {
exec = "${lib.getExe config.play.wrappers.heroic-gaming.wrappedPackage}"; steam = lib.mkDefault {
icon = "com.heroicgameslauncher.hgl"; name = "Steam";
type = "Application"; comment = "Steam Big Picture (Gamescope Session)";
categories = [ "Game" ]; exec = "${lib.getExe config.play.wrappers.steam-gamescope.wrappedPackage}";
icon = "steam";
type = "Application";
terminal = false;
categories = [ "Game" ];
mimeType = [
"x-scheme-handler/steam"
"x-scheme-handler/steamlink"
];
settings = {
StartupNotify = "true";
StartupWMClass = "Steam";
PrefersNonDefaultGPU = "true";
X-KDE-RunOnDiscreteGpu = "true";
Keywords = "gaming;";
};
actions = {
client = {
name = "Steam Client (No Gamescope)";
exec = "${lib.getExe osConfig.programs.steam.package}";
};
steamdeck = {
name = "Steam Deck (Gamescope)";
exec = "${lib.getExe config.play.wrappers.steam-gamescope.wrappedPackage} -steamdeck";
};
};
};
heroic = {
name = "Heroic (Gamescope)";
exec = "${lib.getExe config.play.wrappers.heroic-gamescope.wrappedPackage}";
icon = "com.heroicgameslauncher.hgl";
type = "Application";
categories = [ "Game" ];
};
}; };
}; }
``` ```
## Usage ## Usage