From 1493ce08e56554927186b838a17e6ea73bf2103a Mon Sep 17 00:00:00 2001 From: BlackMark Date: Sun, 21 Jun 2026 10:41:58 +0200 Subject: [PATCH] Rebalance overlay layout and fix the layout-on-launch overlap Feedback from real use: the center column was far too wide and Injection/Log too narrow; Audio was too tall while Controllers/Video were too short; and the layout overlapped on launch until "Reset layout" was pressed. - Columns are now proportional: Injection (left) and Log (right) take 36% each of the usable width, the center control column 28% -- so the wide panels are wide and the control panels narrow. - The center stack heights are evened out (Controllers 30% / Video 38% / Audio 32% of the column), so Audio no longer hogs it. - The default layout is now forced (ImGuiCond_Always) for the first few frames after launch, because the viewport WorkSize isn't trustworthy on frame 0 -- FirstUseEver was locking in those wrong (overlapping) positions until a manual Reset layout. Co-Authored-By: Claude Opus 4.8 --- host/src/ui/app_chrome.cpp | 49 +++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/host/src/ui/app_chrome.cpp b/host/src/ui/app_chrome.cpp index 5ba26df..5f8452a 100644 --- a/host/src/ui/app_chrome.cpp +++ b/host/src/ui/app_chrome.cpp @@ -13,6 +13,10 @@ namespace // Set by "View -> Reset layout"; true for the one frame in which panels re-apply // their default position/size, then cleared by apply_layout_end_frame(). bool g_layout_reset = false; +// Force the computed layout for the first few frames after launch: the viewport +// WorkSize isn't trustworthy on frame 0, and FirstUseEver would otherwise lock in +// those wrong positions (overlapping) until the user pressed Reset layout. +int g_startup_force = 4; } // namespace void request_layout_reset() @@ -23,6 +27,10 @@ void request_layout_reset() void apply_layout_end_frame() { g_layout_reset = false; + if (g_startup_force > 0) + { + --g_startup_force; + } } void apply_panel_layout(Panel panel) @@ -33,43 +41,52 @@ void apply_panel_layout(Panel panel) const float m = 12.0f; // outer margin const float gap = 10.0f; // between panels - const float left_w = 440.0f; // Injection (window list + hook diagnostics) - const float right_w = 380.0f; // Log - const float center_x = o.x + m + left_w + gap; - const float right_x = o.x + s.x - right_w - m; - const float center_w = std::max(360.0f, right_x - gap - center_x); + // Three columns: Injection (left) and Log (right) are the wide ones (window list + // titles / log lines); the center control-panel column is the narrow one. + const float usable_w = std::max(600.0f, s.x - 2.0f * m - 2.0f * gap); + const float left_w = usable_w * 0.36f; + const float center_w = usable_w * 0.28f; + const float right_w = usable_w * 0.36f; + const float left_x = o.x + m; + const float center_x = left_x + left_w + gap; + const float right_x = center_x + center_w + gap; + + const float top = o.y + m; const float full_h = std::max(200.0f, s.y - 2.0f * m); - const float ctrl_h = 210.0f; // Controllers - const float vid_h = 250.0f; // Video mirror - const float audio_y = o.y + m + ctrl_h + gap + vid_h + gap; - const float bottom = o.y + m + full_h; + + // Center column stacks Controllers / Video / Audio at roughly even heights (Video + // a touch taller for its graphs), so Audio no longer hogs the column. + const float stack_avail = std::max(150.0f, full_h - 2.0f * gap); + const float ctrl_h = stack_avail * 0.30f; + const float vid_h = stack_avail * 0.38f; + const float audio_h = stack_avail * 0.32f; ImVec2 pos, size; switch (panel) { case Panel::Injection: - pos = ImVec2(o.x + m, o.y + m); + pos = ImVec2(left_x, top); size = ImVec2(left_w, full_h); break; case Panel::Controllers: - pos = ImVec2(center_x, o.y + m); + pos = ImVec2(center_x, top); size = ImVec2(center_w, ctrl_h); break; case Panel::Video: - pos = ImVec2(center_x, o.y + m + ctrl_h + gap); + pos = ImVec2(center_x, top + ctrl_h + gap); size = ImVec2(center_w, vid_h); break; case Panel::Audio: - pos = ImVec2(center_x, audio_y); - size = ImVec2(center_w, std::max(180.0f, bottom - audio_y)); + pos = ImVec2(center_x, top + ctrl_h + gap + vid_h + gap); + size = ImVec2(center_w, audio_h); break; case Panel::Log: - pos = ImVec2(right_x, o.y + m); + pos = ImVec2(right_x, top); size = ImVec2(right_w, full_h); break; } - const ImGuiCond cond = g_layout_reset ? ImGuiCond_Always : ImGuiCond_FirstUseEver; + const ImGuiCond cond = (g_layout_reset || g_startup_force > 0) ? ImGuiCond_Always : ImGuiCond_FirstUseEver; ImGui::SetNextWindowPos(pos, cond); ImGui::SetNextWindowSize(size, cond); }