Web-source bounding box: task COMPLETE and verified (creator: 'bounding is perfect') — docs updated, MyMistakes reset to stub, push in this commit
Root-cause note: the apparent remaining gap was a WIDGET GLOW EFFECT (the widget's own CSS glow pushed out its perceived borders), not a code bug — the alpha-bbox already hugged the glow halo. Verified perfect with a second widget without the effect.
This commit is contained in:
+22
-19
@@ -2,22 +2,25 @@
|
||||
|
||||
## Branch / Commit State
|
||||
|
||||
**`main`**, dirty working tree being committed as one unit (web source rendering fix — user-confirmed
|
||||
working). **NOT pushed — user rule: never push without explicit instruction (2026-08-24).** No feature
|
||||
branches pre-1.0: all work lands on `main` per work unit.
|
||||
**`main`**, working tree clean. Web-source bounding work is **DONE, verified, committed, and
|
||||
PUSHED (2026-08-28)** — the first push in a while; the web feature is complete and on origin.
|
||||
No feature branches pre-1.0: all work lands on `main` per work unit.
|
||||
|
||||
## The web-source rendering work (2026-08-28) — CURRENT MODEL: canvas-size viewport + ALPHA-BBOX crop
|
||||
## The web-source rendering work (2026-08-28) — DONE: canvas-size viewport + ALPHA-BBOX crop
|
||||
|
||||
**History of failures (see MyMistakes.md for the full log):** box-size rendering clipped full-bleed
|
||||
widgets to their upper-left chunk (fixed — page renders at the master canvas 1920×1080, stable, the
|
||||
one render the creator confirmed solid). Then four crop attempts failed in different ways: (1) the
|
||||
`JSON.stringify` return double-encoded under `ExecuteScriptAsync`, silently disabling the crop;
|
||||
(2) `scrollWidth/scrollHeight` at canvas size returns the whole viewport for full-canvas wrapper
|
||||
bodies → no trim (ghost boundary); (3) union-of-DOM-elements measured an unsettled layout on
|
||||
NavigationCompleted and BROKE the image (creator's "don't break the rendering" boundary crossed).
|
||||
(4) Reverting to f39ebd9's scroll-crop was another dead end (#2 again).
|
||||
**VERDICT (creator, 2026-08-28):** bounding is PERFECT. Verified with a second widget resource that
|
||||
has no glow effect. The earlier "remaining defect / dead-space gap" was the WIDGET'S OWN GLOW
|
||||
effect pushing out its perceived borders — NOT a code bug. The alpha-bbox was already hugging the
|
||||
glow halo; with a plain widget the dashed selection border sits exactly on the widget edge.
|
||||
|
||||
**The CURRENT MODEL (this commit):**
|
||||
**History of failures (log wiped from MyMistakes.md per task-complete rule; see git history):**
|
||||
box-size rendering clipped full-bleed widgets to their upper-left chunk; `JSON.stringify` return
|
||||
double-encoded under `ExecuteScriptAsync` (crop silently disabled); `scrollWidth/scrollHeight` at
|
||||
canvas size = whole viewport for full-canvas wrappers (no trim); DOM-element-union measured an
|
||||
unsettled layout on NavigationCompleted (BROKE the image); sizing the container to the crop
|
||||
(`ab29ec8`) made things worse (reverted).
|
||||
|
||||
**The model that shipped:**
|
||||
- `Services/WebView2Manager.cs` — page renders at 1920×1080 (stable, never tracked); `overflow:hidden`
|
||||
+ transparent-bg injection. `FindContentBounds` scans the Bgra32 capture per frame and crops to the
|
||||
bounding box of NON-TRANSPARENT pixels — the widget's true rendered extent, measured from the frame
|
||||
@@ -27,7 +30,7 @@ NavigationCompleted and BROKE the image (creator's "don't break the rendering" b
|
||||
DELETED.
|
||||
- `MainWindow.xaml` — web `<Image>` Stretch set to Fill via the IsWebSource DataTrigger (unchanged).
|
||||
- Invariant: **render at canvas size; crop to the alpha extent; Fill to the box.**
|
||||
- Unit tests: 3 new for `FindContentBounds` (tight box, no-alpha no-crop, full-alpha no-crop).
|
||||
- Unit tests: 7/7 (3 `FindContentBounds`, 4 control-size.)
|
||||
|
||||
**Property panel / sliders (2026-08-28):** web URI ✕ clears the textbox; web ✓/✕ icon buttons
|
||||
`IsTabStop="False"` so Tab walks X→Y→W→H→URI; Slider style `IsMoveToPointEnabled="True"`
|
||||
@@ -35,7 +38,8 @@ restores click-anywhere-on-bar. All three confirmed fixed by the creator.
|
||||
|
||||
Build: 0 warnings; tests 7/7 (WebView2Manager). Rejected for the record: box-sized viewport (upper-left
|
||||
truncation), fixed 1920×1080 + `Uniform` (letterbox dead space), CSS margin/100% reset (enlarged gap),
|
||||
viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image).
|
||||
viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image), container==content
|
||||
auto-fit sized to the crop (`ab29ec8`, reverted).
|
||||
|
||||
## Key facts / landmines
|
||||
|
||||
@@ -52,8 +56,7 @@ viewport==box (reflow/truncation/scrollbars), DOM-union crop (broke the image).
|
||||
- No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`.
|
||||
|
||||
## Next steps
|
||||
1. AWAIT creator's verdict on the ALPHA-BBOX crop — reload a widget URL at several box sizes; the
|
||||
selection frame must snap flush to the widget with no dead space, image must stay identical for
|
||||
full-bleed widgets. If an animated widget causes visible jitter, add crop hysteresis as a follow-up.
|
||||
2. Follow-up only if the creator asks: graceful handling of navigation errors / invalid URIs (TASK 17 ×9).
|
||||
1. Done (2026-08-28): web-source bounding verified PERFECT and pushed. If an animated widget causes
|
||||
visible crop jitter later, add hysteresis as a follow-up — not queued.
|
||||
2. Graceful handling of navigation errors / invalid URIs (TASK 17 ×9) — only if the creator asks.
|
||||
3. Continue queue: TASK 18 local recording, TASK 21 media source, TASK 22 audio sync offset.
|
||||
@@ -3,45 +3,3 @@
|
||||
> One task at a time. Updated before every commit touching that task: current iteration +
|
||||
> why the last one failed. On task complete, committed AND pushed → truncate to this stub.
|
||||
> A new task does NOT seed this file until its first failure.
|
||||
|
||||
## Task (active — committed `582d1f4`, NOT pushed, awaiting creator verification)
|
||||
Stream widget bounding box: hug the widget on all four sides, pinned to canvas (0,0).
|
||||
|
||||
## Iterations that failed
|
||||
1. **e917c41 — fixed 1920×1080 viewport + `Stretch="Uniform"` + startup registration.**
|
||||
Failed: `Uniform` letterboxed the 16:9 canvas into arbitrary‑sized boxes → asymmetric dead
|
||||
padding read as a "gap". Lesson: Fill the box with the cropped frame, never Uniform.
|
||||
2. **9d4103c — per‑document CSS reset (`html/body` width/height 100%) + (0,0) anchor.**
|
||||
Failed ("enlarged the gap"): forcing dimensions overrode the widget's own layout and expanded
|
||||
the dead space. Lesson: inject only `overflow:hidden` + transparent background — never set sizes.
|
||||
3. **8d793af — viewport == element‑box size + `Stretch="Fill"`.**
|
||||
Failed (janky / truncating / scrollbars): hosting at the box size clips full‑bleed widgets to
|
||||
their upper‑left chunk, and tracking the box reflows the page on drag. Lesson: render at a
|
||||
fixed canvas size, never track the box.
|
||||
4. **f39ebd9 — crop capture to `scrollWidth/scrollHeight` bounds + (0,0) + Fill.**
|
||||
Partially passed (panel fixes 1a/1b/4 confirmed) but the box stayed loose; the apparent
|
||||
"tight right/bottom" was just the small‑viewport clip edge. **ROOT CAUSE: the crop never ran.**
|
||||
The script returned `JSON.stringify(...)` (a string); `ExecuteScriptAsync` JSON‑encodes every
|
||||
result, so the JSON was double‑encoded → `JsonDocument.Parse` got a string node →
|
||||
`GetProperty` threw → try/catch swallowed → bounds unset → no crop. Lesson: return a real JS
|
||||
object, never a stringified one. Also: scroll extents ≠ widget rect (they include page margins).
|
||||
5. **70fe2b8 — fixed canvas‑size viewport (1920×1080) + crop + Fill.**
|
||||
Image render/resize became solid (creator confirmed) but the box still gapped right/bottom and
|
||||
wasn't 0,0. Same silent JSON bug — the crop still never executed — and the measure was scroll
|
||||
extents regardless. Lesson: verify declared mechanics actually execute; assume nothing ran.
|
||||
|
||||
## Current iteration (web bounding box — UNCOMMITTED, verification pending)
|
||||
ALPHA-BBOX CROP: `FindContentBounds` scans the captured Bgra32 frame and returns the bounding box
|
||||
of non-transparent pixels (the background is injected transparent, so alpha = the widget's extent).
|
||||
Capture is cropped to that rect and `Stretch="Fill"` maps it flush under the box. No DOM query, no
|
||||
layout timing — the crop rect IS the rendered widget by construction, so it can NEVER truncate
|
||||
visible content. Worst case (widget fills the canvas) = full frame = the confirmed-good render.
|
||||
Canvas-size viewport + Fill untouched. `QueryContentBoundsAsync` + the JS script are DELETED.
|
||||
|
||||
## Iteration that just failed (`a5b9952` — wrapper-excluded DOM-union crop + image alignment)
|
||||
Broke the image rendering — creator could not evaluate the box because the image was gone/ruined.
|
||||
Why: the visible-element-union rect is measured ONCE on NavigationCompleted; widget layout isn't
|
||||
settled then (async fonts/images, load animations, iframes), so the crop rect comes out tiny/wrong
|
||||
and the Fill-stretched frame renders a broken/zoomed sliver. This was against the creator's explicit
|
||||
"don't break the rendering" instruction. Lesson: measure actual RENDERED PIXELS (alpha), never
|
||||
transient DOM state; and never ship a crop blind.
|
||||
@@ -917,16 +917,21 @@ 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-BBOX crop — DONE, creator-verified):**
|
||||
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.
|
||||
the JS content-bounds script are DELETED. **RESULT: bounding verified PERFECT by the creator with
|
||||
two widgets.** Root-cause note on the earlier "remaining defect/gap": that was a WIDGET GLOW EFFECT
|
||||
(the widget's own CSS glow pushes out its perceived borders), not a code bug — the alpha-bbox was
|
||||
already hugging the glow halo. Lesson: test with a second, plain widget before changing code.
|
||||
⚠️ Lesson bank: never return `JSON.stringify` from `ExecuteScriptAsync` (double-encodes); never
|
||||
measure DOM stuff on NavigationCompleted (unsettled layout broke the image — `a5b9952`); avoid
|
||||
sizing the container to the crop (`ab29ec8` reverted — made it worse); a widget glow effect can
|
||||
fake a gap — verify with a plain widget first; 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).
|
||||
|
||||
Reference in New Issue
Block a user