GlosSITarget: Allow Desktop config setting

pull/169/head
Peter Repukat 2 years ago
parent 21abef9bde
commit 33623936ed

@ -21,12 +21,18 @@ limitations under the License.
#include <ShObjIdl.h>
#include <atlbase.h>
#include <tlhelp32.h>
#include <Propsys.h>
#include <propkey.h>
#pragma comment(lib, "Shell32.lib")
#endif
#include "Settings.h"
#include <regex>
AppLauncher::AppLauncher(std::function<void()> shutdown) : shutdown_(std::move(shutdown))
AppLauncher::AppLauncher(
std::vector<HWND>& process_hwnds,
std::function<void()> shutdown) : process_hwnds_(process_hwnds), shutdown_(std::move(shutdown))
{
#ifdef _WIN32
UnPatchValveHooks();
@ -38,8 +44,10 @@ void AppLauncher::launchApp(const std::wstring& path, const std::wstring& args)
#ifdef _WIN32
if (Settings::launch.isUWP) {
spdlog::info("LaunchApp is UWP, launching...");
launched_uwp_path_ = path;
launchUWPApp(path.data(), args);
} else {
}
else {
spdlog::info("LaunchApp is Win32, launching...");
launchWin32App(path, args);
}
@ -75,6 +83,7 @@ void AppLauncher::update()
shutdown_();
}
}
getProcessHwnds();
#endif
process_check_clock_.restart();
}
@ -115,6 +124,37 @@ void AppLauncher::getChildPids(DWORD parent_pid)
}
CloseHandle(hp);
}
void AppLauncher::getProcessHwnds()
{
process_hwnds_.clear();
HWND curr_wnd = nullptr;
do {
curr_wnd = FindWindowEx(nullptr, curr_wnd, nullptr, nullptr);
DWORD check_pid = 0;
GetWindowThreadProcessId(curr_wnd, &check_pid);
if (check_pid == launched_pid_ || (std::ranges::find_if(child_pids_, [check_pid](auto pid) {
return pid == check_pid;
}) != child_pids_.end())) {
process_hwnds_.push_back(curr_wnd);
}
} while (curr_wnd != nullptr);
if (!launched_uwp_path_.empty()) {
// UWP and ApplicationFrameHost Bullshit.
// iterate all "ApplicationFrameWindow"; check the AppUserModelId (used for launching) and add on match.
do {
curr_wnd = FindWindowEx(nullptr, curr_wnd, L"ApplicationFrameWindow", nullptr);
IPropertyStore* propStore;
SHGetPropertyStoreForWindow(curr_wnd, IID_IPropertyStore, reinterpret_cast<void**>(&propStore));
PROPVARIANT prop;
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);
}
}
#endif
#ifdef _WIN32
@ -203,10 +243,12 @@ void AppLauncher::launchUWPApp(const LPCWSTR package_full_name, const std::wstri
result = sp_app_activation_manager->ActivateApplication(package_full_name, args.empty() ? nullptr : args.data(), AO_NONE, &launched_pid_);
if (!SUCCEEDED(result)) {
spdlog::error("ActivateApplication failed: Code {}", result);
} else {
}
else {
spdlog::info(L"Launched UWP Package \"{}\"", package_full_name);
}
} else {
}
else {
spdlog::error("CoCreateInstance failed: Code {}", result);
}
CoUninitialize();

@ -26,20 +26,25 @@ limitations under the License.
class AppLauncher {
public:
explicit AppLauncher(std::function<void()> shutdown = [](){});
explicit AppLauncher(
std::vector<HWND>& process_hwnds,
std::function<void()> shutdown = []() {});
void launchApp(const std::wstring& path, const std::wstring& args = L"");
void update();
void close();
private:
private:
std::function<void()> shutdown_;
sf::Clock process_check_clock_;
#ifdef _WIN32
static bool IsProcessRunning(DWORD pid);
void getChildPids(DWORD parent_pid);
void getProcessHwnds();
std::vector<HWND>& process_hwnds_;
std::wstring launched_uwp_path_;
// Valve also hooks "CreateProcess"
// Unpatch that so that launched programs don't also get hooked...

@ -46,6 +46,7 @@ inline struct Window {
inline struct Controller {
int maxControllers = 4;
bool allowDesktopConfig = true;
} controller;
inline bool checkIsUwp(const std::wstring& launch_path)
@ -132,6 +133,7 @@ inline void Parse(std::string arg1)
if (auto controllerConf = json["controller"]; controllerConf.is_object()) {
safeParseValue(controllerConf, "maxControllers", controller.maxControllers);
safeParseValue(controllerConf, "allowDesktopConfig", controller.allowDesktopConfig);
}
json_file.close();

@ -41,7 +41,7 @@ SteamTarget::SteamTarget(int argc, char* argv[])
}),
overlay_(window_.getOverlay()),
detector_([this](bool overlay_open) { onOverlayChanged(overlay_open); }),
launcher_([this] {
launcher_(force_config_hwnds_, [this] {
delayed_shutdown_ = true;
delay_shutdown_clock_.restart();
})
@ -363,6 +363,13 @@ bool SteamTarget::getXBCRebindingEnabled()
return xbsup == "1";
}
/*
* The "magic" that keeps a controller-config forced (without hooking into Steam)
*
* Hook into own process and detour "GetForegroundWindow"
* Deatour function always returns HWND of own application window
* Steam now doesn't detect application changes and keeps the game-specific input config without reverting to desktop-conf
*/
void SteamTarget::keepControllerConfig(bool keep)
{
#ifdef _WIN32
@ -386,7 +393,28 @@ void SteamTarget::keepControllerConfig(bool keep)
#ifdef _WIN32
HWND SteamTarget::keepFgWindowHookFn()
{
return target_window_handle_;
if (!Settings::controller.allowDesktopConfig) {
return target_window_handle_;
}
subhook::ScopedHookRemove remove(&getFgWinHook);
HWND real_fg_win = GetForegroundWindow();
if (real_fg_win == nullptr) {
return target_window_handle_;
}
if (std::ranges::find_if(force_config_hwnds_, [real_fg_win](auto hwnd) {
return hwnd == real_fg_win;
}) != force_config_hwnds_.end()) {
if (last_real_hwnd_ != real_fg_win) {
last_real_hwnd_ = real_fg_win;
spdlog::debug("Active window (\"{:#x}\") in launched process window list, forcing specific config", reinterpret_cast<uint64_t>(real_fg_win));
}
return target_window_handle_;
}
if (last_real_hwnd_ != real_fg_win) {
last_real_hwnd_ = real_fg_win;
spdlog::debug("Active window (\"{:#x}\") not in launched process window list, allowing desktop-config", reinterpret_cast<uint64_t>(real_fg_win));
}
return real_fg_win;
}
#endif

@ -58,6 +58,8 @@ class SteamTarget {
#ifdef _WIN32
static HWND keepFgWindowHookFn();
static inline subhook::Hook getFgWinHook;
static inline std::vector<HWND> force_config_hwnds_ = {};
static inline HWND last_real_hwnd_ = nullptr;
#endif
/*
@ -89,7 +91,6 @@ class SteamTarget {
bool delayed_shutdown_ = false;
sf::Clock delay_shutdown_clock_;
static constexpr std::wstring_view user_data_path_ = L"/userdata/";
static constexpr std::wstring_view config_file_name_ = L"/config/localconfig.vdf";
static constexpr std::string_view overlay_hotkey_name_ = "InGameOverlayShortcutKey ";

Loading…
Cancel
Save