Web source: container == content — element grid + selection box sized to the cropped frame's canvas extent

- FindContentBounds already trimmed the bitmap; the grid/box still rendered at the uncropped user
  size, so Fill stretched the tight widget into a bigger frame = dead-between-content-and-border.
- ContentCanvasSize maps the crop rect to canvas units (1920/pixW per axis, DPI-correct) and the
  preview event now carries (bitmap, canvasW, canvasH).
- OnWebView2PreviewBitmapChanged sets the element Width/Height to that size; the grid and the
  SelectionOverlay (both bound to the element's Width/Height) now equal the widget exactly.
- IsPreviewDragging (set in MainWindow drag/resize) suppresses auto-fit mid-gesture.
- Tests 10/10 (alpha bounds, canvas-size mapping incl. DPI, control size); 0 warnings.
This commit is contained in:
2026-08-28 12:08:04 -07:00
parent bccdb4892c
commit ab29ec801d
7 changed files with 103 additions and 51 deletions
+10 -7
View File
@@ -917,16 +917,19 @@ 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 + ALPHA-BBOX crop):**
**Rendering model (2026-08-28, canvas-size viewport + alpha crop + CONTAINER==CONTENT):**
the page renders at the MASTER CANVAS size (1920×1080), stable, never tracked (no reflow/truncation;
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.
frame itself (NO DOM query, immune to layout timing, can never truncate content; full-canvas widgets
fall through to the full frame). `ContentCanvasSize` maps the cropped pixel rect to canvas units
(DPI-correct); `MainViewModel.OnWebView2PreviewBitmapChanged` sizes the element's Width/Height to it —
so the element grid AND the SelectionOverlay (both bound to the element's Width/Height) equal the
widget exactly. Auto-fit suppressed while dragging (`IsPreviewDragging`). `Stretch="Fill"` is now
~1:1; no cropped bitmap is stretched into a larger frame.
⚠️ Lesson bank: never return `JSON.stringify` from `ExecuteScriptAsync` (double-encodes); never
measure DOM on NavigationCompleted (unsettled layout broke the image — `a5b9952`); fixing the
bitmap crop without sizing the container leaves the gap (— `bccdb48`).
**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).