fix(input): inject a no-op input event so force-foreground actually works
Follow-up to the AttachThreadInput change: verified against an isolated repro (a foreground-stealing window + the helper spawned exactly like the app) that AttachThreadInput + clearing the foreground-lock timeout was NOT sufficient on this Windows build - SetForegroundWindow still returned false and Genshin stayed in the background. The missing condition is "the calling process received the last input event". Injecting a benign no-op input (a 0,0 relative mouse move, no cursor movement, no menu-mnemonic side effect) right before SetForegroundWindow satisfies it. With the nudge the repro now returns focused:true / setForegroundResult:true from a background process while another app holds the foreground - the exact auto-scan start scenario. Applied to both the C# sidecar and the PowerShell fallback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -216,6 +216,9 @@ function Force-Foreground {
|
|||||||
if ($foreground -ne 0 -and $foreground -ne $current -and $foreground -ne $target) { $attachedForeground = [Native.InputHelper]::AttachThreadInput($current, $foreground, $true) }
|
if ($foreground -ne 0 -and $foreground -ne $current -and $foreground -ne $target) { $attachedForeground = [Native.InputHelper]::AttachThreadInput($current, $foreground, $true) }
|
||||||
$timeoutRead = [Native.InputHelper]::SystemParametersInfoGet(0x2000, 0, [ref]$oldTimeout, 0)
|
$timeoutRead = [Native.InputHelper]::SystemParametersInfoGet(0x2000, 0, [ref]$oldTimeout, 0)
|
||||||
[Native.InputHelper]::SystemParametersInfoSet(0x2001, 0, [IntPtr]::Zero, 0x0002) | Out-Null
|
[Native.InputHelper]::SystemParametersInfoSet(0x2001, 0, [IntPtr]::Zero, 0x0002) | Out-Null
|
||||||
|
# Inject a no-op input (0,0 mouse move) so this process is the last input
|
||||||
|
# source, which Windows requires before it will honor a foreground change.
|
||||||
|
Send-MouseInput -flags 0x0001 | Out-Null
|
||||||
[Native.InputHelper]::ShowWindowAsync($hwnd, 9) | Out-Null
|
[Native.InputHelper]::ShowWindowAsync($hwnd, 9) | Out-Null
|
||||||
[Native.InputHelper]::BringWindowToTop($hwnd) | Out-Null
|
[Native.InputHelper]::BringWindowToTop($hwnd) | Out-Null
|
||||||
return [Native.InputHelper]::SetForegroundWindow($hwnd)
|
return [Native.InputHelper]::SetForegroundWindow($hwnd)
|
||||||
|
|||||||
@@ -316,6 +316,12 @@ internal static class Program
|
|||||||
timeoutRead = Native.SystemParametersInfo(Native.SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
|
timeoutRead = Native.SystemParametersInfo(Native.SPI_GETFOREGROUNDLOCKTIMEOUT, 0, ref oldTimeout, 0);
|
||||||
Native.SystemParametersInfo(Native.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, IntPtr.Zero, Native.SPIF_SENDCHANGE);
|
Native.SystemParametersInfo(Native.SPI_SETFOREGROUNDLOCKTIMEOUT, 0, IntPtr.Zero, Native.SPIF_SENDCHANGE);
|
||||||
|
|
||||||
|
// Inject a no-op input (0,0 relative mouse move) so this process counts
|
||||||
|
// as the last input source - one of the conditions Windows requires to
|
||||||
|
// allow a foreground change. This is what the removed ALT tap did, but
|
||||||
|
// without the menu-mnemonic side effect.
|
||||||
|
NudgeInput();
|
||||||
|
|
||||||
Native.ShowWindowAsync(hwnd, 9); // SW_RESTORE
|
Native.ShowWindowAsync(hwnd, 9); // SW_RESTORE
|
||||||
Native.BringWindowToTop(hwnd);
|
Native.BringWindowToTop(hwnd);
|
||||||
var ok = Native.SetForegroundWindow(hwnd);
|
var ok = Native.SetForegroundWindow(hwnd);
|
||||||
@@ -390,6 +396,14 @@ internal static class Program
|
|||||||
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
return principal.IsInRole(WindowsBuiltInRole.Administrator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void NudgeInput()
|
||||||
|
{
|
||||||
|
var move = new Native.INPUT[1];
|
||||||
|
move[0].type = 0; // INPUT_MOUSE
|
||||||
|
move[0].mi.dwFlags = Native.MOUSEEVENTF_MOVE; // dx=dy=0 -> no cursor movement
|
||||||
|
Native.SendInput(1, move, Marshal.SizeOf<Native.INPUT>());
|
||||||
|
}
|
||||||
|
|
||||||
private static uint SendMouseClickBatch()
|
private static uint SendMouseClickBatch()
|
||||||
{
|
{
|
||||||
var inputs = new Native.INPUT[2];
|
var inputs = new Native.INPUT[2];
|
||||||
@@ -427,6 +441,7 @@ internal static class Program
|
|||||||
|
|
||||||
internal static class Native
|
internal static class Native
|
||||||
{
|
{
|
||||||
|
public const uint MOUSEEVENTF_MOVE = 0x0001;
|
||||||
public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
|
public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
|
||||||
public const uint MOUSEEVENTF_LEFTUP = 0x0004;
|
public const uint MOUSEEVENTF_LEFTUP = 0x0004;
|
||||||
public const uint MOUSEEVENTF_WHEEL = 0x0800;
|
public const uint MOUSEEVENTF_WHEEL = 0x0800;
|
||||||
|
|||||||
Reference in New Issue
Block a user