From 7234c04c159fdd5068fb47f35ffc7361e1b651ca Mon Sep 17 00:00:00 2001 From: Jupeyy Date: Tue, 24 Aug 2021 18:22:31 +0200 Subject: [PATCH] Make fullscreen changes better (especially under windows) --- src/engine/client/backend_sdl.cpp | 44 +++++++++++------ src/engine/client/graphics_threaded.cpp | 66 ++++++++++++++----------- src/engine/client/input.cpp | 3 +- 3 files changed, 67 insertions(+), 46 deletions(-) diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp index 64f615dd1..f44ce4764 100644 --- a/src/engine/client/backend_sdl.cpp +++ b/src/engine/client/backend_sdl.cpp @@ -1168,22 +1168,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); + } } } diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp index 500a7a87e..95db030be 100644 --- a/src/engine/client/graphics_threaded.cpp +++ b/src/engine/client/graphics_threaded.cpp @@ -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) diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp index ae3b5308e..7bdf3eeb7 100644 --- a/src/engine/client/input.cpp +++ b/src/engine/client/input.cpp @@ -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: