app
Adom Desktop - 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.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
"""Capture desktop screenshots for tour debugging. Zero pip deps — Win32 only."""
import ctypes
import ctypes.wintypes
import struct
import sys
import zlib
user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32
# Make this process DPI-aware so we capture at the real physical resolution.
# Without this, topmost/overlay windows may not appear in the capture on
# high-DPI (125%/150%) displays.
try:
user32.SetProcessDPIAware()
except Exception:
pass
def capture_screen(path: str):
"""Capture the entire screen to a PNG file."""
w = user32.GetSystemMetrics(0) # SM_CXSCREEN (physical after DPI-aware)
h = user32.GetSystemMetrics(1) # SM_CYSCREEN
hdc_screen = user32.GetDC(0)
hdc_mem = gdi32.CreateCompatibleDC(hdc_screen)
hbmp = gdi32.CreateCompatibleBitmap(hdc_screen, w, h)
gdi32.SelectObject(hdc_mem, hbmp)
gdi32.BitBlt(hdc_mem, 0, 0, w, h, hdc_screen, 0, 0, 0x00CC0020) # SRCCOPY
# Read bitmap bits
class BITMAPINFOHEADER(ctypes.Structure):
_fields_ = [
("biSize", ctypes.c_uint32), ("biWidth", ctypes.c_int32),
("biHeight", ctypes.c_int32), ("biPlanes", ctypes.c_uint16),
("biBitCount", ctypes.c_uint16), ("biCompression", ctypes.c_uint32),
("biSizeImage", ctypes.c_uint32), ("biXPelsPerMeter", ctypes.c_int32),
("biYPelsPerMeter", ctypes.c_int32), ("biClrUsed", ctypes.c_uint32),
("biClrImportant", ctypes.c_uint32),
]
bmi = BITMAPINFOHEADER()
bmi.biSize = ctypes.sizeof(BITMAPINFOHEADER)
bmi.biWidth = w
bmi.biHeight = -h # top-down
bmi.biPlanes = 1
bmi.biBitCount = 32
bmi.biCompression = 0 # BI_RGB
buf_size = w * h * 4
buf = ctypes.create_string_buffer(buf_size)
gdi32.GetDIBits(hdc_mem, hbmp, 0, h, buf, ctypes.byref(bmi), 0)
# Clean up GDI
gdi32.DeleteObject(hbmp)
gdi32.DeleteDC(hdc_mem)
user32.ReleaseDC(0, hdc_screen)
# Convert BGRA -> RGB and write PNG manually
raw = buf.raw
_write_png(path, w, h, raw)
print(f"Screenshot saved: {path} ({w}x{h})")
def _write_png(path, w, h, bgra_data):
"""Write a minimal PNG from BGRA pixel data."""
# Convert BGRA rows to RGB with filter byte
rows = []
for y in range(h):
row = bytearray([0]) # filter: None
offset = y * w * 4
for x in range(w):
px = offset + x * 4
b, g, r = bgra_data[px], bgra_data[px+1], bgra_data[px+2]
row.extend([r, g, b])
rows.append(bytes(row))
raw_data = b"".join(rows)
compressed = zlib.compress(raw_data, 6)
def _chunk(ctype, data):
c = ctype + data
return struct.pack(">I", len(data)) + c + struct.pack(">I", zlib.crc32(c) & 0xFFFFFFFF)
with open(path, "wb") as f:
f.write(b"\x89PNG\r\n\x1a\n")
f.write(_chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)))
f.write(_chunk(b"IDAT", compressed))
f.write(_chunk(b"IEND", b""))
if __name__ == "__main__":
out = sys.argv[1] if len(sys.argv) > 1 else "screenshot.png"
capture_screen(out)