Viewports: store ImGuiViewport* ParentViewport pointer as well. Backends: SDL3, Win32: use this pointer to reduce lookups. (#8948)

This commit is contained in:
ocornut
2025-09-30 18:39:34 +02:00
parent e7aa0dec5b
commit 3563f1e270
5 changed files with 27 additions and 16 deletions

View File

@@ -1008,14 +1008,13 @@ struct ImGui_ImplSDL3_ViewportData
~ImGui_ImplSDL3_ViewportData() { IM_ASSERT(Window == nullptr && GLContext == nullptr); }
};
static SDL_Window* ImGui_ImplSDL3_GetSDLWindowFromViewportID(ImGuiID viewport_id)
static SDL_Window* ImGui_ImplSDL3_GetSDLWindowFromViewport(ImGuiViewport* viewport)
{
if (viewport_id != 0)
if (ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id))
{
SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
return SDL_GetWindowFromID(window_id);
}
if (viewport != nullptr)
{
SDL_WindowID window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
return SDL_GetWindowFromID(window_id);
}
return nullptr;
}
@@ -1025,7 +1024,7 @@ static void ImGui_ImplSDL3_CreateWindow(ImGuiViewport* viewport)
ImGui_ImplSDL3_ViewportData* vd = IM_NEW(ImGui_ImplSDL3_ViewportData)();
viewport->PlatformUserData = vd;
vd->ParentWindow = ImGui_ImplSDL3_GetSDLWindowFromViewportID(viewport->ParentViewportId);
vd->ParentWindow = ImGui_ImplSDL3_GetSDLWindowFromViewport(viewport->ParentViewport);
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGui_ImplSDL3_ViewportData* main_viewport_data = (ImGui_ImplSDL3_ViewportData*)main_viewport->PlatformUserData;
@@ -1114,7 +1113,7 @@ static void ImGui_ImplSDL3_UpdateWindow(ImGuiViewport* viewport)
#ifndef __APPLE__ // On Mac, SDL3 Parenting appears to prevent viewport from appearing in another monitor
// Update SDL3 parent if it changed _after_ creation.
// This is for advanced apps that are manipulating ParentViewportID manually.
SDL_Window* new_parent = ImGui_ImplSDL3_GetSDLWindowFromViewportID(viewport->ParentViewportId);
SDL_Window* new_parent = ImGui_ImplSDL3_GetSDLWindowFromViewport(viewport->ParentViewport);
if (new_parent != vd->ParentWindow)
{
vd->ParentWindow = new_parent;

View File

@@ -1123,11 +1123,10 @@ static void ImGui_ImplWin32_GetWin32StyleFromViewportFlags(ImGuiViewportFlags fl
*out_ex_style |= WS_EX_TOPMOST;
}
static HWND ImGui_ImplWin32_GetHwndFromViewportID(ImGuiID viewport_id)
static HWND ImGui_ImplWin32_GetHwndFromViewport(ImGuiViewport* viewport)
{
if (viewport_id != 0)
if (ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id))
return (HWND)viewport->PlatformHandle;
if (viewport != nullptr)
return (HWND)viewport->PlatformHandle;
return nullptr;
}
@@ -1138,7 +1137,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
// Select style and parent window
ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &vd->DwStyle, &vd->DwExStyle);
vd->HwndParent = ImGui_ImplWin32_GetHwndFromViewportID(viewport->ParentViewportId);
vd->HwndParent = ImGui_ImplWin32_GetHwndFromViewport(viewport->ParentViewport);
// Create window
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
@@ -1201,7 +1200,7 @@ static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport)
// Update Win32 parent if it changed _after_ creation
// Unlike style settings derived from configuration flags, this is more likely to change for advanced apps that are manipulating ParentViewportID manually.
HWND new_parent = ImGui_ImplWin32_GetHwndFromViewportID(viewport->ParentViewportId);
HWND new_parent = ImGui_ImplWin32_GetHwndFromViewport(viewport->ParentViewport);
if (new_parent != vd->HwndParent)
{
// Win32 windows can either have a "Parent" (for WS_CHILD window) or an "Owner" (which among other thing keeps window above its owner).

View File

@@ -118,6 +118,7 @@ Docking+Viewports Branch:
Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID.
setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation
with what the backend does.
- Viewports: storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID.
- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at
it assumed to be unnecessary as backensd should have done it and we check that
backends have been shutdown since 1.90.4. Changed into asserts. (#7175, #8945)

View File

@@ -17023,11 +17023,22 @@ void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_win
// Update parent viewport ID
// (the !IsFallbackWindow test mimic the one done in WindowSelectViewport())
if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
{
ImGuiID old_parent_viewport_id = window->Viewport->ParentViewportId;
window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
if (window->Viewport->ParentViewportId != old_parent_viewport_id)
window->Viewport->ParentViewport = FindViewportByID(window->Viewport->ParentViewportId);
}
else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack && (!parent_window_in_stack->IsFallbackWindow || parent_window_in_stack->WasActive))
{
window->Viewport->ParentViewport = parent_window_in_stack->Viewport;
window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
}
else
{
window->Viewport->ParentViewport = g.IO.ConfigViewportsNoDefaultParent ? NULL : GetMainViewport();
window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID;
}
}
// Called by user at the end of the main loop, after EndFrame()

View File

@@ -29,7 +29,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.4 WIP"
#define IMGUI_VERSION_NUM 19233
#define IMGUI_VERSION_NUM 19234
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
@@ -4044,6 +4044,7 @@ struct ImGuiViewport
ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size)
float DpiScale; // 1.0f = 96 DPI = No extra scale.
ImGuiID ParentViewportId; // (Advanced) 0: no parent. Instruct the platform backend to setup a parent/child relationship between platform windows.
ImGuiViewport* ParentViewport; // (Advanced) == ImGui::FindViewportByID(ParentViewportId)
ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame().
// Platform/Backend Dependent Data