From 40f3f3a2b524d06e710b724fa0f8c78062f2fd4f Mon Sep 17 00:00:00 2001 From: Timo Suoranta Date: Thu, 5 Nov 2026 18:05:33 +0200 Subject: [PATCH] ColorButton, ColorPicker: fixed swatch drawn with a wrong (often zero) alpha inside BeginDisabled(false). (#9511) Since 19ead810d (#9511), ColorButton() and ColorPicker4() cancel out the dimming of an enclosing BeginDisabled() by restoring the alpha it saved: if (g.DisabledStackSize > 0) g.Style.Alpha = g.DisabledAlphaBackup; DisabledStackSize > 0 means "inside some BeginDisabled() call", not "items are disabled". BeginDisabled(false) increments DisabledStackSize but does not write DisabledAlphaBackup, which is only written when a BeginDisabled() call actually starts disabling. Inside BeginDisabled(false) the swatch therefore picks up whatever value DisabledAlphaBackup holds from elsewhere: - 0.0f, its initial value, when no BeginDisabled(true) has run in the context yet: the swatch is fully transparent and only its border shows. - The style alpha of the last BeginDisabled(true) anywhere in the context (another window, an earlier frame): the swatch looks correct when that was 1.0f, and is drawn with an unrelated alpha when it ran under a pushed ImGuiStyleVar_Alpha. So a swatch's appearance depends on whether, and under which alpha, some unrelated widget was disabled earlier. Typical trigger is the BeginDisabled(condition) idiom with the condition false, e.g.: ImGui::BeginDisabled(is_read_only); // false ImGui::ColorEdit3("##color", col, ImGuiColorEditFlags_NoInputs); ImGui::EndDisabled(); In a fresh context this draws an empty swatch frame; it starts showing the color only after any other window draws a disabled item. Fix: cancel out the dimming only while the Disabled item flag is set, i.e. while an enclosing BeginDisabled(true) is in effect. DisabledAlphaBackup then always holds the alpha that call saved, and inside BeginDisabled(false) the swatch draws with the current style alpha, as any other widget does. Co-Authored-By: Claude Opus 5.5 --- imgui_widgets.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 62bff5880..9a8e1d6d6 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6217,7 +6217,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl g.NextItemData.ClearFlags(); const float backup_alpha = g.Style.Alpha; - if (g.DisabledStackSize > 0) + const bool cancel_disabled_alpha = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; // BeginDisabled(false) leaves DisabledAlphaBackup unset + if (cancel_disabled_alpha) g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches. PushID(label); @@ -6579,7 +6580,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl g.ColorEditCurrentID = 0; PopID(); - if (g.DisabledStackSize > 0) + if (cancel_disabled_alpha) g.Style.Alpha = backup_alpha; return value_changed; @@ -6620,7 +6621,8 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl const bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0; const float backup_alpha = g.Style.Alpha; - if (g.DisabledStackSize > 0) + const bool cancel_disabled_alpha = (g.CurrentItemFlags & ImGuiItemFlags_Disabled) != 0; // BeginDisabled(false) leaves DisabledAlphaBackup unset + if (cancel_disabled_alpha) g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches. if (is_mixed) { @@ -6648,7 +6650,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(col_source), rounding); } - if (g.DisabledStackSize > 0) + if (cancel_disabled_alpha) g.Style.Alpha = backup_alpha; RenderNavCursor(bb, id); if ((flags & ImGuiColorEditFlags_NoBorder) == 0)