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.146: parking instrumentation (attempts, last error, sweep ticks, bridge-window count in focusDebug)
5 files changed
+23−10
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.145+0.9.146
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.145",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.145/adom-bridge-kicad-v0.9.145.zip",- "sha256": "ff0fba27d4a49fa94022e1e633a9dd678488c306e73b058f06c34e86e042a91b",- "size": 418858,+ "version": "0.9.146",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.146/adom-bridge-kicad-v0.9.146.zip",+ "sha256": "af208f574376000f07a75b58794d97b77d250f1f1b330fc5bd62268b3be3f15a",+ "size": 419050, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-17T14:31:45Z",+ "released_at": "2026-08-17T14:33:29Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.146.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.145",+ "version": "0.9.146", "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/win_focus.py+16−3@@ -320,6 +320,10 @@ def get_focus_debug() -> dict: "guardCount": _guard_count, "parkedCount": len(_parked), "baselineCount": len(_park_baseline),+ "bridgeWindows": len(_bridge_windows),+ "parkAttempts": _park_attempts,+ "parkLastError": _park_last_error,+ "sweepTicks": _sweep_ticks, } @@ -356,6 +360,9 @@ def get_focus_events() -> list: # capture works off-screen; the user sees nothing appear. # --------------------------------------------------------------------------- _parked: dict = {} # hwnd -> (x, y)+_park_attempts = 0+_park_last_error = ""+_sweep_ticks = 0 _verb_inflight = 0 @@ -401,6 +408,7 @@ def _start_park_sweep() -> None: try: active = _verb_inflight > 0 or _guard_count > 0 if active:+ globals()["_sweep_ticks"] = _sweep_ticks + 1 quiet_since = None if _t.monotonic() >= _expected_fg_until: for h in _enum_kicad_hwnds() - _park_baseline:@@ -471,11 +479,14 @@ class _WINDOWPLACEMENT(ctypes.Structure if IS_WINDOWS else object): def _park_offscreen(hwnd) -> None: """Move a window fully off the visible desktop WITHOUT activation.+ (Instrumented: attempts + last error surface in focusDebug.) SetWindowPos silently cannot move a MAXIMIZED window (the -13,-13 no-op, 2026-08-17), so parking goes through SetWindowPlacement: demote to normal-size at -32000 with SW_SHOWNOACTIVATE, remembering whether it was maximized so unpark can honor it."""+ global _park_attempts, _park_last_error try:+ _park_attempts += 1 if not _user32.IsWindow(hwnd): return r = ctypes.wintypes.RECT()@@ -497,9 +508,11 @@ def _park_offscreen(hwnd) -> None: wp.rcNormalPosition.right = -32000 + w wp.rcNormalPosition.bottom = -32000 + h wp.flags = 0- _user32.SetWindowPlacement(hwnd, ctypes.byref(wp))- except Exception:- pass+ ok = _user32.SetWindowPlacement(hwnd, ctypes.byref(wp))+ if not ok:+ _park_last_error = f"SetWindowPlacement rc=0 lasterr={ctypes.get_last_error()}"+ except Exception as e:+ _park_last_error = f"{type(e).__name__}: {e}" def _unpark(hwnd, to_bottom: bool = True) -> None: