Improved launching of Steam games by keeping ES-DE running in the background.

This commit is contained in:
Leon Styhre 2021-03-24 20:13:33 +01:00
parent 5248ece0c2
commit 083e0a12e9
5 changed files with 58 additions and 44 deletions

View file

@ -954,9 +954,16 @@ void FileData::launchGame(Window* window)
LOG(LogInfo) << command; LOG(LogInfo) << command;
#if defined(_WIN64) #if defined(_WIN64)
returnValue = launchEmulatorWindows(Utils::String::stringToWideString(command)); if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM) ||
Settings::getInstance()->getBool("RunInBackground"))
returnValue = launchGameWindows(Utils::String::stringToWideString(command), true);
else
returnValue = launchGameWindows(Utils::String::stringToWideString(command), false);
#else #else
returnValue = launchEmulatorUnix(command); if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM))
returnValue = launchGameUnix(command, true);
else
returnValue = launchGameUnix(command, false);
#endif #endif
// Notify the user in case of a failed game launch using a popup window. // Notify the user in case of a failed game launch using a popup window.
@ -972,16 +979,21 @@ void FileData::launchGame(Window* window)
// Stop showing the game launch notification. // Stop showing the game launch notification.
window->stopInfoPopup(); window->stopInfoPopup();
#if defined(_WIN64) #if defined(_WIN64)
// This code is only needed for Windows, where we may need to keep ES running while // If starting a Steam game or if the "RunInBackground" setting has been enabled,
// the game/emulator is in use. It's basically used to pause any playing game video // then keep ES-DE running while the game is launched. This pauses any video and keeps
// and to keep the screensaver from activating. // the screensaver from getting activated.
if (Settings::getInstance()->getBool("RunInBackground")) if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM) ||
Settings::getInstance()->getBool("RunInBackground"))
window->setLaunchedGame(); window->setLaunchedGame();
else else
// Normalize deltaTime so that the screensaver does not start immediately // Normalize deltaTime so that the screensaver does not start immediately
// when returning from the game. // when returning from the game.
window->normalizeNextUpdate(); window->normalizeNextUpdate();
#else #else
// If starting a Steam game, then keep ES-DE running while the game is launched.
// This pauses any video and keeps the screensaver from getting activated.
if (mSystem->hasPlatformId(PlatformIds::VALVE_STEAM))
window->setLaunchedGame();
// Normalize deltaTime so that the screensaver does not start immediately // Normalize deltaTime so that the screensaver does not start immediately
// when returning from the game. // when returning from the game.
window->normalizeNextUpdate(); window->normalizeNextUpdate();

View file

@ -762,18 +762,13 @@ bool ViewController::input(InputConfig* config, Input input)
if (mLockInput) if (mLockInput)
return true; return true;
#if defined(_WIN64) // For Steam games or if enabling the "RunInBackground" setting on Windows, ES-DE will
// This code is only needed for Windows, where we may need to keep ES running while // run in the background while a game is launched. If we're in this state and then
// the game/emulator is in use. It's basically used to pause any playing game video // register some input, it means that the user is back in ES-DE. Therefore unset the game
// and to keep the screensaver from activating. // launch flag and update all the GUI components. This will re-enable the video player
if (Settings::getInstance()->getBool("RunInBackground")) { // and let the screensaver start on schedule again.
// If we have previously launched a game and there is now input registered, it means
// the user is back in ES, so unset the flag to indicate that a game has been launched
// and update all the GUI components to reflect this.
if (mWindow->getGameLaunchedState()) if (mWindow->getGameLaunchedState())
mWindow->unsetLaunchedGame(); mWindow->unsetLaunchedGame();
}
#endif
// Open the main menu. // Open the main menu.
if (!(UIModeController::getInstance()->isUIModeKid() && if (!(UIModeController::getInstance()->isUIModeKid() &&
@ -930,16 +925,12 @@ void ViewController::reloadGameListView(IGameListView* view, bool reloadTheme)
} }
} }
#if defined(_WIN64) // For Steam games or if enabling the "RunInBackground" setting on Windows, ES-DE will
// This code is only needed for Windows, where we may need to keep ES running while // run in the background while a game is launched. If this flag has been set, then update
// the game/emulator is in use. It's basically used to pause any playing game video // all the GUI components. This will disable the video player and prevent the screensaver
// and to keep the screensaver from activating. // from starting on schedule.
if (Settings::getInstance()->getBool("RunInBackground")) {
// If a game has been launched, then update all the GUI components to reflect this.
if (mWindow->getGameLaunchedState()) if (mWindow->getGameLaunchedState())
mWindow->setLaunchedGame(); mWindow->setLaunchedGame();
}
#endif
// Redisplay the current view. // Redisplay the current view.
if (mCurrentView) if (mCurrentView)

View file

@ -71,10 +71,19 @@ int runSystemCommand(const std::wstring& cmd_utf16)
#endif #endif
} }
int launchEmulatorUnix(const std::string& cmd_utf8) int launchGameUnix(const std::string& cmd_utf8, bool runInBackground)
{ {
#if defined(__unix__) || defined (__APPLE__) #if defined(__unix__) || defined (__APPLE__)
std::string command = std::string(cmd_utf8) + " 2>&1"; std::string command = std::string(cmd_utf8) + " 2>&1 &";
// Launching games while keeping ES-DE running in the background is very crude as for
// instance no output from the command is captured and no real error handling is
// implemented. It should therefore only be used when absolutely necessary.
if (runInBackground) {
LOG(LogDebug) << "Platform::launchGameUnix(): Launching game while keeping ES-DE "
"running in the background, no command output will be written to the log file";
return system(command.c_str());
}
FILE* commandPipe; FILE* commandPipe;
std::array<char, 128> buffer; std::array<char, 128> buffer;
@ -101,15 +110,15 @@ int launchEmulatorUnix(const std::string& cmd_utf8)
} }
if (returnValue) { if (returnValue) {
LOG(LogError) << "launchEmulatorUnix - return value " << LOG(LogError) << "launchGameUnix - return value " <<
std::to_string(returnValue) + ":"; std::to_string(returnValue) + ":";
if (commandOutput.size()) if (commandOutput.size())
LOG(LogError) << commandOutput; LOG(LogError) << commandOutput;
else else
LOG(LogError) << "No error output provided by emulator."; LOG(LogError) << "No error output provided by game or emulator";
} }
else if (commandOutput.size()) { else if (commandOutput.size()) {
LOG(LogDebug) << "Platform::launchEmulatorUnix():"; LOG(LogDebug) << "Platform::launchGameUnix():";
LOG(LogDebug) << "Output from launched game:\n" << commandOutput; LOG(LogDebug) << "Output from launched game:\n" << commandOutput;
} }
@ -120,7 +129,7 @@ int launchEmulatorUnix(const std::string& cmd_utf8)
#endif #endif
} }
int launchEmulatorWindows(const std::wstring& cmd_utf16) int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground)
{ {
#if defined(_WIN64) #if defined(_WIN64)
STARTUPINFOW si {}; STARTUPINFOW si {};
@ -142,12 +151,14 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
&si, // Pointer to the STARTUPINFOW structure. &si, // Pointer to the STARTUPINFOW structure.
&pi); // Pointer to the PROCESS_INFORMATION structure. &pi); // Pointer to the PROCESS_INFORMATION structure.
// Unfortunately suspending ES and resuming when the emulator process has exited // Unfortunately suspending ES-DE and resuming when the game/emulator process has exited
// doesn't work reliably on Windows, so we may need to keep ES running in the // doesn't work reliably on Windows, so we may need to keep ES-DE running in the background
// background while the game is launched. I'm not sure if there is a workaround // while the game is launched. I'm not sure if there is a workaround for this, but on most
// for this, but on some Windows installations it seems to work fine so we'll let // Windows installations it seems to work fine so we'll let the user choose via a menu option.
// the user choose via a menu option. // Possibly the issue is specific to Windows 8.
if (!Settings::getInstance()->getBool("RunInBackground")) { // Running in the background is also required for Steam games as ES-DE would otherwise
// wait forever for Steam to exit unless it was already running when the game was launched.
if (!runInBackground) {
// Wait for the child process to exit. // Wait for the child process to exit.
WaitForSingleObject(pi.hThread, INFINITE); WaitForSingleObject(pi.hThread, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE); WaitForSingleObject(pi.hProcess, INFINITE);
@ -174,7 +185,7 @@ int launchEmulatorWindows(const std::wstring& cmd_utf16)
} }
} }
LOG(LogError) << "launchEmulatorWindows - system error code " << LOG(LogError) << "launchGameWindows - system error code " <<
errorCode << ": " << errorMessage; errorCode << ": " << errorMessage;
} }

View file

@ -26,8 +26,8 @@ int runSystemCommand(const std::string& cmd_utf8);
// Windows specific UTF-16/wstring function. (FOR FUTURE USE) // Windows specific UTF-16/wstring function. (FOR FUTURE USE)
int runSystemCommand(const std::wstring& cmd_utf16); int runSystemCommand(const std::wstring& cmd_utf16);
int launchEmulatorUnix(const std::string& cmd_utf8); int launchGameUnix(const std::string& cmd_utf8, bool runInBackground);
int launchEmulatorWindows(const std::wstring& cmd_utf16); int launchGameWindows(const std::wstring& cmd_utf16, bool runInBackground);
unsigned int getTaskbarState(); unsigned int getTaskbarState();
void hideTaskbar(); void hideTaskbar();

View file

@ -648,7 +648,7 @@ void Window::setLaunchedGame()
void Window::unsetLaunchedGame() void Window::unsetLaunchedGame()
{ {
// Tell the GUI components that the user is back in ES again. // Tell the GUI components that the user is back in ES-DE again.
for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++) for (auto it = mGuiStack.cbegin(); it != mGuiStack.cend(); it++)
(*it)->onGameLaunchedDeactivate(); (*it)->onGameLaunchedDeactivate();