Skip to content

Stacked calls on BeginDisabled/EndDisabled lead to broken states #4462

@Legulysse

Description

@Legulysse

Version/Branch of Dear ImGui:

Version: 1.84.1
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: sfml + custom engine integration
Compiler: visual 2019
Operating System: Win7

My Issue/Question:

After testing some cases of stacked calls to Begin/EndDisabled with various combinations of boolean values, I stumbled upon 2 bugs :

  • Bug 1 : A call to BeginDisabled inside another disabled block will hide everything related to imgui, without any recovery possible (I reported the issue with more details as comments in this issue EndDisabled() after BeginDisabled(false) sets global alpha to 0 #4452 , but I'm not sure how I can re-open an issue).
  • Bug 2 : Any call to EndDisabled stacked inside another block will kill the "disabled" state, instead of keeping the "disabled" state until we exit the top-most block.

Standalone, minimal, complete and verifiable example:

        static bool a = true;
        static bool b = false;
        static bool c = false;

        ImGui::Checkbox("TestDisabled A", &a);
        ImGui::BeginDisabled(a);
        ImGui::Text("block A");

        ImGui::Checkbox("TestDisabled B", &b);
        ImGui::BeginDisabled(b);
        ImGui::Text("block B");
        ImGui::EndDisabled();

        ImGui::Checkbox("TestDisabled C", &c);
        ImGui::BeginDisabled(c);
        ImGui::Text("block C");
        ImGui::EndDisabled();

        ImGui::Text("block A");

        ImGui::EndDisabled();

Fix proposal:

void ImGui::BeginDisabled(bool disabled)
{
    ImGuiContext& g = *GImGui;
    bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
    if (!was_disabled && disabled)
    {
        g.DisabledAlphaBackup = g.Style.Alpha;    // FIX 1 : move this line here instead of outside the if block
        g.Style.Alpha *= g.Style.DisabledAlpha; // PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * g.Style.DisabledAlpha);
    }
    if (was_disabled || disabled)
        g.CurrentItemFlags |= ImGuiItemFlags_Disabled;
    g.ItemFlagsStack.push_back(g.CurrentItemFlags);
}

void ImGui::EndDisabled()
{
    ImGuiContext& g = *GImGui;
    bool was_disabled = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0;
    //PopItemFlag();
    g.ItemFlagsStack.pop_back();
    g.CurrentItemFlags = g.ItemFlagsStack.back();   // FIX 2 : replace g.CurrentItemFlags &= ~ImGuiItemFlags_Disabled;
    if (was_disabled && (g.CurrentItemFlags & ImGuiItemFlags_Disabled) == 0)
        g.Style.Alpha = g.DisabledAlphaBackup; //PopStyleVar();
}

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions