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:
parent
de8d2b37bb
commit
7506f65801
@ -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(¶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;
|
||||
|
143
src/d3d9/d3d9_window.cpp
Normal file
143
src/d3d9/d3d9_window.cpp
Normal 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(¶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<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
37
src/d3d9/d3d9_window.h
Normal 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);
|
||||
|
||||
}
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user