GlosSITarget: Added Steambase URL

add `WS_EX_TOOLWINDOW` in extended windows styles for GlosSI-Target

https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles

Goal is to remove GlosSI-Target window in Alt-Tab listing as it will induce issues with Steam Link and not particularly intuitive when switching from and to a game.

Currently untested, PR needed only for building a PoC of it and checking for possible issues

typo

added comment

Added proper setting value (default: off)

Added toggle inside ImGui

It's that time of the year again

Clone submodules via https instead of ssh

Uncamelcasify EGS game names

Fix shortcut names not editable

Add Configurator option to exclude target-window from windowlist

Hack together shitty method to retrieve original unhooking bytes via GlosSIConfig

Here's hoping that this will prevent access-violation issues for some users

Store SteamPath/SteamUserId in Settings and use as fallback

Option to disable GlosSIs additional overlay

Update Usage.md

Added steambase url

Update Usage.md

Update Usage.md

Update Usage.md
pull/231/head
Peter Repukat 1 year ago committed by Simon Ferns
parent be8e206683
commit 4374ec0429

8
.gitmodules vendored

@ -27,13 +27,13 @@
url = https://github.com/nlohmann/json
[submodule "deps/traypp"]
path = deps/traypp
url = https://github.com/Soundux/traypp.git
url = https://github.com/Soundux/traypp
[submodule "deps/fifo_map"]
path = deps/fifo_map
url = git@github.com:nlohmann/fifo_map.git
url = https://github.com/nlohmann/fifo_map
[submodule "deps/Shortcuts_VDF"]
path = deps/Shortcuts_VDF
url = git@github.com:Alia5/Shortcuts_VDF.git
url = https://github.com/Alia5/Shortcuts_VDF
[submodule "deps/cpp-httplib"]
path = deps/cpp-httplib
url = git@github.com:yhirose/cpp-httplib.git
url = https://github.com/yhirose/cpp-httplib

@ -69,7 +69,7 @@
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/Zc:__cplusplus /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
<CompileAsWinRT>false</CompileAsWinRT>
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NOMINMAX;CONFIGAPP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\deps\WinReg;..\deps\fifo_map\src;..\deps\Shortcuts_VDF\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Manifest>
@ -92,7 +92,7 @@
<AdditionalUsingDirectories>%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<AdditionalOptions>/Zc:__cplusplus /Zc:zwoPhase- /permissive- %(AdditionalOptions)</AdditionalOptions>
<CompileAsWinRT>false</CompileAsWinRT>
<PreprocessorDefinitions>NOMINMAX;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NOMINMAX;CONFIGAPP;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\deps\WinReg;..\deps\fifo_map\src;..\deps\Shortcuts_VDF\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Manifest>
@ -136,6 +136,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp" />
<ClCompile Include="ExeImageProvider.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="UIModel.cpp" />

@ -37,6 +37,9 @@
<ClCompile Include="ExeImageProvider.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\GlosSITarget\UnhookUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="qml\main.qml">

@ -51,8 +51,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,1,1,101000823500
PRODUCTVERSION 0,1,1,101000823500
FILEVERSION 0,1,1,2012005004400
PRODUCTVERSION 0,1,1,2012005004400
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.1.1-1-ga8235ca"
VALUE "FileVersion", "0.1.1.2-12-g5fe44d0"
VALUE "InternalName", "GlosSIConfig"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSIConfig.exe"
VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.1.1.1-1-ga8235ca"
VALUE "ProductVersion", "0.1.1.2-12-g5fe44d0"
END
END
BLOCK "VarFileInfo"
@ -1400,6 +1400,106 @@ IDI_ICON1 ICON "..\GlosSI_Icon.ico"

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -22,6 +22,8 @@ limitations under the License.
#include <QJsonArray>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMetaType>
#include <WinReg/WinReg.hpp>
@ -36,6 +38,9 @@ limitations under the License.
#include "ExeImageProvider.h"
#include "../version.hpp"
#include "../../GlosSITarget/UnhookUtil.h"
UIModel::UIModel() : QObject(nullptr)
{
wchar_t* localAppDataFolder;
@ -60,9 +65,13 @@ UIModel::UIModel() : QObject(nullptr)
if (!std::filesystem::exists(path))
std::filesystem::create_directories(path);
auto defaultConf = getDefaultConf();
saveDefaultConf(defaultConf);
parseShortcutVDF();
readTargetConfigs();
updateCheck();
readUnhookBytes();
auto font = QGuiApplication::font();
font.setPointSize(11);
@ -115,6 +124,8 @@ bool UIModel::updateTarget(int index, QVariant shortcut)
const auto map = shortcut.toMap();
const auto json = QJsonObject::fromVariantMap(map);
const auto was_in_steam_ = isInSteam(shortcut);
auto oldSteamName = targets_[index].toMap()["name"].toString();
auto oldName =
targets_[index].toMap()["name"].toString().replace(QRegularExpression("[\\\\/:*?\"<>|]"), "") + ".json";
@ -132,15 +143,19 @@ bool UIModel::updateTarget(int index, QVariant shortcut)
path /= config_dir_name_.toStdString();
path /= (map["name"].toString()).toStdString();
if (removeFromSteam(oldSteamName, QString::fromStdWString(path.wstring()))) {
if (!addToSteam(shortcut, QString::fromStdWString(path.wstring()))) {
qDebug() << "Couldn't add shortcut \"" << (map["name"].toString()) << "\" to Steam when updating";
return false;
if (was_in_steam_) {
if (removeFromSteam(oldSteamName, QString::fromStdWString(path.wstring()))) {
if (!addToSteam(shortcut, QString::fromStdWString(path.wstring()))) {
qDebug() << "Couldn't add shortcut \"" << (map["name"].toString()) << "\" to Steam when updating";
return false;
}
return true;
}
qDebug() << "Couldn't remove shortcut \"" << oldName << "\" from Steam when updating";
return false;
} else {
return true;
}
qDebug() << "Couldn't remove shortcut \"" << oldName << "\" from Steam when updating";
return false;
}
void UIModel::deleteTarget(int index)
@ -159,7 +174,9 @@ bool UIModel::isInSteam(QVariant shortcut) const
{
const auto map = shortcut.toMap();
for (auto& steam_shortcut : shortcuts_vdf_) {
if (map["name"].toString() == QString::fromStdString(steam_shortcut.appname)) {
if (
map["name"].toString() == QString::fromStdString(steam_shortcut.appname) ||
map["oldName"].toString() == QString::fromStdString(steam_shortcut.appname)) {
if (QString::fromStdString(steam_shortcut.exe).toLower().contains("glossitarget.exe")) {
return true;
}
@ -383,6 +400,10 @@ QVariantMap UIModel::getDefaultConf() const
{"extendedLogging", false},
{"snapshotNotify", false},
{"steamgridApiKey", QJsonValue::Null},
{"steamPath",
QJsonValue::fromVariant(QString::fromStdWString(getSteamPath(false).wstring()))},
{"steamUserId",
QJsonValue::fromVariant(QString::fromStdWString(getSteamUserId(false)))},
{"controller", QJsonObject{{"maxControllers", 1}, {"emulateDS4", false}, {"allowDesktopConfig", false}}},
{"devices",
QJsonObject{
@ -403,9 +424,11 @@ QVariantMap UIModel::getDefaultConf() const
{"window",
QJsonObject{
{"disableOverlay", false},
{"hideAltTab", false},
{"maxFps", QJsonValue::Null},
{"scale", QJsonValue::Null},
{"windowMode", false},
{"disableGlosSIOverlay", false},
}},
};
@ -719,20 +742,33 @@ QString UIModel::getVersionString() const { return QString(version::VERSION_STR)
QString UIModel::getNewVersionName() const { return new_version_name_; }
std::filesystem::path UIModel::getSteamPath() const
std::filesystem::path UIModel::getSteamPath(bool tryConfig) const
{
QVariantMap defaultConf;
if (tryConfig) {
defaultConf = getDefaultConf();
}
try {
#ifdef _WIN32
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam"};
if (!key.IsValid()) {
if (defaultConf.contains("steamPath") &&
QMetaType::canConvert(defaultConf["steamPath"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamPath"].toString().toStdWString();
}
return "";
}
const auto res = key.GetStringValue(L"SteamPath");
return res;
}
catch (...) {
if (defaultConf.contains("steamPath") &&
QMetaType::canConvert(defaultConf["steamPath"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamPath"].toString().toStdWString();
}
return "";
}
#else
@ -740,23 +776,39 @@ std::filesystem::path UIModel::getSteamPath() const
#endif
}
std::wstring UIModel::getSteamUserId() const
std::wstring UIModel::getSteamUserId(bool tryConfig) const
{
QVariantMap defaultConf;
if (tryConfig) {
defaultConf = getDefaultConf();
}
#ifdef _WIN32
try {
// TODO: check if keys/value exist
// steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"};
if (!key.IsValid()) {
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
return L"0";
}
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
if (res == L"0") {
qDebug() << "Steam not open?";
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
}
return res;
}
catch (...) {
if (defaultConf.contains("steamUserId") &&
QMetaType::canConvert(defaultConf["steamUserId"].metaType(), QMetaType(QMetaType::QString))) {
return defaultConf["steamUserId"].toString().toStdWString();
}
return L"0";
}
#else
@ -830,3 +882,35 @@ bool UIModel::isSteamInputXboxSupportEnabled() const
}
return true;
}
void UIModel::readUnhookBytes() const
{
std::map<std::string, std::string> unhook_bytes;
for (const auto& name : UnhookUtil::UNHOOK_BYTES_ORIGINAL_22000 | std::views::keys) {
auto bytes = UnhookUtil::ReadOriginalBytes(
name,
name.starts_with("Hid")
? L"hid.dll"
: name.starts_with("Setup")
? L"setupapi.dll"
: L"Kernel32.dll"
);
unhook_bytes[name] = bytes;
}
auto path = config_path_;
path /= "unhook_bytes";
QFile file(path);
if (!file.open(QIODevice::Truncate | QIODevice::ReadWrite)) {
qDebug() << "Couldn't open file for writing: " << path;
return;
}
for (const auto& [name, bytes] : unhook_bytes) {
file.write(
QString::fromStdString(name + ":").toStdString().data()
);
file.write(bytes.data(), bytes.size());
file.write("\n");
}
file.close();
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -125,10 +125,12 @@ class UIModel : public QObject {
QString getVersionString() const;
QString getNewVersionName() const;
std::filesystem::path getSteamPath() const;
std::wstring getSteamUserId() const;
std::filesystem::path getSteamPath(bool tryConfig = true) const;
std::wstring getSteamUserId(bool tryConfig = true) const;
bool foundSteam() const;
void parseShortcutVDF();
bool isSteamInputXboxSupportEnabled() const;
void readUnhookBytes() const;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -140,7 +140,7 @@ CollapsiblePane {
RPane {
width: parent.width / 2 - 8
height: 248
height: 324
radius: 4
Material.elevation: 32
bgOpacity: 0.97
@ -290,7 +290,7 @@ CollapsiblePane {
}
RPane {
width: parent.width / 2 - 8
height: 248
height: 324
radius: 4
Material.elevation: 32
bgOpacity: 0.97
@ -359,6 +359,76 @@ CollapsiblePane {
height: 24
}
}
}
Item {
width: 1
height: 4
}
Row {
CheckBox {
id: hideAltTabCheckbox
text: qsTr("Hide GlosSI from Windowlist (Alt+Tab)")
checked: shortcutInfo.window.hideAltTab
onCheckedChanged: shortcutInfo.window.hideAltTab = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Hide GlosSI from Windowlist (Alt+Tab)")
helpInfoDialog.text =
qsTr("Hides GlosSI from the Windowlist (Alt+Tab)")
+ "\n"
+ qsTr("You can close the GlosSI-Window via the system-tray")
+ "\n"
+ "\n"
+ qsTr("Might help with Steam remote play.")
helpInfoDialog.open()
}
width: 48
height: 48
Material.elevation: 0
anchors.topMargin: 16
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
}
}
}
Item {
width: 1
height: 4
}
Row {
CheckBox {
id: disableGlosSIOverlayCheckbox
text: qsTr("Disable GlosSI overlay")
checked: shortcutInfo.window.disableGlosSIOverlay
onCheckedChanged: shortcutInfo.window.disableGlosSIOverlay = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Disable GlosSI overlay")
helpInfoDialog.text =
qsTr("Disables the additional GlosSI overlay")
+ "\n"
+ qsTr("but keeps the Steam overlay");
helpInfoDialog.open()
}
width: 48
height: 48
Material.elevation: 0
anchors.topMargin: 16
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
}
}
}
Item {
width: 1

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -189,7 +189,7 @@ Dialog {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Label {
text: modelData.InstallLocation.split('/').pop().split('\\').pop()
text: modelData.InstallLocation.split('/').pop().split('\\').pop().replace(/([a-z])([A-Z])/g, '$1 $2')
font.pixelSize: 18
font.bold: true
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -136,7 +136,11 @@ Item {
id: nameInput
placeholderText: qsTr("...")
text: shortcutInfo.name
onTextChanged: shortcutInfo.name = text
onTextChanged: function() {
shortcutInfo.oldName = shortcutInfo.oldName || shortcutInfo.name
shortcutInfo.name = nameInput.text
shortcutInfo = shortcutInfo
}
validator: RegularExpressionValidator { regularExpression: /([0-z]|\s|.)+/gm }
}
}
@ -374,7 +378,7 @@ Item {
id: egsSelectDialog
onConfirmed: function(modelData) {
if (nameInput.text == "") {
nameInput.text = modelData.InstallLocation.split('/').pop().split('\\').pop()
nameInput.text = modelData.InstallLocation.split('/').pop().split('\\').pop().replace(/([a-z])([A-Z])/g, '$1 $2')
}
pathInput.text = "com.epicgames.launcher://apps/"
+ modelData.NamespaceId

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -492,12 +492,12 @@ Window {
if (windowContent.editedIndex < 0) {
uiModel.addTarget(shortcut)
} else {
if (uiModel.isInSteam(shortcut)) {
if (uiModel.updateTarget(windowContent.editedIndex, shortcut)) {
if (steamShortcutsChanged == false) {
steamChangedDialog.open();
}
} else {
if (uiModel.updateTarget(windowContent.editedIndex, shortcut)) {
if (uiModel.isInSteam(shortcut) && steamShortcutsChanged == false) {
steamChangedDialog.open();
}
} else {
if (uiModel.isInSteam(shortcut)) {
manualInfo = uiModel.manualProps(shortcut);
writeErrorDialog.open();
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,7 +21,7 @@ limitations under the License.
#include "AppLauncher.h"
#include "Settings.h"
HttpServer::HttpServer(AppLauncher& app_launcher) : app_launcher_(app_launcher)
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(close)
{
}
@ -62,6 +62,10 @@ void HttpServer::run()
res.set_content(j.dump(), "text/json");
});
server_.Post("/quit", [this](const httplib::Request& req, httplib::Response& res) {
close_();
});
server_.Get("/settings", [this](const httplib::Request& req, httplib::Response& res) {
res.set_content(Settings::toJson().dump(), "text/json");
});

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -23,7 +23,7 @@ class AppLauncher;
class HttpServer {
public:
explicit HttpServer(AppLauncher& app_launcher);
explicit HttpServer(AppLauncher& app_launcher, std::function<void()> close);
void run();
void stop();
@ -34,4 +34,5 @@ class HttpServer {
uint16_t port_ = 8756;
AppLauncher& app_launcher_;
std::function<void()> close_;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -182,6 +182,11 @@ void Overlay::update()
}
}
if (Settings::window.disableGlosSIOverlay) {
ImGui::SFML::Render(window_);
return;
}
showLogs(0);
if (enabled_ || force_enable_) {

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -54,6 +54,8 @@ inline struct Window {
int maxFps = 0;
float scale = 0.f;
bool disableOverlay = false;
bool hideAltTab = false;
bool disableGlosSIOverlay = false;
} window;
inline struct Controller {
@ -69,6 +71,8 @@ inline struct Common {
std::wstring name;
std::wstring icon;
int version;
std::wstring steamPath;
std::wstring steamUserId;
} common;
inline std::filesystem::path settings_path_ = "";
@ -189,6 +193,8 @@ inline void Parse(const nlohmann::basic_json<>& json)
safeParseValue(winconf, "maxFps", window.maxFps);
safeParseValue(winconf, "scale", window.scale);
safeParseValue(winconf, "disableOverlay", window.disableOverlay);
safeParseValue(winconf, "hideAltTab", window.hideAltTab);
safeParseValue(winconf, "disableGlosSIOverlay", window.disableGlosSIOverlay);
}
if (auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object()) {
@ -200,6 +206,9 @@ inline void Parse(const nlohmann::basic_json<>& json)
safeWStringParse(json, "name", common.name);
safeWStringParse(json, "icon", common.icon);
safeParseValue(json, "version", common.version);
safeWStringParse(json, "steamPath", common.steamPath);
safeWStringParse(json, "steamUserId", common.steamUserId);
}
catch (const nlohmann::json::exception& e) {
spdlog::warn("Err parsing config: {}", e.what());
@ -293,6 +302,7 @@ inline nlohmann::json toJson()
json["window"]["maxFps"] = window.maxFps;
json["window"]["scale"] = window.scale;
json["window"]["disableOverlay"] = window.disableOverlay;
json["window"]["hideAltTab"] = window.hideAltTab;
json["controller"]["maxControllers"] = controller.maxControllers;
json["controller"]["allowDesktopConfig"] = controller.allowDesktopConfig;
json["controller"]["emulateDS4"] = controller.emulateDS4;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -46,7 +46,7 @@ SteamTarget::SteamTarget()
delayed_shutdown_ = true;
delay_shutdown_clock_.restart();
}),
server_(launcher_)
server_(launcher_, [this] { run_ = false; })
{
target_window_handle_ = window_.getSystemHandle();
#ifdef _WIN32
@ -180,6 +180,9 @@ void SteamTarget::onOverlayChanged(bool overlay_open)
void SteamTarget::toggleGlossiOverlay()
{
if (Settings::window.disableGlosSIOverlay) {
return;
}
if (overlay_.expired()) {
return;
}
@ -253,7 +256,7 @@ std::filesystem::path SteamTarget::getSteamPath() const
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return L"";
return Settings::common.steamPath;
#else
return L""; // TODO
#endif
@ -273,7 +276,7 @@ std::wstring SteamTarget::getSteamUserId() const
catch (const winreg::RegException& e) {
spdlog::error("Couldn't get Steam path from Registry; {}", e.what());
}
return L"";
return Settings::common.steamUserId;
#else
return L""; // TODO
#endif

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -56,6 +56,11 @@ TargetWindow::TargetWindow(
if (ImGui::Checkbox("Window mode", &Settings::window.windowMode)) {
toggle_window_mode_after_frame_ = true;
}
#ifdef _WIN32
if (ImGui::Checkbox("Hide from Alt+Tab", &Settings::window.hideAltTab)) {
toggle_hidealttab_after_frame_ = true;
}
#endif
ImGui::Text("Max. FPS");
ImGui::SameLine();
int max_fps_copy = Settings::window.maxFps;
@ -116,13 +121,30 @@ void TargetWindow::setClickThrough(bool click_through)
}
#ifdef _WIN32
HWND hwnd = window_.getSystemHandle();
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
// hiding GlosSI from Alt-Tab list
// https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
if (Settings::window.hideAltTab) {
toggle_hidealttab_after_frame_ = false;
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED | WS_EX_TOOLWINDOW);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED | WS_EX_TOOLWINDOW);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
if (click_through) {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
else {
SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_LAYERED | WS_EX_COMPOSITED);
SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
}
#endif
}
@ -142,9 +164,15 @@ void TargetWindow::update()
screenShotWorkaround();
overlay_->update();
window_.display();
#ifdef _WIN32
if (toggle_hidealttab_after_frame_) {
toggle_hidealttab_after_frame_ = false;
}
#endif
if (toggle_window_mode_after_frame_) {
createWindow();
}
// As SFML screws us out of most windows-events, just poll resolution every once in a while
// If changed, recreate window.
// Fixes Blackscreen issues when user does funky stuff and still uses GlosSI in non windowed mod...
@ -335,6 +363,7 @@ void TargetWindow::createWindow()
style &= ~WS_OVERLAPPED;
style |= WS_POPUP;
SetWindowLong(hwnd, GWL_STYLE, style);
MARGINS margins;
margins.cxLeftWidth = -1;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -82,4 +82,5 @@ class TargetWindow {
void createWindow();
bool toggle_window_mode_after_frame_ = false;
bool toggle_hidealttab_after_frame_ = false;
};

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -15,12 +15,63 @@ limitations under the License.
*/
#include "UnhookUtil.h"
#ifndef CONFIGAPP
#include <spdlog/spdlog.h>
#include "Settings.h"
#endif
void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
{
#ifndef CONFIGAPP
std::map<std::string, std::string> original_bytes_from_file;
wchar_t* localAppDataFolder;
std::filesystem::path configDirPath;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &localAppDataFolder) != S_OK) {
configDirPath = std::filesystem::temp_directory_path().parent_path().parent_path().parent_path();
}
else {
configDirPath = std::filesystem::path(localAppDataFolder).parent_path();
}
configDirPath /= "Roaming";
configDirPath /= "GlosSI";
if (std::filesystem::exists(configDirPath)) {
auto unhook_file_path = configDirPath / "unhook_bytes";
if (std::filesystem::exists(unhook_file_path)) {
std::ifstream ifile;
ifile.open(unhook_file_path, std::ios::binary | std::ios::in);
if (ifile.is_open()) {
std::string funcName;
char buff;
do {
if (ifile.eof()) {
break;
}
ifile.read(&buff, sizeof(char));
if (buff != ':') {
funcName.push_back(buff);
} else {
char bytes[8];
ifile.read(bytes, sizeof(char) * 8);
ifile.read(&buff, sizeof(char)); // newline
original_bytes_from_file[funcName] = std::string(bytes, 8);
funcName = "";
}
} while (!ifile.eof());
ifile.close();
}
}
}
spdlog::trace("Patching \"{}\"...", name);
BYTE* address = reinterpret_cast<BYTE*>(GetProcAddress(module, name.c_str()));
@ -28,11 +79,19 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
spdlog::error("failed to unpatch \"{}\"", name);
}
std::string bytes;
if (Settings::isWin10 && UNHOOK_BYTES_ORIGINAL_WIN10.contains(name)) {
bytes = UNHOOK_BYTES_ORIGINAL_WIN10.at(name);
if (original_bytes_from_file.contains(name)) {
bytes = original_bytes_from_file.at(name);
spdlog::trace("Using originalBytes from file for {}", name);
}
else {
bytes = UNHOOK_BYTES_ORIGINAL_22000.at(name);
if (Settings::isWin10 && UNHOOK_BYTES_ORIGINAL_WIN10.contains(name)) {
bytes = UNHOOK_BYTES_ORIGINAL_WIN10.at(name);
}
else {
bytes = UNHOOK_BYTES_ORIGINAL_22000.at(name);
}
spdlog::trace("Using fallback originalBytes for {}", name);
}
DWORD dw_old_protect, dw_bkup;
const auto len = bytes.size();
@ -52,4 +111,18 @@ void UnhookUtil::UnPatchHook(const std::string& name, HMODULE module)
spdlog::trace("Unpatched \"{}\"", name);
}
VirtualProtect(address, len, dw_old_protect, &dw_bkup); // Revert permission change...
#endif
}
std::string UnhookUtil::ReadOriginalBytes(const std::string& name, const std::wstring& moduleName)
{
auto module = LoadLibraryW(moduleName.c_str());
auto address = reinterpret_cast<BYTE*>(GetProcAddress(module, name.c_str()));
std::string res;
res.resize(8);
for (int i = 0; i < 8; i++) {
res[i] = static_cast<char>(*(address + i));
}
return res;
}

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -25,6 +25,8 @@ limitations under the License.
namespace UnhookUtil {
void UnPatchHook(const std::string& name, HMODULE module);
std::string ReadOriginalBytes(const std::string& name, const std::wstring& moduleName);
static inline const std::vector<uint8_t> JUMP_INSTR_OPCODES = {
0xE9,
0xE8,
@ -34,6 +36,9 @@ static inline const std::vector<uint8_t> JUMP_INSTR_OPCODES = {
// Valve Hooks various functions and hides Gaming devices like this.
// To be able to query them, unpatch the hook with the original bytes...
// Bytes here are just fallbacks; originalbytes will get read from GlosSIConfig and stored in %APPDATA%\GlosSI\unhook_bytes
// 22000 ^= Windows build number
static inline const std::map<std::string, std::string> UNHOOK_BYTES_ORIGINAL_22000 = {
{"SetupDiEnumDeviceInfo", "\x48\x89\x5C\x24\x08"},

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -168,8 +168,9 @@ int main(int argc, char* argv[])
auto existingwindow = FindWindowA(nullptr, "GlosSITarget");
if (existingwindow) {
spdlog::error("GlosSITarget is already running!");
return 1;
spdlog::error("GlosSITarget is already running! Closing old process...");
httplib::Client client("http://localhost:8756");
client.Post("/quit");
}
int numArgs;

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -67,7 +67,7 @@ For Building instructions refer to [BUILDING.md](./docs/BUILDING.md)
## License
```license
Copyright 2017-2022 Peter Repukat - FlatspotSoftware
Copyright 2017-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -1,5 +1,5 @@
/*
Copyright 2021-2022 Peter Repukat - FlatspotSoftware
Copyright 2021-2023 Peter Repukat - FlatspotSoftware
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

@ -121,11 +121,11 @@ The GlosSI overlay can also be navigated with controller-inputs
Rename the shortcut in Steam to the Steam-AppID of the game you want to access to community-configs.
Community configs may only be available **before** you launch the shortcut.
AppIDs can be retrieved from [SteamDB](https://steamdb.info/apps/)
AppIDs can be retrieved from [SteamDB](https://steamdb.info/apps/) or [Steambase](https://steambase.io/apps)
<details>
<summary>Screenie 📸</summary>
![appid-trick](./appid_trick.png)
</details>
</details>

Loading…
Cancel
Save