diff --git a/MainWindow.xaml b/MainWindow.xaml
index db18f9f..8a46848 100644
--- a/MainWindow.xaml
+++ b/MainWindow.xaml
@@ -857,12 +857,6 @@
-
-
-
-
diff --git a/MyMistakes.md b/MyMistakes.md
index 77e84bb..784cf93 100644
--- a/MyMistakes.md
+++ b/MyMistakes.md
@@ -31,18 +31,15 @@ Stream widget bounding box: hug the widget on all four sides, pinned to canvas (
extents regardless. Lesson: verify declared mechanics actually execute; assume nothing ran.
## Current iteration (web bounding box — UNCOMMITTED, verification pending)
-Render stays the confirmed-solid 1920×1080 canvas-size viewport + `Stretch="Fill"` (UNTOUCHED).
-Crop now uses the WIDGET rect, not scroll extents: union of every visible element's
-`getBoundingClientRect`, EXCLUDING elements spanning ≥98% of the viewport (bodies,
-full-canvas background layers — they are wrappers, not content). Crop is taken AT the
-rect's top-left (l,t) so content pins to bitmap (0,0). Web Image explicitly
-`Margin="0"` + `HorizontalAlignment="Left"`/`VerticalAlignment="Top"`.
+RENDER RESTORED to the last creator-verified-good state (`70fe2b8`): full-frame capture (no crop),
+1920×1080 canvas-size viewport, plain `Stretch="Fill"`. Image rendering is back to "renders and
+resizes beautifully". The bounding-box dead-space problem is STILL OPEN — do NOT reintroduce any
+crop until the creator explicitly approves the approach.
-## Iteration that just failed (`b862a0f` — reverted to f39ebd9's scrollWidth/Height crop)
-Creator still saw a massive "ghost" frame around the visible widget. Root cause: for widgets
-whose body/background spans the full 1920×1080 canvas, `scrollWidth/scrollHeight` returns the
-WHOLE viewport → the crop keeps massive transparent margins → dead space inside the bitmap →
-content floats inside the Fill-stretched box. So the earlier "nailed right/bottom" (f39ebd9) was
-only right for box-sized viewports: at the canvas size, scroll extents == viewport for full-canvas
-wrappers. Lesson: never trust scrollWidth/scrollHeight at canvas-size render; measure visible
-content and exclude full-viewport wrappers/backgrounds.
\ No newline at end of file
+## Iteration that just failed (`a5b9952` — wrapper-excluded content-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: the canvas-size render + Fill is the ONLY verified
+good base; any crop must be built on it one tested step at a time, never shipped blind.
\ No newline at end of file
diff --git a/Services/WebView2Manager.cs b/Services/WebView2Manager.cs
index f3854d7..7a2ec62 100644
--- a/Services/WebView2Manager.cs
+++ b/Services/WebView2Manager.cs
@@ -29,8 +29,6 @@ public sealed class WebView2Manager : IDisposable
public VideoFrame? LatestFrame;
public double ViewportCssW;
public double ViewportCssH;
- public double ContentCssX;
- public double ContentCssY;
public double ContentCssW;
public double ContentCssH;
public bool Disposed;
@@ -161,63 +159,25 @@ public sealed class WebView2Manager : IDisposable
catch (Exception ex) { AppLog.Write($"WebView2Manager: navigate failed: {ex.Message}"); }
}
- // The true widget rect for the crop. scrollWidth/scrollHeight is useless for
- // widgets whose body/background spans the full 1920×1080 canvas — it returns
- // the whole viewport, so the crop keeps massive transparent margins and the
- // rendered bitmap floats inside the Fill-stretched box ("ghost boundary").
- // Fix: union the getBoundingClientRect of every visible element, EXCLUDING
- // elements that span (nearly) the full viewport — bodies and full-canvas
- // background/overlay layers are layout wrappers, not widget content. If the
- // exclusion empties the set, the widget IS full-bleed: use the full rect.
- // Returned as a real JS object (NOT JSON.stringify — ExecuteScriptAsync
- // JSON-encodes the result, so stringifying would double-encode and the
- // parse would throw, silently disabling the crop).
- private const string ContentBoundsScript =
- "(function(){" +
- "var vw=window.innerWidth||1,vh=window.innerHeight||1;" +
- "var all=[];var body=document.body;" +
- "if(body){var br=body.getBoundingClientRect();if(br.width||br.height)all.push(br);" +
- "var els=body.querySelectorAll('*');" +
- "for(var i=0;i=vw*0.98&&rr.height>=vh*0.98)continue;" +
- "content.push(rr);" +
- "}" +
- "var use=content.length?content:all;" +
- "var l=use[0].left,t=use[0].top,rt=use[0].right,bt=use[0].bottom;" +
- "for(var k=1;k= 1 && session.ViewportCssH >= 1 &&
session.ContentCssW >= 1 && session.ContentCssH >= 1)
{
var sx = pixW / session.ViewportCssW;
var sy = pixH / session.ViewportCssH;
- cropX = (int)Math.Clamp(Math.Round(session.ContentCssX * sx), 0, pixW - 1);
- cropY = (int)Math.Clamp(Math.Round(session.ContentCssY * sy), 0, pixH - 1);
- cropW = (int)Math.Clamp(Math.Round(session.ContentCssW * sx), 1, pixW - cropX);
- cropH = (int)Math.Clamp(Math.Round(session.ContentCssH * sy), 1, pixH - cropY);
+ cropW = (int)Math.Clamp(Math.Round(session.ContentCssW * sx), 1, pixW);
+ cropH = (int)Math.Clamp(Math.Round(session.ContentCssH * sy), 1, pixH);
}
var outPixels = pixels;
- if (cropW != pixW || cropH != pixH || cropX != 0 || cropY != 0)
+ if (cropW != pixW || cropH != pixH)
{
var dstStride = cropW * 4;
outPixels = new byte[dstStride * cropH];
for (var r = 0; r < cropH; r++)
- Buffer.BlockCopy(pixels, (cropY + r) * stride + cropX * 4, outPixels, r * dstStride, dstStride);
+ Buffer.BlockCopy(pixels, r * stride, outPixels, r * dstStride, dstStride);
}
var wb = new WriteableBitmap(cropW, cropH, 96, 96, PixelFormats.Bgra32, null);
diff --git a/TASKS.md b/TASKS.md
index fc9f14e..3983441 100644
--- a/TASKS.md
+++ b/TASKS.md
@@ -917,17 +917,14 @@ 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 + wrapper-safe content-rect crop):**
+**Rendering model (2026-08-28, canvas-size viewport, NO crop — the only creator-verified state):**
the page renders at the MASTER CANVAS size (1920×1080), stable, never tracked (no reflow/truncation;
-scrollbars suppressed via `overflow:hidden`). After each navigation the manager measures the WIDGET
-rect — union of every visible element's `getBoundingClientRect`, EXCLUDING elements that span
-≥98% of the viewport (bodies, full-canvas background/overlay layers are layout wrappers, not
-content; full-bleed widgets fall back to the full rect) — and crops the capture AT that rect's
-top-left (l,t), pinning the widget to the bitmap's (0,0). `Stretch="Fill"` (+ explicit `Margin=0`,
-Left/Top alignment) maps the frame flush under the box: the selection box bounds the widget tight
-on all four sides, no dead space. ⚠️ `ExecuteScriptAsync` JSON-encodes the returned value — the
-script must return a real OBJECT (not `JSON.stringify`, which double-encodes → parse exception →
-crop silently skipped). Graceful-error handling (item 9) is a follow-up.
+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.
**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).