diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8b0f9b7..e720ca9 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -285,9 +285,10 @@ { SDL_Window* Window; Uint32 WindowID; + bool WindowOwned; SDL_GLContext GLContext; - ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; GLContext = NULL; } + ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; } ~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; @@ -316,8 +317,8 @@ sdl_flags |= SDL_WINDOW_HIDDEN; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; - data->Window = SDL_CreateWindow("No Title Yet", - (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->WindowOwned = true; if (use_opengl) data->GLContext = SDL_GL_CreateContext(data->Window); if (use_opengl && backup_context) @@ -329,11 +330,11 @@ { if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData) { - if (data->GLContext) + if (data->GLContext && data->WindowOwned) SDL_GL_DeleteContext(data->GLContext); - data->GLContext = NULL; - if (data->Window) + if (data->Window && data->WindowOwned) SDL_DestroyWindow(data->Window); + data->GLContext = NULL; data->Window = NULL; IM_DELETE(data); } @@ -455,11 +456,12 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)(); data->Window = window; data->WindowID = SDL_GetWindowID(window); + data->WindowOwned = false; data->GLContext = sdl_gl_context; main_viewport->PlatformUserData = data; main_viewport->PlatformHandle = data->Window; diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8b0f9b7..e720ca9 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -285,9 +285,10 @@ { SDL_Window* Window; Uint32 WindowID; + bool WindowOwned; SDL_GLContext GLContext; - ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; GLContext = NULL; } + ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; } ~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; @@ -316,8 +317,8 @@ sdl_flags |= SDL_WINDOW_HIDDEN; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; - data->Window = SDL_CreateWindow("No Title Yet", - (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->WindowOwned = true; if (use_opengl) data->GLContext = SDL_GL_CreateContext(data->Window); if (use_opengl && backup_context) @@ -329,11 +330,11 @@ { if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData) { - if (data->GLContext) + if (data->GLContext && data->WindowOwned) SDL_GL_DeleteContext(data->GLContext); - data->GLContext = NULL; - if (data->Window) + if (data->Window && data->WindowOwned) SDL_DestroyWindow(data->Window); + data->GLContext = NULL; data->Window = NULL; IM_DELETE(data); } @@ -455,11 +456,12 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)(); data->Window = window; data->WindowID = SDL_GetWindowID(window); + data->WindowOwned = false; data->GLContext = sdl_gl_context; main_viewport->PlatformUserData = data; main_viewport->PlatformHandle = data->Window; diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 3d2192c..0dec6e8 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -1108,6 +1108,7 @@ 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_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator); diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8b0f9b7..e720ca9 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -285,9 +285,10 @@ { SDL_Window* Window; Uint32 WindowID; + bool WindowOwned; SDL_GLContext GLContext; - ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; GLContext = NULL; } + ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; } ~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; @@ -316,8 +317,8 @@ sdl_flags |= SDL_WINDOW_HIDDEN; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; - data->Window = SDL_CreateWindow("No Title Yet", - (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->WindowOwned = true; if (use_opengl) data->GLContext = SDL_GL_CreateContext(data->Window); if (use_opengl && backup_context) @@ -329,11 +330,11 @@ { if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData) { - if (data->GLContext) + if (data->GLContext && data->WindowOwned) SDL_GL_DeleteContext(data->GLContext); - data->GLContext = NULL; - if (data->Window) + if (data->Window && data->WindowOwned) SDL_DestroyWindow(data->Window); + data->GLContext = NULL; data->Window = NULL; IM_DELETE(data); } @@ -455,11 +456,12 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)(); data->Window = window; data->WindowID = SDL_GetWindowID(window); + data->WindowOwned = false; data->GLContext = sdl_gl_context; main_viewport->PlatformUserData = data; main_viewport->PlatformHandle = data->Window; diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 3d2192c..0dec6e8 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -1108,6 +1108,7 @@ 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_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator); diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 47a6592..411e529 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -364,10 +364,11 @@ struct ImGuiViewportDataWin32 { HWND Hwnd; + bool HwndOwned; DWORD DwStyle; DWORD DwExStyle; - ImGuiViewportDataWin32() { Hwnd = NULL; DwStyle = DwExStyle = 0; } + ImGuiViewportDataWin32() { Hwnd = NULL; HwndOwned = false; DwStyle = DwExStyle = 0; } ~ImGuiViewportDataWin32() { IM_ASSERT(Hwnd == NULL); } }; @@ -393,10 +394,11 @@ // Create window RECT rect = { (LONG)viewport->PlatformPos.x, (LONG)viewport->PlatformPos.y, (LONG)(viewport->PlatformPos.x + viewport->Size.x), (LONG)(viewport->PlatformPos.y + viewport->Size.y) }; ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); - data->Hwnd = ::CreateWindowExA( - data->DwExStyle, "ImGui Platform", "No Title Yet", data->DwStyle, // Style, class name, window name - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area - g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->Hwnd = ::CreateWindowEx( + data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area + g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = data->Hwnd; } @@ -411,7 +413,7 @@ ::ReleaseCapture(); ::SetCapture(g_hWnd); } - if (data->Hwnd) + if (data->Hwnd && data->HwndOwned) ::DestroyWindow(data->Hwnd); data->Hwnd = NULL; IM_DELETE(data); @@ -564,12 +566,13 @@ platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)(); data->Hwnd = g_hWnd; + data->HwndOwned = false; main_viewport->PlatformUserData = data; - main_viewport->PlatformHandle = (void*)data->Hwnd; + main_viewport->PlatformHandle = (void*)g_hWnd; } static void ImGui_ImplWin32_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8b0f9b7..e720ca9 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -285,9 +285,10 @@ { SDL_Window* Window; Uint32 WindowID; + bool WindowOwned; SDL_GLContext GLContext; - ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; GLContext = NULL; } + ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; } ~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; @@ -316,8 +317,8 @@ sdl_flags |= SDL_WINDOW_HIDDEN; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; - data->Window = SDL_CreateWindow("No Title Yet", - (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->WindowOwned = true; if (use_opengl) data->GLContext = SDL_GL_CreateContext(data->Window); if (use_opengl && backup_context) @@ -329,11 +330,11 @@ { if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData) { - if (data->GLContext) + if (data->GLContext && data->WindowOwned) SDL_GL_DeleteContext(data->GLContext); - data->GLContext = NULL; - if (data->Window) + if (data->Window && data->WindowOwned) SDL_DestroyWindow(data->Window); + data->GLContext = NULL; data->Window = NULL; IM_DELETE(data); } @@ -455,11 +456,12 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)(); data->Window = window; data->WindowID = SDL_GetWindowID(window); + data->WindowOwned = false; data->GLContext = sdl_gl_context; main_viewport->PlatformUserData = data; main_viewport->PlatformHandle = data->Window; diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 3d2192c..0dec6e8 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -1108,6 +1108,7 @@ 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_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator); diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 47a6592..411e529 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -364,10 +364,11 @@ struct ImGuiViewportDataWin32 { HWND Hwnd; + bool HwndOwned; DWORD DwStyle; DWORD DwExStyle; - ImGuiViewportDataWin32() { Hwnd = NULL; DwStyle = DwExStyle = 0; } + ImGuiViewportDataWin32() { Hwnd = NULL; HwndOwned = false; DwStyle = DwExStyle = 0; } ~ImGuiViewportDataWin32() { IM_ASSERT(Hwnd == NULL); } }; @@ -393,10 +394,11 @@ // Create window RECT rect = { (LONG)viewport->PlatformPos.x, (LONG)viewport->PlatformPos.y, (LONG)(viewport->PlatformPos.x + viewport->Size.x), (LONG)(viewport->PlatformPos.y + viewport->Size.y) }; ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); - data->Hwnd = ::CreateWindowExA( - data->DwExStyle, "ImGui Platform", "No Title Yet", data->DwStyle, // Style, class name, window name - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area - g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->Hwnd = ::CreateWindowEx( + data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area + g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = data->Hwnd; } @@ -411,7 +413,7 @@ ::ReleaseCapture(); ::SetCapture(g_hWnd); } - if (data->Hwnd) + if (data->Hwnd && data->HwndOwned) ::DestroyWindow(data->Hwnd); data->Hwnd = NULL; IM_DELETE(data); @@ -564,12 +566,13 @@ platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)(); data->Hwnd = g_hWnd; + data->HwndOwned = false; main_viewport->PlatformUserData = data; - main_viewport->PlatformHandle = (void*)data->Hwnd; + main_viewport->PlatformHandle = (void*)g_hWnd; } static void ImGui_ImplWin32_ShutdownPlatformInterface() diff --git a/imgui.cpp b/imgui.cpp index dd4ade4..abf5f2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -762,7 +762,7 @@ static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); // Viewports -const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using a constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. +const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static inline ImRect GetViewportRect(ImGuiWindow* window) { return window->Viewport->GetRect(); } static inline ImVec2 ConvertViewportPosToPlatformPos(const ImVec2& imgui_pos, ImGuiViewport* viewport) { return imgui_pos - viewport->Pos + viewport->PlatformPos; } static inline ImVec2 ConvertPlatformPosToViewportPos(const ImVec2& platform_pos, ImGuiViewport* viewport) { return platform_pos - viewport->PlatformPos + viewport->Pos; } @@ -3530,7 +3530,8 @@ if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) return; - // Create/resize/destroy platform windows and update the list that the user can process + // Create/resize/destroy platform windows to match each active viewport. Update the user-facing list. + // Skip the main viewport (index 0), which is always fully handled by the application! for (int i = 1; i < g.Viewports.Size; i++) { ImGuiViewportP* viewport = g.Viewports[i]; @@ -3609,12 +3610,12 @@ // for (int i = 1; i < data->Viewports.Size; i++) // MySwapBufferFunction(data->Viewports[i], my_args); // -// Note how we intentionally skip the main viewport (index 0) which is generally rendered as part of our main application. void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg) { if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnableViewports)) return; + // Skip the main viewport (index 0), which is always fully handled by the application! ImGuiPlatformData* data = ImGui::GetPlatformData(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); for (int i = 1; i < data->Viewports.Size; i++) @@ -3779,7 +3780,7 @@ IM_ASSERT(g.FrameCount == 0 || g.FrameCountPlatformEnded == g.FrameCount && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?"); IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?"); - IM_ASSERT(g.Viewports[0]->PlatformUserData != NULL && "Platform init didn't setup main viewport."); + IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) && "Platform init didn't setup main viewport."); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function! #endif @@ -4059,6 +4060,9 @@ void ImGui::DestroyPlatformWindows() { + // We call the destroy window on the main viewport (index 0) to give a chance to the back-end to clear any data it may hold on it. + // It is expected that the back-end stored a flag to remember that it doesn't own the window created for the main viewport, + // and won't destroy the underlying platform/renderer data. ImGuiContext& g = *GImGui; if (g.PlatformIO.Renderer_DestroyWindow) for (int i = 0; i < g.Viewports.Size; i++) diff --git a/examples/imgui_impl_dx10.cpp b/examples/imgui_impl_dx10.cpp index ad19ecf..de0ed14 100644 --- a/examples/imgui_impl_dx10.cpp +++ b/examples/imgui_impl_dx10.cpp @@ -554,6 +554,7 @@ static void ImGui_ImplDX10_DestroyWindow(ImGuiViewport* viewport) { + // The main viewport (owned by the application) will always have RendererUserData == NULL here since we didn't create the data for it. if (ImGuiViewportDataDx10* data = (ImGuiViewportDataDx10*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx11.cpp b/examples/imgui_impl_dx11.cpp index 1463fc3..1ce2d7f 100644 --- a/examples/imgui_impl_dx11.cpp +++ b/examples/imgui_impl_dx11.cpp @@ -561,6 +561,7 @@ static void ImGui_ImplDX11_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 (ImGuiViewportDataDx11* data = (ImGuiViewportDataDx11*)viewport->RendererUserData) { if (data->SwapChain) diff --git a/examples/imgui_impl_dx12.cpp b/examples/imgui_impl_dx12.cpp index 206a24c..00dfb5f 100644 --- a/examples/imgui_impl_dx12.cpp +++ b/examples/imgui_impl_dx12.cpp @@ -690,6 +690,7 @@ static void ImGui_ImplDX12_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 (ImGuiViewportDataDx12* data = (ImGuiViewportDataDx12*)viewport->RendererUserData) { IM_ASSERT(0); diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index 8b1bb5a..f7e16a4 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -371,12 +371,14 @@ { if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData) { + if (data->WindowOwned) + { #if GLFW_HAS_GLFW_HOVERED - HWND hwnd = glfwGetWin32Window(data->Window); - ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); - #endif - if (data->Window && data->WindowOwned) + HWND hwnd = glfwGetWin32Window(data->Window); + ::RemovePropA(hwnd, "IMGUI_VIEWPORT"); +#endif glfwDestroyWindow(data->Window); + } data->Window = NULL; IM_DELETE(data); } @@ -539,12 +541,13 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataGlfw* data = IM_NEW(ImGuiViewportDataGlfw)(); data->Window = g_Window; data->WindowOwned = false; main_viewport->PlatformUserData = data; + main_viewport->PlatformHandle = (void*)g_Window; } static void ImGui_ImplGlfw_ShutdownPlatformInterface() diff --git a/examples/imgui_impl_sdl2.cpp b/examples/imgui_impl_sdl2.cpp index 8b0f9b7..e720ca9 100644 --- a/examples/imgui_impl_sdl2.cpp +++ b/examples/imgui_impl_sdl2.cpp @@ -285,9 +285,10 @@ { SDL_Window* Window; Uint32 WindowID; + bool WindowOwned; SDL_GLContext GLContext; - ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; GLContext = NULL; } + ImGuiViewportDataSDL2() { Window = NULL; WindowID = 0; WindowOwned = false; GLContext = NULL; } ~ImGuiViewportDataSDL2() { IM_ASSERT(Window == NULL && GLContext == NULL); } }; @@ -316,8 +317,8 @@ sdl_flags |= SDL_WINDOW_HIDDEN; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? SDL_WINDOW_BORDERLESS : 0; sdl_flags |= (viewport->Flags & ImGuiViewportFlags_NoDecoration) ? 0 : SDL_WINDOW_RESIZABLE; - data->Window = SDL_CreateWindow("No Title Yet", - (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->Window = SDL_CreateWindow("No Title Yet", (int)viewport->PlatformPos.x, (int)viewport->PlatformPos.y, (int)viewport->Size.x, (int)viewport->Size.y, sdl_flags); + data->WindowOwned = true; if (use_opengl) data->GLContext = SDL_GL_CreateContext(data->Window); if (use_opengl && backup_context) @@ -329,11 +330,11 @@ { if (ImGuiViewportDataSDL2* data = (ImGuiViewportDataSDL2*)viewport->PlatformUserData) { - if (data->GLContext) + if (data->GLContext && data->WindowOwned) SDL_GL_DeleteContext(data->GLContext); - data->GLContext = NULL; - if (data->Window) + if (data->Window && data->WindowOwned) SDL_DestroyWindow(data->Window); + data->GLContext = NULL; data->Window = NULL; IM_DELETE(data); } @@ -455,11 +456,12 @@ platform_io.Platform_CreateVkSurface = ImGui_ImplSDL2_CreateVkSurface; #endif - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataSDL2* data = IM_NEW(ImGuiViewportDataSDL2)(); data->Window = window; data->WindowID = SDL_GetWindowID(window); + data->WindowOwned = false; data->GLContext = sdl_gl_context; main_viewport->PlatformUserData = data; main_viewport->PlatformHandle = data->Window; diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 3d2192c..0dec6e8 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -1108,6 +1108,7 @@ 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_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator); diff --git a/examples/imgui_impl_win32.cpp b/examples/imgui_impl_win32.cpp index 47a6592..411e529 100644 --- a/examples/imgui_impl_win32.cpp +++ b/examples/imgui_impl_win32.cpp @@ -364,10 +364,11 @@ struct ImGuiViewportDataWin32 { HWND Hwnd; + bool HwndOwned; DWORD DwStyle; DWORD DwExStyle; - ImGuiViewportDataWin32() { Hwnd = NULL; DwStyle = DwExStyle = 0; } + ImGuiViewportDataWin32() { Hwnd = NULL; HwndOwned = false; DwStyle = DwExStyle = 0; } ~ImGuiViewportDataWin32() { IM_ASSERT(Hwnd == NULL); } }; @@ -393,10 +394,11 @@ // Create window RECT rect = { (LONG)viewport->PlatformPos.x, (LONG)viewport->PlatformPos.y, (LONG)(viewport->PlatformPos.x + viewport->Size.x), (LONG)(viewport->PlatformPos.y + viewport->Size.y) }; ::AdjustWindowRectEx(&rect, data->DwStyle, FALSE, data->DwExStyle); - data->Hwnd = ::CreateWindowExA( - data->DwExStyle, "ImGui Platform", "No Title Yet", data->DwStyle, // Style, class name, window name - rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area - g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->Hwnd = ::CreateWindowEx( + data->DwExStyle, _T("ImGui Platform"), _T("No Title Yet"), data->DwStyle, // Style, class name, window name + rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, // Window area + g_hWnd, NULL, ::GetModuleHandle(NULL), NULL); // Parent window, Menu, Instance, Param + data->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = data->Hwnd; } @@ -411,7 +413,7 @@ ::ReleaseCapture(); ::SetCapture(g_hWnd); } - if (data->Hwnd) + if (data->Hwnd && data->HwndOwned) ::DestroyWindow(data->Hwnd); data->Hwnd = NULL; IM_DELETE(data); @@ -564,12 +566,13 @@ platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha; platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; - // Register main window handle + // Register main window handle (which is owned by the main application, not by us) ImGuiViewport* main_viewport = ImGui::GetMainViewport(); ImGuiViewportDataWin32* data = IM_NEW(ImGuiViewportDataWin32)(); data->Hwnd = g_hWnd; + data->HwndOwned = false; main_viewport->PlatformUserData = data; - main_viewport->PlatformHandle = (void*)data->Hwnd; + main_viewport->PlatformHandle = (void*)g_hWnd; } static void ImGui_ImplWin32_ShutdownPlatformInterface() diff --git a/imgui.cpp b/imgui.cpp index dd4ade4..abf5f2a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -762,7 +762,7 @@ static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); // Viewports -const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using a constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. +const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHash("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter. static inline ImRect GetViewportRect(ImGuiWindow* window) { return window->Viewport->GetRect(); } static inline ImVec2 ConvertViewportPosToPlatformPos(const ImVec2& imgui_pos, ImGuiViewport* viewport) { return imgui_pos - viewport->Pos + viewport->PlatformPos; } static inline ImVec2 ConvertPlatformPosToViewportPos(const ImVec2& platform_pos, ImGuiViewport* viewport) { return platform_pos - viewport->PlatformPos + viewport->Pos; } @@ -3530,7 +3530,8 @@ if (!(g.IO.ConfigFlags & ImGuiConfigFlags_EnableViewports)) return; - // Create/resize/destroy platform windows and update the list that the user can process + // Create/resize/destroy platform windows to match each active viewport. Update the user-facing list. + // Skip the main viewport (index 0), which is always fully handled by the application! for (int i = 1; i < g.Viewports.Size; i++) { ImGuiViewportP* viewport = g.Viewports[i]; @@ -3609,12 +3610,12 @@ // for (int i = 1; i < data->Viewports.Size; i++) // MySwapBufferFunction(data->Viewports[i], my_args); // -// Note how we intentionally skip the main viewport (index 0) which is generally rendered as part of our main application. void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg) { if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_EnableViewports)) return; + // Skip the main viewport (index 0), which is always fully handled by the application! ImGuiPlatformData* data = ImGui::GetPlatformData(); ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); for (int i = 1; i < data->Viewports.Size; i++) @@ -3779,7 +3780,7 @@ IM_ASSERT(g.FrameCount == 0 || g.FrameCountPlatformEnded == g.FrameCount && "Forgot to call UpdatePlatformWindows() at the end of the previous frame?"); IM_ASSERT(g.PlatformIO.Platform_CreateWindow != NULL && "Platform init didn't install handlers?"); IM_ASSERT(g.PlatformIO.Platform_DestroyWindow != NULL && "Platform init didn't install handlers?"); - IM_ASSERT(g.Viewports[0]->PlatformUserData != NULL && "Platform init didn't setup main viewport."); + IM_ASSERT((g.Viewports[0]->PlatformUserData != NULL || g.Viewports[0]->PlatformHandle != NULL) && "Platform init didn't setup main viewport."); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS IM_ASSERT(g.IO.RenderDrawListsFn == NULL); // Call ImGui::Render() then pass ImGui::GetDrawData() yourself to your render function! #endif @@ -4059,6 +4060,9 @@ void ImGui::DestroyPlatformWindows() { + // We call the destroy window on the main viewport (index 0) to give a chance to the back-end to clear any data it may hold on it. + // It is expected that the back-end stored a flag to remember that it doesn't own the window created for the main viewport, + // and won't destroy the underlying platform/renderer data. ImGuiContext& g = *GImGui; if (g.PlatformIO.Renderer_DestroyWindow) for (int i = 0; i < g.Viewports.Size; i++) diff --git a/imgui.h b/imgui.h index e23621e..81d5232 100644 --- a/imgui.h +++ b/imgui.h @@ -549,10 +549,10 @@ // (Optional) Platform interface for multi-viewport support IMGUI_API ImGuiPlatformIO& GetPlatformIO(); // Platform/Renderer function, for back-end to setup. IMGUI_API ImGuiPlatformData* GetPlatformData(); // List of viewports. Viewport 0 is always the main viewport, followed by the secondary viewports. - IMGUI_API ImGuiViewport* GetMainViewport(); // GetPlatformData()->MainViewport - IMGUI_API void UpdatePlatformWindows(); // Call in main loop. Create/Destroy/Resize platform windows so there's one for each viewport - IMGUI_API void RenderPlatformWindowsDefault(void* platform_render_arg = NULL, void* renderer_render_arg = NULL); // Call in main loop. Call RenderWindow/SwapBuffers from the ImGuiPlatformIO structure. May be reimplemented by user. - IMGUI_API void DestroyPlatformWindows(); // (Optional) Call in back-end shutdown if you need to close Platform Windows before imgui shutdown. + IMGUI_API ImGuiViewport* GetMainViewport(); // == GetPlatformData()->MainViewport == GetPlatformData()->Viewports[0] + IMGUI_API void UpdatePlatformWindows(); // Call in main loop. Will call CreateWindow/ResizeWindow/etc. platform functions for each secondary viewport, and DestroyWindow for each inactive viewport. + IMGUI_API void RenderPlatformWindowsDefault(void* platform_arg = NULL, void* renderer_arg = NULL); // Call in main loop. Will call RenderWindow/SwapBuffers platform functions for each secondary viewport. May be reimplemented by user for custom rendering needs. + IMGUI_API void DestroyPlatformWindows(); // (Optional) Call DestroyWindow platform functions for all viewports. Call from back-end Shutdown() if you need to close platform windows before imgui shutdown. Otherwise will be called by DestroyContext(). IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); // Memory Utilities