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

Disabled themes, fixed nonclient area rendering and caret deadlock

Disabled visual styles and added WM_NCPAINT handling (as a simple BitBlt copy
from the original DC) to reduce glitches in rendering of common controls and
windows, such as the GetSaveFileName dialog window in StarCraft.

Fixed a deadlock in the caret emulation code caused by locking the GDI
critical section prior to calling beginGdiRendering, which is locking both the
DirectDraw and GDI critical sections. Another thread that only calls
beginGdiRendering without entering the GDI critical section first could thus
run into a deadlock as both threads were waiting on each other's critical
sections.
Now the global caret data has it its own critical section instead of sharing
the GDI critical section.
This commit is contained in:
narzoul 2016-01-17 15:31:08 +01:00
parent 2a23cf5636
commit acbc183d00
5 changed files with 69 additions and 9 deletions

View File

@ -22,6 +22,21 @@ namespace
};
CaretData g_caret = {};
CRITICAL_SECTION g_caretCriticalSection;
class CaretScopedThreadLock
{
public:
CaretScopedThreadLock()
{
EnterCriticalSection(&g_caretCriticalSection);
}
~CaretScopedThreadLock()
{
LeaveCriticalSection(&g_caretCriticalSection);
}
};
void drawCaret()
{
@ -55,7 +70,7 @@ namespace
DWORD /*dwEventThread*/,
DWORD /*dwmsEventTime*/)
{
CompatGdi::GdiScopedThreadLock gdiLock;
CaretScopedThreadLock caretLock;
if (OBJID_CARET != idObject || !g_caret.isDrawn || g_caret.hwnd != hwnd)
{
return;
@ -80,7 +95,7 @@ namespace
BOOL result = CALL_ORIG_GDI(CreateCaret)(hWnd, hBitmap, nWidth, nHeight);
if (result)
{
CompatGdi::GdiScopedThreadLock gdiLock;
CaretScopedThreadLock caretLock;
if (g_caret.isDrawn)
{
drawCaret();
@ -99,7 +114,7 @@ namespace
return FALSE;
}
CompatGdi::GdiScopedThreadLock gdiLock;
CaretScopedThreadLock caretLock;
if (!g_caret.isDrawn)
{
IAccessible* accessible = nullptr;
@ -129,7 +144,7 @@ namespace
BOOL result = CALL_ORIG_GDI(HideCaret)(hWnd);
if (result)
{
CompatGdi::GdiScopedThreadLock gdiLock;
CaretScopedThreadLock caretLock;
if (g_caret.isDrawn)
{
drawCaret();
@ -147,6 +162,8 @@ namespace CompatGdiCaret
{
void installHooks()
{
InitializeCriticalSection(&g_caretCriticalSection);
DetourTransactionBegin();
HOOK_GDI_FUNCTION(user32, CreateCaret, createCaret);
HOOK_GDI_FUNCTION(user32, ShowCaret, showCaret);

View File

@ -99,10 +99,8 @@ namespace
if (hwnd)
{
ExcludeClipRectsData excludeClipRectsData = { compatDc, origin, GetAncestor(hwnd, GA_ROOT) };
EnumThreadWindows(GetCurrentThreadId(), &excludeClipRectsForOverlappingWindows,
EnumWindows(&excludeClipRectsForOverlappingWindows,
reinterpret_cast<LPARAM>(&excludeClipRectsData));
RECT windowRect = {};
GetWindowRect(hwnd, &windowRect);
}
}
}

View File

@ -10,6 +10,7 @@
namespace
{
void eraseBackground(HWND hwnd, HDC dc);
void ncPaint(HWND wnd);
LRESULT CALLBACK callWndRetProc(int nCode, WPARAM wParam, LPARAM lParam)
{
@ -23,6 +24,13 @@ namespace
eraseBackground(ret->hwnd, reinterpret_cast<HDC>(ret->wParam));
}
}
else if (WM_NCPAINT == ret->message)
{
if (0 == ret->lResult)
{
ncPaint(ret->hwnd);
}
}
else if (WM_WINDOWPOSCHANGED == ret->message)
{
CompatGdi::invalidate();
@ -49,6 +57,37 @@ namespace
CompatGdi::endGdiRendering();
}
}
void ncPaint(HWND hwnd)
{
if (!CompatGdi::beginGdiRendering())
{
return;
}
HDC windowDc = GetWindowDC(hwnd);
HDC compatDc = CompatGdiDc::getDc(windowDc);
if (compatDc)
{
RECT windowRect = {};
GetWindowRect(hwnd, &windowRect);
RECT clientRect = {};
GetClientRect(hwnd, &clientRect);
POINT clientOrigin = {};
ClientToScreen(hwnd, &clientOrigin);
OffsetRect(&clientRect, clientOrigin.x - windowRect.left, clientOrigin.y - windowRect.top);
ExcludeClipRect(compatDc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom);
CALL_ORIG_GDI(BitBlt)(compatDc, 0, 0,
windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, windowDc, 0, 0, SRCCOPY);
CompatGdiDc::releaseDc(windowDc);
}
ReleaseDC(hwnd, windowDc);
CompatGdi::endGdiRendering();
}
}
namespace CompatGdiWinProc

View File

@ -94,7 +94,7 @@
</ClCompile>
<Link>
<ModuleDefinitionFile>DDrawCompat.def</ModuleDefinitionFile>
<AdditionalDependencies>dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -121,7 +121,7 @@
</ClCompile>
<Link>
<ModuleDefinitionFile>DDrawCompat.def</ModuleDefinitionFile>
<AdditionalDependencies>dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>dxguid.lib;detours.lib;msimg32.lib;oleacc.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>No</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>

View File

@ -1,5 +1,10 @@
#define WIN32_LEAN_AND_MEAN
#include <string>
#include <Windows.h>
#include <Uxtheme.h>
#include "CompatDirectDraw.h"
#include "CompatDirectDrawSurface.h"
#include "CompatDirectDrawPalette.h"
@ -163,6 +168,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
Compat::origProcs.DirectInputCreateA = GetProcAddress(g_origDInputModule, "DirectInputCreateA");
SetProcessAffinityMask(GetCurrentProcess(), 1);
SetThemeAppProperties(0);
if (Compat::origProcs.SetAppCompatData)
{