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
|
## Branch / Commit State
|
||||||
|
|
||||||
**`main`**, dirty working tree being committed as one unit (web source rendering fix — user-confirmed
|
**`main`**, working tree clean. Web-source bounding work is **DONE, verified, committed, and
|
||||||
working). **NOT pushed — user rule: never push without explicit instruction (2026-08-24).** No feature
|
PUSHED (2026-08-28)** — the first push in a while; the web feature is complete and on origin.
|
||||||
branches pre-1.0: all work lands on `main` per work unit.
|
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
|
**VERDICT (creator, 2026-08-28):** bounding is PERFECT. Verified with a second widget resource that
|
||||||
widgets to their upper-left chunk (fixed — page renders at the master canvas 1920×1080, stable, the
|
has no glow effect. The earlier "remaining defect / dead-space gap" was the WIDGET'S OWN GLOW
|
||||||
one render the creator confirmed solid). Then four crop attempts failed in different ways: (1) the
|
effect pushing out its perceived borders — NOT a code bug. The alpha-bbox was already hugging the
|
||||||
`JSON.stringify` return double-encoded under `ExecuteScriptAsync`, silently disabling the crop;
|
glow halo; with a plain widget the dashed selection border sits exactly on the widget edge.
|
||||||
(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).
|
|
||||||
|
|
||||||
**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`
|
- `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
|
+ 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
|
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.
|
DELETED.
|
||||||
- `MainWindow.xaml` — web `<Image>` Stretch set to Fill via the IsWebSource DataTrigger (unchanged).
|
- `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.**
|
- 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
|
**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"`
|
`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
|
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),
|
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
|
## 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`.
|
- No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`.
|
||||||
|
|
||||||
## Next steps
|
## Next steps
|
||||||
1. AWAIT creator's verdict on the ALPHA-BBOX crop — reload a widget URL at several box sizes; the
|
1. Done (2026-08-28): web-source bounding verified PERFECT and pushed. If an animated widget causes
|
||||||
selection frame must snap flush to the widget with no dead space, image must stay identical for
|
visible crop jitter later, add hysteresis as a follow-up — not queued.
|
||||||
full-bleed widgets. If an animated widget causes visible jitter, add crop hysteresis as a follow-up.
|
2. Graceful handling of navigation errors / invalid URIs (TASK 17 ×9) — only if the creator asks.
|
||||||
2. Follow-up only if the creator asks: graceful handling of navigation errors / invalid URIs (TASK 17 ×9).
|
|
||||||
3. Continue queue: TASK 18 local recording, TASK 21 media source, TASK 22 audio sync offset.
|
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 +
|
> 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.
|
> 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.
|
> 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)
|
8. ✅ Preview shows live web content (not just a blank rectangle)
|
||||||
9. ☐ Handle navigation errors, invalid URIs, timeout gracefully
|
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;
|
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
|
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
|
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
|
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
|
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` +
|
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
|
the JS content-bounds script are DELETED. **RESULT: bounding verified PERFECT by the creator with
|
||||||
`ExecuteScriptAsync` (double-encodes); never measure DOM stuff on NavigationCompleted (unsettled
|
two widgets.** Root-cause note on the earlier "remaining defect/gap": that was a WIDGET GLOW EFFECT
|
||||||
layout broke the image — `a5b9952`); measure rendered pixels instead.
|
(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
|
**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).
|
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