From e5668b8c738bd76d372a46e6a3d10812193be12f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:48:31 +0100 Subject: [PATCH 01/18] Internals: rename ImGuiNextWindowData::Flags to HasFlags for consistency and to reduce mistakes. --- imgui.cpp | 52 +++++++++++++++++++++++------------------------ imgui_internal.h | 9 +++++--- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 12 +++++------ 4 files changed, 39 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 29fe4a220..4ba2051d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6068,7 +6068,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I // A SetNextWindowSize() call always has priority (#8020) // (since the code in Begin() never supported SizeVal==0.0f aka auto-resize via SetNextWindowSize() call, we don't support it here for now) // FIXME: We only support ImGuiCond_Always in this path. Supporting other paths would requires to obtain window pointer. - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) != 0 && (g.NextWindowData.SizeCond & ImGuiCond_Always) != 0) { if (g.NextWindowData.SizeVal.x > 0.0f) { @@ -6084,11 +6084,11 @@ 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.Flags & ImGuiNextWindowDataFlags_HasChildFlags) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) g.NextWindowData.ChildFlags |= child_flags; else g.NextWindowData.ChildFlags = child_flags; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasChildFlags; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags; // 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. @@ -6302,7 +6302,7 @@ static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, const ImVec2& s { ImGuiContext& g = *GImGui; ImVec2 new_size = size_desired; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint) { // See comments in SetNextWindowSizeConstraints() for details about setting size_min an size_max. ImRect cr = g.NextWindowData.SizeConstraintRect; @@ -6780,7 +6780,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar ImU32 bg_col = GetColorU32(GetWindowBgColorIdx(window)); bool override_alpha = false; float alpha = 1.0f; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasBgAlpha) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasBgAlpha) { alpha = g.NextWindowData.BgAlphaVal; override_alpha = true; @@ -6950,7 +6950,7 @@ void ImGui::UpdateWindowSkipRefresh(ImGuiWindow* window) { ImGuiContext& g = *GImGui; window->SkipRefresh = false; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasRefreshPolicy) == 0) return; if (g.NextWindowData.RefreshFlagsVal & ImGuiWindowRefreshFlags_TryToAvoidRefresh) { @@ -7031,7 +7031,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.Flags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; + window->ChildFlags = (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags) ? g.NextWindowData.ChildFlags : 0; window->LastFrameActive = current_frame; window->LastTimeActive = (float)g.Time; window->BeginOrderWithinParent = 0; @@ -7095,7 +7095,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // (FIXME: Consider splitting the HasXXX flags into X/Y components bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) { window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) @@ -7111,7 +7111,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); } } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) { window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); @@ -7121,7 +7121,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) g.NextWindowData.SizeVal.y = window->SizeFull.y; SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll) { if (g.NextWindowData.ScrollVal.x >= 0.0f) { @@ -7134,13 +7134,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ScrollTargetCenterRatio.y = 0.0f; } } - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasContentSize) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasContentSize) window->ContentSizeExplicit = g.NextWindowData.ContentSizeVal; else if (first_begin_of_the_frame) window->ContentSizeExplicit = ImVec2(0.0f, 0.0f); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasCollapsed) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasCollapsed) SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasFocus) FocusWindow(window); if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); @@ -8223,7 +8223,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasPos; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasPos; g.NextWindowData.PosVal = pos; g.NextWindowData.PosPivotVal = pivot; g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; @@ -8233,7 +8233,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSize; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSize; g.NextWindowData.SizeVal = size; g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } @@ -8245,7 +8245,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasSizeConstraint; g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); g.NextWindowData.SizeCallback = custom_callback; g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; @@ -8256,14 +8256,14 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasContentSize; g.NextWindowData.ContentSizeVal = ImTrunc(size); } void ImGui::SetNextWindowScroll(const ImVec2& scroll) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasScroll; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasScroll; g.NextWindowData.ScrollVal = scroll; } @@ -8271,7 +8271,7 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasCollapsed; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasCollapsed; g.NextWindowData.CollapsedVal = collapsed; g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } @@ -8279,7 +8279,7 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) void ImGui::SetNextWindowBgAlpha(float alpha) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasBgAlpha; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasBgAlpha; g.NextWindowData.BgAlphaVal = alpha; } @@ -8287,7 +8287,7 @@ void ImGui::SetNextWindowBgAlpha(float alpha) void ImGui::SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags) { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasRefreshPolicy; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasRefreshPolicy; g.NextWindowData.RefreshFlagsVal = flags; } @@ -11301,7 +11301,7 @@ bool ImGui::BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags ext // See FindBestWindowPosForPopup() for positionning logic of other tooltips (not drag and drop ones). //ImVec2 tooltip_pos = g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding; const bool is_touchscreen = (g.IO.MouseSource == ImGuiMouseSource_TouchScreen); - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0) { ImVec2 tooltip_pos = is_touchscreen ? (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_TOUCH * g.Style.MouseCursorScale) : (g.IO.MousePos + TOOLTIP_DEFAULT_OFFSET_MOUSE * g.Style.MouseCursorScale); ImVec2 tooltip_pivot = is_touchscreen ? TOOLTIP_DEFAULT_PIVOT_TOUCH : ImVec2(0.0f, 0.0f); @@ -11724,7 +11724,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla // Center modal windows by default for increased visibility // (this won't really last as settings will kick in, and is mostly for backward compatibility. user may do the same themselves) // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasPos) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasPos) == 0) { const ImGuiViewport* viewport = GetMainViewport(); SetNextWindowPos(viewport->GetCenter(), ImGuiCond_FirstUseEver, ImVec2(0.5f, 0.5f)); @@ -12017,7 +12017,7 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus; + g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasFocus; } // Similar to IsWindowHovered() @@ -16548,7 +16548,7 @@ static void ShowDebugLogFlag(const char* name, ImGuiDebugLogFlags flags) void ImGui::ShowDebugLogWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 12.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui Debug Log", p_open) || GetCurrentWindow()->BeginCount > 1) { @@ -16868,7 +16868,7 @@ static int StackToolFormatLevelInfo(ImGuiIDStackTool* tool, int n, bool format_f void ImGui::ShowIDStackToolWindow(bool* p_open) { ImGuiContext& g = *GImGui; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0) SetNextWindowSize(ImVec2(0.0f, GetFontSize() * 8.0f), ImGuiCond_FirstUseEver); if (!Begin("Dear ImGui ID Stack Tool", p_open) || GetCurrentWindow()->BeginCount > 1) { diff --git a/imgui_internal.h b/imgui_internal.h index 0aa894d56..ad9dc91e8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1201,7 +1201,9 @@ enum ImGuiNextWindowDataFlags_ // Storage for SetNexWindow** functions struct ImGuiNextWindowData { - ImGuiNextWindowDataFlags Flags; + ImGuiNextWindowDataFlags HasFlags; + + // Members below are NOT cleared. Always rely on HasFlags. ImGuiCond PosCond; ImGuiCond SizeCond; ImGuiCond CollapsedCond; @@ -1220,7 +1222,7 @@ struct ImGuiNextWindowData ImGuiWindowRefreshFlags RefreshFlagsVal; ImGuiNextWindowData() { memset(this, 0, sizeof(*this)); } - inline void ClearFlags() { Flags = ImGuiNextWindowDataFlags_None; } + inline void ClearFlags() { HasFlags = ImGuiNextWindowDataFlags_None; } }; enum ImGuiNextItemDataFlags_ @@ -1237,7 +1239,8 @@ struct ImGuiNextItemData { ImGuiNextItemDataFlags HasFlags; // Called HasFlags instead of Flags to avoid mistaking this ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData. - // Non-flags members are NOT cleared by ItemAdd() meaning they are still valid during NavProcessItem() + + // Members below are NOT cleared by ItemAdd() meaning they are still valid during e.g. NavProcessItem(). Always rely on HasFlags. ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData() ImGuiSelectionUserData SelectionUserData; // Set by SetNextItemSelectionUserData() (note that NULL/0 is a valid value, we use -1 == ImGuiSelectionUserData_Invalid to mark invalid values) float Width; // Set by SetNextItemWidth() diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 71d1e7d8b..3bd9502d0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -415,7 +415,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // Reset scroll if we are reactivating it if ((previous_flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) == 0) - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasScroll) == 0) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasScroll) == 0) SetNextWindowScroll(ImVec2(0.0f, 0.0f)); // Create scrolling region (without border and zero window padding) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d246147bd..2b95c0dd5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1829,7 +1829,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags; + ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.HasFlags; g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values if (window->SkipItems) return false; @@ -1898,7 +1898,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (!popup_open) return false; - g.NextWindowData.Flags = backup_next_window_data_flags; + g.NextWindowData.HasFlags = backup_next_window_data_flags; return BeginComboPopup(popup_id, bb, flags); } @@ -1913,7 +1913,7 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags // Set popup size float w = bb.GetWidth(); - if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) + if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint) { g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); } @@ -1927,9 +1927,9 @@ bool ImGui::BeginComboPopup(ImGuiID popup_id, const ImRect& bb, ImGuiComboFlags else if (flags & ImGuiComboFlags_HeightSmall) popup_max_height_in_items = 4; else if (flags & ImGuiComboFlags_HeightLarge) popup_max_height_in_items = 20; ImVec2 constraint_min(0.0f, 0.0f), constraint_max(FLT_MAX, FLT_MAX); - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.x <= 0.0f) // Don't apply constraints if user specified a size constraint_min.x = w; - if ((g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f) + if ((g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSize) == 0 || g.NextWindowData.SizeVal.y <= 0.0f) constraint_max.y = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(constraint_min, constraint_max); } @@ -2061,7 +2061,7 @@ bool ImGui::Combo(const char* label, int* current_item, const char* (*getter)(vo preview_value = getter(user_data, *current_item); // The old Combo() API exposed "popup_max_height_in_items". The new more general BeginCombo() API doesn't have/need it, but we emulate it here. - if (popup_max_height_in_items != -1 && !(g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint)) + if (popup_max_height_in_items != -1 && !(g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasSizeConstraint)) SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, CalcMaxPopupHeightFromItemCount(popup_max_height_in_items))); if (!BeginCombo(label, preview_value, ImGuiComboFlags_None)) From e368015d79a9deffc45894fcd33586092f968395 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:56:02 +0100 Subject: [PATCH 02/18] Tables: a clipped scrolling table correctly clears SetNextWindowXXX flags. (#8196) Amend 43c51eb12 --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b9888b134..8fa53fc25 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Other changes: visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] - Scrollbar: Rework logic that fades-out scrollbar when it becomes too small, which amusingly made it disappear when using very big font/frame size. +- Tables: fixed calling SetNextWindowScroll() on clipped scrolling table + to not leak the value into a subsequent window. (#8196) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3bd9502d0..2c1a0d362 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -340,6 +340,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG { ItemSize(outer_rect); ItemAdd(outer_rect, id); + g.NextWindowData.ClearFlags(); return false; } From 50dbb086f23594c1b3b8db8ecaf255b6cbace832 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 7 Feb 2025 22:57:15 +0100 Subject: [PATCH 03/18] Tables: sneakily honor ImGuiNextWindowDataFlags_HasChildFlags/ImGuiNextWindowDataFlags_HasWindowFlags as a way to facilitate various hacks/workarounds. --- imgui_internal.h | 6 ++++-- imgui_tables.cpp | 7 +++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index ad9dc91e8..f2aaeaa83 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1194,8 +1194,9 @@ enum ImGuiNextWindowDataFlags_ ImGuiNextWindowDataFlags_HasFocus = 1 << 5, ImGuiNextWindowDataFlags_HasBgAlpha = 1 << 6, ImGuiNextWindowDataFlags_HasScroll = 1 << 7, - ImGuiNextWindowDataFlags_HasChildFlags = 1 << 8, - ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 9, + ImGuiNextWindowDataFlags_HasWindowFlags = 1 << 8, + ImGuiNextWindowDataFlags_HasChildFlags = 1 << 9, + ImGuiNextWindowDataFlags_HasRefreshPolicy = 1 << 10, }; // Storage for SetNexWindow** functions @@ -1212,6 +1213,7 @@ struct ImGuiNextWindowData ImVec2 SizeVal; ImVec2 ContentSizeVal; ImVec2 ScrollVal; + ImGuiWindowFlags WindowFlags; // Only honored by BeginTable() ImGuiChildFlags ChildFlags; bool CollapsedVal; ImRect SizeConstraintRect; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 2c1a0d362..c2e012776 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -420,8 +420,11 @@ 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) - ImGuiWindowFlags child_window_flags = (flags & ImGuiTableFlags_ScrollX) ? ImGuiWindowFlags_HorizontalScrollbar : ImGuiWindowFlags_None; - BeginChildEx(name, instance_id, outer_rect.GetSize(), ImGuiChildFlags_None, child_window_flags); + 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); table->InnerWindow = g.CurrentWindow; table->WorkRect = table->InnerWindow->WorkRect; table->OuterRect = table->InnerWindow->Rect(); From e8ad60cc4f7ade30db505f739772befd3eb62b26 Mon Sep 17 00:00:00 2001 From: edenware <52419657+edenoftheware@users.noreply.github.com> Date: Fri, 7 Feb 2025 21:01:46 -0600 Subject: [PATCH 04/18] Fix typo (#8382) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index d58473801..6f9f11ebc 100644 --- a/imgui.h +++ b/imgui.h @@ -3132,7 +3132,7 @@ struct ImDrawList // General polygon // - Only simple polygons are supported by filling functions (no self-intersections, no holes). - // - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience fo user but not used by main library. + // - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library. IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness); IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col); IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col); From 2206e31e5449217b7298d7d704ef5da1763a128f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 11:37:55 +0100 Subject: [PATCH 05/18] Demo: Combos: demonstrate a very simple way to add a filter to a combo. (#718) --- docs/CHANGELOG.txt | 2 ++ imgui_demo.cpp | 32 +++++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 8fa53fc25..c30f81817 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- Demo: Combos: demonstrate a very simple way to add a filter to a combo, + by showing the filter inside the combo contents. (#718) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3c40de2e7..0898ef251 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1435,7 +1435,6 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[]) const char* combo_preview_value = items[item_selected_idx]; - if (ImGui::BeginCombo("combo 1", combo_preview_value, flags)) { for (int n = 0; n < IM_ARRAYSIZE(items); n++) @@ -1451,23 +1450,46 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) ImGui::EndCombo(); } + // Show case embedding a filter using a simple trick: displaying the filter inside combo contents. + // See https://github.com/ocornut/imgui/issues/718 for advanced/esoteric alternatives. + if (ImGui::BeginCombo("combo 2 (w/ filter)", combo_preview_value, flags)) + { + static ImGuiTextFilter filter; + if (ImGui::IsWindowAppearing()) + { + ImGui::SetKeyboardFocusHere(); + filter.Clear(); + } + ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); + filter.Draw("##Filter", -FLT_MIN); + + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + const bool is_selected = (item_selected_idx == n); + if (filter.PassFilter(items[n])) + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + } + ImGui::EndCombo(); + } + ImGui::Spacing(); ImGui::SeparatorText("One-liner variants"); - HelpMarker("Flags above don't apply to this section."); + HelpMarker("The Combo() function is not greatly useful apart from cases were you want to embed all options in a single strings.\nFlags above don't apply to this section."); // Simplified one-liner Combo() API, using values packed in a single constant string // This is a convenience for when the selection set is small and known at compile-time. static int item_current_2 = 0; - ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + ImGui::Combo("combo 3 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Simplified one-liner Combo() using an array of const char* // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control. static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview - ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); + ImGui::Combo("combo 4 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); // Simplified one-liner Combo() using an accessor function static int item_current_4 = 0; - ImGui::Combo("combo 4 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); + ImGui::Combo("combo 5 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items)); ImGui::TreePop(); } From a18622c3695c8fb178acefad2da26f3ba2e50ffc Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:02:01 +0100 Subject: [PATCH 06/18] TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 +++++- imgui.h | 2 +- imgui_demo.cpp | 3 +++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c30f81817..ab4345fb3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to + handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] diff --git a/imgui.cpp b/imgui.cpp index 4ba2051d5..2402bf109 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -15090,7 +15090,11 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha #endif static bool Platform_OpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) { - return (INT_PTR)::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT) > 32; + const int path_wsize = ::MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0); + ImVector path_wbuf; + path_wbuf.resize(path_wsize); + ::MultiByteToWideChar(CP_UTF8, 0, path, -1, path_wbuf.Data, path_wsize); + return (INT_PTR)::ShellExecuteW(NULL, L"open", path_wbuf.Data, NULL, NULL, SW_SHOWDEFAULT) > 32; } #else #include diff --git a/imgui.h b/imgui.h index 6f9f11ebc..29daaae7e 100644 --- a/imgui.h +++ b/imgui.h @@ -3565,7 +3565,7 @@ struct ImGuiPlatformIO void* Platform_ClipboardUserData; // Optional: Open link/folder/file in OS Shell - // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) + // (default to use ShellExecuteW() on Windows, system() on Linux/Mac) bool (*Platform_OpenInShellFn)(ImGuiContext* ctx, const char* path); void* Platform_OpenInShellUserData; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0898ef251..2774fbc96 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7771,6 +7771,9 @@ void ImGui::ShowAboutWindow(bool* p_open) #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS"); #endif +#ifdef IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS + ImGui::Text("define: IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS"); +#endif #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS"); #endif From a431e1277e8f4907ff874b466b71b98696cdc227 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:09:44 +0100 Subject: [PATCH 07/18] Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. (#7660) --- backends/imgui_impl_sdl2.cpp | 3 +++ backends/imgui_impl_sdl3.cpp | 2 ++ docs/CHANGELOG.txt | 2 ++ 3 files changed, 7 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index a27962a31..abe0e4342 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,6 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: from SDL 2.30.9, SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f. // 2024-09-09: use SDL_Vulkan_GetDrawableSize() when available. (#7967, #3190) @@ -480,6 +481,8 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetImeDataFn = ImGui_ImplSDL2_PlatformSetImeData; #ifdef __EMSCRIPTEN__ platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { ImGui_ImplSDL2_EmscriptenOpenURL(url); return true; }; +#else + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; #endif // Gamepad handling diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index d5de5443e..16ab5706b 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -20,6 +20,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-02-10: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn handler. // 2025-01-20: Made ImGui_ImplSDL3_SetGamepadMode(ImGui_ImplSDL3_GamepadMode_Manual) accept an empty array. // 2024-10-24: Emscripten: SDL_EVENT_MOUSE_WHEEL event doesn't require dividing by 100.0f on Emscripten. // 2024-09-03: Update for SDL3 api changes: SDL_GetGamepads() memory ownership revert. (#7918, #7898, #7807) @@ -464,6 +465,7 @@ static bool ImGui_ImplSDL3_Init(SDL_Window* window, SDL_Renderer* renderer, void platform_io.Platform_SetClipboardTextFn = ImGui_ImplSDL3_SetClipboardText; platform_io.Platform_GetClipboardTextFn = ImGui_ImplSDL3_GetClipboardText; platform_io.Platform_SetImeDataFn = ImGui_ImplSDL3_PlatformSetImeData; + platform_io.Platform_OpenInShellFn = [](ImGuiContext*, const char* url) { return SDL_OpenURL(url) == 0; }; // Gamepad handling bd->GamepadMode = ImGui_ImplSDL3_GamepadMode_AutoFirst; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ab4345fb3..74416e373 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -61,6 +61,8 @@ Other changes: handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, by showing the filter inside the combo contents. (#718) +- Backends: SDL2, SDL3: Using SDL_OpenURL() in platform_io.Platform_OpenInShellFn + handler. (#7660) [@achabense] - Backends: Metal: Fixed a crash on application resources. (#8367, #7419) [@anszom] - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) From 88cda0cab6f369c2629f6a32b0eaae4436d77c1c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 12:39:54 +0100 Subject: [PATCH 08/18] Fixed minor warning. Added comment. --- backends/imgui_impl_opengl3.cpp | 1 + imgui.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index efc1a3c49..9465388a6 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -303,6 +303,7 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) // GLES 2 bd->GlVersion = 200; bd->GlProfileIsES2 = true; + IM_UNUSED(gl_version_str); #else // Desktop or GLES 3 GLint major = 0; diff --git a/imgui.cpp b/imgui.cpp index 2402bf109..b909e0c30 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2399,7 +2399,7 @@ int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* int e = 0; e = (*out_char < mins[len]) << 6; // non-canonical encoding e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? - e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? + e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range we can store in ImWchar (FIXME: May evolve) e |= (s[1] & 0xc0) >> 2; e |= (s[2] & 0xc0) >> 4; e |= (s[3] ) >> 6; From 4dc9df6aae8ff1f09701c13c053ed9fd55efaff4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 19:29:18 +0100 Subject: [PATCH 09/18] Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) --- docs/CHANGELOG.txt | 3 +++ imgui_internal.h | 4 ++-- imgui_tables.cpp | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 74416e373..b76f7455b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,6 +57,8 @@ Other changes: which amusingly made it disappear when using very big font/frame size. - Tables: fixed calling SetNextWindowScroll() on clipped scrolling table to not leak the value into a subsequent window. (#8196) +- Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly + overridden when hot-reloading .ini state. (#7934) - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, @@ -67,6 +69,7 @@ Other changes: - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) + ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) ----------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index f2aaeaa83..b904909d7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2944,7 +2944,7 @@ struct ImGuiTableColumnSettings ImGuiTableColumnIdx DisplayOrder; ImGuiTableColumnIdx SortOrder; ImU8 SortDirection : 2; - ImU8 IsEnabled : 1; // "Visible" in ini file + ImS8 IsEnabled : 2; // "Visible" in ini file ImU8 IsStretch : 1; ImGuiTableColumnSettings() @@ -2954,7 +2954,7 @@ struct ImGuiTableColumnSettings Index = -1; DisplayOrder = SortOrder = -1; SortDirection = ImGuiSortDirection_None; - IsEnabled = 1; + IsEnabled = -1; IsStretch = 0; } }; diff --git a/imgui_tables.cpp b/imgui_tables.cpp index c2e012776..3a023d426 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -3741,7 +3741,7 @@ void ImGui::TableLoadSettings(ImGuiTable* table) else column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder; - column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled; + column->IsUserEnabled = column->IsUserEnabledNextFrame = (column_settings->IsEnabled != -1 ? column_settings->IsEnabled == 1 : (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1); column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; } From 3b2f2602b4d6ecb0d7c09865dccbf8036afc002a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 10 Feb 2025 21:33:49 +0100 Subject: [PATCH 10/18] Windows: Fixed an issue where BeginChild() inside a collapsed Begin() wouldn't inherit the SkipItems flag. Amend/fix a89f05a10 (old!) Discovered while looking at glyph being processed in WIP branch. --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 2 +- imgui.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b76f7455b..1253dc41d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,9 @@ Other changes: - Fixed IsItemDeactivatedAfterEdit() signal being broken for Checkbox(), RadioButton(), Selectable(). Regression from 2025/01/13. (#8370) +- Windows: Fixed an issue where BeginChild() inside a collapsed Begin() + wouldn't inherit the SkipItems flag, resulting in missing coarse clipping + opportunity for code not checking the BeginChild() return value. - Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders and detection of hovered window. diff --git a/imgui.cpp b/imgui.cpp index b909e0c30..1945dd6c4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7702,7 +7702,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Hide along with parent or if parent is collapsed if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCanSkipItems > 0)) window->HiddenFramesCanSkipItems = 1; - if (parent_window && (parent_window->Collapsed || parent_window->HiddenFramesCannotSkipItems > 0)) + if (parent_window && parent_window->HiddenFramesCannotSkipItems > 0) window->HiddenFramesCannotSkipItems = 1; } diff --git a/imgui.h b/imgui.h index 29daaae7e..86137e5e1 100644 --- a/imgui.h +++ b/imgui.h @@ -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.91.9 WIP" -#define IMGUI_VERSION_NUM 19183 +#define IMGUI_VERSION_NUM 19184 #define IMGUI_HAS_TABLE /* From 6916f935eb221b351178349deb33282cbc24f7a9 Mon Sep 17 00:00:00 2001 From: fdsa <14tanks999@gmail.com> Date: Tue, 11 Feb 2025 13:12:55 -0800 Subject: [PATCH 11/18] InputText: Allow CTRL+Shift+Z to redo even outside of OSX. (#8389) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 ++- imgui_demo.cpp | 8 ++++---- imgui_widgets.cpp | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1253dc41d..cdb5e3845 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -53,6 +53,7 @@ Other changes: - Windows, Style: Added style.WindowBorderHoverPadding setting to configure inner/outer padding applied to hit-testing of windows borders and detection of hovered window. +- InputText: Allow CTRL+Shift+Z to redo even outside of OSX. (#8389) [@tanksdude] - InputTextWithHint(): Fixed buffer-overflow (luckily often with no visible effect) when a user callback modified the buffer contents in a way that altered the visibility of the preview/hint buffer. (#8368) [@m9710797, @ocornut] diff --git a/imgui.cpp b/imgui.cpp index 1945dd6c4..af4aa2068 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -142,7 +142,8 @@ CODE - CTRL+Shift+Left/Right: Select words. - CTRL+A or Double-Click: Select All. - CTRL+X, CTRL+C, CTRL+V: Use OS clipboard. - - CTRL+Z, CTRL+Y: Undo, Redo. + - CTRL+Z Undo. + - CTRL+Y or CTRL+Shift+Z: Redo. - ESCAPE: Revert text to its original value. - On OSX, controls are automatically adjusted to match standard OSX text editing 2ts and behaviors. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2774fbc96..db9a6de1a 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -861,8 +861,8 @@ static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data) "Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or Double-Click to select all.\n" - "CTRL+X,CTRL+C,CTRL+V clipboard.\n" - "CTRL+Z,CTRL+Y undo/redo.\n" + "CTRL+X,CTRL+C,CTRL+V for clipboard.\n" + "CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo.\n" "ESCAPE to revert.\n\n" "PROGRAMMER:\n" "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() " @@ -8237,7 +8237,7 @@ void ImGui::ShowUserGuide() ImGui::BulletText("CTRL+Left/Right to word jump."); ImGui::BulletText("CTRL+A or double-click to select all."); ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste."); - ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo."); + ImGui::BulletText("CTRL+Z to undo, CTRL+Y/CTRL+SHIFT+Z to redo."); ImGui::BulletText("ESCAPE to revert."); ImGui::Unindent(); ImGui::BulletText("With keyboard navigation enabled:"); @@ -8273,7 +8273,7 @@ static void ShowExampleAppMainMenuBar() if (ImGui::BeginMenu("Edit")) { if (ImGui::MenuItem("Undo", "CTRL+Z")) {} - if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item + if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item ImGui::Separator(); if (ImGui::MenuItem("Cut", "CTRL+X")) {} if (ImGui::MenuItem("Copy", "CTRL+C")) {} diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2b95c0dd5..6676a96d5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4804,14 +4804,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = is_osx && io.KeyCtrl && !io.KeySuper && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) + // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: former would be handled by InputText) // Otherwise we could simply assume that we own the keys as we are active. const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat; const bool is_cut = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_X, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, f_repeat, id)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); const bool is_copy = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_C, 0, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, 0, id)) && !is_password && (!is_multiline || state->HasSelection()); const bool is_paste = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_V, f_repeat, id) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, f_repeat, id)) && !is_readonly; const bool is_undo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Z, f_repeat, id)) && !is_readonly && is_undoable; - const bool is_redo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Y, f_repeat, id) || (is_osx && Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z, f_repeat, id))) && !is_readonly && is_undoable; + const bool is_redo = (Shortcut(ImGuiMod_Ctrl | ImGuiKey_Y, f_repeat, id) || Shortcut(ImGuiMod_Ctrl | ImGuiMod_Shift | ImGuiKey_Z, f_repeat, id)) && !is_readonly && is_undoable; const bool is_select_all = Shortcut(ImGuiMod_Ctrl | ImGuiKey_A, 0, id); // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. From 3d900edba7c47bf957a7c7bfcf9773ecf923fa53 Mon Sep 17 00:00:00 2001 From: PuPuHX <654524200@qq.com> Date: Tue, 11 Feb 2025 10:57:47 +0800 Subject: [PATCH 12/18] Examples: Win32+DirectX12: Fixed ExampleDescriptorHeapAllocator overflow free index. Amend 40b2286d1. --- examples/example_win32_directx12/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example_win32_directx12/main.cpp b/examples/example_win32_directx12/main.cpp index 5b1a7af37..e83ce7dcb 100644 --- a/examples/example_win32_directx12/main.cpp +++ b/examples/example_win32_directx12/main.cpp @@ -54,7 +54,7 @@ struct ExampleDescriptorHeapAllocator HeapHandleIncrement = device->GetDescriptorHandleIncrementSize(HeapType); FreeIndices.reserve((int)desc.NumDescriptors); for (int n = desc.NumDescriptors; n > 0; n--) - FreeIndices.push_back(n); + FreeIndices.push_back(n - 1); } void Destroy() { From ef7ffaff7425ceabb2145ff4cf1df3cdadd252c9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 15:46:17 +0100 Subject: [PATCH 13/18] Styles, Tabs: (Breaking) Renamed TabMinWidthForCloseButton to TabCloseButtonMinWidthUnselected. Added TabCloseButtonMinWidthSelected. (#8387) --- docs/CHANGELOG.txt | 8 ++++++++ imgui.cpp | 6 ++++-- imgui.h | 8 +++++++- imgui_demo.cpp | 12 ++++++++---- imgui_widgets.cpp | 10 +++++++--- 5 files changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index cdb5e3845..7036ba64d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -42,6 +42,7 @@ HOW TO UPDATE? Breaking changes: - Renamed ImFontConfig::GlyphExtraSpacing.x option to GlyphExtraAdvanceX. (#242) +- Renamed style.TabMinWidthForCloseButton to style.TabCloseButtonMinWidthUnselected. Other changes: @@ -63,6 +64,13 @@ Other changes: to not leak the value into a subsequent window. (#8196) - Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) +- Styles, Tabs: made the Close Button of selected tabs always visible by default, + without requiring to hover the tab. (#8387) + - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings + to configure visibility of the Close Button for selected and unselected tabs. + (-1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width) + - Default for selected tabs: TabCloseButtonMinWidthSelected = -1.0f (always visible) + - Default for unselected tabs: TabCloseButtonMinWidthUnselected = 0.0f (visible when hovered) - TextLinkOpenURL(): fixed default Win32 io.PlatformOpenInShellFn handler to handle UTF-8 regardless of system regional settings. (#7660) [@achabense] - Demo: Combos: demonstrate a very simple way to add a filter to a combo, diff --git a/imgui.cpp b/imgui.cpp index af4aa2068..d6b763631 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1339,7 +1339,8 @@ ImGuiStyle::ImGuiStyle() LogSliderDeadzone = 4.0f; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. TabBorderSize = 0.0f; // Thickness of border around tabs. - TabMinWidthForCloseButton = 0.0f; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. + TabCloseButtonMinWidthSelected = -1.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. + TabCloseButtonMinWidthUnselected = 0.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected. TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. TabBarOverlineSize = 1.0f; // Thickness of tab-bar overline, which highlights the selected tab-bar. TableAngledHeadersAngle = 35.0f * (IM_PI / 180.0f); // Angle of angled headers (supported values range from -50 degrees to +50 degrees). @@ -1394,7 +1395,8 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); - TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImTrunc(TabMinWidthForCloseButton * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : FLT_MAX; TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); diff --git a/imgui.h b/imgui.h index 86137e5e1..6174b8a89 100644 --- a/imgui.h +++ b/imgui.h @@ -2170,7 +2170,8 @@ struct ImGuiStyle float LogSliderDeadzone; // The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero. float TabRounding; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs. float TabBorderSize; // Thickness of border around tabs. - float TabMinWidthForCloseButton; // Minimum width for close button to appear on an unselected tab when hovered. Set to 0.0f to always show when hovering, set to FLT_MAX to never show close button unless selected. + float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. + float TabCloseButtonMinWidthUnselected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected. float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus. float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar. float TableAngledHeadersAngle; // Angle of angled headers (supported values range from -50.0f degrees to +50.0f degrees). @@ -2201,6 +2202,11 @@ struct ImGuiStyle IMGUI_API ImGuiStyle(); IMGUI_API void ScaleAllSizes(float scale_factor); + + // Obsolete names +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + // TabMinWidthForCloseButton = TabCloseButtonMinWidthUnselected // Renamed in 1.91.9. +#endif }; //----------------------------------------------------------------------------- diff --git a/imgui_demo.cpp b/imgui_demo.cpp index db9a6de1a..7671b7764 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7991,10 +7991,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f"); ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); - ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); - ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 3.0f, "%.0f"); - ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); ImGui::SeparatorText("Rounding"); ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f"); @@ -8003,6 +7999,14 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f"); ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f"); + + ImGui::SeparatorText("Tabs"); + ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f"); + ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f"); + ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 3.0f, "%.0f"); + ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set."); + ImGui::DragFloat("TabCloseButtonMinWidthSelected", &style.TabCloseButtonMinWidthSelected, 0.1f, -1.0f, 100.0f, (style.TabCloseButtonMinWidthSelected < 0.0f) ? "%.0f (Always)" : "%.0f"); + ImGui::DragFloat("TabCloseButtonMinWidthUnselected", &style.TabCloseButtonMinWidthUnselected, 0.1f, -1.0f, 100.0f, (style.TabCloseButtonMinWidthUnselected < 0.0f) ? "%.0f (Always)" : "%.0f"); ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f"); ImGui::SeparatorText("Tables"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 6676a96d5..1b56d5944 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -10369,9 +10369,13 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, bool close_button_pressed = false; bool close_button_visible = false; if (close_button_id != 0) - if (is_contents_visible || bb.GetWidth() >= ImMax(button_sz, g.Style.TabMinWidthForCloseButton)) - if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) - close_button_visible = true; + { + bool is_hovered = g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id; // Any interaction account for this too. + if (is_contents_visible) + close_button_visible = (g.Style.TabCloseButtonMinWidthSelected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthSelected)); + else + close_button_visible = (g.Style.TabCloseButtonMinWidthUnselected < 0.0f) ? true : (is_hovered && bb.GetWidth() >= ImMax(button_sz, g.Style.TabCloseButtonMinWidthUnselected)); + } bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x); if (close_button_visible) From 7221f5e739c78e8367ac368f120248b2fed93b19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:01:02 +0100 Subject: [PATCH 14/18] Styles, Tabs: Fixed ef7ffaf. (#8387) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d6b763631..a69ae6c03 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1395,8 +1395,8 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabRounding = ImTrunc(GrabRounding * scale_factor); LogSliderDeadzone = ImTrunc(LogSliderDeadzone * scale_factor); TabRounding = ImTrunc(TabRounding * scale_factor); - TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : FLT_MAX; - TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : FLT_MAX; + TabCloseButtonMinWidthSelected = (TabCloseButtonMinWidthSelected > 0.0f && TabCloseButtonMinWidthSelected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthSelected * scale_factor) : TabCloseButtonMinWidthSelected; + TabCloseButtonMinWidthUnselected = (TabCloseButtonMinWidthUnselected > 0.0f && TabCloseButtonMinWidthUnselected != FLT_MAX) ? ImTrunc(TabCloseButtonMinWidthUnselected * scale_factor) : TabCloseButtonMinWidthUnselected; TabBarOverlineSize = ImTrunc(TabBarOverlineSize * scale_factor); SeparatorTextPadding = ImTrunc(SeparatorTextPadding * scale_factor); DisplayWindowPadding = ImTrunc(DisplayWindowPadding * scale_factor); From 7cd31c3557caadcf095fcf6da513b1a763ac77dc Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:08:52 +0100 Subject: [PATCH 15/18] Tables: tamed some .ini settings optimizations to more accurately allow overwriting/hot-reloading settings. (#7934) --- docs/CHANGELOG.txt | 2 ++ imgui_tables.cpp | 23 +++++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7036ba64d..d897ace83 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other changes: to not leak the value into a subsequent window. (#8196) - Tables: fixed an issue where Columns Visible/Hidden state wouldn't be correctly overridden when hot-reloading .ini state. (#7934) +- Tables: tamed some .ini settings optimizations to more accurately allow + overwriting/hot-reloading settings in more situations. (#7934) - Styles, Tabs: made the Close Button of selected tabs always visible by default, without requiring to hover the tab. (#8387) - Added style.TabCloseButtonMinWidthSelected/TabCloseButtonMinWidthUnselected settings diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 3a023d426..b7726e908 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -577,6 +577,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG // Initialize table->SettingsOffset = -1; table->IsSortSpecsDirty = true; + table->IsSettingsDirty = true; // Records itself into .ini file even when in default state (#7934) table->InstanceInteracted = -1; table->ContextPopupColumn = -1; table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1; @@ -3718,6 +3719,19 @@ void ImGui::TableLoadSettings(ImGuiTable* table) table->SettingsLoadedFlags = settings->SaveFlags; table->RefScale = settings->RefScale; + // Initialize default columns settings + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + { + ImGuiTableColumn* column = &table->Columns[column_n]; + column->StretchWeight = -1.0f; + column->WidthRequest = -1.0f; + column->AutoFitQueue = 0x00; + column->DisplayOrder = (ImGuiTableColumnIdx)column_n; + column->IsUserEnabled = column->IsUserEnabledNextFrame = (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1; + column->SortOrder = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? 0 : -1; + column->SortDirection = (column->Flags & ImGuiTableColumnFlags_DefaultSort) ? (ImS8)ImGuiSortDirection_None : (column->Flags & ImGuiTableColumnFlags_PreferSortDescending) ? (ImS8)ImGuiSortDirection_Descending : (ImU8)(ImGuiSortDirection_Ascending); + } + // Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings(); ImU64 display_order_mask = 0; @@ -3734,14 +3748,12 @@ void ImGui::TableLoadSettings(ImGuiTable* table) column->StretchWeight = column_settings->WidthOrWeight; else column->WidthRequest = column_settings->WidthOrWeight; - column->AutoFitQueue = 0x00; } if (settings->SaveFlags & ImGuiTableFlags_Reorderable) column->DisplayOrder = column_settings->DisplayOrder; - else - column->DisplayOrder = (ImGuiTableColumnIdx)column_n; display_order_mask |= (ImU64)1 << column->DisplayOrder; - column->IsUserEnabled = column->IsUserEnabledNextFrame = (column_settings->IsEnabled != -1 ? column_settings->IsEnabled == 1 : (column->Flags & ImGuiTableColumnFlags_DefaultHide) ? 0 : 1); + if ((settings->SaveFlags & ImGuiTableFlags_Hideable) && column_settings->IsEnabled != -1) + column->IsUserEnabled = column->IsUserEnabledNextFrame = column_settings->IsEnabled == 1; column->SortOrder = column_settings->SortOrder; column->SortDirection = column_settings->SortDirection; } @@ -3837,8 +3849,7 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle const bool save_visible = (settings->SaveFlags & ImGuiTableFlags_Hideable) != 0; const bool save_order = (settings->SaveFlags & ImGuiTableFlags_Reorderable) != 0; const bool save_sort = (settings->SaveFlags & ImGuiTableFlags_Sortable) != 0; - if (!save_size && !save_visible && !save_order && !save_sort) - continue; + // We need to save the [Table] entry even if all the bools are false, since this records a table with "default settings". buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount); From a931fb7f51269edda025180710fbd7a286e09688 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 12 Feb 2025 19:15:00 +0100 Subject: [PATCH 16/18] Fixed static analyzer warning. (was harmless as initialized in NewFrame) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index a69ae6c03..251e46819 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3906,6 +3906,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) InputEventsNextEventId = 1; WindowsActiveCount = 0; + WindowsBorderHoverPadding = 0.0f; CurrentWindow = NULL; HoveredWindow = NULL; HoveredWindowUnderMovingWindow = NULL; From 95c41117833039b44060973c33d2fc61f13ea284 Mon Sep 17 00:00:00 2001 From: Gabriel Rodriguez Date: Wed, 12 Feb 2025 12:39:44 +0100 Subject: [PATCH 17/18] Viewports: default to first monitor is viewport is outside bounds. (#8393, #8385) Before the assert was introduced in d66f4e589 the viewport would be eventually clamped with ClampWindowPos using g.FallbackMonitor, but code would run temporarly with DpiScale=0. --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7a37d8bbe..d89f16783 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -83,6 +83,11 @@ Other changes: - Backends: WebGPU: Fix for DAWN API rename WGPUProgrammableStageDescriptor -> WGPUComputeState. [@PhantomCloak] (#8369) +Docking+Viewports Branch: + +- Viewports: fixed an assert when a window load settings with a position outside + monitor bounds, when there are multiple monitors. (#8393, #8385) [@gaborodriguez] + ----------------------------------------------------------------------- VERSION 1.91.8 (Released 2025-01-31) diff --git a/imgui.cpp b/imgui.cpp index e222c3205..7050db209 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16536,13 +16536,14 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect) ImGuiContext& g = *GImGui; const int monitor_count = g.PlatformIO.Monitors.Size; + IM_ASSERT(monitor_count > 0); if (monitor_count <= 1) - return monitor_count - 1; + return 0; // Use a minimum threshold of 1.0f so a zero-sized rect won't false positive, and will still find the correct monitor given its position. // This is necessary for tooltips which always resize down to zero at first. const float surface_threshold = ImMax(rect.GetWidth() * rect.GetHeight() * 0.5f, 1.0f); - int best_monitor_n = -1; + int best_monitor_n = 0; // Default to the first monitor as fallback float best_monitor_surface = 0.001f; for (int monitor_n = 0; monitor_n < g.PlatformIO.Monitors.Size && best_monitor_surface < surface_threshold; monitor_n++) From a4ebe3d57637fa513ee44a153d083b04ccaebb7a Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 14 Feb 2025 12:04:05 +0100 Subject: [PATCH 18/18] Viewports: Fixed assertion when multi-viewports disabled and no monitor submitted. Reworked 95c4111. (#8401, #8393, #8385) --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7050db209..a3d7973d7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -16117,6 +16117,8 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const // This is so we can select an appropriate font size on the first frame of our window lifetime if (viewport->PlatformMonitor != -1) viewport->DpiScale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale; + else + viewport->DpiScale = 1.0f; } viewport->Window = window; @@ -16536,9 +16538,8 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect) ImGuiContext& g = *GImGui; const int monitor_count = g.PlatformIO.Monitors.Size; - IM_ASSERT(monitor_count > 0); if (monitor_count <= 1) - return 0; + return monitor_count - 1; // Use a minimum threshold of 1.0f so a zero-sized rect won't false positive, and will still find the correct monitor given its position. // This is necessary for tooltips which always resize down to zero at first.