From 6a6d7bc3ca5f6a88517177988f4b8b8caf3b3822 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Aug 2026 20:38:18 +0200 Subject: [PATCH] Internals: added SetNextWindowFlags(), SetNextWindowChildFlags() helpers + made BeginChildEx() itself read from them. (#9503, #8280, #9412, #9499, #9393, #8488) As a result BeginTable() doesn't need to read itself and pass that to BeginChildEx(). --- imgui.cpp | 44 +++++++++++++++++++++++++++++--------------- imgui.h | 2 +- imgui_internal.h | 8 ++++++-- imgui_tables.cpp | 7 ++----- 4 files changed, 38 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e8b16a7fa..d157353cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6537,6 +6537,9 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I ImGuiWindow* parent_window = g.CurrentWindow; IM_ASSERT(id != 0); + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) + child_flags = (child_flags | g.NextWindowData.ChildFlagsSet) & ~g.NextWindowData.ChildFlagsClear; + // Sanity check as it is likely that some user will accidentally pass ImGuiWindowFlags into the ImGuiChildFlags argument. const ImGuiChildFlags ImGuiChildFlags_SupportedMask_ = ImGuiChildFlags_Borders | ImGuiChildFlags_AlwaysUseWindowPadding | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY | ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize | ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened; IM_UNUSED(ImGuiChildFlags_SupportedMask_); @@ -6599,13 +6602,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I } } SetNextWindowSize(size); - - // Forward child flags (we allow prior settings to merge but it'll only work for adding flags) - if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) - g.NextWindowData.ChildFlags |= child_flags; - else - g.NextWindowData.ChildFlags = child_flags; - g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags; + SetNextWindowChildFlags(child_flags, true); // Build up name. If you need to append to a same child from multiple location in the ID stack, use BeginChild(ImGuiID id) with a stable value. // FIXME: 2023/11/14: commented out shorted version. We had an issue with multiple ### in child window path names, which the trailing hash helped workaround. @@ -7550,6 +7547,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (g.DebugBreakInWindow == window->ID) IM_DEBUG_BREAK(); + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) + flags = (flags | g.NextWindowData.WindowFlagsSet) & ~g.NextWindowData.WindowFlagsClear; + // Automatically disable manual moving/resizing when NoInputs is set if ((flags & ImGuiWindowFlags_NoInputs) == ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; @@ -7575,7 +7575,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { UpdateWindowInFocusOrderList(window, window_just_created, flags); window->Flags = (ImGuiWindowFlags)flags; - window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; + window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlagsSet : 0; window->LastFrameActive = current_frame; window->LastTimeActive = (float)g.Time; window->BeginOrderWithinParent = 0; @@ -8834,6 +8834,26 @@ void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags) g.NextWindowData.RefreshFlagsVal = flags; } +void ImGui::SetNextWindowFlags(ImGuiWindowFlags flags, bool enabled) +{ + ImGuiContext& g = *GImGui; + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) == 0) + g.NextWindowData.WindowFlagsSet = g.NextWindowData.WindowFlagsClear = ImGuiChildFlags_None; + g.NextWindowData.WindowFlagsSet = enabled ? (g.NextWindowData.WindowFlagsSet | flags) : (g.NextWindowData.WindowFlagsSet & ~flags); + g.NextWindowData.WindowFlagsClear = !enabled ? (g.NextWindowData.WindowFlagsClear | flags) : (g.NextWindowData.WindowFlagsClear & ~flags); + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasWindowFlags; +} + +void ImGui::SetNextWindowChildFlags(ImGuiChildFlags flags, bool enabled) +{ + ImGuiContext& g = *GImGui; + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) == 0) + g.NextWindowData.ChildFlagsSet = g.NextWindowData.ChildFlagsClear = ImGuiChildFlags_None; + g.NextWindowData.ChildFlagsSet = enabled ? (g.NextWindowData.ChildFlagsSet | flags) : (g.NextWindowData.ChildFlagsSet & ~flags); + g.NextWindowData.ChildFlagsClear = !enabled ? (g.NextWindowData.ChildFlagsClear | flags) : (g.NextWindowData.ChildFlagsClear & ~flags); + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags; +} + ImDrawList* ImGui::GetWindowDrawList() { ImGuiWindow* window = GetCurrentWindow(); @@ -12674,13 +12694,7 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext // As we bypass BeginChild(), set ImGuiChildFlags_AlwaysAutoResize as it is checked independently from ImGuiWindowFlags_AlwaysAutoResize for now (see #9355) // Ideally we should remove setting ImGuiWindowFlags_AlwaysAutoResize in BeginChild(). if ((extra_window_flags & ImGuiWindowFlags_ChildWindow) && (extra_window_flags & ImGuiWindowFlags_AlwaysAutoResize)) - { - if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) - g.NextWindowData.ChildFlags |= ImGuiChildFlags_AlwaysAutoResize; - else - g.NextWindowData.ChildFlags = ImGuiChildFlags_AlwaysAutoResize; - g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags; - } + SetNextWindowChildFlags(ImGuiChildFlags_AlwaysAutoResize, true); char name[128]; IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu); diff --git a/imgui.h b/imgui.h index fea82515d..43f297d44 100644 --- a/imgui.h +++ b/imgui.h @@ -30,7 +30,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.93.0 WIP" -#define IMGUI_VERSION_NUM 19292 +#define IMGUI_VERSION_NUM 19293 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198 diff --git a/imgui_internal.h b/imgui_internal.h index 59f005508..d837a6962 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1360,8 +1360,10 @@ struct ImGuiNextWindowData ImVec2 SizeVal; ImVec2 ContentSizeVal; ImVec2 ScrollVal; - ImGuiWindowFlags WindowFlags; // Only honored by BeginTable() - ImGuiChildFlags ChildFlags; + ImGuiWindowFlags WindowFlagsSet; // Flags to set. Use SetNextWindowFlags()! + ImGuiWindowFlags WindowFlagsClear; + ImGuiChildFlags ChildFlagsSet; // Flags to set. Use SetNextWindowChildFlags(). + ImGuiChildFlags ChildFlagsClear; bool CollapsedVal; ImRect SizeConstraintRect; ImGuiSizeCallback SizeCallback; @@ -3368,6 +3370,8 @@ namespace ImGui inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); } inline ImVec2 WindowPosAbsToRel(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x - off.x, p.y - off.y); } inline ImVec2 WindowPosRelToAbs(ImGuiWindow* window, const ImVec2& p) { ImVec2 off = window->DC.CursorStartPos; return ImVec2(p.x + off.x, p.y + off.y); } + IMGUI_API void SetNextWindowFlags(ImGuiWindowFlags flags, bool enabled); + IMGUI_API void SetNextWindowChildFlags(ImGuiChildFlags flags, bool enabled); // Windows: Display Order and Focus Order IMGUI_API void FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags = 0); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 19f7933ed..8f260c873 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -428,11 +428,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) - ImGuiChildFlags child_child_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : ImGuiChildFlags_None; - ImGuiWindowFlags child_window_flags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasWindowFlags) ? g.NextWindowData.WindowFlags : ImGuiWindowFlags_None; - if (flags & ImGuiTableFlags_ScrollX) - child_window_flags |= ImGuiWindowFlags_HorizontalScrollbar; - BeginChildEx(name, instance_id, outer_rect.GetSize(), child_child_flags, child_window_flags); + ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; + BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect();