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

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

@ -90,7 +90,7 @@ CollapsiblePane {
shortcutInfo.launch.waitForChildProcs = checked shortcutInfo.launch.waitForChildProcs = checked
} }
} }
CheckBox { /*CheckBox {
height: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher") ? 32 : 0 height: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher") ? 32 : 0
visible: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher") visible: subTitle != "" || (shortcutInfo.launch.launchPath || "").includes("epicgames.launcher")
id: ignoreEGS id: ignoreEGS
@ -109,7 +109,7 @@ CollapsiblePane {
onCheckedChanged: function(){ onCheckedChanged: function(){
shortcutInfo.killEGS = checked shortcutInfo.killEGS = checked
} }
} }*/
} }
Column { Column {
spacing: 2 spacing: 2
@ -483,7 +483,104 @@ CollapsiblePane {
id: commonPane id: commonPane
Column { Column {
spacing: 4 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 { Row {
anchors.topMargin: 24
Row { Row {
CheckBox { CheckBox {
id: extendedLogging id: extendedLogging

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

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

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

@ -39,6 +39,9 @@ inline struct Launch {
bool closeOnExit = true; bool closeOnExit = true;
bool waitForChildProcs = true; bool waitForChildProcs = true;
bool isUWP = false; bool isUWP = false;
bool ignoreLauncher = true;
bool killLauncher = false;
std::vector<std::wstring> launcherProcesses{};
} launch; } launch;
inline struct Devices { inline struct Devices {
@ -63,8 +66,6 @@ inline struct Common {
bool no_uwp_overlay = false; bool no_uwp_overlay = false;
bool disable_watchdog = false; bool disable_watchdog = false;
bool extendedLogging = false; bool extendedLogging = false;
bool ignoreEGS = true;
bool killEGS = false;
std::wstring name; std::wstring name;
std::wstring icon; std::wstring icon;
int version; int version;
@ -165,6 +166,17 @@ inline void Parse(const nlohmann::basic_json<>& json)
safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs); safeWStringParse(launchconf, "launchAppArgs", launch.launchAppArgs);
safeParseValue(launchconf, "closeOnExit", launch.closeOnExit); safeParseValue(launchconf, "closeOnExit", launch.closeOnExit);
safeParseValue(launchconf, "waitForChildProcs", launch.waitForChildProcs); 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()) { 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, "allowDesktopConfig", controller.allowDesktopConfig);
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4); 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) { catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what()); spdlog::warn("Err parsing config: {}", e.what());
@ -191,14 +207,6 @@ inline void Parse(const nlohmann::basic_json<>& json)
catch (const std::exception& e) { catch (const std::exception& e) {
spdlog::warn("Err parsing config: {}", e.what()); 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) { if (launch.launch) {
launch.isUWP = checkIsUwp(launch.launchPath); launch.isUWP = checkIsUwp(launch.launchPath);
} }
@ -217,8 +225,8 @@ inline void Parse(const std::vector<std::wstring>& args)
else if (arg == L"-disablewatchdog") { else if (arg == L"-disablewatchdog") {
common.disable_watchdog = true; common.disable_watchdog = true;
} }
else if (arg == L"-ignoreegs") { else if (arg == L"-ignorelauncher") {
common.ignoreEGS = true; launch.ignoreLauncher = true;
} }
else { else {
configName += L" " + std::wstring(arg.begin(), arg.end()); configName += L" " + std::wstring(arg.begin(), arg.end());

Loading…
Cancel
Save