From 416cfdb99d9e2eb251cf64fd45d5715ba4b49e23 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 20 Jun 2024 17:44:19 -0700 Subject: [PATCH] Backends: Win32: Secondary viewports WndProc handler retrieve/set imgui context from the HWND. Allowing WndProc dispatch to work in multi-context setups. --- backends/imgui_impl_win32.cpp | 26 +++++++++++++++++++------- docs/CHANGELOG.txt | 2 ++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index 63b57de85..0db29004f 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -1054,6 +1054,9 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) vd->HwndOwned = true; viewport->PlatformRequestResize = false; viewport->PlatformHandle = viewport->PlatformHandleRaw = vd->Hwnd; + + // Secondary viewports store their imgui context + ::SetPropA(vd->Hwnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext()); } static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport) @@ -1256,10 +1259,16 @@ static void ImGui_ImplWin32_OnChangedViewport(ImGuiViewport* viewport) static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) - return true; + // Allow secondary viewport WndProc to be called regardless of current context + ImGuiContext* hwnd_ctx = (ImGuiContext*)::GetPropA(hWnd, "IMGUI_CONTEXT"); + ImGuiContext* prev_ctx = ImGui::GetCurrentContext(); + if (hwnd_ctx != prev_ctx && hwnd_ctx != NULL) + ImGui::SetCurrentContext(hwnd_ctx); - if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hWnd)) + LRESULT result = 0; + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) + result = true; + else if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hWnd)) { switch (msg) { @@ -1274,7 +1283,7 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, break; case WM_MOUSEACTIVATE: if (viewport->Flags & ImGuiViewportFlags_NoFocusOnClick) - return MA_NOACTIVATE; + result = MA_NOACTIVATE; break; case WM_NCHITTEST: // Let mouse pass-through the window. This will allow the backend to call io.AddMouseViewportEvent() correctly. (which is optional). @@ -1282,12 +1291,15 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, // If you cannot easily access those viewport flags from your windowing/event code: you may manually synchronize its state e.g. in // your main loop after calling UpdatePlatformWindows(). Iterate all viewports/platform windows and pass the flag to your windowing system. if (viewport->Flags & ImGuiViewportFlags_NoInputs) - return HTTRANSPARENT; + result = HTTRANSPARENT; break; } } - - return DefWindowProc(hWnd, msg, wParam, lParam); + if (result == 0) + result = DefWindowProc(hWnd, msg, wParam, lParam); + if (hwnd_ctx != prev_ctx && hwnd_ctx != NULL) + ImGui::SetCurrentContext(prev_ctx); + return result; } static void ImGui_ImplWin32_InitPlatformInterface(bool platform_has_own_dc) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index df9118786..fafb8c4df 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -68,6 +68,8 @@ Docking+Viewports Branch: - Backends: SDL3: Update for introduction of SDL_GLContext from void*. (#7701, #7702) [@bcsanches] +- Backends: Win32: Secondary viewports WndProc handler retrieve/set imgui context from + the HWND, allowing WndProc dispatch to work in multi-context setups. -----------------------------------------------------------------------