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

View File

@@ -1123,11 +1123,10 @@ static void ImGui_ImplWin32_GetWin32StyleFromViewportFlags(ImGuiViewportFlags fl
*out_ex_style |= WS_EX_TOPMOST; *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 (viewport != nullptr)
if (ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id)) return (HWND)viewport->PlatformHandle;
return (HWND)viewport->PlatformHandle;
return nullptr; return nullptr;
} }
@@ -1138,7 +1137,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
// Select style and parent window // Select style and parent window
ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &vd->DwStyle, &vd->DwExStyle); 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 // 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) }; 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 // 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. // 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) 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). // 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. Note that for GLFW/SDL2/OSX backends, which do not support honoring ParentViewportID.
setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation setting io.ConfigViewportsNoDefaultParent=true will align imgui's expectation
with what the backend does. with what the backend does.
- Viewports: storing `ImGuiViewport* ParentViewport` pointer along with ParentViewportID.
- Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at - Viewports: DestroyContext() does not call DestroyPlatformWindows() anymore at
it assumed to be unnecessary as backensd should have done it and we check that 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) 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 // Update parent viewport ID
// (the !IsFallbackWindow test mimic the one done in WindowSelectViewport()) // (the !IsFallbackWindow test mimic the one done in WindowSelectViewport())
if (window->WindowClass.ParentViewportId != (ImGuiID)-1) if (window->WindowClass.ParentViewportId != (ImGuiID)-1)
{
ImGuiID old_parent_viewport_id = window->Viewport->ParentViewportId;
window->Viewport->ParentViewportId = window->WindowClass.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)) 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; window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
}
else else
{
window->Viewport->ParentViewport = g.IO.ConfigViewportsNoDefaultParent ? NULL : GetMainViewport();
window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID; window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID;
}
} }
// Called by user at the end of the main loop, after EndFrame() // Called by user at the end of the main loop, after EndFrame()

View File

@@ -29,7 +29,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (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 "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_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch. #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) 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. 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. 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(). ImDrawData* DrawData; // The ImDrawData corresponding to this viewport. Valid after Render() and until the next call to NewFrame().
// Platform/Backend Dependent Data // Platform/Backend Dependent Data