fix(ui): #375 residual — activate the Configure Keyboard screen's own tab control

The gate-3 screenshot flight showed the keyboard list still rendering as
overlapping text after the string-resolver + parked-prototype fixes: all
SIX ActionClass pages were visible simultaneously (six stacked ListBoxes
— 'EmotesterSettings' is the Emote and CharacterSettings pages
interleaved) with six dead tab buttons above them. Root cause: OP8's
Bind built every page's rows but never called ActivateTabBehavior() on
the screen's own Type-8 tab host (0x1000049B), so no authored click
bindings were wired and no default-entry switch ran. The authored table
marks Movement (0x1000049D) IsDefault=true — activation now performs the
same default switch OptionsPanelController runs on ITS host, hiding the
other five pages and making the six tabs live.

Regressed by Bind_ActivatesTheTabControl_MovementDefaultShown_OtherPagesHidden
(fixture-driven: BehaviorActive, Movement visible, five pages hidden,
SwitchTo flips exclusivity).

Full Release suite: 13,087 passed / 4 skipped / 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-11 16:11:22 +02:00
parent 3441a71833
commit a8ce010d02
2 changed files with 71 additions and 0 deletions

View file

@ -161,6 +161,11 @@ public sealed class KeyboardConfigController
private const int HeaderTemplateIndex = 0;
private const int RowTemplateIndex = 1;
/// <summary>The screen's own Type-8 tab control hosting the six ActionClass
/// pages (class doc §"Six ActionClass list boxes"). Its authored tab table
/// (dat property 0x2E) marks Movement (0x1000049D) as the default entry.</summary>
private const uint TabHostElementId = 0x1000049Bu;
// The row template's 3 key-button children, in "Mapping 1/2/3" column order.
private static readonly uint[] KeyButtonIds = { 0x10000030u, 0x10000031u, 0x10000032u };
@ -291,6 +296,25 @@ public sealed class KeyboardConfigController
WireScreenButtons(layout, controller, bindings);
// Gate-2 screenshot finding (#375 residual): OP8 built all six pages
// but never ACTIVATED the screen's own tab control, so every page
// stayed Visible simultaneously — six stacked ListBoxes reading as
// "overlapping text", with six dead tab buttons above them.
// ActivateTabBehavior wires the authored tab clicks and performs the
// authored default-entry switch (Movement, IsDefault=true in the DAT
// table), hiding the other five pages — the exact same call
// OptionsPanelController makes on ITS Type-8 host at construction.
if (layout.FindElement(TabHostElementId) is UiTabPanel tabHost)
{
tabHost.ActivateTabBehavior();
}
else
{
Console.WriteLine(
$"[D.2b] KeyboardConfigController: tab host 0x{TabHostElementId:X8} not found "
+ "(or not a UiTabPanel) — all six ActionClass pages will render stacked.");
}
return controller;
}