1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Moved presentation windows to dedicated thread

This commit is contained in:
narzoul 2018-11-25 11:46:43 +01:00
parent 906ef5ebe2
commit 12e78aab84
4 changed files with 101 additions and 29 deletions

View File

@ -51,6 +51,7 @@ namespace Gdi
DcFunctions::installHooks(); DcFunctions::installHooks();
PaintHandlers::installHooks(); PaintHandlers::installHooks();
ScrollFunctions::installHooks(); ScrollFunctions::installHooks();
Window::installHooks();
WinProc::installHooks(); WinProc::installHooks();
Caret::installHooks(); Caret::installHooks();
} }
@ -93,6 +94,7 @@ namespace Gdi
{ {
Caret::uninstallHooks(); Caret::uninstallHooks();
WinProc::uninstallHooks(); WinProc::uninstallHooks();
Window::uninstallHooks();
Dc::dllProcessDetach(); Dc::dllProcessDetach();
DcCache::dllProcessDetach(); DcCache::dllProcessDetach();
ReleaseDC(nullptr, g_screenDc); ReleaseDC(nullptr, g_screenDc);

View File

@ -91,16 +91,9 @@ namespace
{ {
DWORD windowPid = 0; DWORD windowPid = 0;
GetWindowThreadProcessId(hwnd, &windowPid); GetWindowThreadProcessId(hwnd, &windowPid);
if (GetCurrentProcessId() != windowPid) if (GetCurrentProcessId() == windowPid)
{ {
return TRUE; onCreateWindow(hwnd);
}
onCreateWindow(hwnd);
if (!(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED))
{
RedrawWindow(hwnd, nullptr, nullptr,
RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN | RDW_UPDATENOW);
} }
return TRUE; return TRUE;
} }

View File

@ -1,4 +1,5 @@
#include "Common/Hook.h" #include "Common/Hook.h"
#include "Common/Log.h"
#include "DDraw/ScopedThreadLock.h" #include "DDraw/ScopedThreadLock.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Window.h" #include "Gdi/Window.h"
@ -7,8 +8,12 @@ extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace namespace
{ {
ATOM registerPresentationWindowClass(); const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
HANDLE g_presentationWindowThread = nullptr;
DWORD g_presentationWindowThreadId = 0;
HWND g_messageWindow = nullptr;
ATOM getComboLBoxAtom() ATOM getComboLBoxAtom()
{ {
WNDCLASS wc = {}; WNDCLASS wc = {};
@ -16,24 +21,65 @@ namespace
return comboLBoxAtom; return comboLBoxAtom;
} }
ATOM getPresentationWindowClassAtom() LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
static ATOM atom = registerPresentationWindowClass(); LOG_FUNC("messageWindowProc", hwnd, Compat::hex(uMsg), Compat::hex(wParam), Compat::hex(lParam));
return atom; switch (uMsg)
{
case WM_CREATEPRESENTATIONWINDOW:
{
HWND presentationWindow = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TRANSPARENT,
"DDrawCompatPresentationWindow",
nullptr,
WS_DISABLED | WS_POPUP,
0, 0, 1, 1,
reinterpret_cast<HWND>(wParam),
nullptr,
nullptr,
nullptr);
SetLayeredWindowAttributes(presentationWindow, 0, 255, LWA_ALPHA);
return reinterpret_cast<LRESULT>(presentationWindow);
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
}
} }
LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK presentationWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{ {
LOG_FUNC("presentationWindowProc", hwnd, Compat::hex(uMsg), Compat::hex(wParam), Compat::hex(lParam));
return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam); return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
} }
ATOM registerPresentationWindowClass() DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
{ {
WNDCLASS wc = {}; WNDCLASS wc = {};
wc.lpfnWndProc = &presentationWindowProc; wc.lpfnWndProc = &messageWindowProc;
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase); wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
wc.lpszClassName = "DDrawCompatPresentationWindow"; wc.lpszClassName = "DDrawCompatMessageWindow";
return RegisterClass(&wc); RegisterClass(&wc);
g_messageWindow = CreateWindow(
"DDrawCompatMessageWindow", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, nullptr, nullptr);
if (!g_messageWindow)
{
return 0;
}
MSG msg = {};
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
} }
} }
@ -48,17 +94,8 @@ namespace Gdi
const ATOM atom = static_cast<ATOM>(GetClassLong(hwnd, GCW_ATOM)); const ATOM atom = static_cast<ATOM>(GetClassLong(hwnd, GCW_ATOM));
if (MENU_ATOM != atom && getComboLBoxAtom() != atom) if (MENU_ATOM != atom && getComboLBoxAtom() != atom)
{ {
m_presentationWindow = CreateWindowEx( m_presentationWindow = reinterpret_cast<HWND>(SendMessage(
WS_EX_LAYERED | WS_EX_TRANSPARENT, g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast<WPARAM>(hwnd), 0));
reinterpret_cast<const char*>(getPresentationWindowClassAtom()),
nullptr,
WS_DISABLED | WS_POPUP,
0, 0, 1, 1,
m_hwnd,
nullptr,
nullptr,
nullptr);
SetLayeredWindowAttributes(m_presentationWindow, 0, 255, LWA_ALPHA);
} }
update(); update();
@ -137,9 +174,33 @@ namespace Gdi
return s_windows; return s_windows;
} }
void Window::installHooks()
{
WNDCLASS wc = {};
wc.lpfnWndProc = &presentationWindowProc;
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
wc.lpszClassName = "DDrawCompatPresentationWindow";
RegisterClass(&wc);
g_presentationWindowThread = CreateThread(
nullptr, 0, &presentationWindowThreadProc, nullptr, 0, &g_presentationWindowThreadId);
int i = 0;
while (!g_messageWindow && i < 1000)
{
Sleep(1);
++i;
}
if (!g_messageWindow)
{
Compat::Log() << "Failed to create a message-only window";
}
}
bool Window::isPresentationWindow(HWND hwnd) bool Window::isPresentationWindow(HWND hwnd)
{ {
return IsWindow(hwnd) && GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom(); return IsWindow(hwnd) && g_presentationWindowThreadId == GetWindowThreadProcessId(hwnd, nullptr);
} }
bool Window::isTopLevelNonLayeredWindow(HWND hwnd) bool Window::isTopLevelNonLayeredWindow(HWND hwnd)
@ -155,6 +216,19 @@ namespace Gdi
s_windows.erase(hwnd); s_windows.erase(hwnd);
} }
void Window::uninstallHooks()
{
if (g_presentationWindowThread)
{
SendMessage(g_messageWindow, WM_CLOSE, 0, 0);
if (WAIT_OBJECT_0 != WaitForSingleObject(g_presentationWindowThread, 1000))
{
TerminateThread(g_presentationWindowThread, 0);
Compat::Log() << "The presentation window thread was terminated forcefully";
}
}
}
void Window::update() void Window::update()
{ {
DDraw::ScopedThreadLock lock; DDraw::ScopedThreadLock lock;

View File

@ -32,6 +32,9 @@ namespace Gdi
static bool isTopLevelNonLayeredWindow(HWND hwnd); static bool isTopLevelNonLayeredWindow(HWND hwnd);
static void updateAll(); static void updateAll();
static void installHooks();
static void uninstallHooks();
private: private:
void calcInvalidatedRegion(const RECT& oldWindowRect, const Region& oldVisibleRegion); void calcInvalidatedRegion(const RECT& oldWindowRect, const Region& oldVisibleRegion);
void update(); void update();