diff --git a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp index 2f6ed1c6..b01051a5 100644 --- a/src/hello_imgui/internal/backend_impls/abstract_runner.cpp +++ b/src/hello_imgui/internal/backend_impls/abstract_runner.cpp @@ -159,6 +159,39 @@ void AbstractRunner::PrepareWindowGeometry() params.appWindowParams.windowGeometry.size = windowBounds.size; } + +// If needed, change the size to match the current DPI versus the DPI when the size was saved +// (we want the window to "look" as big as it was when saved, even if the DPI has changed, +// or if we are on a different monitor / computer / OS) +void AbstractRunner::AdjustWindowBoundsAfterCreation_IfDpiChangedBetweenRuns() +{ + bool reloadLastSize = params.appWindowParams.restorePreviousGeometry && + HelloImGuiIniSettings::LoadLastRunWindowBounds(IniSettingsLocation(params)).has_value(); + if (!reloadLastSize) + return; + + std::optional lastRunDpiWindowSizeFactorOpt = HelloImGuiIniSettings::LoadLastRunDpiWindowSizeFactor(IniSettingsLocation(params)); + if (!lastRunDpiWindowSizeFactorOpt.has_value()) + return; + + float lastRunDpiWindowSizeFactor = lastRunDpiWindowSizeFactorOpt.value(); + float currentDpiWindowSizeFactor = params.dpiAwareParams.dpiWindowSizeFactor; + float ratio = currentDpiWindowSizeFactor / lastRunDpiWindowSizeFactor; + bool isSane = ratio > 0.25f && ratio < 4.f; + if (isSane && ratio != 1.f) + { + auto bounds = mBackendWindowHelper->GetWindowBounds(mWindow); + bounds.size = {(int)((float)bounds.size[0] * ratio), + (int)((float)bounds.size[1] * ratio)}; + bounds.position = { + (int)((float)bounds.position[0] * ratio), + (int)((float)bounds.position[1] * ratio) + }; + mBackendWindowHelper->SetWindowBounds(mWindow, bounds); + } +} + + bool AbstractRunner::WantAutoSize() { #ifdef __EMSCRIPTEN__ @@ -717,6 +750,7 @@ void AbstractRunner::Setup() //printf("Window resized by code\n"); } }; + Impl_CreateWindow(fnRenderCallbackDuringResize); #ifdef HELLOIMGUI_HAS_OPENGL @@ -729,7 +763,10 @@ void AbstractRunner::Setup() Impl_SetWindowIcon(); + // The order is important: first read the DPI aware params SetupDpiAwareParams(); + // Then adjust window size if needed + AdjustWindowBoundsAfterCreation_IfDpiChangedBetweenRuns(); // This should be done before Impl_LinkPlatformAndRenderBackends() diff --git a/src/hello_imgui/internal/backend_impls/abstract_runner.h b/src/hello_imgui/internal/backend_impls/abstract_runner.h index be28e974..9f198655 100644 --- a/src/hello_imgui/internal/backend_impls/abstract_runner.h +++ b/src/hello_imgui/internal/backend_impls/abstract_runner.h @@ -90,6 +90,7 @@ class AbstractRunner void SetupDpiAwareParams(); bool CheckDpiAwareParamsChanges(); void PrepareWindowGeometry(); + void AdjustWindowBoundsAfterCreation_IfDpiChangedBetweenRuns(); void HandleDpiOnSecondFrame(); void MakeWindowSizeRelativeTo96Ppi_IfRequired(); bool ShallSizeWindowRelativeTo96Ppi(); diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp index 2098cb19..235d3205 100644 --- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp +++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp @@ -193,7 +193,6 @@ namespace HelloImGui if (!iniParts.HasIniPart("AppWindow")) return std::nullopt; - auto iniPartContent = iniParts.GetIniPart("AppWindow"); ini::IniFile iniFile; try @@ -235,50 +234,51 @@ namespace HelloImGui failed = true; } - // Read DPI Window Size Factor - // If needed, change the size to match the current DPI versus the DPI when the size was saved - // (we want the window to "look" as big as it was when saved, even if the DPI has changed, - // or if we are on a different monitor / computer / OS) + if (failed) + return std::nullopt; + else + return screenBounds; + + } + + std::optional LoadLastRunDpiWindowSizeFactor(const std::string& iniPartsFilename) + { + IniParts iniParts = IniParts::LoadFromFile(iniPartsFilename); + + if (!iniParts.HasIniPart("AppWindow")) + return std::nullopt; + + auto iniPartContent = iniParts.GetIniPart("AppWindow"); + ini::IniFile iniFile; + try { - // DpiWindowSizeFactor was added late, so it may not be present in the ini file - if (appWindowSection.find("DpiWindowSizeFactor") != appWindowSection.end()) - { - float dpiWindowSizeFactor_Now = - HelloImGui::GetRunnerParams()->dpiAwareParams.dpiWindowSizeFactor; - float dpiWindowSizeFactor_WhenSaved = - iniFile["AppWindow"]["DpiWindowSizeFactor"].as(); - bool isDpiSane = (dpiWindowSizeFactor_WhenSaved >= 0.1f) && - (dpiWindowSizeFactor_WhenSaved <= 10.f) && - (dpiWindowSizeFactor_Now > 0.1f) && - (dpiWindowSizeFactor_Now < 10.f); - if (isDpiSane) - { - float ratio = dpiWindowSizeFactor_Now / dpiWindowSizeFactor_WhenSaved; - if (ratio != 1.f) - { - auto applyRatio = [](int v, float ratio) -> int - { - return static_cast(static_cast(v) * ratio); - }; - screenBounds.position[0] = applyRatio(screenBounds.position[0], ratio); - screenBounds.position[1] = applyRatio(screenBounds.position[1], ratio); - screenBounds.size[0] = applyRatio(screenBounds.size[0], ratio); - screenBounds.size[1] = applyRatio(screenBounds.size[1], ratio); - } - } - } + iniFile.decode(iniPartContent); } + catch (const std::exception &) { - + return std::nullopt; } - if (failed) + ScreenBounds screenBounds; + bool failed = false; + + if (iniFile.find("AppWindow") == iniFile.end()) return std::nullopt; - else - return screenBounds; + auto &appWindowSection = iniFile["AppWindow"]; + if (appWindowSection.find("DpiWindowSizeFactor") != appWindowSection.end()) + { + float dpiWindowSizeFactor_WhenSaved = + iniFile["AppWindow"]["DpiWindowSizeFactor"].as(); + bool isDpiSane = (dpiWindowSizeFactor_WhenSaved >= 0.1f) && + (dpiWindowSizeFactor_WhenSaved <= 10.f); + if (isDpiSane) + return dpiWindowSizeFactor_WhenSaved; + } + return std::nullopt; } + void LoadImGuiSettings(const std::string& iniPartsFilename, const std::string& layoutName) { std::string iniPartName = "ImGui_" + details::SanitizeIniNameOrCategory(layoutName); diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.h b/src/hello_imgui/internal/hello_imgui_ini_settings.h index 49c4a1ca..ed86d49b 100644 --- a/src/hello_imgui/internal/hello_imgui_ini_settings.h +++ b/src/hello_imgui/internal/hello_imgui_ini_settings.h @@ -61,6 +61,7 @@ namespace HelloImGui // void SaveLastRunWindowBounds(const std::string& iniPartsFilename, const ScreenBounds& windowBounds); std::optional LoadLastRunWindowBounds(const std::string& iniPartsFilename); + std::optional LoadLastRunDpiWindowSizeFactor(const std::string& iniPartsFilename); void SaveHelloImGuiMiscSettings(const std::string& iniPartsFilename, const RunnerParams& runnerParams); void LoadHelloImGuiMiscSettings(const std::string& iniPartsFilename, RunnerParams* inOutRunnerParams);