Merge pull request #179 from Alia5/develop

Develop
pull/184/head 0.0.9.0
Peter Repukat 2 years ago committed by GitHub
commit e8b2ab0ec0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,5 @@
UseTab: false UseTab: false
BasedOnStyle: LLVM
IndentWidth: 4 IndentWidth: 4
BreakBeforeBraces: "Stroustrup" BreakBeforeBraces: "Stroustrup"
AllowShortIfStatementsOnASingleLine: false AllowShortIfStatementsOnASingleLine: false

@ -137,6 +137,8 @@
<ClCompile Include="UIModel.cpp" /> <ClCompile Include="UIModel.cpp" />
<None Include=".clang-format" /> <None Include=".clang-format" />
<None Include="GetAUMIDs.ps1" /> <None Include="GetAUMIDs.ps1" />
<None Include="qml\CollapsiblePane.qml" />
<None Include="qml\SteamInputXboxDisabledDialog.qml" />
<None Include="qml\AddSelectTypeDialog.qml" /> <None Include="qml\AddSelectTypeDialog.qml" />
<None Include="qml\FluentTextInput.qml" /> <None Include="qml\FluentTextInput.qml" />
<None Include="qml\InfoDialog.qml" /> <None Include="qml\InfoDialog.qml" />
@ -144,6 +146,7 @@
<None Include="qml\ShortcutCards.qml" /> <None Include="qml\ShortcutCards.qml" />
<None Include="qml\ShortcutProps.qml" /> <None Include="qml\ShortcutProps.qml" />
<None Include="qml\UWPSelectDialog.qml" /> <None Include="qml\UWPSelectDialog.qml" />
<None Include="qml\SteamNotFoundDialog.qml" />
<QtRcc Include="qml.qrc" /> <QtRcc Include="qml.qrc" />
<None Include="qml\main.qml" /> <None Include="qml\main.qml" />
</ItemGroup> </ItemGroup>

@ -65,6 +65,15 @@
</None> </None>
<None Include=".clang-format" /> <None Include=".clang-format" />
<None Include="GetAUMIDs.ps1" /> <None Include="GetAUMIDs.ps1" />
<None Include="qml\SteamNotFoundDialog.qml">
<Filter>qml</Filter>
</None>
<None Include="qml\SteamInputXboxDisabledDialog.qml">
<Filter>qml</Filter>
</None>
<None Include="qml\CollapsiblePane.qml">
<Filter>qml</Filter>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="UIModel.h"> <QtMoc Include="UIModel.h">

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,8,003002880001 FILEVERSION 0,0,8,1023005406006
PRODUCTVERSION 0,0,8,003002880001 PRODUCTVERSION 0,0,8,1023005406006
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.0.8.0-3-g288bba1" VALUE "FileVersion", "0.0.8.1-23-g54e6bf6"
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.0.8.0-3-g288bba1" VALUE "ProductVersion", "0.0.8.1-23-g54e6bf6"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -756,6 +756,342 @@ IDI_ICON1 ICON "..\GloSC_Icon.ico"

@ -39,16 +39,16 @@ UIModel::UIModel() : QObject(nullptr)
std::filesystem::create_directories(path); std::filesystem::create_directories(path);
config_path_ = path; config_path_ = path;
config_dir_name_ = QString::fromStdWString((path /= "Targets").wstring().data()); config_dir_name_ = QString::fromStdWString((path /= "Targets").wstring());
if (!std::filesystem::exists(path)) if (!std::filesystem::exists(path))
std::filesystem::create_directories(path); std::filesystem::create_directories(path);
parseShortcutVDF(); parseShortcutVDF();
readConfigs(); readTargetConfigs();
} }
void UIModel::readConfigs() void UIModel::readTargetConfigs()
{ {
QDir dir(config_dir_name_); QDir dir(config_dir_name_);
auto entries = dir.entryList(QDir::Files, QDir::SortFlag::Name); auto entries = dir.entryList(QDir::Files, QDir::SortFlag::Name);
@ -68,29 +68,13 @@ void UIModel::readConfigs()
const auto data = file.readAll(); const auto data = file.readAll();
file.close(); file.close();
const auto jsondoc = QJsonDocument::fromJson(data); const auto jsondoc = QJsonDocument::fromJson(data);
const auto filejson = jsondoc.object(); auto filejson = jsondoc.object();
QJsonObject json; filejson["name"] = filejson.contains("name")
json["version"] = filejson["version"]; ? filejson["name"].toString()
json["icon"] = filejson["icon"]; : QString(name).replace(QRegularExpression("\\.json"), "");
json["launch"] = filejson["launch"]["launch"];
json["launchPath"] = filejson["launch"]["launchPath"]; targets_.append(filejson.toVariantMap());
json["launchAppArgs"] = filejson["launch"]["launchAppArgs"];
json["closeOnExit"] = filejson["launch"]["closeOnExit"];
json["waitForChildProcs"] = filejson["launch"]["waitForChildProcs"];
json["hideDevices"] = filejson["devices"]["hideDevices"];
json["realDeviceIds"] = filejson["devices"]["realDeviceIds"];
json["windowMode"] = filejson["window"]["windowMode"];
json["maxFps"] = filejson["window"]["maxFps"];
json["scale"] = filejson["window"]["scale"];
json["disableOverlay"] = filejson["window"]["disableOverlay"];
json["maxControllers"] = filejson["controller"]["maxControllers"];
json["allowDesktopConfig"] = filejson["controller"]["allowDesktopConfig"];
json["emulateDS4"] = filejson["controller"]["emulateDS4"];
json["name"] = filejson.contains("name") ? filejson["name"] : QString(name).replace(QRegularExpression("\\.json"), "");
targets_.append(json.toVariantMap());
}); });
emit targetListChanged(); emit targetListChanged();
@ -237,6 +221,46 @@ QVariantMap UIModel::manualProps(QVariant shortcut)
return res; return res;
} }
void UIModel::enableSteamInputXboxSupport()
{
if (foundSteam()) {
const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + user_config_file_.toStdWString();
if (!std::filesystem::exists(config_path)) {
qDebug() << "localconfig.vdf does not exist.";
}
QFile file(config_path);
if (file.open(QIODevice::Text | QIODevice::ReadOnly)) {
QTextStream in(&file);
QStringList lines;
QString line = in.readLine();
// simple approach is enough...
while (!in.atEnd()) {
if (line.contains("SteamController_XBoxSupport")) {
if (line.contains("1")) {
qDebug() << "\"SteamController_XBoxSupport\" is already enabled! aborting write...";
file.close();
return;
}
qDebug() << "found \"SteamController_XBoxSupport\" line, replacing value...";
line.replace("0", "1");
}
lines.push_back(line);
line = in.readLine();
}
file.close();
QFile updatedFile(config_path);
if (updatedFile.open(QFile::WriteOnly | QFile::Truncate | QFile::Text)) {
qDebug() << "writing localconfig.vdf...";
QTextStream out(&updatedFile);
for (const auto& l : lines) {
out << l << "\n";
}
}
updatedFile.close();
}
}
}
#ifdef _WIN32 #ifdef _WIN32
QVariantList UIModel::uwpApps() QVariantList UIModel::uwpApps()
{ {
@ -319,60 +343,41 @@ void UIModel::setAcrylicEffect(bool has_acrylic_affect)
emit acrylicChanged(); emit acrylicChanged();
} }
void UIModel::writeTarget(const QJsonObject& json, const QString& name) void UIModel::writeTarget(const QJsonObject& json, const QString& name) const
{ {
auto path = config_path_; auto path = config_path_;
path /= config_dir_name_.toStdWString(); path /= config_dir_name_.toStdWString();
path /= (QString(name).replace(QRegularExpression("[\\\\/:*?\"<>|]"), "") + ".json").toStdWString(); path /= (QString(name).replace(QRegularExpression("[\\\\/:*?\"<>|]"), "") + ".json").toStdWString();
QFile file(path); QFile file(path);
if (!file.open(QIODevice::Text | QIODevice::ReadWrite)) { if (!file.open(QIODevice::Text | QIODevice::ReadWrite)) {
// meh qDebug() << "Couldn't open file for writing: " << path;
return; return;
} }
QJsonObject fileJson;
fileJson["version"] = json["version"]; file.write(
fileJson["icon"] = json["icon"]; QString(QJsonDocument(json).toJson(QJsonDocument::Indented))
fileJson["name"] = json["name"]; .toStdString()
.data()
QJsonObject launchObject; );
launchObject["launch"] = json["launch"];
launchObject["launchPath"] = json["launchPath"];
launchObject["launchAppArgs"] = json["launchAppArgs"];
launchObject["closeOnExit"] = json["closeOnExit"];
launchObject["waitForChildProcs"] = json["waitForChildProcs"];
fileJson["launch"] = launchObject;
QJsonObject devicesObject;
devicesObject["hideDevices"] = json["hideDevices"];
devicesObject["realDeviceIds"] = json["realDeviceIds"];
fileJson["devices"] = devicesObject;
QJsonObject windowObject;
windowObject["windowMode"] = json["windowMode"];
windowObject["maxFps"] = json["maxFps"];
windowObject["scale"] = json["scale"];
windowObject["disableOverlay"] = json["disableOverlay"];
fileJson["window"] = windowObject;
QJsonObject controllerObject;
controllerObject["maxControllers"] = json["maxControllers"];
controllerObject["allowDesktopConfig"] = json["allowDesktopConfig"];
controllerObject["emulateDS4"] = json["emulateDS4"];
fileJson["controller"] = controllerObject;
auto wtf = QString(QJsonDocument(fileJson).toJson(QJsonDocument::Indented)).toStdString();
file.write(wtf.data());
file.close(); file.close();
} }
std::filesystem::path UIModel::getSteamPath() const std::filesystem::path UIModel::getSteamPath() const
{ {
try {
#ifdef _WIN32 #ifdef _WIN32
// TODO: check if keys/value exist // TODO: check if keys/value exist
// steam should always be open and have written reg values... // steam should always be open and have written reg values...
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam"}; winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam"};
const auto res = key.GetStringValue(L"SteamPath"); if (!key.IsValid()) {
return res; return "";
}
const auto res = key.GetStringValue(L"SteamPath");
return res;
}
catch (...) {
return "";
}
#else #else
return L""; // TODO LINUX return L""; // TODO LINUX
#endif #endif
@ -381,22 +386,46 @@ std::filesystem::path UIModel::getSteamPath() const
std::wstring UIModel::getSteamUserId() const std::wstring UIModel::getSteamUserId() const
{ {
#ifdef _WIN32 #ifdef _WIN32
// TODO: check if keys/value exist try {
// steam should always be open and have written reg values... // TODO: check if keys/value exist
winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"}; // steam should always be open and have written reg values...
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser")); winreg::RegKey key{HKEY_CURRENT_USER, L"SOFTWARE\\Valve\\Steam\\ActiveProcess"};
if (res == L"0") { if (!key.IsValid()) {
qDebug() << "Steam not open?"; return L"0";
}
const auto res = std::to_wstring(key.GetDwordValue(L"ActiveUser"));
if (res == L"0") {
qDebug() << "Steam not open?";
}
return res;
} catch(...) {
return L"0";
} }
return res;
#else #else
return L""; // TODO LINUX return L""; // TODO LINUX
#endif #endif
} }
bool UIModel::foundSteam() const
{
if (getSteamPath() == "" || getSteamUserId() == L"0") {
return false;
}
const std::filesystem::path user_config_dir = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId();
if (!std::filesystem::exists(user_config_dir)) {
return false;
}
return true;
}
void UIModel::parseShortcutVDF() void UIModel::parseShortcutVDF()
{ {
const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + shortcutsfile_.toStdWString(); const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + shortcutsfile_.toStdWString();
if (!std::filesystem::exists(config_path)) {
qDebug() << "Shortcuts file does not exist.";
return;
}
try { try {
shortcuts_vdf_ = VDFParser::Parser::parseShortcuts(config_path, qDebug()); shortcuts_vdf_ = VDFParser::Parser::parseShortcuts(config_path, qDebug());
} }
@ -404,3 +433,39 @@ void UIModel::parseShortcutVDF()
qDebug() << "Error parsing VDF: " << e.what(); qDebug() << "Error parsing VDF: " << e.what();
} }
} }
bool UIModel::isSteamInputXboxSupportEnabled() const
{
// return true as default to not bug the user in error cases.
if (foundSteam()) {
const std::filesystem::path config_path = std::wstring(getSteamPath()) + user_data_path_.toStdWString() + getSteamUserId() + user_config_file_.toStdWString();
if (!std::filesystem::exists(config_path)) {
qDebug() << "localconfig.vdf does not exist.";
return true;
}
QFile file(config_path);
if (file.open(QIODevice::Text | QIODevice::ReadOnly)) {
QTextStream in(&file);
QString line = in.readLine();
// simple, regex approach should be enough...
while (!in.atEnd()) {
if (line.contains("SteamController_XBoxSupport")) {
file.close();
if (line.contains("1")) {
qDebug() << "\"SteamController_XBoxSupport\" is enabled!";
return true;
}
qDebug() << "\"SteamController_XBoxSupport\" is disabled!";
return false;
}
line = in.readLine();
}
qDebug() << "couldn't find \"SteamController_XBoxSupport\" in localconfig.vdf";
file.close();
}
else {
qDebug() << "could not open localconfig.vdf";
}
}
return true;
}

@ -27,11 +27,13 @@ class UIModel : public QObject {
Q_PROPERTY(bool hasAcrlyicEffect READ hasAcrylicEffect NOTIFY acrylicChanged) Q_PROPERTY(bool hasAcrlyicEffect READ hasAcrylicEffect NOTIFY acrylicChanged)
Q_PROPERTY(QVariantList targetList READ getTargetList NOTIFY targetListChanged) Q_PROPERTY(QVariantList targetList READ getTargetList NOTIFY targetListChanged)
Q_PROPERTY(QVariantList uwpList READ uwpApps CONSTANT) Q_PROPERTY(QVariantList uwpList READ uwpApps CONSTANT)
Q_PROPERTY(bool foundSteam READ foundSteam CONSTANT)
Q_PROPERTY(bool steamInputXboxSupportEnabled READ isSteamInputXboxSupportEnabled CONSTANT)
public: public:
UIModel(); UIModel();
Q_INVOKABLE void readConfigs(); Q_INVOKABLE void readTargetConfigs();
Q_INVOKABLE QVariantList getTargetList() const; Q_INVOKABLE QVariantList getTargetList() const;
Q_INVOKABLE void addTarget(QVariant shortcut); Q_INVOKABLE void addTarget(QVariant shortcut);
Q_INVOKABLE void updateTarget(int index, QVariant shortcut); Q_INVOKABLE void updateTarget(int index, QVariant shortcut);
@ -41,6 +43,7 @@ class UIModel : public QObject {
bool addToSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); bool addToSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false);
Q_INVOKABLE bool removeFromSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false); Q_INVOKABLE bool removeFromSteam(const QString& name, const QString& shortcutspath, bool from_cmd = false);
Q_INVOKABLE QVariantMap manualProps(QVariant shortcut); Q_INVOKABLE QVariantMap manualProps(QVariant shortcut);
Q_INVOKABLE void enableSteamInputXboxSupport();
#ifdef _WIN32 #ifdef _WIN32
Q_INVOKABLE QVariantList uwpApps(); Q_INVOKABLE QVariantList uwpApps();
#endif #endif
@ -61,25 +64,30 @@ class UIModel : public QObject {
void targetListChanged(); void targetListChanged();
private: private:
#ifdef _WIN32
bool is_windows_ = true;
#else
bool is_windows_ = false;
#endif
bool has_acrylic_affect_ = false;
std::filesystem::path config_path_; std::filesystem::path config_path_;
QString config_dir_name_; QString config_dir_name_;
void writeTarget(const QJsonObject& json, const QString& name);
std::filesystem::path getSteamPath() const;
std::wstring getSteamUserId() const;
void parseShortcutVDF();
QString shortcutsfile_ = "/config/shortcuts.vdf"; QString shortcutsfile_ = "/config/shortcuts.vdf";
QString user_config_file_ = "/config/localconfig.vdf";
QString user_data_path_ = "/userdata/"; QString user_data_path_ = "/userdata/";
QVariantList targets_; QVariantList targets_;
std::vector<VDFParser::Shortcut> shortcuts_vdf_; std::vector<VDFParser::Shortcut> shortcuts_vdf_;
void writeTarget(const QJsonObject& json, const QString& name) const;
#ifdef _WIN32 std::filesystem::path getSteamPath() const;
bool is_windows_ = true; std::wstring getSteamUserId() const;
#else bool foundSteam() const;
bool is_windows_ = false; void parseShortcutVDF();
#endif
bool has_acrylic_affect_ = false; bool isSteamInputXboxSupportEnabled() const;
}; };

@ -15,5 +15,9 @@
<file>noise.png</file> <file>noise.png</file>
<file>GloSC_Icon_small.png</file> <file>GloSC_Icon_small.png</file>
<file>svg/help_outline_white_24dp.svg</file> <file>svg/help_outline_white_24dp.svg</file>
<file>qml/SteamNotFoundDialog.qml</file>
<file>qml/SteamInputXboxDisabledDialog.qml</file>
<file>qml/CollapsiblePane.qml</file>
<file>svg/expand_more_white_24dp.svg</file>
</qresource> </qresource>
</RCC> </RCC>

@ -0,0 +1,97 @@
/*
Copyright 2021-2022 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import QtQuick 2.9
import QtQuick.Controls 2.9
import QtQuick.Controls.Material 2.9
import QtQuick.Controls.Material.impl 2.9
RPane {
property alias title: paneTitle.text
width: parent.width
property alias content: ldr.sourceComponent
clip: true
height: paneHeader.height + collapseColumn.spacing
property bool collapsed: true
id: collapsePane
Behavior on height {
NumberAnimation {
duration: 300
easing.type: Easing.InOutQuad
}
}
Column {
id: collapseColumn
width: parent.width
spacing: 16
Item {
id: paneHeader
width: parent.width
height: paneTitle.height + 32
Label {
id: paneTitle
anchors.left: parent.left
anchors.leftMargin: 4
font.bold: true
font.pixelSize: 24
anchors.top: parent.top
anchors.topMargin: 14
}
RoundButton {
width: 48
height: 48
Material.elevation: 0
anchors.rightMargin: 0
anchors.top: parent.top
anchors.topMargin: 0
onClicked: function(){
collapsed = !collapsed;
if (collapsed) {
collapsePane.height = paneHeader.height + collapseColumn.spacing
} else {
collapsePane.height = paneHeader.height + collapseColumn.spacing * 3 + ldr.item.height
}
}
Image {
id: arrowImg
anchors.centerIn: parent
source: "qrc:/svg/expand_more_white_24dp.svg"
width: 24
height: 24
transform: Rotation{
angle: collapsed ? 0 : 180
origin.x: arrowImg.width/2
origin.y: arrowImg.height/2
Behavior on angle {
NumberAnimation {
duration: 125
easing.type: Easing.InOutQuad
}
}
}
}
anchors.right: parent.right
}
}
Loader {
id: ldr
width: parent.width
}
}
}

@ -29,62 +29,62 @@ Item {
signal cancel() signal cancel()
signal done(var shortcut) signal done(var shortcut)
property var shortcutInfo: ({ property var shortcutInfo: ({})
version: 1,
name: null,
launch: false,
launchPath: null,
launchAppArgs: null,
closeOnExit: true,
waitForChildProcs: true,
hideDevices: true,
windowMode: false,
maxFps: null,
scale: null,
icon: null,
maxControllers: 4,
disableOverlay: false,
realDeviceIds: false,
allowDesktopConfig: false,
emulateDS4: false,
})
function resetInfo() { function resetInfo() {
shortcutInfo = ({ shortcutInfo = ({
version: 1, "controller": {
name: null, "maxControllers": 1,
launch: false, "emulateDS4": false,
launchPath: null, "allowDesktopConfig": false
launchAppArgs: null, },
closeOnExit: true, "devices": {
waitForChildProcs: true, "hideDevices": true,
hideDevices: true, "realDeviceIds": false
windowMode: false, },
maxFps: null, "icon": null,
scale: null, "launch": {
icon: null, "closeOnExit": true,
maxControllers: 4, "launch": false,
disableOverlay: false, "launchAppArgs": null,
realDeviceIds: false, "launchPath": null,
allowDesktopConfig: false, "waitForChildProcs": true
emulateDS4: false, },
"name": null,
"version": 1,
"window": {
"disableOverlay": false,
"maxFps": null,
"scale": null,
"windowMode": false
},
"extendedLogging": false
}) })
} }
Component.onCompleted: function() {
resetInfo()
}
onShortcutInfoChanged: function() { onShortcutInfoChanged: function() {
nameInput.text = shortcutInfo.name || "" nameInput.text = shortcutInfo.name || ""
launchApp.checked = shortcutInfo.launch || false if (extendedLogging) {
pathInput.text = shortcutInfo.launchPath || "" extendedLogging.checked = shortcutInfo.extendedLogging || false
argsInput.text = shortcutInfo.launchAppArgs || "" }
closeOnExit.checked = shortcutInfo.closeOnExit || false launchApp.checked = shortcutInfo.launch.launch
waitForChildren.checked = shortcutInfo.waitForChildProcs pathInput.text = shortcutInfo.launch.launchPath || ""
hideDevices.checked = shortcutInfo.hideDevices || false argsInput.text = shortcutInfo.launch.launchAppArgs || ""
windowMode.checked = shortcutInfo.windowMode || false closeOnExit.checked = shortcutInfo.launch.closeOnExit
maxControllersSpinBox.value = shortcutInfo.maxControllers waitForChildren.checked = shortcutInfo.launch.waitForChildProcs
disableOverlayCheckbox.checked = shortcutInfo.disableOverlay || false hideDevices.checked = shortcutInfo.devices.hideDevices
realDeviceIds.checked = shortcutInfo.realDeviceIds || false realDeviceIds.checked = shortcutInfo.devices.realDeviceIds
allowDesktopConfig.checked = shortcutInfo.allowDesktopConfig || false windowMode.checked = shortcutInfo.window.windowMode
emulateDS4.checked = shortcutInfo.emulateDS4 || false disableOverlayCheckbox.checked = shortcutInfo.window.disableOverlay
scaleSpinBox.value = shortcutInfo.window.scale
maxFPSSpinBox.value = shortcutInfo.window.maxFps
maxControllersSpinBox.value = shortcutInfo.controller.maxControllers
allowDesktopConfig.checked = shortcutInfo.controller.allowDesktopConfig
emulateDS4.checked = shortcutInfo.controller.emulateDS4
} }
Flickable { Flickable {
@ -144,7 +144,6 @@ Item {
} }
RPane { RPane {
width: parent.width width: parent.width
height: 248
radius: 4 radius: 4
Material.elevation: 32 Material.elevation: 32
bgOpacity: 0.97 bgOpacity: 0.97
@ -155,17 +154,18 @@ Item {
Row { Row {
spacing: 32 spacing: 32
width: parent.width width: parent.width
height: closeOnExitCol.height
CheckBox { CheckBox {
id: launchApp id: launchApp
text: qsTr("Launch app") text: qsTr("Launch app")
checked: shortcutInfo.launch checked: shortcutInfo.launch.launch
onCheckedChanged: function() { onCheckedChanged: function() {
shortcutInfo.launch = checked shortcutInfo.launch.launch = checked
if (checked) { if (checked) {
closeOnExit.enabled = true; if (closeOnExit) {
if (closeOnExit.checked) { closeOnExit.enabled = true;
waitForChildren.enabled = true; if (closeOnExit.checked) {
waitForChildren.enabled = true;
}
} }
allowDesktopConfig.enabled = true; allowDesktopConfig.enabled = true;
} else { } else {
@ -175,54 +175,6 @@ Item {
} }
} }
} }
Column {
id: closeOnExitCol
spacing: 2
CheckBox {
id: closeOnExit
text: qsTr("Close when launched app quits")
checked: shortcutInfo.closeOnExit
onCheckedChanged: function() {
shortcutInfo.closeOnExit = checked
if (checked) {
waitForChildren.enabled = true;
} else {
waitForChildren.enabled = false;
}
}
}
Label {
text: qsTr("Recommended to disable for launcher-games")
wrapMode: Text.WordWrap
width: parent.width
leftPadding: 32
topPadding: -8
}
CheckBox {
id: waitForChildren
text: qsTr("Wait for child processes")
checked: shortcutInfo.waitForChildProcs
onCheckedChanged: function(){
shortcutInfo.waitForChildProcs = checked
}
}
}
Column {
spacing: 2
CheckBox {
id: allowDesktopConfig
text: qsTr("Allow desktop-config")
checked: shortcutInfo.allowDesktopConfig
onCheckedChanged: function(){
shortcutInfo.allowDesktopConfig = checked
}
}
Label {
text: qsTr("Use desktop-config if launched application is not focused")
leftPadding: 32
topPadding: -8
}
}
} }
Item { Item {
width: 1 width: 1
@ -231,14 +183,17 @@ Item {
RowLayout { RowLayout {
id: launchlayout id: launchlayout
spacing: 4 spacing: 4
width: parent.width anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: 32
anchors.rightMargin: 32
Image { Image {
id: maybeIcon id: maybeIcon
source: shortcutInfo.icon source: shortcutInfo.icon
? shortcutInfo.icon.endsWith(".exe") ? shortcutInfo.icon.endsWith(".exe")
? "image://exe/" + shortcutInfo.icon ? "image://exe/" + shortcutInfo.icon
: "file:///" + shortcutInfo.icon : "file:///" + shortcutInfo.icon
: null : ''
Layout.preferredWidth: 48 Layout.preferredWidth: 48
Layout.preferredHeight: 48 Layout.preferredHeight: 48
visible: shortcutInfo.icon visible: shortcutInfo.icon
@ -267,8 +222,8 @@ Item {
id: pathInput id: pathInput
placeholderText: qsTr("...") placeholderText: qsTr("...")
enabled: launchApp.checked enabled: launchApp.checked
text: shortcutInfo.launchPath || "" text: shortcutInfo.launch.launchPath || ""
onTextChanged: shortcutInfo.launchPath = text onTextChanged: shortcutInfo.launch.launchPath = text
} }
} }
Button { Button {
@ -304,8 +259,8 @@ Item {
anchors.topMargin: 4 anchors.topMargin: 4
id: argsInput id: argsInput
enabled: launchApp.checked enabled: launchApp.checked
text: shortcutInfo.launchAppArgs text: shortcutInfo.launch.launchAppArgs
onTextChanged: shortcutInfo.launchAppArgs = text onTextChanged: shortcutInfo.launch.launchAppArgs = text
} }
} }
} }
@ -315,183 +270,467 @@ Item {
width: 1 width: 1
height: 8 height: 8
} }
Row {
spacing: 16
width: parent.width
RPane { CollapsiblePane {
width: parent.width / 2 - 8 radius: 4
height: 264 Material.elevation: 32
radius: 4 bgOpacity: 0.97
Material.elevation: 32 title: qsTr("Advanced")
bgOpacity: 0.97 content:
Column {
spacing: 16
Column { RPane {
spacing: 2
width: parent.width width: parent.width
Row { radius: 4
CheckBox { Material.elevation: 32
id: hideDevices bgOpacity: 0.97
text: qsTr("Hide (Real) Controllers") height: advancedLaunchCol.height + 24
checked: shortcutInfo.hideDevices Column {
onCheckedChanged: shortcutInfo.hideDevices = checked id: advancedLaunchCol
} spacing: 4
RoundButton { height: advancedLaunchedRow.height
onClicked: () => { Row {
helpInfoDialog.titleText = qsTr("Hide (Real) Controllers") id: advancedLaunchedRow
helpInfoDialog.text = spacing: 32
qsTr("Hides real game controllers from the system\nThis may prevent doubled inputs") width: parent.width
+ "\n" height: closeOnExitCol.height
+ qsTr("You can change this setting and which devices are hidden in the GlosSI overlay") Column {
id: closeOnExitCol
helpInfoDialog.open() spacing: 2
CheckBox {
id: closeOnExit
text: qsTr("Close when launched app quits")
checked: shortcutInfo.launch.closeOnExit
onCheckedChanged: function() {
shortcutInfo.launch.closeOnExit = checked
if (checked) {
waitForChildren.enabled = true;
} else {
waitForChildren.enabled = false;
}
}
}
Label {
text: qsTr("Recommended to disable for launcher-games")
wrapMode: Text.WordWrap
width: parent.width
leftPadding: 32
topPadding: -8
}
CheckBox {
id: waitForChildren
text: qsTr("Wait for child processes")
checked: shortcutInfo.launch.waitForChildProcs
onCheckedChanged: function(){
shortcutInfo.launch.waitForChildProcs = checked
}
}
} }
width: 48 Column {
height: 48 spacing: 2
Material.elevation: 0 CheckBox {
anchors.topMargin: 16 id: allowDesktopConfig
Image { text: qsTr("Allow desktop-config")
anchors.centerIn: parent checked: shortcutInfo.controller.allowDesktopConfig
source: "qrc:/svg/help_outline_white_24dp.svg" onCheckedChanged: function(){
width: 24 shortcutInfo.controller.allowDesktopConfig = checked
height: 24 }
}
Label {
text: qsTr("Allow desktop-config if launched application is not focused")
leftPadding: 32
topPadding: -8
}
} }
} }
} }
Item { }
width: 1
height: 4 Row {
} spacing: 16
Row { width: parent.width
CheckBox {
id: realDeviceIds RPane {
text: qsTr("Use real device (USB)-IDs") width: parent.width / 2 - 8
checked: shortcutInfo.realDeviceIds height: 248
onCheckedChanged: shortcutInfo.realDeviceIds = checked radius: 4
} Material.elevation: 32
RoundButton { bgOpacity: 0.97
onClicked: () => {
helpInfoDialog.titleText = qsTr("Use real device (USB)-IDs") Column {
helpInfoDialog.text = spacing: 0
qsTr("Only enable if input's are not recognized by the game") width: parent.width
+ "\n" Row {
+ qsTr("If enabled, device-hiding won't work.\nUse the \"Max. Controller count\" setting!") CheckBox {
id: hideDevices
helpInfoDialog.open() text: qsTr("Hide (Real) Controllers")
checked: shortcutInfo.devices.hideDevices
onCheckedChanged: shortcutInfo.devices.hideDevices = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Hide (Real) Controllers")
helpInfoDialog.text =
qsTr("Hides real game controllers from the system\nThis may prevent doubled inputs")
+ "\n"
+ qsTr("You can change this setting and which devices are hidden in the GlosSI 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
}
}
} }
width: 48 Item {
height: 48 width: 1
Material.elevation: 0 height: 4
anchors.topMargin: 16
Image {
anchors.centerIn: parent
source: "qrc:/svg/help_outline_white_24dp.svg"
width: 24
height: 24
} }
} Row {
} CheckBox {
Item { id: realDeviceIds
width: 1 text: qsTr("Use real device (USB)-IDs")
height: 4 checked: shortcutInfo.devices.realDeviceIds
} onCheckedChanged: shortcutInfo.devices.realDeviceIds = checked
Row { }
CheckBox { RoundButton {
id: emulateDS4 onClicked: () => {
text: qsTr("Emulate DS4") helpInfoDialog.titleText = qsTr("Use real device (USB)-IDs")
checked: shortcutInfo.emulateDS4 helpInfoDialog.text =
onCheckedChanged: shortcutInfo.emulateDS4 = checked qsTr("Only enable if input's are not recognized by the game")
} + "\n"
RoundButton { + qsTr("If enabled, device-hiding won't work.\nUse the \"Max. Controller count\" setting!")
onClicked: () => {
helpInfoDialog.titleText = qsTr("Emulate DS4") helpInfoDialog.open()
helpInfoDialog.text = }
qsTr("Instead of X360 Pad") width: 48
+ "\n" height: 48
+ qsTr("Disable \"Playstation Configuration support\" in Steam") Material.elevation: 0
helpInfoDialog.open() 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: emulateDS4
text: qsTr("Emulate DS4")
checked: shortcutInfo.controller.emulateDS4 || false
onCheckedChanged: shortcutInfo.controller.emulateDS4 = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Emulate DS4")
helpInfoDialog.text =
qsTr("Emulates a DS4 instead of X360 Pad")
+ "\n"
qsTr("for usage with, for example, PSNow")
+ "\n"
+ qsTr("If enabled you have to disable \"Playstation Configuration support\" in Steam")
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
}
}
} }
width: 48 Item {
height: 48 width: 1
Material.elevation: 0 height: 4
anchors.topMargin: 16 }
Image { Row {
anchors.centerIn: parent leftPadding: 16
source: "qrc:/svg/help_outline_white_24dp.svg" Label {
width: 24 text: qsTr("Max. emulated controllers")
height: 24 topPadding: 16
}
SpinBox {
id: maxControllersSpinBox
width: 128
editable: true
value: shortcutInfo.controller.maxControllers
from: 0
to: 4
onValueChanged: shortcutInfo.controller.maxControllers = value
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Max. emulated controllers")
helpInfoDialog.text =
qsTr("GlosSI will only provide [NUMBER] of controllers")
+ "\n"
+ qsTr("Required to set to actually connected controller count when using \"real device IDs\" ")
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 { RPane {
width: 1 width: parent.width / 2 - 8
height: 4 height: 248
} radius: 4
Row { Material.elevation: 32
leftPadding: 16 bgOpacity: 0.97
Label { Column {
text: qsTr("Max. emulated controllers") spacing: 0
topPadding: 16 width: parent.width
} Row {
SpinBox { CheckBox {
id: maxControllersSpinBox id: windowMode
width: 128 text: qsTr("Steam/GlosSI overlay as separate window")
value: 4 checked: shortcutInfo.window.windowMode
from: 0 onCheckedChanged: shortcutInfo.window.windowMode = checked
to: 4 }
onValueChanged: shortcutInfo.maxControllers = value RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Steam/GlosSI overlay as separate window")
helpInfoDialog.text =
qsTr("Doesn't show overlay on top, but as separate window")
+ "\n"
+ qsTr("Use if blackscreen-issues are encountered.")
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: disableOverlayCheckbox
text: qsTr("Disable Steam/GlosSI overlay")
checked: shortcutInfo.window.disableOverlay
onCheckedChanged: shortcutInfo.window.disableOverlay = checked
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Disable Steam/GlosSI overlay")
helpInfoDialog.text =
qsTr("Only controller emulation - No extra window")
+ "\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 {
leftPadding: 16
Label {
text: qsTr("GlosSI-Overlay scale")
topPadding: 16
}
SpinBox {
id: scaleSpinBox
width: 172
from: -100
value: shortcutInfo.window.scale * 100 || 0
to: 350
stepSize: 10
editable: true
property int decimals: 2
property real realValue: value / 100
validator: DoubleValidator {
bottom: Math.min(scaleSpinBox.from, scaleSpinBox.to)
top: Math.max(scaleSpinBox.from, scaleSpinBox.to)
}
textFromValue: function(value, locale) {
return Number(value / 100).toLocaleString(locale, 'f', scaleSpinBox.decimals)
}
valueFromText: function(text, locale) {
return Number.fromLocaleString(locale, text) * 100
}
onValueChanged: function() {
if (value <= 0) {
shortcutInfo.window.scale = null
return
}
shortcutInfo.window.scale = value / 100
}
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("GloSI-Overlay scaling")
helpInfoDialog.text =
qsTr("Scales the elements of the GlosSI-Overlay (not Steam Overlay)")
+ "\n"
+ qsTr(" <= 0.0 to use auto-detection")
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 {
leftPadding: 16
Label {
text: qsTr("Max. Overlay FPS")
topPadding: 16
}
SpinBox {
id: maxFPSSpinBox
width: 172
from: -1
value: shortcutInfo.window.maxFps || 0
to: 244
stepSize: 5
editable: true
onValueChanged: function() {
if (value <= 0) {
shortcutInfo.window.maxFps = null
return
}
shortcutInfo.window.maxFps = value
}
}
RoundButton {
onClicked: () => {
helpInfoDialog.titleText = qsTr("Max. Overlay FPS")
helpInfoDialog.text =
qsTr("Restricts the FPS of the overlay to the given value")
+ "\n"
+ qsTr(" <= 0.0 to use screen refresh rate")
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
}
}
}
} }
} }
} }
}
RPane { RPane {
width: parent.width / 2 - 8
height: 264
radius: 4
Material.elevation: 32
bgOpacity: 0.97
Column {
spacing: 2
width: parent.width width: parent.width
CheckBox { radius: 4
id: windowMode Material.elevation: 32
text: qsTr("Steam/GlosSI overlay as separate window") bgOpacity: 0.97
checked: shortcutInfo.windowMode Column {
onCheckedChanged: shortcutInfo.windowMode = checked spacing: 4
} Row {
Label { Row {
text: qsTr("Doesn't show overlay on top, but as separate window") CheckBox {
wrapMode: Text.WordWrap id: extendedLogging
width: parent.width text: qsTr("Extended Logging")
leftPadding: 32 checked: shortcutInfo.extendedLogging
topPadding: -8 onCheckedChanged: shortcutInfo.extendedLogging = checked
} }
Label { // RoundButton {
text: qsTr("Use if blackscreen-issues are encountered.") // onClicked: () => {
wrapMode: Text.WordWrap // helpInfoDialog.titleText = qsTr("Hide (Real) Controllers")
width: parent.width // helpInfoDialog.text =
leftPadding: 32 // qsTr("Hides real game controllers from the system\nThis may prevent doubled inputs")
} // + "\n"
Item { // + qsTr("You can change this setting and which devices are hidden in the GlosSI overlay")
width: 1
height: 4 // helpInfoDialog.open()
} // }
CheckBox { // width: 48
id: disableOverlayCheckbox // height: 48
text: qsTr("Disable Steam/GlosSI overlay") // Material.elevation: 0
checked: shortcutInfo.disableOverlay // anchors.topMargin: 16
onCheckedChanged: shortcutInfo.disableOverlay = checked // Image {
} // anchors.centerIn: parent
Label { // source: "qrc:/svg/help_outline_white_24dp.svg"
text: qsTr("Only controller emulation - No extra window") // width: 24
wrapMode: Text.WordWrap // height: 24
width: parent.width // }
leftPadding: 32 // }
topPadding: -8 }
}
} }
} }
} }
} }
Item { Item {
id: bottomspacing id: bottomspacing
width: 1 width: 1

@ -0,0 +1,111 @@
/*
Copyright 2021-2022 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import QtQuick 6.2
import QtQuick.Controls 6.2
import QtQuick.Layouts 6.2
import QtQuick.Controls.Material 6.2
Dialog {
id: dlg
anchors.centerIn: parent
signal confirmed(var param)
visible: false
modal: true
dim: true
parent: Overlay.overlay
Overlay.modal: Rectangle {
color: Qt.rgba(0,0,0,0.4)
opacity: backdropOpacity
Behavior on opacity {
NumberAnimation {
duration: 300
}
}
}
property real backdropOpacity: 1.0
enter: Transition {
NumberAnimation{target: content; property: "y"; from: parent.height; to: 16; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: background; property: "y"; from: parent.height; to: 0; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: dlg; property: "backdropOpacity"; from: 0; to: 1; duration: 300; easing.type: Easing.OutQuad }
}
exit: Transition {
NumberAnimation{target: content; property: "y"; from: 16; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: background; property: "y"; from: 0; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: dlg; property: "backdropOpacity"; from: 1; to: 0; duration: 300; easing.type: Easing.InQuad }
}
background: RPane {
id: background
radius: 4
Material.elevation: 64
bgOpacity: 0.97
}
contentItem: Item {
id: content
clip: true
Column {
spacing: 4
bottomPadding: 96
Label {
id: titlelabel
text: qsTr("Steam Input Xbox support disabled")
font.pixelSize: 24
font.bold: true
}
Item {
height: 32
}
Label {
text: qsTr("Please enable \"Xbox configuration support\" in Steams controller settings.\n\nGlosSI cannot function properly with this setting disabled\n\nEnable now?")
wrapMode: Text.WordWrap
width: parent.width
}
Row {
anchors.right: parent.right
anchors.topMargin: 16
anchors.rightMargin: 2
spacing: 8
Button {
id: noBtn
text: qsTr("No")
onClicked: dlg.close()
}
Button {
id: yesBtn
text: qsTr("Yes")
onClicked: function() {
uiModel.enableSteamInputXboxSupport();
dlg.close();
steamChangedDialog2.open();
}
}
}
}
InfoDialog {
id: steamChangedDialog2
titleText: qsTr("Steam config changed!")
text: qsTr("Please restart Steam to reload your changes!")
onConfirmed: function (callback) {
callback();
}
}
}
}

@ -0,0 +1,92 @@
/*
Copyright 2021-2022 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.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import QtQuick 6.2
import QtQuick.Controls 6.2
import QtQuick.Layouts 6.2
import QtQuick.Controls.Material 6.2
Dialog {
id: dlg
anchors.centerIn: parent
signal confirmed(var param)
visible: false
modal: true
dim: true
parent: Overlay.overlay
Overlay.modal: Rectangle {
color: Qt.rgba(0,0,0,0.4)
opacity: backdropOpacity
Behavior on opacity {
NumberAnimation {
duration: 300
}
}
}
property real backdropOpacity: 1.0
enter: Transition {
NumberAnimation{target: content; property: "y"; from: parent.height; to: 16; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: background; property: "y"; from: parent.height; to: 0; duration: 300; easing.type: Easing.OutQuad }
NumberAnimation{target: dlg; property: "backdropOpacity"; from: 0; to: 1; duration: 300; easing.type: Easing.OutQuad }
}
exit: Transition {
NumberAnimation{target: content; property: "y"; from: 16; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: background; property: "y"; from: 0; to: parent.height; duration: 300; easing.type: Easing.InQuad }
NumberAnimation{target: dlg; property: "backdropOpacity"; from: 1; to: 0; duration: 300; easing.type: Easing.InQuad }
}
background: RPane {
id: background
radius: 4
Material.elevation: 64
bgOpacity: 0.97
}
contentItem: Item {
id: content
clip: true
Column {
spacing: 4
bottomPadding: 24
Label {
id: titlelabel
text: qsTr("Could not detect Steam")
font.pixelSize: 24
font.bold: true
}
Item {
height: 24
}
Label {
text: qsTr("Please make sure that Steam is running and you are logged in.")
wrapMode: Text.WordWrap
width: parent.width
}
Button {
anchors.right: parent.right
anchors.top: listview.bottom
anchors.topMargin: 16
anchors.rightMargin: 2
text: qsTr("Ok")
onClicked: dlg.close()
}
}
}
}

@ -45,6 +45,16 @@ Window {
property bool steamShortcutsChanged: false property bool steamShortcutsChanged: false
Component.onCompleted: function() {
if (!uiModel.foundSteam) {
steamNotFoundDialog.open();
return;
}
if (!uiModel.steamInputXboxSupportEnabled) {
steamXboxDisabledDialog.open();
}
}
Image { Image {
anchors.top: parent.top anchors.top: parent.top
anchors.left: parent.left anchors.left: parent.left
@ -55,10 +65,18 @@ Window {
opacity: 0.033 opacity: 0.033
} }
SteamNotFoundDialog {
id: steamNotFoundDialog
}
SteamInputXboxDisabledDialog {
id: steamXboxDisabledDialog
}
InfoDialog { InfoDialog {
id: steamChangedDialog id: steamChangedDialog
titleText: qsTr("Attention!") titleText: qsTr("Steam shortcuts changed!")
text: qsTr("Please restart Steam to reload your changes!") text: qsTr("Please restart Steam to reload your changes")
onConfirmed: function (callback) { onConfirmed: function (callback) {
callback(); callback();
} }

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" width="24" fill="#FFFFFF"><path d="m12 15.375-6-6 1.4-1.4 4.6 4.6 4.6-4.6 1.4 1.4Z"/></svg>

After

Width:  |  Height:  |  Size: 143 B

@ -1,3 +1,4 @@
BasedOnStyle: LLVM
UseTab: false UseTab: false
IndentWidth: 4 IndentWidth: 4
BreakBeforeBraces: "Stroustrup" BreakBeforeBraces: "Stroustrup"

@ -77,6 +77,9 @@ void AppLauncher::update()
} }
if (Settings::launch.waitForChildProcs) { if (Settings::launch.waitForChildProcs) {
std::erase_if(pids_, [](auto pid) { std::erase_if(pids_, [](auto pid) {
if (pid == 0) {
return true;
}
const auto running = IsProcessRunning(pid); const auto running = IsProcessRunning(pid);
if (!running) if (!running)
spdlog::trace("Child process with PID \"{}\" died", pid); spdlog::trace("Child process with PID \"{}\" died", pid);

@ -102,9 +102,19 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
whitelist.push_back(path); whitelist.push_back(path);
} }
} }
if (Settings::extendedLogging) {
std::ranges::for_each(whitelist, [](const auto& exe) {
spdlog::trace(L"Whitelisted executable: {}", exe);
});
}
setAppWhiteList(whitelist); setAppWhiteList(whitelist);
avail_devices_ = GetHidDeviceList(); avail_devices_ = GetHidDeviceList();
if (Settings::extendedLogging) {
std::ranges::for_each(avail_devices_, [](const auto& dev) {
spdlog::trace(L"AvailDevice device: {}", dev.name);
});
}
blacklisted_devices_ = getBlackListDevices(); blacklisted_devices_ = getBlackListDevices();
for (const auto& dev : avail_devices_) { for (const auto& dev : avail_devices_) {
@ -112,11 +122,11 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
return blackdev == dev.device_instance_path || blackdev == dev.base_container_device_instance_path; return blackdev == dev.device_instance_path || blackdev == dev.base_container_device_instance_path;
})) { })) {
// Valve emulated gamepad PID/VID; mirrord by ViGEm // Valve emulated gamepad PID/VID; mirrord by ViGEm
if (!(dev.vendor_id == 0x28de && dev.product_id == 0x11FF)) { if (!(dev.vendor_id == 0x28de && (dev.product_id == 0x11FF || dev.product_id == 0x028E))) {
if (!dev.device_instance_path.empty()) { if (!dev.device_instance_path.empty()) {
blacklisted_devices_.push_back(dev.device_instance_path); blacklisted_devices_.push_back(dev.device_instance_path);
} }
if (!dev.device_instance_path.empty()) { if (!dev.base_container_device_instance_path.empty()) {
blacklisted_devices_.push_back(dev.base_container_device_instance_path); blacklisted_devices_.push_back(dev.base_container_device_instance_path);
} }
} }
@ -127,6 +137,11 @@ void HidHide::hideDevices(const std::filesystem::path& steam_path)
setBlacklistDevices(blacklisted_devices_); setBlacklistDevices(blacklisted_devices_);
setActive(true); setActive(true);
spdlog::info("Hid Gaming Devices; Enabling Overlay element..."); spdlog::info("Hid Gaming Devices; Enabling Overlay element...");
if (Settings::extendedLogging) {
std::ranges::for_each(blacklisted_devices_, [](const auto& dev) {
spdlog::trace(L"Blacklisted device: {}", dev);
});
}
enableOverlayElement(); enableOverlayElement();
} }
closeCtrlDevice(); closeCtrlDevice();
@ -148,7 +163,7 @@ void HidHide::UnPatchValveHooks()
// need to load addresses that way.. Otherwise we land before some jumps... // need to load addresses that way.. Otherwise we land before some jumps...
if (const auto setupapidll = GetModuleHandle(L"setupapi.dll")) { if (const auto setupapidll = GetModuleHandle(L"setupapi.dll")) {
UnPatchHook("SetupDiEnumDeviceInfo", setupapidll); UnPatchHook("SetupDiEnumDeviceInfo", setupapidll);
//UnPatchHook("SetupDiGetClassDevsW", setupapidll); UnPatchHook("SetupDiGetClassDevsW", setupapidll);
} }
if (const auto hiddll = GetModuleHandle(L"hid.dll")) { if (const auto hiddll = GetModuleHandle(L"hid.dll")) {
for (const auto& name : ORIGINAL_BYTES | std::views::keys) { for (const auto& name : ORIGINAL_BYTES | std::views::keys) {
@ -182,56 +197,70 @@ void HidHide::UnPatchHook(const std::string& name, HMODULE module)
void HidHide::enableOverlayElement() void HidHide::enableOverlayElement()
{ {
Overlay::AddOverlayElem([this](bool window_has_focus) { Overlay::AddOverlayElem([this](bool window_has_focus, ImGuiID dockspace_id) {
if (window_has_focus && (overlay_elem_clock_.getElapsedTime().asSeconds() > OVERLAY_ELEM_REFRESH_INTERVAL_S_)) { ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
openCtrlDevice(); if (ImGui::Begin("Hidden Devices")) {
bool hidehide_state_store = hidhide_active_; if (window_has_focus && (overlay_elem_clock_.getElapsedTime().asSeconds() > OVERLAY_ELEM_REFRESH_INTERVAL_S_)) {
if (hidhide_active_) { // UnPatchValveHooks();
setActive(false);
}
avail_devices_ = GetHidDeviceList();
blacklisted_devices_ = getBlackListDevices();
if (hidehide_state_store) {
setActive(true);
}
closeCtrlDevice();
overlay_elem_clock_.restart();
}
ImGui::SetNextWindowPos({650, 100}, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints({400, 270}, {1000, 1000});
ImGui::Begin("Hidden Devices");
ImGui::BeginChild("Inner", {0.f, ImGui::GetItemRectSize().y - 64}, true);
std::ranges::for_each(avail_devices_, [this](const auto& device) {
std::string label = (std::string(device.name.begin(), std::ranges::find(device.name, L'\0')) + "##" + std::string(device.device_instance_path.begin(), device.device_instance_path.end()));
const auto findDeviceFn = [&device](const auto& blackdev) {
return device.device_instance_path == blackdev || device.base_container_device_instance_path == blackdev;
};
bool hidden = std::ranges::find_if(blacklisted_devices_, findDeviceFn) != blacklisted_devices_.end();
if (ImGui::Checkbox(label.data(), &hidden)) {
openCtrlDevice(); openCtrlDevice();
if (hidden) { bool hidehide_state_store = hidhide_active_;
if (std::ranges::none_of(blacklisted_devices_, findDeviceFn)) { if (Settings::extendedLogging) {
if (!device.device_instance_path.empty()) { spdlog::debug("Refreshing HID devices");
blacklisted_devices_.push_back(device.device_instance_path); }
} if (hidhide_active_) {
if (!device.device_instance_path.empty()) { setActive(false);
blacklisted_devices_.push_back(device.base_container_device_instance_path); }
avail_devices_ = GetHidDeviceList();
if (Settings::extendedLogging) {
std::ranges::for_each(avail_devices_, [](const auto& dev) {
spdlog::trace(L"AvailDevice device: {}", dev.name);
});
}
blacklisted_devices_ = getBlackListDevices();
if (hidehide_state_store) {
setActive(true);
}
closeCtrlDevice();
overlay_elem_clock_.restart();
}
ImGui::BeginChild("Inner", {0.f, ImGui::GetItemRectSize().y - 64}, true);
std::ranges::for_each(avail_devices_, [this](const auto& device) {
std::string label = (std::string(device.name.begin(), std::ranges::find(device.name, L'\0')) + "##" + std::string(device.device_instance_path.begin(), device.device_instance_path.end()));
const auto findDeviceFn = [&device](const auto& blackdev) {
return device.device_instance_path == blackdev || device.base_container_device_instance_path == blackdev;
};
bool hidden = std::ranges::find_if(blacklisted_devices_, findDeviceFn) != blacklisted_devices_.end();
if (ImGui::Checkbox(label.data(), &hidden)) {
openCtrlDevice();
if (hidden) {
if (std::ranges::none_of(blacklisted_devices_, findDeviceFn)) {
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.device_instance_path);
}
if (!device.device_instance_path.empty()) {
blacklisted_devices_.push_back(device.base_container_device_instance_path);
}
} }
} }
else {
blacklisted_devices_.erase(std::ranges::remove_if(blacklisted_devices_, findDeviceFn).begin(),
blacklisted_devices_.end());
}
setBlacklistDevices(blacklisted_devices_);
if (Settings::extendedLogging) {
std::ranges::for_each(blacklisted_devices_, [](const auto& dev) {
spdlog::trace(L"Blacklisted device: {}", dev);
});
}
closeCtrlDevice();
} }
else { });
blacklisted_devices_.erase(std::ranges::remove_if(blacklisted_devices_, findDeviceFn).begin(), ImGui::EndChild();
blacklisted_devices_.end()); if (ImGui::Checkbox("Devices Hidden", &hidhide_active_)) {
} openCtrlDevice();
setBlacklistDevices(blacklisted_devices_); setActive(hidhide_active_);
closeCtrlDevice(); closeCtrlDevice();
} }
});
ImGui::EndChild();
if (ImGui::Checkbox("Devices Hidden", &hidhide_active_)) {
openCtrlDevice();
setActive(hidhide_active_);
closeCtrlDevice();
} }
ImGui::End(); ImGui::End();
}); });
@ -316,6 +345,9 @@ void HidHide::setActive(bool active)
return; return;
} }
hidhide_active_ = active; hidhide_active_ = active;
if (Settings::extendedLogging) {
spdlog::debug("HidHide State set to {}", active);
}
} }
DWORD HidHide::getRequiredOutputBufferSize(IOCTL_TYPE type) const DWORD HidHide::getRequiredOutputBufferSize(IOCTL_TYPE type) const

@ -53,9 +53,8 @@ void InputRedirector::run()
max_controller_count_ = Settings::controller.maxControllers; max_controller_count_ = Settings::controller.maxControllers;
use_real_vid_pid_ = Settings::devices.realDeviceIds; use_real_vid_pid_ = Settings::devices.realDeviceIds;
#ifdef _WIN32 #ifdef _WIN32
Overlay::AddOverlayElem([this](bool window_has_focus) { Overlay::AddOverlayElem([this](bool window_has_focus, ImGuiID dockspace_id) {
ImGui::SetNextWindowPos({650, 450}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints({400, 270}, {1000, 1000});
ImGui::Begin("Controller Emulation"); ImGui::Begin("Controller Emulation");
int countcopy = max_controller_count_; int countcopy = max_controller_count_;
ImGui::Text("Max. controller count"); ImGui::Text("Max. controller count");
@ -163,7 +162,11 @@ void InputRedirector::runLoop()
// Multiple controllers can be worked around with by setting max count. // Multiple controllers can be worked around with by setting max count.
if (!use_real_vid_pid_) { if (!use_real_vid_pid_) {
vigem_target_set_vid(vt_pad_[i], 0x28de); //VALVE_DIRECTINPUT_GAMEPAD_VID vigem_target_set_vid(vt_pad_[i], 0x28de); //VALVE_DIRECTINPUT_GAMEPAD_VID
// vigem_target_set_pid(vt_pad_[i], 0x11FF); //VALVE_DIRECTINPUT_GAMEPAD_PID //vigem_target_set_pid(vt_pad_[i], 0x11FF); //VALVE_DIRECTINPUT_GAMEPAD_PID
vigem_target_set_pid(vt_pad_[i], 0x028E); // XBOX 360 Controller
} else {
vigem_target_set_vid(vt_pad_[i], 0x045E); // MICROSOFT
vigem_target_set_pid(vt_pad_[i], 0x028E); // XBOX 360 Controller
} }
// TODO: MAYBE!: In a future version, use something like OpenXInput // TODO: MAYBE!: In a future version, use something like OpenXInput
//and filter out emulated controllers to support a greater amount of controllers simultaneously //and filter out emulated controllers to support a greater amount of controllers simultaneously
@ -178,7 +181,11 @@ void InputRedirector::runLoop()
} }
} }
if (target_add_res == VIGEM_ERROR_NONE) { if (target_add_res == VIGEM_ERROR_NONE) {
spdlog::info("Plugged in controller {}, {}", i, vigem_target_get_index(vt_pad_[i])); spdlog::info("Plugged in controller {}, {}; VID: {:x}; PID: {:x}",
i,
vigem_target_get_index(vt_pad_[i]),
vigem_target_get_vid(vt_pad_[i]),
vigem_target_get_pid(vt_pad_[i]));
if (Settings::controller.emulateDS4) { if (Settings::controller.emulateDS4) {
const auto callback_register_res = vigem_target_ds4_register_notification( const auto callback_register_res = vigem_target_ds4_register_notification(

@ -21,6 +21,7 @@ limitations under the License.
#include <codecvt> #include <codecvt>
#include "Roboto.h" #include "Roboto.h"
#include "Settings.h"
Overlay::Overlay( Overlay::Overlay(
sf::RenderWindow& window, sf::RenderWindow& window,
@ -37,12 +38,14 @@ Overlay::Overlay(
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
io.Fonts->Clear(); // clear fonts if you loaded some before (even if only default one was loaded) io.Fonts->Clear(); // clear fonts if you loaded some before (even if only default one was loaded)
auto fontconf = ImFontConfig{}; auto fontconf = ImFontConfig{};
fontconf.FontDataOwnedByAtlas = false; fontconf.FontDataOwnedByAtlas = false;
io.Fonts->AddFontFromMemoryTTF(Roboto_Regular_ttf.data(), Roboto_Regular_ttf.size(), 24, &fontconf); io.Fonts->AddFontFromMemoryTTF(Roboto_Regular_ttf.data(), Roboto_Regular_ttf.size(), 24, &fontconf);
ImGui::SFML::UpdateFontTexture(); // important call: updates font texture ImGui::SFML::UpdateFontTexture();
#ifdef _WIN32 #ifdef _WIN32
auto config_path = std::filesystem::temp_directory_path() auto config_path = std::filesystem::temp_directory_path()
@ -55,6 +58,7 @@ Overlay::Overlay(
if (!std::filesystem::exists(config_path)) if (!std::filesystem::exists(config_path))
std::filesystem::create_directories(config_path); std::filesystem::create_directories(config_path);
config_path /= "imgui.ini"; config_path /= "imgui.ini";
// This assumes that char is utf8 and wchar_t is utf16, which is guaranteed on Windows. // This assumes that char is utf8 and wchar_t is utf16, which is guaranteed on Windows.
config_file_name_ = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(config_path.wstring()); config_file_name_ = std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(config_path.wstring());
io.IniFilename = config_file_name_.data(); io.IniFilename = config_file_name_.data();
@ -151,14 +155,31 @@ void Overlay::update()
{ {
ImGui::SFML::Update(window_, update_clock_.restart()); ImGui::SFML::Update(window_, update_clock_.restart());
showLogs(); showLogs(0);
if (enabled_ || force_enable_) { if (enabled_ || force_enable_) {
// Create a DockSpace node where any window can be docked
ImGui::SetNextWindowSize({ImGui::GetMainViewport()->Size.x * 0.6f, ImGui::GetMainViewport()->Size.y * 0.7f}, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos({ImGui::GetMainViewport()->Size.x * 0.25f, 100 }, ImGuiCond_FirstUseEver);
ImGui::Begin("GlosSI Settings");
if (Settings::settings_path_ != "") {
if (ImGui::Button("Save shortcut settings", {256, 32})) {
Settings::StoreSettings();
}
}
ImGuiID dockspace_id = ImGui::GetID("GlosSI-DockSpace");
ImGui::DockSpace(dockspace_id);
window_.clear(sf::Color(0, 0, 0, 128)); // make window slightly dim screen with overlay window_.clear(sf::Color(0, 0, 0, 128)); // make window slightly dim screen with overlay
std::ranges::for_each(OVERLAY_ELEMS_, [this](const auto& elem) {
elem.second(window_.hasFocus());
std::ranges::for_each(OVERLAY_ELEMS_, [this, &dockspace_id](const auto& elem) {
elem.second(window_.hasFocus(), dockspace_id);
}); });
ImGui::End();
// ImGui::ShowDemoWindow(); // ImGui::ShowDemoWindow();
if (closeButton()) { if (closeButton()) {
@ -186,7 +207,7 @@ void Overlay::AddLog(const spdlog::details::log_msg& msg)
LOG_MSGS_.push_back({.time = msg.time, .level = msg.level, .payload = msg.payload.data()}); LOG_MSGS_.push_back({.time = msg.time, .level = msg.level, .payload = msg.payload.data()});
} }
int Overlay::AddOverlayElem(const std::function<void(bool window_has_focus)>& elem_fn) int Overlay::AddOverlayElem(const std::function<void(bool window_has_focus, ImGuiID dockspace_id)>& elem_fn)
{ {
OVERLAY_ELEMS_.insert({overlay_element_id_, elem_fn}); OVERLAY_ELEMS_.insert({overlay_element_id_, elem_fn});
// keep this non confusing, but longer... // keep this non confusing, but longer...
@ -200,20 +221,22 @@ void Overlay::RemoveOverlayElem(int id)
OVERLAY_ELEMS_.erase(id); OVERLAY_ELEMS_.erase(id);
} }
void Overlay::showLogs() void Overlay::showLogs(ImGuiID dockspace_id)
{ {
std::vector<Log> logs; std::vector<Log> logs;
if (!enabled_ && !log_expanded_) { if (!enabled_ && !log_expanded_) {
return; return;
} }
bool logs_contain_warn_or_worse = false;
if (enabled_) { if (enabled_) {
logs = LOG_MSGS_; logs = LOG_MSGS_;
} }
else { else {
std::ranges::copy_if(LOG_MSGS_, std::ranges::copy_if(LOG_MSGS_,
std::back_inserter(logs), std::back_inserter(logs),
[](const auto& log) { [&logs_contain_warn_or_worse](const auto& log) {
return (
const auto res = (
log.time.time_since_epoch() + std::chrono::seconds( log.time.time_since_epoch() + std::chrono::seconds(
LOG_RETENTION_TIME_) > LOG_RETENTION_TIME_) >
std::chrono::system_clock::now().time_since_epoch()) std::chrono::system_clock::now().time_since_epoch())
@ -221,9 +244,13 @@ void Overlay::showLogs()
&& (log.level > spdlog::level::debug) && (log.level > spdlog::level::debug)
#endif #endif
; ;
if (res && log.level > spdlog::level::warn) {
logs_contain_warn_or_worse = true;
}
return res;
}); });
} }
if (logs.empty()) if (logs.empty() || ( !enabled_ && !logs_contain_warn_or_worse && time_since_start_clock_.getElapsedTime().asSeconds() > HIDE_NORMAL_LOGS_AFTER_S))
return; return;
ImGui::SetNextWindowSizeConstraints({150, 150}, {1000, window_.getSize().y - 250.f}); ImGui::SetNextWindowSizeConstraints({150, 150}, {1000, window_.getSize().y - 250.f});
if (!enabled_) { if (!enabled_) {
@ -232,6 +259,9 @@ void Overlay::showLogs()
ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar); ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoTitleBar);
} }
else { else {
//ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize({ImGui::GetMainViewport()->Size.x * 0.2f, ImGui::GetMainViewport()->Size.y * 0.7f}, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos({ImGui::GetMainViewport()->Size.x * 0.05f, 100}, ImGuiCond_FirstUseEver);
log_expanded_ = ImGui::Begin("Log"); log_expanded_ = ImGui::Begin("Log");
} }
if (log_expanded_) { if (log_expanded_) {

@ -38,7 +38,7 @@ class Overlay {
static void Shutdown(); static void Shutdown();
static void AddLog(const spdlog::details::log_msg& msg); static void AddLog(const spdlog::details::log_msg& msg);
static int AddOverlayElem(const std::function<void(bool window_has_focus)>& elem_fn); static int AddOverlayElem(const std::function<void(bool window_has_focus, ImGuiID dockspace_id)>& elem_fn);
static void RemoveOverlayElem(int id); static void RemoveOverlayElem(int id);
private: private:
@ -47,11 +47,12 @@ class Overlay {
bool enabled_ = true; bool enabled_ = true;
std::function<void()> on_close_; std::function<void()> on_close_;
std::function<void()> trigger_state_change_; std::function<void()> trigger_state_change_;
void showLogs(); void showLogs(ImGuiID dockspace_id);
bool closeOverlayButton() const; bool closeOverlayButton() const;
[[nodiscard]] bool closeButton() const; [[nodiscard]] bool closeButton() const;
bool force_enable_ = false; bool force_enable_ = false;
bool log_expanded_ = true; bool log_expanded_ = true;
sf::Clock time_since_start_clock_;
struct Log { struct Log {
std::chrono::system_clock::time_point time; std::chrono::system_clock::time_point time;
@ -60,9 +61,10 @@ class Overlay {
}; };
static inline std::vector<Log> LOG_MSGS_; static inline std::vector<Log> LOG_MSGS_;
static constexpr int LOG_RETENTION_TIME_ = 5; static constexpr int LOG_RETENTION_TIME_ = 5;
static constexpr int HIDE_NORMAL_LOGS_AFTER_S = 20;
static inline int overlay_element_id_ = 0; static inline int overlay_element_id_ = 0;
static inline std::map<int, std::function<void(bool window_has_focus)>> OVERLAY_ELEMS_; static inline std::map<int, std::function<void(bool window_has_focus, ImGuiID dockspace_id)>> OVERLAY_ELEMS_;
#ifdef _WIN32 #ifdef _WIN32
std::string config_file_name_; std::string config_file_name_;

@ -12,35 +12,41 @@ static int current_priority = HIGH_PRIORITY_CLASS;
inline void init() inline void init()
{ {
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
spdlog::trace("Set process priority to HIGH_PRIORITY_CLASS");
Overlay::AddOverlayElem([](bool window_has_focus) { Overlay::AddOverlayElem([](bool window_has_focus, ImGuiID dockspace_id) {
ImGui::SetNextWindowPos({913, 418}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints({170, 325}, {1000, 1000});
ImGui::Begin("Process Priority"); ImGui::Begin("Process Priority");
ImGui::Text("Might help with input-lag or bad game performance"); ImGui::Text("Might help with input-lag or bad game performance");
if (ImGui::RadioButton("Realtime", current_priority == REALTIME_PRIORITY_CLASS)) { if (ImGui::RadioButton("Realtime", current_priority == REALTIME_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
current_priority = REALTIME_PRIORITY_CLASS; current_priority = REALTIME_PRIORITY_CLASS;
spdlog::trace("Set process priority to REALTIME_PRIORITY_CLASS");
} }
if (ImGui::RadioButton("High", current_priority == HIGH_PRIORITY_CLASS)) { if (ImGui::RadioButton("High", current_priority == HIGH_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
current_priority = HIGH_PRIORITY_CLASS; current_priority = HIGH_PRIORITY_CLASS;
spdlog::trace("Set process priority to HIGH_PRIORITY_CLASS");
} }
if (ImGui::RadioButton("Above Normal", current_priority == ABOVE_NORMAL_PRIORITY_CLASS)) { if (ImGui::RadioButton("Above Normal", current_priority == ABOVE_NORMAL_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
current_priority = ABOVE_NORMAL_PRIORITY_CLASS; current_priority = ABOVE_NORMAL_PRIORITY_CLASS;
spdlog::trace("Set process priority to ABOVE_NORMAL_PRIORITY_CLASS");
} }
if (ImGui::RadioButton("Normal", current_priority == NORMAL_PRIORITY_CLASS)) { if (ImGui::RadioButton("Normal", current_priority == NORMAL_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
current_priority = NORMAL_PRIORITY_CLASS; current_priority = NORMAL_PRIORITY_CLASS;
spdlog::trace("Set process priority to NORMAL_PRIORITY_CLASS");
} }
if (ImGui::RadioButton("Below Normal", current_priority == BELOW_NORMAL_PRIORITY_CLASS)) { if (ImGui::RadioButton("Below Normal", current_priority == BELOW_NORMAL_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS);
current_priority = BELOW_NORMAL_PRIORITY_CLASS; current_priority = BELOW_NORMAL_PRIORITY_CLASS;
spdlog::trace("Set process priority to BELOW_NORMAL_PRIORITY_CLASS");
} }
if (ImGui::RadioButton("Low", current_priority == IDLE_PRIORITY_CLASS)) { if (ImGui::RadioButton("Low", current_priority == IDLE_PRIORITY_CLASS)) {
SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS); SetPriorityClass(GetCurrentProcess(), IDLE_PRIORITY_CLASS);
current_priority = IDLE_PRIORITY_CLASS; current_priority = IDLE_PRIORITY_CLASS;
spdlog::trace("Set process priority to IDLE_PRIORITY_CLASS");
} }
ImGui::End(); ImGui::End();
}); });

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,0,7,1018000020006 FILEVERSION 0,0,8,1031000051035
PRODUCTVERSION 0,0,7,1018000020006 PRODUCTVERSION 0,0,8,1031000051035
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.0.7.1-18-g0f2bac6" VALUE "FileVersion", "0.0.8.1-31-gda51d35"
VALUE "InternalName", "GlosSITarget" VALUE "InternalName", "GlosSITarget"
VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware" VALUE "LegalCopyright", "Copyright (C) 2021 Peter Repukat - FlatspotSoftware"
VALUE "OriginalFilename", "GlosSITarget.exe" VALUE "OriginalFilename", "GlosSITarget.exe"
VALUE "ProductName", "GlosSI" VALUE "ProductName", "GlosSI"
VALUE "ProductVersion", "0.0.7.1-18-g0f2bac6" VALUE "ProductVersion", "0.0.8.1-31-gda51d35"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
@ -168,6 +168,234 @@ IDI_ICON1 ICON "GloSC_Icon.ico"

@ -47,11 +47,15 @@ inline struct Window {
} window; } window;
inline struct Controller { inline struct Controller {
int maxControllers = 4; int maxControllers = 1;
bool allowDesktopConfig = false; bool allowDesktopConfig = false;
bool emulateDS4 = false; bool emulateDS4 = false;
} controller; } controller;
inline bool extendedLogging = false;
inline std::filesystem::path settings_path_ = "";
inline bool checkIsUwp(const std::wstring& launch_path) inline bool checkIsUwp(const std::wstring& launch_path)
{ {
if (launch_path.find(L"://") != std::wstring::npos) { if (launch_path.find(L"://") != std::wstring::npos) {
@ -87,14 +91,9 @@ inline void Parse(std::wstring arg1)
spdlog::error(L"Couldn't open settings file {}", path.wstring()); spdlog::error(L"Couldn't open settings file {}", path.wstring());
return; return;
} }
const auto json = nlohmann::json::parse(json_file); settings_path_ = path;
if (json["version"] != 1) { // TODO: versioning stuff
spdlog::warn("Config version doesn't match application version.");
}
// TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately. auto safeParseValue = [](const auto& object, const auto& key, auto& value) {
auto safeParseValue = [](const auto& object, const auto& key, auto& value) {
try { try {
if (object.is_null() || object.empty() || object.at(key).empty() || object.at(key).is_null()) { if (object.is_null() || object.empty() || object.at(key).empty() || object.at(key).is_null()) {
return; return;
@ -102,10 +101,10 @@ inline void Parse(std::wstring arg1)
value = object[key]; value = object[key];
} }
catch (const nlohmann::json::exception& e) { catch (const nlohmann::json::exception& e) {
spdlog::error("Err parsing \"{}\"; {}", key, e.what()); spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
} }
catch (const std::exception& e) { catch (const std::exception& e) {
spdlog::error("Err parsing \"{}\"; {}", key, e.what()); spdlog::warn("Err parsing \"{}\"; {}", key, e.what());
} }
}; };
@ -118,6 +117,15 @@ inline void Parse(std::wstring arg1)
} }
}; };
const auto json = nlohmann::json::parse(json_file);
int version;
safeParseValue(json, "version" ,version);
if (version != 1) { // TODO: versioning stuff
spdlog::warn("Config version doesn't match application version.");
}
// TODO: make this as much generic as fits in about the same amount of code if one would parse every value separately.
if (auto launchconf = json["launch"]; launchconf.is_object()) { if (auto launchconf = json["launch"]; launchconf.is_object()) {
safeParseValue(launchconf, "launch", launch.launch); safeParseValue(launchconf, "launch", launch.launch);
safeWStringParse(launchconf, "launchPath", launch.launchPath); safeWStringParse(launchconf, "launchPath", launch.launchPath);
@ -144,13 +152,47 @@ inline void Parse(std::wstring arg1)
safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4); safeParseValue(controllerConf, "emulateDS4", controller.emulateDS4);
} }
safeParseValue(json, "extendedLogging", extendedLogging);
json_file.close(); json_file.close();
spdlog::debug(L"Read config file \"{}\"", path.wstring()); // c++ is stupid...
spdlog::debug(L"Read config file \"{}\"; config: {}", path.wstring(), std::filesystem::path(json.dump()).wstring());
if (launch.launch) { if (launch.launch) {
launch.isUWP = checkIsUwp(launch.launchPath); launch.isUWP = checkIsUwp(launch.launchPath);
} }
} }
inline void StoreSettings()
{
nlohmann::json json;
json["version"] = 1;
json["launch"]["launch"] = launch.launch;
json["launch"]["launchPath"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(launch.launchPath);
json["launch"]["launchAppArgs"] = std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(launch.launchAppArgs);
json["launch"]["closeOnExit"] = launch.closeOnExit;
json["launch"]["waitForChildProcs"] = launch.waitForChildProcs;
json["devices"]["hideDevices"] = devices.hideDevices;
json["devices"]["realDeviceIds"] = devices.realDeviceIds;
json["window"]["windowMode"] = window.windowMode;
json["window"]["maxFps"] = window.maxFps;
json["window"]["scale"] = window.scale;
json["window"]["disableOverlay"] = window.disableOverlay;
json["controller"]["maxControllers"] = controller.maxControllers;
json["controller"]["allowDesktopConfig"] = controller.allowDesktopConfig;
json["controller"]["emulateDS4"] = controller.emulateDS4;
json["extendedLogging"] = extendedLogging;
std::ofstream json_file;
json_file.open(settings_path_);
if (!json_file.is_open()) {
spdlog::error(L"Couldn't open settings file {}", settings_path_.wstring());
return;
}
json_file << json.dump(4);
json_file.close();
}
} // namespace Settings } // namespace Settings

@ -17,6 +17,8 @@ limitations under the License.
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include "Settings.h"
#ifdef _WIN32 #ifdef _WIN32
#define NOMINMAX #define NOMINMAX
#include <Windows.h> #include <Windows.h>
@ -44,6 +46,11 @@ void SteamOverlayDetector::update()
// okey to use nullptr as hwnd. get EVERY message // okey to use nullptr as hwnd. get EVERY message
if (PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { if (PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) {
// filter out some messages as not all get altered by steam... // filter out some messages as not all get altered by steam...
if (Settings::extendedLogging && msg.message != 512 && msg.message != 5374) {
spdlog::trace("PeekMessage: Window msg: {}", msg.message);
}
if (msg.message < 1000 && msg.message > 0) { if (msg.message < 1000 && msg.message > 0) {
return; return;
} }

@ -181,6 +181,9 @@ void SteamTarget::toggleGlossiOverlay()
void SteamTarget::focusWindow(WindowHandle hndl) void SteamTarget::focusWindow(WindowHandle hndl)
{ {
if (reinterpret_cast<uint64_t>(hndl) == 0) {
return;
}
#ifdef _WIN32 #ifdef _WIN32
if (hndl == target_window_handle_) { if (hndl == target_window_handle_) {
spdlog::debug("Bring own window to foreground"); spdlog::debug("Bring own window to foreground");

@ -50,9 +50,9 @@ TargetWindow::TargetWindow(
{ {
createWindow(Settings::window.windowMode); createWindow(Settings::window.windowMode);
Overlay::AddOverlayElem([this](bool window_has_focus) { Overlay::AddOverlayElem([this](bool window_has_focus, ImGuiID dockspace_id) {
ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
bool windowed_copy = windowed_; bool windowed_copy = windowed_;
ImGui::SetNextWindowPos({window_.getSize().x - 370.f, 100}, ImGuiCond_FirstUseEver);
ImGui::Begin("Window mode"); ImGui::Begin("Window mode");
if (ImGui::Checkbox("Window mode", &windowed_copy)) { if (ImGui::Checkbox("Window mode", &windowed_copy)) {
toggle_window_mode_after_frame_ = true; toggle_window_mode_after_frame_ = true;
@ -254,14 +254,26 @@ void TargetWindow::createWindow(bool window_mode)
#ifdef _WIN32 #ifdef _WIN32
// For some completely odd reason, the Background becomes black when enabled dpi-awareness and making the window desktop-size. // For some completely odd reason, the Background becomes black when enabled dpi-awareness and making the window desktop-size.
// Scaling down by 1px each direction is barely noticeable and works. // Scaling down by 1px each direction is barely noticeable and works.
// Due to some other issue, the (Steam) overlay might get blurred when doing this
// as a workaround, start in full size, and scale down later...
spdlog::info("Creating Overlay window (Borderless Fullscreen)..."); spdlog::info("Creating Overlay window (Borderless Fullscreen)...");
window_.create(sf::VideoMode(desktop_mode.width - 1, desktop_mode.height - 1, 32), "GlosSITarget", sf::Style::None); window_.create(sf::VideoMode(desktop_mode.width -1, desktop_mode.height -1, 32), "GlosSITarget", sf::Style::None);
// get size of all monitors combined
const auto screenWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
const auto screenHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
spdlog::debug("Full screen size: {}x{}", screenWidth, screenHeight);
spdlog::debug("Primary monitor size: {}x{}", desktop_mode.width, desktop_mode.height);
#else #else
window_.create(desktop_mode, "GlosSITarget", sf::Style::None); window_.create(desktop_mode, "GlosSITarget", sf::Style::None);
#endif #endif
windowed_ = false; windowed_ = false;
} }
window_.setActive(true); window_.setActive(true);
spdlog::debug("Window position: {}x{}", window_.getPosition().x, window_.getPosition().y);
#ifdef _WIN32 #ifdef _WIN32
HWND hwnd = window_.getSystemHandle(); HWND hwnd = window_.getSystemHandle();
@ -320,6 +332,9 @@ void TargetWindow::createWindow(bool window_mode)
else { else {
spdlog::warn("Not applying too low screen scale setting"); spdlog::warn("Not applying too low screen scale setting");
} }
// window_.setSize({desktop_mode.width - 1, desktop_mode.height - 1 });
on_window_changed_(); on_window_changed_();
#ifdef _WIN32 #ifdef _WIN32

@ -60,10 +60,8 @@ inline void EnableUwpOverlay()
inline void AddUwpOverlayOvWidget() inline void AddUwpOverlayOvWidget()
{ {
Overlay::AddOverlayElem([](bool window_has_focus) { Overlay::AddOverlayElem([](bool window_has_focus, ImGuiID dockspace_id) {
ImGui::SetNextWindowPos({1200, 250}, ImGuiCond_FirstUseEver); ImGui::SetNextWindowDockID(dockspace_id, ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints({170, 325}, {1000, 1000});
ImGui::SetNextWindowCollapsed(true, ImGuiCond_FirstUseEver);
ImGui::Begin("UWP-Overlay"); ImGui::Begin("UWP-Overlay");
ImGui::Text("To enable the overlay on top of \"fullscreen\" UWP-Apps,"); ImGui::Text("To enable the overlay on top of \"fullscreen\" UWP-Apps,");
ImGui::Text("a .dll has to be injected into explorer.exe"); ImGui::Text("a .dll has to be injected into explorer.exe");

@ -78,11 +78,11 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>..\deps\subhook;$(IncludePath)</IncludePath> <IncludePath>..\deps\subhook;..\deps\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>..\deps\subhook;$(IncludePath)</IncludePath> <IncludePath>..\deps\subhook;..\deps\spdlog\include;$(IncludePath)</IncludePath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
@ -126,6 +126,7 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
@ -143,6 +144,7 @@
<ConformanceMode>true</ConformanceMode> <ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>NotUsing</PrecompiledHeader> <PrecompiledHeader>NotUsing</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>

@ -47,8 +47,15 @@ There are two (known to me, at time of writing) ways to get a working overlay fo
#define SUBHOOK_STATIC #define SUBHOOK_STATIC
#include <atomic> #include <atomic>
#include <filesystem>
#include <subhook.h> #include <subhook.h>
#include <spdlog/sinks/basic_file_sink.h>
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <fstream>
enum ZBID enum ZBID
{ {
ZBID_DEFAULT = 0, ZBID_DEFAULT = 0,
@ -71,6 +78,7 @@ enum ZBID
ZBID_LOCK = 17, ZBID_LOCK = 17,
ZBID_ABOVELOCK_UX = 18, ZBID_ABOVELOCK_UX = 18,
}; };
typedef BOOL(WINAPI* fSetWindowBand)(HWND hWnd, HWND hwndInsertAfter, DWORD dwBand); typedef BOOL(WINAPI* fSetWindowBand)(HWND hWnd, HWND hwndInsertAfter, DWORD dwBand);
@ -79,18 +87,22 @@ fSetWindowBand SetWindowBand;
std::atomic<bool> allow_exit = false; std::atomic<bool> allow_exit = false;
std::atomic<ZBID> to_set_window_band = ZBID_SYSTEM_TOOLS;
BOOL WINAPI SetGlosSIWindowBand(HWND hWnd, HWND hwndInsertAfter, DWORD dwBand) BOOL WINAPI SetGlosSIWindowBand(HWND hWnd, HWND hwndInsertAfter, DWORD dwBand)
{ {
subhook::ScopedHookRemove remove(&SetWindowBandHook); subhook::ScopedHookRemove remove(&SetWindowBandHook);
const auto glossi_hwnd = FindWindowA(nullptr, "GlosSITarget"); const auto glossi_hwnd = FindWindowA(nullptr, "GlosSITarget");
if (glossi_hwnd) if (glossi_hwnd)
{ {
spdlog::info("Found GlosSI Window");
// Most window bands don't really seem to work. // Most window bands don't really seem to work.
// However, notification and system_tools does! // However, notification and system_tools does!
// use system tools, as that allows the steam overlay to be interacted with // use system tools, as that allows the steam overlay to be interacted with
// without UWP apps minimizing // without UWP apps minimizing
SetWindowBand(glossi_hwnd, nullptr, ZBID_SYSTEM_TOOLS); auto success = SetWindowBand(glossi_hwnd, nullptr, to_set_window_band);
allow_exit = true; allow_exit = true;
spdlog::info("Set GlosSI Window Band to {}; success: {}", static_cast<int>(to_set_window_band), success);
} }
return SetWindowBand(hWnd, hwndInsertAfter, dwBand); return SetWindowBand(hWnd, hwndInsertAfter, dwBand);
} }
@ -102,7 +114,10 @@ DWORD WINAPI WaitThread(HMODULE hModule)
Sleep(10); Sleep(10);
} }
if (SetWindowBandHook.IsInstalled()) if (SetWindowBandHook.IsInstalled())
{
spdlog::debug("Uninstalling SetWindowBand hook");
SetWindowBandHook.Remove(); SetWindowBandHook.Remove();
}
FreeLibraryAndExitThread(hModule, 0); FreeLibraryAndExitThread(hModule, 0);
} }
@ -113,17 +128,104 @@ BOOL APIENTRY DllMain( HMODULE hModule,
{ {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{ {
auto configDirPath = std::filesystem::temp_directory_path()
.parent_path()
.parent_path()
.parent_path();
configDirPath /= "Roaming";
configDirPath /= "GlosSI";
if (!std::filesystem::exists(configDirPath))
std::filesystem::create_directories(configDirPath);
auto logPath = configDirPath;
logPath /= "UWPOverlayEnabler.log";
const auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(logPath.string(), true);
std::vector<spdlog::sink_ptr> sinks{ file_sink };
auto logger = std::make_shared<spdlog::logger>("log", sinks.begin(), sinks.end());
logger->set_level(spdlog::level::trace);
logger->flush_on(spdlog::level::trace);
spdlog::set_default_logger(logger);
spdlog::info("UWPOverlayEnabler loaded");
auto configPath = configDirPath;
configPath /= "UWPOverlayEnabler.cfg";
if (std::filesystem::exists(configPath))
{
std::ifstream config(configPath);
std::string line;
while (std::getline(config, line))
{
// github copilot, lol
// i take it!
if (line == "ZBID_DEFAULT")
to_set_window_band = ZBID_DEFAULT;
else if (line == "ZBID_DESKTOP")
to_set_window_band = ZBID_DESKTOP;
else if (line == "ZBID_UIACCESS")
to_set_window_band = ZBID_UIACCESS;
else if (line == "ZBID_IMMERSIVE_IHM")
to_set_window_band = ZBID_IMMERSIVE_IHM;
else if (line == "ZBID_IMMERSIVE_NOTIFICATION")
to_set_window_band = ZBID_IMMERSIVE_NOTIFICATION;
else if (line == "ZBID_IMMERSIVE_APPCHROME")
to_set_window_band = ZBID_IMMERSIVE_APPCHROME;
else if (line == "ZBID_IMMERSIVE_MOGO")
to_set_window_band = ZBID_IMMERSIVE_MOGO;
else if (line == "ZBID_IMMERSIVE_EDGY")
to_set_window_band = ZBID_IMMERSIVE_EDGY;
else if (line == "ZBID_IMMERSIVE_INACTIVEMOBODY")
to_set_window_band = ZBID_IMMERSIVE_INACTIVEMOBODY;
else if (line == "ZBID_IMMERSIVE_INACTIVEDOCK")
to_set_window_band = ZBID_IMMERSIVE_INACTIVEDOCK;
else if (line == "ZBID_IMMERSIVE_ACTIVEMOBODY")
to_set_window_band = ZBID_IMMERSIVE_ACTIVEMOBODY;
else if (line == "ZBID_IMMERSIVE_ACTIVEDOCK")
to_set_window_band = ZBID_IMMERSIVE_ACTIVEDOCK;
else if (line == "ZBID_IMMERSIVE_BACKGROUND")
to_set_window_band = ZBID_IMMERSIVE_BACKGROUND;
else if (line == "ZBID_IMMERSIVE_SEARCH")
to_set_window_band = ZBID_IMMERSIVE_SEARCH;
else if (line == "ZBID_GENUINE_WINDOWS")
to_set_window_band = ZBID_GENUINE_WINDOWS;
else if (line == "ZBID_IMMERSIVE_RESTRICTED")
to_set_window_band = ZBID_IMMERSIVE_RESTRICTED;
else if (line == "ZBID_SYSTEM_TOOLS")
to_set_window_band = ZBID_SYSTEM_TOOLS;
else if (line == "ZBID_LOCK")
to_set_window_band = ZBID_LOCK;
else if (line == "ZBID_ABOVELOCK_UX")
to_set_window_band = ZBID_ABOVELOCK_UX;
}
spdlog::info("Read window band from config: {}", static_cast<int>(to_set_window_band));
}
const auto hpath = LoadLibrary(L"user32.dll"); const auto hpath = LoadLibrary(L"user32.dll");
if (hpath) if (hpath)
{ {
spdlog::debug("Loaded user32.dll");
spdlog::debug("Installing SetWindowBand hook");
SetWindowBand = reinterpret_cast<fSetWindowBand>(GetProcAddress(hpath, "SetWindowBand")); SetWindowBand = reinterpret_cast<fSetWindowBand>(GetProcAddress(hpath, "SetWindowBand"));
SetWindowBandHook.Install(GetProcAddress(hpath, "SetWindowBand"), &SetGlosSIWindowBand, subhook::HookFlags::HookFlag64BitOffset); SetWindowBandHook.Install(GetProcAddress(hpath, "SetWindowBand"), &SetGlosSIWindowBand, subhook::HookFlags::HookFlag64BitOffset);
spdlog::debug("Creating wait thread");
CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)WaitThread, hModule, 0, nullptr)); CloseHandle(CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)WaitThread, hModule, 0, nullptr));
} else
{
spdlog::error("Loaded user32.dll");
} }
} }
else if (ul_reason_for_call == DLL_PROCESS_DETACH) { else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
spdlog::info("unloading UWPOverlayEnabler");
if (SetWindowBandHook.IsInstalled()) if (SetWindowBandHook.IsInstalled())
{
spdlog::debug("Uninstalling SetWindowBand hook");
SetWindowBandHook.Remove(); SetWindowBandHook.Remove();
}
} }
return TRUE; return TRUE;
} }

@ -1 +1 @@
Subproject commit 2816b31c8e777c2920e1f0881ce10c5c66e30c63 Subproject commit 59108a7f9a938911e1cc237003a396c886be85f8

2
deps/imgui vendored

@ -1 +1 @@
Subproject commit 9aae45eb4a05a5a1f96be1ef37eb503a12ceb889 Subproject commit 9cd9c2eff99877a3f10a7f9c2a3a5b9c15ea36c6
Loading…
Cancel
Save