Add configurable Launcher options / Launcher ProcessList

pull/192/head
Peter Repukat 2 years ago
parent 63fdab1685
commit 5528dfb733

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,0,2035000100080
PRODUCTVERSION 0,1,0,2035000100080
FILEVERSION 0,1,0,2045006300001
PRODUCTVERSION 0,1,0,2045006300001
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - Config"
VALUE "FileVersion", "0.1.0.2-35-g01efd8d"
VALUE "FileVersion", "0.1.0.2-45-g63fdab1"
VALUE "InternalName", "GlosSIConfig"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSIConfig.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.0.2-35-g01efd8d"
VALUE "ProductVersion", "0.1.0.2-45-g63fdab1"
END
END
BLOCK "VarFileInfo"

@ -19,6 +19,7 @@ limitations under the License.
#include <QFont>
#include <QGuiApplication>
#include <QJsonDocument>
#include <QJsonArray>
#include <QNetworkAccessManager>
#include <QNetworkReply>
@ -32,6 +33,8 @@ limitations under the License.
#include <shlobj.h>
#endif
#include "ExeImageProvider.h"
#include "ExeImageProvider.h"
#include "../version.hpp"
#include "steamgrid_api_keys.h"
@ -365,15 +368,13 @@ QVariantMap UIModel::getDefaultConf() const
path /= "Roaming";
path /= "GlosSI";
path /= "default.json";
QJsonObject defaults = {
{"icon", QJsonValue::Null},
{"name", QJsonValue::Null},
{"version", 1},
{"extendedLogging", false},
{"snapshotNotify", false},
{"ignoreEGS", true},
{"killEGS", false},
{"controller", QJsonObject{{"maxControllers", 1}, {"emulateDS4", false}, {"allowDesktopConfig", false}}},
{"devices",
QJsonObject{
@ -387,6 +388,9 @@ QVariantMap UIModel::getDefaultConf() const
{"launchAppArgs", QJsonValue::Null},
{"launchPath", QJsonValue::Null},
{"waitForChildProcs", true},
{"launcherProcesses", QJsonArray{}},
{"ignoreLauncher", true},
{"killLauncher", false},
}},
{"window",
QJsonObject{

@ -90,7 +90,7 @@ CollapsiblePane {
shortcutInfo.launch.waitForChildProcs = checked
}
}
CheckBox {
/*CheckBox {
height: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher") ? 32 : 0
visible: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher")
id: ignoreEGS
@ -109,7 +109,7 @@ CollapsiblePane {
onCheckedChanged: function(){
shortcutInfo.killEGS = checked
}
}
}*/
}
Column {
spacing: 2
@ -483,7 +483,104 @@ CollapsiblePane {
id: commonPane
Column {
spacing: 4
width: parent.width
Column {
width: parent.width
Row {
width: parent.width
Label {
text: qsTr("Launcher processes")
anchors.verticalCenter: parent.verticalCenter
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Launcher processes")
helpInfoDialog.text =
qsTr("Tells GlosSI what processes should be treated as launchers")
+ "\n"
qsTr("Only use executable name, not full path")
+ "\n"
qsTr("One process per line")
+ "\n"
+ qsTr("List must be filled for \"")
+ qsTr("Ignore launcher for close detection")
+ qsTr("\" and \"") + qsTr("Close launcher on game exit.")
+ qsTr("\" to work")
helpInfoDialog.open()
}
width: 48
height: 48
Material.elevation: 0
anchors.verticalCenter: parent.verticalCenter
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
}
}
}
RPane {
color: Qt.lighter(Material.background, 1.6)
bgOpacity: 0.3
radius: 8
width: parent.width
height: launcherProcessesTextArea.height + 16
Flickable {
width: parent.width
height: parent.height
clip: true
ScrollBar.vertical: ScrollBar {
}
contentWidth: parent.width
flickableDirection: Flickable.VerticalFlick
TextArea {
id: launcherProcessesTextArea
width: parent.width
TextArea.flickable: parent
text: ((shortcutInfo.launch.launcherProcesses || []).length == 0 && (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher"))
? "EpicGamesLauncher.exe\nEpicWebHelper.exe"
: (shortcutInfo.launch.launcherProcesses || [""]).reduce((acc, curr) => {
return acc + "\n" + curr;
})
onTextChanged: function() {
shortcutInfo.launch.launcherProcesses = text.split("\n")
.map((e) => {
e = e.endsWith(".exe") ? e : e + ".exe"
return e.trim()
})
.filter((e) => {
return e != "" && e != ".exe"
});
}
}
}
}
}
Row {
CheckBox {
id: ignoreLauncherCheckbox
text: qsTr("Ignore launcher for close detection")
checked: shortcutInfo.launch.ignoreLauncher
onCheckedChanged: function(){
shortcutInfo.launch.ignoreLauncher = checked
}
}
CheckBox {
id: killLauncherCheckbox
text: qsTr("Close launcher on game exit.")
enabled: ignoreLauncherCheckbox.checked
checked: shortcutInfo.launch.killLauncher
onCheckedChanged: function(){
shortcutInfo.launch.killLauncher = checked
}
}
}
Row {
anchors.topMargin: 24
Row {
CheckBox {
id: extendedLogging

@ -51,6 +51,12 @@ AppLauncher::AppLauncher(
void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args)
{
#ifdef _WIN32
if (!Settings::launch.launcherProcesses.empty()) {
has_extra_launchers_ = true;
spdlog::debug("Has extra launchers");
}
if (Settings::launch.isUWP) {
spdlog::info("LaunchApp is UWP, launching...");
launched_uwp_path_ = path;
@ -87,8 +93,8 @@ void AppLauncher::update()
if (process_check_clock_.getElapsedTime().asMilliseconds() > 250) {
pid_mutex_.lock();
#ifdef _WIN32
if (was_egs_launch_ && pids_.empty()) {
findEgsPid();
if (has_extra_launchers_ && pids_.empty()) {
findLauncherPids();
}
if (!pids_.empty() && pids_[0] > 0) {
if (Settings::launch.waitForChildProcs) {
@ -116,14 +122,14 @@ void AppLauncher::update()
});
auto filtered_pids = pids_ | std::ranges::views::filter([](DWORD pid) {
return std::ranges::find(EGS_LAUNCHER_PROCNAMES_, glossi_util::GetProcName(pid)) == EGS_LAUNCHER_PROCNAMES_.end();
return std::ranges::find(Settings::launch.launcherProcesses, glossi_util::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
});
if (was_egs_launch_ && !filtered_pids.empty()) {
egs_has_launched_game_ = true;
if (has_extra_launchers_ && !filtered_pids.empty()) {
launcher_has_launched_game_ = true;
}
if (Settings::launch.closeOnExit && Settings::launch.launch) {
if (was_egs_launch_ && (Settings::common.ignoreEGS || Settings::common.killEGS)) {
if (egs_has_launched_game_ && filtered_pids.empty()) {
if (has_extra_launchers_ && (Settings::launch.ignoreLauncher || Settings::launch.killLauncher)) {
if (launcher_has_launched_game_ && filtered_pids.empty()) {
spdlog::info("Configured to close on all children exit. Shutting down after game launched via EGS quit...");
shutdown_();
}
@ -158,12 +164,12 @@ std::vector<DWORD> AppLauncher::launchedPids()
pid_mutex_.lock();
std::vector<DWORD> res;
res.reserve(pids_.size());
if (!Settings::common.killEGS && Settings::common.ignoreEGS) {
if (!Settings::launch.killLauncher && Settings::launch.ignoreLauncher) {
for (const auto& pid : pids_ | std::ranges::views::filter(
[](DWORD pid) {
return std::ranges::find(
EGS_LAUNCHER_PROCNAMES_,
glossi_util::GetProcName(pid)) == EGS_LAUNCHER_PROCNAMES_.end();
Settings::launch.launcherProcesses,
glossi_util::GetProcName(pid)) == Settings::launch.launcherProcesses.end();
})) {
res.push_back(pid);
}
@ -255,7 +261,7 @@ void AppLauncher::getProcessHwnds()
#endif
#ifdef _WIN32
bool AppLauncher::findEgsPid()
bool AppLauncher::findLauncherPids()
{
if (const auto pid = glossi_util::PidByName(L"EpicGamesLauncher.exe")) {
spdlog::debug("Found EGS-Launcher running");
@ -395,7 +401,7 @@ void AppLauncher::launchURL(const std::wstring& url, const std::wstring& args, c
CoUninitialize();
if (url.find(L"epicgames.launcher") != std::wstring::npos) {
was_egs_launch_ = true;
has_extra_launchers_ = true;
}
if (execute_info.hProcess != nullptr) {
if (const auto pid = GetProcessId(execute_info.hProcess); pid > 0) {
@ -407,12 +413,12 @@ void AppLauncher::launchURL(const std::wstring& url, const std::wstring& args, c
}
}
if (was_egs_launch_) {
if (has_extra_launchers_) {
spdlog::debug("Epic Games launch; Couldn't find egs launcher PID");
pid_mutex_.lock();
const auto pid = glossi_util::PidByName(L"EpicGamesLauncher.exe");
if (!findEgsPid()) {
if (!findLauncherPids()) {
spdlog::debug("Did not find EGS-Launcher not running, retrying later...");
}
pid_mutex_.unlock();

@ -51,15 +51,9 @@ class AppLauncher {
void getProcessHwnds();
std::vector<HWND>& process_hwnds_;
static inline const std::array<std::wstring_view, 2> EGS_LAUNCHER_PROCNAMES_{
L"EpicGamesLauncher.exe",
L"EpicWebHelper.exe",
};
bool was_egs_launch_ = false;
bool egs_has_launched_game_ = false;
bool findEgsPid();
bool has_extra_launchers_ = false;
bool launcher_has_launched_game_ = false;
bool findLauncherPids();
std::wstring launched_uwp_path_;

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,0,2033009290000
PRODUCTVERSION 0,1,0,2033009290000
FILEVERSION 0,1,0,2045006300001
PRODUCTVERSION 0,1,0,2045006300001
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -69,12 +69,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Peter Repukat - FlatspotSoftware"
VALUE "FileDescription", "GlosSI - SteamTarget"
VALUE "FileVersion", "0.1.0.2-33-g929abfe"
VALUE "FileVersion", "0.1.0.2-45-g63fdab1"
VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021-2022 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.0.2-33-g929abfe"
VALUE "ProductVersion", "0.1.0.2-45-g63fdab1"
END
END
BLOCK "VarFileInfo"

@ -39,6 +39,9 @@ inline struct Launch {
bool closeOnExit = true;
bool waitForChildProcs = true;
bool isUWP = false;
bool ignoreLauncher = true;
bool killLauncher = false;
std::vector<std::wstring> launcherProcesses{};
} launch;
inline struct Devices {
@ -63,8 +66,6 @@ inline struct Common {
bool no_uwp_overlay = false;
bool disable_watchdog = false;
bool extendedLogging = false;
bool ignoreEGS = true;
bool killEGS = false;
std::wstring name;
std::wstring icon;
int version;
@ -165,6 +166,17 @@ inline void Parse(const nlohmann::basic_json<>& json)
safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs);
safeParseValue(launchconf, "closeOnExit", launch.closeOnExit);
safeParseValue(launchconf, "waitForChildProcs", launch.waitForChildProcs);
safeParseValue(launchconf, "killLauncher", launch.killLauncher);
safeParseValue(launchconf, "ignoreLauncher", launch.ignoreLauncher);
if (auto launcherProcs = launchconf["launcherProcesses"];
!launcherProcs.is_null() && !launcherProcs.empty() && launcherProcs.is_array()) {
launch.launcherProcesses.clear();
launch.launcherProcesses.reserve(launcherProcs.size());
for (auto& proc : launcherProcs) {
launch.launcherProcesses.push_back(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().from_bytes(proc));
}
}
}
if (auto devconf = json["devices"]; !devconf.is_null() && !devconf.empty() && devconf.is_object()) {
@ -184,6 +196,10 @@ inline void Parse(const nlohmann::basic_json<>& json)
safeParseValue(controllerConf, "allowDesktopConfig", controller.allowDesktopConfig);
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4);
}
safeParseValue(json, "extendedLogging", common.extendedLogging);
safeWStringParse(json, "name", common.name);
safeWStringParse(json, "icon", common.icon);
safeParseValue(json, "version", common.version);
}
catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
@ -191,14 +207,6 @@ inline void Parse(const nlohmann::basic_json<>& json)
catch (const std::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
}
safeParseValue(json, "extendedLogging", common.extendedLogging);
safeWStringParse(json, "name", common.name);
safeWStringParse(json, "icon", common.icon);
safeParseValue(json, "version", common.version);
safeParseValue(json, "ignoreEGS", common.ignoreEGS);
safeParseValue(json, "killEGS", common.killEGS);
if (launch.launch) {
launch.isUWP = checkIsUwp(launch.launchPath);
}
@ -217,8 +225,8 @@ inline void Parse(const std::vector<std::wstring>& args)
else if (arg == L"-disablewatchdog") {
common.disable_watchdog = true;
}
else if (arg == L"-ignoreegs") {
common.ignoreEGS = true;
else if (arg == L"-ignorelauncher") {
launch.ignoreLauncher = true;
}
else {
configName += L" " + std::wstring(arg.begin(), arg.end());

Loading…
Cancel
Save