1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Move window proc handling code to own file

This commit is contained in:
Joshua Ashton 2022-08-14 17:15:44 +00:00
parent de8d2b37bb
commit 7506f65801
4 changed files with 183 additions and 166 deletions

View File

@ -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<HWND, D3D9WindowData> 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 <typename T, typename J, typename ... Args>
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<WNDPROC>(
CallCharsetFunction(
GetWindowLongPtrW, GetWindowLongPtrA, it->second.unicode,
window, GWLP_WNDPROC));
if (proc == D3D9WindowProc)
CallCharsetFunction(
SetWindowLongPtrW, SetWindowLongPtrA, it->second.unicode,
window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(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<WNDPROC>(
CallCharsetFunction(
SetWindowLongPtrW, SetWindowLongPtrA, windowData.unicode,
window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(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(&params);
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;

143
src/d3d9/d3d9_window.cpp Normal file
View File

@ -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<HWND, D3D9WindowData> 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(&params);
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<WNDPROC>(
CallCharsetFunction(
GetWindowLongPtrW, GetWindowLongPtrA, it->second.unicode,
window, GWLP_WNDPROC));
if (proc == D3D9WindowProc)
CallCharsetFunction(
SetWindowLongPtrW, SetWindowLongPtrA, it->second.unicode,
window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(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<WNDPROC>(
CallCharsetFunction(
SetWindowLongPtrW, SetWindowLongPtrA, windowData.unicode,
window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(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;
}
}

37
src/d3d9/d3d9_window.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <windows.h>
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 <typename T, typename J, typename ... Args>
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);
}

View File

@ -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,