app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Reference implementation of the KiCad bridge: multi-instance Python server, forward path via kicad-cli, reverse path via in-process plugin. Most complex of the three bundled bridges.
← Commit history
v0.9.149: fight escalation - a window reasserting its geometry (eeschema mid-load) gets minimized-no-activate after 4 repark fights (flicker-free); screenshots restore park-minimized windows off-screen for capture
6 files changed
+44−9
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.148+0.9.149
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.148",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.148/adom-bridge-kicad-v0.9.148.zip",- "sha256": "e8cbef9b98554667ef37777118316f6ca38508ce2a6edc3805fd9c5beda8c421",- "size": 419322,+ "version": "0.9.149",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.149/adom-bridge-kicad-v0.9.149.zip",+ "sha256": "c7a6c63fb953b57cb1e014661b2ce2e31dea3cc896dc7e872647146fc34f45e3",+ "size": 419858, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-17T14:36:47Z",+ "released_at": "2026-08-17T14:38:31Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.149.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.148",+ "version": "0.9.149", "description": "Reverse bridge for KiCad \u2014 board/schematic introspection, lint via kicad-cli, plugin install, multi-instance probe, in-process DRC.", "homepage": "https://wiki.adom.inc/adom/adom-bridge", "author": "Adom Inc.",
handlers/kicad_ui.py+21@@ -267,6 +267,27 @@ def _write_bmp(path: str, width: int, height: int, pixel_data: bytes): def _screenshot_hwnd(hwnd: int, label: str = "", max_dim: int = 1568) -> dict: """Capture a window by HWND using PrintWindow. Returns {success, savedTo, sizeKB}."""+ # A park-minimized window (focus machinery) can't PrintWindow reliably —+ # restore it OFF-SCREEN without activation just for the capture.+ try:+ if user32.IsIconic(hwnd):+ from handlers.win_focus import _park_offscreen, _WINDOWPLACEMENT+ import ctypes as _ct+ wp = _WINDOWPLACEMENT()+ wp.length = _ct.sizeof(_WINDOWPLACEMENT)+ user32.GetWindowPlacement(hwnd, _ct.byref(wp))+ w = max(400, wp.rcNormalPosition.right - wp.rcNormalPosition.left)+ h = max(300, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top)+ wp.rcNormalPosition.left = -32000+ wp.rcNormalPosition.top = -32000+ wp.rcNormalPosition.right = -32000 + w+ wp.rcNormalPosition.bottom = -32000 + h+ wp.flags = 0+ wp.showCmd = 4 # SW_SHOWNOACTIVATE+ user32.SetWindowPlacement(hwnd, _ct.byref(wp))+ time.sleep(0.3)+ except Exception:+ pass rect = _get_window_rect(hwnd) width = rect["width"] height = rect["height"]
handlers/win_focus.py+16−2@@ -359,7 +359,8 @@ def get_focus_events() -> list: # AT THE BOTTOM of the z-order. Taskbar buttons keep working; PrintWindow # capture works off-screen; the user sees nothing appear. # ----------------------------------------------------------------------------_parked: dict = {} # hwnd -> (x, y)+_parked: dict = {} # hwnd -> (x, y, was_max)+_park_fights: dict = {} # hwnd -> repark count _park_attempts = 0 _park_last_error = "" _sweep_ticks = 0@@ -427,7 +428,8 @@ def _start_park_sweep() -> None: quiet_since = None else: for h in list(_parked.keys()):- _park_offscreen(h)+ if not _user32.IsIconic(h):+ _park_offscreen(h) _t.sleep(0.05) continue _t.sleep(0.1)@@ -500,6 +502,17 @@ def _park_offscreen(hwnd) -> None: was_max = wp.showCmd == SW_SHOWMAXIMIZED if hwnd not in _parked: _parked[hwnd] = (r.left, r.top, was_max)+ # ESCALATION: an app that keeps reasserting its geometry (eeschema+ # during load re-maximizes every ~120ms) turns positional parking into+ # visible flicker — after a few fights, minimize it without activation+ # instead. wx does not un-minimize itself; the taskbar button still+ # works; the screenshot path restores off-screen for capture.+ _park_fights[hwnd] = _park_fights.get(hwnd, 0) + 1+ if _park_fights[hwnd] >= 4:+ wp.flags = 2 if was_max else 0 # WPF_RESTORETOMAXIMIZED+ wp.showCmd = 7 # SW_SHOWMINNOACTIVE+ _user32.SetWindowPlacement(hwnd, ctypes.byref(wp))+ return wp.showCmd = SW_SHOWNOACTIVATE # 4 w = max(200, wp.rcNormalPosition.right - wp.rcNormalPosition.left) h = max(150, wp.rcNormalPosition.bottom - wp.rcNormalPosition.top)@@ -518,6 +531,7 @@ def _park_offscreen(hwnd) -> None: def _unpark(hwnd, to_bottom: bool = True) -> None: try: pos = _parked.pop(hwnd, None)+ _park_fights.pop(hwnd, None) if pos is None or not _user32.IsWindow(hwnd): return x, y, was_max = (pos if len(pos) == 3 else (pos[0], pos[1], False))