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

Fixed various multi-monitor display issues

This commit is contained in:
narzoul 2018-12-09 14:23:36 +01:00
parent 727be63db1
commit 291a9c2f9a
18 changed files with 172 additions and 51 deletions

View File

@ -81,9 +81,9 @@ namespace D3dDdi
return g_ddiVersion; return g_ddiVersion;
} }
void installHooks() void installHooks(HMODULE origDDrawModule)
{ {
KernelModeThunks::installHooks(); KernelModeThunks::installHooks(origDDrawModule);
} }
void onUmdFileNameQueried(const std::wstring& umdFileName) void onUmdFileNameQueried(const std::wstring& umdFileName)

View File

@ -5,7 +5,7 @@
namespace D3dDdi namespace D3dDdi
{ {
UINT getDdiVersion(); UINT getDdiVersion();
void installHooks(); void installHooks(HMODULE origDDrawModule);
void onUmdFileNameQueried(const std::wstring& umdFileName); void onUmdFileNameQueried(const std::wstring& umdFileName);
void uninstallHooks(); void uninstallHooks();
} }

View File

@ -1,5 +1,6 @@
#include <atomic> #include <atomic>
#include <map> #include <map>
#include <string>
#include <d3d.h> #include <d3d.h>
#include <d3dumddi.h> #include <d3dumddi.h>
@ -34,6 +35,7 @@ namespace
std::map<D3DKMT_HANDLE, ContextInfo> g_contexts; std::map<D3DKMT_HANDLE, ContextInfo> g_contexts;
AdapterInfo g_gdiAdapterInfo = {}; AdapterInfo g_gdiAdapterInfo = {};
AdapterInfo g_lastOpenAdapterInfo = {}; AdapterInfo g_lastOpenAdapterInfo = {};
std::string g_lastDDrawCreateDcDevice;
UINT g_lastFlipInterval = 0; UINT g_lastFlipInterval = 0;
UINT g_flipIntervalOverride = 0; UINT g_flipIntervalOverride = 0;
D3DKMT_HANDLE g_lastPresentContext = 0; D3DKMT_HANDLE g_lastPresentContext = 0;
@ -108,6 +110,13 @@ namespace
return LOG_RESULT(result); return LOG_RESULT(result);
} }
HDC WINAPI ddrawCreateDcA(LPCSTR pwszDriver, LPCSTR pwszDevice, LPCSTR pszPort, const DEVMODEA* pdm)
{
LOG_FUNC("ddrawCreateDCA", pwszDriver, pwszDevice, pszPort, pdm);
g_lastDDrawCreateDcDevice = pwszDevice ? pwszDevice : std::string();
return LOG_RESULT(CALL_ORIG_FUNC(CreateDCA)(pwszDriver, pwszDevice, pszPort, pdm));
}
NTSTATUS APIENTRY destroyContext(const D3DKMT_DESTROYCONTEXT* pData) NTSTATUS APIENTRY destroyContext(const D3DKMT_DESTROYCONTEXT* pData)
{ {
LOG_FUNC("D3DKMTDestroyContext", pData); LOG_FUNC("D3DKMTDestroyContext", pData);
@ -123,18 +132,35 @@ namespace
return LOG_RESULT(result); return LOG_RESULT(result);
} }
BOOL CALLBACK findDDrawMonitorRect(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM dwData)
{
MONITORINFOEX mi = {};
mi.cbSize = sizeof(mi);
GetMonitorInfo(hMonitor, &mi);
if (g_lastDDrawCreateDcDevice == mi.szDevice)
{
*reinterpret_cast<RECT*>(dwData) = mi.rcMonitor;
return FALSE;
}
return TRUE;
}
AdapterInfo getAdapterInfo(const D3DKMT_OPENADAPTERFROMHDC& data) AdapterInfo getAdapterInfo(const D3DKMT_OPENADAPTERFROMHDC& data)
{ {
AdapterInfo adapterInfo = {}; AdapterInfo adapterInfo = {};
adapterInfo.adapter = data.hAdapter; adapterInfo.adapter = data.hAdapter;
adapterInfo.vidPnSourceId = data.VidPnSourceId; adapterInfo.vidPnSourceId = data.VidPnSourceId;
POINT p = {}; EnumDisplayMonitors(nullptr, nullptr, findDDrawMonitorRect,
GetDCOrgEx(data.hDc, &p); reinterpret_cast<LPARAM>(&adapterInfo.monitorRect));
MONITORINFO mi = {};
mi.cbSize = sizeof(mi); if (IsRectEmpty(&adapterInfo.monitorRect))
GetMonitorInfo(MonitorFromPoint(p, MONITOR_DEFAULTTOPRIMARY), &mi); {
adapterInfo.monitorRect = mi.rcMonitor; MONITORINFO mi = {};
mi.cbSize = sizeof(mi);
GetMonitorInfo(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
adapterInfo.monitorRect = mi.rcMonitor;
}
return adapterInfo; return adapterInfo;
} }
@ -282,7 +308,7 @@ namespace D3dDdi
{ {
lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness; lastDisplaySettingsUniqueness = currentDisplaySettingsUniqueness;
CompatPtr<IUnknown> ddUnk; CompatPtr<IUnknown> ddUnk;
primary->GetDDInterface(primary, reinterpret_cast<void**>(&ddUnk.getRef())); primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast<void**>(&ddUnk.getRef()));
CompatPtr<IDirectDraw7> dd7(ddUnk); CompatPtr<IDirectDraw7> dd7(ddUnk);
DDDEVICEIDENTIFIER2 di = {}; DDDEVICEIDENTIFIER2 di = {};
@ -297,7 +323,7 @@ namespace D3dDdi
return g_qpcLastVerticalBlank; return g_qpcLastVerticalBlank;
} }
void installHooks() void installHooks(HMODULE origDDrawModule)
{ {
HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter); HOOK_FUNCTION(gdi32, D3DKMTCloseAdapter, closeAdapter);
HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext); HOOK_FUNCTION(gdi32, D3DKMTCreateContext, createContext);
@ -308,6 +334,7 @@ namespace D3dDdi
HOOK_FUNCTION(gdi32, D3DKMTQueryAdapterInfo, queryAdapterInfo); HOOK_FUNCTION(gdi32, D3DKMTQueryAdapterInfo, queryAdapterInfo);
HOOK_FUNCTION(gdi32, D3DKMTPresent, present); HOOK_FUNCTION(gdi32, D3DKMTPresent, present);
HOOK_FUNCTION(gdi32, D3DKMTSetQueuedLimit, setQueuedLimit); HOOK_FUNCTION(gdi32, D3DKMTSetQueuedLimit, setQueuedLimit);
Compat::hookIatFunction(origDDrawModule, "gdi32.dll", "CreateDCA", ddrawCreateDcA);
// Functions not available in Windows Vista // Functions not available in Windows Vista
Compat::hookFunction("gdi32", "D3DKMTCreateContextVirtual", Compat::hookFunction("gdi32", "D3DKMTCreateContextVirtual",

View File

@ -13,7 +13,7 @@ namespace D3dDdi
UINT getLastSubmittedFrameCount(); UINT getLastSubmittedFrameCount();
RECT getMonitorRect(); RECT getMonitorRect();
long long getQpcLastVerticalBlank(); long long getQpcLastVerticalBlank();
void installHooks(); void installHooks(HMODULE origDDrawModule);
void setFlipIntervalOverride(UINT flipInterval); void setFlipIntervalOverride(UINT flipInterval);
void waitForVerticalBlank(); void waitForVerticalBlank();
} }

View File

@ -28,22 +28,6 @@ namespace
namespace DDraw namespace DDraw
{ {
CompatPtr<IDirectDrawSurface7> createCompatibleSurface(DWORD bpp)
{
DDSURFACEDESC2 desc = {};
desc.dwSize = sizeof(desc);
desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
desc.dwWidth = 1;
desc.dwHeight = 1;
desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
desc.ddpfPixelFormat = getRgbPixelFormat(bpp);
CompatPtr<IDirectDrawSurface7> surface;
auto dd = DDraw::Repository::getDirectDraw();
dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr);
return surface;
}
template <typename TDirectDraw> template <typename TDirectDraw>
void* getDdObject(TDirectDraw& dd) void* getDdObject(TDirectDraw& dd)
{ {

View File

@ -2,7 +2,6 @@
#include <ddraw.h> #include <ddraw.h>
#include "Common/CompatPtr.h"
#include "Common/CompatRef.h" #include "Common/CompatRef.h"
#include "Common/CompatVtable.h" #include "Common/CompatVtable.h"
#include "DDraw/Visitors/DirectDrawVtblVisitor.h" #include "DDraw/Visitors/DirectDrawVtblVisitor.h"
@ -10,8 +9,6 @@
namespace DDraw namespace DDraw
{ {
CompatPtr<IDirectDrawSurface7> createCompatibleSurface(DWORD bpp);
template <typename TDirectDraw> template <typename TDirectDraw>
void* getDdObject(TDirectDraw& dd); void* getDdObject(TDirectDraw& dd);

View File

@ -2,8 +2,10 @@
#include <vector> #include <vector>
#include "Common/CompatRef.h" #include "Common/CompatRef.h"
#include "D3dDdi/KernelModeThunks.h"
#include "DDraw/DirectDrawClipper.h" #include "DDraw/DirectDrawClipper.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Region.h"
namespace namespace
{ {
@ -28,9 +30,16 @@ namespace
void updateWindowClipList(CompatRef<IDirectDrawClipper> clipper, ClipperData& data) void updateWindowClipList(CompatRef<IDirectDrawClipper> clipper, ClipperData& data)
{ {
HDC dc = GetDC(data.hwnd); HDC dc = GetDC(data.hwnd);
HRGN rgn = CreateRectRgn(0, 0, 0, 0); Gdi::Region rgn;
GetRandomRgn(dc, rgn, SYSRGN); GetRandomRgn(dc, rgn, SYSRGN);
CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc);
RECT primaryRect = D3dDdi::KernelModeThunks::getMonitorRect();
if (0 != primaryRect.left || 0 != primaryRect.top)
{
rgn.offset(-primaryRect.left, -primaryRect.top);
}
DWORD rgnSize = GetRegionData(rgn, 0, nullptr); DWORD rgnSize = GetRegionData(rgn, 0, nullptr);
std::vector<unsigned char> rgnData(rgnSize); std::vector<unsigned char> rgnData(rgnSize);
GetRegionData(rgn, rgnSize, reinterpret_cast<RGNDATA*>(rgnData.data())); GetRegionData(rgn, rgnSize, reinterpret_cast<RGNDATA*>(rgnData.data()));
@ -40,9 +49,6 @@ namespace
{ {
clipper->SetHWnd(&clipper, 0, data.hwnd); clipper->SetHWnd(&clipper, 0, data.hwnd);
} }
DeleteObject(rgn);
CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc);
} }
HRESULT STDMETHODCALLTYPE GetHWnd(IDirectDrawClipper* This, HWND* lphWnd) HRESULT STDMETHODCALLTYPE GetHWnd(IDirectDrawClipper* This, HWND* lphWnd)
@ -115,6 +121,24 @@ namespace
namespace DDraw namespace DDraw
{ {
HRGN DirectDrawClipper::getClipRgn(CompatRef<IDirectDrawClipper> clipper)
{
std::vector<unsigned char> rgnData;
DWORD size = 0;
clipper->GetClipList(&clipper, nullptr, nullptr, &size);
rgnData.resize(size);
clipper->GetClipList(&clipper, nullptr, reinterpret_cast<RGNDATA*>(rgnData.data()), &size);
return ExtCreateRegion(nullptr, size, reinterpret_cast<RGNDATA*>(rgnData.data()));
}
HRESULT DirectDrawClipper::setClipRgn(CompatRef<IDirectDrawClipper> clipper, HRGN rgn)
{
std::vector<unsigned char> rgnData;
rgnData.resize(GetRegionData(rgn, 0, nullptr));
GetRegionData(rgn, rgnData.size(), reinterpret_cast<RGNDATA*>(rgnData.data()));
return clipper->SetClipList(&clipper, reinterpret_cast<RGNDATA*>(rgnData.data()), 0);
}
void DirectDrawClipper::setCompatVtable(IDirectDrawClipperVtbl& vtable) void DirectDrawClipper::setCompatVtable(IDirectDrawClipperVtbl& vtable)
{ {
vtable.GetHWnd = &GetHWnd; vtable.GetHWnd = &GetHWnd;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Common/CompatRef.h"
#include "Common/CompatVtable.h" #include "Common/CompatVtable.h"
#include "DDraw/Visitors/DirectDrawClipperVtblVisitor.h" #include "DDraw/Visitors/DirectDrawClipperVtblVisitor.h"
@ -8,6 +9,9 @@ namespace DDraw
class DirectDrawClipper : public CompatVtable<IDirectDrawClipperVtbl> class DirectDrawClipper : public CompatVtable<IDirectDrawClipperVtbl>
{ {
public: public:
static HRGN getClipRgn(CompatRef<IDirectDrawClipper> clipper);
static HRESULT setClipRgn(CompatRef<IDirectDrawClipper> clipper, HRGN rgn);
static void setCompatVtable(IDirectDrawClipperVtbl& vtable); static void setCompatVtable(IDirectDrawClipperVtbl& vtable);
}; };
} }

View File

@ -12,7 +12,7 @@ namespace
HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params) HRESULT STDMETHODCALLTYPE callImpl(TSurface* This, Params... params)
{ {
DDraw::Surface* surface = This ? DDraw::Surface::getSurface(*This) : nullptr; DDraw::Surface* surface = This ? DDraw::Surface::getSurface(*This) : nullptr;
if (!surface) if (!surface || !(surface->getImpl<TSurface>()))
{ {
return (CompatVtable<Vtable<TSurface>>::s_origVtable.*origMethod)(This, params...); return (CompatVtable<Vtable<TSurface>>::s_origVtable.*origMethod)(This, params...);
} }

View File

@ -78,6 +78,7 @@ namespace
void bltToWindowViaGdi(Gdi::Region* primaryRegion) void bltToWindowViaGdi(Gdi::Region* primaryRegion)
{ {
std::unique_ptr<HDC__, void(*)(HDC)> virtualScreenDc(nullptr, &Gdi::VirtualScreen::deleteDc); std::unique_ptr<HDC__, void(*)(HDC)> virtualScreenDc(nullptr, &Gdi::VirtualScreen::deleteDc);
RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds();
for (auto windowPair : Gdi::Window::getWindows()) for (auto windowPair : Gdi::Window::getWindows())
{ {
@ -110,12 +111,14 @@ namespace
} }
} }
Gdi::GdiAccessGuard gdiAccessGuard(Gdi::ACCESS_READ); Gdi::GdiAccessGuard gdiAccessGuard(Gdi::ACCESS_READ, !primaryRegion);
HWND presentationWindow = windowPair.second->getPresentationWindow(); HWND presentationWindow = windowPair.second->getPresentationWindow();
HDC dc = GetWindowDC(presentationWindow); HDC dc = GetWindowDC(presentationWindow);
RECT rect = windowPair.second->getWindowRect(); RECT rect = windowPair.second->getWindowRect();
CALL_ORIG_FUNC(BitBlt)(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, visibleRegion.offset(-rect.left, -rect.top);
virtualScreenDc.get(), rect.left, rect.top, SRCCOPY); SelectClipRgn(dc, visibleRegion);
CALL_ORIG_FUNC(BitBlt)(dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top, virtualScreenDc.get(),
rect.left - virtualScreenBounds.left, rect.top - virtualScreenBounds.top, SRCCOPY);
CALL_ORIG_FUNC(ReleaseDC)(presentationWindow, dc); CALL_ORIG_FUNC(ReleaseDC)(presentationWindow, dc);
} }
} }
@ -138,6 +141,7 @@ namespace
HDC backBufferDc = nullptr; HDC backBufferDc = nullptr;
backBuffer->GetDC(backBuffer, &backBufferDc); backBuffer->GetDC(backBuffer, &backBufferDc);
RECT ddrawMonitorRect = D3dDdi::KernelModeThunks::getMonitorRect();
for (auto it = visibleLayeredWindows.rbegin(); it != visibleLayeredWindows.rend(); ++it) for (auto it = visibleLayeredWindows.rbegin(); it != visibleLayeredWindows.rend(); ++it)
{ {
@ -145,6 +149,12 @@ namespace
HRGN rgn = Gdi::getVisibleWindowRgn(*it); HRGN rgn = Gdi::getVisibleWindowRgn(*it);
RECT wr = {}; RECT wr = {};
GetWindowRect(*it, &wr); GetWindowRect(*it, &wr);
if (0 != ddrawMonitorRect.left || 0 != ddrawMonitorRect.top)
{
OffsetRect(&wr, -ddrawMonitorRect.left, -ddrawMonitorRect.top);
OffsetRgn(rgn, -ddrawMonitorRect.left, -ddrawMonitorRect.top);
}
SelectClipRgn(backBufferDc, rgn); SelectClipRgn(backBufferDc, rgn);
CALL_ORIG_FUNC(BitBlt)(backBufferDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, CALL_ORIG_FUNC(BitBlt)(backBufferDc, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top,

View File

@ -1,12 +1,69 @@
#include "Common/CompatPtr.h"
#include "D3dDdi/KernelModeThunks.h"
#include "DDraw/DirectDrawClipper.h"
#include "DDraw/DirectDrawPalette.h" #include "DDraw/DirectDrawPalette.h"
#include "DDraw/DirectDrawSurface.h" #include "DDraw/DirectDrawSurface.h"
#include "DDraw/RealPrimarySurface.h" #include "DDraw/RealPrimarySurface.h"
#include "DDraw/Surfaces/PrimarySurface.h" #include "DDraw/Surfaces/PrimarySurface.h"
#include "DDraw/Surfaces/PrimarySurfaceImpl.h" #include "DDraw/Surfaces/PrimarySurfaceImpl.h"
#include "Dll/Procs.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Region.h"
#include "Gdi/VirtualScreen.h"
namespace namespace
{ {
template <typename TSurface>
void bltToGdi(TSurface* This, LPRECT lpDestRect, TSurface* lpDDSrcSurface, LPRECT lpSrcRect,
DWORD dwFlags, LPDDBLTFX lpDDBltFx)
{
if (!lpDestRect)
{
return;
}
CompatPtr<IDirectDrawClipper> clipper;
CompatVtable<Vtable<TSurface>>::s_origVtable.GetClipper(This, &clipper.getRef());
if (!clipper)
{
return;
}
Gdi::Region clipRgn(DDraw::DirectDrawClipper::getClipRgn(*clipper));
RECT monitorRect = D3dDdi::KernelModeThunks::getMonitorRect();
RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds();
clipRgn.offset(monitorRect.left, monitorRect.top);
clipRgn &= virtualScreenBounds;
clipRgn -= monitorRect;
if (clipRgn.isEmpty())
{
return;
}
auto gdiSurface(Gdi::VirtualScreen::createSurface(virtualScreenBounds));
if (!gdiSurface)
{
return;
}
CompatPtr<IDirectDrawClipper> gdiClipper;
CALL_ORIG_PROC(DirectDrawCreateClipper, 0, &gdiClipper.getRef(), nullptr);
if (!gdiClipper)
{
return;
}
RECT dstRect = *lpDestRect;
OffsetRect(&dstRect, monitorRect.left - virtualScreenBounds.left, monitorRect.top - virtualScreenBounds.top);
clipRgn.offset(-virtualScreenBounds.left, -virtualScreenBounds.top);
DDraw::DirectDrawClipper::setClipRgn(*gdiClipper, clipRgn);
auto srcSurface(CompatPtr<IDirectDrawSurface7>::from(lpDDSrcSurface));
gdiSurface->SetClipper(gdiSurface, gdiClipper);
gdiSurface->Blt(gdiSurface, &dstRect, srcSurface, lpSrcRect, dwFlags, lpDDBltFx);
gdiSurface->SetClipper(gdiSurface, nullptr);
}
void restorePrimaryCaps(DWORD& caps) void restorePrimaryCaps(DWORD& caps)
{ {
caps &= ~DDSCAPS_OFFSCREENPLAIN; caps &= ~DDSCAPS_OFFSCREENPLAIN;
@ -41,6 +98,7 @@ namespace DDraw
HRESULT result = m_impl.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx); HRESULT result = m_impl.Blt(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
bltToGdi(This, lpDestRect, lpDDSrcSurface, lpSrcRect, dwFlags, lpDDBltFx);
RealPrimarySurface::update(); RealPrimarySurface::update();
} }
return result; return result;

View File

@ -122,7 +122,7 @@ namespace DDraw
privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER))) privateData.get(), sizeof(privateData.get()), DDSPD_IUNKNOWNPOINTER)))
{ {
CompatPtr<IUnknown> dd; CompatPtr<IUnknown> dd;
dds->GetDDInterface(&dds, reinterpret_cast<void**>(&dd.getRef())); dds.get().lpVtbl->GetDDInterface(&dds, reinterpret_cast<void**>(&dd.getRef()));
privateData->createImpl(); privateData->createImpl();
privateData->m_impl->m_data = privateData.get(); privateData->m_impl->m_data = privateData.get();

View File

@ -39,7 +39,7 @@ namespace
Compat::Log() << "Installing registry hooks"; Compat::Log() << "Installing registry hooks";
Win32::Registry::installHooks(); Win32::Registry::installHooks();
Compat::Log() << "Installing Direct3D driver hooks"; Compat::Log() << "Installing Direct3D driver hooks";
D3dDdi::installHooks(); D3dDdi::installHooks(g_origDDrawModule);
Compat::Log() << "Installing display mode hooks"; Compat::Log() << "Installing display mode hooks";
Win32::DisplayMode::installHooks(g_origDDrawModule); Win32::DisplayMode::installHooks(g_origDDrawModule);
Gdi::VirtualScreen::init(); Gdi::VirtualScreen::init();

View File

@ -111,13 +111,15 @@ namespace
} }
} }
void setClippingRegion(const CompatDc& compatDc, std::shared_ptr<Gdi::Window> rootWindow, const POINT& origin) void setClippingRegion(const CompatDc& compatDc, std::shared_ptr<Gdi::Window> rootWindow,
const POINT& origin, const RECT& virtualScreenBounds)
{ {
if (rootWindow) if (rootWindow)
{ {
Gdi::Region sysRgn; Gdi::Region sysRgn;
CALL_ORIG_FUNC(GetRandomRgn)(compatDc.origDc, sysRgn, SYSRGN); CALL_ORIG_FUNC(GetRandomRgn)(compatDc.origDc, sysRgn, SYSRGN);
sysRgn &= rootWindow->getVisibleRegion(); sysRgn &= rootWindow->getVisibleRegion();
OffsetRgn(sysRgn, -virtualScreenBounds.left, -virtualScreenBounds.top);
SelectClipRgn(compatDc.dc, sysRgn); SelectClipRgn(compatDc.dc, sysRgn);
} }
else else
@ -206,15 +208,18 @@ namespace Gdi
POINT origin = {}; POINT origin = {};
GetDCOrgEx(origDc, &origin); GetDCOrgEx(origDc, &origin);
RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds(); RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds();
origin.x -= virtualScreenBounds.left; if (wnd && GetDesktopWindow() != wnd)
origin.y -= virtualScreenBounds.top; {
origin.x -= virtualScreenBounds.left;
origin.y -= virtualScreenBounds.top;
}
compatDc.refCount = 1; compatDc.refCount = 1;
compatDc.origDc = origDc; compatDc.origDc = origDc;
compatDc.threadId = GetCurrentThreadId(); compatDc.threadId = GetCurrentThreadId();
compatDc.savedState = useMetaRgn ? SaveDC(compatDc.dc) : 0; compatDc.savedState = useMetaRgn ? SaveDC(compatDc.dc) : 0;
copyDcAttributes(compatDc, origDc, origin); copyDcAttributes(compatDc, origDc, origin);
setClippingRegion(compatDc, rootWindow, origin); setClippingRegion(compatDc, rootWindow, origin, virtualScreenBounds);
g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc)); g_origDcToCompatDc.insert(CompatDcMap::value_type(origDc, compatDc));

View File

@ -14,6 +14,11 @@ namespace
namespace Gdi namespace Gdi
{ {
Region::Region(HRGN rgn)
: m_region(rgn)
{
}
Region::Region(const RECT& rect) Region::Region(const RECT& rect)
: m_region(CreateRectRgnIndirect(&rect)) : m_region(CreateRectRgnIndirect(&rect))
{ {

View File

@ -9,6 +9,7 @@ namespace Gdi
class Region class Region
{ {
public: public:
Region(HRGN rgn);
Region(const RECT& rect = RECT{ 0, 0, 0, 0 }); Region(const RECT& rect = RECT{ 0, 0, 0, 0 });
~Region(); ~Region();
Region(const Region& other); Region(const Region& other);

View File

@ -1,7 +1,9 @@
#include "Common/Hook.h" #include "Common/Hook.h"
#include "DDraw/Surfaces/PrimarySurface.h" #include "DDraw/Surfaces/PrimarySurface.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Region.h"
#include "Gdi/TitleBar.h" #include "Gdi/TitleBar.h"
#include "Gdi/VirtualScreen.h"
namespace namespace
{ {
@ -101,11 +103,11 @@ namespace Gdi
flags |= DC_GRADIENT; flags |= DC_GRADIENT;
} }
RECT virtualScreenBounds = VirtualScreen::getBounds();
RECT clipRect = m_tbi.rcTitleBar; RECT clipRect = m_tbi.rcTitleBar;
OffsetRect(&clipRect, m_windowRect.left, m_windowRect.top); OffsetRect(&clipRect, m_windowRect.left - virtualScreenBounds.left, m_windowRect.top - virtualScreenBounds.top);
HRGN clipRgn = CreateRectRgnIndirect(&clipRect); Region clipRgn(clipRect);
SelectClipRgn(m_compatDc, clipRgn); SelectClipRgn(m_compatDc, clipRgn);
DeleteObject(clipRgn);
RECT textRect = m_tbi.rcTitleBar; RECT textRect = m_tbi.rcTitleBar;
if (m_hasIcon) if (m_hasIcon)

View File

@ -1,8 +1,8 @@
#include <set> #include <set>
#include "DDraw/DirectDraw.h" #include "DDraw/DirectDraw.h"
#include "DDraw/Repository.h"
#include "DDraw/ScopedThreadLock.h" #include "DDraw/ScopedThreadLock.h"
#include "DDraw/Surfaces/PrimarySurface.h"
#include "Gdi/Gdi.h" #include "Gdi/Gdi.h"
#include "Gdi/Region.h" #include "Gdi/Region.h"
#include "Gdi/VirtualScreen.h" #include "Gdi/VirtualScreen.h"
@ -134,8 +134,12 @@ namespace Gdi
(rect.top - g_bounds.top) * g_pitch + (rect.top - g_bounds.top) * g_pitch +
(rect.left - g_bounds.left) * g_bpp / 8; (rect.left - g_bounds.left) * g_bpp / 8;
auto primary(DDraw::PrimarySurface::getPrimary());
CompatPtr<IUnknown> ddUnk;
primary.get()->lpVtbl->GetDDInterface(primary, reinterpret_cast<void**>(&ddUnk.getRef()));
CompatPtr<IDirectDraw7> dd(ddUnk);
CompatPtr<IDirectDrawSurface7> surface; CompatPtr<IDirectDrawSurface7> surface;
auto dd(DDraw::Repository::getDirectDraw());
dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr); dd->CreateSurface(dd, &desc, &surface.getRef(), nullptr);
return surface; return surface;
} }