Web source: crop to the frame's ALPHA bounding box — the widget's true rendered extent, no DOM timing, can't break the render

- FindContentBounds scans the Bgra32 capture for the bounding box of non-transparent pixels
  (background is injected transparent, so alpha = widget extent). Crop to that rect + Stretch=Fill
  maps the widget flush under the selection box: full-canvas widgets fall through to the full frame
  (identical to the confirmed-good image); floating widgets get tight-fitted with no dead space.
- Removes QueryContentBoundsAsync + the JS script entirely — the DOM-union attempt (a5b9952) broke
  rendering by measuring an unsettled layout on NavigationCompleted; alpha measurement is immune.
- 3 new unit tests: tight box, no-alpha no-crop, full-alpha no-crop. 7/7 pass, 0 warnings.
This commit is contained in:
2026-08-28 11:53:36 -07:00
parent 5348b5c480
commit bccdb4892c
5 changed files with 117 additions and 80 deletions
+9 -7
View File
@@ -917,14 +917,16 @@ capturing the primary display (which causes the infinity mirror effect).
8. ✅ Preview shows live web content (not just a blank rectangle)
9. ☐ Handle navigation errors, invalid URIs, timeout gracefully
**Rendering model (2026-08-28, canvas-size viewport, NO crop — the only creator-verified state):**
**Rendering model (2026-08-28, canvas-size viewport + ALPHA-BBOX crop):**
the page renders at the MASTER CANVAS size (1920×1080), stable, never tracked (no reflow/truncation;
scrollbars suppressed via `overflow:hidden`). Capture is the FULL frame; `Stretch="Fill"` maps it
under the box. Image rendering verified good ("renders and resizes beautifully"). WEB BOX DEAD SPACE
STILL OPEN: previous cropping attempts all failed (JSON double-encode silently disabled the crop;
scrollWidth returns the full canvas for full-canvas wrappers; content-union measured an unsettled
layout on NavigationCompleted and BROKE the image). Any further crop needs creator approval first.
⚠️ `ExecuteScriptAsync` JSON-encodes the returned value — never return `JSON.stringify` from script.
scrollbars suppressed via `overflow:hidden`). `FindContentBounds` scans the Bgra32 capture and crops
to the bounding box of non-transparent pixels — the widget's true rendered extent, measured from the
frame itself (NO DOM query, immune to layout timing; can never truncate content; full-canvas widgets
fall through to the full frame = prior verified-good image). `Stretch="Fill"` maps the cropped frame
flush under the selection box → box hugs the widget on all four sides. `QueryContentBoundsAsync` +
the JS content-bounds script are DELETED. ⚠️ Lesson bank: never return `JSON.stringify` from
`ExecuteScriptAsync` (double-encodes); never measure DOM stuff on NavigationCompleted (unsettled
layout broke the image — `a5b9952`); measure rendered pixels instead.
**Properties panel (2026-08-28):** web URI ✓/✕ icon buttons are `IsTabStop="False"` so Tab flows
X→Y→W→H→URI; the ✕ button now clears the URI textbox (was reverting to the pre-accept snapshot).