|
@@ -3337,13 +3337,13 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged)
|
|
|
+bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
if (!bb.Overlaps(window->ClipRect))
|
|
|
if (id == 0 || (id != g.ActiveId && id != g.NavId))
|
|
|
- if (clip_even_when_logged || !g.LogEnabled)
|
|
|
+ if (!g.LogEnabled)
|
|
|
return true;
|
|
|
return false;
|
|
|
}
|
|
@@ -4219,6 +4219,10 @@ void ImGui::NewFrame()
|
|
|
g.DragDropWithinTarget = false;
|
|
|
g.DragDropHoldJustPressedId = 0;
|
|
|
|
|
|
+ // Close popups on focus lost (currently wip/opt-in)
|
|
|
+ //if (g.IO.AppFocusLost)
|
|
|
+ // ClosePopupsExceptModals();
|
|
|
+
|
|
|
// Clear buttons state when focus is lost
|
|
|
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle)
|
|
|
if (g.IO.AppFocusLost)
|
|
@@ -5411,7 +5415,7 @@ void ImGui::EndChild()
|
|
|
ItemAdd(bb, window->ChildId);
|
|
|
RenderNavHighlight(bb, window->ChildId);
|
|
|
|
|
|
- // When browsing a window that has no activable items (scroll only) we keep a highlight on the child
|
|
|
+ // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying)
|
|
|
if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow)
|
|
|
RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin);
|
|
|
}
|
|
@@ -6261,12 +6265,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
// Add to stack
|
|
|
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
|
|
|
+ g.CurrentWindow = window;
|
|
|
ImGuiWindowStackData window_stack_data;
|
|
|
window_stack_data.Window = window;
|
|
|
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
|
|
|
+ window_stack_data.StackSizesOnBegin.SetToCurrentState();
|
|
|
g.CurrentWindowStack.push_back(window_stack_data);
|
|
|
- g.CurrentWindow = window;
|
|
|
- window->DC.StackSizesOnBegin.SetToCurrentState();
|
|
|
g.CurrentWindow = NULL;
|
|
|
|
|
|
if (flags & ImGuiWindowFlags_Popup)
|
|
@@ -7004,10 +7008,10 @@ void ImGui::End()
|
|
|
|
|
|
// Pop from window stack
|
|
|
g.LastItemData = g.CurrentWindowStack.back().ParentLastItemDataBackup;
|
|
|
- g.CurrentWindowStack.pop_back();
|
|
|
if (window->Flags & ImGuiWindowFlags_Popup)
|
|
|
g.BeginPopupStack.pop_back();
|
|
|
- window->DC.StackSizesOnBegin.CompareWithCurrentState();
|
|
|
+ g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithCurrentState();
|
|
|
+ g.CurrentWindowStack.pop_back();
|
|
|
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
|
|
|
if (g.CurrentWindow)
|
|
|
SetCurrentViewport(g.CurrentWindow, g.CurrentWindow->Viewport);
|
|
@@ -7215,11 +7219,14 @@ void ImGui::BeginDisabled(bool disabled)
|
|
|
if (was_disabled || disabled)
|
|
|
g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
|
|
|
g.ItemFlagsStack.push_back(g.CurrentItemFlags);
|
|
|
+ g.DisabledStackSize++;
|
|
|
}
|
|
|
|
|
|
void ImGui::EndDisabled()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
+ IM_ASSERT(g.DisabledStackSize > 0);
|
|
|
+ g.DisabledStackSize--;
|
|
|
bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
|
|
|
//PopItemFlag();
|
|
|
g.ItemFlagsStack.pop_back();
|
|
@@ -7317,7 +7324,6 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
|
|
IM_ASSERT(cur_window); // Not inside a Begin()/End()
|
|
|
const bool popup_hierarchy = (flags & ImGuiHoveredFlags_NoPopupHierarchy) == 0;
|
|
|
const bool dock_hierarchy = (flags & ImGuiHoveredFlags_DockHierarchy) != 0;
|
|
|
-
|
|
|
if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
|
|
|
|
|
@@ -7352,7 +7358,6 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
|
|
|
IM_ASSERT(cur_window); // Not inside a Begin()/End()
|
|
|
const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
|
|
|
const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
|
|
|
-
|
|
|
if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
|
|
|
|
|
@@ -7972,53 +7977,13 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
|
|
|
{
|
|
|
// PVS-Studio V1044 is "Loop break conditions do not depend on the number of iterations"
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
- while (g.CurrentWindowStack.Size > 0)
|
|
|
+ while (g.CurrentWindowStack.Size > 0) //-V1044
|
|
|
{
|
|
|
- while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
|
|
|
- EndTable();
|
|
|
- }
|
|
|
+ ErrorCheckEndWindowRecover(log_callback, user_data);
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
- IM_ASSERT(window != NULL);
|
|
|
- while (g.CurrentTabBar != NULL) //-V1044
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
|
|
|
- EndTabBar();
|
|
|
- }
|
|
|
- while (window->DC.TreeDepth > 0)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
|
|
|
- TreePop();
|
|
|
- }
|
|
|
- while (g.GroupStack.Size > window->DC.StackSizesOnBegin.SizeOfGroupStack)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
|
|
|
- EndGroup();
|
|
|
- }
|
|
|
- while (window->IDStack.Size > 1)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
|
|
|
- PopID();
|
|
|
- }
|
|
|
- while (g.ColorStack.Size > window->DC.StackSizesOnBegin.SizeOfColorStack)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col));
|
|
|
- PopStyleColor();
|
|
|
- }
|
|
|
- while (g.StyleVarStack.Size > window->DC.StackSizesOnBegin.SizeOfStyleVarStack)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
|
|
|
- PopStyleVar();
|
|
|
- }
|
|
|
- while (g.FocusScopeStack.Size > window->DC.StackSizesOnBegin.SizeOfFocusScopeStack)
|
|
|
- {
|
|
|
- if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
|
|
|
- PopFocusScope();
|
|
|
- }
|
|
|
if (g.CurrentWindowStack.Size == 1)
|
|
|
{
|
|
|
- IM_ASSERT(g.CurrentWindow->IsFallbackWindow);
|
|
|
+ IM_ASSERT(window->IsFallbackWindow);
|
|
|
break;
|
|
|
}
|
|
|
IM_ASSERT(window == g.CurrentWindow);
|
|
@@ -8035,6 +8000,66 @@ void ImGui::ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, voi
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// Must be called before End()/EndChild()
|
|
|
+void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ while (g.CurrentTable && (g.CurrentTable->OuterWindow == g.CurrentWindow || g.CurrentTable->InnerWindow == g.CurrentWindow))
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing EndTable() in '%s'", g.CurrentTable->OuterWindow->Name);
|
|
|
+ EndTable();
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGuiWindow* window = g.CurrentWindow;
|
|
|
+ ImGuiStackSizes* stack_sizes = &g.CurrentWindowStack.back().StackSizesOnBegin;
|
|
|
+ IM_ASSERT(window != NULL);
|
|
|
+ while (g.CurrentTabBar != NULL) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing EndTabBar() in '%s'", window->Name);
|
|
|
+ EndTabBar();
|
|
|
+ }
|
|
|
+ while (window->DC.TreeDepth > 0)
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing TreePop() in '%s'", window->Name);
|
|
|
+ TreePop();
|
|
|
+ }
|
|
|
+ while (g.GroupStack.Size > stack_sizes->SizeOfGroupStack) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing EndGroup() in '%s'", window->Name);
|
|
|
+ EndGroup();
|
|
|
+ }
|
|
|
+ while (window->IDStack.Size > 1)
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing PopID() in '%s'", window->Name);
|
|
|
+ PopID();
|
|
|
+ }
|
|
|
+ while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name);
|
|
|
+ EndDisabled();
|
|
|
+ }
|
|
|
+ while (g.ColorStack.Size > stack_sizes->SizeOfColorStack)
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing PopStyleColor() in '%s' for ImGuiCol_%s", window->Name, GetStyleColorName(g.ColorStack.back().Col));
|
|
|
+ PopStyleColor();
|
|
|
+ }
|
|
|
+ while (g.ItemFlagsStack.Size > stack_sizes->SizeOfItemFlagsStack) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing PopItemFlag() in '%s'", window->Name);
|
|
|
+ PopItemFlag();
|
|
|
+ }
|
|
|
+ while (g.StyleVarStack.Size > stack_sizes->SizeOfStyleVarStack) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
|
|
|
+ PopStyleVar();
|
|
|
+ }
|
|
|
+ while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack) //-V1044
|
|
|
+ {
|
|
|
+ if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
|
|
|
+ PopFocusScope();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// Save current stack sizes for later compare
|
|
|
void ImGuiStackSizes::SetToCurrentState()
|
|
|
{
|
|
@@ -8046,7 +8071,9 @@ void ImGuiStackSizes::SetToCurrentState()
|
|
|
SizeOfFontStack = (short)g.FontStack.Size;
|
|
|
SizeOfFocusScopeStack = (short)g.FocusScopeStack.Size;
|
|
|
SizeOfGroupStack = (short)g.GroupStack.Size;
|
|
|
+ SizeOfItemFlagsStack = (short)g.ItemFlagsStack.Size;
|
|
|
SizeOfBeginPopupStack = (short)g.BeginPopupStack.Size;
|
|
|
+ SizeOfDisabledStack = (short)g.DisabledStackSize;
|
|
|
}
|
|
|
|
|
|
// Compare to detect usage errors
|
|
@@ -8064,6 +8091,8 @@ void ImGuiStackSizes::CompareWithCurrentState()
|
|
|
// For color, style and font stacks there is an incentive to use Push/Begin/Pop/.../End patterns, so we relax our checks a little to allow them.
|
|
|
IM_ASSERT(SizeOfGroupStack == g.GroupStack.Size && "BeginGroup/EndGroup Mismatch!");
|
|
|
IM_ASSERT(SizeOfBeginPopupStack == g.BeginPopupStack.Size && "BeginPopup/EndPopup or BeginMenu/EndMenu Mismatch!");
|
|
|
+ IM_ASSERT(SizeOfDisabledStack == g.DisabledStackSize && "BeginDisabled/EndDisabled Mismatch!");
|
|
|
+ IM_ASSERT(SizeOfItemFlagsStack >= g.ItemFlagsStack.Size && "PushItemFlag/PopItemFlag Mismatch!");
|
|
|
IM_ASSERT(SizeOfColorStack >= g.ColorStack.Size && "PushStyleColor/PopStyleColor Mismatch!");
|
|
|
IM_ASSERT(SizeOfStyleVarStack >= g.StyleVarStack.Size && "PushStyleVar/PopStyleVar Mismatch!");
|
|
|
IM_ASSERT(SizeOfFontStack >= g.FontStack.Size && "PushFont/PopFont Mismatch!");
|
|
@@ -8195,7 +8224,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
|
|
|
#endif
|
|
|
|
|
|
// Clipping test
|
|
|
- const bool is_clipped = IsClippedEx(bb, id, false);
|
|
|
+ const bool is_clipped = IsClippedEx(bb, id);
|
|
|
if (is_clipped)
|
|
|
return false;
|
|
|
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
|
|
@@ -8985,6 +9014,21 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void ImGui::ClosePopupsExceptModals()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+
|
|
|
+ int popup_count_to_keep;
|
|
|
+ for (popup_count_to_keep = g.OpenPopupStack.Size; popup_count_to_keep > 0; popup_count_to_keep--)
|
|
|
+ {
|
|
|
+ ImGuiWindow* window = g.OpenPopupStack[popup_count_to_keep - 1].Window;
|
|
|
+ if (!window || window->Flags & ImGuiWindowFlags_Modal)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
|
|
|
+ ClosePopupToLevel(popup_count_to_keep, true);
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|