From 66f6637f594239781dfc8e45b1bc0239597f1a32 Mon Sep 17 00:00:00 2001 From: lhog <1476261+lhog@users.noreply.github.com> Date: Sun, 2 Jan 2022 21:28:59 +0300 Subject: [PATCH] BAR105 Window / Resolution improvements (#152) * Expose window borders via LuaUnsyncedRead, somewhat sanitized globalrendering winres implementation * Remove legacy and weird resolution constraints. Many of them are not weird or legacy anymore * Expose display name to Lua too * Expose screenPos{X,Y}. Can be non-0 if spring window is not on the main monitor * Exposed Spring.SetWindowGeometry() as slightly unfriendly, but a prefered way to set up spring window geometry --- rts/Lua/LuaConstPlatform.cpp | 17 ++-- rts/Lua/LuaHandle.cpp | 8 +- rts/Lua/LuaUnsyncedCtrl.cpp | 24 +++++- rts/Lua/LuaUnsyncedCtrl.h | 2 + rts/Lua/LuaUnsyncedRead.cpp | 12 ++- rts/Rendering/GL/myGL.cpp | 19 ++--- rts/Rendering/GlobalRendering.cpp | 117 ++++++++++++++++++++++++---- rts/Rendering/GlobalRendering.h | 15 +++- rts/Rendering/GlobalRenderingInfo.h | 12 ++- rts/System/SpringApp.cpp | 1 + 10 files changed, 189 insertions(+), 38 deletions(-) diff --git a/rts/Lua/LuaConstPlatform.cpp b/rts/Lua/LuaConstPlatform.cpp index 8564c92c95..fbe41b4cb6 100644 --- a/rts/Lua/LuaConstPlatform.cpp +++ b/rts/Lua/LuaConstPlatform.cpp @@ -32,27 +32,32 @@ bool LuaConstPlatform::PushEntries(lua_State* L) for (int i = 0; i < globalRenderingInfo.availableVideoModes.size(); ++i) { lua_pushnumber(L, i + 1); - lua_createtable(L, 0, 5); + lua_createtable(L, 0, 6); lua_pushsstring(L, "display"); - lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i][0]); + lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i].displayIndex); + lua_rawset(L, -3); + + lua_pushsstring(L, "displayName"); + lua_pushsstring(L, globalRenderingInfo.availableVideoModes[i].displayName.c_str()); lua_rawset(L, -3); lua_pushsstring(L, "w"); - lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i][1]); + lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i].width); lua_rawset(L, -3); lua_pushsstring(L, "h"); - lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i][2]); + lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i].height); lua_rawset(L, -3); lua_pushsstring(L, "bpp"); - lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i][3]); + lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i].bpp); lua_rawset(L, -3); lua_pushsstring(L, "hz"); - lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i][4]); + lua_pushnumber(L, globalRenderingInfo.availableVideoModes[i].refreshRate); lua_rawset(L, -3); + lua_rawset(L, -3); } lua_rawset(L, -3); diff --git a/rts/Lua/LuaHandle.cpp b/rts/Lua/LuaHandle.cpp index 05d2543866..f9a652c815 100644 --- a/rts/Lua/LuaHandle.cpp +++ b/rts/Lua/LuaHandle.cpp @@ -1699,12 +1699,16 @@ void CLuaHandle::ViewResize() lua_newtable(L); LuaPushNamedNumber(L, "screenSizeX", globalRendering->screenSizeX); LuaPushNamedNumber(L, "screenSizeY", globalRendering->screenSizeY); - LuaPushNamedNumber(L, "screenPosX", 0.0f); - LuaPushNamedNumber(L, "screenPosY", 0.0f); + LuaPushNamedNumber(L, "screenPosX", globalRendering->screenPosX); + LuaPushNamedNumber(L, "screenPosY", globalRendering->screenPosY); LuaPushNamedNumber(L, "windowSizeX", globalRendering->winSizeX); LuaPushNamedNumber(L, "windowSizeY", globalRendering->winSizeY); LuaPushNamedNumber(L, "windowPosX", globalRendering->winPosX); LuaPushNamedNumber(L, "windowPosY", winPosY_bl); + LuaPushNamedNumber(L, "windowBorderTop" , globalRendering->winBorder[0]); + LuaPushNamedNumber(L, "windowBorderLeft" , globalRendering->winBorder[1]); + LuaPushNamedNumber(L, "windowBorderBottom", globalRendering->winBorder[2]); + LuaPushNamedNumber(L, "windowBorderRight" , globalRendering->winBorder[3]); LuaPushNamedNumber(L, "viewSizeX", globalRendering->viewSizeX); LuaPushNamedNumber(L, "viewSizeY", globalRendering->viewSizeY); LuaPushNamedNumber(L, "viewPosX", globalRendering->viewPosX); diff --git a/rts/Lua/LuaUnsyncedCtrl.cpp b/rts/Lua/LuaUnsyncedCtrl.cpp index 8b15c2d9bb..14d544780e 100644 --- a/rts/Lua/LuaUnsyncedCtrl.cpp +++ b/rts/Lua/LuaUnsyncedCtrl.cpp @@ -286,6 +286,8 @@ bool LuaUnsyncedCtrl::PushEntries(lua_State* L) REGISTER_LUA_CFUNC(SDLStartTextInput); REGISTER_LUA_CFUNC(SDLStopTextInput); + REGISTER_LUA_CFUNC(SetWindowGeometry); + return true; } @@ -2198,8 +2200,11 @@ int LuaUnsyncedCtrl::SetConfigInt(lua_State* L) return 0; } + const int val = luaL_checkint(L, 2); + const bool uo = luaL_optboolean(L, 3, false); + configHandler->EnableWriting(globalConfig.luaWritableConfigFile); - configHandler->Set(key, luaL_checkint(L, 2), luaL_optboolean(L, 3, false)); + configHandler->Set(key, val, uo); configHandler->EnableWriting(true); return 0; } @@ -3303,3 +3308,20 @@ int LuaUnsyncedCtrl::SDLStopTextInput(lua_State* L) SDL_StopTextInput(); return 0; } + +int LuaUnsyncedCtrl::SetWindowGeometry(lua_State* L) +{ + const int displayIndex = luaL_checkint(L, 1) - 1; + const int winRelPosX = luaL_checkint(L, 2); + const int winRelPosY = luaL_checkint(L, 3); + const int winSizeX = luaL_checkint(L, 4); + const int winSizeY = luaL_checkint(L, 5); + const int fullScreen = luaL_checkboolean(L, 6); + const int borderless = luaL_checkboolean(L, 7); + + const bool r = globalRendering->SetWindowPosHelper(displayIndex, winRelPosX, winRelPosY, winSizeX, winSizeY, fullScreen, borderless); + if (!r) + luaL_error(L, "[%s] Invalid function parameters\n", __func__); + + return 0; +} diff --git a/rts/Lua/LuaUnsyncedCtrl.h b/rts/Lua/LuaUnsyncedCtrl.h index e3d66cf6db..0e724fbf93 100644 --- a/rts/Lua/LuaUnsyncedCtrl.h +++ b/rts/Lua/LuaUnsyncedCtrl.h @@ -188,6 +188,8 @@ class LuaUnsyncedCtrl { static int SDLSetTextInputRect(lua_State* L); static int SDLStartTextInput(lua_State* L); static int SDLStopTextInput(lua_State* L); + + static int SetWindowGeometry(lua_State* L); }; #endif /* LUA_UNSYNCED_CTRL_H */ diff --git a/rts/Lua/LuaUnsyncedRead.cpp b/rts/Lua/LuaUnsyncedRead.cpp index de7c7eb1a5..587f999c5a 100644 --- a/rts/Lua/LuaUnsyncedRead.cpp +++ b/rts/Lua/LuaUnsyncedRead.cpp @@ -499,7 +499,12 @@ int LuaUnsyncedRead::GetWindowGeometry(lua_State* L) lua_pushnumber(L, globalRendering->winSizeY); lua_pushnumber(L, globalRendering->winPosX); lua_pushnumber(L, winPosY_bl); - return 4; + + lua_pushnumber(L, globalRendering->winBorder[0]); + lua_pushnumber(L, globalRendering->winBorder[1]); + lua_pushnumber(L, globalRendering->winBorder[2]); + lua_pushnumber(L, globalRendering->winBorder[3]); + return 4 + 4; } @@ -507,8 +512,9 @@ int LuaUnsyncedRead::GetScreenGeometry(lua_State* L) { lua_pushnumber(L, globalRendering->screenSizeX); lua_pushnumber(L, globalRendering->screenSizeY); - lua_pushnumber(L, 0.0f); - lua_pushnumber(L, 0.0f); + lua_pushnumber(L, globalRendering->screenPosX); + lua_pushnumber(L, globalRendering->screenPosY); + return 4; } diff --git a/rts/Rendering/GL/myGL.cpp b/rts/Rendering/GL/myGL.cpp index c93da7e49c..ceb4fbfae3 100644 --- a/rts/Rendering/GL/myGL.cpp +++ b/rts/Rendering/GL/myGL.cpp @@ -76,24 +76,25 @@ bool CheckAvailableVideoModes() SDL_DisplayMode pm = {0, 0, 0, 0, nullptr}; SDL_Rect db; SDL_GetDisplayBounds(k, &db); + const std::string dn = SDL_GetDisplayName(k); - LOG("\tdisplay=%d modes=%d bounds={x=%d, y=%d, w=%d, h=%d}", k + 1, numModes, db.x, db.y, db.w, db.h); + LOG("\tDisplay (%s)=%d modes=%d bounds={x=%d, y=%d, w=%d, h=%d}", dn.c_str(), k + 1, numModes, db.x, db.y, db.w, db.h); for (int i = 0; i < numModes; ++i) { SDL_GetDisplayMode(k, i, &cm); - const float r0 = (cm.w * 9.0f) / cm.h; - const float r1 = (cm.w * 10.0f) / cm.h; - const float r2 = (cm.w * 16.0f) / cm.h; - - // skip legacy (3:2, 4:3, 5:4, ...) and weird (10:6, ...) ratios - if (r0 != 16.0f && r1 != 16.0f && r2 != 25.0f) - continue; // show only the largest refresh-rate and bit-depth per resolution if (cm.w == pm.w && cm.h == pm.h && (SDL_BPP(cm.format) < SDL_BPP(pm.format) || cm.refresh_rate < pm.refresh_rate)) continue; - globalRenderingInfo.availableVideoModes.emplace_back(std::array{ k + 1, cm.w, cm.h, static_cast(SDL_BPP(cm.format)), cm.refresh_rate }); + globalRenderingInfo.availableVideoModes.emplace_back(GlobalRenderingInfo::AvailableVideoMode{ + dn, + k + 1, + cm.w, + cm.h, + static_cast(SDL_BPP(cm.format)), + cm.refresh_rate + }); LOG("\t\t[%2i] %ix%ix%ibpp@%iHz", int(i + 1), cm.w, cm.h, SDL_BPP(cm.format), cm.refresh_rate); pm = cm; diff --git a/rts/Rendering/GlobalRendering.cpp b/rts/Rendering/GlobalRendering.cpp index be7b79a004..d09bfb099f 100644 --- a/rts/Rendering/GlobalRendering.cpp +++ b/rts/Rendering/GlobalRendering.cpp @@ -103,6 +103,8 @@ CR_REG_METADATA(CGlobalRendering, ( CR_IGNORED(screenSizeX), CR_IGNORED(screenSizeY), + CR_IGNORED(screenPosX), + CR_IGNORED(screenPosY), CR_IGNORED(winPosX), CR_IGNORED(winPosY), CR_IGNORED(winSizeX), @@ -111,6 +113,8 @@ CR_REG_METADATA(CGlobalRendering, ( CR_IGNORED(viewPosY), CR_IGNORED(viewSizeX), CR_IGNORED(viewSizeY), + CR_IGNORED(winBorder), + CR_IGNORED(winChgFrame), CR_IGNORED(screenViewMatrix), CR_IGNORED(screenProjMatrix), CR_IGNORED(pixelX), @@ -186,6 +190,8 @@ CGlobalRendering::CGlobalRendering() , screenSizeX(1) , screenSizeY(1) + , screenPosX(0) + , screenPosY(0) // window geometry , winPosX(configHandler->GetInt("WindowPosX")) @@ -199,6 +205,10 @@ CGlobalRendering::CGlobalRendering() , viewSizeX(1) , viewSizeY(1) + , winBorder{0} + + , winChgFrame(0) + , screenViewMatrix() , screenProjMatrix() @@ -276,7 +286,16 @@ CGlobalRendering::CGlobalRendering() , glTimerQueries{0} { verticalSync->WrapNotifyOnChange(); - configHandler->NotifyOnChange(this, {"Fullscreen", "WindowBorderless"}); + configHandler->NotifyOnChange(this, { + "Fullscreen", + "WindowBorderless", + "XResolution", + "YResolution", + "XResolutionWindowed", + "YResolutionWindowed", + "WindowPosX", + "WindowPosY" + }); } CGlobalRendering::~CGlobalRendering() @@ -305,7 +324,7 @@ void CGlobalRendering::PreKill() } -SDL_Window* CGlobalRendering::CreateSDLWindow(const int2& winRes, const int2& minRes, const char* title, bool hidden) const +SDL_Window* CGlobalRendering::CreateSDLWindow(const int2& winRes, const int2& minRes, const char* title, bool hidden) { SDL_Window* newWindow = nullptr; @@ -940,8 +959,11 @@ void CGlobalRendering::SetWindowTitle(const std::string& title) SDL_SetWindowTitle(sdlWindows[0], title.c_str()); } -void CGlobalRendering::ConfigNotify(const std::string& key, const std::string& value) +void CGlobalRendering::UpdateWindow() { + if (winChgFrame < drawFrame) + return; + if (sdlWindows[0] == nullptr) return; @@ -958,40 +980,59 @@ void CGlobalRendering::ConfigNotify(const std::string& key, const std::string& v const int2 newRes = GetCfgWinRes(fullScreen); const int2 maxRes = GetMaxWinRes(); - LOG("[GR::%s][1] key=%s val=%s (cfgFullScreen=%d sdlFullScreen=%d) newRes=<%d,%d>", __func__, key.c_str(), value.c_str(), fullScreen, fullScreenFlag == SDL_WINDOW_FULLSCREEN, newRes.x, newRes.y); + LOG("[GR::%s][1] (cfgFullScreen=%d sdlFullScreen=%d) newRes=<%d,%d>", __func__, fullScreen, fullScreenFlag == SDL_WINDOW_FULLSCREEN, newRes.x, newRes.y); // if currently in fullscreen mode, neither SDL_SetWindowSize nor SDL_SetWindowBordered will work // need to first drop to windowed mode before changing these properties, then switch modes again // the maximized-flag also has to be cleared, otherwise going from native fullscreen to windowed // ignores the configured *ResolutionWindowed values // (SDL_SetWindowDisplayMode sets the mode used by fullscreen windows which is not what we want) - #if 0 +#if 0 if (fullScreenFlag == SDL_WINDOW_FULLSCREEN) { SDL_SetWindowFullscreen(sdlWindows[0], 0); SDL_RestoreWindow(sdlWindows[0]); } - #endif +#endif if (SDL_SetWindowFullscreen(sdlWindows[0], 0) != 0) LOG("[GR::%s][2][SDL_SetWindowFullscreen] err=\"%s\"", __func__, SDL_GetError()); + screenPosX = 0; + screenPosY = 0; + screenSizeX = maxRes.x; + screenSizeY = maxRes.y; + + winPosX = configHandler->GetInt("WindowPosX"); + winPosY = configHandler->GetInt("WindowPosY"); + winSizeX = newRes.x; + winSizeY = newRes.y; + SDL_RestoreWindow(sdlWindows[0]); - SDL_SetWindowPosition(sdlWindows[0], configHandler->GetInt("WindowPosX"), configHandler->GetInt("WindowPosY")); - SDL_SetWindowSize(sdlWindows[0], newRes.x, newRes.y); SDL_SetWindowBordered(sdlWindows[0], borderless ? SDL_FALSE : SDL_TRUE); - if (SDL_SetWindowFullscreen(sdlWindows[0], (borderless? SDL_WINDOW_FULLSCREEN_DESKTOP: SDL_WINDOW_FULLSCREEN) * fullScreen) != 0) - LOG("[GR::%s][3][SDL_SetWindowFullscreen] err=\"%s\"", __func__, SDL_GetError()); + SDL_GetWindowBordersSize(sdlWindows[0], &winBorder[0], &winBorder[1], &winBorder[2], &winBorder[3]); + + SDL_SetWindowPosition(sdlWindows[0], winPosX, winPosY); + SDL_SetWindowSize(sdlWindows[0], newRes.x, newRes.y); if (newRes == maxRes) SDL_MaximizeWindow(sdlWindows[0]); WindowManagerHelper::SetWindowResizable(sdlWindows[0], !borderless && !fullScreen); + if (SDL_SetWindowFullscreen(sdlWindows[0], (borderless ? SDL_WINDOW_FULLSCREEN_DESKTOP : SDL_WINDOW_FULLSCREEN) * fullScreen) != 0) + LOG("[GR::%s][3][SDL_SetWindowFullscreen] err=\"%s\"", __func__, SDL_GetError()); + // on Windows, fullscreen-to-windowed switches can sometimes cause the context to be lost (?) MakeCurrentContext(false, false, false); } +void CGlobalRendering::ConfigNotify(const std::string& key, const std::string& value) +{ + LOG("[GR::%s][1] key=%s val=%s", __func__, key.c_str(), value.c_str()); + winChgFrame = drawFrame + 1; //will happen on next frame +} + bool CGlobalRendering::GetWindowInputGrabbing() { @@ -1012,6 +1053,45 @@ bool CGlobalRendering::ToggleWindowInputGrabbing() return (SetWindowInputGrabbing(true)); } +bool CGlobalRendering::SetWindowPosHelper(int displayIdx, int winRPosX, int winRPosY, int winSizeX_, int winSizeY_, bool fs, bool bl) +{ + if (fs && !bl) //fullscreen and not borderless + return false; + + const int numDisplays = SDL_GetNumVideoDisplays(); + if (displayIdx < 0 || displayIdx >= numDisplays) + return false; + + SDL_Rect db; + + if (fs) + SDL_GetDisplayBounds(displayIdx, &db); + else + SDL_GetDisplayUsableBounds(displayIdx, &db); + + const int2 tlPos = { db.x + winRPosX , db.y + winRPosY }; + const int2 brPos = { db.x + winRPosX + winSizeX_, db.y + winRPosY + winSizeY_ }; + + if ((tlPos.x < db.x) || (tlPos.y < db.y) || (tlPos.x > db.x + db.w) || (tlPos.y > db.y + db.h)) + return false; + + if (fs && (winRPosX != 0 || winRPosY != 0 || winSizeX_ != db.w || winSizeY_ != db.h)) + return false; + + configHandler->Set("WindowPosX", tlPos.x); + configHandler->Set("WindowPosY", tlPos.y); + + static const char* xsKeys[2] = { "XResolutionWindowed", "XResolution" }; + static const char* ysKeys[2] = { "YResolutionWindowed", "YResolution" }; + + configHandler->Set(xsKeys[fs], winSizeX_); + configHandler->Set(ysKeys[fs], winSizeY_); + configHandler->Set("Fullscreen", fs); + configHandler->Set("WindowBorderless", bl); + + return true; +} + int2 CGlobalRendering::GetMaxWinRes() const { SDL_DisplayMode dmode; @@ -1083,6 +1163,8 @@ void CGlobalRendering::UpdatePixelGeometry() void CGlobalRendering::ReadWindowPosAndSize() { #ifdef HEADLESS + screenPosX = 8; + screenPosY = 8; screenSizeX = 8; screenSizeY = 8; winSizeX = 8; @@ -1091,20 +1173,27 @@ void CGlobalRendering::ReadWindowPosAndSize() winPosY = 0; #else - SDL_Rect screenSize; SDL_GetDisplayBounds(SDL_GetWindowDisplayIndex(sdlWindows[0]), &screenSize); + SDL_GetWindowBordersSize(sdlWindows[0], &winBorder[0], &winBorder[1], &winBorder[2], &winBorder[3]); + // no other good place to set these + screenPosX = screenSize.x; + screenPosY = screenSize.y; screenSizeX = screenSize.w; screenSizeY = screenSize.h; SDL_GetWindowSize(sdlWindows[0], &winSizeX, &winSizeY); SDL_GetWindowPosition(sdlWindows[0], &winPosX, &winPosY); - //enforce >=0 https://github.com/beyond-all-reason/spring/issues/23 - winPosX = std::max(winPosX, 0); - winPosY = std::max(winPosY, 0); + // enforce >=0 https://github.com/beyond-all-reason/spring/issues/23 + // enforce screenSize bounds instead + winPosX = std::max(winPosX, screenSize.x); + winPosY = std::max(winPosY, screenSize.y); + + winSizeX = std::min(winSizeX, screenSize.w); + winSizeY = std::min(winSizeY, screenSize.h); #endif // should be done by caller diff --git a/rts/Rendering/GlobalRendering.h b/rts/Rendering/GlobalRendering.h index a48663e1e4..644d7827fc 100644 --- a/rts/Rendering/GlobalRendering.h +++ b/rts/Rendering/GlobalRendering.h @@ -40,7 +40,7 @@ class CGlobalRendering { * Sets SDL video mode options/settings */ bool CreateWindowAndContext(const char* title, bool hidden); - SDL_Window* CreateSDLWindow(const int2& winRes, const int2& minRes, const char* title, bool hidden) const; + SDL_Window* CreateSDLWindow(const int2& winRes, const int2& minRes, const char* title, bool hidden); SDL_GLContext CreateGLContext(const int2& minCtx, SDL_Window* targetWindow) const; SDL_Window* GetWindow(size_t i) { return sdlWindows[i]; } SDL_GLContext GetContext(size_t i) { return glContexts[i]; } @@ -64,6 +64,7 @@ class CGlobalRendering { void LogDisplayMode(SDL_Window* window) const; void SetWindowTitle(const std::string& title); + void UpdateWindow(); // Notify on Fullscreen/WindowBorderless change void ConfigNotify(const std::string& key, const std::string& value); @@ -71,6 +72,8 @@ class CGlobalRendering { bool SetWindowInputGrabbing(bool enable); bool ToggleWindowInputGrabbing(); + bool SetWindowPosHelper(int displayIdx, int winRPosX, int winRPosY, int winSizeX_, int winSizeY_, bool fs, bool bl); + void SetFullScreen(bool cliWindowed, bool cliFullScreen); void SetDualScreenParams(); void UpdateViewPortGeometry(); @@ -125,6 +128,10 @@ class CGlobalRendering { int screenSizeX; int screenSizeY; + /// the screen offsets in pixels (in case display is not the first one) + int screenPosX; + int screenPosY; + /// the window position relative to the screen's bottom-left corner int winPosX; int winPosY; @@ -141,6 +148,12 @@ class CGlobalRendering { int viewSizeX; int viewSizeY; + /// the window borders + std::array winBorder; + + /// Some settings got changed need to adjust the way window is + unsigned int winChgFrame; + /// screen {View,Proj} matrices for rendering in pixel coordinates CMatrix44f screenViewMatrix; CMatrix44f screenProjMatrix; diff --git a/rts/Rendering/GlobalRenderingInfo.h b/rts/Rendering/GlobalRenderingInfo.h index 850a314a47..4065fdbf08 100644 --- a/rts/Rendering/GlobalRenderingInfo.h +++ b/rts/Rendering/GlobalRenderingInfo.h @@ -7,9 +7,17 @@ #include "System/type2.h" #include -#include struct GlobalRenderingInfo { + struct AvailableVideoMode { + std::string displayName; + int32_t displayIndex; + int32_t width; + int32_t height; + int32_t bpp; + int32_t refreshRate; + }; + const char* gpuName; const char* gpuVendor; @@ -29,7 +37,7 @@ struct GlobalRenderingInfo { SDL_version sdlVersionCompiled; SDL_version sdlVersionLinked; - std::vector> availableVideoModes; + std::vector availableVideoModes; }; extern GlobalRenderingInfo globalRenderingInfo; diff --git a/rts/System/SpringApp.cpp b/rts/System/SpringApp.cpp index e7e9df844c..303e70f3be 100644 --- a/rts/System/SpringApp.cpp +++ b/rts/System/SpringApp.cpp @@ -768,6 +768,7 @@ bool SpringApp::Update() swap = (retc && activeController != nullptr && activeController->Draw()); #endif + globalRendering->UpdateWindow(); // always swap by default, not doing so can upset some drivers globalRendering->SwapBuffers(swap, false); return retc;