Web source: geometry-agnostic viewport==box model — viewport locked to element box, Stretch=Fill, no dead space

This commit is contained in:
2026-08-28 10:48:53 -07:00
parent 9d4103c44b
commit 8d793af91a
5 changed files with 121 additions and 82 deletions
+27 -21
View File
@@ -6,28 +6,34 @@
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.
## The web-source rendering fix (2026-08-28) — USER-CONFIRMED WORKING
## The web-source rendering work (2026-08-28) — CURRENT MODEL: viewport == element box
**The bug:** preloaded web resources rendered truncated (upper-left only) and misbehaved as the box
resized. The WebView2 control was being resized to the element box as it changed.
**Background:** the fixed-viewport fix (1920×1080 control + `Stretch="Uniform"`) made the page
render without truncation but left dead space between the selection box and the content (box
aspect ≠ capture aspect → letterbox; box is sized by the parent layout, capture is a separate
hardcoded viewport — they bind to different rects). A CSS-reset experiment made the gap worse
and was shelved by the creator. He stressed the systems must be GEOMETRY-AGNOSTIC: no 16:9,
no fixed render size, no per-widget assumptions.
**The fix — one idea, three-line change, the OBS/CEF pattern:**
- `Services/WebView2Manager.cs` — viewport is FIXED at the master canvas size (1920×1080), never
tracks the box. Control lives off-screen at (-5000,-5000). Page renders full at its designed size;
the preview scales the captured frame independently via `<Image Stretch="Uniform">`. This is what
OBS obs-browser does (fixed-viewport texture + independent scene-item scale). Removed the
PropertyChanged resize hook. Added an immediate `CaptureFrame` on `NavigationCompleted` so content
appears instantly on load (was waiting for the next 100ms tick).
- `ViewModels/MainViewModel.cs` — `InitWebView2` now calls `RegisterLoadedWebSources()` itself;
before, registration only happened when `LoadLayout` ran after manager init, so preloaded sources
never registered at startup.
- `MainWindow.xaml` — scene-element `<Image>` had a LOCAL `Stretch="UniformToFill"` that outranked
the Style DataTrigger (WPF precedence). Removed the local attribute; Style default is
`UniformToFill`; `IsWebSource` trigger overrides to `Stretch="Uniform"` (no crop/truncation).
- `ytLive.Tests/WebView2ManagerTests.cs` — 3 scale-sync tests tested the removed behavior; replaced
with 2 tests asserting the fixed 1920×1080 viewport and that it does not track source dimensions.
**The model that delivers it (implemented, needs visual verification):**
- `Services/WebView2Manager.cs` — the WebView2 viewport IS the element box
(`Source.Width × Source.Height`). The page renders at exactly the box size; a `PropertyChanged`
hook keeps the viewport locked to the box (re-triggers capture on resize, sub-0.5px drift is
ignored). `CaptureFrame` is unchanged (aspect-preserving Physical-size capture).
- `MainWindow.xaml` — web `<Image>` uses `Stretch="Fill"` (capture aspect == box aspect by
construction, so Fill == Uniform with zero dead space; during a transient stale frame it just
holds aspect briefly). Everything else still `UniformToFill`.
- Selection rect == content rect by construction → flush edges, no padding, works for any widget
geometry the creator throws at it. FramePump still reads `GetLatestFrame` via `ResolveOutputFrame`.
- Transparent-background JS injection retained (background only — no layout/CSS-reset meddling).
Build: 0 warnings, 0 errors. User verified it renders correctly.
Build: 0 warnings; WebView2Manager tests 4/4 (size tracks source, sub-pixel drift ignored,
minimum 1, transparent bg).
**Landmines (earlier attempts — do not repeat):** fixed-viewport (letterbox dead space),
CSS reset/margin juggling (enlarged the gap), control-tracking-box combined with
`UniformToFill` display (truncation), ZoomFactor meddling. The working invariant is:
**viewport rect == selection rect, display = Fill.**
## Key facts / landmines
@@ -44,7 +50,7 @@ Build: 0 warnings, 0 errors. User verified it renders correctly.
- No `CODING.md`; conventions live in `AGENTS.md` + `ai.md`.
## Next steps
1. Await creator comments on the committed rendering fix; address what he raises; also testing
the box-vs-content padding fix (CSS reset + (0,0) anchor) just committed.
1. AWAIT creator's verdict on viewport==box (geometry-agnostic) rendering — visual check with a
widget URL at several box sizes; the selection frame must snap flush with no padding.
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.