diff --git a/imgui.cpp b/imgui.cpp index fc2db679..e0cce5b0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7630,7 +7630,8 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) window->ViewportId = window->Viewport->ID; } -// Called by imgui at the end of the main loop, after EndFrame() +// Called by user at the end of the main loop, after EndFrame() +// This will handle the creation/update of all OS windows via function defined in the ImGuiPlatformIO api. void ImGui::UpdatePlatformWindows() { ImGuiContext& g = *GImGui; @@ -7658,34 +7659,34 @@ void ImGui::UpdatePlatformWindows() if (viewport->LastFrameActive < g.FrameCount) continue; - // New windows that appears directly in a new viewport won't always have a size on their frame + // New windows that appears directly in a new viewport won't always have a size on their first frame if (viewport->Size.x <= 0 || viewport->Size.y <= 0) continue; // Update common viewport flags for owned viewports - if (viewport->Window != NULL) + if (ImGuiWindow* window = viewport->Window) { ImGuiViewportFlags flags = viewport->Flags & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration); - if (viewport->Window->Flags & ImGuiWindowFlags_Tooltip) + if (window->Flags & ImGuiWindowFlags_Tooltip) flags |= ImGuiViewportFlags_TopMost; - if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) flags |= ImGuiViewportFlags_NoTaskBarIcon; - if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) + if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0) flags |= ImGuiViewportFlags_NoDecoration; viewport->Flags = flags; } // Create window - bool is_new_window = (viewport->PlatformWindowCreated == false); - if (is_new_window) + bool is_new_platform_window = (viewport->PlatformWindowCreated == false); + if (is_new_platform_window) { //IMGUI_DEBUG_LOG("Create Platform Window %08X (%s)\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a"); g.PlatformIO.Platform_CreateWindow(viewport); if (g.PlatformIO.Renderer_CreateWindow != NULL) g.PlatformIO.Renderer_CreateWindow(viewport); viewport->LastNameHash = 0; - viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX); // By clearing those we'll enforce a call to Platform_SetWindowPos/Platform_SetWindowSize before Platform_ShowWindow - viewport->LastRendererSize = viewport->Size; + viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX); // By clearing those we'll enforce a call to Platform_SetWindowPos/Size below, before Platform_ShowWindow (FIXME: Is that necessary?) + viewport->LastRendererSize = viewport->Size; // We don't need to call Renderer_SetWindowSize() as it is expected Renderer_CreateWindow() already did it. viewport->PlatformWindowCreated = true; } @@ -7708,29 +7709,32 @@ void ImGui::UpdatePlatformWindows() if (viewport->LastNameHash != title_hash) { char title_end_backup_c = *title_end; - *title_end = 0; // Cut existing buffer short instead of doing an alloc/free + *title_end = 0; // Cut existing buffer short instead of doing an alloc/free, no small gain. g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin); *title_end = title_end_backup_c; viewport->LastNameHash = title_hash; } } - // Update alpha + // Update alpha (if it changed) if (viewport->LastAlpha != viewport->Alpha && g.PlatformIO.Platform_SetWindowAlpha) g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha); viewport->LastAlpha = viewport->Alpha; - // Show window. On startup ensure platform window don't get focus - if (is_new_window) + if (is_new_platform_window) { - if (g.FrameCount < 3) // Give a few frames for the application to stabilize (nested contents may lead to viewport being created a few frames late) + // On startup ensure new platform window don't steal focus (give it a few frames, as nested contents may lead to viewport being created a few frames late) + if (g.FrameCount < 3) viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing; - g.PlatformIO.Platform_ShowWindow(viewport); - } - // Even without focus, we assume the window becomes front-most. This is used by our platform z-order heuristic when io.MouseHoveredViewport is not available. - if (is_new_window && viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount) - viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount; + // Show window + g.PlatformIO.Platform_ShowWindow(viewport); + + // Even without focus, we assume the window becomes front-most. + // This is useful for our platform z-order heuristic when io.MouseHoveredViewport is not available. + if (viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount) + viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount; + } // Clear request flags viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false; @@ -7757,6 +7761,34 @@ void ImGui::UpdatePlatformWindows() } } +// This is a default/basic function for performing the rendering/swap of multiple Platform Windows. +// Custom renderers may prefer to not call this function at all, and instead iterate the publicly exposed platform data and handle rendering/sync themselves. +// The Render/Swap functions stored in ImGuiPlatformIO are merely here to allow for this helper to exist, but you can do it yourself: +// +// ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); +// for (int i = 1; i < platform_io.Viewports.Size; i++) +// MyRenderFunction(platform_io.Viewports[i], my_args); +// for (int i = 1; i < platform_io.Viewports.Size; i++) +// MySwapBufferFunction(platform_io.Viewports[i], my_args); +// +void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg) +{ + // Skip the main viewport (index 0), which is always fully handled by the application! + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + for (int i = 1; i < platform_io.Viewports.Size; i++) + { + ImGuiViewport* viewport = platform_io.Viewports[i]; + if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg); + if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg); + } + for (int i = 1; i < platform_io.Viewports.Size; i++) + { + ImGuiViewport* viewport = platform_io.Viewports[i]; + if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg); + if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg); + } +} + static int ImGui::FindPlatformMonitorForPos(const ImVec2& pos) { ImGuiContext& g = *GImGui; @@ -7798,37 +7830,6 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect) return best_monitor_n; } -// This is a default/basic function for performing the rendering/swap of multiple platform windows. -// Custom renderers may prefer to not call this function at all, and instead iterate the publicly exposed platform data and handle rendering/sync themselves. -// The Render/Swap functions stored in ImGuiPlatformIO are merely here to allow for this helper to exist, but you can do it yourself: -// -// ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); -// for (int i = 1; i < platform_io.Viewports.Size; i++) -// MyRenderFunction(platform_io.Viewports[i], my_args); -// for (int i = 1; i < platform_io.Viewports.Size; i++) -// MySwapBufferFunction(platform_io.Viewports[i], my_args); -// -void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg) -{ - if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable)) - return; - - // Skip the main viewport (index 0), which is always fully handled by the application! - ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); - for (int i = 1; i < platform_io.Viewports.Size; i++) - { - ImGuiViewport* viewport = platform_io.Viewports[i]; - if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg); - if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg); - } - for (int i = 1; i < platform_io.Viewports.Size; i++) - { - ImGuiViewport* viewport = platform_io.Viewports[i]; - if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg); - if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg); - } -} - void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 3601dada..65d481e7 100644 --- a/imgui.h +++ b/imgui.h @@ -2143,13 +2143,13 @@ struct ImGuiPlatformMonitor }; // (Optional) Setup required only if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) is enabled. -// Access via ImGui::GetPlatformIO(). This is designed so we can mix and match two imgui_impl_xxxx files, one for -// the Platform (~window handling), one for Renderer. Custom engine back-ends will often provide both Platform -// and Renderer interfaces and thus may not need to use all functions. +// Access via ImGui::GetPlatformIO(). This is designed so we can mix and match two imgui_impl_xxxx files, +// one for the Platform (~window handling), one for Renderer. Custom engine back-ends will often provide +// both Platform and Renderer interfaces and so may not need to use all functions. // Platform functions are typically called before their Renderer counterpart, // apart from Destroy which are called the other way. // RenderPlatformWindowsDefault() is that helper that iterate secondary viewports and call, in this order: -// Platform_RenderWindow(), Renderer_RenderWindow(), Platform_SwapBuffers(), Renderer_SwapBuffers() +// Platform_RenderWindow(), Renderer_RenderWindow(), Platform_SwapBuffers(), Renderer_SwapBuffers() // You may skip using RenderPlatformWindowsDefault() and call your draw/swap functions yourself if you need // specific behavior for your multi-window rendering. struct ImGuiPlatformIO @@ -2159,6 +2159,7 @@ struct ImGuiPlatformIO //------------------------------------------------------------------ // (Optional) Platform functions (e.g. Win32, GLFW, SDL2) + // Most of them are called by ImGui::UpdatePlatformWindows() and ImGui::RenderPlatformWindowsDefault(). void (*Platform_CreateWindow)(ImGuiViewport* vp); // Create a new platform window for the given viewport void (*Platform_DestroyWindow)(ImGuiViewport* vp); void (*Platform_ShowWindow)(ImGuiViewport* vp); // Newly created windows are initially hidden so SetWindowPos/Size/Title can be called on them first @@ -2171,7 +2172,7 @@ struct ImGuiPlatformIO bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp); void (*Platform_SetWindowTitle)(ImGuiViewport* vp, const char* title); void (*Platform_SetWindowAlpha)(ImGuiViewport* vp, float alpha); // (Optional) Setup window transparency - void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Setup for render (platform side) + void (*Platform_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Setup for render void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (platform side) float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // (Optional) [BETA] (FIXME-DPI) DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI. void (*Platform_OnChangedViewport)(ImGuiViewport* vp); // (Optional) [BETA] (FIXME-DPI) DPI handling: Called during Begin() every time the viewport we are outputting into changes, so back-end has a chance to swap fonts to adjust style. @@ -2213,8 +2214,8 @@ enum ImGuiViewportFlags_ // The viewports created and managed by imgui. The role of the platform back-end is to create the platform/OS windows corresponding to each viewport. struct ImGuiViewport { - ImGuiID ID; - ImGuiViewportFlags Flags; + ImGuiID ID; // Unique identifier for the viewport + ImGuiViewportFlags Flags; // See ImGuiViewportFlags_ ImVec2 Pos; // Position of viewport both in imgui space and in OS desktop/native space ImVec2 Size; // Size of viewport in pixel float DpiScale; // 1.0f = 96 DPI = No extra scale