From fedf45c77e77a5db01be6e67d34e70a4498a3e87 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 28 Oct 2024 16:56:34 +0100 Subject: [PATCH] Backends: Win32 + Viewports: tweak ImGui_ImplWin32_WndProcHandler_PlatformWindow() to be easier to rework in a parallal friendly way. (#8069) --- backends/imgui_impl_win32.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index a127fa2ad..ec771d06c 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2024-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2024-10-28: [Docking] Rely on property stored inside HWND to retrieve context/viewport, should facilitate attempt to use this for parallel contexts. (#8069) // 2024-09-16: [Docking] Inputs: fixed an issue where a viewport destroyed while clicking would hog mouse tracking and temporary lead to incorrect update of HoveredWindow. (#7971) // 2024-07-08: Inputs: Fixed ImGuiMod_Super being mapped to VK_APPS instead of VK_LWIN||VK_RWIN. (#7768) // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. @@ -187,6 +188,8 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc) // 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; + ::SetPropA(bd->hWnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext()); + ::SetPropA(bd->hWnd, "IMGUI_VIEWPORT", main_viewport); ImGui_ImplWin32_InitMultiViewportSupport(platform_has_own_dc); // Dynamically load XInput library @@ -230,6 +233,8 @@ void ImGui_ImplWin32_Shutdown() IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); ImGuiIO& io = ImGui::GetIO(); + ::SetPropA(bd->hWnd, "IMGUI_CONTEXT", nullptr); + ::SetPropA(bd->hWnd, "IMGUI_VIEWPORT", nullptr); ImGui_ImplWin32_ShutdownMultiViewportSupport(); // Unload XInput library @@ -314,6 +319,14 @@ static void ImGui_ImplWin32_UpdateKeyModifiers() io.AddKeyEvent(ImGuiMod_Super, IsVkDown(VK_LWIN) || IsVkDown(VK_RWIN)); } +static ImGuiViewport* ImGui_ImplWin32_FindViewportByPlatformHandle(HWND hwnd) +{ + // We could use ImGui::FindViewportByPlatformHandle() but GetPropA() gets us closer to parallel multi-contexts, + // until we can pass an explicit context to FindViewportByPlatformHandle(). + //return ImGui::FindViewportByPlatformHandle((void*)hwnd); + return (ImGuiViewport*)::GetPropA(hwnd, "IMGUI_VIEWPORT"); +} + // This code supports multi-viewports (multiple OS Windows mapped into different Dear ImGui viewports) // Because of that, it is a little more complicated than your typical single-viewport binding code! static void ImGui_ImplWin32_UpdateMouseData() @@ -326,7 +339,7 @@ static void ImGui_ImplWin32_UpdateMouseData() bool has_mouse_screen_pos = ::GetCursorPos(&mouse_screen_pos) != 0; HWND focused_window = ::GetForegroundWindow(); - const bool is_app_focused = (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd) || ImGui::FindViewportByPlatformHandle((void*)focused_window))); + const bool is_app_focused = (focused_window && (focused_window == bd->hWnd || ::IsChild(focused_window, bd->hWnd) || ImGui_ImplWin32_FindViewportByPlatformHandle(focused_window))); if (is_app_focused) { // (Optional) Set OS mouse position from Dear ImGui if requested (rarely used, only when io.ConfigNavMoveSetMousePos is enabled by user) @@ -364,7 +377,7 @@ static void ImGui_ImplWin32_UpdateMouseData() ImGuiID mouse_viewport_id = 0; if (has_mouse_screen_pos) if (HWND hovered_hwnd = ::WindowFromPoint(mouse_screen_pos)) - if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hovered_hwnd)) + if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(hovered_hwnd)) mouse_viewport_id = viewport->ID; io.AddMouseViewportEvent(mouse_viewport_id); } @@ -1072,6 +1085,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport) // Secondary viewports store their imgui context ::SetPropA(vd->Hwnd, "IMGUI_CONTEXT", ImGui::GetCurrentContext()); + ::SetPropA(vd->Hwnd, "IMGUI_VIEWPORT", viewport); } static void ImGui_ImplWin32_DestroyWindow(ImGuiViewport* viewport) @@ -1294,7 +1308,7 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd, LRESULT result = 0; if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) result = true; - else if (ImGuiViewport* viewport = ImGui::FindViewportByPlatformHandle((void*)hWnd)) + else if (ImGuiViewport* viewport = ImGui_ImplWin32_FindViewportByPlatformHandle(hWnd)) { switch (msg) {