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();
PaintHandlers::installHooks();
ScrollFunctions::installHooks();
Window::installHooks();
WinProc::installHooks();
Caret::installHooks();
}
@ -93,6 +94,7 @@ namespace Gdi
{
Caret::uninstallHooks();
WinProc::uninstallHooks();
Window::uninstallHooks();
Dc::dllProcessDetach();
DcCache::dllProcessDetach();
ReleaseDC(nullptr, g_screenDc);

View File

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

View File

@ -1,4 +1,5 @@
#include "Common/Hook.h"
#include "Common/Log.h"
#include "DDraw/ScopedThreadLock.h"
#include "Gdi/Gdi.h"
#include "Gdi/Window.h"
@ -7,8 +8,12 @@ extern "C" IMAGE_DOS_HEADER __ImageBase;
namespace
{
ATOM registerPresentationWindowClass();
const UINT WM_CREATEPRESENTATIONWINDOW = WM_USER;
HANDLE g_presentationWindowThread = nullptr;
DWORD g_presentationWindowThreadId = 0;
HWND g_messageWindow = nullptr;
ATOM getComboLBoxAtom()
{
WNDCLASS wc = {};
@ -16,24 +21,65 @@ namespace
return comboLBoxAtom;
}
ATOM getPresentationWindowClassAtom()
LRESULT CALLBACK messageWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static ATOM atom = registerPresentationWindowClass();
return atom;
LOG_FUNC("messageWindowProc", hwnd, Compat::hex(uMsg), Compat::hex(wParam), Compat::hex(lParam));
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)
{
LOG_FUNC("presentationWindowProc", hwnd, Compat::hex(uMsg), Compat::hex(wParam), Compat::hex(lParam));
return CALL_ORIG_FUNC(DefWindowProc)(hwnd, uMsg, wParam, lParam);
}
ATOM registerPresentationWindowClass()
DWORD WINAPI presentationWindowThreadProc(LPVOID /*lpParameter*/)
{
WNDCLASS wc = {};
wc.lpfnWndProc = &presentationWindowProc;
wc.lpfnWndProc = &messageWindowProc;
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
wc.lpszClassName = "DDrawCompatPresentationWindow";
return RegisterClass(&wc);
wc.lpszClassName = "DDrawCompatMessageWindow";
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));
if (MENU_ATOM != atom && getComboLBoxAtom() != atom)
{
m_presentationWindow = CreateWindowEx(
WS_EX_LAYERED | WS_EX_TRANSPARENT,
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);
m_presentationWindow = reinterpret_cast<HWND>(SendMessage(
g_messageWindow, WM_CREATEPRESENTATIONWINDOW, reinterpret_cast<WPARAM>(hwnd), 0));
}
update();
@ -137,9 +174,33 @@ namespace Gdi
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)
{
return IsWindow(hwnd) && GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom();
return IsWindow(hwnd) && g_presentationWindowThreadId == GetWindowThreadProcessId(hwnd, nullptr);
}
bool Window::isTopLevelNonLayeredWindow(HWND hwnd)
@ -155,6 +216,19 @@ namespace Gdi
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()
{
DDraw::ScopedThreadLock lock;

View File

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