diff --git a/src/olympic/studio/applib/src/app.cpp b/src/olympic/studio/applib/src/app.cpp index c7f4d18d..8507638c 100644 --- a/src/olympic/studio/applib/src/app.cpp +++ b/src/olympic/studio/applib/src/app.cpp @@ -43,7 +43,7 @@ static ox::Error runApp( oxLogError(turbine::setWindowIcon(*ctx, WindowIcons())); turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName); turbine::setKeyEventHandler(*ctx, keyEventHandler); - turbine::setRefreshWithin(*ctx, 0); + turbine::requireRefreshWithin(*ctx, 0); StudioUI ui(*ctx, projectDataDir); StudioUIDrawer drawer(ui); turbine::gl::addDrawer(*ctx, &drawer); diff --git a/src/olympic/studio/applib/src/deleteconfirmation.cpp b/src/olympic/studio/applib/src/deleteconfirmation.cpp index 56135433..e05ad400 100644 --- a/src/olympic/studio/applib/src/deleteconfirmation.cpp +++ b/src/olympic/studio/applib/src/deleteconfirmation.cpp @@ -2,6 +2,8 @@ * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include + #include #include "deleteconfirmation.hpp" @@ -43,6 +45,9 @@ void DeleteConfirmation::draw(Context &ctx) noexcept { ImGui::OpenPopup(title().c_str()); m_stage = Stage::Open; m_open = true; + // require extended refresh in case new contents require resize + // this can take around a second + turbine::requireRefreshFor(ctx.tctx, 1000); [[fallthrough]]; case Stage::Open: drawWindow(ctx.tctx, m_open, [this] { diff --git a/src/olympic/studio/applib/src/studioui.cpp b/src/olympic/studio/applib/src/studioui.cpp index d0aea543..c807c773 100644 --- a/src/olympic/studio/applib/src/studioui.cpp +++ b/src/olympic/studio/applib/src/studioui.cpp @@ -347,7 +347,7 @@ void StudioUI::drawTabs() noexcept { pc->activeTabItemName = m_activeEditor->itemPath(); } }); - turbine::setRefreshWithin(m_tctx, 0); + turbine::requireRefreshWithin(m_tctx, 0); } else [[likely]] { if (m_activeEditorUpdatePending == e.get()) [[unlikely]] { m_activeEditorUpdatePending = nullptr; diff --git a/src/olympic/studio/modlib/src/imguiutil.cpp b/src/olympic/studio/modlib/src/imguiutil.cpp index 9c61820a..e4886d9a 100644 --- a/src/olympic/studio/modlib/src/imguiutil.cpp +++ b/src/olympic/studio/modlib/src/imguiutil.cpp @@ -275,6 +275,9 @@ void QuestionPopup::draw(Context &ctx) noexcept { ImGui::OpenPopup(m_title.c_str()); m_stage = Stage::Open; m_open = true; + // require extended refresh in case new contents require resize + // this can take around a second + turbine::requireRefreshFor(ctx.tctx, 1000); [[fallthrough]]; case Stage::Open: centerNextWindow(ctx.tctx); diff --git a/src/olympic/turbine/include/turbine/gfx.hpp b/src/olympic/turbine/include/turbine/gfx.hpp index c5124233..1b2a55c3 100644 --- a/src/olympic/turbine/include/turbine/gfx.hpp +++ b/src/olympic/turbine/include/turbine/gfx.hpp @@ -49,6 +49,19 @@ ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept; * @param ctx - Context * @param ms - milliseconds */ -void setRefreshWithin(Context &ctx, int ms) noexcept; +void requireRefreshWithin(Context &ctx, int ms) noexcept; + +/** + * Stimulates screen to draw for a period of a short period of + * time (168 ms on GLFW implementation). + * @param ctx - Context + */ +void requireRefresh(Context &ctx) noexcept; + +/** + * Stimulates screen to draw for a specified period of time. + * @param ctx - Context + */ +void requireRefreshFor(Context &ctx, int ms) noexcept; } diff --git a/src/olympic/turbine/src/glfw/turbine.cpp b/src/olympic/turbine/src/glfw/turbine.cpp index 53666d81..ff02f4d0 100644 --- a/src/olympic/turbine/src/glfw/turbine.cpp +++ b/src/olympic/turbine/src/glfw/turbine.cpp @@ -155,6 +155,10 @@ static ox::Result toGlfwImgPixels(ox::SpanView const &iconPng return out; } +static void setMandatoryRefreshPeriod(Context &ctx, TimeMs const newVal) { + ctx.mandatoryRefreshPeriodEnd = ox::max(ctx.mandatoryRefreshPeriodEnd, newVal); +} + ox::Error setWindowIcon(Context &ctx, ox::SpanView> const &iconPngs) noexcept { if constexpr(ox::defines::OS != ox::OS::Darwin) { ox::Vector src; @@ -216,10 +220,19 @@ ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept { return {}; } -void setRefreshWithin(Context &ctx, int ms) noexcept { +void requireRefreshWithin(Context &ctx, int const ms) noexcept { ctx.refreshWithinMs = ox::min(ms, ctx.refreshWithinMs); } +void requireRefresh(Context &ctx) noexcept { + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); +} + +void requireRefreshFor(Context &ctx, int ms) noexcept { + ms = ox::max(0, ms); + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + static_cast(ms)); +} + static void draw(Context &ctx) noexcept { // draw start #if TURBINE_USE_IMGUI @@ -288,12 +301,12 @@ static void handleGlfwCursorPosEvent(GLFWwindow*, double, double) noexcept { static void handleGlfwMouseButtonEvent(GLFWwindow *window, int, int, int) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); } static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const action, int) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); if (action == GLFW_PRESS) { handleKeyPress(ctx, key, true); } else if (action == GLFW_RELEASE) { @@ -303,7 +316,7 @@ static void handleGlfwKeyEvent(GLFWwindow *window, int const key, int, int const static void handleGlfwWindowCloseEvent(GLFWwindow *window) noexcept { auto &ctx = *static_cast(glfwGetWindowUserPointer(window)); - ctx.mandatoryRefreshPeriodEnd = ticksMs(ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(ctx, ticksMs(ctx) + config::MandatoryRefreshPeriod); ctx.running = ctx.shutdownHandler ? !ctx.shutdownHandler(ctx) : false; glfwSetWindowShouldClose(window, !ctx.running); glfwPostEmptyEvent(); @@ -316,7 +329,7 @@ ox::Result> init( using namespace std::chrono; ctx->startTime = static_cast( duration_cast(system_clock::now().time_since_epoch()).count()); - ctx->mandatoryRefreshPeriodEnd = ticksMs(*ctx) + config::MandatoryRefreshPeriod; + setMandatoryRefreshPeriod(*ctx, ticksMs(*ctx) + config::MandatoryRefreshPeriod); // init GLFW context glfwInit(); glfwSetErrorCallback(handleGlfwError);