pcbjam/wasm/editor/merged_kiface_dispatch.cpp
Istvan Matejcsok bbeef6d20e feat(wasm): kicad_editor — merge the pcbnew+eeschema kifaces into ONE bundle (Part 2)
All four editors (PCB / Footprint / Schematic / Symbol) are now runtime --frame
choices of a single kicad_editor.wasm (178 MB at -O1 vs 147+82 separate; shared
wx/common/boost linked once). One editor per page load, as before; frames pcb /
fpedit / sch / symedit.

- wasm/editor/: the merged executable target (single_top + both kiface library sets,
  whole-archive pcbcommon) + the safety-net focus-walk Kiface() dispatch TU. Gated by
  KICAD_WASM_MERGED_EDITOR (kicad submodule bump carries the fork side: per-engine
  Kiface/getter binding + ODR renames + dual-kiface launcher).
- wasm/bindings/: per-editor collab entries renamed pcbCollab*/schCollab* (JS names
  unchanged); duplicate kicadOpenFile/kicadCollabOnSave + shared-name registrations
  guarded behind KICAD_MERGED_EMBIND; new kicad_editor_embind.cpp registers each
  shared JS name once, dispatching on the live frame.
- Build: kicad_editor app (build wrapper, target case arms, 3-object embind compile
  with the ABI-critical flags, STUB_APP=pcbnew); docker/build.sh "all" =
  kicad_editor calculator pl_editor gerbview (pcbnew/eeschema stay as explicit debug
  apps); scripts/kicad/audit-merged-symbols.sh = repeatable ODR-collision audit (run
  on kicad bumps).
- Frontend: Bundle type (bundle ≠ tool); TOOL_BUNDLE maps all four editors to
  kicad_editor; explicit --frame tokens for pcbnew (pcb) and eeschema (sch); publish
  list = the 4 real bundles.
- Tests/CI: five harnesses load kicad_editor.js with explicit frame tokens;
  PCBNEW_FAMILY_SPECS renamed BIG_MODULE_SPECS + the 8 eeschema-family specs (they
  now boot the merged module — SpiderMonkey x86 CI OOM routing); frame-runtime spec
  covers all four frames from the one bundle.

Validated so far: frame-runtime 4/4 (each frame boots with the right title, no
aborts, no duplicate embind registration); 24-spec merged-module regression green;
3D raytracer renders. Known pre-existing failure: 3d-viewer title-bar drag deadlock,
fixed on main by 7630c7e (2N+8 pthread pre-warm) — picked up by the follow-up rebase.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 17:56:02 +02:00

68 lines
2.3 KiB
C++

/*
* Merged-editor safety-net Kiface() (editor-unification Part 2).
*
* In the merged kicad_editor image the pcbnew and eeschema kifaces are compiled with
* -DKiface=PcbKiface / -DKiface=SchKiface, so every module-owned call site binds
* statically to its own engine. The handful of shared common/ call sites are patched
* to resolve their owning frame's kiface exactly (eda_base_frame.cpp,
* dialog_color_picker.cpp, design_block_tree_model_adapter.cpp) and only FALL BACK to
* the plain Kiface() — which, in this image, is THIS definition. It also keeps any
* future upstream common/ caller linking.
*
* Resolution is best-effort by design: focused window → top window → KIWAY top frame,
* walking parents to an EDA_BASE_FRAME whose FRAME_T names its face. With the one-
* frame-per-page-load model there is exactly one editor frame, so the walk is exact
* in practice; FACE_PCB is the last-resort default.
*/
#ifdef __EMSCRIPTEN__
#include <wx/app.h>
#include <wx/window.h>
#include <kiway.h>
#include <kiface_base.h>
#include <eda_base_frame.h>
// single_top.cpp's process-global KIWAY (declared in kiway.h).
static KIFACE_BASE* frameKiface( wxWindow* aWindow )
{
for( wxWindow* w = aWindow; w; w = w->GetParent() )
{
if( EDA_BASE_FRAME* frame = dynamic_cast<EDA_BASE_FRAME*>( w ) )
{
KIWAY::FACE_T face = KIWAY::KifaceType( frame->GetFrameType() );
if( face != KIWAY::FACE_T( -1 ) )
{
if( KIFACE* kiface = Kiway.KiFACE( face ) )
return static_cast<KIFACE_BASE*>( kiface );
}
}
}
return nullptr;
}
KIFACE_BASE& Kiface()
{
if( KIFACE_BASE* kiface = frameKiface( wxWindow::FindFocus() ) )
return *kiface;
if( wxTheApp )
{
if( KIFACE_BASE* kiface = frameKiface( wxTheApp->GetTopWindow() ) )
return *kiface;
}
if( KIFACE_BASE* kiface = frameKiface( Kiway.GetTop() ) )
return *kiface;
// Last resort — no frame up yet. FACE_PCB is the merged image's default TOP_FRAME
// face; both faces are registered in OnPgmInit, so this cannot be reached before
// registration in any path that previously had a working Kiface().
return *static_cast<KIFACE_BASE*>( Kiway.KiFACE( KIWAY::FACE_PCB ) );
}
#endif // __EMSCRIPTEN__