Refactor window platform helper functions

This commit is contained in:
WarmUpTill
2026-05-18 19:35:41 +02:00
parent ee1d0136d9
commit 930e8b38d4
10 changed files with 388 additions and 470 deletions

View File

@@ -42,19 +42,20 @@ void CloseWindow(const std::string &) {}
std::optional<std::string> MacroActionWindow::GetMatchingWindow() const
{
const auto windowList = GetWindowList();
const auto windows = GetWindows();
if (!_regex.Enabled()) {
if (std::find(windowList.begin(), windowList.end(),
std::string(_window)) == windowList.end()) {
return {};
for (const auto &info : windows) {
if (info.title == std::string(_window)) {
return info.title;
}
}
return _window;
return {};
}
for (const auto &window : windowList) {
if (_regex.Matches(window, _window)) {
return window;
for (const auto &info : windows) {
if (_regex.Matches(info.title, _window)) {
return info.title;
}
}

View File

@@ -14,21 +14,6 @@ bool MacroConditionWindow::_registered = MacroConditionFactory::Register(
{MacroConditionWindow::Create, MacroConditionWindowEdit::Create,
"AdvSceneSwitcher.condition.window"});
static bool windowContainsText(const std::string &window,
const std::string &matchText,
const RegexConfig &regex)
{
auto text = GetTextInWindow(window);
if (!text.has_value()) {
return false;
}
if (regex.Enabled()) {
return regex.Matches(*text, matchText);
}
return text == matchText;
}
void MacroConditionWindow::SetCheckText(bool value)
{
#ifdef _WIN32
@@ -46,92 +31,76 @@ bool MacroConditionWindow::GetCheckText()
}
bool MacroConditionWindow::WindowMatchesRequirements(
const std::string &window) const
const WindowInfo &info) const
{
const bool focusCheckOK =
(!_focus || window == ForegroundWindowTitle());
if (!focusCheckOK) {
if (_focus && !info.focused) {
return false;
}
const bool fullscreenCheckOK = (!_fullscreen || IsFullscreen(window));
if (!fullscreenCheckOK) {
if (_fullscreen && !info.fullscreen) {
return false;
}
const bool maxCheckOK = (!_maximized || IsMaximized(window));
if (!maxCheckOK) {
if (_maximized && !info.maximized) {
return false;
}
const bool textCheckOK =
(!_checkText || windowContainsText(window, _text, _textRegex));
if (!textCheckOK) {
return false;
if (_checkText) {
if (!info.text.has_value()) {
return false;
}
if (_textRegex.Enabled()) {
if (!_textRegex.Matches(*info.text, _text)) {
return false;
}
} else {
if (*info.text != std::string(_text)) {
return false;
}
}
}
return true;
}
bool MacroConditionWindow::WindowMatches(
const std::vector<std::string> &windowList)
bool MacroConditionWindow::FindMatch(const std::vector<WindowInfo> &windows)
{
bool match = !_checkTitle ||
std::find(windowList.begin(), windowList.end(),
std::string(_window)) != windowList.end();
match = match && WindowMatchesRequirements(_window);
SetVariableValueBasedOnMatch(_window);
return match;
}
#ifdef _WIN32
std::string GetWindowClassByWindowTitle(const std::string &window);
#endif
bool MacroConditionWindow::WindowRegexMatches(
const std::vector<std::string> &windowList)
{
// No need to test if checking for window title is required as if the
// user has disabled window title matching the option will always be
// enabled in the backend and use the regular expression ".*".
for (const auto &window : windowList) {
if (_windowRegex.Matches(window, _window) &&
WindowMatchesRequirements(window)) {
SetVariableValueBasedOnMatch(window);
return true;
// When regex is enabled the title check is always active (the backend
// uses ".*" when the user disables the title check), so we can use a
// single predicate for both modes.
for (const auto &info : windows) {
const bool titleOK =
_windowRegex.Enabled()
? _windowRegex.Matches(info.title, _window)
: (!_checkTitle ||
info.title == std::string(_window));
if (!titleOK || !WindowMatchesRequirements(info)) {
continue;
}
SetVariableValueBasedOnMatch(&info);
return true;
}
SetVariableValueBasedOnMatch("");
SetVariableValueBasedOnMatch(nullptr);
return false;
}
void MacroConditionWindow::SetVariableValueBasedOnMatch(
const std::string &matchWindow)
void MacroConditionWindow::SetVariableValueBasedOnMatch(const WindowInfo *info)
{
SetTempVarValue("window", matchWindow);
const auto geo = GetWindowGeometry(matchWindow);
if (geo) {
SetTempVarValue("windowX", std::to_string(geo->x));
SetTempVarValue("windowY", std::to_string(geo->y));
SetTempVarValue("windowWidth", std::to_string(geo->width));
SetTempVarValue("windowHeight", std::to_string(geo->height));
}
const std::string title = info ? info->title : "";
SetTempVarValue("window", title);
SetTempVarValue("windowX", info ? std::to_string(info->x) : "");
SetTempVarValue("windowY", info ? std::to_string(info->y) : "");
SetTempVarValue("windowWidth", info ? std::to_string(info->width) : "");
SetTempVarValue("windowHeight",
info ? std::to_string(info->height) : "");
#ifdef _WIN32
SetTempVarValue("windowClass",
GetWindowClassByWindowTitle(matchWindow));
SetTempVarValue("windowClass", info ? info->windowClass : "");
if (_checkText) {
const auto text = GetTextInWindow(matchWindow);
if (text) {
SetTempVarValue("windowText", *text);
}
SetTempVarValue("windowText",
(info && info->text) ? *info->text : "");
}
#endif
if (!IsReferencedInVars()) {
return;
}
if (_checkText) {
const auto text = GetTextInWindow(matchWindow);
SetVariableValue(text.value_or(""));
SetVariableValue((info && info->text) ? *info->text : "");
} else {
SetVariableValue(ForegroundWindowTitle());
}
@@ -144,13 +113,18 @@ static bool foregroundWindowChanged()
bool MacroConditionWindow::CheckCondition()
{
const auto windowList = GetWindowList();
bool match = false;
if (_windowRegex.Enabled()) {
match = WindowRegexMatches(windowList);
} else {
match = WindowMatches(windowList);
}
WindowQueryOptions options;
options.focus = _focus;
options.fullscreen = _fullscreen;
options.maximized = _maximized;
options.geometry = true;
#ifdef _WIN32
options.windowClass = true;
options.text = _checkText;
#endif
const auto windows = GetWindows(options);
bool match = FindMatch(windows);
match = match && (!_windowFocusChanged || foregroundWindowChanged());
return match;
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include "macro-condition-edit.hpp"
#include "platform-funcs.hpp"
#include "variable-text-edit.hpp"
#include "regex-config.hpp"
#include "window-selection.hpp"
@@ -37,10 +38,9 @@ public:
RegexConfig _textRegex = RegexConfig::PartialMatchRegexConfig();
private:
bool WindowMatchesRequirements(const std::string &window) const;
bool WindowMatches(const std::vector<std::string> &windowList);
bool WindowRegexMatches(const std::vector<std::string> &windowList);
void SetVariableValueBasedOnMatch(const std::string &matchWindow);
bool WindowMatchesRequirements(const WindowInfo &info) const;
bool FindMatch(const std::vector<WindowInfo> &windows);
void SetVariableValueBasedOnMatch(const WindowInfo *info);
void SetupTempVars();
// For now only supported on Windows

View File

@@ -205,26 +205,6 @@ static std::vector<HWND> getHWNDfromTitle(const std::string &title)
return hwnds;
}
std::string GetWindowClassByWindowTitle(const std::string &window)
{
auto hwnds = getHWNDfromTitle(window);
if (hwnds.empty()) {
return "";
}
auto hwnd = hwnds.at(0);
std::wstring wClass;
wClass.resize(1024);
if (!GetClassNameW(hwnd, &wClass[0], wClass.capacity())) {
return "";
}
size_t len = os_wcs_to_utf8(wClass.c_str(), 0, nullptr, 0);
std::string className;
className.resize(len);
os_wcs_to_utf8(wClass.c_str(), 0, &className[0], len + 1);
return className;
}
void SetFocusWindow(const std::string &title)
{
auto hwnds = getHWNDfromTitle(title);