| Filename | Latest commit message | Latest commit date |
|---|---|---|
The eeschema/pcbnew binding TUs had ~1000 lines of copy-pasted collab code. Factored into two header-only shared files (zero build-script changes — the collab_presence_style.h precedent): - collab_common.h (pcbjam_collab): toUtf8, runOnFiber (the CallAfter+COROUTINE fiber idiom — was ~25 inline copies), the window.kicadCollab wire emitters (onDelta/onItems/onCursor/onSelection/onViewport), frame-generic undo test hooks. - collab_presence_core.h (pcbjam_presence::CORE): PEER/PIN + all presence state and machinery (start/canvas binds/lock query, setRemote/setPins/ setStyle, selection check + dedupe, overlay redraw loop, viewport push/pull, releaseSelection, locks probe), written against the EDA_DRAW_FRAME + SELECTION_TOOL base classes. Per-editor hooks: frame, selectionTool, selectionEmitPayload, resolveItem, drawPeerShapes. One CORE instance per TU (anonymous-namespace presenceCore()) so the merged image keeps per-editor state separation. - NEW per-editor resolveXsel(frame, peer): ONE cross-app resolver shared by the ghost render AND kicadCollabTestGetCrossMapped — the mapping loop was duplicated within each TU, letting the test probe drift from the pixels. Deliberately NOT factored: the Yjs differ/apply halves (itemToJson/makeItem/ flushDiff/doApply*) — structurally parallel but the bodies encode per-editor sync semantics and editor-specific asyncify devirtualization workarounds that must stay visible. kicadOpenFile/kicadCollabOnSave keep the existing KICAD_MERGED_EMBIND mechanism. TestClearSelection stays editor-typed (ClearSelection is not on the SELECTION_TOOL base). eeschema_embind 2203→1721 lines, pcbnew_embind 2518→1993. JS-facing names, signatures and the kicad_editor_embind.cpp dispatcher are unchanged. Verified: kicad_editor image builds clean; tests/kicad presence+locks 18/18 (incl. ghost-render pixel compares), collab+ysync-repros 31 passed/2 skipped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013u9h8fkQktH7KRECaHJmUG |
||
| .. | ||
| bindings | ||
| cli | ||
| cmake | ||
| editor | ||
| gl1 | ||
| kiplatform | ||
| occ-service | ||
| shims | ||
| stubs | ||
| README.md | ||
WASM Compatibility Layer
This directory contains WASM-specific implementations that allow KiCad to run in a web browser while keeping our KiCad fork as close to upstream as possible.
Principle
Instead of patching KiCad source files, we:
- Provide alternative implementations for platform-specific code (kiplatform)
- Stub out libraries/features that can't work in the browser (libgit2, curl, nng, scripting, 3D viewer, ...)
- Expose KiCad to JavaScript via Embind bindings
- Override host package detection during cross-compilation (cmake find-modules)
The KiCad-side hooks for this are small if(EMSCRIPTEN) branches in KiCad's own
CMakeLists that pull sources from this directory — see "How it's wired" below.
Directory Structure
wasm/
├── README.md # This file
├── kiplatform/ # Platform abstraction implementations (compiled into KiCad)
│ ├── app.cpp # App lifecycle (paths, startup)
│ ├── drivers.cpp # GPU detection (returns "WebGL")
│ ├── environment.cpp # Environment variables
│ ├── io.cpp # File I/O (WASM virtual filesystem)
│ ├── policy.cpp # Security policy (always permissive)
│ ├── secrets.cpp # Credential storage
│ ├── sysinfo.cpp # System information
│ ├── printing.cpp # Print support (browser print())
│ └── ui.cpp # UI helpers
├── bindings/ # Embind bindings exposing each app to JavaScript
│ ├── pcbnew_embind.cpp
│ ├── eeschema_embind.cpp
│ ├── pl_editor_embind.cpp
│ └── calculator_embind.cpp
├── stubs/ # Stub implementations + header shims for unavailable deps
│ ├── *.c / *.cpp # libgit2, curl, nng, scripting, 3D viewer, frame stubs, ...
│ ├── char_traits_uint16_workaround.h
│ └── GL/ nng/ ngspice/ # Header stubs found via include paths
└── cmake/ # CMake find-module overrides for cross-compilation
└── Find*.cmake / Use*.cmake
How it's wired
kiplatform — compiled into KiCad
The kiplatform/*.cpp files are added directly to KiCad's kiplatform library by an
if(EMSCRIPTEN) branch in kicad/libs/kiplatform/CMakeLists.txt, which references
them as ${PROJECT_SOURCE_DIR}/../wasm/kiplatform/*.cpp. There is no separate
libkiplatform_wasm.a.
stubs — compiled by the build script and KiCad CMakeLists
scripts/kicad/build-kicad-target.sh compiles the C stubs (libgit2_stub.c,
curl_stub.c, nng_stub.c) and force-includes char_traits_uint16_workaround.h.
App-specific *_frame_stub.cpp / *_scripting_stub.cpp are picked up per app, and
the remaining *_stub.cpp files are pulled in by if(EMSCRIPTEN) branches in the
KiCad fork's own CMakeLists. Header stubs under GL/, nng/, ngspice/ are resolved
via include paths.
bindings — per app
build-kicad-target.sh compiles wasm/bindings/<app>_embind.cpp for the app being
built (apps without an embind file get an empty placeholder object).
cmake — module path
build-kicad-target.sh passes -DCMAKE_MODULE_PATH="${PROJECT_ROOT}/wasm/cmake" so
the WASM find-module stubs override host package detection.
Coroutine/fiber support is not in this directory — it comes from the KiCad fork's
kicad/thirdparty/libcontext/libcontext.cpp(LIBCONTEXT_PLATFORM_wasm32). The GLU tesselator comes fromkicad/libs/kimath/glu_tess/glu_tess_impl.cpp.
Adding New Implementations
- Create the implementation file in the appropriate directory (
kiplatform/,stubs/,bindings/). - Wire it in: a stub C file goes in
build-kicad-target.sh; a kiplatform/app source goes in the relevantif(EMSCRIPTEN)branch of the KiCad-side CMakeLists. - Ensure the header interface matches KiCad's expected interface.
- Test with a minimal build before full integration.