From af34aba577d84c5e2dac9b5209c740541fc46f62 Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Wed, 5 Jun 2024 16:58:12 +0200 Subject: [PATCH] ImGui: Apply patch from upstream that fixes tooltips of disabled buttons Upstream commit: "Disabled: nested tooltips or other non-child window within a BeginDisabled() block disable the disabled state. (#211, #7640)" Should be in the next Dear ImGui release --- neo/libs/imgui/imgui.cpp | 40 +++++++++++++++++++++++++++++++-- neo/libs/imgui/imgui_internal.h | 3 +++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/neo/libs/imgui/imgui.cpp b/neo/libs/imgui/imgui.cpp index d0c509ca..ab22dc52 100644 --- a/neo/libs/imgui/imgui.cpp +++ b/neo/libs/imgui/imgui.cpp @@ -6648,6 +6648,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // [EXPERIMENTAL] Skip Refresh mode UpdateWindowSkipRefresh(window); + // Nested root windows (typically tooltips) override disabled state + if (window->RootWindow == window) + if ((window->DC.BackupItemDisabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0)) + BeginDisabledOverrideReenable(); + // We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow() g.CurrentWindow = NULL; @@ -7257,6 +7262,8 @@ void ImGui::End() if (!window->SkipRefresh) PopClipRect(); // Inner window clip rectangle PopFocusScope(); + if (window->RootWindow == window && window->DC.BackupItemDisabled) + EndDisabledOverrideReenable(); if (window->SkipRefresh) { @@ -7521,7 +7528,7 @@ void ImGui::BeginDisabled(bool disabled) } if (was_disabled || disabled) g.CurrentItemFlags |= ImGuiItemFlags_Disabled; - g.ItemFlagsStack.push_back(g.CurrentItemFlags); + g.ItemFlagsStack.push_back(g.CurrentItemFlags); // FIXME-OPT: can we simply skip this and use DisabledStackSize? g.DisabledStackSize++; } @@ -7538,6 +7545,29 @@ void ImGui::EndDisabled() g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar(); } +// Could have been called BeginDisabledDisable() but it didn't want to be award nominated for most awkward function name. +// Ideally we would use a shared e.g. BeginDisabled()->BeginDisabledEx() but earlier needs to be optimal. +// The whole code for this is awkward, will reevaluate if we find a way to implement SetNextItemDisabled(). +void ImGui::BeginDisabledOverrideReenable() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.CurrentItemFlags & ImGuiItemFlags_Disabled); + g.Style.Alpha = g.DisabledAlphaBackup; + g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled; + g.ItemFlagsStack.push_back(g.CurrentItemFlags); + g.DisabledStackSize++; +} + +void ImGui::EndDisabledOverrideReenable() +{ + ImGuiContext& g = *GImGui; + g.DisabledStackSize--; + IM_ASSERT(g.DisabledStackSize > 0); + g.ItemFlagsStack.pop_back(); + g.CurrentItemFlags = g.ItemFlagsStack.back(); + g.Style.Alpha = g.DisabledAlphaBackup * g.Style.DisabledAlpha; +} + void ImGui::PushTabStop(bool tab_stop) { PushItemFlag(ImGuiItemFlags_NoTabStop, !tab_stop); @@ -9993,7 +10023,13 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo while (g.DisabledStackSize > stack_sizes->SizeOfDisabledStack) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing EndDisabled() in '%s'", window->Name); - EndDisabled(); + if (g.CurrentItemFlags & ImGuiItemFlags_Disabled) + EndDisabled(); + else + { + EndDisabledOverrideReenable(); + window->DC.BackupItemDisabled = false; + } } while (g.ColorStack.Size > stack_sizes->SizeOfColorStack) { diff --git a/neo/libs/imgui/imgui_internal.h b/neo/libs/imgui/imgui_internal.h index f2ac5ad0..9d8d03eb 100644 --- a/neo/libs/imgui/imgui_internal.h +++ b/neo/libs/imgui/imgui_internal.h @@ -2468,6 +2468,7 @@ struct IMGUI_API ImGuiWindowTempData bool NavWindowHasScrollY; // Set per window when scrolling can be used (== ScrollMax.y > 0.0f) // Miscellaneous + bool BackupItemDisabled; // Non-child window override disabled flag bool MenuBarAppending; // FIXME: Remove this ImVec2 MenuBarOffset; // MenuBarOffset.x is sort of equivalent of a per-layer CursorPos.x, saved/restored as we switch to the menu bar. The only situation when MenuBarOffset.y is > 0 if when (SafeAreaPadding.y > FramePadding.y), often used on TVs. ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items measurement @@ -3124,6 +3125,8 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx); + IMGUI_API void BeginDisabledOverrideReenable(); + IMGUI_API void EndDisabledOverrideReenable(); // Logging/Capture IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.