mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Hook all GDI threads
This commit is contained in:
parent
4717b9aa1b
commit
58aba66ca2
@ -6,6 +6,20 @@
|
||||
|
||||
namespace Compat
|
||||
{
|
||||
class CriticalSection : public CRITICAL_SECTION
|
||||
{
|
||||
public:
|
||||
CriticalSection()
|
||||
{
|
||||
InitializeCriticalSection(this);
|
||||
}
|
||||
|
||||
~CriticalSection()
|
||||
{
|
||||
DeleteCriticalSection(this);
|
||||
}
|
||||
};
|
||||
|
||||
class ScopedCriticalSection
|
||||
{
|
||||
public:
|
||||
|
@ -39,7 +39,7 @@ namespace
|
||||
D3DKMT_HANDLE g_lastPresentContext = 0;
|
||||
UINT g_presentCount = 0;
|
||||
std::atomic<long long> g_qpcLastVerticalBlank = 0;
|
||||
CRITICAL_SECTION g_vblankCs = {};
|
||||
Compat::CriticalSection g_vblankCs;
|
||||
|
||||
decltype(D3DKMTCreateContextVirtual)* g_origD3dKmtCreateContextVirtual = nullptr;
|
||||
|
||||
@ -313,7 +313,6 @@ namespace D3dDdi
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
InitializeCriticalSection(&g_vblankCs);
|
||||
HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter);
|
||||
HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext);
|
||||
HOOK_FUNCTION(gdi32, D3DKMTCreateDevice, createDevice);
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "DDraw/ActivateAppHandler.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/TagSurface.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "Win32/DisplayMode.h"
|
||||
|
||||
@ -182,15 +181,6 @@ namespace DDraw
|
||||
HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
void* ddObject = getDdObject(*This);
|
||||
TagSurface* tagSurface = TagSurface::get(ddObject);
|
||||
if (!tagSurface)
|
||||
{
|
||||
CompatPtr<IDirectDraw> dd(Compat::queryInterface<IDirectDraw>(This));
|
||||
TagSurface::create(*dd);
|
||||
tagSurface = TagSurface::get(ddObject);
|
||||
}
|
||||
|
||||
ActivateAppHandler::setCooperativeLevel(hWnd, dwFlags);
|
||||
}
|
||||
return result;
|
||||
|
@ -50,7 +50,11 @@ namespace
|
||||
|
||||
BOOL CALLBACK addVisibleLayeredWindowToVector(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
if (IsWindowVisible(hwnd) && (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||
DWORD windowPid = 0;
|
||||
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||
if (GetCurrentProcessId() == windowPid &&
|
||||
IsWindowVisible(hwnd) &&
|
||||
(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||
!Gdi::Window::isPresentationWindow(hwnd))
|
||||
{
|
||||
auto& visibleLayeredWindows = *reinterpret_cast<std::vector<HWND>*>(lParam);
|
||||
@ -119,8 +123,7 @@ namespace
|
||||
void bltVisibleLayeredWindowsToBackBuffer()
|
||||
{
|
||||
std::vector<HWND> visibleLayeredWindows;
|
||||
EnumThreadWindows(Gdi::getGdiThreadId(), addVisibleLayeredWindowToVector,
|
||||
reinterpret_cast<LPARAM>(&visibleLayeredWindows));
|
||||
EnumWindows(addVisibleLayeredWindowToVector, reinterpret_cast<LPARAM>(&visibleLayeredWindows));
|
||||
|
||||
if (visibleLayeredWindows.empty())
|
||||
{
|
||||
|
@ -151,7 +151,6 @@ namespace DDraw
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
PrimarySurface::onRestore();
|
||||
Gdi::redraw(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,48 +0,0 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/TagSurface.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<void*, DDraw::TagSurface*> g_tagSurfaces;
|
||||
}
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
TagSurface::~TagSurface()
|
||||
{
|
||||
Repository::onRelease(m_ddObject);
|
||||
g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
|
||||
[=](auto& i) { return i.second == this; }));
|
||||
}
|
||||
|
||||
HRESULT TagSurface::create(CompatRef<IDirectDraw> dd)
|
||||
{
|
||||
DDSURFACEDESC desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||||
desc.dwWidth = 1;
|
||||
desc.dwHeight = 1;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||||
|
||||
IDirectDrawSurface* surface = nullptr;
|
||||
HRESULT result = Surface::create(dd, desc, surface);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
std::unique_ptr<Surface> privateData(new TagSurface());
|
||||
g_tagSurfaces[getDdObject(dd.get())] = static_cast<TagSurface*>(privateData.get());
|
||||
CompatPtr<IDirectDrawSurface7> surface7(Compat::queryInterface<IDirectDrawSurface7>(surface));
|
||||
attach(*surface7, privateData);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TagSurface* TagSurface::get(void* ddObject)
|
||||
{
|
||||
auto it = g_tagSurfaces.find(ddObject);
|
||||
return it != g_tagSurfaces.end() ? it->second : nullptr;
|
||||
}
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
class TagSurface : public Surface
|
||||
{
|
||||
public:
|
||||
virtual ~TagSurface();
|
||||
|
||||
static HRESULT create(CompatRef<IDirectDraw> dd);
|
||||
static TagSurface* get(void* ddObject);
|
||||
};
|
||||
}
|
@ -188,7 +188,6 @@
|
||||
<ClInclude Include="DDraw\Hooks.h" />
|
||||
<ClInclude Include="DDraw\Repository.h" />
|
||||
<ClInclude Include="DDraw\ScopedThreadLock.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\TagSurface.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\PrimarySurface.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h" />
|
||||
<ClInclude Include="DDraw\Surfaces\Surface.h" />
|
||||
@ -261,7 +260,6 @@
|
||||
<ClCompile Include="DDraw\Repository.cpp" />
|
||||
<ClCompile Include="DDraw\IReleaseNotifier.cpp" />
|
||||
<ClCompile Include="DDraw\RealPrimarySurface.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\PrimarySurface.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp" />
|
||||
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />
|
||||
|
@ -255,9 +255,6 @@
|
||||
<ClInclude Include="DDraw\Surfaces\PrimarySurfaceImpl.h">
|
||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DDraw\Surfaces\TagSurface.h">
|
||||
<Filter>Header Files\DDraw\Surfaces</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Direct3d\Visitors\Direct3dViewportVtblVisitor.h">
|
||||
<Filter>Header Files\Direct3d\Visitors</Filter>
|
||||
</ClInclude>
|
||||
@ -449,9 +446,6 @@
|
||||
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp">
|
||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DDraw\Surfaces\TagSurface.cpp">
|
||||
<Filter>Source Files\DDraw\Surfaces</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Direct3d\Direct3dViewport.cpp">
|
||||
<Filter>Source Files\Direct3d</Filter>
|
||||
</ClCompile>
|
||||
|
@ -84,7 +84,7 @@ namespace
|
||||
#define LOAD_ORIGINAL_PROC(procName) \
|
||||
Dll::g_origProcs.procName = Compat::getProcAddress(g_origDDrawModule, #procName);
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
@ -96,7 +96,8 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
||||
|
||||
char currentDllPath[MAX_PATH] = {};
|
||||
GetModuleFileName(hinstDLL, currentDllPath, MAX_PATH);
|
||||
Compat::Log() << "Loading DDrawCompat from " << currentDllPath;
|
||||
Compat::Log() << "Loading DDrawCompat " << (lpvReserved ? "statically" : "dynamically")
|
||||
<< " from " << currentDllPath;
|
||||
|
||||
char systemDirectory[MAX_PATH] = {};
|
||||
GetSystemDirectory(systemDirectory, MAX_PATH);
|
||||
@ -138,17 +139,24 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/)
|
||||
}
|
||||
else if (fdwReason == DLL_PROCESS_DETACH)
|
||||
{
|
||||
Compat::Log() << "Detaching DDrawCompat";
|
||||
DDraw::uninstallHooks();
|
||||
D3dDdi::uninstallHooks();
|
||||
Gdi::uninstallHooks();
|
||||
Compat::unhookAllFunctions();
|
||||
FreeLibrary(g_origDInputModule);
|
||||
FreeLibrary(g_origDDrawModule);
|
||||
Compat::Log() << "Detaching DDrawCompat due to " << (lpvReserved ? "process termination" : "FreeLibrary");
|
||||
if (!lpvReserved)
|
||||
{
|
||||
DDraw::uninstallHooks();
|
||||
D3dDdi::uninstallHooks();
|
||||
Gdi::uninstallHooks();
|
||||
Compat::unhookAllFunctions();
|
||||
FreeLibrary(g_origDInputModule);
|
||||
FreeLibrary(g_origDDrawModule);
|
||||
}
|
||||
Win32::FontSmoothing::setSystemSettingsForced(Win32::FontSmoothing::g_origSystemSettings);
|
||||
timeEndPeriod(1);
|
||||
Compat::Log() << "DDrawCompat detached successfully";
|
||||
}
|
||||
else if (fdwReason == DLL_THREAD_DETACH)
|
||||
{
|
||||
Gdi::dllThreadDetach();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ namespace
|
||||
bool isDrawn;
|
||||
};
|
||||
|
||||
|
||||
CaretData g_caret = {};
|
||||
long long g_qpcLastBlink = 0;
|
||||
|
||||
|
@ -18,14 +18,15 @@ namespace
|
||||
HDC dc;
|
||||
DWORD refCount;
|
||||
HDC origDc;
|
||||
DWORD threadId;
|
||||
int savedState;
|
||||
};
|
||||
|
||||
typedef std::unique_ptr<HDC__, void(*)(HDC)> OrigDc;
|
||||
typedef std::unordered_map<HDC, CompatDc> CompatDcMap;
|
||||
|
||||
CompatDcMap g_origDcToCompatDc;
|
||||
thread_local std::vector<OrigDc> g_threadDcs;
|
||||
|
||||
void restoreDc(const CompatDc& compatDc);
|
||||
|
||||
void copyDcAttributes(const CompatDc& compatDc, HDC origDc, const POINT& origin)
|
||||
{
|
||||
@ -79,13 +80,12 @@ namespace
|
||||
MoveToEx(compatDc.dc, currentPos.x, currentPos.y, nullptr);
|
||||
}
|
||||
|
||||
void deleteDc(HDC origDc)
|
||||
void restoreDc(const CompatDc& compatDc)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
auto it = g_origDcToCompatDc.find(origDc);
|
||||
RestoreDC(it->second.dc, it->second.savedState);
|
||||
Gdi::DcCache::deleteDc(it->second.dc);
|
||||
g_origDcToCompatDc.erase(origDc);
|
||||
// Bitmap may have changed during VirtualScreen::update, do not let RestoreDC restore the old one
|
||||
HGDIOBJ bitmap = GetCurrentObject(compatDc.dc, OBJ_BITMAP);
|
||||
RestoreDC(compatDc.dc, compatDc.savedState);
|
||||
SelectObject(compatDc.dc, bitmap);
|
||||
}
|
||||
|
||||
void setClippingRegion(HDC compatDc, HDC origDc, HWND hwnd, const POINT& origin)
|
||||
@ -115,6 +115,37 @@ namespace Gdi
|
||||
{
|
||||
namespace Dc
|
||||
{
|
||||
void dllProcessDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
for (auto& origDcToCompatDc : g_origDcToCompatDc)
|
||||
{
|
||||
restoreDc(origDcToCompatDc.second);
|
||||
Gdi::DcCache::deleteDc(origDcToCompatDc.second.dc);
|
||||
}
|
||||
g_origDcToCompatDc.clear();
|
||||
}
|
||||
|
||||
void dllThreadDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
const DWORD threadId = GetCurrentThreadId();
|
||||
auto it = g_origDcToCompatDc.begin();
|
||||
while (it != g_origDcToCompatDc.end())
|
||||
{
|
||||
if (threadId == it->second.threadId)
|
||||
{
|
||||
restoreDc(it->second);
|
||||
Gdi::DcCache::deleteDc(it->second.dc);
|
||||
it = g_origDcToCompatDc.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HDC getDc(HDC origDc)
|
||||
{
|
||||
if (!origDc || OBJ_DC != GetObjectType(origDc) || DT_RASDISPLAY != GetDeviceCaps(origDc, TECHNOLOGY))
|
||||
@ -161,8 +192,8 @@ namespace Gdi
|
||||
|
||||
compatDc.refCount = 1;
|
||||
compatDc.origDc = origDc;
|
||||
compatDc.threadId = GetCurrentThreadId();
|
||||
g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));
|
||||
g_threadDcs.emplace_back(origDc, &deleteDc);
|
||||
|
||||
return compatDc.dc;
|
||||
}
|
||||
@ -188,12 +219,7 @@ namespace Gdi
|
||||
--compatDc.refCount;
|
||||
if (0 == compatDc.refCount)
|
||||
{
|
||||
auto threadDcIter = std::find_if(g_threadDcs.begin(), g_threadDcs.end(),
|
||||
[origDc](const OrigDc& dc) { return dc.get() == origDc; });
|
||||
threadDcIter->release();
|
||||
g_threadDcs.erase(threadDcIter);
|
||||
|
||||
RestoreDC(compatDc.dc, compatDc.savedState);
|
||||
restoreDc(compatDc);
|
||||
Gdi::DcCache::releaseDc(compatDc.dc);
|
||||
g_origDcToCompatDc.erase(origDc);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ namespace Gdi
|
||||
{
|
||||
namespace Dc
|
||||
{
|
||||
void dllProcessDetach();
|
||||
void dllThreadDetach();
|
||||
HDC getDc(HDC origDc);
|
||||
HDC getOrigDc(HDC dc);
|
||||
void releaseDc(HDC origDc);
|
||||
|
@ -1,14 +1,15 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Gdi/DcCache.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef std::unique_ptr<HDC__, void(*)(HDC)> CachedDc;
|
||||
|
||||
thread_local std::vector<CachedDc> g_cache;
|
||||
std::map<DWORD, std::vector<HDC>> g_threadIdToDcCache;
|
||||
}
|
||||
|
||||
namespace Gdi
|
||||
@ -17,29 +18,69 @@ namespace Gdi
|
||||
{
|
||||
void deleteDc(HDC cachedDc)
|
||||
{
|
||||
Gdi::VirtualScreen::deleteDc(cachedDc);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||
{
|
||||
auto& dcCache = threadIdToDcCache.second;
|
||||
auto it = std::find(dcCache.begin(), dcCache.end(), cachedDc);
|
||||
if (it != dcCache.end())
|
||||
{
|
||||
Gdi::VirtualScreen::deleteDc(*it);
|
||||
dcCache.erase(it);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dllProcessDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
for (auto& threadIdToDcCache : g_threadIdToDcCache)
|
||||
{
|
||||
for (HDC dc : threadIdToDcCache.second)
|
||||
{
|
||||
Gdi::VirtualScreen::deleteDc(dc);
|
||||
}
|
||||
}
|
||||
g_threadIdToDcCache.clear();
|
||||
}
|
||||
|
||||
void dllThreadDetach()
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
auto it = g_threadIdToDcCache.find(GetCurrentThreadId());
|
||||
if (it == g_threadIdToDcCache.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (HDC dc : it->second)
|
||||
{
|
||||
Gdi::VirtualScreen::deleteDc(dc);
|
||||
}
|
||||
|
||||
g_threadIdToDcCache.erase(it);
|
||||
}
|
||||
|
||||
HDC getDc()
|
||||
{
|
||||
HDC cachedDc = nullptr;
|
||||
DDraw::ScopedThreadLock lock;
|
||||
std::vector<HDC>& dcCache = g_threadIdToDcCache[GetCurrentThreadId()];
|
||||
|
||||
if (g_cache.empty())
|
||||
if (dcCache.empty())
|
||||
{
|
||||
cachedDc = Gdi::VirtualScreen::createDc();
|
||||
}
|
||||
else
|
||||
{
|
||||
cachedDc = g_cache.back().release();
|
||||
g_cache.pop_back();
|
||||
return Gdi::VirtualScreen::createDc();
|
||||
}
|
||||
|
||||
return cachedDc;
|
||||
HDC dc = dcCache.back();
|
||||
dcCache.pop_back();
|
||||
return dc;
|
||||
}
|
||||
|
||||
void releaseDc(HDC cachedDc)
|
||||
{
|
||||
g_cache.emplace_back(CachedDc(cachedDc, &deleteDc));
|
||||
DDraw::ScopedThreadLock lock;
|
||||
g_threadIdToDcCache[GetCurrentThreadId()].push_back(cachedDc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ namespace Gdi
|
||||
namespace DcCache
|
||||
{
|
||||
void deleteDc(HDC cachedDc);
|
||||
void dllProcessDetach();
|
||||
void dllThreadDetach();
|
||||
HDC getDc();
|
||||
void releaseDc(HDC cachedDc);
|
||||
}
|
||||
|
@ -13,6 +13,39 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
class CompatDc
|
||||
{
|
||||
public:
|
||||
CompatDc(HDC dc) : m_origDc(dc), m_compatDc(Gdi::Dc::getDc(dc))
|
||||
{
|
||||
}
|
||||
|
||||
CompatDc(const CompatDc&) = delete;
|
||||
|
||||
CompatDc(CompatDc&& other) : m_origDc(nullptr), m_compatDc(nullptr)
|
||||
{
|
||||
std::swap(m_origDc, other.m_origDc);
|
||||
std::swap(m_compatDc, other.m_compatDc);
|
||||
}
|
||||
|
||||
~CompatDc()
|
||||
{
|
||||
if (m_compatDc)
|
||||
{
|
||||
Gdi::Dc::releaseDc(m_origDc);
|
||||
}
|
||||
}
|
||||
|
||||
operator HDC() const
|
||||
{
|
||||
return m_compatDc ? m_compatDc : m_origDc;
|
||||
}
|
||||
|
||||
private:
|
||||
HDC m_origDc;
|
||||
HDC m_compatDc;
|
||||
};
|
||||
|
||||
struct ExcludeRgnForOverlappingWindowArgs
|
||||
{
|
||||
HRGN rgn;
|
||||
@ -56,25 +89,9 @@ namespace
|
||||
return t;
|
||||
}
|
||||
|
||||
HDC replaceDc(HDC dc)
|
||||
CompatDc replaceDc(HDC dc)
|
||||
{
|
||||
HDC compatDc = Gdi::Dc::getDc(dc);
|
||||
return compatDc ? compatDc : dc;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void releaseDc(T) {}
|
||||
|
||||
void releaseDc(HDC dc)
|
||||
{
|
||||
Gdi::Dc::releaseDc(dc);
|
||||
}
|
||||
|
||||
template <typename T, typename... Params>
|
||||
void releaseDc(T t, Params... params)
|
||||
{
|
||||
releaseDc(params...);
|
||||
releaseDc(t);
|
||||
return CompatDc(dc);
|
||||
}
|
||||
|
||||
template <typename OrigFuncPtr, OrigFuncPtr origFunc, typename Result, typename... Params>
|
||||
@ -90,7 +107,6 @@ namespace
|
||||
const bool isReadOnlyAccess = !hasDisplayDcArg(getDestinationDc<OrigFuncPtr, origFunc>(params...));
|
||||
Gdi::GdiAccessGuard accessGuard(isReadOnlyAccess ? Gdi::ACCESS_READ : Gdi::ACCESS_WRITE);
|
||||
result = Compat::getOrigFuncPtr<OrigFuncPtr, origFunc>()(replaceDc(params)...);
|
||||
releaseDc(params...);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -135,7 +151,6 @@ namespace
|
||||
{
|
||||
Gdi::GdiAccessGuard accessGuard(Gdi::ACCESS_WRITE);
|
||||
result = CALL_ORIG_FUNC(ExtTextOutW)(replaceDc(hdc), x, y, options, lprect, lpString, c, lpDx);
|
||||
releaseDc(hdc);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -155,7 +170,10 @@ namespace
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!IsWindowVisible(hwnd) ||
|
||||
DWORD windowPid = 0;
|
||||
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||
if (GetCurrentProcessId() != windowPid ||
|
||||
!IsWindowVisible(hwnd) ||
|
||||
(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & (WS_EX_LAYERED | WS_EX_TRANSPARENT)))
|
||||
{
|
||||
return TRUE;
|
||||
@ -248,8 +266,7 @@ namespace
|
||||
}
|
||||
|
||||
ExcludeRgnForOverlappingWindowArgs args = { hrgn, GetAncestor(hwnd, GA_ROOT) };
|
||||
EnumThreadWindows(Gdi::getGdiThreadId(), excludeRgnForOverlappingWindow,
|
||||
reinterpret_cast<LPARAM>(&args));
|
||||
EnumWindows(excludeRgnForOverlappingWindow, reinterpret_cast<LPARAM>(&args));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -282,8 +299,7 @@ namespace Gdi
|
||||
{
|
||||
HRGN rgn = getWindowRegion(hwnd);
|
||||
ExcludeRgnForOverlappingWindowArgs args = { rgn, hwnd };
|
||||
EnumThreadWindows(Gdi::getGdiThreadId(), excludeRgnForOverlappingWindow,
|
||||
reinterpret_cast<LPARAM>(&args));
|
||||
EnumWindows(excludeRgnForOverlappingWindow, reinterpret_cast<LPARAM>(&args));
|
||||
return rgn;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "Gdi/Caret.h"
|
||||
#include "Gdi/Dc.h"
|
||||
#include "Gdi/DcCache.h"
|
||||
#include "Gdi/DcFunctions.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/PaintHandlers.h"
|
||||
@ -9,21 +11,27 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
DWORD g_gdiThreadId = 0;
|
||||
HDC g_screenDc = nullptr;
|
||||
|
||||
BOOL CALLBACK redrawWindowCallback(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
Gdi::redrawWindow(hwnd, reinterpret_cast<HRGN>(lParam));
|
||||
DWORD windowPid = 0;
|
||||
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||
if (GetCurrentProcessId() == windowPid)
|
||||
{
|
||||
Gdi::redrawWindow(hwnd, reinterpret_cast<HRGN>(lParam));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Gdi
|
||||
{
|
||||
DWORD getGdiThreadId()
|
||||
void dllThreadDetach()
|
||||
{
|
||||
return g_gdiThreadId;
|
||||
WinProc::dllThreadDetach();
|
||||
Dc::dllThreadDetach();
|
||||
DcCache::dllThreadDetach();
|
||||
}
|
||||
|
||||
HDC getScreenDc()
|
||||
@ -38,19 +46,18 @@ namespace Gdi
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
g_gdiThreadId = GetCurrentThreadId();
|
||||
g_screenDc = GetDC(nullptr);
|
||||
|
||||
Gdi::DcFunctions::installHooks();
|
||||
Gdi::PaintHandlers::installHooks();
|
||||
Gdi::ScrollFunctions::installHooks();
|
||||
Gdi::WinProc::installHooks();
|
||||
Gdi::Caret::installHooks();
|
||||
DcFunctions::installHooks();
|
||||
PaintHandlers::installHooks();
|
||||
ScrollFunctions::installHooks();
|
||||
WinProc::installHooks();
|
||||
Caret::installHooks();
|
||||
}
|
||||
|
||||
void redraw(HRGN rgn)
|
||||
{
|
||||
EnumThreadWindows(g_gdiThreadId, &redrawWindowCallback, reinterpret_cast<LPARAM>(rgn));
|
||||
EnumWindows(&redrawWindowCallback, reinterpret_cast<LPARAM>(rgn));
|
||||
}
|
||||
|
||||
void redrawWindow(HWND hwnd, HRGN rgn)
|
||||
@ -68,7 +75,6 @@ namespace Gdi
|
||||
}
|
||||
|
||||
RedrawWindow(hwnd, nullptr, rgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
|
||||
RedrawWindow(hwnd, nullptr, rgn, RDW_ERASENOW);
|
||||
|
||||
if (rgn)
|
||||
{
|
||||
@ -85,9 +91,10 @@ namespace Gdi
|
||||
|
||||
void uninstallHooks()
|
||||
{
|
||||
Gdi::Caret::uninstallHooks();
|
||||
Gdi::WinProc::uninstallHooks();
|
||||
Gdi::PaintHandlers::uninstallHooks();
|
||||
Caret::uninstallHooks();
|
||||
WinProc::uninstallHooks();
|
||||
Dc::dllProcessDetach();
|
||||
DcCache::dllProcessDetach();
|
||||
ReleaseDC(nullptr, g_screenDc);
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace Gdi
|
||||
|
||||
typedef void(*WindowPosChangeNotifyFunc)();
|
||||
|
||||
DWORD getGdiThreadId();
|
||||
void dllThreadDetach();
|
||||
HDC getScreenDc();
|
||||
HRGN getVisibleWindowRgn(HWND hwnd);
|
||||
void installHooks();
|
||||
|
@ -41,7 +41,6 @@ namespace
|
||||
LRESULT onPaint(HWND hwnd, WNDPROC origWndProc);
|
||||
LRESULT onPrint(HWND hwnd, UINT msg, HDC dc, LONG flags, WNDPROC origWndProc);
|
||||
|
||||
HHOOK g_cbtProcHook = nullptr;
|
||||
int g_menuWndProcIndex = 0;
|
||||
int g_scrollBarWndProcIndex = 0;
|
||||
|
||||
@ -71,52 +70,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT CALLBACK cbtProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Compat::LogEnter("cbtProc", Compat::hex(nCode), Compat::hex(wParam), Compat::hex(lParam));
|
||||
LRESULT result = 0;
|
||||
|
||||
if (nCode < 0)
|
||||
{
|
||||
result = CallNextHookEx(nullptr, nCode, wParam, lParam);
|
||||
}
|
||||
else if (HCBT_CREATEWND == nCode)
|
||||
{
|
||||
HWND hwnd = reinterpret_cast<HWND>(wParam);
|
||||
WNDPROC wndProcA = reinterpret_cast<WNDPROC>(GetWindowLongA(hwnd, GWL_WNDPROC));
|
||||
WNDPROC wndProcW = reinterpret_cast<WNDPROC>(GetWindowLongW(hwnd, GWL_WNDPROC));
|
||||
|
||||
int index = -1;
|
||||
if (wndProcA == g_user32WndProcA[g_menuWndProcIndex].oldWndProc ||
|
||||
wndProcW == g_user32WndProcW[g_menuWndProcIndex].oldWndProc)
|
||||
{
|
||||
index = g_menuWndProcIndex;
|
||||
}
|
||||
else if (wndProcA == g_user32WndProcA[g_scrollBarWndProcIndex].oldWndProc ||
|
||||
wndProcW == g_user32WndProcW[g_scrollBarWndProcIndex].oldWndProc)
|
||||
{
|
||||
index = g_scrollBarWndProcIndex;
|
||||
}
|
||||
|
||||
if (-1 != index)
|
||||
{
|
||||
if (IsWindowUnicode(hwnd))
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowLongW)(hwnd, GWL_WNDPROC,
|
||||
reinterpret_cast<LONG>(g_user32WndProcW[index].newWndProc));
|
||||
}
|
||||
else
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC,
|
||||
reinterpret_cast<LONG>(g_user32WndProcA[index].newWndProc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Compat::LogLeave("cbtProc", Compat::hex(nCode), Compat::hex(wParam), Compat::hex(lParam)) << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
LRESULT comboBoxWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, WNDPROC origWndProc)
|
||||
{
|
||||
return defPaintProc(hwnd, msg, wParam, lParam, origWndProc);
|
||||
@ -481,13 +434,38 @@ namespace Gdi
|
||||
HOOK_FUNCTION(user32, DefWindowProcW, defWindowProcW);
|
||||
HOOK_FUNCTION(user32, DefDlgProcA, defDlgProcA);
|
||||
HOOK_FUNCTION(user32, DefDlgProcW, defDlgProcW);
|
||||
|
||||
g_cbtProcHook = SetWindowsHookEx(WH_CBT, cbtProc, nullptr, Gdi::getGdiThreadId());
|
||||
}
|
||||
|
||||
void uninstallHooks()
|
||||
void onCreateWindow(HWND hwnd)
|
||||
{
|
||||
UnhookWindowsHookEx(g_cbtProcHook);
|
||||
WNDPROC wndProcA = reinterpret_cast<WNDPROC>(GetWindowLongA(hwnd, GWL_WNDPROC));
|
||||
WNDPROC wndProcW = reinterpret_cast<WNDPROC>(GetWindowLongW(hwnd, GWL_WNDPROC));
|
||||
|
||||
int index = -1;
|
||||
if (wndProcA == g_user32WndProcA[g_menuWndProcIndex].oldWndProc ||
|
||||
wndProcW == g_user32WndProcW[g_menuWndProcIndex].oldWndProc)
|
||||
{
|
||||
index = g_menuWndProcIndex;
|
||||
}
|
||||
else if (wndProcA == g_user32WndProcA[g_scrollBarWndProcIndex].oldWndProc ||
|
||||
wndProcW == g_user32WndProcW[g_scrollBarWndProcIndex].oldWndProc)
|
||||
{
|
||||
index = g_scrollBarWndProcIndex;
|
||||
}
|
||||
|
||||
if (-1 != index)
|
||||
{
|
||||
if (IsWindowUnicode(hwnd))
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowLongW)(hwnd, GWL_WNDPROC,
|
||||
reinterpret_cast<LONG>(g_user32WndProcW[index].newWndProc));
|
||||
}
|
||||
else
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC,
|
||||
reinterpret_cast<LONG>(g_user32WndProcA[index].newWndProc));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,6 @@ namespace Gdi
|
||||
namespace PaintHandlers
|
||||
{
|
||||
void installHooks();
|
||||
void uninstallHooks();
|
||||
void onCreateWindow(HWND hwnd);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
#include <set>
|
||||
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Gdi/Region.h"
|
||||
#include "Gdi/VirtualScreen.h"
|
||||
@ -10,7 +10,6 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
CRITICAL_SECTION g_cs = {};
|
||||
Gdi::Region g_region;
|
||||
RECT g_bounds = {};
|
||||
DWORD g_bpp = 0;
|
||||
@ -71,7 +70,7 @@ namespace Gdi
|
||||
{
|
||||
HDC createDc()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
std::unique_ptr<void, decltype(&DeleteObject)> dib(createDib(), DeleteObject);
|
||||
if (!dib)
|
||||
{
|
||||
@ -100,7 +99,7 @@ namespace Gdi
|
||||
|
||||
HBITMAP createDib()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
if (!g_surfaceFileMapping)
|
||||
{
|
||||
return nullptr;
|
||||
@ -110,7 +109,7 @@ namespace Gdi
|
||||
|
||||
HBITMAP createOffScreenDib(DWORD width, DWORD height)
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
return createDibSection(width, height, nullptr);
|
||||
}
|
||||
|
||||
@ -122,7 +121,7 @@ namespace Gdi
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DDSURFACEDESC2 desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS | DDSD_PITCH | DDSD_LPSURFACE;
|
||||
@ -148,7 +147,7 @@ namespace Gdi
|
||||
return;
|
||||
}
|
||||
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DeleteObject(SelectObject(dc, g_stockBitmap));
|
||||
DeleteDC(dc);
|
||||
g_dcs.erase(dc);
|
||||
@ -156,19 +155,18 @@ namespace Gdi
|
||||
|
||||
RECT getBounds()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
return g_bounds;
|
||||
}
|
||||
|
||||
const Region& getRegion()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
return g_region;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
InitializeCriticalSection(&g_cs);
|
||||
update();
|
||||
updatePalette();
|
||||
}
|
||||
@ -176,7 +174,7 @@ namespace Gdi
|
||||
bool update()
|
||||
{
|
||||
Compat::LogEnter("VirtualScreen::update");
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
|
||||
static auto prevDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness() - 1;
|
||||
const auto currentDisplaySettingsUniqueness = Win32::DisplayMode::queryDisplaySettingsUniqueness();
|
||||
@ -224,7 +222,7 @@ namespace Gdi
|
||||
|
||||
void updatePalette()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
if (8 != g_bpp)
|
||||
{
|
||||
return;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include <dwmapi.h>
|
||||
@ -11,15 +10,20 @@
|
||||
#include "Common/ScopedCriticalSection.h"
|
||||
#include "Gdi/AccessGuard.h"
|
||||
#include "Gdi/Dc.h"
|
||||
#include "Gdi/PaintHandlers.h"
|
||||
#include "Gdi/ScrollBar.h"
|
||||
#include "Gdi/ScrollFunctions.h"
|
||||
#include "Gdi/TitleBar.h"
|
||||
#include "Gdi/Window.h"
|
||||
#include "Gdi/WinProc.h"
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
|
||||
namespace
|
||||
{
|
||||
HHOOK g_callWndRetProcHook = nullptr;
|
||||
std::multimap<DWORD, HHOOK> g_threadIdToHook;
|
||||
Compat::CriticalSection g_threadIdToHookCs;
|
||||
HWINEVENTHOOK g_objectCreateEventHook = nullptr;
|
||||
HWINEVENTHOOK g_objectStateChangeEventHook = nullptr;
|
||||
std::set<Gdi::WindowPosChangeNotifyFunc> g_windowPosChangeNotifyFuncs;
|
||||
|
||||
@ -35,13 +39,9 @@ namespace
|
||||
auto ret = reinterpret_cast<CWPRETSTRUCT*>(lParam);
|
||||
Compat::LogEnter("callWndRetProc", Compat::hex(nCode), Compat::hex(wParam), ret);
|
||||
|
||||
if (HC_ACTION == nCode)
|
||||
if (HC_ACTION == nCode && !Gdi::Window::isPresentationWindow(ret->hwnd))
|
||||
{
|
||||
if (WM_CREATE == ret->message)
|
||||
{
|
||||
onCreateWindow(ret->hwnd);
|
||||
}
|
||||
else if (WM_DESTROY == ret->message)
|
||||
if (WM_DESTROY == ret->message)
|
||||
{
|
||||
onDestroyWindow(ret->hwnd);
|
||||
}
|
||||
@ -79,8 +79,25 @@ namespace
|
||||
&disableTransitions, sizeof(disableTransitions));
|
||||
}
|
||||
|
||||
void hookThread(DWORD threadId)
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||
if (g_threadIdToHook.end() == g_threadIdToHook.find(threadId))
|
||||
{
|
||||
g_threadIdToHook.emplace(threadId,
|
||||
SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId));
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK initTopLevelWindow(HWND hwnd, LPARAM /*lParam*/)
|
||||
{
|
||||
DWORD windowPid = 0;
|
||||
GetWindowThreadProcessId(hwnd, &windowPid);
|
||||
if (GetCurrentProcessId() != windowPid)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
onCreateWindow(hwnd);
|
||||
if (!(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED))
|
||||
{
|
||||
@ -90,6 +107,21 @@ namespace
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CALLBACK objectCreateEvent(
|
||||
HWINEVENTHOOK /*hWinEventHook*/,
|
||||
DWORD /*event*/,
|
||||
HWND hwnd,
|
||||
LONG idObject,
|
||||
LONG /*idChild*/,
|
||||
DWORD /*dwEventThread*/,
|
||||
DWORD /*dwmsEventTime*/)
|
||||
{
|
||||
if (OBJID_WINDOW == idObject && !Gdi::Window::isPresentationWindow(hwnd))
|
||||
{
|
||||
onCreateWindow(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void CALLBACK objectStateChangeEvent(
|
||||
HWINEVENTHOOK /*hWinEventHook*/,
|
||||
DWORD /*event*/,
|
||||
@ -149,9 +181,14 @@ namespace
|
||||
|
||||
void onCreateWindow(HWND hwnd)
|
||||
{
|
||||
hookThread(GetWindowThreadProcessId(hwnd, nullptr));
|
||||
disableDwmAttributes(hwnd);
|
||||
removeDropShadow(hwnd);
|
||||
Gdi::Window::add(hwnd);
|
||||
Gdi::PaintHandlers::onCreateWindow(hwnd);
|
||||
if (Gdi::Window::isTopLevelNonLayeredWindow(hwnd))
|
||||
{
|
||||
Gdi::Window::add(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void onDestroyWindow(HWND hwnd)
|
||||
@ -191,14 +228,30 @@ namespace Gdi
|
||||
{
|
||||
namespace WinProc
|
||||
{
|
||||
void dllThreadDetach()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||
const DWORD threadId = GetCurrentThreadId();
|
||||
for (auto threadIdToHook : g_threadIdToHook)
|
||||
{
|
||||
if (threadId == threadIdToHook.first)
|
||||
{
|
||||
UnhookWindowsHookEx(threadIdToHook.second);
|
||||
}
|
||||
}
|
||||
g_threadIdToHook.erase(threadId);
|
||||
}
|
||||
|
||||
void installHooks()
|
||||
{
|
||||
const DWORD threadId = Gdi::getGdiThreadId();
|
||||
g_callWndRetProcHook = SetWindowsHookEx(WH_CALLWNDPROCRET, callWndRetProc, nullptr, threadId);
|
||||
g_objectCreateEventHook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
|
||||
reinterpret_cast<HMODULE>(&__ImageBase), &objectCreateEvent,
|
||||
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||
g_objectStateChangeEventHook = SetWinEventHook(EVENT_OBJECT_STATECHANGE, EVENT_OBJECT_STATECHANGE,
|
||||
nullptr, &objectStateChangeEvent, 0, threadId, WINEVENT_OUTOFCONTEXT);
|
||||
reinterpret_cast<HMODULE>(&__ImageBase), &objectStateChangeEvent,
|
||||
GetCurrentProcessId(), 0, WINEVENT_INCONTEXT);
|
||||
|
||||
EnumThreadWindows(threadId, initTopLevelWindow, 0);
|
||||
EnumWindows(initTopLevelWindow, 0);
|
||||
}
|
||||
|
||||
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc)
|
||||
@ -209,7 +262,16 @@ namespace Gdi
|
||||
void uninstallHooks()
|
||||
{
|
||||
UnhookWinEvent(g_objectStateChangeEventHook);
|
||||
UnhookWindowsHookEx(g_callWndRetProcHook);
|
||||
UnhookWinEvent(g_objectCreateEventHook);
|
||||
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_threadIdToHookCs);
|
||||
for (auto threadIdToHook : g_threadIdToHook)
|
||||
{
|
||||
UnhookWindowsHookEx(threadIdToHook.second);
|
||||
}
|
||||
g_threadIdToHook.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ namespace Gdi
|
||||
{
|
||||
namespace WinProc
|
||||
{
|
||||
void dllThreadDetach();
|
||||
void installHooks();
|
||||
void watchWindowPosChanges(WindowPosChangeNotifyFunc notifyFunc);
|
||||
void uninstallHooks();
|
||||
|
@ -66,13 +66,9 @@ namespace Gdi
|
||||
|
||||
bool Window::add(HWND hwnd)
|
||||
{
|
||||
const bool isTopLevelNonLayeredWindow = !(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||
(!(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) || GetParent(hwnd) == GetDesktopWindow() ||
|
||||
getComboLBoxAtom() == GetClassLong(hwnd, GCW_ATOM));
|
||||
|
||||
if (isTopLevelNonLayeredWindow && !get(hwnd) &&
|
||||
GetClassLong(hwnd, GCW_ATOM) != getPresentationWindowClassAtom())
|
||||
if (isTopLevelNonLayeredWindow(hwnd) && !get(hwnd))
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
s_windows.emplace(hwnd, std::make_shared<Window>(hwnd));
|
||||
return true;
|
||||
}
|
||||
@ -143,7 +139,14 @@ namespace Gdi
|
||||
|
||||
bool Window::isPresentationWindow(HWND hwnd)
|
||||
{
|
||||
return GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom();
|
||||
return IsWindow(hwnd) && GetClassLong(hwnd, GCW_ATOM) == getPresentationWindowClassAtom();
|
||||
}
|
||||
|
||||
bool Window::isTopLevelNonLayeredWindow(HWND hwnd)
|
||||
{
|
||||
return !(GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) &&
|
||||
(!(GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CHILD) || GetParent(hwnd) == GetDesktopWindow() ||
|
||||
getComboLBoxAtom() == GetClassLong(hwnd, GCW_ATOM));
|
||||
}
|
||||
|
||||
void Window::remove(HWND hwnd)
|
||||
@ -175,14 +178,14 @@ namespace Gdi
|
||||
newVisibleRegion &= VirtualScreen::getRegion();
|
||||
}
|
||||
|
||||
if (m_presentationWindow)
|
||||
if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))
|
||||
{
|
||||
SetWindowPos(m_presentationWindow, nullptr, newWindowRect.left, newWindowRect.top,
|
||||
newWindowRect.right - newWindowRect.left, newWindowRect.bottom - newWindowRect.top,
|
||||
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW);
|
||||
}
|
||||
}
|
||||
else if (m_presentationWindow)
|
||||
else if (m_presentationWindow && GetCurrentThreadId() == GetWindowThreadProcessId(m_hwnd, nullptr))
|
||||
{
|
||||
ShowWindow(m_presentationWindow, SW_HIDE);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ namespace Gdi
|
||||
|
||||
static std::map<HWND, std::shared_ptr<Window>> getWindows();
|
||||
static bool isPresentationWindow(HWND hwnd);
|
||||
static bool isTopLevelNonLayeredWindow(HWND hwnd);
|
||||
static void updateAll();
|
||||
|
||||
private:
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/Hook.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/RealPrimarySurface.h"
|
||||
#include "DDraw/ScopedThreadLock.h"
|
||||
#include "Win32/DisplayMode.h"
|
||||
|
||||
BOOL WINAPI DWM8And16Bit_IsShimApplied_CallOut() { return FALSE; };
|
||||
@ -48,12 +48,12 @@ namespace
|
||||
EnumDisplaySettingsExFunc origEnumDisplaySettingsEx,
|
||||
CStr lpszDeviceName, DevMode* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DevMode prevDevMode = {};
|
||||
if (!(dwflags & CDS_TEST))
|
||||
{
|
||||
prevDevMode.dmSize = sizeof(prevDevMode);
|
||||
origEnumDisplaySettingsEx(lpszDeviceName, ENUM_CURRENT_SETTINGS, &prevDevMode, 0);
|
||||
DDraw::RealPrimarySurface::disableUpdates();
|
||||
}
|
||||
|
||||
BOOL result = FALSE;
|
||||
@ -99,11 +99,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
if (!(dwflags & CDS_TEST))
|
||||
{
|
||||
DDraw::RealPrimarySurface::enableUpdates();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user