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.115: sentinel bless test fixed - 'recent input' wrongly blessed self-raises while the user typed in ANOTHER app (caught live); now only a click landing ON the window or an in-progress alt-tab counts as user intent
5 files changed
+40−14
BRIDGE_VERSION+1−1@@ -1 +1 @@-0.9.114+0.9.115
adom-bridge-kicad-manifest.json+5−5@@ -1,15 +1,15 @@ { "manifest_version": 1, "name": "kicad",- "version": "0.9.114",- "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.114/adom-bridge-kicad-v0.9.114.zip",- "sha256": "4aafd591a26ff321f3ba3242a03d7a0db35664971552b96104db0e8899a297a0",- "size": 408981,+ "version": "0.9.115",+ "url": "https://wiki.adom.inc/download/adom/kicad-bridge/0.9.115/adom-bridge-kicad-v0.9.115.zip",+ "sha256": "733b6ddad46b92a6ec97fc74909ca917ea63f7b610269c90209d687966d6af87",+ "size": 409411, "verbPrefixes": [ "kicad_" ], "healthEndpoint": "/status",- "released_at": "2026-08-16T13:25:01Z",+ "released_at": "2026-08-16T13:29:16Z", "hero": "https://wiki.adom.inc/blob/app/kicad-bridge/kicad-hero.png", "languages": [ "Python",
adom-bridge-kicad-v0.9.115.zipadded⋯ 1 unchanged line ⋯
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "kicad", "displayName": "KiCad EDA",- "version": "0.9.114",+ "version": "0.9.115", "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+33−7@@ -338,20 +338,48 @@ def start_focus_sentinel() -> None: except Exception: pass + def _cursor_over(hwnd) -> bool:+ """Is the cursor currently over this window (top-level hit test)?"""+ try:+ import ctypes as _ct+ pt = _ct.wintypes.POINT()+ _user32.GetCursorPos(_ct.byref(pt))+ under = _user32.WindowFromPoint(pt)+ GA_ROOT = 2+ return bool(under) and _user32.GetAncestor(under, GA_ROOT) == hwnd+ except Exception:+ return False+ def _loop():+ # v0.9.115: "recent user input" was the wrong bless test — the user+ # typing in ANOTHER app is exactly when a self-raise is most disruptive,+ # yet it counted as user intent (caught live by John over RustDesk).+ # A foreground is user-initiated only if a mouse CLICK landed (and the+ # cursor sits on the new window) or an alt-tab was in progress. last_fg = None- blessed = set() # KiCad hwnds the user deliberately foregrounded+ last_click_t = 0.0+ last_alt_t = 0.0+ VK_LBUTTON, VK_RBUTTON, VK_MENU = 0x01, 0x02, 0x12 while True: try:+ now = _t.monotonic()+ try:+ if (_user32.GetAsyncKeyState(VK_LBUTTON) & 0x8000) or \+ (_user32.GetAsyncKeyState(VK_RBUTTON) & 0x8000):+ last_click_t = now+ if _user32.GetAsyncKeyState(VK_MENU) & 0x8000:+ last_alt_t = now+ except Exception:+ pass fg = _user32.GetForegroundWindow() if fg != last_fg: if fg and is_kicad_window(fg): ago = _seconds_since_user_input()- if _t.monotonic() < _expected_fg_until:- blessed.add(fg)+ clicked_here = (now - last_click_t) <= 1.2 and _cursor_over(fg)+ alt_tabbed = (now - last_alt_t) <= 2.0+ if now < _expected_fg_until: _log("sanctioned-foreground (allowed)", fg, ago)- elif ago <= _USER_INTENT_WINDOW_S:- blessed.add(fg)+ elif clicked_here or alt_tabbed: _log("user-foregrounded (left alone)", fg, ago) elif _guard_count > 0: _log("steal-during-guard (guardian handles)", fg, ago)@@ -361,8 +389,6 @@ def start_focus_sentinel() -> None: # no guard is active: immediately clear the NOACTIVATE # bit the bounce set, so a real user click still works allow_activation(fg)- else:- blessed.discard(last_fg) last_fg = fg _t.sleep(0.12) except Exception: