refactor: collapse dual-mode plumbing — the DOM port is the only WASM build
The canvas (wxUniversal) mode is gone (wxwidgets submodule); remove every piece of side-by-side plumbing so there is exactly one build and one test flow: - scripts/build-wxuniversal-wasm.sh -> scripts/build-wx-wasm.sh; no --dom/--enable-universal; builds into build-wasm/wxwidgets - build-wasm-test.sh: no DOM_BUILD / apps-dom rsync mirror / PORT=dom; apps build straight into tests/apps (Makefile.wasm PORT conditionals collapsed; wx.js + wx-dom.js always pre-js) - docker/build.sh, build-kicad-target.sh, env.sh: WX_PORT / -dom / -universal suffixes removed; kicad builds to kicad-<app>, outputs to output/; wx.js/wx-dom.js copied from the real source path (/workspace/wxwidgets/build/wasm — the old build-wasm path never existed and silently failed) - setup-kicad-wasm.sh: single target dir; the perl wx-dom.js injection is gone — the 7 checked-in kicad pages now reference wx-dom.js directly - playwright configs serve apps/; fixtures drop the test-results/dom and logs/wxwidgets/dom namespacing; boot.spec asserts wxDomPort unconditionally; pcbnew.spec uses one reference image; appearance.spec assertions unconditional - compare/update-baseline-screenshots.sh: --port removed - tests/gal-regression/wasm/Makefile: links build-wasm/wxwidgets and carries wx-dom.js as a second pre-js — the gal-webgl suite (30 specs) now actually builds and runs here (it needed host-side boost+glm via scripts/deps; the bundle had been missing, timing the whole spec out) - tests: clickCanvas() dispatches via page.mouse (DOM widgets legitimately cover the canvas; locator actionability refused the click); the comprehensive spec drives wxChoice through its native <select> (browser-owned popup cannot be coordinate-clicked) - docs: README/CLAUDE.md/build.md script names and dirs; features/wx-dom-port README reframed (DOM is THE port), visual-notes bugs 26-28; FindwxWidgets.cmake config label drops 'wasmuniv' - wxwidgets submodule -> 9dbacc9448 (DOM-only port, fork diff shrunk) Gate: full wx e2e suite 292 passed / 1 skipped / 0 failed — first run ever with the gal-webgl specs green (28 scenarios + load + sequential). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
2c1b0d409b
commit
7dc1bf27e0
32 changed files with 199 additions and 335 deletions
|
|
@ -143,7 +143,7 @@ Import patterns used:
|
|||
**Full rebuild removes:**
|
||||
- `build-wasm/stamps/*` - All build stamps
|
||||
- `build-wasm/deps/*` - All dependency builds
|
||||
- `build-wasm/wxwidgets-universal` - wxWidgets build
|
||||
- `build-wasm/wxwidgets` - wxWidgets build
|
||||
- `build-wasm/sysroot/*` - Installed headers/libraries
|
||||
- `build-wasm/kicad-pcbnew` - KiCad build
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ After changing build flags (debug/release), use `--full` to force a complete reb
|
|||
|--------|---------|
|
||||
| `docker/build.sh` | Host entry point (starts Docker, runs build) |
|
||||
| `scripts/kicad/build-pcbnew.sh` | KiCad PCBnew build (runs inside Docker) |
|
||||
| `scripts/build-wxuniversal-wasm.sh` | wxWidgets build |
|
||||
| `scripts/build-wx-wasm.sh` | wxWidgets build |
|
||||
| `scripts/build-wasm-test.sh` | Build wxWidgets test apps |
|
||||
| `scripts/deps/build-all-deps.sh` | All dependencies |
|
||||
| `scripts/deps/build-*.sh` | Individual dependency builds |
|
||||
|
|
@ -240,7 +240,7 @@ OpenCASCADE is the longest dependency to build (~30 minutes).
|
|||
|
||||
### Incremental build not picking up changes
|
||||
- For KiCad: use `--clean-kicad` to force rebuild
|
||||
- For wxWidgets: delete `build-wasm/wxwidgets-universal/Makefile` to force reconfigure
|
||||
- For wxWidgets: delete `build-wasm/wxwidgets/Makefile` to force reconfigure
|
||||
|
||||
### WASM exception with numeric error (e.g., `3788888`)
|
||||
- Build with debug symbols (default): No `--release` flag
|
||||
|
|
|
|||
|
|
@ -1,65 +1,71 @@
|
|||
# wxWidgets DOM port (`feature/wx-dom-port`)
|
||||
|
||||
A second WASM build mode where wxWidgets widgets are **real HTML elements**
|
||||
THE wxWidgets WASM port: widgets are **real HTML elements**
|
||||
(`wxButton` → `<button>`, `wxTextCtrl` → `<input>`, menus → popup divs)
|
||||
instead of wxUniversal pixels on a canvas. Goals: styleable modern UI,
|
||||
native text input/IME, accessibility, crisp rendering — while the existing
|
||||
canvas port keeps working unchanged from the same source tree.
|
||||
instead of pixels on a canvas. Goals: styleable modern UI, native text
|
||||
input/IME, accessibility, crisp rendering.
|
||||
|
||||
Status: COMPLETE (Phases 0–7). wxWidgets-side port done, both wx e2e
|
||||
suites green from one tree, and all six KiCad apps (pcbnew, eeschema,
|
||||
calculator, pl_editor, symbol_editor, gerbview) build and run on the DOM
|
||||
port — full kicad e2e suite green under `WX_PORT=dom` (28/0, 1 flaky,
|
||||
2 skipped). Build with `WX_PORT=dom docker/build.sh <app>` (outputs in
|
||||
`output/dom/`); test with `WX_PORT=dom npm run test:kicad`. Work
|
||||
intentionally stays on `feature/wx-dom-port` (root + wxwidgets + kicad) —
|
||||
not merged to `main`/`wasm-port`.
|
||||
Status: COMPLETE and consolidated (2026-06-12). The original canvas
|
||||
(wxUniversal) mode and all dual-build plumbing have been **removed** —
|
||||
`--with-wasm` builds the DOM port, full stop. All `src/univ/` +
|
||||
`include/wx/univ/` modifications were reverted to upstream v3.2.6, so the
|
||||
wxwidgets fork is upstream + new `src/wasm/` + `include/wx/wasm/` +
|
||||
`build/wasm/` files + thin hooks. All six KiCad apps (pcbnew, eeschema,
|
||||
calculator, pl_editor, symbol_editor, gerbview) build and run on it.
|
||||
|
||||
Build: `docker/build.sh <app>` (outputs in `output/`), wx standalone via
|
||||
`scripts/build-wx-wasm.sh`, test apps via `scripts/build-wasm-test.sh`.
|
||||
Test: `npm test` / `npm run test:kicad` from `tests/` (no env vars).
|
||||
Work intentionally stays on `feature/wx-dom-port` (root + wxwidgets +
|
||||
kicad) — not merged to `main`/`wasm-port`.
|
||||
|
||||
## Architecture in one page
|
||||
|
||||
- **One toolkit, two modes.** `--with-wasm --enable-universal` = canvas
|
||||
(untouched); `--with-wasm` alone = DOM. Selection is file-level via the
|
||||
build system: `src/univ/` only in canvas builds, `WASM_SRC` (native
|
||||
controls) only under `WXUNIV_0`. Source of truth is
|
||||
`build/bakefiles/files.bkl` → dockerized bakefile regenerates
|
||||
`Makefile.in`/`autoconf_inc.m4` → autoconf regenerates `configure`
|
||||
(`scripts/build-wxuniversal-wasm.sh` auto-detects each stage's
|
||||
staleness; `--dom` flag selects the mode).
|
||||
- **C++ owns state; the DOM is a projection.** Controls call
|
||||
`WasmCreateDomNode("type")` once in `Create()`; the shared
|
||||
`wxWindowWasm` machinery then syncs geometry (TLW-relative absolute
|
||||
positioning, recursing into descendants), visibility
|
||||
(`IsShownOnScreen`, whole subtree), enabled/font/focus/destruction.
|
||||
DOM-native state (typed text, checked, selection) syncs back through
|
||||
events into C++ caches so getters stay synchronous.
|
||||
positioning, recursing into descendants; ancestor-viewport clipping via
|
||||
`clip-path`), visibility (`IsShownOnScreen`, whole subtree),
|
||||
enabled/font/focus/destruction. DOM-native state (typed text, checked,
|
||||
selection) syncs back through events into C++ caches so getters stay
|
||||
synchronous. NB: `GetScreenPosition()` is the CLIENT-AREA origin
|
||||
(`ClientToScreen(0,0)`), not the top-left — the projection subtracts
|
||||
`GetClientAreaOrigin()` (matters for wxNotebook's tab strip).
|
||||
- **Layout is wx sizers, not CSS.** DOM contributes intrinsic measurement
|
||||
only (clone-based, in an offscreen always-rendered host — sizers run
|
||||
before `Show()`); positions are written as absolute `left/top/w/h`.
|
||||
- **Events** flow element listener → `ccall('wx_dom_event')` →
|
||||
`domevents.cpp` routing table → virtual `wxWindowWasm::OnDomEvent` —
|
||||
the same direct-dispatch pattern as the port's mouse callbacks (proven
|
||||
against Asyncify-suspended modals). Keyboard arbitration: keystrokes go
|
||||
untouched to focused DOM editables (Escape excepted).
|
||||
against Asyncify-suspended modals). Document-level listeners forward
|
||||
mouse activity over DOM children into the wx hit-test pipeline
|
||||
(`wx_dom_mouse`); wheel events walk up the window hierarchy. Keyboard
|
||||
arbitration: keystrokes go untouched to focused DOM editables (Escape
|
||||
excepted).
|
||||
- **Canvas islands.** Owner-drawn/generic widgets (wxGrid, listctrl,
|
||||
tree, AUI, STC, calendar...) keep painting via the shared `dc.cpp`
|
||||
Canvas2D path inside per-window canvases; they render near-pixel-equal
|
||||
to the canvas port.
|
||||
Canvas2D path inside per-window canvases — the same architecture native
|
||||
ports use for owner-drawn widgets.
|
||||
- **Menus/toolbars** serialize C++→JS as JSON; popups are DOM divs;
|
||||
command ids route back via `wxDOM_EVENT_MENU`/`TOOL`. Menu titles,
|
||||
items, and tools register as rendered elements with the same
|
||||
type strings the canvas port uses, so registry-based e2e utilities work
|
||||
identically on both ports.
|
||||
command ids route back via `wxDOM_EVENT_MENU`/`TOOL`. The DOM-native
|
||||
wxNotebook renders a real tab strip (`<button role=tab>`).
|
||||
- **E2E registry.** `window.wxElementRegistry` (wx.js) carries element
|
||||
geometry for Playwright. wxWindow-level entries come from
|
||||
`src/wasm/window.cpp`; canvas-island content (grid cells, list rows,
|
||||
calendar dates, AUI parts...) is published from thin paint-site hooks
|
||||
that call helpers in `src/wasm/elementtracker.cpp`; DOM-native
|
||||
composites (tabs, menu items, tools, spin arrows, text fields) are
|
||||
mirrored by wx-dom.js. One contract for everything.
|
||||
|
||||
Key files: `wxwidgets/build/wasm/wx-dom.js` (the whole JS control layer),
|
||||
`wxwidgets/include/wx/wasm/private/dom.h` (C++→JS bridge),
|
||||
`wxwidgets/src/wasm/domevents.cpp` (event routing + bitmap data URLs),
|
||||
`wxwidgets/src/wasm/window.cpp` (DOM-backing machinery, guarded
|
||||
`#ifndef __WXUNIVERSAL__`).
|
||||
`wxwidgets/src/wasm/window.cpp` (DOM-backing machinery),
|
||||
`wxwidgets/src/wasm/elementtracker.cpp` (e2e registry bridge).
|
||||
|
||||
## What works (e2e-verified, WX_PORT=dom)
|
||||
## What works (e2e-verified)
|
||||
|
||||
Full `tests/e2e` suite green (256/0; canvas 263/0 from the same tree, its
|
||||
stable screenshot set byte-identical to the pre-feature reference).
|
||||
Full `tests/e2e` suite green; full kicad suite green.
|
||||
|
||||
- Native DOM: stattext, button (stock labels, default size), textctrl
|
||||
(single/multi/password, two-way sync, wxEVT_TEXT/_ENTER), checkbox,
|
||||
|
|
@ -67,8 +73,9 @@ stable screenshot set byte-identical to the pre-feature reference).
|
|||
togglebutton, gauge, slider, statline, statbox, statbmp (PNG data
|
||||
URLs), bitmap buttons, choice, listbox, editable combobox
|
||||
(input+datalist), checklistbox, spinbutton (drives generic wxSpinCtrl),
|
||||
menubar+menus, toolbar, tooltips (title attrs), dialogs (shared
|
||||
Asyncify ShowModal), frame bar geometry (univ-parity).
|
||||
notebook (DOM tab strip), menubar+menus, toolbar, tooltips (#wx-tooltip
|
||||
layer, island widgets included), dialogs (shared Asyncify ShowModal),
|
||||
frame bar geometry.
|
||||
- Canvas islands verified visually: AUI, calendar, virtual listctrl,
|
||||
grid, tree, propgrid, STC.
|
||||
|
||||
|
|
@ -78,19 +85,22 @@ stable screenshot set byte-identical to the pre-feature reference).
|
|||
sizing); bitmap-button vertical centering; checklistbox selection
|
||||
highlight; wxLB_SINGLE uses a multiple `<select>`; native scrollbars
|
||||
replace univ gutters.
|
||||
- Tracker hooks in `src/generic/`+aui/stc/propgrid are shared with the
|
||||
canvas port and stay until the canvas port retires (the DOM port itself
|
||||
doesn't need them — its controls register from creation + ARIA). The
|
||||
univ hooks die with univ automatically.
|
||||
- Element-registry hooks remain in `src/generic/` + aui/stc/propgrid as
|
||||
thin guarded one-liners (canvas islands have no per-item DOM, so tests
|
||||
need C++-fed geometry); everything heavier lives in
|
||||
`src/wasm/elementtracker.cpp`.
|
||||
|
||||
## Upstreaming surface (vs `wasm-port` base)
|
||||
## Fork surface (vs upstream wxWidgets v3.2.6)
|
||||
|
||||
8 commits, ~107 files: the port directory itself (new files), 35
|
||||
dispatch-header branches (2–4 lines each), build-system entries
|
||||
(bakefile-generated), one-line `prntbase.cpp` PostScript condition, and
|
||||
two genuine upstream bug fixes in the generic notebook
|
||||
(`tabg.cpp` uninitialized background brush; `notebook.cpp` first-page
|
||||
selection never syncing the tab view). Zero changes to univ/aui/stc.
|
||||
Upstream + new files (`src/wasm/`, `include/wx/wasm/`, `build/wasm/`),
|
||||
the `__WXWASM__` dispatch branches in `include/wx/*.h` (2–4 lines each),
|
||||
WASM toolkit registration in the build system (bakefile-generated),
|
||||
wasm-generic fixes in `src/common/`, a handful of unguarded island
|
||||
rendering tweaks in `src/generic/` (renderg/gridctrl/stattextg/msgdlgg/
|
||||
spinctlg/filedlgg), and thin `#ifdef __EMSCRIPTEN__` tracker shims at
|
||||
paint sites. `src/univ/`, `include/wx/univ/`, `src/generic/notebook.cpp`,
|
||||
`tabg.cpp`, `build/msw/`, `tests/makefile.vc` are byte-identical to
|
||||
upstream.
|
||||
|
||||
See `visual-notes.md` for the 15-bug log the cross-port screenshot
|
||||
See `visual-notes.md` for the full bug log the cross-port screenshot
|
||||
comparison protocol produced.
|
||||
|
|
|
|||
|
|
@ -184,3 +184,33 @@ User-reported pcbnew issues, all fixed and e2e-pinned
|
|||
25. Universal tooltip layer (#wx-tooltip div, 600 ms, hover hit-test
|
||||
driven) — island widgets (color swatches, visibility toggles) get
|
||||
KiCad's SetToolTip texts; title attrs replaced by aria-label.
|
||||
|
||||
## DOM-only consolidation (2026-06-12)
|
||||
|
||||
The canvas (wxUniversal) mode and dual-build plumbing were removed; the
|
||||
DOM port is THE WASM port. Rebuilding everything from clean surfaced
|
||||
three latent bugs (all pre-existing — verified by rebuilding the
|
||||
pre-consolidation tree, which failed identically):
|
||||
|
||||
26. The DOM projection treated GetScreenPosition() as the window's
|
||||
top-left; it is ClientToScreen(0,0) — the CLIENT-AREA origin. The
|
||||
first widget with a non-zero client origin (the DOM notebook's tab
|
||||
strip) rendered its whole box a strip-height too low, overlapping
|
||||
its own pages, and ComputeAncestorClip double-added the origin,
|
||||
clipping page content (dataview/grid/minimal buttons cut to
|
||||
slivers, clicks swallowed by the strip). This was bug-logged
|
||||
earlier as "tab-strip/content slight overlap" and believed
|
||||
cosmetic. Fixed in UpdateDomGeometryRecursive (+ eager strip
|
||||
re-measure + re-projection in wxNotebook::WasmRebuildTabs).
|
||||
27. The DOM port never mirrored spin arrows and text fields into the
|
||||
e2e registry (the canvas port published them from univ paint
|
||||
hooks, which died with univ). wx-dom.js now registers
|
||||
'spinbutton' (up/down) and 'textctrl' (singleline/multiline)
|
||||
rendered elements, and clears a control's mirrored entries on
|
||||
destroy.
|
||||
28. tests: clickCanvas() used locator.click(), whose actionability
|
||||
check refuses points covered by DOM elements — in the DOM port
|
||||
real widgets legitimately cover the canvas. It now dispatches via
|
||||
page.mouse. The minimal-app comprehensive spec drives the wxChoice
|
||||
through its native <select> (browsers own that popup; it cannot be
|
||||
coordinate-clicked).
|
||||
|
|
|
|||
Loading…
Reference in a new issue