diff --git a/CMakeLists.txt b/CMakeLists.txt index 416528845..1fda6631c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1975,6 +1975,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -2171,6 +2172,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -3804,6 +3806,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -4000,6 +4003,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -4196,6 +4200,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -6549,6 +6554,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -6745,6 +6751,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -7661,6 +7668,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -8575,6 +8583,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -9491,6 +9500,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" @@ -10407,6 +10417,7 @@ if(REF_BUILD_FRAMEWORK AND CMAKE_SIZEOF_VOID_P EQUAL 8) # build-framework "src/Main.cpp" "src/Mods.cpp" "src/REFramework.cpp" + "src/WindowFilter.cpp" "src/WindowsMessageHook.cpp" "src/mods/APIProxy.cpp" "src/mods/Camera.cpp" diff --git a/src/WindowFilter.cpp b/src/WindowFilter.cpp new file mode 100644 index 000000000..e41b131c2 --- /dev/null +++ b/src/WindowFilter.cpp @@ -0,0 +1,81 @@ +#include "WindowFilter.hpp" + +// To prevent usage of statics (TLS breaks the present thread...?) +WindowFilter g_window_filter{}; + +WindowFilter& WindowFilter::get() { + return g_window_filter; +} + +WindowFilter::WindowFilter() { + // We create a job thread because GetWindowTextA can actually deadlock inside + // the present thread... + m_job_thread = std::make_unique([this](std::stop_token s){ + while (!s.stop_requested()) { + std::this_thread::sleep_for(std::chrono::milliseconds{100}); + + if (m_window_jobs.empty()) { + return; + } + + std::vector window_jobs{}; + + { + std::scoped_lock _{m_mutex}; + window_jobs = std::move(m_window_jobs); + } + + for (const auto hwnd : window_jobs) { + if (is_filtered_nocache(hwnd)) { + filter_window(hwnd); + } + } + } + }); +} + +WindowFilter::~WindowFilter() { + m_job_thread->request_stop(); + m_job_thread->join(); +} + +bool WindowFilter::is_filtered(HWND hwnd) { + if (hwnd == nullptr) { + return true; + } + + std::scoped_lock _{m_mutex}; + + if (m_filtered_windows.find(hwnd) != m_filtered_windows.end()) { + return true; + } + + // if we havent even seen this window yet, add it to the job queue + // and return true; + if (m_seen_windows.find(hwnd) == m_seen_windows.end()) { + m_seen_windows.insert(hwnd); + m_window_jobs.push_back(hwnd); + return true; + } + + return false; +} + +bool WindowFilter::is_filtered_nocache(HWND hwnd) { + // get window name + char window_name[256]{}; + GetWindowTextA(hwnd, window_name, sizeof(window_name)); + + const auto sv = std::string_view{window_name}; + + if (sv.find("UE4SS") != std::string_view::npos) { + return true; + } + + if (sv.find("PimaxXR") != std::string_view::npos) { + return true; + } + + // TODO: more problematic windows + return false; +} \ No newline at end of file diff --git a/src/WindowFilter.hpp b/src/WindowFilter.hpp index 1d543c9bd..f6732e759 100644 --- a/src/WindowFilter.hpp +++ b/src/WindowFilter.hpp @@ -1,65 +1,35 @@ #pragma once -#include #include #include #include +#include +#include +#include class WindowFilter { public: - static WindowFilter& get() { - static WindowFilter instance{}; - return instance; - } + static WindowFilter& get(); public: - bool is_filtered(HWND hwnd) { - if (hwnd == nullptr) { - return true; - } - - std::scoped_lock _{m_mutex}; - - if (m_filtered_windows.find(hwnd) != m_filtered_windows.end()) { - return true; - } - - if (m_seen_windows.find(hwnd) != m_seen_windows.end()) { - return false; - } - - m_seen_windows.insert(hwnd); + WindowFilter(); + virtual ~WindowFilter(); - if (is_filtered_nocache(hwnd)) { - filter_window(hwnd); - return true; - } + bool is_filtered(HWND hwnd); - return false; - } - -private: void filter_window(HWND hwnd) { + std::scoped_lock _{m_mutex}; m_filtered_windows.insert(hwnd); } - bool is_filtered_nocache(HWND hwnd) { - // get window name - char window_name[256]{}; - GetWindowTextA(hwnd, window_name, sizeof(window_name)); - - const auto sv = std::string_view{window_name}; - - if (sv.find("PimaxXR") != std::string_view::npos) { - return true; - } +private: + bool is_filtered_nocache(HWND hwnd); - // TODO: more problematic windows - return false; - } + std::recursive_mutex m_mutex{}; + std::vector m_window_jobs{}; + std::unique_ptr m_job_thread{}; - std::mutex m_mutex{}; std::unordered_set m_seen_windows{}; std::unordered_set m_filtered_windows{}; }; \ No newline at end of file