diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj
index c44216c..0884e32 100644
--- a/DDrawCompat/DDrawCompat.vcxproj
+++ b/DDrawCompat/DDrawCompat.vcxproj
@@ -301,6 +301,7 @@
+
@@ -401,6 +402,7 @@
+
@@ -454,4 +456,4 @@
-
+
\ No newline at end of file
diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters
index 35f0bda..845994c 100644
--- a/DDrawCompat/DDrawCompat.vcxproj.filters
+++ b/DDrawCompat/DDrawCompat.vcxproj.filters
@@ -513,6 +513,9 @@
Header Files\Common
+
+ Header Files\Gdi
+
@@ -809,6 +812,9 @@
Source Files\Common
+
+ Source Files\Gdi
+
diff --git a/DDrawCompat/Dll/DllMain.cpp b/DDrawCompat/Dll/DllMain.cpp
index f705a95..1eb6508 100644
--- a/DDrawCompat/Dll/DllMain.cpp
+++ b/DDrawCompat/Dll/DllMain.cpp
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -113,7 +114,7 @@ namespace
Compat::Log() << "Installing GDI hooks";
Gdi::installHooks();
Compat::closeDbgEng();
- Gdi::PresentationWindow::startThread();
+ Gdi::GuiThread::start();
Compat::Log() << "Finished installing hooks";
isAlreadyInstalled = true;
}
diff --git a/DDrawCompat/Gdi/Gdi.cpp b/DDrawCompat/Gdi/Gdi.cpp
index 700e6a1..fc1732f 100644
--- a/DDrawCompat/Gdi/Gdi.cpp
+++ b/DDrawCompat/Gdi/Gdi.cpp
@@ -8,6 +8,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -74,6 +75,7 @@ namespace Gdi
Caret::installHooks();
Cursor::installHooks();
Font::installHooks();
+ WinProc::installHooks();
}
bool isDisplayDc(HDC dc)
@@ -90,7 +92,7 @@ namespace Gdi
void redrawWindow(HWND hwnd, HRGN rgn)
{
- if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || PresentationWindow::isPresentationWindow(hwnd))
+ if (!IsWindowVisible(hwnd) || IsIconic(hwnd) || GuiThread::isGuiThreadWindow(hwnd))
{
return;
}
diff --git a/DDrawCompat/Gdi/GuiThread.cpp b/DDrawCompat/Gdi/GuiThread.cpp
new file mode 100644
index 0000000..37952a9
--- /dev/null
+++ b/DDrawCompat/Gdi/GuiThread.cpp
@@ -0,0 +1,157 @@
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace
+{
+ const UINT WM_USER_EXECUTE = WM_USER;
+
+ unsigned g_threadId = 0;
+ Overlay::ConfigWindow* g_configWindow = nullptr;
+ HWND g_messageWindow = nullptr;
+ bool g_isReady = false;
+
+ BOOL CALLBACK initChildWindow(HWND hwnd, LPARAM /*lParam*/)
+ {
+ Gdi::WinProc::onCreateWindow(hwnd);
+ return TRUE;
+ }
+
+ BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
+ {
+ DWORD windowPid = 0;
+ GetWindowThreadProcessId(hwnd, &windowPid);
+ if (GetCurrentProcessId() == windowPid)
+ {
+ Gdi::WinProc::onCreateWindow(hwnd);
+ EnumChildWindows(hwnd, &initChildWindow, 0);
+ if (8 == Win32::DisplayMode::getBpp())
+ {
+ PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast(GetDesktopWindow()), 0);
+ }
+ }
+ return TRUE;
+ }
+
+ LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
+
+ if (WM_USER_EXECUTE == uMsg)
+ {
+ auto& func = *reinterpret_cast*>(lParam);
+ func();
+ return LOG_RESULT(0);
+ }
+
+ return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam));
+ }
+
+ unsigned WINAPI messageWindowThreadProc(LPVOID /*lpParameter*/)
+ {
+ WNDCLASS wc = {};
+ wc.lpfnWndProc = &messageWindowProc;
+ wc.hInstance = Dll::g_currentModule;
+ wc.lpszClassName = "DDrawCompatMessageWindow";
+ CALL_ORIG_FUNC(RegisterClassA)(&wc);
+
+ g_messageWindow = CreateWindow(
+ "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
+ if (!g_messageWindow)
+ {
+ Compat::Log() << "ERROR: Failed to create a message-only window";
+ return 0;
+ }
+
+ Overlay::ConfigWindow configWindow;
+ g_configWindow = &configWindow;
+
+ {
+ D3dDdi::ScopedCriticalSection lock;
+ g_isReady = true;
+ EnumWindows(initTopLevelWindow, 0);
+ }
+
+ MSG msg = {};
+ while (GetMessage(&msg, nullptr, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ return 0;
+ }
+}
+
+namespace Gdi
+{
+ namespace GuiThread
+ {
+ HWND createWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
+ int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
+ {
+ // Workaround for ForceSimpleWindow shim
+ static auto createWindowExA = reinterpret_cast(
+ Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
+
+ HWND hwnd = nullptr;
+ execute([&]()
+ {
+ hwnd = createWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight,
+ hWndParent, hMenu, hInstance, lpParam);
+ });
+ return hwnd;
+ }
+
+ void destroyWindow(HWND hwnd)
+ {
+ execute([&]() { DestroyWindow(hwnd); });
+ }
+
+ void executeFunc(const std::function& func)
+ {
+ DWORD_PTR result = 0;
+ SendMessageTimeout(g_messageWindow, WM_USER_EXECUTE, 0, reinterpret_cast(&func),
+ SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result);
+ }
+
+ Overlay::ConfigWindow* getConfigWindow()
+ {
+ return g_configWindow;
+ }
+
+ bool isGuiThreadWindow(HWND hwnd)
+ {
+ return GetWindowThreadProcessId(hwnd, nullptr) == g_threadId;
+ }
+
+ bool isReady()
+ {
+ return g_isReady;
+ }
+
+ void setWindowRgn(HWND hwnd, Gdi::Region rgn)
+ {
+ execute([&]()
+ {
+ if (SetWindowRgn(hwnd, rgn, FALSE))
+ {
+ rgn.release();
+ }
+ });
+ }
+
+ void start()
+ {
+ Dll::createThread(messageWindowThreadProc, &g_threadId, THREAD_PRIORITY_TIME_CRITICAL, 0);
+ }
+ }
+}
diff --git a/DDrawCompat/Gdi/GuiThread.h b/DDrawCompat/Gdi/GuiThread.h
new file mode 100644
index 0000000..cd9c02a
--- /dev/null
+++ b/DDrawCompat/Gdi/GuiThread.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include
+
+#include
+
+#include
+
+namespace Overlay
+{
+ class ConfigWindow;
+}
+
+namespace Gdi
+{
+ namespace GuiThread
+ {
+ HWND createWindow(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle,
+ int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
+ void destroyWindow(HWND hwnd);
+ void setWindowRgn(HWND hwnd, Gdi::Region rgn);
+
+ Overlay::ConfigWindow* getConfigWindow();
+
+ template
+ void execute(const Func& func) { executeFunc(std::cref(func)); }
+ void executeFunc(const std::function& func);
+
+ bool isGuiThreadWindow(HWND hwnd);
+ bool isReady();
+
+ void start();
+ }
+}
diff --git a/DDrawCompat/Gdi/Palette.cpp b/DDrawCompat/Gdi/Palette.cpp
index 7d234ea..f5050ff 100644
--- a/DDrawCompat/Gdi/Palette.cpp
+++ b/DDrawCompat/Gdi/Palette.cpp
@@ -196,7 +196,7 @@ namespace
if (result && !bForceBackground)
{
HWND dcWindow = CALL_ORIG_FUNC(WindowFromDC)(hdc);
- if (dcWindow && !(GetWindowLong(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
+ if (dcWindow && !(CALL_ORIG_FUNC(GetWindowLongA)(dcWindow, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
{
HWND activeWindow = GetActiveWindow();
if (activeWindow == dcWindow || IsChild(activeWindow, dcWindow))
diff --git a/DDrawCompat/Gdi/PresentationWindow.cpp b/DDrawCompat/Gdi/PresentationWindow.cpp
index c7c1324..fbc7253 100644
--- a/DDrawCompat/Gdi/PresentationWindow.cpp
+++ b/DDrawCompat/Gdi/PresentationWindow.cpp
@@ -1,160 +1,17 @@
#include
#include
-#include
#include
+#include
#include
-#include
-#include
-#include
namespace
{
- const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
- const UINT WM_SETPRESENTATIONWINDOWPOS = WM_USER + 1;
- const UINT WM_SETPRESENTATIONWINDOWRGN = WM_USER + 2;
-
- HANDLE g_presentationWindowThread = nullptr;
- unsigned g_presentationWindowThreadId = 0;
- Overlay::ConfigWindow* g_configWindow = nullptr;
- HWND g_messageWindow = nullptr;
- bool g_isThreadReady = false;
-
- BOOL CALLBACK initChildWindow(HWND hwnd, LPARAM /*lParam*/)
- {
- Gdi::WinProc::onCreateWindow(hwnd);
- return TRUE;
- }
-
- BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
- {
- DWORD windowPid = 0;
- GetWindowThreadProcessId(hwnd, &windowPid);
- if (GetCurrentProcessId() == windowPid)
- {
- Gdi::WinProc::onCreateWindow(hwnd);
- EnumChildWindows(hwnd, &initChildWindow, 0);
- if (8 == Win32::DisplayMode::getBpp())
- {
- PostMessage(hwnd, WM_PALETTECHANGED, reinterpret_cast(GetDesktopWindow()), 0);
- }
- }
- return TRUE;
- }
-
- LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
- {
- LOG_FUNC("messageWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
-
- switch (uMsg)
- {
- case WM_CREATEPRESENTATIONWINDOW:
- {
- // Workaround for ForceSimpleWindow shim
- static auto origCreateWindowExA = reinterpret_cast(
- Compat::getProcAddress(GetModuleHandle("user32"), "CreateWindowExA"));
-
- HWND owner = reinterpret_cast(wParam);
- HWND presentationWindow = origCreateWindowExA(
- WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW,
- "DDrawCompatPresentationWindow",
- nullptr,
- WS_DISABLED | WS_POPUP,
- 0, 0, 1, 1,
- owner,
- nullptr,
- nullptr,
- nullptr);
-
- if (presentationWindow)
- {
- if (lParam)
- {
- CALL_ORIG_FUNC(SetWindowLongA)(presentationWindow, GWL_WNDPROC, lParam);
- }
- CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
- }
-
- return LOG_RESULT(reinterpret_cast(presentationWindow));
- }
-
- case WM_DESTROY:
- PostQuitMessage(0);
- return LOG_RESULT(0);
- }
-
- return LOG_RESULT(CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam));
- }
+ ATOM g_classAtom = 0;
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LOG_FUNC("presentationWindowProc", Compat::WindowMessageStruct(hwnd, uMsg, wParam, lParam));
-
- switch (uMsg)
- {
- case WM_SETPRESENTATIONWINDOWPOS:
- {
- const auto& wp = *reinterpret_cast(lParam);
- return SetWindowPos(hwnd, wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
- }
-
- case WM_SETPRESENTATIONWINDOWRGN:
- {
- HRGN rgn = nullptr;
- if (wParam)
- {
- rgn = CreateRectRgn(0, 0, 0, 0);
- CombineRgn(rgn, reinterpret_cast(wParam), nullptr, RGN_COPY);
- }
- return SetWindowRgn(hwnd, rgn, FALSE);
- }
- }
-
- return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
- }
-
- unsigned WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
- {
- WNDCLASS wc = {};
- wc.lpfnWndProc = &messageWindowProc;
- wc.hInstance = Dll::g_currentModule;
- wc.lpszClassName = "DDrawCompatMessageWindow";
- CALL_ORIG_FUNC(RegisterClassA)(&wc);
-
- g_messageWindow = CreateWindow(
- "DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
- if (!g_messageWindow)
- {
- Compat::Log() << "ERROR: Failed to create a message-only window";
- return 0;
- }
-
- {
- D3dDdi::ScopedCriticalSection lock;
- Gdi::WinProc::installHooks();
- g_isThreadReady = true;
- EnumWindows(initTopLevelWindow, 0);
- }
-
- Compat::closeDbgEng();
-
- Overlay::ConfigWindow configWindow;
- g_configWindow = &configWindow;
-
- MSG msg = {};
- while (GetMessage(&msg, nullptr, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- return 0;
- }
-
- LRESULT sendMessageBlocking(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
- {
- DWORD_PTR result = 0;
- SendMessageTimeout(hwnd, msg, wParam, lParam, SMTO_BLOCK | SMTO_NOTIMEOUTIFNOTHUNG, 0, &result);
- return result;
+ return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
}
}
@@ -162,20 +19,28 @@ namespace Gdi
{
namespace PresentationWindow
{
- HWND create(HWND owner, WNDPROC wndProc)
+ HWND create(HWND owner)
{
- return reinterpret_cast(sendMessageBlocking(g_messageWindow, WM_CREATEPRESENTATIONWINDOW,
- reinterpret_cast(owner), reinterpret_cast(wndProc)));
- }
+ HWND presentationWindow = nullptr;
+ GuiThread::execute([&]()
+ {
+ presentationWindow = GuiThread::createWindow(
+ WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOPARENTNOTIFY | WS_EX_TOOLWINDOW,
+ reinterpret_cast(g_classAtom),
+ nullptr,
+ WS_DISABLED | WS_POPUP,
+ 0, 0, 1, 1,
+ owner,
+ nullptr,
+ nullptr,
+ nullptr);
- void destroy(HWND hwnd)
- {
- PostMessage(hwnd, WM_CLOSE, 0, 0);
- }
-
- Overlay::ConfigWindow* getConfigWindow()
- {
- return g_configWindow;
+ if (presentationWindow)
+ {
+ CALL_ORIG_FUNC(SetLayeredWindowAttributes)(presentationWindow, 0, 255, LWA_ALPHA);
+ }
+ });
+ return presentationWindow;
}
void installHooks()
@@ -184,35 +49,7 @@ namespace Gdi
wc.lpfnWndProc = &presentationWindowProc;
wc.hInstance = Dll::g_currentModule;
wc.lpszClassName = "DDrawCompatPresentationWindow";
- CALL_ORIG_FUNC(RegisterClassA)(&wc);
-
- g_presentationWindowThread = Dll::createThread(presentationWindowThreadProc, &g_presentationWindowThreadId,
- THREAD_PRIORITY_TIME_CRITICAL, CREATE_SUSPENDED);
- }
-
- bool isPresentationWindow(HWND hwnd)
- {
- return GetWindowThreadProcessId(hwnd, nullptr) == g_presentationWindowThreadId;
- }
-
- bool isThreadReady()
- {
- return g_isThreadReady;
- }
-
- void setWindowPos(HWND hwnd, const WINDOWPOS& wp)
- {
- sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWPOS, 0, reinterpret_cast(&wp));
- }
-
- void setWindowRgn(HWND hwnd, HRGN rgn)
- {
- sendMessageBlocking(hwnd, WM_SETPRESENTATIONWINDOWRGN, reinterpret_cast(rgn), 0);
- }
-
- void startThread()
- {
- ResumeThread(g_presentationWindowThread);
+ g_classAtom = CALL_ORIG_FUNC(RegisterClassA)(&wc);
}
}
}
diff --git a/DDrawCompat/Gdi/PresentationWindow.h b/DDrawCompat/Gdi/PresentationWindow.h
index 31223e1..4f5f519 100644
--- a/DDrawCompat/Gdi/PresentationWindow.h
+++ b/DDrawCompat/Gdi/PresentationWindow.h
@@ -2,23 +2,11 @@
#include
-namespace Overlay
-{
- class ConfigWindow;
-}
-
namespace Gdi
{
namespace PresentationWindow
{
- HWND create(HWND owner, WNDPROC wndProc = nullptr);
- void destroy(HWND hwnd);
- Overlay::ConfigWindow* getConfigWindow();
- bool isPresentationWindow(HWND hwnd);
- bool isThreadReady();
- void setWindowPos(HWND hwnd, const WINDOWPOS& wp);
- void setWindowRgn(HWND hwnd, HRGN rgn);
- void startThread();
+ HWND create(HWND owner);
void installHooks();
}
diff --git a/DDrawCompat/Gdi/User32WndProcs.cpp b/DDrawCompat/Gdi/User32WndProcs.cpp
index b771a5b..a5dd531 100644
--- a/DDrawCompat/Gdi/User32WndProcs.cpp
+++ b/DDrawCompat/Gdi/User32WndProcs.cpp
@@ -3,7 +3,7 @@
#include
#include
#include
-#include
+#include
#include
#include
#include
@@ -319,7 +319,7 @@ namespace
if (wp.x + wp.cx > mr.right)
{
HWND parent = GetNextWindow(wp.hwnd, GW_HWNDNEXT);
- while (Gdi::PresentationWindow::isPresentationWindow(parent))
+ while (Gdi::GuiThread::isGuiThreadWindow(parent))
{
parent = GetNextWindow(parent, GW_HWNDNEXT);
}
diff --git a/DDrawCompat/Gdi/WinProc.cpp b/DDrawCompat/Gdi/WinProc.cpp
index 95efb3c..0d2d121 100644
--- a/DDrawCompat/Gdi/WinProc.cpp
+++ b/DDrawCompat/Gdi/WinProc.cpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -39,7 +40,6 @@ namespace
WindowProc getWindowProc(HWND hwnd);
bool isTopLevelWindow(HWND hwnd);
bool isUser32ScrollBar(HWND hwnd);
- void onCreateWindow(HWND hwnd);
void onDestroyWindow(HWND hwnd);
void onGetMinMaxInfo(MINMAXINFO& mmi);
void onInitMenuPopup(HMENU menu);
@@ -95,12 +95,15 @@ namespace
case WM_ACTIVATEAPP:
if (!wParam)
{
- auto configWindow = Gdi::PresentationWindow::getConfigWindow();
- if (configWindow)
- {
- configWindow->setVisible(false);
- }
- CALL_ORIG_FUNC(ClipCursor)(nullptr);
+ Gdi::GuiThread::execute([&]()
+ {
+ auto configWindow = Gdi::GuiThread::getConfigWindow();
+ if (configWindow)
+ {
+ configWindow->setVisible(false);
+ }
+ CALL_ORIG_FUNC(ClipCursor)(nullptr);
+ });
}
break;
@@ -202,40 +205,6 @@ namespace
IsWindowUnicode(hwnd) ? it->second.wndProcW : it->second.wndProcA);
}
- void onCreateWindow(HWND hwnd)
- {
- LOG_FUNC("onCreateWindow", hwnd);
-
- {
- Compat::ScopedSrwLockExclusive lock(g_windowProcSrwLock);
- if (g_windowProc.find(hwnd) != g_windowProc.end())
- {
- return;
- }
-
- auto wndProcA = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC));
- auto wndProcW = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongW)(hwnd, GWL_WNDPROC));
- g_windowProc[hwnd] = { wndProcA, wndProcW };
- setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW);
- }
-
- if (!isTopLevelWindow(hwnd))
- {
- return;
- }
-
- char className[64] = {};
- GetClassName(hwnd, className, sizeof(className));
- if (std::string(className) == "CompatWindowDesktopReplacement")
- {
- // Disable VirtualizeDesktopPainting shim
- SendNotifyMessage(hwnd, WM_CLOSE, 0, 0);
- return;
- }
-
- Gdi::Window::updateAll();
- }
-
void onDestroyWindow(HWND hwnd)
{
if (isTopLevelWindow(hwnd))
@@ -415,9 +384,9 @@ namespace
switch (event)
{
case EVENT_OBJECT_CREATE:
- if (OBJID_WINDOW == idObject && !Gdi::PresentationWindow::isPresentationWindow(hwnd))
+ if (OBJID_WINDOW == idObject)
{
- onCreateWindow(hwnd);
+ Gdi::WinProc::onCreateWindow(hwnd);
}
break;
@@ -511,10 +480,40 @@ namespace Gdi
void onCreateWindow(HWND hwnd)
{
- if (PresentationWindow::isThreadReady())
+ LOG_FUNC("onCreateWindow", hwnd);
+ if (!GuiThread::isReady() || GuiThread::isGuiThreadWindow(hwnd))
{
- ::onCreateWindow(hwnd);
+ return;
}
+
+ {
+ Compat::ScopedSrwLockExclusive lock(g_windowProcSrwLock);
+ if (g_windowProc.find(hwnd) != g_windowProc.end())
+ {
+ return;
+ }
+
+ auto wndProcA = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC));
+ auto wndProcW = reinterpret_cast(CALL_ORIG_FUNC(GetWindowLongW)(hwnd, GWL_WNDPROC));
+ g_windowProc[hwnd] = { wndProcA, wndProcW };
+ setWindowProc(hwnd, ddcWindowProcA, ddcWindowProcW);
+ }
+
+ if (!isTopLevelWindow(hwnd))
+ {
+ return;
+ }
+
+ char className[64] = {};
+ GetClassName(hwnd, className, sizeof(className));
+ if (std::string(className) == "CompatWindowDesktopReplacement")
+ {
+ // Disable VirtualizeDesktopPainting shim
+ SendNotifyMessage(hwnd, WM_CLOSE, 0, 0);
+ return;
+ }
+
+ Gdi::Window::updateAll();
}
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
diff --git a/DDrawCompat/Gdi/Window.cpp b/DDrawCompat/Gdi/Window.cpp
index 656b7c1..13f0636 100644
--- a/DDrawCompat/Gdi/Window.cpp
+++ b/DDrawCompat/Gdi/Window.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -249,7 +250,7 @@ namespace
DWORD processId = 0;
GetWindowThreadProcessId(hwnd, &processId);
if (processId != context.processId ||
- Gdi::PresentationWindow::isPresentationWindow(hwnd))
+ Gdi::GuiThread::isGuiThreadWindow(hwnd))
{
return TRUE;
}
@@ -277,7 +278,7 @@ namespace
}
else if (it->second.presentationWindow)
{
- Gdi::PresentationWindow::destroy(it->second.presentationWindow);
+ Gdi::GuiThread::destroyWindow(it->second.presentationWindow);
it->second.presentationWindow = nullptr;
}
}
@@ -351,7 +352,7 @@ namespace
{
if (setPresentationWindowRgn)
{
- Gdi::PresentationWindow::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
+ Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
}
WINDOWPOS wp = {};
@@ -379,7 +380,11 @@ namespace
wp.flags |= SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
}
- Gdi::PresentationWindow::setWindowPos(it->second.presentationWindow, wp);
+ Gdi::GuiThread::execute([&]()
+ {
+ CALL_ORIG_FUNC(SetWindowPos)(it->second.presentationWindow,
+ wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+ });
}
}
return TRUE;
@@ -524,7 +529,7 @@ namespace Gdi
}
RECT wr = {};
- auto configWindow = PresentationWindow::getConfigWindow();
+ auto configWindow = GuiThread::getConfigWindow();
if (configWindow && configWindow->isVisible())
{
GetWindowRect(configWindow->getWindow(), &wr);
@@ -550,7 +555,7 @@ namespace Gdi
void updateAll()
{
LOG_FUNC("Window::updateAll");
- if (!Gdi::PresentationWindow::isThreadReady())
+ if (!GuiThread::isReady())
{
return;
}
@@ -571,7 +576,7 @@ namespace Gdi
{
if (it->second.presentationWindow)
{
- Gdi::PresentationWindow::destroy(it->second.presentationWindow);
+ GuiThread::destroyWindow(it->second.presentationWindow);
}
it = g_windows.erase(it);
}
diff --git a/DDrawCompat/Input/Input.cpp b/DDrawCompat/Input/Input.cpp
index 19c0880..9622fcd 100644
--- a/DDrawCompat/Input/Input.cpp
+++ b/DDrawCompat/Input/Input.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -21,9 +22,6 @@ namespace
void* context;
};
- const UINT WM_USER_HOTKEY = WM_USER;
- const UINT WM_USER_RESET_HOOK = WM_USER + 1;
-
HANDLE g_bmpArrow = nullptr;
SIZE g_bmpArrowSize = {};
Overlay::Window* g_capture = nullptr;
@@ -31,7 +29,6 @@ namespace
HWND g_cursorWindow = nullptr;
std::map g_hotKeys;
RECT g_monitorRect = {};
- DWORD g_inputThreadId = 0;
HHOOK g_keyboardHook = nullptr;
HHOOK g_mouseHook = nullptr;
@@ -65,72 +62,22 @@ namespace
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
}
- unsigned WINAPI inputThreadProc(LPVOID /*lpParameter*/)
- {
- g_inputThreadId = GetCurrentThreadId();
- g_bmpArrow = CALL_ORIG_FUNC(LoadImageA)(Dll::g_currentModule, "BMP_ARROW", IMAGE_BITMAP, 0, 0, 0);
-
- BITMAP bm = {};
- GetObject(g_bmpArrow, sizeof(bm), &bm);
- g_bmpArrowSize = { bm.bmWidth, bm.bmHeight };
-
- g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
-
- MSG msg = {};
- while (GetMessage(&msg, nullptr, 0, 0))
- {
- if (msg.message == WM_TIMER && !msg.hwnd && msg.lParam)
- {
- reinterpret_cast(msg.lParam)(nullptr, WM_TIMER, msg.wParam, 0);
- }
- if (!msg.hwnd)
- {
- if (WM_USER_HOTKEY == msg.message)
- {
- DWORD pid = 0;
- GetWindowThreadProcessId(GetForegroundWindow(), &pid);
- if (GetCurrentProcessId() == pid)
- {
- auto it = std::find_if(g_hotKeys.begin(), g_hotKeys.end(),
- [&](const auto& v) { return v.first.vk == msg.wParam; });
- if (it != g_hotKeys.end())
- {
- it->second.action(it->second.context);
- }
- }
- }
- else if (WM_USER_RESET_HOOK == msg.message)
- {
- if (msg.wParam == WH_KEYBOARD_LL)
- {
- UnhookWindowsHookEx(g_keyboardHook);
- g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
- WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
- }
- else if (msg.wParam == WH_MOUSE_LL && g_mouseHook)
- {
- UnhookWindowsHookEx(g_mouseHook);
- g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
- WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
- }
- }
- }
- else
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
- return 0;
- }
-
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
if (HC_ACTION == nCode && (WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam))
{
- auto llHook = reinterpret_cast(lParam);
- PostThreadMessage(GetCurrentThreadId(), WM_USER_HOTKEY, llHook->vkCode, llHook->scanCode);
+ DWORD pid = 0;
+ GetWindowThreadProcessId(GetForegroundWindow(), &pid);
+ if (GetCurrentProcessId() == pid)
+ {
+ auto llHook = reinterpret_cast(lParam);
+ auto it = std::find_if(g_hotKeys.begin(), g_hotKeys.end(),
+ [&](const auto& v) { return v.first.vk == llHook->vkCode; });
+ if (it != g_hotKeys.end())
+ {
+ it->second.action(it->second.context);
+ }
+ }
}
return CallNextHookEx(nullptr, nCode, wParam, lParam);
}
@@ -174,6 +121,32 @@ namespace
return CallNextHookEx(nullptr, nCode, wParam, lParam);
}
+ void resetKeyboardHook()
+ {
+ Gdi::GuiThread::execute([]()
+ {
+ if (g_keyboardHook)
+ {
+ UnhookWindowsHookEx(g_keyboardHook);
+ }
+ g_keyboardHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
+ WH_KEYBOARD_LL, &lowLevelKeyboardProc, Dll::g_currentModule, 0);
+ });
+ }
+
+ void resetMouseHook()
+ {
+ Gdi::GuiThread::execute([]()
+ {
+ if (g_mouseHook)
+ {
+ UnhookWindowsHookEx(g_mouseHook);
+ }
+ g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
+ WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
+ });
+ }
+
void setCursorPos(POINT cp)
{
g_cursorPos = cp;
@@ -191,9 +164,16 @@ namespace
}
HHOOK result = origSetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);
- if (result && g_inputThreadId && (WH_KEYBOARD_LL == idHook || WH_MOUSE_LL == idHook))
+ if (result)
{
- PostThreadMessage(g_inputThreadId, WM_USER_RESET_HOOK, idHook, 0);
+ if (WH_KEYBOARD_LL == idHook)
+ {
+ resetKeyboardHook();
+ }
+ else if (WH_MOUSE_LL == idHook && g_mouseHook)
+ {
+ resetMouseHook();
+ }
}
return result;
}
@@ -235,16 +215,22 @@ namespace Input
void installHooks()
{
+ g_bmpArrow = CALL_ORIG_FUNC(LoadImageA)(Dll::g_currentModule, "BMP_ARROW", IMAGE_BITMAP, 0, 0, 0);
+
+ BITMAP bm = {};
+ GetObject(g_bmpArrow, sizeof(bm), &bm);
+ g_bmpArrowSize = { bm.bmWidth, bm.bmHeight };
+
HOOK_FUNCTION(user32, SetWindowsHookExA, setWindowsHookExA);
HOOK_FUNCTION(user32, SetWindowsHookExW, setWindowsHookExW);
}
void registerHotKey(const HotKey& hotKey, std::function action, void* context)
{
- static HANDLE thread = Dll::createThread(&inputThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
- if (thread)
+ g_hotKeys[hotKey] = { action, context };
+ if (!g_keyboardHook)
{
- g_hotKeys[hotKey] = { action, context };
+ resetKeyboardHook();
}
}
@@ -255,7 +241,8 @@ namespace Input
{
if (!g_mouseHook)
{
- g_cursorWindow = Gdi::PresentationWindow::create(window->getWindow(), &cursorWindowProc);
+ g_cursorWindow = Gdi::PresentationWindow::create(window->getWindow());
+ CALL_ORIG_FUNC(SetWindowLongA)(g_cursorWindow, GWL_WNDPROC, reinterpret_cast(&cursorWindowProc));
CALL_ORIG_FUNC(SetLayeredWindowAttributes)(g_cursorWindow, RGB(0xFF, 0xFF, 0xFF), 0, LWA_COLORKEY);
MONITORINFO mi = {};
@@ -266,17 +253,16 @@ namespace Input
RECT r = window->getRect();
g_cursorPos = { (r.left + r.right) / 2, (r.top + r.bottom) / 2 };
CALL_ORIG_FUNC(SetWindowPos)(g_cursorWindow, HWND_TOPMOST, g_cursorPos.x, g_cursorPos.y,
- g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING);
- ShowWindow(g_cursorWindow, SW_SHOW);
+ g_bmpArrowSize.cx, g_bmpArrowSize.cy, SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
- g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
+ resetMouseHook();
}
}
else if (g_mouseHook)
{
UnhookWindowsHookEx(g_mouseHook);
g_mouseHook = nullptr;
- PostMessage(g_cursorWindow, WM_CLOSE, 0, 0);
+ Gdi::GuiThread::destroyWindow(g_cursorWindow);
g_cursorWindow = nullptr;
}
}
diff --git a/DDrawCompat/Overlay/Window.cpp b/DDrawCompat/Overlay/Window.cpp
index e0d9753..c79f74f 100644
--- a/DDrawCompat/Overlay/Window.cpp
+++ b/DDrawCompat/Overlay/Window.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -46,12 +47,14 @@ namespace Overlay
{
Window::Window(Window* parentWindow, const RECT& rect, const Input::HotKey& hotKey)
: Control(nullptr, rect, WS_BORDER)
- , m_hwnd(Gdi::PresentationWindow::create(parentWindow ? parentWindow->m_hwnd : nullptr, &staticWindowProc))
+ , m_hwnd(Gdi::PresentationWindow::create(parentWindow ? parentWindow->m_hwnd : nullptr))
, m_parentWindow(parentWindow)
, m_transparency(25)
{
g_windows.emplace(m_hwnd, *this);
+ CALL_ORIG_FUNC(SetWindowLongA)(m_hwnd, GWL_WNDPROC, reinterpret_cast(&staticWindowProc));
setTransparency(m_transparency);
+
if (0 != hotKey.vk)
{
Input::registerHotKey(hotKey, &toggleWindow, this);
@@ -60,7 +63,7 @@ namespace Overlay
Window::~Window()
{
- Gdi::PresentationWindow::destroy(m_hwnd);
+ Gdi::GuiThread::destroyWindow(m_hwnd);
g_windows.erase(m_hwnd);
}
@@ -122,7 +125,7 @@ namespace Overlay
else
{
auto capture = Input::getCapture();
- if (capture != this && capture->m_parentWindow == this)
+ if (capture && capture != this && capture->m_parentWindow == this)
{
capture->setVisible(false);
}
@@ -133,7 +136,12 @@ namespace Overlay
LRESULT CALLBACK Window::staticWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
- return g_windows.find(hwnd)->second.windowProc(uMsg, wParam, lParam);
+ auto it = g_windows.find(hwnd);
+ if (it != g_windows.end())
+ {
+ return it->second.windowProc(uMsg, wParam, lParam);
+ }
+ return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
}
void Window::updatePos()
diff --git a/DDrawCompat/Win32/DisplayMode.cpp b/DDrawCompat/Win32/DisplayMode.cpp
index dec79d8..19dcd51 100644
--- a/DDrawCompat/Win32/DisplayMode.cpp
+++ b/DDrawCompat/Win32/DisplayMode.cpp
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
@@ -672,7 +673,7 @@ namespace
{
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
- if (GetCurrentProcessId() == pid)
+ if (GetCurrentProcessId() == pid && !Gdi::GuiThread::isGuiThreadWindow(hwnd))
{
SendNotifyMessage(hwnd, WM_DISPLAYCHANGE, 0, lParam);
}