mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Improved support for DPI unaware apps
This commit is contained in:
parent
a9ec2bbe7c
commit
97805b17b6
@ -12,6 +12,11 @@ struct RectF
|
||||
|
||||
namespace Rect
|
||||
{
|
||||
inline SIZE getSize(const RECT& rect)
|
||||
{
|
||||
return { rect.right - rect.left, rect.bottom - rect.top };
|
||||
}
|
||||
|
||||
RectF toRectF(const RECT& rect);
|
||||
bool isEqualSize(const RECT& rect1, const RECT& rect2);
|
||||
void transform(RECT& rect, const RECT& srcView, const RECT& dstView);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <Common/Comparison.h>
|
||||
#include <Common/CompatVtable.h>
|
||||
#include <Common/Rect.h>
|
||||
#include <Config/Settings/Antialiasing.h>
|
||||
#include <Config/Settings/DisplayAspectRatio.h>
|
||||
#include <Config/Settings/PalettizedTextures.h>
|
||||
@ -63,23 +64,23 @@ namespace D3dDdi
|
||||
{
|
||||
}
|
||||
|
||||
Int2 Adapter::getAspectRatio(Win32::DisplayMode::Resolution res) const
|
||||
Int2 Adapter::getAspectRatio(SIZE appRes, SIZE displayRes) const
|
||||
{
|
||||
SIZE ar = Config::displayAspectRatio.get();
|
||||
if (Config::Settings::DisplayAspectRatio::APP == ar)
|
||||
{
|
||||
return 0 != res.app.cx ? res.app : Win32::DisplayMode::getAppResolution(m_deviceName);
|
||||
return 0 != appRes.cx ? appRes : Rect::getSize(Win32::DisplayMode::getMonitorInfo(m_deviceName).rcEmulated);
|
||||
}
|
||||
else if (Config::Settings::DisplayAspectRatio::DISPLAY == ar)
|
||||
{
|
||||
return 0 != res.display.cx ? res.display : Win32::DisplayMode::getDisplayResolution(m_deviceName);
|
||||
return 0 != displayRes.cx ? displayRes : Rect::getSize(Win32::DisplayMode::getMonitorInfo(m_deviceName).rcReal);
|
||||
}
|
||||
return ar;
|
||||
}
|
||||
|
||||
Int2 Adapter::getAspectRatio() const
|
||||
{
|
||||
return getAspectRatio({});
|
||||
return getAspectRatio({}, {});
|
||||
}
|
||||
|
||||
const Adapter::AdapterInfo& Adapter::findInfo() const
|
||||
@ -253,20 +254,23 @@ namespace D3dDdi
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto res = Win32::DisplayMode::getResolution(m_deviceName);
|
||||
const auto& mi = Win32::DisplayMode::getMonitorInfo(m_deviceName);
|
||||
auto displayRes = Rect::getSize(mi.rcReal);
|
||||
auto appRes = Rect::getSize(mi.isEmulated ? mi.rcEmulated : mi.rcReal);
|
||||
|
||||
Int2 targetResolution = resolutionScale;
|
||||
if (Config::Settings::ResolutionScale::APP == resolutionScale)
|
||||
{
|
||||
targetResolution = res.app;
|
||||
targetResolution = appRes;
|
||||
}
|
||||
else if (Config::Settings::ResolutionScale::DISPLAY == resolutionScale)
|
||||
{
|
||||
targetResolution = res.display;
|
||||
targetResolution = displayRes;
|
||||
}
|
||||
|
||||
targetResolution *= abs(multiplier);
|
||||
|
||||
const Int2 ar = getAspectRatio(res);
|
||||
const Int2 ar = getAspectRatio(appRes, displayRes);
|
||||
if (targetResolution.y * ar.x / ar.y <= targetResolution.x)
|
||||
{
|
||||
targetResolution.x = targetResolution.y * ar.x / ar.y;
|
||||
@ -276,7 +280,7 @@ namespace D3dDdi
|
||||
targetResolution.y = targetResolution.x * ar.y / ar.x;
|
||||
}
|
||||
|
||||
const auto scaleFactor = Float2(targetResolution) / Float2(res.app);
|
||||
const auto scaleFactor = Float2(targetResolution) / Float2(appRes);
|
||||
return multiplier < 0 ? scaleFactor : ceil(scaleFactor);
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ namespace D3dDdi
|
||||
Int2 getAspectRatio() const;
|
||||
const AdapterInfo& getInfo() const { return m_info; }
|
||||
LUID getLuid() const { return m_luid; }
|
||||
const auto& getMonitorInfo() const { return Win32::DisplayMode::getMonitorInfo(m_deviceName); }
|
||||
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
|
||||
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
|
||||
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
|
||||
@ -58,7 +59,7 @@ namespace D3dDdi
|
||||
template <typename Data>
|
||||
HRESULT getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size = sizeof(Data)) const;
|
||||
|
||||
Int2 getAspectRatio(Win32::DisplayMode::Resolution res) const;
|
||||
Int2 getAspectRatio(SIZE appRes, SIZE displayRes) const;
|
||||
std::map<D3DDDIFORMAT, FORMATOP> getFixedFormatOps(const AdapterInfo& info) const;
|
||||
std::map<D3DDDIFORMAT, FORMATOP> getFormatOps() const;
|
||||
Float2 getScaleFactor() const;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <Gdi/Palette.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -310,7 +311,7 @@ namespace
|
||||
|
||||
MONITORINFOEX mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoA)(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
|
||||
|
||||
D3DKMT_OPENADAPTERFROMHDC data = {};
|
||||
data.hDc = CreateDC(mi.szDevice, mi.szDevice, nullptr, nullptr);
|
||||
@ -374,11 +375,11 @@ namespace D3dDdi
|
||||
HWND presentationWindow = DDraw::RealPrimarySurface::getPresentationWindow();
|
||||
if (presentationWindow && presentationWindow == data.hWindow)
|
||||
{
|
||||
rect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
Win32::ScopedDpiAwareness dpiAwareness;
|
||||
GetWindowRect(presentationWindow, &rect);
|
||||
OffsetRect(&rect, -rect.left, -rect.top);
|
||||
data.SrcRect = rect;
|
||||
data.DstRect.right = data.DstRect.left + rect.right;
|
||||
data.DstRect.bottom = data.DstRect.top + rect.bottom;
|
||||
data.DstRect = rect;
|
||||
if (1 == data.SubRectCnt)
|
||||
{
|
||||
data.pSrcSubRects = ▭
|
||||
|
@ -1270,10 +1270,8 @@ namespace D3dDdi
|
||||
|
||||
if (!IsRectEmpty(&g_presentationRect))
|
||||
{
|
||||
auto dstRect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
OffsetRect(&dstRect, -dstRect.left, -dstRect.top);
|
||||
presentLayeredWindows(*this, data.DstSubResourceIndex, dstRect,
|
||||
Gdi::Window::getVisibleOverlayWindows(), dstRect);
|
||||
presentLayeredWindows(*this, data.DstSubResourceIndex, getRect(data.DstSubResourceIndex),
|
||||
Gdi::Window::getVisibleOverlayWindows(), m_device.getAdapter().getMonitorInfo().rcMonitor);
|
||||
}
|
||||
|
||||
return LOG_RESULT(S_OK);
|
||||
@ -1294,7 +1292,7 @@ namespace D3dDdi
|
||||
continue;
|
||||
}
|
||||
|
||||
RECT srcRect = { 0, 0, visibleRect.right - visibleRect.left, visibleRect.bottom - visibleRect.top };
|
||||
RECT srcRect = { 0, 0, visibleRect.right - visibleRect.left + 1, visibleRect.bottom - visibleRect.top + 1 };
|
||||
auto& windowSurface = repo.getTempSysMemSurface(srcRect.right, srcRect.bottom);
|
||||
auto& texture = repo.getTempTexture(srcRect.right, srcRect.bottom, D3DDDIFMT_A8R8G8B8);
|
||||
if (!windowSurface.resource || !texture.resource)
|
||||
@ -1304,9 +1302,16 @@ namespace D3dDdi
|
||||
|
||||
HDC srcDc = GetWindowDC(layeredWindow.hwnd);
|
||||
HDC dstDc = nullptr;
|
||||
POINT srcOrig = { visibleRect.left - layeredWindow.rect.left, visibleRect.top - layeredWindow.rect.top };
|
||||
windowSurface.surface->GetDC(windowSurface.surface, &dstDc);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, 0, 0, srcRect.right, srcRect.bottom, srcDc,
|
||||
visibleRect.left - layeredWindow.rect.left, visibleRect.top - layeredWindow.rect.top, SRCCOPY);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, 0, 0, srcRect.right - 1, srcRect.bottom - 1,
|
||||
srcDc, srcOrig.x, srcOrig.y, SRCCOPY);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, srcRect.right - 1, 0, 1, srcRect.bottom - 1,
|
||||
srcDc, srcOrig.x + srcRect.right - 2, srcOrig.y, SRCCOPY);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, 0, srcRect.bottom - 1, srcRect.right - 1, 1,
|
||||
srcDc, srcOrig.x, srcOrig.y + srcRect.bottom - 2, SRCCOPY);
|
||||
CALL_ORIG_FUNC(BitBlt)(dstDc, srcRect.right - 1, srcRect.bottom - 1, 1, 1,
|
||||
srcDc, srcOrig.x + srcRect.right - 2, srcOrig.y + srcRect.bottom - 2, SRCCOPY);
|
||||
windowSurface.surface->ReleaseDC(windowSurface.surface, dstDc);
|
||||
ReleaseDC(layeredWindow.hwnd, srcDc);
|
||||
|
||||
@ -1327,8 +1332,10 @@ namespace D3dDdi
|
||||
}
|
||||
Rect::transform(visibleRect, monitorRect, dstRect);
|
||||
|
||||
blitter.textureBlt(dst, dstSubResourceIndex, visibleRect, *texture.resource, 0, srcRect, D3DTEXF_POINT,
|
||||
ck, (flags & ULW_ALPHA) ? &alpha : nullptr,
|
||||
srcRect.right--;
|
||||
srcRect.bottom--;
|
||||
blitter.textureBlt(dst, dstSubResourceIndex, visibleRect, *texture.resource, 0, srcRect,
|
||||
D3DTEXF_LINEAR | D3DTEXF_SRGB, ck, (flags & ULW_ALPHA) ? &alpha : nullptr,
|
||||
layeredWindow.region);
|
||||
}
|
||||
}
|
||||
@ -1398,14 +1405,16 @@ namespace D3dDdi
|
||||
|
||||
const Int2 ar = m_device.getAdapter().getAspectRatio();
|
||||
g_presentationRect = calculateScaledRect({ 0, 0, ar.x, ar.y }, DDraw::RealPrimarySurface::getMonitorRect());
|
||||
auto& si = m_origData.pSurfList[0];
|
||||
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };
|
||||
|
||||
Gdi::Cursor::setMonitorClipRect(DDraw::PrimarySurface::getMonitorRect());
|
||||
if (!EqualRect(&g_presentationRect, &primaryRect))
|
||||
const auto& mi = m_device.getAdapter().getMonitorInfo();
|
||||
auto clipRect = mi.rcEmulated;
|
||||
if (!EqualRect(&mi.rcMonitor, &mi.rcReal))
|
||||
{
|
||||
Gdi::Cursor::setEmulated(true);
|
||||
InflateRect(&clipRect, -1, -1);
|
||||
}
|
||||
|
||||
Gdi::Cursor::setMonitorClipRect(clipRect);
|
||||
Gdi::Cursor::setEmulated(mi.isEmulated);
|
||||
Gdi::VirtualScreen::setFullscreenMode(m_origData.Flags.MatchGdiPrimary);
|
||||
}
|
||||
else
|
||||
|
@ -180,14 +180,6 @@ namespace DDraw
|
||||
{
|
||||
namespace DirectDraw
|
||||
{
|
||||
DDSURFACEDESC2 getDisplayMode(CompatRef<IDirectDraw7> dd)
|
||||
{
|
||||
DDSURFACEDESC2 dm = {};
|
||||
dm.dwSize = sizeof(dm);
|
||||
dd->GetDisplayMode(&dd, &dm);
|
||||
return dm;
|
||||
}
|
||||
|
||||
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp)
|
||||
{
|
||||
DDPIXELFORMAT pf = {};
|
||||
|
@ -12,7 +12,6 @@ namespace DDraw
|
||||
{
|
||||
namespace DirectDraw
|
||||
{
|
||||
DDSURFACEDESC2 getDisplayMode(CompatRef<IDirectDraw7> dd);
|
||||
DDPIXELFORMAT getRgbPixelFormat(DWORD bpp);
|
||||
LRESULT handleActivateApp(bool isActivated, std::function<LRESULT()> callOrigWndProc);
|
||||
void onCreate(GUID* guid, CompatRef<IDirectDraw7> dd);
|
||||
|
@ -5,8 +5,8 @@
|
||||
#include <Common/CompatVtable.h>
|
||||
#include <D3dDdi/KernelModeThunks.h>
|
||||
#include <DDraw/DirectDrawClipper.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/ScopedThreadLock.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <DDraw/Surfaces/Surface.h>
|
||||
#include <DDraw/Visitors/DirectDrawClipperVtblVisitor.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
@ -46,7 +46,7 @@ namespace
|
||||
GetRandomRgn(dc, rgn, SYSRGN);
|
||||
CALL_ORIG_FUNC(ReleaseDC)(data.hwnd, dc);
|
||||
|
||||
RECT primaryRect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
RECT primaryRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
if (0 != primaryRect.left || 0 != primaryRect.top)
|
||||
{
|
||||
rgn.offset(-primaryRect.left, -primaryRect.top);
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#include <Common/Comparison.h>
|
||||
#include <Common/CompatPtr.h>
|
||||
#include <Common/Hook.h>
|
||||
@ -8,6 +11,7 @@
|
||||
#include <Common/ScopedThreadPriority.h>
|
||||
#include <Common/Time.h>
|
||||
#include <Config/Settings/FpsLimiter.h>
|
||||
#include <Config/Settings/FullscreenMode.h>
|
||||
#include <Config/Settings/VSync.h>
|
||||
#include <D3dDdi/Device.h>
|
||||
#include <D3dDdi/KernelModeThunks.h>
|
||||
@ -35,6 +39,7 @@
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
#include <Win32/Thread.h>
|
||||
|
||||
namespace
|
||||
@ -54,6 +59,7 @@ namespace
|
||||
DDraw::IReleaseNotifier g_releaseNotifier(onRelease);
|
||||
|
||||
bool g_isFullscreen = false;
|
||||
bool g_isExclusiveFullscreen = false;
|
||||
DDraw::Surface* g_lastFlipSurface = nullptr;
|
||||
DDraw::TagSurface* g_tagSurface = nullptr;
|
||||
|
||||
@ -82,6 +88,9 @@ namespace
|
||||
{
|
||||
if (!g_isFullscreen)
|
||||
{
|
||||
updatePresentationWindow();
|
||||
|
||||
if (g_presentationWindow)
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto srcResource = D3dDdi::Device::findResource(
|
||||
@ -99,8 +108,7 @@ namespace
|
||||
bbResource->presentationBlt(blt, srcResource);
|
||||
}
|
||||
|
||||
updatePresentationWindow();
|
||||
Gdi::Window::present(*g_frontBuffer, *g_windowedBackBuffer, *g_clipper);
|
||||
Gdi::Window::present(*g_frontBuffer, g_presentationWindow ? *g_windowedBackBuffer : src, *g_clipper);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -172,7 +180,7 @@ namespace
|
||||
DDraw::RealPrimarySurface::destroyDefaultPrimary();
|
||||
|
||||
auto dm = Win32::DisplayMode::getEmulatedDisplayMode();
|
||||
if (0 == dm.diff.cx && 0 == dm.diff.cy)
|
||||
if (dm.deviceName.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -373,7 +381,7 @@ namespace
|
||||
Input::updateCursor();
|
||||
});
|
||||
|
||||
if (!g_frontBuffer || !src || DDraw::RealPrimarySurface::isLost() || FAILED(src->IsLost(src)))
|
||||
if (!g_frontBuffer || !src || DDraw::RealPrimarySurface::isLost())
|
||||
{
|
||||
Gdi::Window::present(nullptr);
|
||||
return;
|
||||
@ -409,49 +417,67 @@ namespace
|
||||
{
|
||||
LOG_FUNC("RealPrimarySurface::updatePresentationWindow");
|
||||
|
||||
const bool isActive = isProcessActive();
|
||||
HWND fullscreenWindow = nullptr;
|
||||
if (g_isFullscreen && IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
||||
if (isProcessActive())
|
||||
{
|
||||
fullscreenWindow = g_deviceWindow;
|
||||
if (g_isFullscreen && IsWindowVisible(g_deviceWindow) && !IsIconic(g_deviceWindow))
|
||||
{
|
||||
if (g_isExclusiveFullscreen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
fullscreenWindow = g_deviceWindow;
|
||||
}
|
||||
else if (g_frontBuffer && DDraw::PrimarySurface::getPrimary() && SUCCEEDED(g_frontBuffer->IsLost(g_frontBuffer)))
|
||||
{
|
||||
fullscreenWindow = Gdi::Window::getFullscreenWindow();
|
||||
}
|
||||
}
|
||||
else if (g_frontBuffer && DDraw::PrimarySurface::getPrimary() && SUCCEEDED(g_frontBuffer->IsLost(g_frontBuffer)))
|
||||
else if (g_isFullscreen)
|
||||
{
|
||||
fullscreenWindow = Gdi::Window::getFullscreenWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
fullscreenWindow = fullscreenWindow ? Gdi::Window::getPresentationWindow(fullscreenWindow) : nullptr;
|
||||
HWND fullscreenPresentationWindow = nullptr;
|
||||
if (fullscreenWindow)
|
||||
{
|
||||
Gdi::Window::setDpiAwareness(fullscreenWindow, true);
|
||||
fullscreenPresentationWindow = Gdi::Window::getPresentationWindow(fullscreenWindow);
|
||||
}
|
||||
|
||||
if (g_windowedBackBuffer)
|
||||
{
|
||||
auto resource = D3dDdi::Device::findResource(
|
||||
DDraw::DirectDrawSurface::getDriverResourceHandle(*g_windowedBackBuffer));
|
||||
resource->setFullscreenMode(isActive && fullscreenWindow);
|
||||
resource->setFullscreenMode(fullscreenPresentationWindow);
|
||||
}
|
||||
|
||||
if (!isActive)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
g_presentationWindow = fullscreenWindow;
|
||||
g_presentationWindow = fullscreenPresentationWindow;
|
||||
|
||||
if (g_presentationWindow)
|
||||
{
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_presentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top,
|
||||
Win32::ScopedDpiAwareness dpiAwareness;
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_presentationWindow, HWND_TOPMOST, g_monitorRect.left, g_monitorRect.top, 0, 0,
|
||||
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOSIZE);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(g_presentationWindow, nullptr, 0, 0,
|
||||
g_monitorRect.right - g_monitorRect.left, g_monitorRect.bottom - g_monitorRect.top,
|
||||
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
|
||||
SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE);
|
||||
});
|
||||
}
|
||||
|
||||
static HWND prevPresentationWindow = nullptr;
|
||||
if (prevPresentationWindow && prevPresentationWindow != g_presentationWindow)
|
||||
static HWND prevFullscreenWindow = nullptr;
|
||||
if (prevFullscreenWindow && prevFullscreenWindow != fullscreenWindow)
|
||||
{
|
||||
Gdi::Window::updatePresentationWindowPos(prevPresentationWindow, GetParent(prevPresentationWindow));
|
||||
Gdi::Window::setDpiAwareness(prevFullscreenWindow, false);
|
||||
HWND prevFullscreenPresentationWindow = Gdi::Window::getPresentationWindow(prevFullscreenWindow);
|
||||
if (prevFullscreenPresentationWindow)
|
||||
{
|
||||
Gdi::Window::updatePresentationWindowPos(prevFullscreenPresentationWindow, prevFullscreenWindow);
|
||||
}
|
||||
}
|
||||
prevPresentationWindow = g_presentationWindow;
|
||||
prevFullscreenWindow = fullscreenWindow;
|
||||
}
|
||||
|
||||
unsigned WINAPI updateThreadProc(LPVOID /*lpParameter*/)
|
||||
@ -481,9 +507,10 @@ namespace DDraw
|
||||
{
|
||||
LOG_FUNC("RealPrimarySurface::create", &dd);
|
||||
DDraw::ScopedThreadLock lock;
|
||||
const auto& mi = Win32::DisplayMode::getMonitorInfo(
|
||||
D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr<IDirectDraw7>::from(&dd)).deviceName);
|
||||
auto prevMonitorRect = g_monitorRect;
|
||||
g_monitorRect = Win32::DisplayMode::getMonitorInfo(
|
||||
D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr<IDirectDraw7>::from(&dd)).deviceName).rcMonitor;
|
||||
g_monitorRect = g_isExclusiveFullscreen ? mi.rcReal : mi.rcDpiAware;
|
||||
|
||||
DDSURFACEDESC desc = {};
|
||||
desc.dwSize = sizeof(desc);
|
||||
@ -499,6 +526,7 @@ namespace DDraw
|
||||
if (DDERR_NOEXCLUSIVEMODE == result)
|
||||
{
|
||||
g_isFullscreen = false;
|
||||
g_monitorRect = mi.rcDpiAware;
|
||||
desc.dwFlags = DDSD_CAPS;
|
||||
desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||||
desc.dwBackBufferCount = 0;
|
||||
@ -603,6 +631,7 @@ namespace DDraw
|
||||
static UINT lastOverlayCheckVsyncCount = 0;
|
||||
if (vsyncCount != lastOverlayCheckVsyncCount)
|
||||
{
|
||||
setPresentationWindowTopmost();
|
||||
Gdi::Cursor::update();
|
||||
Gdi::Caret::blink();
|
||||
auto statsWindow = Gdi::GuiThread::getStatsWindow();
|
||||
@ -676,13 +705,9 @@ namespace DDraw
|
||||
|
||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||
CompatWeakPtr<IDirectDrawSurface7> src;
|
||||
if (g_isDelayedFlipPending)
|
||||
if (primary && SUCCEEDED(primary->IsLost(primary)))
|
||||
{
|
||||
src = g_lastFlipSurface->getDDS();
|
||||
}
|
||||
else if (primary && SUCCEEDED(primary->IsLost(primary)))
|
||||
{
|
||||
src = primary;
|
||||
src = g_isDelayedFlipPending ? g_lastFlipSurface->getDDS() : primary;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -734,6 +759,8 @@ namespace DDraw
|
||||
|
||||
void RealPrimarySurface::init()
|
||||
{
|
||||
g_isExclusiveFullscreen = Config::Settings::FullscreenMode::EXCLUSIVE == Config::fullscreenMode.get() ||
|
||||
!IsWindows8OrGreater();
|
||||
Dll::createThread(&updateThreadProc, nullptr, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
}
|
||||
|
||||
|
@ -92,12 +92,10 @@ namespace DDraw
|
||||
LOG_FUNC("PrimarySurface::create", &dd, desc, surface);
|
||||
DDraw::RealPrimarySurface::destroyDefaultPrimary();
|
||||
|
||||
const auto& dm = DDraw::DirectDraw::getDisplayMode(*CompatPtr<IDirectDraw7>::from(&dd));
|
||||
auto deviceName = D3dDdi::KernelModeThunks::getAdapterInfo(*CompatPtr<IDirectDraw7>::from(&dd)).deviceName;
|
||||
const auto& mi = Win32::DisplayMode::getMonitorInfo(deviceName);
|
||||
auto prevMonitorRect = g_monitorRect;
|
||||
g_monitorRect = Win32::DisplayMode::getMonitorInfo(deviceName).rcMonitor;
|
||||
g_monitorRect.right = g_monitorRect.left + dm.dwWidth;
|
||||
g_monitorRect.bottom = g_monitorRect.top + dm.dwHeight;
|
||||
g_monitorRect = mi.rcEmulated;
|
||||
|
||||
HRESULT result = RealPrimarySurface::create(*CompatPtr<IDirectDraw>::from(&dd));
|
||||
if (FAILED(result))
|
||||
@ -111,12 +109,12 @@ namespace DDraw
|
||||
auto data = privateData.get();
|
||||
|
||||
desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
|
||||
desc.dwWidth = dm.dwWidth;
|
||||
desc.dwHeight = dm.dwHeight;
|
||||
desc.dwWidth = g_monitorRect.right - g_monitorRect.left;
|
||||
desc.dwHeight = g_monitorRect.bottom - g_monitorRect.top;
|
||||
desc.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
|
||||
DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
|
||||
desc.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
||||
desc.ddpfPixelFormat = dm.ddpfPixelFormat;
|
||||
desc.ddpfPixelFormat = DirectDraw::getRgbPixelFormat(mi.bpp);
|
||||
|
||||
result = Surface::create(dd, desc, surface, std::move(privateData));
|
||||
if (FAILED(result))
|
||||
|
@ -35,7 +35,7 @@ namespace
|
||||
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
Gdi::Region clipRgn(DDraw::DirectDrawClipper::getClipRgn(*clipper));
|
||||
RECT monitorRect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
RECT monitorRect = DDraw::PrimarySurface::getMonitorRect();
|
||||
RECT virtualScreenBounds = Gdi::VirtualScreen::getBounds();
|
||||
clipRgn.offset(monitorRect.left, monitorRect.top);
|
||||
clipRgn &= virtualScreenBounds;
|
||||
|
@ -327,6 +327,7 @@
|
||||
<ClInclude Include="Overlay\StatsWindow.h" />
|
||||
<ClInclude Include="Overlay\Window.h" />
|
||||
<ClInclude Include="Win32\DisplayMode.h" />
|
||||
<ClInclude Include="Win32\DpiAwareness.h" />
|
||||
<ClInclude Include="Win32\Log.h" />
|
||||
<ClInclude Include="Win32\MemoryManagement.h" />
|
||||
<ClInclude Include="Win32\Registry.h" />
|
||||
@ -460,6 +461,7 @@
|
||||
<ClCompile Include="Overlay\StatsWindow.cpp" />
|
||||
<ClCompile Include="Overlay\Window.cpp" />
|
||||
<ClCompile Include="Win32\DisplayMode.cpp" />
|
||||
<ClCompile Include="Win32\DpiAwareness.cpp" />
|
||||
<ClCompile Include="Win32\Log.cpp" />
|
||||
<ClCompile Include="Win32\MemoryManagement.cpp" />
|
||||
<ClCompile Include="Win32\Registry.cpp" />
|
||||
|
@ -705,6 +705,9 @@
|
||||
<ClInclude Include="Config\Settings\CrashDump.h">
|
||||
<Filter>Header Files\Config\Settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Win32\DpiAwareness.h">
|
||||
<Filter>Header Files\Win32</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Gdi\Gdi.cpp">
|
||||
@ -1100,6 +1103,9 @@
|
||||
<ClCompile Include="Config\Settings\ConfigRows.cpp">
|
||||
<Filter>Source Files\Config\Settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Win32\DpiAwareness.cpp">
|
||||
<Filter>Source Files\Win32</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="DDrawCompat.rc">
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
#include <Win32/MemoryManagement.h>
|
||||
#include <Win32/Registry.h>
|
||||
#include <Win32/Thread.h>
|
||||
@ -149,12 +150,6 @@ namespace
|
||||
(!Compat::isEqual(currentDllPath, dciman32DllPath) && GetModuleHandleW(dciman32DllPath.c_str()));
|
||||
}
|
||||
|
||||
void logDpiAwareness(bool isSuccessful, DPI_AWARENESS_CONTEXT dpiAwareness, const char* funcName)
|
||||
{
|
||||
LOG_INFO << (isSuccessful ? "DPI awareness was successfully changed" : "Failed to change process DPI awareness")
|
||||
<< " to \"" << Config::dpiAwareness.convertToString(dpiAwareness) << "\" via " << funcName;
|
||||
}
|
||||
|
||||
void onDirectDrawCreate(GUID* lpGUID, LPDIRECTDRAW* lplpDD, IUnknown* /*pUnkOuter*/)
|
||||
{
|
||||
return DDraw::DirectDraw::onCreate(lpGUID, *CompatPtr<IDirectDraw7>::from(*lplpDD));
|
||||
@ -180,71 +175,6 @@ namespace
|
||||
return LOG_RESULT(CALL_ORIG_PROC(SetAppCompatData)(param1, param2));
|
||||
}
|
||||
|
||||
void setDpiAwareness()
|
||||
{
|
||||
auto dpiAwareness = Config::dpiAwareness.get();
|
||||
if (!dpiAwareness)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HMODULE user32 = LoadLibrary("user32");
|
||||
auto isValidDpiAwarenessContext = reinterpret_cast<decltype(&IsValidDpiAwarenessContext)>(
|
||||
Compat::getProcAddress(user32, "IsValidDpiAwarenessContext"));
|
||||
auto setProcessDpiAwarenessContext = reinterpret_cast<decltype(&SetProcessDpiAwarenessContext)>(
|
||||
Compat::getProcAddress(user32, "SetProcessDpiAwarenessContext"));
|
||||
if (isValidDpiAwarenessContext && setProcessDpiAwarenessContext)
|
||||
{
|
||||
if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness &&
|
||||
!isValidDpiAwarenessContext(dpiAwareness))
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
}
|
||||
|
||||
if (DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness &&
|
||||
!isValidDpiAwarenessContext(dpiAwareness))
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
|
||||
logDpiAwareness(setProcessDpiAwarenessContext(dpiAwareness), dpiAwareness, "SetProcessDpiAwarenessContext");
|
||||
return;
|
||||
}
|
||||
|
||||
auto setProcessDpiAwareness = reinterpret_cast<decltype(&SetProcessDpiAwareness)>(
|
||||
Compat::getProcAddress(LoadLibrary("shcore"), "SetProcessDpiAwareness"));
|
||||
if (setProcessDpiAwareness)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE == dpiAwareness ||
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness)
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
result = setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
}
|
||||
else if (DPI_AWARENESS_CONTEXT_SYSTEM_AWARE == dpiAwareness)
|
||||
{
|
||||
result = setProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
result = setProcessDpiAwareness(PROCESS_DPI_UNAWARE);
|
||||
}
|
||||
|
||||
logDpiAwareness(SUCCEEDED(result), dpiAwareness, "SetProcessDpiAwareness");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DPI_AWARENESS_CONTEXT_UNAWARE == dpiAwareness ||
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness)
|
||||
{
|
||||
LOG_INFO << "DPI awareness was not changed";
|
||||
}
|
||||
|
||||
logDpiAwareness(SetProcessDPIAware(), DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, "SetProcessDPIAware");
|
||||
}
|
||||
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER WINAPI setUnhandledExceptionFilter(LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter)
|
||||
{
|
||||
LOG_FUNC("SetUnhandledExceptionFilter", Compat::funcPtrToStr(lpTopLevelExceptionFilter));
|
||||
@ -407,7 +337,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
Compat::closeDbgEng();
|
||||
|
||||
CALL_ORIG_FUNC(timeBeginPeriod)(1);
|
||||
setDpiAwareness();
|
||||
Win32::DpiAwareness::init();
|
||||
SetThemeAppProperties(0);
|
||||
Time::init();
|
||||
Win32::Thread::applyConfig();
|
||||
|
@ -192,7 +192,7 @@ namespace Gdi
|
||||
|
||||
POINT pos = {};
|
||||
CALL_ORIG_FUNC(GetCursorPos)(&pos);
|
||||
SetCursorPos(pos.x, pos.y);
|
||||
CALL_ORIG_FUNC(SetCursorPos)(pos.x, pos.y);
|
||||
}
|
||||
|
||||
void setMonitorClipRect(const RECT& rect)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -105,8 +106,8 @@ namespace Gdi
|
||||
{
|
||||
namespace GuiThread
|
||||
{
|
||||
HWND createWindow(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
|
||||
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
|
||||
HWND createWindow(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y,
|
||||
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, bool dpiAware)
|
||||
{
|
||||
// Workaround for ForceSimpleWindow shim
|
||||
static auto createWindowExW = reinterpret_cast<decltype(&CreateWindowExW)>(
|
||||
@ -115,6 +116,7 @@ namespace Gdi
|
||||
HWND hwnd = nullptr;
|
||||
execute([&]()
|
||||
{
|
||||
Win32::ScopedDpiAwareness dpiAwareness(dpiAware);
|
||||
hwnd = createWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight,
|
||||
hWndParent, hMenu, hInstance, lpParam);
|
||||
});
|
||||
|
@ -16,8 +16,8 @@ namespace Gdi
|
||||
{
|
||||
namespace GuiThread
|
||||
{
|
||||
HWND createWindow(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
|
||||
int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
|
||||
HWND createWindow(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y,
|
||||
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam, bool dpiAware);
|
||||
void deleteTaskbarTab(HWND hwnd);
|
||||
void destroyWindow(HWND hwnd);
|
||||
void setWindowRgn(HWND hwnd, Gdi::Region rgn);
|
||||
|
@ -12,11 +12,10 @@ namespace
|
||||
int getAdjustedDisplayMetrics(int nIndex, int cxIndex)
|
||||
{
|
||||
int result = CALL_ORIG_FUNC(GetSystemMetrics)(nIndex);
|
||||
auto dm = Win32::DisplayMode::getEmulatedDisplayMode();
|
||||
if (0 == dm.rect.left && 0 == dm.rect.top)
|
||||
{
|
||||
result += (nIndex == cxIndex) ? dm.diff.cx : dm.diff.cy;
|
||||
}
|
||||
auto mi = Win32::DisplayMode::getMonitorInfo();
|
||||
result += (nIndex == cxIndex)
|
||||
? (mi.rcEmulated.right - mi.rcMonitor.right)
|
||||
: (mi.rcEmulated.bottom - mi.rcMonitor.bottom);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,9 @@ namespace Gdi
|
||||
{
|
||||
namespace PresentationWindow
|
||||
{
|
||||
HWND create(HWND owner)
|
||||
HWND create(HWND owner, bool dpiAware)
|
||||
{
|
||||
LOG_FUNC("PresentationWindow::create", owner);
|
||||
LOG_FUNC("PresentationWindow::create", owner, dpiAware);
|
||||
HWND presentationWindow = nullptr;
|
||||
GuiThread::execute([&]()
|
||||
{
|
||||
@ -34,7 +34,8 @@ namespace Gdi
|
||||
owner,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
nullptr,
|
||||
dpiAware);
|
||||
|
||||
if (presentationWindow)
|
||||
{
|
||||
|
@ -6,7 +6,7 @@ namespace Gdi
|
||||
{
|
||||
namespace PresentationWindow
|
||||
{
|
||||
HWND create(HWND owner);
|
||||
HWND create(HWND owner, bool dpiAware = false);
|
||||
|
||||
void installHooks();
|
||||
}
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <DDraw/ScopedThreadLock.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/Gdi.h>
|
||||
#include <Gdi/Region.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Gdi/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
@ -24,7 +23,6 @@ namespace
|
||||
};
|
||||
|
||||
Compat::CriticalSection g_cs;
|
||||
Gdi::Region g_region;
|
||||
RECT g_bounds = {};
|
||||
DWORD g_bpp = 0;
|
||||
LONG g_width = 0;
|
||||
@ -39,27 +37,6 @@ namespace
|
||||
RGBQUAD g_systemPalette[256] = {};
|
||||
std::map<HDC, VirtualScreenDc> g_dcs;
|
||||
|
||||
BOOL CALLBACK addMonitorRectToRegion(
|
||||
HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT lprcMonitor, LPARAM dwData)
|
||||
{
|
||||
MONITORINFOEXW mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, &mi);
|
||||
|
||||
auto res = Win32::DisplayMode::getDisplayResolution(mi.szDevice);
|
||||
RECT rect = *lprcMonitor;
|
||||
if (0 != res.cx && 0 != res.cy)
|
||||
{
|
||||
rect.right = rect.left + res.cx;
|
||||
rect.bottom = rect.top + res.cy;
|
||||
}
|
||||
|
||||
Gdi::Region& virtualScreenRegion = *reinterpret_cast<Gdi::Region*>(dwData);
|
||||
Gdi::Region monitorRegion(rect);
|
||||
virtualScreenRegion |= monitorRegion;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
RGBQUAD convertToRgbQuad(PALETTEENTRY entry)
|
||||
{
|
||||
RGBQUAD quad = {};
|
||||
@ -199,12 +176,6 @@ namespace Gdi
|
||||
return g_bounds;
|
||||
}
|
||||
|
||||
Region getRegion()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_region;
|
||||
}
|
||||
|
||||
DDSURFACEDESC2 getSurfaceDesc(const RECT& rect)
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
@ -278,13 +249,14 @@ namespace Gdi
|
||||
if (g_isFullscreen)
|
||||
{
|
||||
g_bounds = DDraw::PrimarySurface::getMonitorRect();
|
||||
g_region = g_bounds;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_region.clear();
|
||||
EnumDisplayMonitors(nullptr, nullptr, addMonitorRectToRegion, reinterpret_cast<LPARAM>(&g_region));
|
||||
GetRgnBox(g_region, &g_bounds);
|
||||
g_bounds = {};
|
||||
for (const auto& mi : Win32::DisplayMode::getAllMonitorInfo())
|
||||
{
|
||||
UnionRect(&g_bounds, &g_bounds, &mi.second.rcMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
g_bpp = Win32::DisplayMode::getBpp();
|
||||
|
@ -17,7 +17,6 @@ namespace Gdi
|
||||
void deleteDc(HDC dc);
|
||||
|
||||
RECT getBounds();
|
||||
Region getRegion();
|
||||
DDSURFACEDESC2 getSurfaceDesc(const RECT& rect);
|
||||
|
||||
void init();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -51,7 +52,6 @@ namespace
|
||||
};
|
||||
|
||||
decltype(&DwmSetIconicThumbnail) g_dwmSetIconicThumbnail = nullptr;
|
||||
decltype(&SetThreadDpiAwarenessContext) g_setThreadDpiAwarenessContext = nullptr;
|
||||
|
||||
wchar_t g_dummyWindowText;
|
||||
std::map<HMENU, UINT> g_menuMaxHeight;
|
||||
@ -327,19 +327,8 @@ namespace
|
||||
DeleteDC(dstDc);
|
||||
ReleaseDC(presentationWindow, srcDc);
|
||||
|
||||
DPI_AWARENESS_CONTEXT prevContext = nullptr;
|
||||
if (g_setThreadDpiAwarenessContext)
|
||||
{
|
||||
prevContext = g_setThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
|
||||
}
|
||||
|
||||
Win32::ScopedDpiAwareness dpiAwareness;
|
||||
g_dwmSetIconicThumbnail(hwnd, bmp, 0);
|
||||
|
||||
if (prevContext)
|
||||
{
|
||||
g_setThreadDpiAwarenessContext(prevContext);
|
||||
}
|
||||
|
||||
DeleteObject(bmp);
|
||||
}
|
||||
|
||||
@ -370,6 +359,11 @@ namespace
|
||||
return getMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax, CALL_ORIG_FUNC(GetMessageW));
|
||||
}
|
||||
|
||||
int WINAPI getRandomRgn(HDC hdc, HRGN hrgn, INT i)
|
||||
{
|
||||
return Gdi::Window::getRandomRgn(hdc, hrgn, i);
|
||||
}
|
||||
|
||||
LONG getWindowLong(HWND hWnd, int nIndex,
|
||||
decltype(&GetWindowLongA) origGetWindowLong, WNDPROC(WindowProc::* wndProc))
|
||||
{
|
||||
@ -441,24 +435,22 @@ namespace
|
||||
return;
|
||||
}
|
||||
|
||||
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||
auto mi = Win32::DisplayMode::getMonitorInfo(hwnd);
|
||||
|
||||
MONITORINFO origMi = {};
|
||||
origMi.cbSize = sizeof(origMi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoA)(monitor, &origMi);
|
||||
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfoA(monitor, &mi);
|
||||
|
||||
if (!EqualRect(&origMi.rcMonitor, &mi.rcMonitor))
|
||||
if (!EqualRect(&mi.rcEmulated, &mi.rcMonitor))
|
||||
{
|
||||
RECT wr = {};
|
||||
GetWindowRect(hwnd, &wr);
|
||||
const LONG width = wr.right - wr.left;
|
||||
const LONG height = wr.bottom - wr.top;
|
||||
|
||||
const RECT& mr = 0 == g_inMessageBox ? mi.rcWork : mi.rcMonitor;
|
||||
if (0 == g_inMessageBox)
|
||||
{
|
||||
mi.rcWork.right = mi.rcWork.left + mi.rcEmulated.right - mi.rcEmulated.left;
|
||||
mi.rcWork.bottom = mi.rcWork.top + mi.rcEmulated.bottom - mi.rcEmulated.top;
|
||||
}
|
||||
|
||||
const RECT& mr = 0 == g_inMessageBox ? mi.rcWork : mi.rcEmulated;
|
||||
const LONG left = (mr.left + mr.right - width) / 2;
|
||||
const LONG top = (mr.top + mr.bottom - height) / 2;
|
||||
|
||||
@ -506,11 +498,9 @@ namespace
|
||||
|
||||
void onGetMinMaxInfo(MINMAXINFO& mmi)
|
||||
{
|
||||
MONITORINFOEXA mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfoA(MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY), &mi);
|
||||
mmi.ptMaxSize.x = mi.rcMonitor.right - 2 * mmi.ptMaxPosition.x;
|
||||
mmi.ptMaxSize.y = mi.rcMonitor.bottom - 2 * mmi.ptMaxPosition.y;
|
||||
const auto& mi = Win32::DisplayMode::getMonitorInfo();
|
||||
mmi.ptMaxSize.x = mi.rcEmulated.right - 2 * mmi.ptMaxPosition.x;
|
||||
mmi.ptMaxSize.y = mi.rcEmulated.bottom - 2 * mmi.ptMaxPosition.y;
|
||||
}
|
||||
|
||||
void onInitMenuPopup(HMENU menu)
|
||||
@ -861,6 +851,7 @@ namespace Gdi
|
||||
HOOK_FUNCTION(user32, GetCursorPos, getCursorPos);
|
||||
HOOK_FUNCTION(user32, GetMessageA, getMessageA);
|
||||
HOOK_FUNCTION(user32, GetMessageW, getMessageW);
|
||||
HOOK_FUNCTION(gdi32, GetRandomRgn, getRandomRgn);
|
||||
HOOK_FUNCTION(user32, GetWindowLongA, getWindowLongA);
|
||||
HOOK_FUNCTION(user32, GetWindowLongW, getWindowLongW);
|
||||
HOOK_FUNCTION(user32, MessageBoxA, messageBox<MessageBoxA>);
|
||||
@ -878,8 +869,6 @@ namespace Gdi
|
||||
|
||||
g_dwmSetIconicThumbnail = reinterpret_cast<decltype(&DwmSetIconicThumbnail)>(
|
||||
GetProcAddress(GetModuleHandle("dwmapi"), "DwmSetIconicThumbnail"));
|
||||
g_setThreadDpiAwarenessContext = reinterpret_cast<decltype(&SetThreadDpiAwarenessContext)>(
|
||||
GetProcAddress(GetModuleHandle("user32"), "SetThreadDpiAwarenessContext"));
|
||||
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "SetWindowLongA", ddrawSetWindowLongA);
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/StatsWindow.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -35,28 +37,24 @@ namespace
|
||||
HWND presentationWindow;
|
||||
RECT windowRect;
|
||||
RECT clientRect;
|
||||
Gdi::Region windowRegion;
|
||||
Gdi::Region visibleRegion;
|
||||
Gdi::Region invalidatedRegion;
|
||||
bool isMenu;
|
||||
bool isLayered;
|
||||
bool isVisibleRegionChanged;
|
||||
bool isDpiAware;
|
||||
|
||||
Window(HWND hwnd)
|
||||
: hwnd(hwnd)
|
||||
, presentationWindow(nullptr)
|
||||
, windowRect{}
|
||||
, clientRect{}
|
||||
, windowRegion(nullptr)
|
||||
, isMenu(Gdi::MENU_ATOM == GetClassLong(hwnd, GCW_ATOM))
|
||||
, isLayered(true)
|
||||
, isVisibleRegionChanged(false)
|
||||
, isDpiAware(false)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
const RECT REGION_OVERRIDE_MARKER_RECT = { 32000, 32000, 32001, 32001 };
|
||||
|
||||
std::map<HWND, Window> g_windows;
|
||||
std::vector<Window*> g_windowZOrder;
|
||||
|
||||
@ -92,16 +90,6 @@ namespace
|
||||
return true;
|
||||
}
|
||||
|
||||
Gdi::Region getWindowRegion(HWND hwnd)
|
||||
{
|
||||
Gdi::Region rgn;
|
||||
if (ERROR == CALL_ORIG_FUNC(GetWindowRgn)(hwnd, rgn))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return rgn;
|
||||
}
|
||||
|
||||
void presentLayeredWindow(CompatWeakPtr<IDirectDrawSurface7> dst,
|
||||
HWND hwnd, RECT wr, const RECT& monitorRect, HDC& dstDc, Gdi::Region* rgn = nullptr, bool isMenu = false)
|
||||
{
|
||||
@ -261,17 +249,14 @@ namespace
|
||||
const LONG exStyle = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_EXSTYLE);
|
||||
const bool isLayered = it->second.isMenu || (exStyle & WS_EX_LAYERED);
|
||||
const bool isVisible = IsWindowVisible(hwnd) && !IsIconic(hwnd);
|
||||
bool setPresentationWindowRgn = false;
|
||||
|
||||
if (isLayered != it->second.isLayered)
|
||||
{
|
||||
it->second.isLayered = isLayered;
|
||||
it->second.isVisibleRegionChanged = isVisible;
|
||||
if (!isLayered)
|
||||
{
|
||||
it->second.presentationWindow = Gdi::PresentationWindow::create(hwnd);
|
||||
Gdi::WinProc::updatePresentationWindowText(hwnd);
|
||||
setPresentationWindowRgn = true;
|
||||
}
|
||||
else if (it->second.presentationWindow)
|
||||
{
|
||||
@ -280,14 +265,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
Gdi::Region windowRegion(getWindowRegion(hwnd));
|
||||
if (windowRegion && !PtInRegion(windowRegion, REGION_OVERRIDE_MARKER_RECT.left, REGION_OVERRIDE_MARKER_RECT.top) ||
|
||||
!windowRegion && it->second.windowRegion)
|
||||
{
|
||||
swap(it->second.windowRegion, windowRegion);
|
||||
setPresentationWindowRgn = true;
|
||||
}
|
||||
|
||||
WINDOWINFO wi = {};
|
||||
Gdi::Region visibleRegion;
|
||||
|
||||
@ -297,15 +274,24 @@ namespace
|
||||
GetWindowInfo(hwnd, &wi);
|
||||
if (!IsRectEmpty(&wi.rcWindow))
|
||||
{
|
||||
if (it->second.windowRegion)
|
||||
if (isLayered)
|
||||
{
|
||||
visibleRegion = it->second.windowRegion;
|
||||
visibleRegion.offset(wi.rcWindow.left, wi.rcWindow.top);
|
||||
if (ERROR != GetWindowRgn(hwnd, visibleRegion))
|
||||
{
|
||||
visibleRegion.offset(wi.rcWindow.left, wi.rcWindow.top);
|
||||
}
|
||||
else
|
||||
{
|
||||
visibleRegion = wi.rcWindow;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visibleRegion = wi.rcWindow;
|
||||
HDC windowDc = GetWindowDC(hwnd);
|
||||
CALL_ORIG_FUNC(GetRandomRgn)(windowDc, visibleRegion, SYSRGN);
|
||||
ReleaseDC(hwnd, windowDc);
|
||||
}
|
||||
|
||||
visibleRegion &= context.virtualScreenRegion;
|
||||
if (!it->second.isMenu)
|
||||
{
|
||||
@ -335,27 +321,11 @@ namespace
|
||||
context.invalidatedRegion |= visibleRegion - it->second.visibleRegion;
|
||||
}
|
||||
|
||||
if (isVisible && !it->second.isVisibleRegionChanged)
|
||||
if (it->second.presentationWindow &&
|
||||
(!isVisible || it->second.presentationWindow != DDraw::RealPrimarySurface::getPresentationWindow()))
|
||||
{
|
||||
visibleRegion.offset(it->second.windowRect.left - wi.rcWindow.left, it->second.windowRect.top - wi.rcWindow.top);
|
||||
|
||||
if (it->second.visibleRegion != visibleRegion)
|
||||
{
|
||||
it->second.isVisibleRegionChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->second.presentationWindow)
|
||||
{
|
||||
if (setPresentationWindowRgn)
|
||||
{
|
||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, it->second.windowRegion);
|
||||
}
|
||||
|
||||
if (it->second.presentationWindow != DDraw::RealPrimarySurface::getPresentationWindow())
|
||||
{
|
||||
Gdi::Window::updatePresentationWindowPos(it->second.presentationWindow, hwnd);
|
||||
}
|
||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, Gdi::Window::getWindowRgn(hwnd));
|
||||
Gdi::Window::updatePresentationWindowPos(it->second.presentationWindow, hwnd);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
@ -395,7 +365,7 @@ namespace Gdi
|
||||
if (statsWindow && statsWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(statsWindow->getWindow(), &wr);
|
||||
auto visibleRegion(getWindowRegion(statsWindow->getWindow()));
|
||||
auto visibleRegion(getWindowRgn(statsWindow->getWindow()));
|
||||
visibleRegion.offset(wr.left, wr.top);
|
||||
layeredWindows.push_back({ statsWindow->getWindow(), wr, visibleRegion });
|
||||
}
|
||||
@ -404,7 +374,7 @@ namespace Gdi
|
||||
if (configWindow && configWindow->isVisible())
|
||||
{
|
||||
GetWindowRect(configWindow->getWindow(), &wr);
|
||||
auto visibleRegion(getWindowRegion(configWindow->getWindow()));
|
||||
auto visibleRegion(getWindowRgn(configWindow->getWindow()));
|
||||
visibleRegion.offset(wr.left, wr.top);
|
||||
layeredWindows.push_back({ configWindow->getWindow(), wr, visibleRegion });
|
||||
auto capture = Input::getCaptureWindow();
|
||||
@ -445,6 +415,47 @@ namespace Gdi
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int getRandomRgn(HDC hdc, HRGN hrgn, INT i)
|
||||
{
|
||||
auto result = CALL_ORIG_FUNC(GetRandomRgn)(hdc, hrgn, i);
|
||||
if (1 != result || SYSRGN != i)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
HWND hwnd = WindowFromDC(hdc);
|
||||
if (!hwnd)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
HWND root = GetAncestor(hwnd, GA_ROOT);
|
||||
if (!root)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto it = g_windows.find(root);
|
||||
if (it == g_windows.end())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
CombineRgn(hrgn, hrgn, it->second.visibleRegion, RGN_AND);
|
||||
return result;
|
||||
}
|
||||
|
||||
Gdi::Region getWindowRgn(HWND hwnd)
|
||||
{
|
||||
Gdi::Region rgn;
|
||||
if (ERROR == CALL_ORIG_FUNC(GetWindowRgn)(hwnd, rgn))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
return rgn;
|
||||
}
|
||||
|
||||
bool isTopLevelWindow(HWND hwnd)
|
||||
{
|
||||
return GetDesktopWindow() == GetAncestor(hwnd, GA_PARENT);
|
||||
@ -470,7 +481,6 @@ namespace Gdi
|
||||
void onSyncPaint(HWND hwnd)
|
||||
{
|
||||
LOG_FUNC("Window::onSyncPaint", hwnd);
|
||||
bool isInvalidated = false;
|
||||
|
||||
{
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
@ -480,38 +490,13 @@ namespace Gdi
|
||||
return;
|
||||
}
|
||||
|
||||
if (it->second.isVisibleRegionChanged)
|
||||
{
|
||||
it->second.isVisibleRegionChanged = false;
|
||||
const LONG origWndProc = CALL_ORIG_FUNC(GetWindowLongA)(hwnd, GWL_WNDPROC);
|
||||
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC, reinterpret_cast<LONG>(CALL_ORIG_FUNC(DefWindowProcA)));
|
||||
Gdi::Region rgn(it->second.isLayered ? it->second.windowRegion : it->second.visibleRegion);
|
||||
if (!it->second.isLayered)
|
||||
{
|
||||
rgn.offset(-it->second.windowRect.left, -it->second.windowRect.top);
|
||||
rgn |= REGION_OVERRIDE_MARKER_RECT;
|
||||
}
|
||||
if (SetWindowRgn(hwnd, rgn, FALSE))
|
||||
{
|
||||
rgn.release();
|
||||
}
|
||||
CALL_ORIG_FUNC(SetWindowLongA)(hwnd, GWL_WNDPROC, origWndProc);
|
||||
}
|
||||
|
||||
isInvalidated = !it->second.invalidatedRegion.isEmpty();
|
||||
if (isInvalidated)
|
||||
{
|
||||
RedrawWindow(hwnd, nullptr, it->second.invalidatedRegion,
|
||||
RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
|
||||
it->second.invalidatedRegion.clear();
|
||||
}
|
||||
RedrawWindow(hwnd, nullptr, it->second.invalidatedRegion,
|
||||
RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
|
||||
it->second.invalidatedRegion.clear();
|
||||
}
|
||||
|
||||
if (isInvalidated)
|
||||
{
|
||||
RECT emptyRect = {};
|
||||
RedrawWindow(hwnd, &emptyRect, nullptr, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ERASENOW);
|
||||
}
|
||||
RECT emptyRect = {};
|
||||
RedrawWindow(hwnd, &emptyRect, nullptr, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ERASENOW);
|
||||
}
|
||||
|
||||
void present(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
@ -526,12 +511,13 @@ namespace Gdi
|
||||
return;
|
||||
}
|
||||
|
||||
auto mr = DDraw::PrimarySurface::getMonitorRect();
|
||||
for (auto window : g_windowZOrder)
|
||||
{
|
||||
if (window->presentationWindow && !window->visibleRegion.isEmpty())
|
||||
{
|
||||
clipper->SetHWnd(&clipper, 0, window->presentationWindow);
|
||||
dst->Blt(&dst, nullptr, &src, nullptr, DDBLT_WAIT, nullptr);
|
||||
dst->Blt(&dst, &mr, &src, nullptr, DDBLT_WAIT, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -589,7 +575,7 @@ namespace Gdi
|
||||
|
||||
UpdateWindowContext context;
|
||||
context.processId = GetCurrentProcessId();
|
||||
context.virtualScreenRegion = VirtualScreen::getRegion();
|
||||
context.virtualScreenRegion = VirtualScreen::getBounds();
|
||||
std::vector<HWND> invalidatedWindows;
|
||||
|
||||
{
|
||||
@ -616,7 +602,7 @@ namespace Gdi
|
||||
for (auto it = g_windowZOrder.rbegin(); it != g_windowZOrder.rend(); ++it)
|
||||
{
|
||||
auto& window = **it;
|
||||
if (window.isVisibleRegionChanged || !window.invalidatedRegion.isEmpty())
|
||||
if (!window.invalidatedRegion.isEmpty())
|
||||
{
|
||||
invalidatedWindows.push_back(window.hwnd);
|
||||
}
|
||||
@ -629,6 +615,31 @@ namespace Gdi
|
||||
}
|
||||
}
|
||||
|
||||
void setDpiAwareness(HWND hwnd, bool dpiAware)
|
||||
{
|
||||
if (!Win32::DpiAwareness::isMixedModeSupported())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
D3dDdi::ScopedCriticalSection lock;
|
||||
auto it = g_windows.find(hwnd);
|
||||
if (it != g_windows.end() && it->second.isDpiAware != dpiAware)
|
||||
{
|
||||
it->second.isDpiAware = dpiAware;
|
||||
auto prevPresentationWindow = it->second.presentationWindow;
|
||||
it->second.presentationWindow = Gdi::PresentationWindow::create(hwnd, dpiAware);
|
||||
|
||||
if (it->second.presentationWindow)
|
||||
{
|
||||
Gdi::WinProc::updatePresentationWindowText(hwnd);
|
||||
Gdi::GuiThread::setWindowRgn(it->second.presentationWindow, getWindowRgn(hwnd));
|
||||
}
|
||||
|
||||
Gdi::GuiThread::destroyWindow(prevPresentationWindow);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePresentationWindowPos(HWND presentationWindow, HWND owner)
|
||||
{
|
||||
if (IsIconic(owner))
|
||||
@ -667,7 +678,9 @@ namespace Gdi
|
||||
Gdi::GuiThread::execute([&]()
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(presentationWindow,
|
||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags);
|
||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOMOVE);
|
||||
CALL_ORIG_FUNC(SetWindowPos)(presentationWindow,
|
||||
wp.hwndInsertAfter, wp.x, wp.y, wp.cx, wp.cy, wp.flags | SWP_NOSIZE);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -21,12 +21,15 @@ namespace Gdi
|
||||
std::vector<LayeredWindow> getVisibleLayeredWindows();
|
||||
std::vector<LayeredWindow> getVisibleOverlayWindows();
|
||||
HWND getFullscreenWindow();
|
||||
int getRandomRgn(HDC hdc, HRGN hrgn, INT i);
|
||||
Gdi::Region getWindowRgn(HWND hwnd);
|
||||
bool isTopLevelWindow(HWND hwnd);
|
||||
void onStyleChanged(HWND hwnd, WPARAM wParam);
|
||||
void onSyncPaint(HWND hwnd);
|
||||
void present(CompatRef<IDirectDrawSurface7> dst, CompatRef<IDirectDrawSurface7> src,
|
||||
CompatRef<IDirectDrawClipper> clipper);
|
||||
void present(Gdi::Region excludeRegion);
|
||||
void setDpiAwareness(HWND hwnd, bool dpiAware);
|
||||
void updateAll();
|
||||
void updatePresentationWindowPos(HWND presentationWindow, HWND owner);
|
||||
}
|
||||
|
@ -3,10 +3,12 @@
|
||||
#include <tuple>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <hidusage.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Path.h>
|
||||
#include <Common/Rect.h>
|
||||
#include <Config/Settings/TerminateHotKey.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
@ -15,9 +17,18 @@
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/ConfigWindow.h>
|
||||
#include <Overlay/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct DInputMouseHookData
|
||||
{
|
||||
HOOKPROC origHookProc;
|
||||
LPARAM origHookStruct;
|
||||
MSLLHOOKSTRUCT hookStruct;
|
||||
DWORD dpiScale;
|
||||
};
|
||||
|
||||
struct HotKeyData
|
||||
{
|
||||
std::function<void(void*)> action;
|
||||
@ -29,14 +40,19 @@ namespace
|
||||
SIZE g_bmpArrowSize = {};
|
||||
Overlay::Control* g_capture = nullptr;
|
||||
POINT g_cursorPos = {};
|
||||
POINT g_origCursorPos = { MAXLONG, MAXLONG };
|
||||
HWND g_cursorWindow = nullptr;
|
||||
std::map<Input::HotKey, HotKeyData> g_hotKeys;
|
||||
RECT g_monitorRect = {};
|
||||
HHOOK g_keyboardHook = nullptr;
|
||||
HHOOK g_mouseHook = nullptr;
|
||||
|
||||
DInputMouseHookData g_dinputMouseHookData = {};
|
||||
decltype(&PhysicalToLogicalPointForPerMonitorDPI) g_physicalToLogicalPointForPerMonitorDPI = nullptr;
|
||||
|
||||
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
LRESULT CALLBACK lowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam);
|
||||
POINT physicalToLogicalPoint(POINT pt, DWORD dpiScale);
|
||||
|
||||
LRESULT CALLBACK cursorWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@ -67,6 +83,44 @@ namespace
|
||||
return CALL_ORIG_FUNC(DefWindowProcA)(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT WINAPI dinputCallNextHookEx(HHOOK hhk, int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (lParam == reinterpret_cast<LPARAM>(&g_dinputMouseHookData.hookStruct))
|
||||
{
|
||||
lParam = g_dinputMouseHookData.origHookStruct;
|
||||
}
|
||||
return CallNextHookEx(hhk, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK dinputLowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (HC_ACTION == nCode)
|
||||
{
|
||||
auto& data = g_dinputMouseHookData;
|
||||
data.origHookStruct = lParam;
|
||||
data.hookStruct = *reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
|
||||
|
||||
if (WM_MOUSEMOVE == wParam)
|
||||
{
|
||||
data.hookStruct.pt = physicalToLogicalPoint(data.hookStruct.pt, data.dpiScale);
|
||||
}
|
||||
else
|
||||
{
|
||||
CALL_ORIG_FUNC(GetCursorPos)(&data.hookStruct.pt);
|
||||
}
|
||||
|
||||
lParam = reinterpret_cast<LPARAM>(&g_dinputMouseHookData.hookStruct);
|
||||
}
|
||||
return g_dinputMouseHookData.origHookProc(nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
DWORD getDpiScaleForCursorPos()
|
||||
{
|
||||
POINT cp = {};
|
||||
CALL_ORIG_FUNC(GetCursorPos)(&cp);
|
||||
return Win32::DisplayMode::getMonitorInfo(cp).dpiScale;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (HC_ACTION == nCode &&
|
||||
@ -101,12 +155,25 @@ namespace
|
||||
|
||||
if (WM_MOUSEMOVE == wParam)
|
||||
{
|
||||
POINT cp = g_cursorPos;
|
||||
POINT origCp = {};
|
||||
CALL_ORIG_FUNC(GetCursorPos)(&origCp);
|
||||
if (MAXLONG == g_origCursorPos.y)
|
||||
{
|
||||
if (llHook.flags & LLMHF_INJECTED)
|
||||
{
|
||||
if (MAXLONG == g_origCursorPos.x)
|
||||
{
|
||||
g_origCursorPos.x = llHook.pt.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_origCursorPos.y = llHook.pt.y;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
cp.x += (llHook.pt.x - origCp.x);
|
||||
cp.y += (llHook.pt.y - origCp.y);
|
||||
POINT cp = g_cursorPos;
|
||||
cp.x += llHook.pt.x - g_origCursorPos.x;
|
||||
cp.y += llHook.pt.y - g_origCursorPos.y;
|
||||
cp.x = std::min(std::max(g_monitorRect.left, cp.x), g_monitorRect.right);
|
||||
cp.y = std::min(std::max(g_monitorRect.top, cp.y), g_monitorRect.bottom);
|
||||
g_cursorPos = cp;
|
||||
@ -150,6 +217,16 @@ namespace
|
||||
TerminateProcess(GetCurrentProcess(), 0);
|
||||
}
|
||||
|
||||
POINT physicalToLogicalPoint(POINT pt, DWORD dpiScale)
|
||||
{
|
||||
if (g_physicalToLogicalPointForPerMonitorDPI)
|
||||
{
|
||||
g_physicalToLogicalPointForPerMonitorDPI(nullptr, &pt);
|
||||
return pt;
|
||||
}
|
||||
return { MulDiv(pt.x, 100, dpiScale), MulDiv(pt.y, 100, dpiScale) };
|
||||
}
|
||||
|
||||
void resetKeyboardHook()
|
||||
{
|
||||
Gdi::GuiThread::execute([]()
|
||||
@ -171,18 +248,54 @@ namespace
|
||||
{
|
||||
UnhookWindowsHookEx(g_mouseHook);
|
||||
}
|
||||
|
||||
g_origCursorPos = { MAXLONG, MAXLONG };
|
||||
g_mouseHook = CALL_ORIG_FUNC(SetWindowsHookExA)(
|
||||
WH_MOUSE_LL, &lowLevelMouseProc, Dll::g_currentModule, 0);
|
||||
|
||||
INPUT inputs[2] = {};
|
||||
inputs[0].mi.dy = 1;
|
||||
inputs[0].mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
inputs[1].mi.dx = 1;
|
||||
inputs[1].mi.dwFlags = MOUSEEVENTF_MOVE;
|
||||
SendInput(2, inputs, sizeof(INPUT));
|
||||
});
|
||||
}
|
||||
|
||||
BOOL WINAPI setCursorPos(int X, int Y)
|
||||
{
|
||||
LOG_FUNC("SetCursorPos", X, Y);
|
||||
auto result = CALL_ORIG_FUNC(SetCursorPos)(X, Y);
|
||||
if (result && g_mouseHook)
|
||||
{
|
||||
resetMouseHook();
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
|
||||
HHOOK setWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hmod, DWORD dwThreadId,
|
||||
decltype(&SetWindowsHookExA) origSetWindowsHookEx)
|
||||
{
|
||||
if (WH_KEYBOARD_LL == idHook && hmod && GetModuleHandle("AcGenral") == hmod)
|
||||
if (hmod && (WH_KEYBOARD_LL == idHook || WH_MOUSE_LL == idHook))
|
||||
{
|
||||
// Disable the IgnoreAltTab shim
|
||||
return nullptr;
|
||||
auto moduleName = Compat::getModulePath(hmod).stem().string();
|
||||
if (WH_KEYBOARD_LL == idHook && 0 == _stricmp(moduleName.c_str(), "acgenral"))
|
||||
{
|
||||
// Disable the IgnoreAltTab shim
|
||||
return nullptr;
|
||||
}
|
||||
else if (WH_MOUSE_LL == idHook &&
|
||||
(0 == _stricmp(moduleName.c_str(), "dinput") || 0 == _stricmp(moduleName.c_str(), "dinput8")))
|
||||
{
|
||||
g_dinputMouseHookData.origHookProc = lpfn;
|
||||
if (!g_physicalToLogicalPointForPerMonitorDPI)
|
||||
{
|
||||
g_dinputMouseHookData.dpiScale = getDpiScaleForCursorPos();
|
||||
}
|
||||
|
||||
lpfn = dinputLowLevelMouseProc;
|
||||
Compat::hookIatFunction(hmod, "CallNextHookEx", dinputCallNextHookEx);
|
||||
}
|
||||
}
|
||||
|
||||
HHOOK result = origSetWindowsHookEx(idHook, lpfn, hmod, dwThreadId);
|
||||
@ -235,11 +348,6 @@ namespace Input
|
||||
return g_capture ? static_cast<Overlay::Window*>(&g_capture->getRoot()) : nullptr;
|
||||
}
|
||||
|
||||
POINT getCursorPos()
|
||||
{
|
||||
return g_cursorPos;
|
||||
}
|
||||
|
||||
HWND getCursorWindow()
|
||||
{
|
||||
return g_cursorWindow;
|
||||
@ -272,6 +380,10 @@ namespace Input
|
||||
GetObject(g_bmpArrow, sizeof(bm), &bm);
|
||||
g_bmpArrowSize = { bm.bmWidth, bm.bmHeight };
|
||||
|
||||
g_physicalToLogicalPointForPerMonitorDPI = reinterpret_cast<decltype(&PhysicalToLogicalPointForPerMonitorDPI)>(
|
||||
GetProcAddress(GetModuleHandle("user32"), "PhysicalToLogicalPointForPerMonitorDPI"));
|
||||
|
||||
HOOK_FUNCTION(user32, SetCursorPos, setCursorPos);
|
||||
HOOK_FUNCTION(user32, SetWindowsHookExA, setWindowsHookExA);
|
||||
HOOK_FUNCTION(user32, SetWindowsHookExW, setWindowsHookExW);
|
||||
|
||||
@ -301,11 +413,7 @@ namespace Input
|
||||
if (control)
|
||||
{
|
||||
auto window = getCaptureWindow();
|
||||
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoA)(MonitorFromWindow(window->getWindow(), MONITOR_DEFAULTTOPRIMARY), &mi);
|
||||
g_monitorRect = mi.rcMonitor;
|
||||
g_monitorRect = Win32::DisplayMode::getMonitorInfo(window->getWindow()).rcMonitor;
|
||||
|
||||
if (!g_mouseHook)
|
||||
{
|
||||
|
@ -18,7 +18,6 @@ namespace Input
|
||||
|
||||
Overlay::Control* getCapture();
|
||||
Overlay::Window* getCaptureWindow();
|
||||
POINT getCursorPos();
|
||||
HWND getCursorWindow();
|
||||
POINT getRelativeCursorPos();
|
||||
void installHooks();
|
||||
|
@ -72,7 +72,8 @@ namespace
|
||||
namespace Overlay
|
||||
{
|
||||
ConfigWindow::ConfigWindow()
|
||||
: Window(nullptr, { 0, 0, 640, 480 }, WS_BORDER, Config::configTransparency.get(), Config::configHotKey.get())
|
||||
: Window(nullptr, { 0, 0, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT },
|
||||
WS_BORDER, Config::configTransparency.get(), Config::configHotKey.get())
|
||||
, m_buttonCount(0)
|
||||
, m_focus(nullptr)
|
||||
{
|
||||
|
@ -7,12 +7,12 @@
|
||||
#include <Common/Log.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <DDraw/RealPrimarySurface.h>
|
||||
#include <DDraw/Surfaces/PrimarySurface.h>
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/PresentationWindow.h>
|
||||
#include <Input/Input.h>
|
||||
#include <Overlay/Control.h>
|
||||
#include <Overlay/Window.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -179,42 +179,20 @@ namespace Overlay
|
||||
|
||||
void Window::updatePos()
|
||||
{
|
||||
RECT monitorRect = DDraw::RealPrimarySurface::getMonitorRect();
|
||||
if (IsRectEmpty(&monitorRect))
|
||||
{
|
||||
HMONITOR monitor = nullptr;
|
||||
HWND foregroundWindow = GetForegroundWindow();
|
||||
if (foregroundWindow)
|
||||
{
|
||||
monitor = MonitorFromWindow(foregroundWindow, MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
else
|
||||
{
|
||||
monitor = MonitorFromPoint({ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoA)(monitor, &mi);
|
||||
monitorRect = mi.rcMonitor;
|
||||
|
||||
if (IsRectEmpty(&monitorRect))
|
||||
{
|
||||
monitorRect = { 0, 0, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top };
|
||||
}
|
||||
}
|
||||
|
||||
int scaleX = (monitorRect.right - monitorRect.left) / 640;
|
||||
int scaleY = (monitorRect.bottom - monitorRect.top) / 480;
|
||||
const RECT monitorRect = Win32::DisplayMode::getMonitorInfo(GetForegroundWindow()).rcMonitor;
|
||||
int scaleX = (monitorRect.right - monitorRect.left) / VIRTUAL_SCREEN_WIDTH;
|
||||
int scaleY = (monitorRect.bottom - monitorRect.top) / VIRTUAL_SCREEN_HEIGHT;
|
||||
m_scaleFactor = std::min(scaleX, scaleY);
|
||||
m_scaleFactor = std::max(1, m_scaleFactor);
|
||||
m_rect = calculateRect({ monitorRect.left / m_scaleFactor, monitorRect.top / m_scaleFactor,
|
||||
monitorRect.right / m_scaleFactor, monitorRect.bottom / m_scaleFactor });
|
||||
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, getTopmost(),
|
||||
m_rect.left * m_scaleFactor, m_rect.top * m_scaleFactor,
|
||||
(m_rect.right - m_rect.left) * m_scaleFactor, (m_rect.bottom - m_rect.top) * m_scaleFactor,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
{
|
||||
CALL_ORIG_FUNC(SetWindowPos)(m_hwnd, getTopmost(),
|
||||
m_rect.left * m_scaleFactor, m_rect.top * m_scaleFactor,
|
||||
(m_rect.right - m_rect.left) * m_scaleFactor, (m_rect.bottom - m_rect.top) * m_scaleFactor,
|
||||
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOREDRAW | SWP_NOSENDCHANGING | SWP_SHOWWINDOW);
|
||||
}
|
||||
|
||||
if (Input::getCaptureWindow() == this)
|
||||
{
|
||||
|
@ -13,6 +13,9 @@ namespace Overlay
|
||||
class Window : public Control
|
||||
{
|
||||
public:
|
||||
static const LONG VIRTUAL_SCREEN_WIDTH = 640;
|
||||
static const LONG VIRTUAL_SCREEN_HEIGHT = 480;
|
||||
|
||||
Window(Window* parentWindow, const RECT& rect, DWORD style, int alpha, const Input::HotKey& hotKey = {});
|
||||
virtual ~Window() override;
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
#include <Common/Comparison.h>
|
||||
#include <Common/CompatPtr.h>
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/ScopedSrwLock.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Rect.h>
|
||||
#include <Common/ScopedCriticalSection.h>
|
||||
#include <Config/Settings/DesktopColorDepth.h>
|
||||
#include <Config/Settings/DesktopResolution.h>
|
||||
#include <Config/Settings/DisplayRefreshRate.h>
|
||||
@ -21,6 +23,7 @@
|
||||
#include <Gdi/GuiThread.h>
|
||||
#include <Gdi/VirtualScreen.h>
|
||||
#include <Win32/DisplayMode.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
BOOL WINAPI DWM8And16Bit_IsShimApplied_CallOut() { return FALSE; }
|
||||
ULONG WINAPI GdiEntry13() { return 0; }
|
||||
@ -62,7 +65,10 @@ namespace
|
||||
DWORD g_desktopBpp = 0;
|
||||
ULONG g_displaySettingsUniquenessBias = 0;
|
||||
EmulatedDisplayMode g_emulatedDisplayMode = {};
|
||||
Compat::SrwLock g_srwLock;
|
||||
ULONG g_monitorInfoUniqueness = 0;
|
||||
std::map<HMONITOR, Win32::DisplayMode::MonitorInfo> g_monitorInfo;
|
||||
Win32::DisplayMode::MonitorInfo g_emptyMonitorInfo = {};
|
||||
Compat::CriticalSection g_cs;
|
||||
|
||||
BOOL WINAPI dwm8And16BitIsShimAppliedCallOut();
|
||||
BOOL WINAPI seComHookInterface(CLSID* clsid, GUID* iid, DWORD unk1, DWORD unk2);
|
||||
@ -92,24 +98,10 @@ namespace
|
||||
|
||||
void setDwmDxFullscreenTransitionEvent();
|
||||
|
||||
void adjustMonitorInfo(MONITORINFO& mi)
|
||||
{
|
||||
Compat::ScopedSrwLockShared srwLock(g_srwLock);
|
||||
if (!g_emulatedDisplayMode.deviceName.empty() &&
|
||||
g_emulatedDisplayMode.rect.left == mi.rcMonitor.left &&
|
||||
g_emulatedDisplayMode.rect.top == mi.rcMonitor.top)
|
||||
{
|
||||
mi.rcMonitor.right += g_emulatedDisplayMode.diff.cx;
|
||||
mi.rcMonitor.bottom += g_emulatedDisplayMode.diff.cy;
|
||||
mi.rcWork.right += g_emulatedDisplayMode.diff.cx;
|
||||
mi.rcWork.bottom += g_emulatedDisplayMode.diff.cy;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
LONG changeDisplaySettingsEx(const Char* lpszDeviceName, typename DevMode<Char>* lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam)
|
||||
{
|
||||
DDraw::ScopedThreadLock lock;
|
||||
DDraw::ScopedThreadLock ddLock;
|
||||
auto desktopResolution = Config::desktopResolution.get();
|
||||
if (!lpDevMode && 0 == dwflags && Config::Settings::DesktopResolution::DESKTOP != desktopResolution)
|
||||
{
|
||||
@ -235,7 +227,7 @@ namespace
|
||||
}
|
||||
|
||||
{
|
||||
Compat::ScopedSrwLockExclusive srwLock(g_srwLock);
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
++g_displaySettingsUniquenessBias;
|
||||
if (lpDevMode)
|
||||
{
|
||||
@ -246,13 +238,7 @@ namespace
|
||||
g_emulatedDisplayMode.bpp = lpDevMode->dmBitsPerPel;
|
||||
}
|
||||
g_emulatedDisplayMode.refreshRate = currDevMode.dmDisplayFrequency;
|
||||
|
||||
g_emulatedDisplayMode.deviceName = getDeviceName(lpszDeviceName);
|
||||
g_emulatedDisplayMode.rect = Win32::DisplayMode::getMonitorInfo(g_emulatedDisplayMode.deviceName).rcMonitor;
|
||||
g_emulatedDisplayMode.rect.right = g_emulatedDisplayMode.rect.left + emulatedResolution.cx;
|
||||
g_emulatedDisplayMode.rect.bottom = g_emulatedDisplayMode.rect.top + emulatedResolution.cy;
|
||||
g_emulatedDisplayMode.diff.cx = emulatedResolution.cx - currDevMode.dmPelsWidth;
|
||||
g_emulatedDisplayMode.diff.cy = emulatedResolution.cy - currDevMode.dmPelsHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -322,7 +308,7 @@ namespace
|
||||
BOOL result = origEnumDisplaySettingsEx(lpszDeviceName, iModeNum, lpDevMode, dwFlags);
|
||||
if (result)
|
||||
{
|
||||
Compat::ScopedSrwLockShared srwLock(g_srwLock);
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
if (getDeviceName(lpszDeviceName) == g_emulatedDisplayMode.deviceName)
|
||||
{
|
||||
lpDevMode->dmBitsPerPel = g_emulatedDisplayMode.bpp;
|
||||
@ -388,22 +374,10 @@ namespace
|
||||
|
||||
ULONG WINAPI gdiEntry13()
|
||||
{
|
||||
Compat::ScopedSrwLockShared lock(g_srwLock);
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return CALL_ORIG_FUNC(GdiEntry13)() + g_displaySettingsUniquenessBias;
|
||||
}
|
||||
|
||||
SIZE getAppResolution(const std::wstring& deviceName, SIZE displayResolution = {})
|
||||
{
|
||||
{
|
||||
Compat::ScopedSrwLockShared srwLock(g_srwLock);
|
||||
if (deviceName == g_emulatedDisplayMode.deviceName)
|
||||
{
|
||||
return { static_cast<LONG>(g_emulatedDisplayMode.width), static_cast<LONG>(g_emulatedDisplayMode.height) };
|
||||
}
|
||||
}
|
||||
return 0 != displayResolution.cx ? displayResolution : Win32::DisplayMode::getDisplayResolution(deviceName);
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
DWORD getConfiguredRefreshRate(const Char* deviceName)
|
||||
{
|
||||
@ -464,17 +438,8 @@ namespace
|
||||
case VERTRES:
|
||||
if (Gdi::isDisplayDc(hdc))
|
||||
{
|
||||
MONITORINFO mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(getMonitorFromDc(hdc), &mi);
|
||||
if (HORZRES == nIndex)
|
||||
{
|
||||
return LOG_RESULT(mi.rcMonitor.right - mi.rcMonitor.left);
|
||||
}
|
||||
else
|
||||
{
|
||||
return LOG_RESULT(mi.rcMonitor.bottom - mi.rcMonitor.top);
|
||||
}
|
||||
const auto& r = Win32::DisplayMode::getMonitorInfo().rcEmulated;
|
||||
return HORZRES == nIndex ? (r.right - r.left) : (r.bottom - r.top);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -527,64 +492,13 @@ namespace
|
||||
return mi.szDevice;
|
||||
}
|
||||
|
||||
BOOL CALLBACK getMonitorFromDcEnum(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM dwData)
|
||||
{
|
||||
auto& args = *reinterpret_cast<GetMonitorFromDcEnumArgs*>(dwData);
|
||||
|
||||
MONITORINFOEX mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoA)(hMonitor, &mi);
|
||||
|
||||
HDC dc = CreateDC(mi.szDevice, nullptr, nullptr, nullptr);
|
||||
if (dc)
|
||||
{
|
||||
POINT org = {};
|
||||
GetDCOrgEx(dc, &org);
|
||||
DeleteDC(dc);
|
||||
if (org == args.org)
|
||||
{
|
||||
args.hmonitor = hMonitor;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HMONITOR getMonitorFromDc(HDC dc)
|
||||
{
|
||||
HWND hwnd = CALL_ORIG_FUNC(WindowFromDC)(dc);
|
||||
if (hwnd)
|
||||
{
|
||||
return MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
GetMonitorFromDcEnumArgs args = {};
|
||||
GetDCOrgEx(dc, &args.org);
|
||||
EnumDisplayMonitors(nullptr, nullptr, getMonitorFromDcEnum, reinterpret_cast<LPARAM>(&args));
|
||||
return args.hmonitor ? args.hmonitor : MonitorFromPoint({}, MONITOR_DEFAULTTOPRIMARY);
|
||||
}
|
||||
|
||||
BOOL CALLBACK getMonitorInfoEnum(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM dwData)
|
||||
{
|
||||
MONITORINFOEXW mi = {};
|
||||
mi.cbSize = sizeof(mi);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, &mi);
|
||||
auto& dest = *reinterpret_cast<MONITORINFOEXW*>(dwData);
|
||||
if (0 == wcscmp(mi.szDevice, dest.szDevice))
|
||||
{
|
||||
dest = mi;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI getMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpmi)
|
||||
{
|
||||
LOG_FUNC("GetMonitorInfoA", hMonitor, lpmi);
|
||||
BOOL result = CALL_ORIG_FUNC(GetMonitorInfoA)(hMonitor, lpmi);
|
||||
if (result)
|
||||
{
|
||||
adjustMonitorInfo(*lpmi);
|
||||
lpmi->rcMonitor = Win32::DisplayMode::getMonitorInfo(hMonitor).rcEmulated;
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
@ -595,7 +509,7 @@ namespace
|
||||
BOOL result = CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, lpmi);
|
||||
if (result)
|
||||
{
|
||||
adjustMonitorInfo(*lpmi);
|
||||
lpmi->rcMonitor = Win32::DisplayMode::getMonitorInfo(hMonitor).rcEmulated;
|
||||
}
|
||||
return LOG_RESULT(result);
|
||||
}
|
||||
@ -750,50 +664,129 @@ namespace
|
||||
CloseHandle(dwmDxFullscreenTransitionEvent);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CALLBACK updateMonitorInfoEnum(HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT /*lprcMonitor*/, LPARAM /*dwData*/)
|
||||
{
|
||||
auto& mi = g_monitorInfo[hMonitor];
|
||||
mi.cbSize = sizeof(MONITORINFOEXW);
|
||||
CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, &mi);
|
||||
|
||||
DEVMODEW dm = {};
|
||||
dm.dmSize = sizeof(dm);
|
||||
CALL_ORIG_FUNC(EnumDisplaySettingsExW)(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm, 0);
|
||||
mi.rcReal.left = dm.dmPosition.x;
|
||||
mi.rcReal.top = dm.dmPosition.y;
|
||||
mi.rcReal.right = dm.dmPosition.x + dm.dmPelsWidth;
|
||||
mi.rcReal.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
||||
|
||||
mi.rcDpiAware = Win32::DpiAwareness::isMixedModeSupported() ? mi.rcReal : mi.rcMonitor;
|
||||
|
||||
mi.rcEmulated = mi.rcMonitor;
|
||||
if (g_emulatedDisplayMode.deviceName == mi.szDevice)
|
||||
{
|
||||
mi.rcEmulated.right = mi.rcEmulated.left + g_emulatedDisplayMode.width;
|
||||
mi.rcEmulated.bottom = mi.rcEmulated.top + g_emulatedDisplayMode.height;
|
||||
mi.bpp = g_emulatedDisplayMode.bpp;
|
||||
mi.isEmulated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mi.bpp = g_desktopBpp;
|
||||
}
|
||||
|
||||
mi.dpiScale = MulDiv(100, mi.rcReal.right - mi.rcReal.left, mi.rcMonitor.right - mi.rcMonitor.left);
|
||||
|
||||
if (0 == mi.rcMonitor.left && 0 == mi.rcMonitor.top)
|
||||
{
|
||||
g_monitorInfo[nullptr] = mi;
|
||||
}
|
||||
|
||||
LOG_DEBUG << "updateMonitorInfoEnum: " << hMonitor << " " << mi;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void updateMonitorInfo()
|
||||
{
|
||||
const auto uniqueness = gdiEntry13();
|
||||
if (uniqueness != g_monitorInfoUniqueness || g_monitorInfo.empty())
|
||||
{
|
||||
g_monitorInfo.clear();
|
||||
g_monitorInfoUniqueness = uniqueness;
|
||||
EnumDisplayMonitors(nullptr, nullptr, &updateMonitorInfoEnum, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
namespace DisplayMode
|
||||
{
|
||||
SIZE getAppResolution(const std::wstring& deviceName)
|
||||
std::ostream& operator<<(std::ostream& os, const MonitorInfo& mi)
|
||||
{
|
||||
return ::getAppResolution(deviceName);
|
||||
return Compat::LogStruct(os)
|
||||
<< mi.rcMonitor
|
||||
<< mi.rcWork
|
||||
<< Compat::hex(mi.dwFlags)
|
||||
<< mi.szDevice
|
||||
<< mi.rcReal
|
||||
<< mi.rcDpiAware
|
||||
<< mi.rcEmulated
|
||||
<< mi.bpp
|
||||
<< mi.dpiScale
|
||||
<< mi.isEmulated;
|
||||
}
|
||||
|
||||
std::map<HMONITOR, MonitorInfo> getAllMonitorInfo()
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
updateMonitorInfo();
|
||||
auto mi = g_monitorInfo;
|
||||
mi.erase(nullptr);
|
||||
return mi;
|
||||
}
|
||||
|
||||
DWORD getBpp()
|
||||
{
|
||||
return getEmulatedDisplayMode().bpp;
|
||||
}
|
||||
|
||||
SIZE getDisplayResolution(const std::wstring& deviceName)
|
||||
{
|
||||
DEVMODEW dm = {};
|
||||
dm.dmSize = sizeof(dm);
|
||||
CALL_ORIG_FUNC(EnumDisplaySettingsExW)(deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
|
||||
return { static_cast<LONG>(dm.dmPelsWidth), static_cast<LONG>(dm.dmPelsHeight) };
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_emulatedDisplayMode.bpp;
|
||||
}
|
||||
|
||||
EmulatedDisplayMode getEmulatedDisplayMode()
|
||||
{
|
||||
Compat::ScopedSrwLockShared lock(g_srwLock);
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
return g_emulatedDisplayMode;
|
||||
}
|
||||
|
||||
MONITORINFOEXW getMonitorInfo(const std::wstring& deviceName)
|
||||
const MonitorInfo& getMonitorInfo(HMONITOR monitor)
|
||||
{
|
||||
MONITORINFOEXW mi = {};
|
||||
wcscpy_s(mi.szDevice, deviceName.c_str());
|
||||
EnumDisplayMonitors(nullptr, nullptr, &getMonitorInfoEnum, reinterpret_cast<LPARAM>(&mi));
|
||||
return mi;
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
updateMonitorInfo();
|
||||
auto it = g_monitorInfo.find(monitor);
|
||||
return it != g_monitorInfo.end() ? it->second : g_emptyMonitorInfo;
|
||||
}
|
||||
|
||||
Resolution getResolution(const std::wstring& deviceName)
|
||||
const MonitorInfo& getMonitorInfo(HWND hwnd)
|
||||
{
|
||||
Resolution res = {};
|
||||
res.display = getDisplayResolution(deviceName);
|
||||
res.app = ::getAppResolution(deviceName, res.display);
|
||||
return res;
|
||||
return getMonitorInfo(hwnd ? MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) : nullptr);
|
||||
}
|
||||
|
||||
const MonitorInfo& getMonitorInfo(POINT pt)
|
||||
{
|
||||
return getMonitorInfo(MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST));
|
||||
}
|
||||
|
||||
const MonitorInfo& getMonitorInfo(const std::wstring& deviceName)
|
||||
{
|
||||
Compat::ScopedCriticalSection lock(g_cs);
|
||||
updateMonitorInfo();
|
||||
for (const auto& mi : g_monitorInfo)
|
||||
{
|
||||
if (deviceName == mi.second.szDevice)
|
||||
{
|
||||
return mi.second;
|
||||
}
|
||||
}
|
||||
return g_emptyMonitorInfo;
|
||||
}
|
||||
|
||||
ULONG queryDisplaySettingsUniqueness()
|
||||
|
@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <map>
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include <Common/Comparison.h>
|
||||
#include <Gdi/Region.h>
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
@ -21,31 +22,29 @@ namespace Win32
|
||||
struct EmulatedDisplayMode : DisplayMode
|
||||
{
|
||||
std::wstring deviceName;
|
||||
RECT rect;
|
||||
SIZE diff;
|
||||
};
|
||||
|
||||
struct Resolution
|
||||
struct MonitorInfo : MONITORINFOEXW
|
||||
{
|
||||
SIZE app;
|
||||
SIZE display;
|
||||
RECT rcReal;
|
||||
RECT rcDpiAware;
|
||||
RECT rcEmulated;
|
||||
DWORD bpp;
|
||||
DWORD dpiScale;
|
||||
bool isEmulated;
|
||||
};
|
||||
|
||||
SIZE getAppResolution(const std::wstring& deviceName);
|
||||
std::ostream& operator<<(std::ostream& os, const MonitorInfo& mi);
|
||||
|
||||
std::map<HMONITOR, MonitorInfo> getAllMonitorInfo();
|
||||
DWORD getBpp();
|
||||
SIZE getDisplayResolution(const std::wstring& deviceName);
|
||||
EmulatedDisplayMode getEmulatedDisplayMode();
|
||||
MONITORINFOEXW getMonitorInfo(const std::wstring& deviceName);
|
||||
Resolution getResolution(const std::wstring& deviceName);
|
||||
const MonitorInfo& getMonitorInfo(HMONITOR monitor = nullptr);
|
||||
const MonitorInfo& getMonitorInfo(HWND hwnd);
|
||||
const MonitorInfo& getMonitorInfo(POINT pt);
|
||||
const MonitorInfo& getMonitorInfo(const std::wstring& deviceName);
|
||||
ULONG queryDisplaySettingsUniqueness();
|
||||
|
||||
void installHooks();
|
||||
|
||||
using ::operator<;
|
||||
|
||||
inline auto toTuple(const DisplayMode& dm)
|
||||
{
|
||||
return std::make_tuple(dm.width, dm.height, dm.bpp, dm.refreshRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
179
DDrawCompat/Win32/DpiAwareness.cpp
Normal file
179
DDrawCompat/Win32/DpiAwareness.cpp
Normal file
@ -0,0 +1,179 @@
|
||||
#include <ShellScalingApi.h>
|
||||
|
||||
#include <Common/Log.h>
|
||||
#include <Config/Settings/DpiAwareness.h>
|
||||
#include <Win32/DpiAwareness.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
decltype(&AreDpiAwarenessContextsEqual) g_areDpiAwarenessContextsEqual = nullptr;
|
||||
decltype(&GetProcessDpiAwareness) g_getProcessDpiAwareness = nullptr;
|
||||
decltype(&GetThreadDpiAwarenessContext) g_getThreadDpiAwarenessContext = nullptr;
|
||||
decltype(&IsValidDpiAwarenessContext) g_isValidDpiAwarenessContext = nullptr;
|
||||
decltype(&SetProcessDpiAwareness) g_setProcessDpiAwareness = nullptr;
|
||||
decltype(&SetProcessDpiAwarenessContext) g_setProcessDpiAwarenessContext = nullptr;
|
||||
decltype(&SetThreadDpiAwarenessContext) g_setThreadDpiAwarenessContext = nullptr;
|
||||
|
||||
void logDpiAwareness(bool isSuccessful, DPI_AWARENESS_CONTEXT dpiAwareness, const char* funcName)
|
||||
{
|
||||
LOG_INFO << (isSuccessful ? "DPI awareness was successfully changed" : "Failed to change DPI awareness")
|
||||
<< " to \"" << Config::dpiAwareness.convertToString(dpiAwareness) << "\" via " << funcName;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
ScopedDpiAwareness::ScopedDpiAwareness(bool dpiAware)
|
||||
: m_prevContext(dpiAware ? DpiAwareness::setThreadContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) : nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
ScopedDpiAwareness::~ScopedDpiAwareness()
|
||||
{
|
||||
if (m_prevContext)
|
||||
{
|
||||
DpiAwareness::setThreadContext(m_prevContext);
|
||||
}
|
||||
}
|
||||
|
||||
namespace DpiAwareness
|
||||
{
|
||||
DPI_AWARENESS_CONTEXT getThreadContext()
|
||||
{
|
||||
if (g_getThreadDpiAwarenessContext && g_areDpiAwarenessContextsEqual)
|
||||
{
|
||||
auto context = g_getThreadDpiAwarenessContext();
|
||||
if (g_areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||
{
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
else if (g_areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
||||
{
|
||||
return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
|
||||
}
|
||||
else if (g_areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
||||
{
|
||||
return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
}
|
||||
else if (g_areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
||||
{
|
||||
return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
|
||||
}
|
||||
else if (g_areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
||||
{
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_getProcessDpiAwareness)
|
||||
{
|
||||
PROCESS_DPI_AWARENESS awareness = PROCESS_DPI_UNAWARE;
|
||||
if (SUCCEEDED(g_getProcessDpiAwareness(nullptr, &awareness)))
|
||||
{
|
||||
switch (awareness)
|
||||
{
|
||||
case PROCESS_DPI_UNAWARE:
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
case PROCESS_SYSTEM_DPI_AWARE:
|
||||
return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
|
||||
case PROCESS_PER_MONITOR_DPI_AWARE:
|
||||
return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return IsProcessDPIAware() ? DPI_AWARENESS_CONTEXT_SYSTEM_AWARE : DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
auto user32 = GetModuleHandle("user32");
|
||||
auto shcore = LoadLibrary("shcore");
|
||||
|
||||
g_areDpiAwarenessContextsEqual = reinterpret_cast<decltype(&AreDpiAwarenessContextsEqual)>(
|
||||
GetProcAddress(user32, "AreDpiAwarenessContextsEqual"));
|
||||
g_getProcessDpiAwareness = reinterpret_cast<decltype(&GetProcessDpiAwareness)>(
|
||||
GetProcAddress(shcore, "GetProcessDpiAwareness"));
|
||||
g_getThreadDpiAwarenessContext = reinterpret_cast<decltype(&GetThreadDpiAwarenessContext)>(
|
||||
GetProcAddress(user32, "GetThreadDpiAwarenessContext"));
|
||||
g_isValidDpiAwarenessContext = reinterpret_cast<decltype(&IsValidDpiAwarenessContext)>(
|
||||
GetProcAddress(user32, "IsValidDpiAwarenessContext"));
|
||||
g_setProcessDpiAwareness = reinterpret_cast<decltype(&SetProcessDpiAwareness)>(
|
||||
GetProcAddress(shcore, "SetProcessDpiAwareness"));
|
||||
g_setProcessDpiAwarenessContext = reinterpret_cast<decltype(&SetProcessDpiAwarenessContext)>(
|
||||
GetProcAddress(user32, "SetProcessDpiAwarenessContext"));
|
||||
g_setThreadDpiAwarenessContext = reinterpret_cast<decltype(&SetThreadDpiAwarenessContext)>(
|
||||
GetProcAddress(user32, "SetThreadDpiAwarenessContext"));
|
||||
|
||||
LOG_INFO << "Initial DPI awareness: " << Config::dpiAwareness.convertToString(getThreadContext());
|
||||
|
||||
auto dpiAwareness = Config::dpiAwareness.get();
|
||||
if (!dpiAwareness)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_isValidDpiAwarenessContext && g_setProcessDpiAwarenessContext)
|
||||
{
|
||||
if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness &&
|
||||
!g_isValidDpiAwarenessContext(dpiAwareness))
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
}
|
||||
|
||||
if (DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness &&
|
||||
!g_isValidDpiAwarenessContext(dpiAwareness))
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
|
||||
logDpiAwareness(g_setProcessDpiAwarenessContext(dpiAwareness), dpiAwareness, "SetProcessDpiAwarenessContext");
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_setProcessDpiAwareness)
|
||||
{
|
||||
HRESULT result = S_OK;
|
||||
if (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE == dpiAwareness ||
|
||||
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 == dpiAwareness)
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
|
||||
result = g_setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
}
|
||||
else if (DPI_AWARENESS_CONTEXT_SYSTEM_AWARE == dpiAwareness)
|
||||
{
|
||||
result = g_setProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dpiAwareness = DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
result = g_setProcessDpiAwareness(PROCESS_DPI_UNAWARE);
|
||||
}
|
||||
|
||||
logDpiAwareness(SUCCEEDED(result), dpiAwareness, "SetProcessDpiAwareness");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DPI_AWARENESS_CONTEXT_UNAWARE == dpiAwareness ||
|
||||
DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED == dpiAwareness)
|
||||
{
|
||||
LOG_INFO << "DPI awareness was not changed";
|
||||
}
|
||||
else
|
||||
{
|
||||
logDpiAwareness(SetProcessDPIAware(), DPI_AWARENESS_CONTEXT_SYSTEM_AWARE, "SetProcessDPIAware");
|
||||
}
|
||||
}
|
||||
|
||||
bool isMixedModeSupported()
|
||||
{
|
||||
return g_setThreadDpiAwarenessContext;
|
||||
}
|
||||
|
||||
DPI_AWARENESS_CONTEXT setThreadContext(DPI_AWARENESS_CONTEXT context)
|
||||
{
|
||||
return g_setThreadDpiAwarenessContext ? g_setThreadDpiAwarenessContext(context) : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
26
DDrawCompat/Win32/DpiAwareness.h
Normal file
26
DDrawCompat/Win32/DpiAwareness.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
namespace Win32
|
||||
{
|
||||
class ScopedDpiAwareness
|
||||
{
|
||||
public:
|
||||
ScopedDpiAwareness(bool dpiAware = true);
|
||||
~ScopedDpiAwareness();
|
||||
|
||||
private:
|
||||
DPI_AWARENESS_CONTEXT m_prevContext;
|
||||
};
|
||||
|
||||
namespace DpiAwareness
|
||||
{
|
||||
void init();
|
||||
|
||||
bool isMixedModeSupported();
|
||||
|
||||
DPI_AWARENESS_CONTEXT getThreadContext();
|
||||
DPI_AWARENESS_CONTEXT setThreadContext(DPI_AWARENESS_CONTEXT context);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Common/Path.h>
|
||||
#include <Win32/Log.h>
|
||||
|
||||
namespace
|
||||
@ -261,6 +262,14 @@ std::ostream& operator<<(std::ostream& os, const HFONT__& font)
|
||||
<< lf;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const HINSTANCE__& inst)
|
||||
{
|
||||
os << "MOD";
|
||||
return Compat::LogStruct(os)
|
||||
<< static_cast<const void*>(&inst)
|
||||
<< Compat::getModulePath(const_cast<HINSTANCE>(&inst));
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const HRGN__& rgn)
|
||||
{
|
||||
os << "RGN";
|
||||
|
@ -21,6 +21,7 @@ std::ostream& operator<<(std::ostream& os, const GESTURENOTIFYSTRUCT& gns);
|
||||
std::ostream& operator<<(std::ostream& os, const HDC__& dc);
|
||||
std::ostream& operator<<(std::ostream& os, const HELPINFO& hi);
|
||||
std::ostream& operator<<(std::ostream& os, const HFONT__& font);
|
||||
std::ostream& operator<<(std::ostream& os, const HINSTANCE__& inst);
|
||||
std::ostream& operator<<(std::ostream& os, const HRGN__& rgn);
|
||||
std::ostream& operator<<(std::ostream& os, const HWND__& wnd);
|
||||
std::ostream& operator<<(std::ostream& os, const LOGFONT& lf);
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#include <Common/Hook.h>
|
||||
#include <Common/Log.h>
|
||||
#include <Dll/Dll.h>
|
||||
#include <Win32/Registry.h>
|
||||
|
||||
typedef long NTSTATUS;
|
||||
@ -66,6 +67,19 @@ namespace
|
||||
|
||||
#undef HKLM_SOFTWARE_KEY
|
||||
|
||||
LSTATUS WINAPI ddrawRegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions,
|
||||
REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
|
||||
{
|
||||
LOG_FUNC("ddrawRegCreateKeyExA", hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired,
|
||||
lpSecurityAttributes, phkResult, lpdwDisposition);
|
||||
if (0 == lstrcmpi(lpSubKey, "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers"))
|
||||
{
|
||||
return LOG_RESULT(E_ABORT);
|
||||
}
|
||||
return LOG_RESULT(RegCreateKeyExA(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired,
|
||||
lpSecurityAttributes, phkResult, lpdwDisposition));
|
||||
}
|
||||
|
||||
bool filterType(DWORD type, const DWORD* flags)
|
||||
{
|
||||
if (!flags)
|
||||
@ -424,6 +438,8 @@ namespace Win32
|
||||
HOOK_REGISTRY_FUNCTION(RegGetValueW, regGetValueW);
|
||||
HOOK_REGISTRY_FUNCTION(RegQueryValueExA, regQueryValueExA);
|
||||
HOOK_REGISTRY_FUNCTION(RegQueryValueExW, regQueryValueExW);
|
||||
|
||||
Compat::hookIatFunction(Dll::g_origDDrawModule, "RegCreateKeyExA", ddrawRegCreateKeyExA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user