Skip to content

Commit

Permalink
Add preference repaintDuringResize_GotchaReentrantRepaint
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Jun 3, 2024
1 parent 7866ddf commit f92af95
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 18 deletions.
7 changes: 7 additions & 0 deletions src/hello_imgui/app_window_params.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ struct AppWindowParams
// `handleEdgeInsets`: _bool, default = true_. iOS only.
// If true, HelloImGui will handle the edgeInsets on iOS.
bool handleEdgeInsets = true;

// ----------------- repaint the window during resize -----------------
// Very advanced and reserved for advanced C++ users.
// If you set this to true, the window will be repainted during resize.
// Do read https://github.com/pthom/hello_imgui/issues/112 for info about the possible gotchas
// (This API is not stable, as the name suggests, and this is not supported)
bool repaintDuringResize_GotchaReentrantRepaint = false;
};
// @@md

Expand Down
7 changes: 7 additions & 0 deletions src/hello_imgui/doc_params.md
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,13 @@ struct AppWindowParams
// `handleEdgeInsets`: _bool, default = true_. iOS only.
// If true, HelloImGui will handle the edgeInsets on iOS.
bool handleEdgeInsets = true;

// ----------------- repaint the window during resize -----------------
// Very advanced and reserved for advanced C++ users.
// If you set this to true, the window will be repainted during resize.
// Do read https://github.com/pthom/hello_imgui/issues/112 for info about the possible gotchas
// (This API is not stable, as the name suggests, and this is not supported)
bool repaintDuringResize_GotchaReentrantRepaint = false;
};
```

Expand Down
48 changes: 38 additions & 10 deletions src/hello_imgui/internal/backend_impls/abstract_runner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,14 @@ void AbstractRunner::Setup()
auto fnRenderCallbackDuringResize = [this]()
{
if (! mWasWindowResizedByCodeDuringThisFrame)
{
//printf("Window resized by user\n");
CreateFramesAndRender(true);
}
else
{
//printf("Window resized by code\n");
}
};
Impl_CreateWindow(fnRenderCallbackDuringResize);

Expand Down Expand Up @@ -863,8 +870,19 @@ void AbstractRunner::RenderGui()
void _UpdateFrameRateStats(); // See hello_imgui.cpp


void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)
void AbstractRunner::CreateFramesAndRender(bool insideReentrantCall)
{
// Note: the reentrant call is non-existent for most cases:
// The preference
// repaintDuringResize_GotchaReentrantRepaint
// is false by default. As the name suggests, it is reserved for advanced users
// who are ready to deal with the possible consequences.
//
// This reentrant call is used to be able to repaint during window resize.
// It works on some combinations of OS / platform / rendering backends, but not all.
// See https://github.com/pthom/hello_imgui/issues/112
if (insideReentrantCall && ! params.appWindowParams.repaintDuringResize_GotchaReentrantRepaint)
return;

// ======================================================================================
// Introduction - Lambdas definitions
Expand Down Expand Up @@ -924,7 +942,7 @@ void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)


// handle window size and position on first frames
auto fnHandleWindowSizeAndPositionOnFirstFrames = [this]()
auto fnHandleWindowSizeAndPositionOnFirstFrames_AndAfterResize = [this]()
{
// Note about the application window initial placement and sizing
// i/ On the first frame (mIdxFrame==0), we create a window, and use the user provided size (if provided). The window is initially hidden.
Expand Down Expand Up @@ -1193,6 +1211,7 @@ void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)
//
// 2. Gotcha / possible re-entrance into this function when resizing the window
// -----------------------------------------------------------------------------
// See https://github.com/pthom/hello_imgui/issues/112
// There is a severe gotcha inside GLFW and SDL: PollEvent is supposed to
// return immediately, but it doesn't when resizing the window!
// If you do nothing, the window content is "stretching" during the resize
Expand All @@ -1213,11 +1232,12 @@ void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)
fnHandleLayout();
}


fnRegisterTests_UserCallback();

{
SCOPED_RELEASE_GIL_ON_MAIN_THREAD;
fnHandleWindowSizeAndPositionOnFirstFrames();
fnHandleWindowSizeAndPositionOnFirstFrames_AndAfterResize();
}

// Handle idling & poll events
Expand All @@ -1226,14 +1246,20 @@ void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)
// return immediately, but it doesn't when resizing the window!
// Instead, you have to subscribe to a kind of special "mid-resize" event,
// and then call the render function yourself.
if (!skipPollEvents)
fnHandleIdlingAndPollEvents_MayReRenderDuringResize_GotchaReentrant();
if (!insideReentrantCall) // Do not poll events again in a reentrant call!
{
// We cannot release the GIL here, since we may have a reentrant call!
if (!insideReentrantCall)
fnHandleIdlingAndPollEvents_MayReRenderDuringResize_GotchaReentrant();
}

_UpdateFrameRateStats(); // not in a SCOPED_RELEASE_GIL_ON_MAIN_THREAD, because it is very fast
{
_UpdateFrameRateStats(); // not in a SCOPED_RELEASE_GIL_ON_MAIN_THREAD, because it is very fast
fnLoadAdditionalFontDuringExecution_UserCallback(); // User callback
}

fnLoadAdditionalFontDuringExecution_UserCallback();

if (params.callbacks.PreNewFrame)
if ((params.callbacks.PreNewFrame) && !insideReentrantCall)
params.callbacks.PreNewFrame();

{
Expand All @@ -1245,9 +1271,11 @@ void AbstractRunner::CreateFramesAndRender(bool skipPollEvents)
// so that it can *NOT* be called inside SCOPED_RELEASE_GIL_ON_MAIN_THREAD
ImGui::NewFrame();

fnCheckOpenGlErrorOnFirstFrame_WarnPotentialFontError(); // not in a SCOPED_RELEASE_GIL_ON_MAIN_THREAD, because it is very fast and rare
{
fnCheckOpenGlErrorOnFirstFrame_WarnPotentialFontError(); // not in a SCOPED_RELEASE_GIL_ON_MAIN_THREAD, because it is very fast and rare

fnDrawCustomBackgroundOrClearColor_UserCallback();
fnDrawCustomBackgroundOrClearColor_UserCallback(); // User callback
}

// iii/ At the end of the second frame, we measure the size of the widgets and use it as the application window size,
// if the user required auto size
Expand Down
2 changes: 1 addition & 1 deletion src/hello_imgui/internal/backend_impls/abstract_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class AbstractRunner
virtual void Run(); // Only overriden in emscripten

void Setup();
void CreateFramesAndRender(bool skipPollEvents = false);
void CreateFramesAndRender(bool insideReentrantCall = false);
void RenderGui();
void TearDown(bool gotException);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ namespace HelloImGui { namespace BackendApi
}
static void WindowSizeCallback(GLFWwindow* window, int width, int height)
{
return; // Re-entrance into CreateFramesAndRender may break!

//printf("WindowSizeCallback: %ix%i\n", width, height);
// See https://github.com/pthom/hello_imgui/issues/112
// This may trigger a reentrant call to
// AbstractRunner::CreateFramesAndRender()
// By default, this is disabled.
// See pref AppWindowParams.repaintDuringResize_GotchaReentrantRepaint
if (gRenderCallbackDuringResize_Glfw)
gRenderCallbackDuringResize_Glfw();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,16 @@ namespace HelloImGui { namespace BackendApi

static int resizingEventWatcher(void* data, SDL_Event* event)
{
return 0; // Re-entrance into CreateFramesAndRender may break!

// See https://github.com/pthom/hello_imgui/issues/112
// This may trigger a reentrant call to
// AbstractRunner::CreateFramesAndRender()
// By default, this is disabled.
// See pref AppWindowParams.repaintDuringResize_GotchaReentrantRepaint
if (event->type == SDL_WINDOWEVENT &&
event->window.event == SDL_WINDOWEVENT_RESIZED) {
SDL_Window* win = SDL_GetWindowFromID(event->window.windowID);
if (win == (SDL_Window*)data) {
if (win == (SDL_Window*)data)
{
if (gRenderCallbackDuringResize_Sdl)
gRenderCallbackDuringResize_Sdl();
}
Expand Down
2 changes: 1 addition & 1 deletion src/hello_imgui/internal/backend_impls/runner_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace HelloImGui
void RunnerSdl2::Impl_PollEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
while (SDL_PollEvent(&event))
{
if (params.callbacks.AnyBackendEventCallback)
{
Expand Down

0 comments on commit f92af95

Please sign in to comment.