diff --git a/DDrawCompat/CompatActivateAppHandler.cpp b/DDrawCompat/CompatActivateAppHandler.cpp new file mode 100644 index 0000000..b40e4e0 --- /dev/null +++ b/DDrawCompat/CompatActivateAppHandler.cpp @@ -0,0 +1,96 @@ +#include "CompatActivateAppHandler.h" +#include "CompatDirectDraw.h" +#include "CompatDirectDrawSurface.h" +#include "CompatPrimarySurface.h" +#include "DDrawLog.h" +#include "RealPrimarySurface.h" + +extern HWND g_mainWindow; + +namespace +{ + HWND g_fullScreenCooperativeWindow = nullptr; + DWORD g_fullScreenCooperativeFlags = 0; + HHOOK g_callWndProcHook = nullptr; + + void handleActivateApp(bool isActivated); + + LRESULT CALLBACK callWndProc(int nCode, WPARAM wParam, LPARAM lParam) + { + auto ret = reinterpret_cast(lParam); + Compat::LogEnter("callWndProc", nCode, wParam, ret); + + if (HC_ACTION == nCode && WM_ACTIVATEAPP == ret->message) + { + const bool isActivated = TRUE == ret->wParam; + handleActivateApp(isActivated); + } + + LRESULT result = CallNextHookEx(nullptr, nCode, wParam, lParam); + Compat::LogLeave("callWndProc", nCode, wParam, ret) << result; + return result; + } + + void handleActivateApp(bool isActivated) + { + Compat::LogEnter("handleActivateApp", isActivated); + + static bool isActive = true; + if (isActivated != isActive && RealPrimarySurface::isFullScreen()) + { + IUnknown* ddIntf = nullptr; + CompatDirectDrawSurface::s_origVtable.GetDDInterface( + RealPrimarySurface::getSurface(), reinterpret_cast(&ddIntf)); + IDirectDraw7* dd = nullptr; + ddIntf->lpVtbl->QueryInterface(ddIntf, IID_IDirectDraw7, reinterpret_cast(&dd)); + + if (isActivated) + { + CompatDirectDraw::s_origVtable.SetCooperativeLevel( + dd, g_fullScreenCooperativeWindow, g_fullScreenCooperativeFlags); + if (CompatPrimarySurface::isDisplayModeChanged) + { + const CompatPrimarySurface::DisplayMode& dm = CompatPrimarySurface::displayMode; + CompatDirectDraw::s_origVtable.SetDisplayMode( + dd, dm.width, dm.height, 32, dm.refreshRate, 0); + } + } + else + { + if (CompatPrimarySurface::isDisplayModeChanged) + { + CompatDirectDraw::s_origVtable.RestoreDisplayMode(dd); + } + CompatDirectDraw::s_origVtable.SetCooperativeLevel( + dd, g_fullScreenCooperativeWindow, DDSCL_NORMAL); + ShowWindow(g_fullScreenCooperativeWindow, SW_MINIMIZE); + } + + dd->lpVtbl->Release(dd); + ddIntf->lpVtbl->Release(ddIntf); + } + + isActive = isActivated; + Compat::LogLeave("handleActivateApp", isActivated); + } +} + +namespace CompatActivateAppHandler +{ + void installHooks() + { + const DWORD threadId = GetCurrentThreadId(); + g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, nullptr, threadId); + } + + void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags) + { + g_fullScreenCooperativeWindow = hwnd; + g_fullScreenCooperativeFlags = flags; + } + + void uninstallHooks() + { + UnhookWindowsHookEx(g_callWndProcHook); + } +} diff --git a/DDrawCompat/CompatActivateAppHandler.h b/DDrawCompat/CompatActivateAppHandler.h new file mode 100644 index 0000000..8d04ee9 --- /dev/null +++ b/DDrawCompat/CompatActivateAppHandler.h @@ -0,0 +1,12 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN + +#include + +namespace CompatActivateAppHandler +{ + void installHooks(); + void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags); + void uninstallHooks(); +} diff --git a/DDrawCompat/CompatDirectDraw.cpp b/DDrawCompat/CompatDirectDraw.cpp index 0047567..55d6415 100644 --- a/DDrawCompat/CompatDirectDraw.cpp +++ b/DDrawCompat/CompatDirectDraw.cpp @@ -1,3 +1,4 @@ +#include "CompatActivateAppHandler.h" #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatPrimarySurface.h" @@ -15,6 +16,16 @@ namespace } return DDENUMRET_CANCEL; } + + DWORD getRefreshRate() + { + return 0; + } + + DWORD getRefreshRate(DWORD dwRefreshRate, DWORD /*dwFlags*/) + { + return dwRefreshRate; + } } template @@ -22,6 +33,7 @@ void CompatDirectDraw::setCompatVtable(Vtable& vtable) { vtable.CreateSurface = &CreateSurface; vtable.RestoreDisplayMode = &RestoreDisplayMode; + vtable.SetCooperativeLevel = &SetCooperativeLevel; vtable.SetDisplayMode = &SetDisplayMode; } @@ -78,13 +90,26 @@ HRESULT STDMETHODCALLTYPE CompatDirectDraw::RestoreDisplayMode(TDir if (SUCCEEDED(result)) { CompatPrimarySurface::displayMode = CompatPrimarySurface::getDisplayMode(*This); + CompatPrimarySurface::isDisplayModeChanged = false; + } + return result; +} + +template +HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetCooperativeLevel( + TDirectDraw* This, HWND hWnd, DWORD dwFlags) +{ + HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags); + if (dwFlags & DDSCL_FULLSCREEN) + { + CompatActivateAppHandler::setFullScreenCooperativeLevel(hWnd, dwFlags); } return result; } template template -static HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetDisplayMode( +HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetDisplayMode( TDirectDraw* This, DWORD dwWidth, DWORD dwHeight, @@ -130,6 +155,8 @@ static HRESULT STDMETHODCALLTYPE CompatDirectDraw::SetDisplayMode( CompatPrimarySurface::displayMode.width = dwWidth; CompatPrimarySurface::displayMode.height = dwHeight; CompatPrimarySurface::displayMode.pixelFormat = pf; + CompatPrimarySurface::displayMode.refreshRate = getRefreshRate(params...); + CompatPrimarySurface::isDisplayModeChanged = true; } else { diff --git a/DDrawCompat/CompatDirectDraw.h b/DDrawCompat/CompatDirectDraw.h index e5d9bad..2b44d27 100644 --- a/DDrawCompat/CompatDirectDraw.h +++ b/DDrawCompat/CompatDirectDraw.h @@ -20,7 +20,8 @@ public: IUnknown* pUnkOuter); static HRESULT STDMETHODCALLTYPE RestoreDisplayMode(TDirectDraw* This); - + static HRESULT STDMETHODCALLTYPE SetCooperativeLevel(TDirectDraw* This, HWND hWnd, DWORD dwFlags); + template static HRESULT STDMETHODCALLTYPE SetDisplayMode( TDirectDraw* This, diff --git a/DDrawCompat/CompatPrimarySurface.cpp b/DDrawCompat/CompatPrimarySurface.cpp index 2085d11..2e35a97 100644 --- a/DDrawCompat/CompatPrimarySurface.cpp +++ b/DDrawCompat/CompatPrimarySurface.cpp @@ -41,6 +41,7 @@ namespace CompatPrimarySurface dm.width = desc.dwWidth; dm.height = desc.dwHeight; dm.pixelFormat = desc.ddpfPixelFormat; + dm.refreshRate = desc.dwRefreshRate; return dm; } @@ -50,6 +51,7 @@ namespace CompatPrimarySurface template DisplayMode getDisplayMode(IDirectDraw7& dd); DisplayMode displayMode = {}; + bool isDisplayModeChanged = false; IDirectDrawSurface7* surface = nullptr; LPDIRECTDRAWPALETTE palette = nullptr; PALETTEENTRY paletteEntries[256] = {}; diff --git a/DDrawCompat/CompatPrimarySurface.h b/DDrawCompat/CompatPrimarySurface.h index 4c1ee71..265c043 100644 --- a/DDrawCompat/CompatPrimarySurface.h +++ b/DDrawCompat/CompatPrimarySurface.h @@ -13,12 +13,14 @@ namespace CompatPrimarySurface LONG width; LONG height; DDPIXELFORMAT pixelFormat; + DWORD refreshRate; }; template DisplayMode getDisplayMode(TDirectDraw& dd); extern DisplayMode displayMode; + extern bool isDisplayModeChanged; extern IDirectDrawSurface7* surface; extern LPDIRECTDRAWPALETTE palette; extern PALETTEENTRY paletteEntries[256]; diff --git a/DDrawCompat/DDrawCompat.vcxproj b/DDrawCompat/DDrawCompat.vcxproj index 2fdf64e..5166c04 100644 --- a/DDrawCompat/DDrawCompat.vcxproj +++ b/DDrawCompat/DDrawCompat.vcxproj @@ -144,6 +144,7 @@ + @@ -178,6 +179,7 @@ + diff --git a/DDrawCompat/DDrawCompat.vcxproj.filters b/DDrawCompat/DDrawCompat.vcxproj.filters index 53158a7..4a16f61 100644 --- a/DDrawCompat/DDrawCompat.vcxproj.filters +++ b/DDrawCompat/DDrawCompat.vcxproj.filters @@ -111,6 +111,9 @@ Header Files + + Header Files + @@ -191,6 +194,9 @@ Source Files + + Source Files + diff --git a/DDrawCompat/DDrawLog.cpp b/DDrawCompat/DDrawLog.cpp index b9cdce2..973882c 100644 --- a/DDrawCompat/DDrawLog.cpp +++ b/DDrawCompat/DDrawLog.cpp @@ -106,6 +106,12 @@ std::ostream& operator<<(std::ostream& os, const DDSURFACEDESC2& sd) sd.lpSurface << "," << sd.ddpfPixelFormat << "," << sd.ddsCaps << "," << sd.dwTextureStage << ')'; } +std::ostream& operator<<(std::ostream& os, const CWPSTRUCT& cwrp) +{ + return os << "CWP(" << std::hex << cwrp.message << "," << std::dec << cwrp.hwnd << "," << + std::hex << cwrp.wParam << "," << cwrp.lParam << std::dec << ")"; +} + std::ostream& operator<<(std::ostream& os, const CWPRETSTRUCT& cwrp) { return os << "CWRP(" << std::hex << cwrp.message << "," << std::dec << cwrp.hwnd << "," << diff --git a/DDrawCompat/DDrawLog.h b/DDrawCompat/DDrawLog.h index 108be79..41aac76 100644 --- a/DDrawCompat/DDrawLog.h +++ b/DDrawCompat/DDrawLog.h @@ -25,6 +25,7 @@ std::ostream& operator<<(std::ostream& os, const DDSCAPS2& caps); std::ostream& operator<<(std::ostream& os, const DDPIXELFORMAT& pf); std::ostream& operator<<(std::ostream& os, const DDSURFACEDESC& sd); std::ostream& operator<<(std::ostream& os, const DDSURFACEDESC2& sd); +std::ostream& operator<<(std::ostream& os, const CWPSTRUCT& cwrp); std::ostream& operator<<(std::ostream& os, const CWPRETSTRUCT& cwrp); template diff --git a/DDrawCompat/DllMain.cpp b/DDrawCompat/DllMain.cpp index db3878d..f8c32f2 100644 --- a/DDrawCompat/DllMain.cpp +++ b/DDrawCompat/DllMain.cpp @@ -5,6 +5,7 @@ #include #include +#include "CompatActivateAppHandler.h" #include "CompatDirectDraw.h" #include "CompatDirectDrawSurface.h" #include "CompatDirectDrawPalette.h" @@ -99,6 +100,7 @@ namespace hookDirectDraw(*dd); hookDirectDrawSurface(*dd); hookDirectDrawPalette(*dd); + CompatActivateAppHandler::installHooks(); Compat::Log() << "Installing GDI hooks"; CompatGdi::installHooks(); @@ -188,6 +190,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID /*lpvReserved*/) { Compat::Log() << "Detaching DDrawCompat"; RealPrimarySurface::removeUpdateThread(); + CompatActivateAppHandler::uninstallHooks(); CompatGdi::uninstallHooks(); Compat::unhookAllFunctions(); FreeLibrary(g_origDInputModule);