# Restore the deployment window state: # 1. the RENDERER (GL bridge, main out-the-window view) -> always-on-top # (WS_EX_TOPMOST), so the game view is never covered. # 2. DOSBox-X -> parked at 10,10 with FOREGROUND FOCUS, so its emulation # thread keeps foreground priority (else the RIO ACK deadline is missed # and the board storms -- the RIO focus-sensitivity issue). # A topmost renderer stays visually above the focused-but-non-topmost DOSBox, # yet DOSBox remains the active window (priority boost). Run anytime the stack # gets disturbed (a capture, a click, new windows): .\focus_dosbox.ps1 param([int]$X = 10, [int]$Y = 10) Add-Type @' using System; using System.Text; using System.Runtime.InteropServices; public class DBFocus { delegate bool EP(IntPtr h, IntPtr l); [DllImport("user32.dll")] static extern bool EnumWindows(EP cb, IntPtr l); [DllImport("user32.dll")] static extern int GetWindowTextA(IntPtr h, byte[] b, int m); [DllImport("user32.dll")] static extern bool IsWindowVisible(IntPtr h); [DllImport("user32.dll")] static extern bool SetWindowPos(IntPtr h, IntPtr a, int x,int y,int w,int hh, uint f); [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr h); [DllImport("user32.dll")] static extern bool BringWindowToTop(IntPtr h); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr h, int c); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr h, out uint p); [DllImport("user32.dll")] static extern bool AttachThreadInput(uint a, uint b, bool f); [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); static IntPtr Find(string needle) { IntPtr found=IntPtr.Zero; EnumWindows((h,l)=>{ if(!IsWindowVisible(h)) return true; byte[] b=new byte[256]; int n=GetWindowTextA(h,b,256); if(n>0 && Encoding.ASCII.GetString(b,0,n).Contains(needle)){ found=h; return false; } return true; }, IntPtr.Zero); return found; } static IntPtr FindRenderer() { IntPtr h=Find("dpl3-revive renderer"); if(h!=IntPtr.Zero) return h; return Find("VelociRender"); } public static string Apply(int x, int y) { string s=""; // 1) renderer -> topmost (keeps game view above everything) IntPtr r=FindRenderer(); if(r!=IntPtr.Zero){ SetWindowPos(r, HWND_TOPMOST, 0,0,0,0, 0x0001|0x0002); s+="renderer topmost; "; } else s+="renderer NOT found; "; // 2) DOSBox -> 10,10 + foreground focus (RIO priority) IntPtr d=Find("DOSBox-X"); if(d==IntPtr.Zero) return s+"DOSBox NOT found"; SetWindowPos(d, IntPtr.Zero, x,y, 0,0, 0x0001|0x0004); // NOSIZE|NOZORDER ShowWindow(d, 9); // SW_RESTORE uint pid; uint fg=GetWindowThreadProcessId(GetForegroundWindow(), out pid); uint me=GetCurrentThreadId(); AttachThreadInput(me, fg, true); BringWindowToTop(d); SetForegroundWindow(d); AttachThreadInput(me, fg, false); return s+"DOSBox at "+x+","+y+" focused="+(GetForegroundWindow()==d); } } '@ [DBFocus]::Apply($X, $Y)