mirror of
https://github.com/narzoul/DDrawCompat
synced 2024-12-30 08:55:36 +01:00
Fixed various alt-tabbing issues
This commit is contained in:
parent
d898961a7e
commit
5b5863b028
@ -3,6 +3,7 @@
|
||||
|
||||
#include "D3dDdi/DeviceFuncs.h"
|
||||
#include "D3dDdi/LockResource.h"
|
||||
#include "D3dDdi/KernelModeThunks.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -11,6 +12,7 @@ namespace
|
||||
HANDLE device;
|
||||
HANDLE resource;
|
||||
|
||||
Resource() : device(nullptr), resource(nullptr) {}
|
||||
Resource(HANDLE device, HANDLE resource) : device(device), resource(resource) {}
|
||||
|
||||
bool operator<(const Resource& rhs) const
|
||||
@ -41,6 +43,7 @@ namespace
|
||||
|
||||
std::map<Resource, D3dDdi::LockResource> g_lockResources;
|
||||
std::map<HANDLE, D3dDdi::LockResource::SubResource*> g_renderTargets;
|
||||
Resource g_sharedPrimary;
|
||||
const UINT g_resourceTypeFlags = getResourceTypeFlags().Value;
|
||||
|
||||
ResourceReplacer::ResourceReplacer(HANDLE device, const HANDLE& resource, UINT subResourceIndex)
|
||||
@ -208,6 +211,13 @@ namespace
|
||||
|
||||
HRESULT APIENTRY destroyResource(HANDLE hDevice, HANDLE hResource)
|
||||
{
|
||||
const bool isSharedPrimary =
|
||||
hDevice == g_sharedPrimary.device && hResource == g_sharedPrimary.resource;
|
||||
if (isSharedPrimary)
|
||||
{
|
||||
D3dDdi::KernelModeThunks::releaseVidPnSources();
|
||||
}
|
||||
|
||||
HRESULT result = getOrigVtable(hDevice).pfnDestroyResource(hDevice, hResource);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
@ -224,6 +234,11 @@ namespace
|
||||
getOrigVtable(hDevice).pfnDestroyResource(hDevice, it->second.getHandle());
|
||||
g_lockResources.erase(it);
|
||||
}
|
||||
|
||||
if (isSharedPrimary)
|
||||
{
|
||||
g_sharedPrimary = {};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -251,6 +266,16 @@ namespace
|
||||
return getOrigVtable(hDevice).pfnLock(hDevice, pData);
|
||||
}
|
||||
|
||||
HRESULT APIENTRY openResource(HANDLE hDevice, D3DDDIARG_OPENRESOURCE* pResource)
|
||||
{
|
||||
HRESULT result = getOrigVtable(hDevice).pfnOpenResource(hDevice, pResource);
|
||||
if (SUCCEEDED(result) && pResource->Flags.Fullscreen)
|
||||
{
|
||||
g_sharedPrimary = Resource(hDevice, pResource->hResource);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HRESULT APIENTRY present(HANDLE hDevice, const D3DDDIARG_PRESENT* pData)
|
||||
{
|
||||
auto it = g_lockResources.find(Resource(hDevice, pData->hSrcResource));
|
||||
@ -334,6 +359,7 @@ namespace D3dDdi
|
||||
vtable.pfnDrawRectPatch = &RENDER_FUNC(pfnDrawRectPatch);
|
||||
vtable.pfnDrawTriPatch = &RENDER_FUNC(pfnDrawTriPatch);
|
||||
vtable.pfnLock = &lock;
|
||||
vtable.pfnOpenResource = &openResource;
|
||||
vtable.pfnPresent = &present;
|
||||
vtable.pfnPresent1 = &present1;
|
||||
vtable.pfnSetRenderTarget = &setRenderTarget;
|
||||
|
@ -230,5 +230,18 @@ namespace D3dDdi
|
||||
HOOK_FUNCTION(gdi32, D3DKMTSetVidPnSourceOwner, setVidPnSourceOwner);
|
||||
HOOK_FUNCTION(gdi32, D3DKMTSetVidPnSourceOwner1, setVidPnSourceOwner1);
|
||||
}
|
||||
|
||||
void releaseVidPnSources()
|
||||
{
|
||||
for (auto it : g_devices)
|
||||
{
|
||||
if (D3DDDI_ID_UNINITIALIZED != it.second.vidPnSourceId)
|
||||
{
|
||||
D3DKMT_SETVIDPNSOURCEOWNER vidPnSourceOwner = {};
|
||||
vidPnSourceOwner.hDevice = it.first;
|
||||
D3DKMTSetVidPnSourceOwner(&vidPnSourceOwner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,5 +7,6 @@ namespace D3dDdi
|
||||
namespace KernelModeThunks
|
||||
{
|
||||
void installHooks();
|
||||
void releaseVidPnSources();
|
||||
}
|
||||
}
|
||||
|
@ -1,116 +1,64 @@
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/CompatRef.h"
|
||||
#include "Common/Log.h"
|
||||
#define CINTERFACE
|
||||
|
||||
#include <ddraw.h>
|
||||
|
||||
#include "Common/Hook.h"
|
||||
#include "DDraw/ActivateAppHandler.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
#include "Gdi/Gdi.h"
|
||||
#include "Win32/FontSmoothing.h"
|
||||
|
||||
extern HWND g_mainWindow;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool g_isActive = true;
|
||||
HWND g_fullScreenCooperativeWindow = nullptr;
|
||||
DWORD g_fullScreenCooperativeFlags = 0;
|
||||
Win32::FontSmoothing::SystemSettings g_fontSmoothingSettings = {};
|
||||
HHOOK g_callWndProcHook = nullptr;
|
||||
WNDPROC g_origDdWndProc = nullptr;
|
||||
|
||||
void handleActivateApp(bool isActivated);
|
||||
|
||||
void activateApp(CompatRef<IDirectDraw7> dd)
|
||||
void activateApp()
|
||||
{
|
||||
if (!(g_fullScreenCooperativeFlags & DDSCL_NOWINDOWCHANGES))
|
||||
{
|
||||
ShowWindow(g_fullScreenCooperativeWindow, SW_RESTORE);
|
||||
HWND lastActivePopup = GetLastActivePopup(g_fullScreenCooperativeWindow);
|
||||
if (lastActivePopup && lastActivePopup != g_fullScreenCooperativeWindow)
|
||||
{
|
||||
BringWindowToTop(lastActivePopup);
|
||||
}
|
||||
}
|
||||
|
||||
dd->SetCooperativeLevel(&dd, g_fullScreenCooperativeWindow, g_fullScreenCooperativeFlags);
|
||||
auto dm = DDraw::DisplayMode::getDisplayMode(dd);
|
||||
dd->SetDisplayMode(&dd, dm.dwWidth, dm.dwHeight, 32, dm.dwRefreshRate, 0);
|
||||
|
||||
auto primary(DDraw::PrimarySurface::getPrimary());
|
||||
if (primary && SUCCEEDED(primary->Restore(primary)))
|
||||
{
|
||||
DDraw::SurfaceImpl<IDirectDrawSurface7>::fixSurfacePtrs(*primary);
|
||||
Gdi::invalidate(nullptr);
|
||||
}
|
||||
|
||||
Gdi::enableEmulation();
|
||||
Win32::FontSmoothing::setSystemSettings(g_fontSmoothingSettings);
|
||||
}
|
||||
|
||||
void deactivateApp(CompatRef<IDirectDraw7> dd)
|
||||
void deactivateApp()
|
||||
{
|
||||
dd->RestoreDisplayMode(&dd);
|
||||
dd->SetCooperativeLevel(&dd, g_fullScreenCooperativeWindow, DDSCL_NORMAL);
|
||||
|
||||
if (!(g_fullScreenCooperativeFlags & DDSCL_NOWINDOWCHANGES))
|
||||
{
|
||||
ShowWindow(g_fullScreenCooperativeWindow, SW_SHOWMINNOACTIVE);
|
||||
}
|
||||
|
||||
Gdi::disableEmulation();
|
||||
g_fontSmoothingSettings = Win32::FontSmoothing::getSystemSettings();
|
||||
Win32::FontSmoothing::setSystemSettings(Win32::FontSmoothing::g_origSystemSettings);
|
||||
}
|
||||
|
||||
LRESULT CALLBACK callWndProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||
LRESULT CALLBACK ddWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
auto ret = reinterpret_cast<CWPSTRUCT*>(lParam);
|
||||
Compat::LogEnter("callWndProc", nCode, wParam, ret);
|
||||
static bool isDisplayChangeNotificationEnabled = true;
|
||||
|
||||
if (HC_ACTION == nCode && WM_ACTIVATEAPP == ret->message)
|
||||
switch (uMsg)
|
||||
{
|
||||
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);
|
||||
|
||||
if (isActivated == g_isActive)
|
||||
case WM_ACTIVATEAPP:
|
||||
{
|
||||
return;
|
||||
}
|
||||
g_isActive = isActivated;
|
||||
|
||||
if (!isActivated)
|
||||
{
|
||||
Gdi::disableEmulation();
|
||||
}
|
||||
|
||||
auto dd(DDraw::getFullScreenDirectDraw());
|
||||
if (dd)
|
||||
{
|
||||
if (isActivated)
|
||||
isDisplayChangeNotificationEnabled = false;
|
||||
if (TRUE == wParam)
|
||||
{
|
||||
activateApp(*dd);
|
||||
activateApp();
|
||||
}
|
||||
else
|
||||
{
|
||||
deactivateApp(*dd);
|
||||
deactivateApp();
|
||||
}
|
||||
LRESULT result = g_origDdWndProc(hwnd, uMsg, wParam, lParam);
|
||||
isDisplayChangeNotificationEnabled = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
if (isActivated)
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
Gdi::enableEmulation();
|
||||
// Fix for alt-tabbing in Commandos 2
|
||||
if (!isDisplayChangeNotificationEnabled)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Compat::LogLeave("handleActivateApp", isActivated);
|
||||
return g_origDdWndProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,26 +66,15 @@ namespace DDraw
|
||||
{
|
||||
namespace ActivateAppHandler
|
||||
{
|
||||
void installHooks()
|
||||
void setCooperativeLevel(HWND hwnd, DWORD flags)
|
||||
{
|
||||
const DWORD threadId = GetCurrentThreadId();
|
||||
g_callWndProcHook = SetWindowsHookEx(WH_CALLWNDPROC, callWndProc, nullptr, threadId);
|
||||
}
|
||||
|
||||
bool isActive()
|
||||
{
|
||||
return g_isActive;
|
||||
}
|
||||
|
||||
void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags)
|
||||
{
|
||||
g_fullScreenCooperativeWindow = hwnd;
|
||||
g_fullScreenCooperativeFlags = flags;
|
||||
}
|
||||
|
||||
void uninstallHooks()
|
||||
{
|
||||
UnhookWindowsHookEx(g_callWndProcHook);
|
||||
static bool isDdWndProcHooked = false;
|
||||
if ((flags & DDSCL_FULLSCREEN) && !isDdWndProcHooked)
|
||||
{
|
||||
g_origDdWndProc = reinterpret_cast<WNDPROC>(GetWindowLongPtr(hwnd, GWLP_WNDPROC));
|
||||
Compat::hookFunction(reinterpret_cast<void*&>(g_origDdWndProc), ddWndProc);
|
||||
isDdWndProcHooked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,6 @@ namespace DDraw
|
||||
{
|
||||
namespace ActivateAppHandler
|
||||
{
|
||||
void installHooks();
|
||||
bool isActive();
|
||||
void setFullScreenCooperativeLevel(HWND hwnd, DWORD flags);
|
||||
void uninstallHooks();
|
||||
void setCooperativeLevel(HWND hwnd, DWORD flags);
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,12 @@
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/CompatRef.h"
|
||||
#include "DDraw/ActivateAppHandler.h"
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/DirectDrawSurface.h"
|
||||
#include "DDraw/DisplayMode.h"
|
||||
#include "DDraw/Surfaces/TagSurface.h"
|
||||
#include "DDraw/Surfaces/PrimarySurface.h"
|
||||
#include "DDraw/Surfaces/Surface.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
TagSurface* g_fullScreenTagSurface = nullptr;
|
||||
|
||||
template <typename TDirectDraw>
|
||||
void* getDdObject(TDirectDraw& dd)
|
||||
{
|
||||
@ -23,19 +18,6 @@ namespace DDraw
|
||||
template void* getDdObject(IDirectDraw4&);
|
||||
template void* getDdObject(IDirectDraw7&);
|
||||
|
||||
CompatPtr<IDirectDraw7> getFullScreenDirectDraw()
|
||||
{
|
||||
return g_fullScreenTagSurface ? g_fullScreenTagSurface->getDirectDraw() : nullptr;
|
||||
}
|
||||
|
||||
void onRelease(TagSurface& dd)
|
||||
{
|
||||
if (&dd == g_fullScreenTagSurface)
|
||||
{
|
||||
g_fullScreenTagSurface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TDirectDraw>
|
||||
void DirectDraw<TDirectDraw>::setCompatVtable(Vtable<TDirectDraw>& vtable)
|
||||
{
|
||||
@ -130,11 +112,6 @@ namespace DDraw
|
||||
HRESULT STDMETHODCALLTYPE DirectDraw<TDirectDraw>::SetCooperativeLevel(
|
||||
TDirectDraw* This, HWND hWnd, DWORD dwFlags)
|
||||
{
|
||||
if ((dwFlags & DDSCL_FULLSCREEN) && !ActivateAppHandler::isActive())
|
||||
{
|
||||
return DDERR_EXCLUSIVEMODEALREADYSET;
|
||||
}
|
||||
|
||||
HRESULT result = s_origVtable.SetCooperativeLevel(This, hWnd, dwFlags);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
@ -147,18 +124,7 @@ namespace DDraw
|
||||
tagSurface = TagSurface::get(ddObject);
|
||||
}
|
||||
|
||||
if (tagSurface)
|
||||
{
|
||||
if (dwFlags & DDSCL_FULLSCREEN)
|
||||
{
|
||||
g_fullScreenTagSurface = tagSurface;
|
||||
ActivateAppHandler::setFullScreenCooperativeLevel(hWnd, dwFlags);
|
||||
}
|
||||
else if ((dwFlags & DDSCL_NORMAL) && tagSurface == g_fullScreenTagSurface)
|
||||
{
|
||||
g_fullScreenTagSurface = nullptr;
|
||||
}
|
||||
}
|
||||
ActivateAppHandler::setCooperativeLevel(hWnd, dwFlags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,20 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "Common/CompatPtr.h"
|
||||
#include "Common/CompatVtable.h"
|
||||
#include "DDraw/Visitors/DirectDrawVtblVisitor.h"
|
||||
#include "DDraw/Types.h"
|
||||
|
||||
namespace DDraw
|
||||
{
|
||||
class TagSurface;
|
||||
|
||||
template <typename TDirectDraw>
|
||||
void* getDdObject(TDirectDraw& dd);
|
||||
|
||||
CompatPtr<IDirectDraw7> getFullScreenDirectDraw();
|
||||
void onRelease(TagSurface& dd);
|
||||
|
||||
template <typename TDirectDraw>
|
||||
class DirectDraw: public CompatVtable<Vtable<TDirectDraw>>
|
||||
{
|
||||
|
@ -40,11 +40,16 @@ namespace
|
||||
targetDevMode.dmDisplayFrequency == currentDevMode.dmDisplayFrequency &&
|
||||
targetDevMode.dmDisplayFlags == currentDevMode.dmDisplayFlags)
|
||||
{
|
||||
HANDLE dwmDxFullScreenTransitionEvent = OpenEventW(
|
||||
EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT");
|
||||
SetEvent(dwmDxFullScreenTransitionEvent);
|
||||
CloseHandle(dwmDxFullScreenTransitionEvent);
|
||||
return DISP_CHANGE_SUCCESSFUL;
|
||||
LONG result = origChangeDisplaySettings(
|
||||
lpszDeviceName, lpDevMode, hwnd, dwflags, lParam);
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
HANDLE dwmDxFullScreenTransitionEvent = OpenEventW(
|
||||
EVENT_MODIFY_STATE, FALSE, L"DWM_DX_FULLSCREEN_TRANSITION_EVENT");
|
||||
SetEvent(dwmDxFullScreenTransitionEvent);
|
||||
CloseHandle(dwmDxFullScreenTransitionEvent);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,13 +108,10 @@ namespace DDraw
|
||||
hookDirectDraw(*dd7);
|
||||
hookDirectDrawSurface(*dd7);
|
||||
hookDirectDrawPalette(*dd7);
|
||||
|
||||
ActivateAppHandler::installHooks();
|
||||
}
|
||||
|
||||
void uninstallHooks()
|
||||
{
|
||||
RealPrimarySurface::removeUpdateThread();
|
||||
ActivateAppHandler::uninstallHooks();
|
||||
}
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ namespace
|
||||
timeBeginPeriod(1);
|
||||
|
||||
g_frontBuffer = surface.detach();
|
||||
g_backBuffer = backBuffer.detach();
|
||||
g_backBuffer = backBuffer;
|
||||
g_surfaceDesc = desc;
|
||||
g_isFullScreen = isFlippable;
|
||||
|
||||
@ -149,7 +149,7 @@ namespace
|
||||
ResetEvent(g_updateEvent);
|
||||
timeEndPeriod(1);
|
||||
g_frontBuffer = nullptr;
|
||||
g_backBuffer.release();
|
||||
g_backBuffer = nullptr;
|
||||
g_clipper = nullptr;
|
||||
g_isFullScreen = false;
|
||||
DDraw::PaletteConverter::release();
|
||||
|
@ -145,6 +145,7 @@ namespace DDraw
|
||||
while (SUCCEEDED(result) && next.get() != g_gdiSurface.get() && next.get() != primary)
|
||||
{
|
||||
current = next;
|
||||
next.reset();
|
||||
result = current->GetAttachedSurface(current, &caps, &next.getRef());
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include "DDraw/DirectDraw.h"
|
||||
#include "DDraw/Repository.h"
|
||||
#include "DDraw/Surfaces/SurfaceImpl.h"
|
||||
#include "DDraw/Surfaces/TagSurface.h"
|
||||
|
||||
namespace
|
||||
@ -15,9 +14,6 @@ namespace DDraw
|
||||
{
|
||||
TagSurface::~TagSurface()
|
||||
{
|
||||
std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
|
||||
[=](auto& i) { return i.second == this; })->second;
|
||||
onRelease(*this);
|
||||
Repository::onRelease(m_ddObject);
|
||||
g_tagSurfaces.erase(std::find_if(g_tagSurfaces.begin(), g_tagSurfaces.end(),
|
||||
[=](auto& i) { return i.second == this; }));
|
||||
|
Loading…
x
Reference in New Issue
Block a user