fix(ui): wrap chat panel body in outer BeginChild so drag-trap covers it

The InvisibleButton drag-trap inside BeginChild only catches clicks
inside that specific child. Chat had widgets OUTSIDE the inner
##chattail child (the Copy-mode Checkbox + a Separator at top, the
footer Separator + InputTextSubmit at bottom) — empty space around
those widgets fell through directly to the parent window's
window-drag init.

Fix: wrap the entire chat panel body in a single outer ##chatbody
BeginChild before drawing any content. The renderer's drag-trap
fires inside this outer child too, absorbing every empty-space
click in the chat panel body. The inner ##chattail child is now
nested inside it, which doesn't change its scroll-tail semantics
but does mean it gets its own drag-trap as a bonus.

Test fixed: Render_BeginChild_ReservesNegativeFooterFromFrameHeight
was using Single(BeginChild) — there are now two BeginChild calls
(##chatbody outer + ##chattail inner). Switched to Single(... &&
Args[0] == "##chattail") so the test still pins the footer reserve
on the inner call where it lives.

dotnet build green; 1,309 / 1,309 tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-26 23:10:01 +02:00
parent 2818fcca8c
commit df9f2fd3da
2 changed files with 24 additions and 2 deletions

View file

@ -90,6 +90,20 @@ public sealed class ChatPanel : IPanel
return;
}
// L.0 follow-up: wrap the entire chat panel body in a single
// outer BeginChild so empty-space clicks anywhere in the body
// (Checkbox row, between Separator and input, etc.) are
// absorbed by BeginChild's drag-trap (an InvisibleButton the
// ImGui renderer adds inside every BeginChild). Without this
// wrapper the chat panel was draggable from any empty body
// pixel — only the inner ##chattail area was protected.
if (!renderer.BeginChild("##chatbody", new System.Numerics.Vector2(0f, 0f)))
{
renderer.EndChild();
renderer.End();
return;
}
// L.0 follow-up: top-of-panel "Copy mode" toggle. When on, the
// chat tail rendering swaps to TextMultilineReadOnly so the
// user can mark + Ctrl+C any text. Off (default) preserves the
@ -186,6 +200,7 @@ public sealed class ChatPanel : IPanel
if (TryHandleClientCommand(trimmed))
{
_input = string.Empty;
renderer.EndChild(); // outer ##chatbody
renderer.End();
return;
}
@ -206,6 +221,7 @@ public sealed class ChatPanel : IPanel
_vm.ShowSystemMessage(
$"Unknown command: {verb}. Type /help for the list of supported commands.");
_input = string.Empty;
renderer.EndChild(); // outer ##chatbody
renderer.End();
return;
}
@ -225,6 +241,7 @@ public sealed class ChatPanel : IPanel
_input = string.Empty;
}
renderer.EndChild(); // outer ##chatbody
renderer.End();
}