player: active foreground wait replaces fixed 600ms sleep (#14)

BringSutToForeground() now polls GetForegroundWindow() == SUT hwnd at 25ms
intervals up to 2s, followed by a 100ms tail settle, instead of the brittle
fixed 600ms sleep. First-attempt replay of box-v6.yaml is now reliable
(previously dropped the opening "BOX" keystrokes on a cold start).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
minsung
2026-04-08 19:39:05 +09:00
parent 70bf5703b3
commit 98d801442b
3 changed files with 23 additions and 11 deletions

View File

@@ -212,21 +212,34 @@ public sealed class UiaPlayerHost : IPlayerHost, IDisposable
/// was launched from a shell that still has focus when the first Type/Hotkey
/// step fires.
/// </summary>
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public void BringSutToForeground()
{
try
{
var w = _app?.GetMainWindow(_automation, TimeSpan.FromSeconds(5));
if (w is null) return;
var targetHwnd = w.Properties.NativeWindowHandle.ValueOrDefault;
try { w.SetForeground(); } catch { /* best-effort */ }
try { w.Focus(); } catch { /* best-effort */ }
// Small settle so the OS-level focus switch takes effect before
// the first SendInput. 150ms is enough in practice on Win10.
// Increased from 150→600ms because FlaUI Keyboard.Type drops the
// first couple of characters if SendInput fires before the OS
// finishes the focus transition (observed: "BOX" lost on first
// step, "10" succeeded later once the app had settled).
System.Threading.Thread.Sleep(600);
// Issue #14 follow-up: active wait instead of fixed 600ms sleep.
// Poll until the OS reports the SUT as the foreground window, up
// to 2s. Previously a 600ms fixed sleep was threshold-sensitive
// and caused the first "BOX" keystroke to get dropped on a cold
// first run.
var deadline = DateTime.UtcNow.AddSeconds(2);
while (DateTime.UtcNow < deadline)
{
if (targetHwnd != IntPtr.Zero && GetForegroundWindow() == targetHwnd)
break;
System.Threading.Thread.Sleep(25);
}
// Tiny additional settle for the OS keyboard-focus IPC to finish
// after the foreground transition is observed.
System.Threading.Thread.Sleep(100);
}
catch
{