app
KiCad - the KiCad Bridge
Public Made by Adomby adom
Drive your own KiCad from an AI, in the background: open every editor, read the whole board as data (the EDA Bridge Standard board model), stack-up, part heights, netlists, place, route, pour, DRC and exports.
← Commit history
1.0.44: 1.0.44: the taskbar thread logs what it does (ticker start, each badge applied, and once per distinct failure) so a missing badge can be diagnosed from the bridge log. No behaviour change from 1.0.43.
3 files changed
+32−9
rust/Cargo.lock+3−3@@ -244,7 +244,7 @@ dependencies = [ [[package]] name = "kicad-bridge"-version = "1.0.43"+version = "1.0.44" dependencies = [ "kicad-core", "kicad-platform",@@ -255,7 +255,7 @@ dependencies = [ [[package]] name = "kicad-core"-version = "1.0.43"+version = "1.0.44" dependencies = [ "kicad-ipc-rs", "kicad-platform",@@ -281,7 +281,7 @@ dependencies = [ [[package]] name = "kicad-platform"-version = "1.0.43"+version = "1.0.44" dependencies = [ "serde", "serde_json",
rust/Cargo.toml+1−1@@ -3,7 +3,7 @@ resolver = "2" members = ["crates/*"] [workspace.package]-version = "1.0.43"+version = "1.0.44" edition = "2021" license = "MIT" publish = false
rust/crates/kicad-bridge/src/taskbar.rs+28−5@@ -125,9 +125,26 @@ fn apply_badge(h: u64) { if with_badged(|b| b.contains(&h)).unwrap_or(true) { return; }- let Some(icon) = badge_b64() else { return };- if ab::desktop_taskbar(h, json!({"overlay": {"icon": icon, "tooltip": "Adom is driving this KiCad window"}})).is_ok() {- with_badged(|b| b.insert(h));+ let Some(icon) = badge_b64() else {+ log_once("[taskbar] badge image not found: expected resources/adom-overlay-32.png beside the exe");+ return;+ };+ match ab::desktop_taskbar(h, json!({"overlay": {"icon": icon, "tooltip": "Adom is driving this KiCad window"}})) {+ Ok(_) => {+ with_badged(|b| b.insert(h));+ eprintln!("[taskbar] badge on {h}");+ }+ Err(e) => log_once(&format!("[taskbar] badge on {h} failed: {e:?}")),+ }+}++/// One line per distinct message: a failing call repeats every 2 s and must not flood the log.+fn log_once(msg: &str) {+ static SEEN: Mutex<Option<HashSet<String>>> = Mutex::new(None);+ if let Ok(mut g) = SEEN.lock() {+ if g.get_or_insert_with(HashSet::new).insert(msg.to_string()) {+ eprintln!("{msg}");+ } } } @@ -156,17 +173,22 @@ pub fn live_percent(frames: &[Value]) -> Option<i64> { } fn ticker() {+ eprintln!("[taskbar] ticker started (badge {}, activity {})", setting_bool("overlayBadges", true), activity_mode()); let mut painted: HashSet<u64> = HashSet::new(); let mut idle_ticks = 0u32; loop { std::thread::sleep(TICK); if !ab::available() {+ log_once("[taskbar] Adom Bridge's direct API is not reachable from this thread: no badge, no bar"); continue; } let driving = INFLIGHT.load(Ordering::SeqCst) > 0 || since_last_drive().is_some_and(|d| d < DRIVE_TAIL); if driving { idle_ticks = 0; let hwnds = kicad_hwnds();+ if hwnds.is_empty() {+ log_once("[taskbar] driving, but no KiCad window is listed");+ } let mode = activity_mode(); let bar = matches!(mode.as_str(), "progress" | "both"); let badge = setting_bool("overlayBadges", true);@@ -180,8 +202,9 @@ fn ticker() { Some(p) => json!({"state": "normal", "value": p.clamp(1, 100)}), None => json!({"state": "indeterminate"}), };- if ab::desktop_taskbar(h, json!({"progress": p})).is_ok() {- painted.insert(h);+ match ab::desktop_taskbar(h, json!({"progress": p})) {+ Ok(_) => { painted.insert(h); }+ Err(e) => log_once(&format!("[taskbar] progress on {h} failed: {e:?}")), } } }