From ad7b15580af847d818b1c5c7c55e8b4299b3f45a Mon Sep 17 00:00:00 2001 From: Chris Toph Date: Thu, 10 Jul 2025 14:07:31 -0400 Subject: [PATCH] Enhance gamescoperun and wrappers with improved environment handling and display features --- modules/home/gamescoperun.nix | 41 +++++++- modules/home/wrappers.nix | 14 ++- readme.md | 179 ++++++++++++++++++++-------------- 3 files changed, 152 insertions(+), 82 deletions(-) diff --git a/modules/home/gamescoperun.nix b/modules/home/gamescoperun.nix index 8a4ac67..c38b190 100644 --- a/modules/home/gamescoperun.nix +++ b/modules/home/gamescoperun.nix @@ -81,18 +81,54 @@ let # Merge user environment with defaults 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" '' #!${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 if set -q GAMESCOPE_WAYLAND_DISPLAY echo "Already inside Gamescope session ($GAMESCOPE_WAYLAND_DISPLAY), running command directly..." exec $argv end - # Set environment variables for the gamescope session + # Set base environment variables from the module ${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 argparse -i 'x/extra-args=' -- $argv if test $status -ne 0 @@ -123,7 +159,8 @@ let set -a final_args (string split ' ' -- $GAMESCOPE_EXTRA_OPTS) 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" # Execute gamescope with the final arguments and the command diff --git a/modules/home/wrappers.nix b/modules/home/wrappers.nix index 5b50494..aec2bb0 100644 --- a/modules/home/wrappers.nix +++ b/modules/home/wrappers.nix @@ -22,9 +22,13 @@ let baseCommand = if wrapperCfg.command != null then wrapperCfg.command else lib.getExe wrapperCfg.package; - # Create environment variable exports - envExports = lib.concatStringsSep "\n" ( - lib.mapAttrsToList (name: value: "set -x ${name} '${toString value}'") wrapperCfg.environment + # 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 @@ -35,8 +39,8 @@ let wrapperScript = pkgs.writeScriptBin name '' #!${lib.getExe pkgs.fish} - # Set additional environment variables - ${envExports} + # Set environment for gamescoperun to consume + ${gamescopeWrapperEnv} # Execute with gamescoperun exec ${lib.getExe config.play.gamescoperun.package} ${extraArgs} ${baseCommand} $argv diff --git a/readme.md b/readme.md index 229055b..29b19a0 100644 --- a/readme.md +++ b/readme.md @@ -48,87 +48,116 @@ play = { ### Home Manager Configuration ```nix -play = { - # Configure monitors for automatic gamescope settings - monitors = [{ - name = "DP-1"; - primary = true; - width = 2560; - height = 1440; - refreshRate = 165; - hdr = true; - vrr = true; - }]; +{ + config, + osConfig, # This config only works with home-manager as a nixos module + lib, + pkgs, + inputs, # Ensure inputs is available to your home-manager configuration + ... +}: +{ + imports = [ + inputs.play.homeManagerModules.play + ]; - # Enable gamescope wrapper - gamescoperun.enable = true; - - # Create application wrappers - wrappers = { - # If you wish to override the "steam" command/bin, remove "-gamescope" - # Overriding the executables makes it so already existing .desktop launchers use the new wrapper - steam-gamescope = { - enable = true; - # 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} -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" + play = { + # Configure monitors for automatic gamescope settings + monitors = [ + { + name = "DP-1"; + primary = true; + width = 2560; + height = 1440; + refreshRate = 144; + hdr = true; + vrr = true; + } ]; - settings = { - StartupNotify = "true"; - StartupWMClass = "Steam"; - PrefersNonDefaultGPU = "true"; - X-KDE-RunOnDiscreteGpu = "true"; - Keywords = "gaming;"; - }; - actions = { - bigpicture = { - name = "Steam Client (No Gamescope)"; - exec = "${lib.getExe (config.play.steam.package or pkgs.steam)}"; + + # Enable gamescope wrapper + gamescoperun.enable = true; + + # Create application wrappers + wrappers = { + # If you wish to override the "steam" command/bin, remove "-gamescope" + # Overriding the executables makes it so already existing .desktop launchers use the new wrapper + steam-gamescope = { + enable = true; + # 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 = { - name = "Heroic (Gamescope)"; - exec = "${lib.getExe config.play.wrappers.heroic-gaming.wrappedPackage}"; - icon = "com.heroicgameslauncher.hgl"; - type = "Application"; - categories = [ "Game" ]; + + # Recomendation: Override desktop entries to use gamescope wrappers + xdg.desktopEntries = { + steam = lib.mkDefault { + name = "Steam"; + comment = "Steam Big Picture (Gamescope Session)"; + 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