fix(dialogs): let Combo dropdowns / popups work inside overlay dialogs

BeginOverlayDialog called ImGui::SetNextWindowFocus() every frame to keep the
dialog on top. That forced the scrim back to the front each frame and closed
any popup opened from inside the dialog — so the portfolio editor's price-basis
Combo and the custom color-picker popup flashed open then vanished, and clicking
a dropdown item that overhung the card could trip the outside-click-dismiss and
close the whole dialog.

Make the overlay popup-aware: compute overlayPopupOpen (IsPopupOpen with
AnyPopupId|AnyPopupLevel) and (1) skip SetNextWindowFocus while a popup is
showing so it stays focused/on-top, and (2) skip the outside-click-dismiss while
a popup is open so clicks inside it don't close the dialog. No change when no
popup is open, so existing dialogs are unaffected.

Full-node + Lite build clean; ctest 1/1; hygiene clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 01:02:18 -05:00
parent 301b3df77e
commit b0ded528b1

View File

@@ -1026,7 +1026,12 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
// Fullscreen scrim overlay
ImGui::SetNextWindowPos(vp_pos);
ImGui::SetNextWindowSize(vp_size);
ImGui::SetNextWindowFocus();
// Focus the scrim so the dialog owns input — but NOT while a popup (a Combo dropdown,
// color picker, etc.) opened from the dialog is showing, or forcing focus back to the
// scrim every frame would immediately close that popup.
const bool overlayPopupOpen =
ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel);
if (!overlayPopupOpen) ImGui::SetNextWindowFocus();
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.04f, 0.04f, 0.06f, scrimOpacity));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
@@ -1094,8 +1099,11 @@ inline bool BeginOverlayDialog(const char* title, bool* p_open, float cardWidth
// Click outside the card dismisses the dialog — but NOT on the frame it first appears, otherwise
// the very click that opened it (a button fired the same frame) is read as an outside-click and
// the dialog flashes open then instantly closes.
if (p_open && !ImGui::IsWindowAppearing() && ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
// the dialog flashes open then instantly closes. Also skip while a popup opened from the dialog
// is showing: a click inside a Combo dropdown / color picker that overhangs the card would
// otherwise be read as an outside-click and close the whole dialog.
if (p_open && !overlayPopupOpen && !ImGui::IsWindowAppearing() &&
ImGui::IsMouseClicked(ImGuiMouseButton_Left) &&
!ImGui::IsMouseHoveringRect(cardMin, cardMax, false)) {
*p_open = false;
}