Skip to content

Commit

Permalink
Merge branch 'render_resize'
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Jun 3, 2024
2 parents a0a0eff + 3ff11ce commit ec0d86d
Show file tree
Hide file tree
Showing 17 changed files with 337 additions and 133 deletions.
335 changes: 234 additions & 101 deletions src/hello_imgui/internal/backend_impls/abstract_runner.cpp

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions 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();
void CreateFramesAndRender(bool skipPollEvents = false);
void RenderGui();
void TearDown(bool gotException);

Expand Down Expand Up @@ -59,7 +59,7 @@ class AbstractRunner
// Methods related to the platform backend (SDL, Glfw, ...)
//
virtual void Impl_InitPlatformBackend() = 0;
virtual void Impl_CreateWindow() = 0;
virtual void Impl_CreateWindow(std::function<void()> renderCallbackDuringResize) = 0;
virtual void Impl_PollEvents() = 0;
virtual void Impl_NewFrame_PlatformBackend() = 0;
virtual void Impl_UpdateAndRenderAdditionalPlatformWindows() = 0;
Expand Down Expand Up @@ -114,6 +114,14 @@ class AbstractRunner
int mIdxFrame = 0;
bool mWasWindowAutoResizedOnPreviousFrame = false;

// Differentiate between cases where the window was resized by code
// and cases where the window was resized by the user
// (in which we have a gotcha, because PollEvents() will *block*
// until the user releases the mouse button)
bool mWasWindowResizedByCodeDuringThisFrame = false;
std::function<void()> setWasWindowResizedByCodeDuringThisFrame =
[&]() { mWasWindowResizedByCodeDuringThisFrame = true; };

// Callbacks related to the rendering backend (OpenGL, ...)
RenderingCallbacksPtr mRenderingBackendCallbacks;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ namespace HelloImGui { namespace BackendApi
// It is only a class in order to enforce a consistent API between backends.
public:
virtual ~IBackendWindowHelper() = default;
virtual WindowPointer CreateWindow(AppWindowParams &info, const BackendOptions& backendOptions) = 0;

// renderCallbackDuringResize is a callback that will be called during window resizing.
// to trigger a render
// This is due to severe gotcha inside GLFW and SDL: PollEvent is supposed to
// 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.
virtual WindowPointer CreateWindow(AppWindowParams &info, const BackendOptions& backendOptions,
std::function<void()> renderCallbackDuringResize) = 0;

// The area of a monitor not occupied by global task bars or menu bars is the work area.
// This is specified in screen coordinates.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,25 @@

namespace HelloImGui { namespace BackendApi
{
WindowPointer GlfwWindowHelper::CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions)
std::function<void()> gRenderCallbackDuringResize_Glfw;

static void FramebufferSizeCallback(GLFWwindow*, int width, int height)
{
// Not used, since WindowSizeCallback is called right after.
}
static void WindowSizeCallback(GLFWwindow* window, int width, int height)
{
if (gRenderCallbackDuringResize_Glfw)
gRenderCallbackDuringResize_Glfw();
}



WindowPointer GlfwWindowHelper::CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions,
std::function<void()> renderCallbackDuringResize)
{
gRenderCallbackDuringResize_Glfw = renderCallbackDuringResize;

auto searchMonitorResult = SearchForMonitor(GetMonitorsWorkAreas(), appWindowParams);
int realMonitorIdx = searchMonitorResult.monitorIdx;
if (searchMonitorResult.newPosition.has_value())
Expand Down Expand Up @@ -125,6 +142,8 @@ namespace HelloImGui { namespace BackendApi
glfwGetWindowSize(window, &windowSize[0], &windowSize[1]);
glfwGetWindowPos(window, &windowPosition[0], &windowPosition[1]);

glfwSetWindowSizeCallback(window, WindowSizeCallback);
glfwSetFramebufferSizeCallback(window, FramebufferSizeCallback);
// printf("Final window size: %ix%i\n", windowSize[0], windowSize[1]);
// printf("Final window position: %ix%i\n", windowPosition[0], windowPosition[1]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ namespace HelloImGui { namespace BackendApi
{
class GlfwWindowHelper: public IBackendWindowHelper
{

// Note: this is a fake class, it has no member
// It is only a class in order to enforce a consistent API between backends.
public:
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions) override;
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions,
std::function<void()> renderCallbackDuringResize) override;

std::vector<ScreenBounds> GetMonitorsWorkAreas() override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ namespace HelloImGui { namespace BackendApi
// Note: this is a fake class, it has no member
// It is only a class in order to enforce a consistent API between backends.
public:
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions) override {
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions,
std::function<void()> gRenderCallbackDuringResize) override {
mWindowBounds.size = appWindowParams.windowGeometry.size;
return nullptr;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,28 @@

namespace HelloImGui { namespace BackendApi
{
WindowPointer SdlWindowHelper::CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions)
std::function<void()> gRenderCallbackDuringResize_Sdl;

static int resizingEventWatcher(void* data, SDL_Event* event)
{
if (event->type == SDL_WINDOWEVENT &&
event->window.event == SDL_WINDOWEVENT_RESIZED) {
SDL_Window* win = SDL_GetWindowFromID(event->window.windowID);
if (win == (SDL_Window*)data) {
printf("resizingEventWatcher: resizing.....\n");
if (gRenderCallbackDuringResize_Sdl)
gRenderCallbackDuringResize_Sdl();
}
}
return 0;
}


WindowPointer SdlWindowHelper::CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions,
std::function<void()> renderCallbackDuringResize)
{
gRenderCallbackDuringResize_Sdl = renderCallbackDuringResize;

#ifdef _WIN32
if (backendOptions.dpiAwareSdl)
Internal::ImGui_ImplWin32_EnableDpiAwareness();
Expand Down Expand Up @@ -139,6 +159,9 @@ namespace HelloImGui { namespace BackendApi
// printf("Final window size: %ix%i\n", windowSize[0], windowSize[1]);
// printf("Final window position: %ix%i\n", windowPosition[0], windowPosition[1]);

SDL_AddEventWatch(resizingEventWatcher, window);


return (void *)(window);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ namespace HelloImGui { namespace BackendApi
// Note: this is a fake class, it has no member
// It is only a class in order to enforce a consistent API between backends.
public:
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions) override;
WindowPointer CreateWindow(AppWindowParams &appWindowParams, const BackendOptions& backendOptions,
std::function<void()> renderCallbackDuringResize) override;

std::vector<ScreenBounds> GetMonitorsWorkAreas() override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ namespace HelloImGui
///////////////////////////////


void WindowGeometryHelper::TrySetWindowSize(BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window, ImVec2 userWidgetsSize)
void WindowGeometryHelper::TrySetWindowSize(
BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window, ImVec2 userWidgetsSize,
std::function<void()> fnBeforeChangingWindowBounds)
{
int widgetsMargin = 6;

Expand All @@ -162,6 +164,7 @@ namespace HelloImGui
auto windowBounds = backendWindowHelper->GetWindowBounds(window);
windowBounds.size = computedSize;

fnBeforeChangingWindowBounds();
backendWindowHelper->SetWindowBounds(window, windowBounds);
}

Expand Down Expand Up @@ -206,7 +209,9 @@ namespace HelloImGui
return bestMonitorIdx;
}

void WindowGeometryHelper::EnsureWindowFitsMonitor(BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window)
void WindowGeometryHelper::EnsureWindowFitsMonitor(
BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window,
std::function<void()> fnBeforeChangingWindowBounds)
{
auto currentMonitorWorkArea = GetCurrentMonitorWorkArea(backendWindowHelper, window);

Expand All @@ -219,17 +224,20 @@ namespace HelloImGui
auto currentWindowBoundsNew = currentMonitorWorkArea.EnsureWindowFitsThisMonitor(currentWindowBounds);
if ( !(currentWindowBoundsNew == currentWindowBounds))
{
fnBeforeChangingWindowBounds();
backendWindowHelper->SetWindowBounds(window, currentWindowBoundsNew);
}
}

void WindowGeometryHelper::CenterWindowOnMonitor(BackendApi::IBackendWindowHelper* backendWindowHelper, BackendApi::WindowPointer window)
void WindowGeometryHelper::CenterWindowOnMonitor(
BackendApi::IBackendWindowHelper* backendWindowHelper, BackendApi::WindowPointer window,
std::function<void()> fnBeforeChangingWindowBounds)
{
ScreenBounds windowBounds = backendWindowHelper->GetWindowBounds(window);
ScreenBounds currentMonitorWorkArea = GetCurrentMonitorWorkArea(backendWindowHelper, window);
ScreenPosition newWindowPosition = currentMonitorWorkArea.WinPositionCentered(windowBounds.size);
windowBounds.position = newWindowPosition;
fnBeforeChangingWindowBounds();
backendWindowHelper->SetWindowBounds(window, windowBounds);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ namespace HelloImGui
bool HasInitialWindowSizeInfo() const;
ScreenBounds AppWindowBoundsInitial(const std::vector<ScreenBounds>& allMonitorsWorkAreas);

void EnsureWindowFitsMonitor(BackendApi::IBackendWindowHelper* helper, BackendApi::WindowPointer window);
void CenterWindowOnMonitor(BackendApi::IBackendWindowHelper* helper, BackendApi::WindowPointer window);
void EnsureWindowFitsMonitor(BackendApi::IBackendWindowHelper* helper, BackendApi::WindowPointer window, std::function<void()> fnBeforeChangingWindowBounds);
void CenterWindowOnMonitor(BackendApi::IBackendWindowHelper* helper, BackendApi::WindowPointer window, std::function<void()> fnBeforeChangingWindowBounds);
ScreenBounds GetCurrentMonitorWorkArea(BackendApi::IBackendWindowHelper* backendWindowHelper,
BackendApi::WindowPointer window);

// Will set the window size, after making sure it fits on the current screen
void TrySetWindowSize(BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window, ImVec2 userWidgetsSize);
void TrySetWindowSize(BackendApi::IBackendWindowHelper *backendWindowHelper, BackendApi::WindowPointer window, ImVec2 userWidgetsSize, std::function<void()> fnBeforeChangingWindowBounds);

private:
int GetMonitorIndexFromWindowPosition(BackendApi::IBackendWindowHelper *backendWindowHelper, const ScreenPosition& windowPosition) const;
Expand Down
4 changes: 2 additions & 2 deletions src/hello_imgui/internal/backend_impls/runner_glfw3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ namespace HelloImGui
IM_ASSERT(glfwInitSuccess);
}

void RunnerGlfw3::Impl_CreateWindow()
void RunnerGlfw3::Impl_CreateWindow(std::function<void()> renderCallbackDuringResize)
{
BackendApi::BackendOptions backendOptions;
backendOptions.rendererBackendType = params.rendererBackendType;
mWindow = mBackendWindowHelper->CreateWindow(params.appWindowParams, backendOptions);
mWindow = mBackendWindowHelper->CreateWindow(params.appWindowParams, backendOptions, renderCallbackDuringResize);
params.backendPointers.glfwWindow = mWindow;
}

Expand Down
2 changes: 1 addition & 1 deletion src/hello_imgui/internal/backend_impls/runner_glfw3.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class RunnerGlfw3 : public AbstractRunner
// Methods related to the platform backend (SDL, Glfw, ...)
//
void Impl_InitPlatformBackend() override;
void Impl_CreateWindow() override;
void Impl_CreateWindow(std::function<void()> gRenderCallbackDuringResize) override;
void Impl_PollEvents() override;
void Impl_NewFrame_PlatformBackend() override;
void Impl_UpdateAndRenderAdditionalPlatformWindows() override;
Expand Down
2 changes: 1 addition & 1 deletion src/hello_imgui/internal/backend_impls/runner_null.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace HelloImGui
auto size = NullConfig::GetScreenBounds().size;
ImGui::GetIO().DisplaySize = ImVec2((float)size[0], (float)size[1]);
}
void Impl_CreateWindow() override {}
void Impl_CreateWindow(std::function<void()> renderCallbackDuringResize) override {}
void Impl_PollEvents() override {}
void Impl_NewFrame_PlatformBackend() override {}
void Impl_UpdateAndRenderAdditionalPlatformWindows() override {}
Expand Down
5 changes: 3 additions & 2 deletions src/hello_imgui/internal/backend_impls/runner_sdl2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <SDL.h>
#include <SDL_main.h>
#include <sstream>
#include <functional>

namespace HelloImGui
{
Expand Down Expand Up @@ -72,11 +73,11 @@ namespace HelloImGui
SDL_SetEventFilter(HandleAppEvents, this);
}

void RunnerSdl2::Impl_CreateWindow()
void RunnerSdl2::Impl_CreateWindow(std::function<void()> renderCallbackDuringResize)
{
BackendApi::BackendOptions backendOptions;
backendOptions.rendererBackendType = params.rendererBackendType;
mWindow = mBackendWindowHelper->CreateWindow(params.appWindowParams, backendOptions);
mWindow = mBackendWindowHelper->CreateWindow(params.appWindowParams, backendOptions, renderCallbackDuringResize);
params.backendPointers.sdlWindow = mWindow;
}

Expand Down
2 changes: 1 addition & 1 deletion src/hello_imgui/internal/backend_impls/runner_sdl2.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace HelloImGui
// Methods related to the platform backend (SDL, Glfw, ...)
//
void Impl_InitPlatformBackend() override;
void Impl_CreateWindow() override;
void Impl_CreateWindow(std::function<void()> renderCallbackDuringResize) override;
void Impl_PollEvents() override;
void Impl_NewFrame_PlatformBackend() override;
void Impl_UpdateAndRenderAdditionalPlatformWindows() override;
Expand Down
16 changes: 8 additions & 8 deletions src/hello_imgui/internal/borderless_movable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
namespace HelloImGui
{
bool HandleBorderlessMovable(
BackendApi::WindowPointer window,
BackendApi::IBackendWindowHelper * backendWindowHelper,
std::function<ScreenBounds()> fnGetWindowBounds,
std::function<void(ScreenBounds)> fnSetWindowBounds,
const HelloImGui::RunnerParams& runnerParams
)
{
Expand Down Expand Up @@ -78,10 +78,10 @@ namespace HelloImGui
mouseDragLastPos = mousePos - dragDelta;
}

auto windowBounds = backendWindowHelper->GetWindowBounds(window);
auto windowBounds = fnGetWindowBounds();
windowBounds.position[0] += (int)(dragDelta.x);
windowBounds.position[1] += (int)(dragDelta.y);
backendWindowHelper->SetWindowBounds(window, windowBounds);
fnSetWindowBounds(windowBounds);
}

// Set mouse cursor: probably not visible for moving (the cursor will be the classic arrow)
Expand Down Expand Up @@ -181,7 +181,7 @@ namespace HelloImGui
{
ImVec2 dragDelta = ImGui::GetMouseDragDelta(0);
ImGui::ResetMouseDragDelta(0);
auto windowBounds = backendWindowHelper->GetWindowBounds(window);
auto windowBounds = fnGetWindowBounds();
windowBounds.size[0] += (int)dragDelta.x;
windowBounds.size[1] += (int)dragDelta.y;
if (windowBounds.size[0] < minAcceptableWindowSize)
Expand All @@ -194,15 +194,15 @@ namespace HelloImGui
windowBounds.size[1] = minAcceptableWindowSize;
isDragging = false;
}
backendWindowHelper->SetWindowBounds(window, windowBounds);
fnSetWindowBounds(windowBounds);
ImGui::ResetMouseDragDelta(ImGuiMouseButton_Left);
}

// With borderless windows, SDL is able to let window resize themselves to 0,
// and they are then impossible to resize! So we force a minimum size here:
{
bool tooSmall = false;
auto windowBounds = backendWindowHelper->GetWindowBounds(window);
auto windowBounds = fnGetWindowBounds();
if (windowBounds.size[0] < minAcceptableWindowSize)
{
windowBounds.size[0] = minAcceptableWindowSize;
Expand All @@ -214,7 +214,7 @@ namespace HelloImGui
tooSmall = true;
}
if (tooSmall)
backendWindowHelper->SetWindowBounds(window, windowBounds);
fnSetWindowBounds(windowBounds);
}

// Set mouse cursor: (not visible under glfw < 3.4, which does not implement this cursor)
Expand Down
4 changes: 2 additions & 2 deletions src/hello_imgui/internal/borderless_movable.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace HelloImGui
// This function is called by the backend to handle borderless movable windows
// it returns true if the window should be closed
bool HandleBorderlessMovable(
BackendApi::WindowPointer window,
BackendApi::IBackendWindowHelper * backendWindowHelper,
std::function<ScreenBounds()> fnGetWindowBounds,
std::function<void(ScreenBounds)> fnSetWindowBounds,
const HelloImGui::RunnerParams& runnerParams
);
}

0 comments on commit ec0d86d

Please sign in to comment.