Files
CydandClaude Fable 5 125d835a05 Deploy: pod_deploy.ps1 cockpit window layout + focus_dosbox.ps1 (renderer topmost, DOSBox focused)
Real-pod deployment launcher for the original VDB + octopus 4-head wiring:
VPX_COCKPIT borderless head windows (radar/win0 800,0; 3-color MFD/win4 1440,0;
2-color MFD/win3 2080,0; all 640x480) + the GL bridge as the main out-the-window
view (0,0, 800x600 via new BRIDGE_W/BRIDGE_H in live_bridge.py). Editable RECTS
at the top of the script for other rigs.

focus_dosbox.ps1 restores the deployment window state: renderer -> always-on-top
(WS_EX_TOPMOST, game view never covered) + DOSBox-X -> 10,10 with foreground
focus (keeps the emu thread at foreground priority so the RIO doesn't starve).
Coexist cleanly: topmost renderer stays above the focused-but-non-topmost DOSBox.
pod_deploy calls it last; re-run anytime the stack is disturbed. LAUNCH.md
documents both.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-09 19:44:45 -05:00

60 lines
3.1 KiB
PowerShell

# 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)