Fixed issue 2600 Each window created in imgui_impl_win32.cpp now creates an openGL context which shares its display list space with the primary window's. IMGUI_IMPL_WIN32_OPENGL3 must be defined to use this fix.
diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 8b72e6e..8a581ec 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp
@@ -89,6 +89,8 @@ static void ImGui_ImplWin32_InitPlatformInterface(); static void ImGui_ImplWin32_ShutdownPlatformInterface(); static void ImGui_ImplWin32_UpdateMonitors(); +static void ImGui_ImplWin32_SetWindowFocus(ImGuiViewport* viewport); +static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport); struct ImGui_ImplWin32_Data { @@ -101,6 +103,10 @@ ImGuiMouseCursor LastMouseCursor; bool WantUpdateMonitors; +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + HGLRC HgLrc; +#endif //IMGUI_IMPL_WIN32_OPENGL3 + #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD bool HasGamepad; bool WantUpdateHasGamepad; @@ -122,7 +128,11 @@ } // Functions +#ifdef IMGUI_IMPL_WIN32_OPENGL3 +bool ImGui_ImplWin32_Init(void* hwnd, void* hglrc) +#else bool ImGui_ImplWin32_Init(void* hwnd) +#endif { ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendPlatformUserData == nullptr && "Already initialized a platform backend!"); @@ -148,6 +158,10 @@ bd->Time = perf_counter; bd->LastMouseCursor = ImGuiMouseCursor_COUNT; +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + bd->HgLrc = (HGLRC)hglrc; +#endif //IMGUI_IMPL_WIN32_OPENGL3 + // Our mouse update function expect PlatformHandle to be filled for the main viewport ImGuiViewport* main_viewport = ImGui::GetMainViewport(); main_viewport->PlatformHandle = main_viewport->PlatformHandleRaw = (void*)bd->hWnd; @@ -899,8 +913,23 @@ bool HwndOwned; DWORD DwStyle; DWORD DwExStyle; +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + HDC Hdc; + HGLRC HgLrc; +#endif - ImGui_ImplWin32_ViewportData() { Hwnd = nullptr; HwndOwned = false; DwStyle = DwExStyle = 0; } + ImGui_ImplWin32_ViewportData() + { + Hwnd = nullptr; + HwndOwned = false; + DwStyle = 0; + DwExStyle = 0; + +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + Hdc = nullptr; + HgLrc = nullptr; +#endif //IMGUI_IMPL_WIN32_OPENGL3 + } ~ImGui_ImplWin32_ViewportData() { IM_ASSERT(Hwnd == nullptr); } }; @@ -942,6 +971,27 @@ vd->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = viewport->PlatformHandleRaw = vd->Hwnd; + +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + vd->Hdc = GetDC(vd->Hwnd); + ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData(); + + // Set pixel format to match base window + HDC Hdc = GetDC(bd->hWnd); + int pf = GetPixelFormat(Hdc); + PIXELFORMATDESCRIPTOR pfd; + DescribePixelFormat(Hdc, pf, sizeof(pfd), &pfd); + SetPixelFormat(vd->Hdc, pf, &pfd); + + // Create OpenGL context for new window + vd->HgLrc = wglCreateContext(vd->Hdc); + wglMakeCurrent(vd->Hdc, vd->HgLrc); + wglShareLists(bd->HgLrc, vd->HgLrc); + + // Present new window + ImGui_ImplWin32_SetWindowFocus(viewport); + ImGui_ImplWin32_ShowWindow(viewport); +#endif //IMGUI_IMPL_WIN32_OPENGL3 } static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport) @@ -956,7 +1006,13 @@ ::SetCapture(bd->hWnd); } if (vd->Hwnd && vd->HwndOwned) + { + #ifdef IMGUI_IMPL_WIN32_OPENGL3 + wglDeleteContext(vd->HgLrc); + #endif + ::DestroyWindow(vd->Hwnd); + } vd->Hwnd = nullptr; IM_DELETE(vd); } @@ -1116,6 +1172,21 @@ #endif } +#ifdef IMGUI_IMPL_WIN32_OPENGL3 +static void ImGui_ImplWin32_RenderWindow(ImGuiViewport* viewport, void*) +{ + ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; + wglMakeCurrent(vd->Hdc, vd->HgLrc); +} + +static void ImGui_ImplWin32_SwapBuffers(ImGuiViewport* viewport, void*) +{ + ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData; + wglMakeCurrent(vd->Hdc, vd->HgLrc); + SwapBuffers(vd->Hdc); +} +#endif //IMGUI_IMPL_WIN32_OPENGL3 + static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) @@ -1125,6 +1196,10 @@ { switch (msg) { +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + case WM_ERASEBKGND: + return 0; // Prevent flickering on window invalidation +#endif //IMGUI_IMPL_WIN32_OPENGL3 case WM_CLOSE: viewport->PlatformRequestClose = true; return 0; @@ -1189,6 +1264,11 @@ platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale; // FIXME-DPI platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI +#ifdef IMGUI_IMPL_WIN32_OPENGL3 + platform_io.Platform_RenderWindow = ImGui_ImplWin32_RenderWindow; + platform_io.Platform_SwapBuffers = ImGui_ImplWin32_SwapBuffers; +#endif //IMGUI_IMPL_WIN32_OPENGL3 + // Register main window handle (which is owned by the main application, not by us) // This is mostly for simplicity and consistency, so that our code (e.g. mouse handling etc.) can use same logic for main and secondary viewports. ImGuiViewport* main_viewport = ImGui::GetMainViewport();
diff --git a/backends/imgui_impl_win32.h b/backends/imgui_impl_win32.h index 5378c7c..d65a11d 100644 --- a/backends/imgui_impl_win32.h +++ b/backends/imgui_impl_win32.h
@@ -17,7 +17,11 @@ #pragma once #include "imgui.h" // IMGUI_IMPL_API +#ifdef IMGUI_IMPL_WIN32_OPENGL3 +IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd, void* hglrc); +#else IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); +#endif IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame();