From b46f929178c638ee44b82c3c8faa58130f37ea88 Mon Sep 17 00:00:00 2001 From: glitchbear <161911268+glitchybear@users.noreply.github.com> Date: Wed, 27 Nov 2024 11:57:19 -0600 Subject: [PATCH] Fixed display settings and refresh rate selection for exclusive fullscreen mode. Now applies the selected settings to the preferred display instead of the primary display. --- src/archutils/Win32/Crash.cpp | 40 +++++++++++++++++++++++--- src/archutils/Win32/GraphicsWindow.cpp | 14 ++++----- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/archutils/Win32/Crash.cpp b/src/archutils/Win32/Crash.cpp index a87e54ad18..faf7bc7d08 100644 --- a/src/archutils/Win32/Crash.cpp +++ b/src/archutils/Win32/Crash.cpp @@ -349,13 +349,45 @@ static DWORD WINAPI MainExceptionHandler( LPVOID lpParameter ) /* The thread that crashed was the thread that created the main window. * Hide the window. This will also restore the video mode, if necessary. */ ShowWindow( g_hForegroundWnd, SW_HIDE ); - } else { + } + else { /* A different thread crashed. Simply kill all other windows. We can't * safely call ShowWindow; the main thread might be deadlocked. */ - RageThread::HaltAllThreads( true ); - ChangeDisplaySettings( nullptr, 0 ); - } + RageThread::HaltAllThreads(true); + auto deviceModeIsValid = [=](const DEVMODE& mode) { + return (mode.dmFields & DM_PELSWIDTH) && (mode.dmFields & DM_PELSHEIGHT) + && (mode.dmFields & DM_DISPLAYFREQUENCY) + && (mode.dmBitsPerPel >= 32 || !(mode.dmFields & DM_BITSPERPEL)); + }; + DEVMODE devmode; + ZeroMemory(&devmode, sizeof(DEVMODE)); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + + DWORD deviceIter = 0; + DISPLAY_DEVICE dd; + ZeroMemory(&dd, sizeof(dd)); + dd.cb = sizeof(dd); + + /* Since we don't know which display was modified for fullscreen exclusive mode, + * loop through all displays it could have been to restore the video mode. */ + while (EnumDisplayDevices(NULL, deviceIter++, &dd, 0)) + { + while (EnumDisplaySettingsEx(dd.DeviceName, ENUM_CURRENT_SETTINGS, &devmode, 0)) + { + if (deviceModeIsValid(devmode)) + { + ChangeDisplaySettingsEx(dd.DeviceName, nullptr, nullptr, 0, nullptr); + } + ZeroMemory(&devmode, sizeof(DEVMODE)); + devmode.dmSize = sizeof(DEVMODE); + devmode.dmDriverExtra = 0; + } + } + ZeroMemory(&dd, sizeof(dd)); + dd.cb = sizeof(dd); + } InHere = false; SetUnhandledExceptionFilter(nullptr); diff --git a/src/archutils/Win32/GraphicsWindow.cpp b/src/archutils/Win32/GraphicsWindow.cpp index 27ce1968bc..b2ebd0d722 100644 --- a/src/archutils/Win32/GraphicsWindow.cpp +++ b/src/archutils/Win32/GraphicsWindow.cpp @@ -87,13 +87,13 @@ static LRESULT CALLBACK GraphicsWindow_WndProc( HWND hWnd, UINT msg, WPARAM wPar * because that's where most other apps seem to do it. */ if( g_bHasFocus && !bHadFocus ) { - ChangeDisplaySettings( &g_FullScreenDevMode, CDS_FULLSCREEN ); + ChangeDisplaySettingsEx( g_CurrentParams.sDisplayId, &g_FullScreenDevMode, nullptr, CDS_FULLSCREEN, nullptr ); ShowWindow( g_hWndMain, SW_SHOWNORMAL ); SetWindowPos( g_hWndMain, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); } else if( !g_bHasFocus && bHadFocus ) { - ChangeDisplaySettings( nullptr, 0 ); + ChangeDisplaySettingsEx(g_CurrentParams.sDisplayId, nullptr, nullptr, 0, nullptr); } } @@ -228,7 +228,7 @@ RString GraphicsWindow::SetScreenMode( const VideoModeParams &p ) if( p.windowed ) { // We're going windowed. If we were previously fullscreen, reset. - ChangeDisplaySettings( nullptr, 0 ); + ChangeDisplaySettingsEx( p.sDisplayId, nullptr, nullptr, 0, nullptr ); return RString(); } @@ -246,13 +246,13 @@ RString GraphicsWindow::SetScreenMode( const VideoModeParams &p ) DevMode.dmDisplayFrequency = p.rate; DevMode.dmFields |= DM_DISPLAYFREQUENCY; } - ChangeDisplaySettings( nullptr, 0 ); + ChangeDisplaySettingsEx(p.sDisplayId, nullptr, nullptr, 0, nullptr); - int ret = ChangeDisplaySettings( &DevMode, CDS_FULLSCREEN ); + int ret = ChangeDisplaySettingsEx( p.sDisplayId, &DevMode, nullptr, CDS_FULLSCREEN, nullptr ); if( ret != DISP_CHANGE_SUCCESSFUL && (DevMode.dmFields & DM_DISPLAYFREQUENCY) ) { DevMode.dmFields &= ~DM_DISPLAYFREQUENCY; - ret = ChangeDisplaySettings( &DevMode, CDS_FULLSCREEN ); + ret = ChangeDisplaySettingsEx( p.sDisplayId, &DevMode, nullptr, CDS_FULLSCREEN, nullptr ); } // XXX: append error @@ -514,7 +514,7 @@ void GraphicsWindow::Shutdown() * It'd be nice to not do this: Windows will do it when we quit, and if * we're shutting down OpenGL to try D3D, this will cause extra mode * switches. However, we need to do this before displaying dialogs. */ - ChangeDisplaySettings( nullptr, 0 ); + ChangeDisplaySettingsEx( g_CurrentParams.sDisplayId, nullptr, nullptr, 0, nullptr ); AppInstance inst; UnregisterClass( g_sClassName, inst );