Three findings from the user's first Configure Keyboard look (OP8 gate, 2026-08-14), each root-caused against the named retail decomp: - #394 row-caption font: the synthesized action-label UiText never set DatFont and fell to the debug bitmap font. The authored row template (0x21000009/0x1000002F, retail UIOption_ActionKeyMap) carries FontDid 0x4000000A (18px serif) — Bind now takes resolveTemplateFont and applies the template's own authored font, resolved once per template pair. - #395 key captions: raw enum spellings ("Shift+ShiftLeft") replaced by the port of CInputManager_WIN32::GetNameFromKey @0x00687F40 / GetNameFromKey_Internal @0x00687800 (RetailKeyNames): DAT string-table override by DIK-name hash (key enum 4 -> 0x2300000A, meta enum 5 -> 0x2300000B, delimiter enum 3 -> 0x23000007 — GetDIDByEnum category 4, live-probed), else the OS keyboard layout's own key name ("SKIFT") via PlatformKeyNameProvider (Win32 GetKeyNameTextW — register row AD-96 for the DirectInput-vs-GetKeyNameText adaptation), else the DIK-suffix spelling. Bare modifier-key bindings show only the key name. - #396 capture feedback: clicking a mapping button now opens retail's instruction dialog (InitiateBinding @0x004899D0 -> OpenMapWarnDialog @0x00488A00): a type-2 WAIT dialog on retail's MapWarn queue key 0x10000001 with ID_ActionKeyMap_MapInstructions (0x23000004, ACTION variable interpolated), closed on key hit or ESC through the capture callback; capture is not armed if the dialog cannot open, matching retail. New RetailWaitDialogView (wait root 0x31 — same authored popup/message pair 0x3D/0x3E as the confirmation root, live-DAT probed) behind a shared IRetailDialogView presenter seam. Probe evidence (env-gated, kept): KeyboardConfigLiveMountProbeTests.ProbeKeyboardFontsAndKeyNameStrings. Register: AD-96 filed. Gate script OP8 section updated (step 4 rewritten; the "pressed/active state is enough" contract is retired). Full Release solution suite green (13,424 passed / 4 skips). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
1528e5693b
commit
30fa6ee507
16 changed files with 1105 additions and 24 deletions
43
src/AcDream.App/Platform/PlatformKeyNameProvider.cs
Normal file
43
src/AcDream.App/Platform/PlatformKeyNameProvider.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace AcDream.App.Platform;
|
||||
|
||||
/// <summary>
|
||||
/// Platform owner (L0 boundary — OS checks live under <c>Platform/</c> only)
|
||||
/// for the OS-localized key-name half of retail's
|
||||
/// <c>CInputManager_WIN32::GetNameFromKey_Internal @ 0x00687800</c> fallback:
|
||||
/// when the DAT string tables have no authored name for a key, retail shows
|
||||
/// the keyboard layout's own name ("SKIFT" on Swedish) via DirectInput's
|
||||
/// <c>IDirectInputDevice8::GetObjectInfo</c>. This port asks Win32
|
||||
/// <c>GetKeyNameTextW</c> instead — the same layout-resident name data, no
|
||||
/// DirectInput device needed (register row AD-96). Non-Windows hosts get no
|
||||
/// OS lookup (null) and callers fall back to the DIK-suffix spelling.
|
||||
/// </summary>
|
||||
public static class PlatformKeyNameProvider
|
||||
{
|
||||
/// <summary>(scanCode, isExtended) → localized key name, or null when the
|
||||
/// current platform has no OS lookup.</summary>
|
||||
public static Func<byte, bool, string?>? ForCurrentProcess()
|
||||
=> OperatingSystem.IsWindows() ? WindowsKeyName : null;
|
||||
|
||||
/// <summary>
|
||||
/// GetKeyNameTextW's lParam wants the hardware scan code in bits 16-23
|
||||
/// and the extended-key flag in bit 24 — the same split DirectInput's
|
||||
/// DIK codes carry in bit 0x80.
|
||||
/// </summary>
|
||||
private static string? WindowsKeyName(byte scan, bool extended)
|
||||
{
|
||||
Span<char> buffer = stackalloc char[64];
|
||||
int lParam = (scan << 16) | (extended ? 1 << 24 : 0);
|
||||
int length;
|
||||
unsafe
|
||||
{
|
||||
fixed (char* p = buffer)
|
||||
length = GetKeyNameTextW(lParam, p, buffer.Length);
|
||||
}
|
||||
return length > 0 ? new string(buffer[..length]) : null;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
|
||||
private static extern unsafe int GetKeyNameTextW(int lParam, char* lpString, int cchSize);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue