From f10f9768a5dc93bfc6cd556ea6df1c13900f42f4 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sun, 31 Aug 2025 13:15:55 +0200 Subject: [PATCH] allows resizing window in windowed mode --- client/GameEngine.cpp | 5 +++-- client/GameEngine.h | 2 +- client/eventsSDL/InputHandler.cpp | 6 ++---- client/eventsSDL/InputSourceKeyboard.cpp | 2 +- client/render/IScreenHandler.h | 2 +- client/renderSDL/ScreenHandler.cpp | 18 ++++++++++++++++-- client/renderSDL/ScreenHandler.h | 2 +- client/windows/settings/GeneralOptionsTab.cpp | 6 +++--- 8 files changed, 28 insertions(+), 15 deletions(-) diff --git a/client/GameEngine.cpp b/client/GameEngine.cpp index 283e611af..786577df6 100644 --- a/client/GameEngine.cpp +++ b/client/GameEngine.cpp @@ -281,10 +281,11 @@ void GameEngine::setStatusbar(const std::shared_ptr & newStatusBar) currentStatusBar = newStatusBar; } -void GameEngine::onScreenResize(bool resolutionChanged) +void GameEngine::onScreenResize(bool resolutionChanged, bool windowResized) { if(resolutionChanged) - screenHandler().onScreenResize(); + if(!screenHandler().onScreenResize(windowResized)) + return; windows().onScreenResize(); ENGINE->cursor().onScreenResize(); diff --git a/client/GameEngine.h b/client/GameEngine.h index 339032a31..07e365238 100644 --- a/client/GameEngine.h +++ b/client/GameEngine.h @@ -122,7 +122,7 @@ public: [[noreturn]] void mainLoop(); /// called whenever SDL_WINDOWEVENT_RESTORED is reported or the user selects a different resolution, requiring to center/resize all windows - void onScreenResize(bool resolutionChanged); + void onScreenResize(bool resolutionChanged, bool windowResized); /// Simulate mouse movement to force refresh UI state that updates on mouse move void fakeMouseMove(); diff --git a/client/eventsSDL/InputHandler.cpp b/client/eventsSDL/InputHandler.cpp index 194b360c5..91bcf2752 100644 --- a/client/eventsSDL/InputHandler.cpp +++ b/client/eventsSDL/InputHandler.cpp @@ -248,17 +248,15 @@ void InputHandler::preprocessEvent(const SDL_Event & ev) #ifndef VCMI_IOS { std::scoped_lock interfaceLock(ENGINE->interfaceMutex); - ENGINE->onScreenResize(false); + ENGINE->onScreenResize(false, false); } #endif break; case SDL_WINDOWEVENT_SIZE_CHANGED: -#ifdef VCMI_MOBILE { std::scoped_lock interfaceLock(ENGINE->interfaceMutex); - ENGINE->onScreenResize(true); + ENGINE->onScreenResize(true, true); } -#endif break; case SDL_WINDOWEVENT_FOCUS_GAINED: { diff --git a/client/eventsSDL/InputSourceKeyboard.cpp b/client/eventsSDL/InputSourceKeyboard.cpp index a3aad2a6b..28a318cdb 100644 --- a/client/eventsSDL/InputSourceKeyboard.cpp +++ b/client/eventsSDL/InputSourceKeyboard.cpp @@ -97,7 +97,7 @@ void InputSourceKeyboard::handleEventKeyDown(const SDL_KeyboardEvent & key) { Settings full = settings.write["video"]["fullscreen"]; full->Bool() = !full->Bool(); - ENGINE->onScreenResize(true); + ENGINE->onScreenResize(true, false); } if (vstd::contains(shortcutsVector, EShortcut::SPECTATE_TRACK_HERO)) diff --git a/client/render/IScreenHandler.h b/client/render/IScreenHandler.h index 18a518675..f959ce586 100644 --- a/client/render/IScreenHandler.h +++ b/client/render/IScreenHandler.h @@ -25,7 +25,7 @@ public: virtual ~IScreenHandler() = default; /// Updates window state after fullscreen state has been changed in settings - virtual void onScreenResize() = 0; + virtual bool onScreenResize(bool keepWindowResolution) = 0; /// Fills screen with black color, erasing any existing content virtual void clearScreen() = 0; diff --git a/client/renderSDL/ScreenHandler.cpp b/client/renderSDL/ScreenHandler.cpp index a490c9226..e234ef5ce 100644 --- a/client/renderSDL/ScreenHandler.cpp +++ b/client/renderSDL/ScreenHandler.cpp @@ -298,7 +298,6 @@ void ScreenHandler::updateWindowState() Point resolution = getPreferredWindowResolution(); SDL_SetWindowFullscreen(mainWindow, 0); SDL_SetWindowSize(mainWindow, resolution.x, resolution.y); - SDL_SetWindowPosition(mainWindow, SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex), SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex)); return; } } @@ -480,9 +479,24 @@ SDL_Window * ScreenHandler::createWindow() #endif } -void ScreenHandler::onScreenResize() +bool ScreenHandler::onScreenResize(bool keepWindowResolution) { + if(getPreferredWindowMode() == EWindowMode::WINDOWED && keepWindowResolution) + { + auto res = getRenderResolution(); + + if(res.x < heroes3Resolution.x || res.y < heroes3Resolution.y) + return false; + + Settings video = settings.write["video"]; + video["resolution"]["width"].Integer() = res.x; + video["resolution"]["height"].Integer() = res.y; + } + else if(keepWindowResolution) + return false; + recreateWindowAndScreenBuffers(); + return true; } void ScreenHandler::validateSettings() diff --git a/client/renderSDL/ScreenHandler.h b/client/renderSDL/ScreenHandler.h index aefae8d1d..78c3885bc 100644 --- a/client/renderSDL/ScreenHandler.h +++ b/client/renderSDL/ScreenHandler.h @@ -100,7 +100,7 @@ public: ~ScreenHandler(); /// Updates and potentially recreates target screen to match selected fullscreen status - void onScreenResize() final; + bool onScreenResize(bool keepWindowResolution) final; /// Fills screen with black color, erasing any existing content void clearScreen() final; diff --git a/client/windows/settings/GeneralOptionsTab.cpp b/client/windows/settings/GeneralOptionsTab.cpp index c00ef1be2..313c003fa 100644 --- a/client/windows/settings/GeneralOptionsTab.cpp +++ b/client/windows/settings/GeneralOptionsTab.cpp @@ -336,7 +336,7 @@ void GeneralOptionsTab::setGameResolution(int index) widget("resolutionLabel")->setText(resolutionToLabelString(resolution.x, resolution.y)); ENGINE->dispatchMainThread([](){ - ENGINE->onScreenResize(true); + ENGINE->onScreenResize(true, false); }); } @@ -360,7 +360,7 @@ void GeneralOptionsTab::setFullscreenMode(bool on, bool exclusive) updateResolutionSelector(); ENGINE->dispatchMainThread([](){ - ENGINE->onScreenResize(true); + ENGINE->onScreenResize(true, false); }); } @@ -419,7 +419,7 @@ void GeneralOptionsTab::setGameScaling(int index) widget("scalingLabel")->setText(scalingToLabelString(scaling)); ENGINE->dispatchMainThread([](){ - ENGINE->onScreenResize(true); + ENGINE->onScreenResize(true, false); }); }