From 7506f658017f4d915a975127b44e662420b03c7e Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sun, 14 Aug 2022 17:15:44 +0000 Subject: [PATCH] [d3d9] Move window proc handling code to own file --- src/d3d9/d3d9_swapchain.cpp | 166 +----------------------------------- src/d3d9/d3d9_window.cpp | 143 +++++++++++++++++++++++++++++++ src/d3d9/d3d9_window.h | 37 ++++++++ src/d3d9/meson.build | 3 +- 4 files changed, 183 insertions(+), 166 deletions(-) create mode 100644 src/d3d9/d3d9_window.cpp create mode 100644 src/d3d9/d3d9_window.h diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 0caa562d8..450070784 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -3,174 +3,10 @@ #include "d3d9_monitor.h" #include "d3d9_hud.h" +#include "d3d9_window.h" namespace dxvk { - - struct D3D9WindowData { - bool unicode; - bool filter; - bool activateProcessed; - WNDPROC proc; - D3D9SwapChainEx* swapchain; - }; - - - static dxvk::recursive_mutex g_windowProcMapMutex; - static std::unordered_map g_windowProcMap; - - static void SetActivateProcessed(HWND window, bool processed) - { - std::lock_guard lock(g_windowProcMapMutex); - auto it = g_windowProcMap.find(window); - if (it != g_windowProcMap.end()) - it->second.activateProcessed = processed; - } - - template - auto CallCharsetFunction(T unicode, J ascii, bool isUnicode, Args... args) { - return isUnicode - ? unicode(args...) - : ascii (args...); - } - - - class D3D9WindowMessageFilter { - - public: - - D3D9WindowMessageFilter(HWND window, bool filter = true) - : m_window(window) { - std::lock_guard lock(g_windowProcMapMutex); - auto it = g_windowProcMap.find(m_window); - m_filter = std::exchange(it->second.filter, filter); - } - - ~D3D9WindowMessageFilter() { - std::lock_guard lock(g_windowProcMapMutex); - auto it = g_windowProcMap.find(m_window); - it->second.filter = m_filter; - } - - D3D9WindowMessageFilter (const D3D9WindowMessageFilter&) = delete; - D3D9WindowMessageFilter& operator = (const D3D9WindowMessageFilter&) = delete; - - private: - - HWND m_window; - bool m_filter; - - }; - - - LRESULT CALLBACK D3D9WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam); - - - void ResetWindowProc(HWND window) { - std::lock_guard lock(g_windowProcMapMutex); - - auto it = g_windowProcMap.find(window); - if (it == g_windowProcMap.end()) - return; - - auto proc = reinterpret_cast( - CallCharsetFunction( - GetWindowLongPtrW, GetWindowLongPtrA, it->second.unicode, - window, GWLP_WNDPROC)); - - - if (proc == D3D9WindowProc) - CallCharsetFunction( - SetWindowLongPtrW, SetWindowLongPtrA, it->second.unicode, - window, GWLP_WNDPROC, reinterpret_cast(it->second.proc)); - - g_windowProcMap.erase(window); - } - - - void HookWindowProc(HWND window, D3D9SwapChainEx* swapchain) { - std::lock_guard lock(g_windowProcMapMutex); - - ResetWindowProc(window); - - D3D9WindowData windowData; - windowData.unicode = IsWindowUnicode(window); - windowData.filter = false; - windowData.activateProcessed = false; - windowData.proc = reinterpret_cast( - CallCharsetFunction( - SetWindowLongPtrW, SetWindowLongPtrA, windowData.unicode, - window, GWLP_WNDPROC, reinterpret_cast(D3D9WindowProc))); - windowData.swapchain = swapchain; - - g_windowProcMap[window] = std::move(windowData); - } - - - LRESULT CALLBACK D3D9WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { - if (message == WM_NCCALCSIZE && wparam == TRUE) - return 0; - - D3D9WindowData windowData = {}; - - { - std::lock_guard lock(g_windowProcMapMutex); - - auto it = g_windowProcMap.find(window); - if (it != g_windowProcMap.end()) - windowData = it->second; - } - - bool unicode = windowData.proc - ? windowData.unicode - : IsWindowUnicode(window); - - if (!windowData.proc || windowData.filter) - return CallCharsetFunction( - DefWindowProcW, DefWindowProcA, unicode, - window, message, wparam, lparam); - - if (message == WM_DESTROY) - ResetWindowProc(window); - else if (message == WM_ACTIVATEAPP) { - D3DDEVICE_CREATION_PARAMETERS create_parms; - windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); - - if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES)) { - D3D9WindowMessageFilter filter(window); - if (wparam && !windowData.activateProcessed) { - // Heroes of Might and Magic V needs this to resume drawing after a focus loss - D3DPRESENT_PARAMETERS params; - RECT rect; - - GetMonitorRect(GetDefaultMonitor(), &rect); - windowData.swapchain->GetPresentParameters(¶ms); - SetWindowPos(window, nullptr, rect.left, rect.top, params.BackBufferWidth, params.BackBufferHeight, - SWP_NOACTIVATE | SWP_NOZORDER); - SetActivateProcessed(window, true); - } - else if (!wparam) { - if (IsWindowVisible(window)) - ShowWindow(window, SW_MINIMIZE); - SetActivateProcessed(window, false); - } - } - } - else if (message == WM_SIZE) - { - D3DDEVICE_CREATION_PARAMETERS create_parms; - windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); - - if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES) && !IsIconic(window)) - PostMessageW(window, WM_ACTIVATEAPP, 1, GetCurrentThreadId()); - } - - return CallCharsetFunction( - CallWindowProcW, CallWindowProcA, unicode, - windowData.proc, window, message, wparam, lparam); - } - - static uint16_t MapGammaControlPoint(float x) { if (x < 0.0f) x = 0.0f; if (x > 1.0f) x = 1.0f; diff --git a/src/d3d9/d3d9_window.cpp b/src/d3d9/d3d9_window.cpp new file mode 100644 index 000000000..68dadcdc0 --- /dev/null +++ b/src/d3d9/d3d9_window.cpp @@ -0,0 +1,143 @@ +#include "d3d9_window.h" + +#include "d3d9_swapchain.h" + +namespace dxvk +{ + + struct D3D9WindowData { + bool unicode; + bool filter; + bool activateProcessed; + WNDPROC proc; + D3D9SwapChainEx* swapchain; + }; + + static dxvk::recursive_mutex g_windowProcMapMutex; + static std::unordered_map g_windowProcMap; + + D3D9WindowMessageFilter::D3D9WindowMessageFilter(HWND window, bool filter) + : m_window(window) { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(m_window); + m_filter = std::exchange(it->second.filter, filter); + } + + D3D9WindowMessageFilter::~D3D9WindowMessageFilter() { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(m_window); + it->second.filter = m_filter; + } + + LRESULT CALLBACK D3D9WindowProc(HWND window, UINT message, WPARAM wparam, LPARAM lparam) { + if (message == WM_NCCALCSIZE && wparam == TRUE) + return 0; + + D3D9WindowData windowData = {}; + + { + std::lock_guard lock(g_windowProcMapMutex); + + auto it = g_windowProcMap.find(window); + if (it != g_windowProcMap.end()) + windowData = it->second; + } + + bool unicode = windowData.proc + ? windowData.unicode + : IsWindowUnicode(window); + + if (!windowData.proc || windowData.filter) + return CallCharsetFunction( + DefWindowProcW, DefWindowProcA, unicode, + window, message, wparam, lparam); + + if (message == WM_DESTROY) + ResetWindowProc(window); + else if (message == WM_ACTIVATEAPP) { + D3DDEVICE_CREATION_PARAMETERS create_parms; + windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); + + if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES)) { + D3D9WindowMessageFilter filter(window); + if (wparam && !windowData.activateProcessed) { + // Heroes of Might and Magic V needs this to resume drawing after a focus loss + D3DPRESENT_PARAMETERS params; + RECT rect; + + GetMonitorRect(GetDefaultMonitor(), &rect); + windowData.swapchain->GetPresentParameters(¶ms); + SetWindowPos(window, nullptr, rect.left, rect.top, params.BackBufferWidth, params.BackBufferHeight, + SWP_NOACTIVATE | SWP_NOZORDER); + SetActivateProcessed(window, true); + } + else if (!wparam) { + if (IsWindowVisible(window)) + ShowWindow(window, SW_MINIMIZE); + SetActivateProcessed(window, false); + } + } + } + else if (message == WM_SIZE) + { + D3DDEVICE_CREATION_PARAMETERS create_parms; + windowData.swapchain->GetDevice()->GetCreationParameters(&create_parms); + + if (!(create_parms.BehaviorFlags & D3DCREATE_NOWINDOWCHANGES) && !IsIconic(window)) + PostMessageW(window, WM_ACTIVATEAPP, 1, GetCurrentThreadId()); + } + + return CallCharsetFunction( + CallWindowProcW, CallWindowProcA, unicode, + windowData.proc, window, message, wparam, lparam); + } + + void ResetWindowProc(HWND window) { + std::lock_guard lock(g_windowProcMapMutex); + + auto it = g_windowProcMap.find(window); + if (it == g_windowProcMap.end()) + return; + + auto proc = reinterpret_cast( + CallCharsetFunction( + GetWindowLongPtrW, GetWindowLongPtrA, it->second.unicode, + window, GWLP_WNDPROC)); + + + if (proc == D3D9WindowProc) + CallCharsetFunction( + SetWindowLongPtrW, SetWindowLongPtrA, it->second.unicode, + window, GWLP_WNDPROC, reinterpret_cast(it->second.proc)); + + g_windowProcMap.erase(window); + } + + + void HookWindowProc(HWND window, D3D9SwapChainEx* swapchain) { + std::lock_guard lock(g_windowProcMapMutex); + + ResetWindowProc(window); + + D3D9WindowData windowData; + windowData.unicode = IsWindowUnicode(window); + windowData.filter = false; + windowData.activateProcessed = false; + windowData.proc = reinterpret_cast( + CallCharsetFunction( + SetWindowLongPtrW, SetWindowLongPtrA, windowData.unicode, + window, GWLP_WNDPROC, reinterpret_cast(D3D9WindowProc))); + windowData.swapchain = swapchain; + + g_windowProcMap[window] = std::move(windowData); + } + + void SetActivateProcessed(HWND window, bool processed) + { + std::lock_guard lock(g_windowProcMapMutex); + auto it = g_windowProcMap.find(window); + if (it != g_windowProcMap.end()) + it->second.activateProcessed = processed; + } + +} diff --git a/src/d3d9/d3d9_window.h b/src/d3d9/d3d9_window.h new file mode 100644 index 000000000..84fcc0048 --- /dev/null +++ b/src/d3d9/d3d9_window.h @@ -0,0 +1,37 @@ +#pragma once + +#include + +namespace dxvk { + + class D3D9SwapChainEx; + + class D3D9WindowMessageFilter { + + public: + + D3D9WindowMessageFilter(HWND window, bool filter = true); + ~D3D9WindowMessageFilter(); + + D3D9WindowMessageFilter (const D3D9WindowMessageFilter&) = delete; + D3D9WindowMessageFilter& operator = (const D3D9WindowMessageFilter&) = delete; + + private: + + HWND m_window; + bool m_filter; + + }; + + template + auto CallCharsetFunction(T unicode, J ascii, bool isUnicode, Args... args) { + return isUnicode + ? unicode(args...) + : ascii (args...); + } + + void ResetWindowProc(HWND window); + void HookWindowProc(HWND window, D3D9SwapChainEx* swapchain); + void SetActivateProcessed(HWND window, bool processed); + +} diff --git a/src/d3d9/meson.build b/src/d3d9/meson.build index 2641f58ee..1af266270 100644 --- a/src/d3d9/meson.build +++ b/src/d3d9/meson.build @@ -41,7 +41,8 @@ d3d9_src = [ 'd3d9_format_helpers.cpp', 'd3d9_hud.cpp', 'd3d9_annotation.cpp', - 'd3d9_mem.cpp' + 'd3d9_mem.cpp', + 'd3d9_window.cpp' ] d3d9_dll = shared_library('d3d9'+dll_ext, d3d9_src, glsl_generator.process(d3d9_shaders), d3d9_res,