Skip to content

[GEN][ZH] Fix Alt-tabbing crash #846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -489,34 +489,6 @@ void W3DDisplay::setGamma(Real gamma, Real bright, Real contrast, Bool calibrate
DX8Wrapper::Set_Gamma(gamma,bright,contrast,calibrate, false);
}

/*Giant hack in order to keep the game from getting stuck when alt-tabbing*/
void Reset_D3D_Device(bool active)
{
if (TheDisplay && WW3D::Is_Initted() && !TheDisplay->getWindowed())
{
if (active)
{
//switch back to desired mode when user alt-tabs back into game
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true);
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{ //check if we're running Win9x variant since they have buggy alt-tab that requires
//reloading all textures.
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{ //only do this on Win9x boxes because it makes alt-tab very slow.
WW3D::_Invalidate_Textures();
}
}
}
else
{
//switch to windowed mode whenever the user alt-tabs out of game. Don't restore assets after reset since we'll do it when returning.
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true, false);
}
}
}

/** Set resolution of display */
//=============================================================================
Bool W3DDisplay::setDisplayMode( UnsignedInt xres, UnsignedInt yres, UnsignedInt bitdepth, Bool windowed )
Expand Down
14 changes: 9 additions & 5 deletions Generals/Code/Main/WinMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ const char *gAppPrefix = ""; /// So WB can have a different debug log file name.
#define DEFAULT_XRESOLUTION 800
#define DEFAULT_YRESOLUTION 600

extern void Reset_D3D_Device(bool active);

static Bool gInitializing = false;
static Bool gDoPaint = true;
static Bool isWinMainActive = false;
Expand Down Expand Up @@ -426,14 +424,20 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
//-------------------------------------------------------------------------
case WM_ACTIVATEAPP:
{
// DWORD threadId=GetCurrentThreadId();
if ((bool) wParam != isWinMainActive)
{ isWinMainActive = (BOOL) wParam;
{
// TheSuperHackers @bugfix xezon 11/05/2025 This event originally called DX8Wrapper::Reset_Device,
// intended to clear resources on a lost device in fullscreen, but effectively also in
// windowed mode, if the DXMaximizedWindowedMode shim was applied in newer versions of Windows,
// which lead to unfortunate application crashing. Resetting the device on WM_ACTIVATEAPP instead
// of TestCooperativeLevel() == D3DERR_DEVICENOTRESET is not a requirement. There are other code
// paths that take care of that.

isWinMainActive = (BOOL) wParam;

if (TheGameEngine)
TheGameEngine->setIsActive(isWinMainActive);

Reset_D3D_Device(isWinMainActive);
if (isWinMainActive)
{ //restore mouse cursor to our custom version.
if (TheWin32Mouse)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,34 +555,6 @@ void W3DDisplay::setGamma(Real gamma, Real bright, Real contrast, Bool calibrate
DX8Wrapper::Set_Gamma(gamma,bright,contrast,calibrate, false);
}

/*Giant hack in order to keep the game from getting stuck when alt-tabbing*/
void Reset_D3D_Device(bool active)
{
if (TheDisplay && WW3D::Is_Initted() && !TheDisplay->getWindowed())
{
if (active)
{
//switch back to desired mode when user alt-tabs back into game
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true);
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
if (GetVersionEx(&osvi))
{ //check if we're running Win9x variant since they have buggy alt-tab that requires
//reloading all textures.
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{ //only do this on Win9x boxes because it makes alt-tab very slow.
WW3D::_Invalidate_Textures();
}
}
}
else
{
//switch to windowed mode whenever the user alt-tabs out of game. Don't restore assets after reset since we'll do it when returning.
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true, false);
}
}
}

/** Set resolution of display */
//=============================================================================
Bool W3DDisplay::setDisplayMode( UnsignedInt xres, UnsignedInt yres, UnsignedInt bitdepth, Bool windowed )
Expand Down
14 changes: 9 additions & 5 deletions GeneralsMD/Code/Main/WinMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ const char *gAppPrefix = ""; /// So WB can have a different debug log file name.
#define DEFAULT_XRESOLUTION 800
#define DEFAULT_YRESOLUTION 600

extern void Reset_D3D_Device(bool active);

static Bool gInitializing = false;
static Bool gDoPaint = true;
static Bool isWinMainActive = false;
Expand Down Expand Up @@ -448,14 +446,20 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
//-------------------------------------------------------------------------
case WM_ACTIVATEAPP:
{
// DWORD threadId=GetCurrentThreadId();
if ((bool) wParam != isWinMainActive)
{ isWinMainActive = (BOOL) wParam;
{
// TheSuperHackers @bugfix xezon 11/05/2025 This event originally called DX8Wrapper::Reset_Device,
// intended to clear resources on a lost device in fullscreen, but effectively also in
// windowed mode, if the DXMaximizedWindowedMode shim was applied in newer versions of Windows,
// which lead to unfortunate application crashing. Resetting the device on WM_ACTIVATEAPP instead
// of TestCooperativeLevel() == D3DERR_DEVICENOTRESET is not a requirement. There are other code
// paths that take care of that.

isWinMainActive = (BOOL) wParam;

if (TheGameEngine)
TheGameEngine->setIsActive(isWinMainActive);

Reset_D3D_Device(isWinMainActive);
if (isWinMainActive)
{ //restore mouse cursor to our custom version.
if (TheWin32Mouse)
Expand Down
Loading