Skip to content

Commit 1b10d4b

Browse files
committed
[GEN][ZH] Fix ALT+Tab crash
1 parent 62719fd commit 1b10d4b

File tree

8 files changed

+34
-68
lines changed

8 files changed

+34
-68
lines changed

Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -489,34 +489,6 @@ void W3DDisplay::setGamma(Real gamma, Real bright, Real contrast, Bool calibrate
489489
DX8Wrapper::Set_Gamma(gamma,bright,contrast,calibrate, false);
490490
}
491491

492-
/*Giant hack in order to keep the game from getting stuck when alt-tabbing*/
493-
void Reset_D3D_Device(bool active)
494-
{
495-
if (TheDisplay && WW3D::Is_Initted() && !TheDisplay->getWindowed())
496-
{
497-
if (active)
498-
{
499-
//switch back to desired mode when user alt-tabs back into game
500-
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true);
501-
OSVERSIONINFO osvi;
502-
osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
503-
if (GetVersionEx(&osvi))
504-
{ //check if we're running Win9x variant since they have buggy alt-tab that requires
505-
//reloading all textures.
506-
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
507-
{ //only do this on Win9x boxes because it makes alt-tab very slow.
508-
WW3D::_Invalidate_Textures();
509-
}
510-
}
511-
}
512-
else
513-
{
514-
//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.
515-
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true, false);
516-
}
517-
}
518-
}
519-
520492
/** Set resolution of display */
521493
//=============================================================================
522494
Bool W3DDisplay::setDisplayMode( UnsignedInt xres, UnsignedInt yres, UnsignedInt bitdepth, Bool windowed )

Generals/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,7 +977,10 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int
977977
bool ret;
978978

979979
if (reset_device)
980+
{
981+
WWDEBUG_SAY(("DX8Wrapper::Set_Render_Device is resetting the device.\n"));
980982
ret = Reset_Device(restore_assets); //reset device without restoring data - we're likely switching out of the app.
983+
}
981984
else
982985
ret = Create_Device();
983986

@@ -1049,6 +1052,7 @@ void DX8Wrapper::Set_Swap_Interval(int swap)
10491052
default: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
10501053
}
10511054

1055+
WWDEBUG_SAY(("DX8Wrapper::Set_Swap_Interval is resetting the device.\n"));
10521056
Reset_Device();
10531057
}
10541058

@@ -1148,6 +1152,7 @@ bool DX8Wrapper::Set_Device_Resolution(int width,int height,int bits,int windowe
11481152
}
11491153
}
11501154
#pragma message("TODO: support changing windowed status and changing the bit depth")
1155+
WWDEBUG_SAY(("DX8Wrapper::Set_Device_Resolution is resetting the device.\n"));
11511156
return Reset_Device();
11521157
} else {
11531158
return false;
@@ -1583,6 +1588,7 @@ void DX8Wrapper::End_Scene(bool flip_frames)
15831588
if (hr==D3DERR_DEVICELOST) {
15841589
hr=_Get_D3D_Device8()->TestCooperativeLevel();
15851590
if (hr==D3DERR_DEVICENOTRESET) {
1591+
WWDEBUG_SAY(("DX8Wrapper::End_Scene is resetting the device.\n"));
15861592
Reset_Device();
15871593
}
15881594
else {

Generals/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,8 @@ WW3DErrorType WW3D::Begin_Render(bool clear,bool clearz,const Vector3 & color, f
817817
// Check if the device needs to be reset
818818
if( D3DERR_DEVICENOTRESET == hr )
819819
{
820-
DX8Wrapper::Reset_Device();
820+
WWDEBUG_SAY(("WW3D::Begin_Render is resetting the device.\n"));
821+
DX8Wrapper::Reset_Device();
821822
}
822823

823824
return WW3D_ERROR_GENERIC;

Generals/Code/Main/WinMain.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,6 @@ const char *gAppPrefix = ""; /// So WB can have a different debug log file name.
8787
#define DEFAULT_XRESOLUTION 800
8888
#define DEFAULT_YRESOLUTION 600
8989

90-
extern void Reset_D3D_Device(bool active);
91-
9290
static Bool gInitializing = false;
9391
static Bool gDoPaint = true;
9492
static Bool isWinMainActive = false;
@@ -424,14 +422,20 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
424422
//-------------------------------------------------------------------------
425423
case WM_ACTIVATEAPP:
426424
{
427-
// DWORD threadId=GetCurrentThreadId();
428425
if ((bool) wParam != isWinMainActive)
429-
{ isWinMainActive = (BOOL) wParam;
426+
{
427+
// TheSuperHackers @bugfix xezon 11/05/2025 This event originally called DX8Wrapper::Reset_Device,
428+
// intended to clear resources on a lost device in fullscreen, but effectively also in
429+
// windowed mode, if the DXMaximizedWindowedMode shim was applied in newer versions of Windows,
430+
// which lead to unfortunate application crashing. Resetting the device on WM_ACTIVATEAPP instead
431+
// of TestCooperativeLevel() == D3DERR_DEVICENOTRESET is not a requirement. There are other code
432+
// paths that take care of that.
433+
434+
isWinMainActive = (BOOL) wParam;
430435

431436
if (TheGameEngine)
432437
TheGameEngine->setIsActive(isWinMainActive);
433438

434-
Reset_D3D_Device(isWinMainActive);
435439
if (isWinMainActive)
436440
{ //restore mouse cursor to our custom version.
437441
if (TheWin32Mouse)

GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -555,34 +555,6 @@ void W3DDisplay::setGamma(Real gamma, Real bright, Real contrast, Bool calibrate
555555
DX8Wrapper::Set_Gamma(gamma,bright,contrast,calibrate, false);
556556
}
557557

558-
/*Giant hack in order to keep the game from getting stuck when alt-tabbing*/
559-
void Reset_D3D_Device(bool active)
560-
{
561-
if (TheDisplay && WW3D::Is_Initted() && !TheDisplay->getWindowed())
562-
{
563-
if (active)
564-
{
565-
//switch back to desired mode when user alt-tabs back into game
566-
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true);
567-
OSVERSIONINFO osvi;
568-
osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
569-
if (GetVersionEx(&osvi))
570-
{ //check if we're running Win9x variant since they have buggy alt-tab that requires
571-
//reloading all textures.
572-
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
573-
{ //only do this on Win9x boxes because it makes alt-tab very slow.
574-
WW3D::_Invalidate_Textures();
575-
}
576-
}
577-
}
578-
else
579-
{
580-
//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.
581-
WW3D::Set_Render_Device( WW3D::Get_Render_Device(),TheDisplay->getWidth(),TheDisplay->getHeight(),TheDisplay->getBitDepth(),TheDisplay->getWindowed(),true, true, false);
582-
}
583-
}
584-
}
585-
586558
/** Set resolution of display */
587559
//=============================================================================
588560
Bool W3DDisplay::setDisplayMode( UnsignedInt xres, UnsignedInt yres, UnsignedInt bitdepth, Bool windowed )

GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dx8wrapper.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,10 @@ bool DX8Wrapper::Set_Render_Device(int dev, int width, int height, int bits, int
10671067
bool ret;
10681068

10691069
if (reset_device)
1070+
{
1071+
WWDEBUG_SAY(("DX8Wrapper::Set_Render_Device is resetting the device.\n"));
10701072
ret = Reset_Device(restore_assets); //reset device without restoring data - we're likely switching out of the app.
1073+
}
10711074
else
10721075
ret = Create_Device();
10731076

@@ -1139,6 +1142,7 @@ void DX8Wrapper::Set_Swap_Interval(int swap)
11391142
default: _PresentParameters.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE ; break;
11401143
}
11411144

1145+
WWDEBUG_SAY(("DX8Wrapper::Set_Swap_Interval is resetting the device.\n"));
11421146
Reset_Device();
11431147
}
11441148

@@ -1238,6 +1242,7 @@ bool DX8Wrapper::Set_Device_Resolution(int width,int height,int bits,int windowe
12381242
}
12391243
}
12401244
#pragma message("TODO: support changing windowed status and changing the bit depth")
1245+
WWDEBUG_SAY(("DX8Wrapper::Set_Device_Resolution is resetting the device.\n"));
12411246
return Reset_Device();
12421247
} else {
12431248
return false;
@@ -1728,6 +1733,7 @@ void DX8Wrapper::End_Scene(bool flip_frames)
17281733
if (hr==D3DERR_DEVICELOST) {
17291734
hr=_Get_D3D_Device8()->TestCooperativeLevel();
17301735
if (hr==D3DERR_DEVICENOTRESET) {
1736+
WWDEBUG_SAY(("DX8Wrapper::End_Scene is resetting the device.\n"));
17311737
Reset_Device();
17321738
}
17331739
else {

GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/ww3d.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,8 @@ WW3DErrorType WW3D::Begin_Render(bool clear,bool clearz,const Vector3 & color, f
810810
// Check if the device needs to be reset
811811
if( D3DERR_DEVICENOTRESET == hr )
812812
{
813-
DX8Wrapper::Reset_Device();
813+
WWDEBUG_SAY(("WW3D::Begin_Render is resetting the device.\n"));
814+
DX8Wrapper::Reset_Device();
814815
}
815816

816817
return WW3D_ERROR_GENERIC;

GeneralsMD/Code/Main/WinMain.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,6 @@ const char *gAppPrefix = ""; /// So WB can have a different debug log file name.
9090
#define DEFAULT_XRESOLUTION 800
9191
#define DEFAULT_YRESOLUTION 600
9292

93-
extern void Reset_D3D_Device(bool active);
94-
9593
static Bool gInitializing = false;
9694
static Bool gDoPaint = true;
9795
static Bool isWinMainActive = false;
@@ -446,14 +444,20 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
446444
//-------------------------------------------------------------------------
447445
case WM_ACTIVATEAPP:
448446
{
449-
// DWORD threadId=GetCurrentThreadId();
450447
if ((bool) wParam != isWinMainActive)
451-
{ isWinMainActive = (BOOL) wParam;
448+
{
449+
// TheSuperHackers @bugfix xezon 11/05/2025 This event originally called DX8Wrapper::Reset_Device,
450+
// intended to clear resources on a lost device in fullscreen, but effectively also in
451+
// windowed mode, if the DXMaximizedWindowedMode shim was applied in newer versions of Windows,
452+
// which lead to unfortunate application crashing. Resetting the device on WM_ACTIVATEAPP instead
453+
// of TestCooperativeLevel() == D3DERR_DEVICENOTRESET is not a requirement. There are other code
454+
// paths that take care of that.
455+
456+
isWinMainActive = (BOOL) wParam;
452457

453458
if (TheGameEngine)
454459
TheGameEngine->setIsActive(isWinMainActive);
455460

456-
Reset_D3D_Device(isWinMainActive);
457461
if (isWinMainActive)
458462
{ //restore mouse cursor to our custom version.
459463
if (TheWin32Mouse)

0 commit comments

Comments
 (0)