4117: Make fullscreen changes better (especially under windows) r=def- a=Jupeyy

This bug already existed in our current release, so its not related to some SDL update

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Jupeyy <jupjopjap@gmail.com>
This commit is contained in:
bors[bot] 2021-08-24 16:29:55 +00:00 committed by GitHub
commit a8c36540e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 46 deletions

View file

@ -1172,22 +1172,36 @@ void CGraphicsBackend_SDL_OpenGL::SetWindowGrab(bool Grab)
void CGraphicsBackend_SDL_OpenGL::ResizeWindow(int w, int h, int RefreshRate)
{
if(SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN)
// don't call resize events when the window is at fullscreen desktop
if((SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP)
{
SDL_DisplayMode SetMode = {};
SDL_DisplayMode ClosestMode = {};
SetMode.format = 0;
SetMode.w = w;
SetMode.h = h;
SetMode.refresh_rate = RefreshRate;
SDL_SetWindowDisplayMode(m_pWindow, SDL_GetClosestDisplayMode(g_Config.m_GfxScreen, &SetMode, &ClosestMode));
}
else
{
SDL_SetWindowSize(m_pWindow, w, h);
if(SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_MAXIMIZED)
// remove maximize flag
SDL_RestoreWindow(m_pWindow);
// if the window is at fullscreen use SDL_SetWindowDisplayMode instead, suggested by SDL
if(SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_FULLSCREEN)
{
#ifdef CONF_PLATFORM_WINDOWS
// in windows make the window windowed mode first, this prevents strange window glitches (other games probably do something similar)
SetWindowParams(0, 1);
#endif
SDL_DisplayMode SetMode = {};
SDL_DisplayMode ClosestMode = {};
SetMode.format = 0;
SetMode.w = w;
SetMode.h = h;
SetMode.refresh_rate = RefreshRate;
SDL_SetWindowDisplayMode(m_pWindow, SDL_GetClosestDisplayMode(g_Config.m_GfxScreen, &SetMode, &ClosestMode));
#ifdef CONF_PLATFORM_WINDOWS
// now change it back to fullscreen, this will restore the above set state, bcs SDL saves fullscreen modes appart from other video modes (as of SDL 2.0.16)
// see implementation of SDL_SetWindowDisplayMode
SetWindowParams(1, 0);
#endif
}
else
{
SDL_SetWindowSize(m_pWindow, w, h);
if(SDL_GetWindowFlags(m_pWindow) & SDL_WINDOW_MAXIMIZED)
// remove maximize flag
SDL_RestoreWindow(m_pWindow);
}
}
}

View file

@ -2329,41 +2329,47 @@ void CGraphics_Threaded::Resize(int w, int h, int RefreshRate, bool SetWindowSiz
if(!ForceResizeEvent && WindowWidth() == w && WindowHeight() == h && (RefreshRate != -1 && RefreshRate == m_ScreenRefreshRate))
return;
// if the size is changed manually, only set the window resize, a window size changed event is triggered anyway
if(SetWindowSize)
m_pBackend->ResizeWindow(w, h, RefreshRate);
m_pBackend->GetViewportSize(m_ScreenWidth, m_ScreenHeight);
// adjust the viewport to only allow certain aspect ratios
if(m_ScreenHeight > 4 * m_ScreenWidth / 5)
m_ScreenHeight = 4 * m_ScreenWidth / 5;
if(m_ScreenWidth > 21 * m_ScreenHeight / 9)
m_ScreenWidth = 21 * m_ScreenHeight / 9;
m_ScreenRefreshRate = RefreshRate == -1 ? m_ScreenRefreshRate : RefreshRate;
g_Config.m_GfxScreenWidth = w;
g_Config.m_GfxScreenHeight = h;
g_Config.m_GfxScreenRefreshRate = m_ScreenRefreshRate;
CCommandBuffer::SCommand_Update_Viewport Cmd;
Cmd.m_X = 0;
Cmd.m_Y = 0;
Cmd.m_Width = m_ScreenWidth;
Cmd.m_Height = m_ScreenHeight;
if(!AddCmd(
Cmd, [] { return true; }, "failed to add resize command"))
{
return;
m_pBackend->ResizeWindow(w, h, RefreshRate);
}
else
{
// if the size change event is triggered, set all parameters and change the viewport
m_pBackend->GetViewportSize(m_ScreenWidth, m_ScreenHeight);
// kick the command buffer
KickCommandBuffer();
WaitForIdle();
// adjust the viewport to only allow certain aspect ratios
if(m_ScreenHeight > 4 * m_ScreenWidth / 5)
m_ScreenHeight = 4 * m_ScreenWidth / 5;
if(m_ScreenWidth > 21 * m_ScreenHeight / 9)
m_ScreenWidth = 21 * m_ScreenHeight / 9;
for(auto &ResizeListener : m_ResizeListeners)
ResizeListener.m_pFunc(ResizeListener.m_pUser);
m_ScreenRefreshRate = RefreshRate == -1 ? m_ScreenRefreshRate : RefreshRate;
g_Config.m_GfxScreenWidth = w;
g_Config.m_GfxScreenHeight = h;
g_Config.m_GfxScreenRefreshRate = m_ScreenRefreshRate;
CCommandBuffer::SCommand_Update_Viewport Cmd;
Cmd.m_X = 0;
Cmd.m_Y = 0;
Cmd.m_Width = m_ScreenWidth;
Cmd.m_Height = m_ScreenHeight;
if(!AddCmd(
Cmd, [] { return true; }, "failed to add resize command"))
{
return;
}
// kick the command buffer
KickCommandBuffer();
WaitForIdle();
for(auto &ResizeListener : m_ResizeListeners)
ResizeListener.m_pFunc(ResizeListener.m_pUser);
}
}
void CGraphics_Threaded::AddWindowResizeListener(WINDOW_RESIZE_FUNC pFunc, void *pUser)

View file

@ -344,7 +344,8 @@ int CInput::Update()
// shortcuts
switch(Event.window.event)
{
case SDL_WINDOWEVENT_RESIZED:
// listen to size changes, this includes our manual changes and the ones by the window manager
case SDL_WINDOWEVENT_SIZE_CHANGED:
Graphics()->Resize(Event.window.data1, Event.window.data2, -1);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED: