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.83: plugin-free background symbol load (WM_SETTEXT filter + Enter) — #20 works even while eeschema python is cold (#21)
5 files changed
+47−9
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.82+0.9.83
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.82",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.82/adom-bridge-kicad-v0.9.82.zip",- "sha256": "fc2c2bfd8196aca51b0f3a934446d97984a48a5e64a7d7e5b1c3648bc374b831",- "size": 376847,+ "version": "0.9.83",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.83/adom-bridge-kicad-v0.9.83.zip",+ "sha256": "edc6f4f0abb235511074b6c50f00b19ff500e305d855160aaea4fbee0350fbf9",+ "size": 377395, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-14T13:01:57Z",+ "released_at": "2026-08-14T15:33:11Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.83.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.82",+ "version": "0.9.83", "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/open_symbol_editor.py+40−2@@ -186,6 +186,34 @@ def _plugin_background_load(symbol_name: str, library_name: str = "", return {"loaded": False, "_error": f"{type(e).__name__}: {e}"} +def _background_navigate_win32(sym_hwnd: int, filter_text: str, verify: str) -> bool:+ """v0.9.83 (#20/#21): plugin-free BACKGROUND symbol load. WM_SETTEXT into the+ LIB_TREE's filter Edit (fires EN_CHANGE -> KiCad filters and auto-selects the+ best match on its debounce timer), then Enter posted to the Edit (KiCad's+ filter box forwards Enter to activate the selection). No focus, no SendInput,+ no in-process plugin needed — works even while eeschema's embedded Python is+ still minutes from initializing (issue #21).+ Returns True when the editor title confirms `verify` loaded."""+ edit = _find_child_by_class_and_parent(sym_hwnd, "Edit", "searchCtrl")+ if not edit:+ return False+ WM_SETTEXT = 0x000C+ WM_KEYDOWN, WM_KEYUP, VK_RETURN = 0x0100, 0x0101, 0x0D+ try:+ user32.SendMessageW(edit, WM_SETTEXT, 0, ctypes.create_unicode_buffer(filter_text))+ except Exception:+ return False+ time.sleep(1.4) # LIB_TREE search debounce runs on the UI thread (~200-500ms) + tree rebuild+ user32.PostMessageW(edit, WM_KEYDOWN, VK_RETURN, 0)+ user32.PostMessageW(edit, WM_KEYUP, VK_RETURN, 0)+ for _ in range(8):+ time.sleep(0.7)+ t = (_get_symbol_editor_title() or "").lower()+ if verify in t and "no symbol loaded" not in t:+ return True+ return False++ def _navigate_to_symbol(sym_hwnd: int, symbol_name: str) -> dict: """Call the PowerShell script to navigate to a specific symbol. @@ -462,7 +490,7 @@ def handle_open_symbol_editor(kicad_info: dict, args: dict) -> dict: # v0.9.77 (#20): wait up to 12s for the plugin on a cold-started eeschema — # first-probe give-up was why symbolName silently produced an empty editor. _verify = (symbol_name or search_text).lower()- _pl = _plugin_background_load(search_text, library_name, wait_plugin_s=12.0)+ _pl = _plugin_background_load(search_text, library_name, wait_plugin_s=4.0) if str(_pl.get("loaded")) in ("True", "unverified"): time.sleep(0.6) _title = _get_symbol_editor_title() if "_get_symbol_editor_title" in globals() else ""@@ -472,7 +500,17 @@ def handle_open_symbol_editor(kicad_info: dict, args: dict) -> dict: "output": f"Symbol '{search_text}' loaded (background plugin path): {_title or _pl.get('frameTitle','')}", "via": "plugin-background", }- # unverified and title doesn't confirm — fall through to PS nav+ # unverified and title doesn't confirm — fall through++ # v0.9.83: plugin-free win32 tier — filter via WM_SETTEXT + Enter, background.+ # This is the workhorse while eeschema's Python is cold (issue #21).+ _filter = f"{library_name} {symbol_name}".strip() if library_name else search_text+ if _background_navigate_win32(sym_hwnd, _filter, _verify):+ return {+ "success": True,+ "output": f"Symbol '{search_text}' loaded (background win32 path): {_get_symbol_editor_title()}",+ "via": "win32-background",+ } nav_result = _navigate_to_symbol(sym_hwnd, search_text)