From 3b041f20c1b6ab24f4fe06cacac5f6ca392292b7 Mon Sep 17 00:00:00 2001 From: DanS Date: Tue, 21 Jul 2026 18:04:15 -0500 Subject: [PATCH] fix(settings): hold the right column with Indent, not a one-shot cursor set The two-column NODE & SECURITY card collapsed both columns onto the left, overlapping. A one-time SetCursorScreenPos() can't hold a column: ImGui resets the cursor X to the window's left indent on every line-advance, so the first widget in the right column (a Dummy spacer) bounced everything after it back to the left margin. Shift the whole right column with ImGui::Indent(colW+gap) instead, so each line-start lands at the column X; set the first widget's X explicitly to match, and Unindent before continuing the page. Left column already renders at the shadowed half-width, so it stays in its lane. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ui/pages/settings_page.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ui/pages/settings_page.cpp b/src/ui/pages/settings_page.cpp index fd71105..de6aa89 100644 --- a/src/ui/pages/settings_page.cpp +++ b/src/ui/pages/settings_page.cpp @@ -1993,6 +1993,11 @@ void RenderSettingsPage(App* app) { const bool nsTwoCol = nsHasDaemon && contentW > 760.0f * Layout::dpiScale(); const float nsColW = nsTwoCol ? (contentW - nsColGap) * 0.5f : contentW; const ImVec2 nsColTop = ImGui::GetCursorScreenPos(); + // Window-local anchor for the right column. We shift it with Indent() (not a one-shot + // SetCursorScreenPos): ImGui resets the cursor X to the window's left indent on every + // line-advance, so only an indent holds a column across multiple rows/widgets. + const float nsColTopLocalX = ImGui::GetCursorPosX(); + const float nsColTopLocalY = ImGui::GetCursorPosY(); { // ---- left column (Node / RPC / Security) ---- const float contentW = nsColW; const ImVec2 sectionOrigin(nsColTop.x, nsColTop.y); @@ -2159,11 +2164,16 @@ void RenderSettingsPage(App* app) { renderSecuritySection(sectionOrigin.x, contentW, /*includeRpcEncrypt=*/true); } // ---- end left column ---- const float nsLeftBottom = ImGui::GetCursorScreenPos().y; - if (nsTwoCol) ImGui::SetCursorScreenPos(ImVec2(nsColTop.x + nsColW + nsColGap, nsColTop.y)); + if (nsTwoCol) { + // Reset to the top, then indent so every line in the right column starts at the + // column X (the indent persists across line-advances; the explicit SetCursorPosX + // places the very first widget on the same line). + ImGui::SetCursorPosY(nsColTopLocalY); + ImGui::Indent(nsColW + nsColGap); + ImGui::SetCursorPosX(nsColTopLocalX + nsColW + nsColGap); + } { // ---- right column (Daemon binary) ---- const float contentW = nsColW; - const ImVec2 sectionOrigin(nsTwoCol ? nsColTop.x + nsColW + nsColGap : nsColTop.x, - nsTwoCol ? nsColTop.y : ImGui::GetCursorScreenPos().y); // -------------------- DAEMON BINARY -------------------- if (app->supportsFullNodeLifecycleActions()) { @@ -2315,6 +2325,7 @@ void RenderSettingsPage(App* app) { } } // ---- end right column ---- const float nsRightBottom = ImGui::GetCursorScreenPos().y; + if (nsTwoCol) ImGui::Unindent(nsColW + nsColGap); // restore indent before the rest of the page ImGui::SetCursorScreenPos(ImVec2(nsColTop.x, nsTwoCol ? std::max(nsLeftBottom, nsRightBottom) : nsRightBottom)); ImGui::PopFont();