Compare commits

...

2 Commits

@ -434,7 +434,8 @@ QVariantMap UIModel::getDefaultConf() const
{"maxFps", QJsonValue::Null},
{"scale", QJsonValue::Null},
{"windowMode", false},
{"disableGlosSIOverlay", false}
{"disableGlosSIOverlay", false},
{"opaqueSteamOverlay", false}
}},
};

@ -28,10 +28,11 @@ limitations under the License.
#pragma comment(lib, "Shell32.lib")
#endif
#include "..\common\Settings.h"
#include "../common/Settings.h"
#include <regex>
#include "HttpServer.h"
#include "Overlay.h"
#include "../common/UnhookUtil.h"
#include "../common/util.h"
@ -47,6 +48,32 @@ AppLauncher::AppLauncher(
spdlog::debug("App launch requested");
}
#endif
HttpServer::AddEndpoint({"/launched-pids",
HttpServer::Method::GET,
[this](const httplib::Request& req, httplib::Response& res) {
const nlohmann::json j = launchedPids();
res.set_content(j.dump(), "text/json");
}});
HttpServer::AddEndpoint({"/launched-pids",
HttpServer::Method::POST,
[this](const httplib::Request& req, httplib::Response& res) {
try {
const nlohmann::json postbody = nlohmann::json::parse(req.body);
addPids(postbody.get<std::vector<DWORD>>());
}
catch (std::exception& e) {
res.status = 401;
res.set_content(nlohmann::json{
{"code", 401},
{"name", "Bad Request"},
{"message", e.what()},
}
.dump(),
"text/json");
}
}});
};
void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args)
@ -255,7 +282,7 @@ void AppLauncher::getProcessHwnds()
propStore->GetValue(PKEY_AppUserModel_ID, &prop);
if (prop.bstrVal != nullptr && std::wstring(prop.bstrVal) == launched_uwp_path_) {
process_hwnds_.push_back(curr_wnd);
}
}
}
} while (curr_wnd != nullptr);
}
@ -298,11 +325,11 @@ void AppLauncher::launchWin32App(const std::wstring& path, const std::wstring& a
// }
std::wstring args_cpy(
args.empty()
? L""
? L""
: ((native_seps_path.find(L" ") != std::wstring::npos
? L"\"" + native_seps_path + L"\""
: native_seps_path) + L" " + args)
);
: native_seps_path) +
L" " + args));
DWORD pid;
@ -319,7 +346,8 @@ void AppLauncher::launchWin32App(const std::wstring& path, const std::wstring& a
&process_info)) {
pid = process_info.dwProcessId;
} else {
}
else {
DWORD error_code = GetLastError();
if (error_code == ERROR_ELEVATION_REQUIRED) {
@ -342,11 +370,13 @@ void AppLauncher::launchWin32App(const std::wstring& path, const std::wstring& a
spdlog::error(L"Couldn't get process id after starting program: \"{}\"; Error code {}", native_seps_path, GetLastError());
}
CloseHandle(shExecInfo.hProcess);
} else {
}
else {
spdlog::error(L"Couldn't start program with elevated permissions: \"{}\"; Error code {}", native_seps_path, GetLastError());
return;
}
} else {
}
else {
spdlog::error(L"Could't start program: \"{}\"; Error code: {}", native_seps_path, error_code);
return;
}

@ -0,0 +1,25 @@
#pragma once
#include "HttpServer.h"
#include "../common/Settings.h"
#include "../common/steam_util.h"
namespace CHTE {
inline void addEndpoints()
{
HttpServer::AddEndpoint(
{"/settings",
HttpServer::Method::GET,
[](const httplib::Request& req, httplib::Response& res) {
res.set_content(Settings::toJson().dump(), "text/json");
}});
HttpServer::AddEndpoint(
{"/steam_settings",
HttpServer::Method::GET,
[](const httplib::Request& req, httplib::Response& res) {
res.set_content(util::steam::getSteamConfig().dump(4), "text/json");
}});
};
} // namespace CHTE

@ -209,6 +209,7 @@
<ClInclude Include="..\deps\imgui\imgui.h" />
<ClInclude Include="..\deps\subhook\subhook.h" />
<ClInclude Include="AppLauncher.h" />
<ClInclude Include="CommonHttpEndpoints.h" />
<ClInclude Include="DllInjector.h" />
<ClInclude Include="GlosSI_logo.h" />
<ClInclude Include="HttpServer.h" />

@ -179,6 +179,9 @@
<ClInclude Include="HttpServer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CommonHttpEndpoints.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\deps\SFML\out\Debug\lib\Debug\sfml-system-d-2.dll" />

@ -23,10 +23,15 @@ limitations under the License.
#include "../common/Settings.h"
#include "../common/steam_util.h"
HttpServer::HttpServer(AppLauncher& app_launcher, std::function<void()> close) : app_launcher_(app_launcher), close_(std::move(close))
HttpServer::HttpServer(std::function<void()> close) : close_(std::move(close))
{
}
void HttpServer::AddEndpoint(const Endpoint&& e)
{
endpoints_.push_back(e);
}
void HttpServer::run()
{
auto setCorsHeader = [](httplib::Response& res) {
@ -38,65 +43,66 @@ void HttpServer::run()
setCorsHeader(res);
});
server_.Get("/launched-pids", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
const nlohmann::json j = app_launcher_.launchedPids();
res.set_content(j.dump(), "text/json");
setCorsHeader(res);
});
for (const auto& e : endpoints_) {
const auto fn = ([this, &e]() -> httplib::Server& (httplib::Server::*)(const std::string&, httplib::Server::Handler) {
switch (e.method) {
case POST:
return &httplib::Server::Post;
case PUT:
return &httplib::Server::Put;
case PATCH:
return &httplib::Server::Patch;
default:
return &httplib::Server::Get;
}
})();
server_.Post("/launched-pids", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
try {
const nlohmann::json postbody = nlohmann::json::parse(req.body);
app_launcher_.addPids(postbody.get<std::vector<DWORD>>());
} catch (std::exception& e) {
res.status = 401;
res.set_content(nlohmann::json{
{"code", 401},
{"name", "Bad Request"},
{"message", e.what()},
}
.dump(),
"text/json");
return;
}
catch (...) {
res.status = 500;
res.set_content(nlohmann::json{
{"code", 500},
{"name", "Internal Server Error"},
{"message", "Unknown Error"},
}
.dump(),
"text/json");
return;
}
const nlohmann::json j = app_launcher_.launchedPids();
res.set_content(j.dump(), "text/json");
});
(server_.*fn)(e.path, [this, &e, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
res.status = 0;
res.content_length_ = 0;
try {
e.handler(req, res);
}
catch (std::exception& err) {
spdlog::error("Exception in http handler: {}", err.what());
res.status = res.status == 0 ? 500 : res.status;
if (res.content_length_ == 0) {
res.set_content(nlohmann::json{
{"code", res.status},
{"name", "HandlerError"},
{"message", err.what()},
}
.dump(),
"text/json");
}
}
catch (...) {
res.status = 500;
res.set_content(nlohmann::json{
{"code", res.status},
{"name", "Internal Server Error"},
{"message", "Unknown Error"},
}
.dump(),
"text/json");
return;
}
});
}
server_.Post("/quit", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
close_();
});
server_.Get("/settings", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
res.set_content(Settings::toJson().dump(), "text/json");
});
server_.Get("/steam_settings", [this, &setCorsHeader](const httplib::Request& req, httplib::Response& res) {
setCorsHeader(res);
res.set_content(util::steam::getSteamConfig().dump(4), "text/json");
});
server_thread_ = std::thread([this]() {
if (!server_.listen("0.0.0.0", port_)) {
spdlog::error("Couldn't start http-server");
return;
}
spdlog::debug("Started http-server on port {}", static_cast<int>(port_));
});
});
}
void HttpServer::stop()

@ -23,16 +23,34 @@ class AppLauncher;
class HttpServer {
public:
explicit HttpServer(AppLauncher& app_launcher, std::function<void()> close);
explicit HttpServer(std::function<void()> close);
enum Method {
GET,
POST,
PUT,
PATCH,
};
struct Endpoint {
std::string path;
Method method;
std::function<void(const httplib::Request& req, httplib::Response& res)> handler;
};
static void AddEndpoint(const Endpoint&& e);
void run();
void stop();
private:
httplib::Server server_;
std::thread server_thread_;
uint16_t port_ = 8756;
AppLauncher& app_launcher_;
std::function<void()> close_;
static inline std::vector<Endpoint> endpoints_;
};

@ -28,6 +28,8 @@ limitations under the License.
#include <CEFInject.h>
#include "CommonHttpEndpoints.h"
SteamTarget::SteamTarget()
: window_(
[this] { run_ = false; },
@ -43,7 +45,7 @@ SteamTarget::SteamTarget()
delayed_shutdown_ = true;
delay_shutdown_clock_.restart();
}),
server_(launcher_, [this] { run_ = false; })
server_([this] { run_ = false; })
{
target_window_handle_ = window_.getSystemHandle();
}
@ -57,6 +59,8 @@ int SteamTarget::run()
run_ = true;
CHTE::addEndpoints();
server_.run();
@ -212,11 +216,17 @@ void SteamTarget::onOverlayChanged(bool overlay_open)
if (overlay_open) {
focusWindow(target_window_handle_);
window_.setClickThrough(!overlay_open);
if (!Settings::window.windowMode && Settings::window.opaqueSteamOverlay) {
window_.setTransparent(false);
}
}
else {
if (!(overlay_.expired() ? false : overlay_.lock()->isEnabled())) {
window_.setClickThrough(!overlay_open);
focusWindow(last_foreground_window_);
if (!Settings::window.windowMode && Settings::window.opaqueSteamOverlay) {
window_.setTransparent(true);
}
}
}
if (!overlay_trigger_flag_) {

@ -149,6 +149,41 @@ void TargetWindow::setClickThrough(bool click_through)
#endif
}
void TargetWindow::setTransparent(bool transparent) const
{
HWND hwnd = window_.getSystemHandle();
if (transparent) {
// if (windowed_) {
// DWM_BLURBEHIND bb{.dwFlags = DWM_BB_ENABLE, .fEnable = true, .hRgnBlur = nullptr};
// DwmEnableBlurBehindWindow(hwnd, &bb);
// } // semi-transparent in window mode, but deprecated api
// On Linux the window will (should) automagically be semi-transparent
// transparent windows window...
auto style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~WS_OVERLAPPED;
style |= WS_POPUP;
SetWindowLong(hwnd, GWL_STYLE, style);
MARGINS margins = { -1 };
DwmExtendFrameIntoClientArea(hwnd, &margins);
spdlog::debug("Setting window to transparent");
} else {
auto style = GetWindowLong(hwnd, GWL_STYLE);
style |= WS_OVERLAPPED;
style &= ~WS_POPUP;
SetWindowLong(hwnd, GWL_STYLE, style);
MARGINS margins = {0};
DwmExtendFrameIntoClientArea(hwnd, &margins);
spdlog::debug("Setting window to opaque");
}
}
void TargetWindow::update()
{
sf::Event event{};
@ -364,22 +399,7 @@ void TargetWindow::createWindow()
auto dpi = GetWindowDPI(hwnd);
spdlog::debug("Screen DPI: {}", dpi);
//if (windowed_) {
// DWM_BLURBEHIND bb{.dwFlags = DWM_BB_ENABLE, .fEnable = true, .hRgnBlur = nullptr};
// DwmEnableBlurBehindWindow(hwnd, &bb);
//} // semi-transparent in window mode, but deprecated api
// On Linux the window will (should) automagically be semi-transparent
// transparent windows window...
auto style = GetWindowLong(hwnd, GWL_STYLE);
style &= ~WS_OVERLAPPED;
style |= WS_POPUP;
SetWindowLong(hwnd, GWL_STYLE, style);
MARGINS margins;
margins.cxLeftWidth = -1;
DwmExtendFrameIntoClientArea(hwnd, &margins);
setTransparent(true);
DEVMODE dev_mode = {};
dev_mode.dmSize = sizeof(DEVMODE);

@ -39,6 +39,7 @@ class TargetWindow {
void setFpsLimit(unsigned int fps_limit);
void setClickThrough(bool click_through);
void setTransparent(bool transparent) const;
void update();
void close();

@ -61,6 +61,7 @@ namespace Settings
bool disableOverlay = false;
bool hideAltTab = true;
bool disableGlosSIOverlay = false;
bool opaqueSteamOverlay = false;
} window;
inline struct Controller
@ -219,6 +220,7 @@ namespace Settings
safeParseValue(winconf, "disableOverlay", window.disableOverlay);
safeParseValue(winconf, "hideAltTab", window.hideAltTab);
safeParseValue(winconf, "disableGlosSIOverlay", window.disableGlosSIOverlay);
safeParseValue(winconf, "opaqueSteamOverlay", window.opaqueSteamOverlay);
}
if (const auto controllerConf = json["controller"]; !controllerConf.is_null() && !controllerConf.empty() && controllerConf.is_object())
@ -336,6 +338,7 @@ namespace Settings
json["window"]["scale"] = window.scale;
json["window"]["disableOverlay"] = window.disableOverlay;
json["window"]["hideAltTab"] = window.hideAltTab;
json["window"]["opaqueSteamOverlay"] = window.opaqueSteamOverlay;
json["controller"]["maxControllers"] = controller.maxControllers;
json["controller"]["allowDesktopConfig"] = controller.allowDesktopConfig;
json["controller"]["emulateDS4"] = controller.emulateDS4;

Loading…
Cancel
Save