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 <noreply@anthropic.com>
This commit is contained in:
Timo Suoranta 2026-11-05 18:05:33 +02:00
parent 253aa51aba
commit 40f3f3a2b5
No known key found for this signature in database

View File

@ -6217,7 +6217,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
g.NextItemData.ClearFlags(); g.NextItemData.ClearFlags();
const float backup_alpha = g.Style.Alpha; 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. g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
PushID(label); PushID(label);
@ -6579,7 +6580,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
g.ColorEditCurrentID = 0; g.ColorEditCurrentID = 0;
PopID(); PopID();
if (g.DisabledStackSize > 0) if (cancel_disabled_alpha)
g.Style.Alpha = backup_alpha; g.Style.Alpha = backup_alpha;
return value_changed; 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 bool is_mixed = (g.LastItemData.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
const float backup_alpha = g.Style.Alpha; 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. g.Style.Alpha = g.DisabledAlphaBackup; // Cancel out effect of BeginDisabled() for color swatches.
if (is_mixed) if (is_mixed)
{ {
@ -6648,7 +6650,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
else else
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(col_source), rounding); window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(col_source), rounding);
} }
if (g.DisabledStackSize > 0) if (cancel_disabled_alpha)
g.Style.Alpha = backup_alpha; g.Style.Alpha = backup_alpha;
RenderNavCursor(bb, id); RenderNavCursor(bb, id);
if ((flags & ImGuiColorEditFlags_NoBorder) == 0) if ((flags & ImGuiColorEditFlags_NoBorder) == 0)