diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 2e1c244edf67..349545ee9dad 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1517,7 +1517,6 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport) static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport) { - // The main viewport (owned by the application) will always have RendererUserData == NULL since we didn't create the data for it. if (ImGuiViewportDataVulkan* data = (ImGuiViewportDataVulkan*)viewport->RendererUserData) { ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo; @@ -1557,6 +1556,7 @@ static void ImGui_ImplVulkan_RenderWindow(ImGuiViewport* viewport, void*) check_vk_result(err); } { + //TODO fixme sometimes fails if multiple main windows and a separate window are open err = vkAcquireNextImageKHR(v->Device, wd->Swapchain, UINT64_MAX, fsd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &wd->FrameIndex); check_vk_result(err); fd = &wd->Frames[wd->FrameIndex]; diff --git a/imgui.cpp b/imgui.cpp index e7d3a7515567..7e2e32f9804c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -937,7 +937,6 @@ static void EndFrameDrawDimmedBackgrounds(); // Viewports const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. -ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags); static void UpdateViewportsNewFrame(); static void UpdateViewportsEndFrame(); static void UpdateSelectWindowViewport(ImGuiWindow* window); @@ -11546,7 +11545,7 @@ static void ImGui::UpdateViewportsNewFrame() viewport->Idx = n; // Erase unused viewports - if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2) + if ((viewport->Flags & ImGuiViewportFlags_OwnedByApp) == 0 && viewport->LastFrameActive < g.FrameCount - 2) { // Clear references to this viewport in windows (window->ViewportId becomes the master data) for (int window_n = 0; window_n < g.Windows.Size; window_n++) @@ -11701,14 +11700,14 @@ static void ImGui::UpdateViewportsEndFrame() viewport->LastPos = viewport->Pos; if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f) { - if ((viewport->Flags & (ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows)) == 0) + if ((viewport->Flags & ImGuiViewportFlags_OwnedByApp) == 0) continue; } if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window)) continue; - if ((viewport->Flags & (ImGuiViewportFlags_OwnedByApp | ImGuiViewportFlags_CanHostOtherWindows)) == 0) { + if ((viewport->Flags & ImGuiViewportFlags_OwnedByApp) == 0) { IM_ASSERT(viewport->Window != NULL); } @@ -11780,6 +11779,52 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const return viewport; } +void ImGui::EraseViewport(ImGuiViewportP* viewport) { + IM_ASSERT(viewport != NULL); + ImGuiContext& g = *GImGui; + IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size); + + // Clear references to this viewport in windows (window->ViewportId becomes the master data) + for (int window_n = 0; window_n < g.Windows.Size; window_n++) + if (g.Windows[window_n]->Viewport == viewport) + { + g.Windows[window_n]->Viewport = (ImGuiViewportP*) GetMainViewport(); +// g.Windows[window_n]->ViewportOwned = false; + } + + if (viewport == g.MouseLastHoveredViewport) + g.MouseLastHoveredViewport = NULL; + + int n=-1; + for (int i = 0; i < g.Viewports.Size; i++) { + if (g.Viewports[i] == viewport) { + n = i; + break; + } + } + + IM_ASSERT(n >= 0); + + g.Viewports.erase(g.Viewports.Data + n); + + // Destroy + IMGUI_DEBUG_LOG_VIEWPORT("Delete Viewport %08X (%s)\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a"); + DestroyPlatformWindow(viewport); + + n=-1; + for (int i = 0; i < g.PlatformIO.Viewports.Size; i++) { + if (g.PlatformIO.Viewports[i] == viewport) { + n = i; + break; + } + } + + IM_ASSERT(n >= 0); + g.PlatformIO.Viewports.erase(g.PlatformIO.Viewports.Data + n); + + IM_DELETE(viewport); +} + // FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten. static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window) { diff --git a/imgui.h b/imgui.h index 5ce9a5633f74..ac3a3824054d 100644 --- a/imgui.h +++ b/imgui.h @@ -833,7 +833,7 @@ namespace ImGui // - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows. // - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports. // - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode. - IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL. + IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL. // Miscellaneous Utilities IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. diff --git a/imgui_internal.h b/imgui_internal.h index 33cf71c24f29..f5a9fc493113 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2473,6 +2473,8 @@ namespace ImGui IMGUI_API void CallContextHooks(ImGuiContext* context, ImGuiContextHookType type); // Viewports + IMGUI_API ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags); + IMGUI_API void EraseViewport(ImGuiViewportP*); IMGUI_API void TranslateWindowsInViewport(ImGuiViewportP* viewport, const ImVec2& old_pos, const ImVec2& new_pos); IMGUI_API void ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale); IMGUI_API void DestroyPlatformWindow(ImGuiViewportP* viewport);