feat: web sources frame-captured via composition (CoreWebView2CompositionController → Windows.Graphics.Capture); PNG poll + CaptureScheduler deleted
The ~30Hz CapturePreviewAsync PNG poll capped real cadence at ~20Hz (35–165ms full-HD encode+decode), so a 60fps widget still juddered at ~1/6 speed. Replaced polling with frame-driven capture of the composition controller's root visual — the mechanism WebView2CompositionControl and Flutter's webview_windows use (graphics_context.cc captures the root surface_ visual via CreateGraphicsCaptureItemFromVisual; reference: github.com/microsoft/Windows.UI.Composition.WinUI / flutter-internal webview_windows). Frames now arrive at the renderer's own pace; capture memory is epoch'd ring reuse + one crop-sized shared WriteableBitmap. New Services/WebCaptureFrameSource.cs owns GraphicsCaptureItem + free- threaded Direct3D11CaptureFramePool + session (Straight alpha readback, per-frame FindContentBounds → CropBounds). WebView2Manager reworked around per-session composition controllers + one UI-thread Compositor created via the CoreMessaging CreateDispatcherQueueController P/Invoke (the 19041 projection lacks CreateOnCurrentThread); internal seam ctor (Dispatcher, Func<string,IScreenCaptureSource>?) for hermetic tests. CaptureScheduler.cs deleted; the three SetCaptureInterval cadence hooks removed; InitWebView2() moved from MainWindow ctor to Loaded (a parent HWND must exist for the composition controller); the hidden WebViewHostPanel overlay deleted. TransparentBackgroundScript unchanged. Tests: WebView2ManagerTests reworked — 4 control-size + scheduler tests dropped, FindContentBounds tests moved to WebCaptureFrameSource, ONE integration test (Frames_PublishCroppedPreview_And_CoalesceToLatest_CarryingCropBounds) drives the seam with a FakeWebSource + background-STA DispatcherPump. Suite 293/293, 0 warnings. NOTE: composition path NOT yet verified on a device — the take is the next step. Web work committed locally only (no push per standing rule). Docs same-commit: ai.md Slice 14 + supersede marker on Slice 11, HANDOFF, MyMistakes (CoreMessaging DQ + namespace-landmine recipe), TASK 17, Controls/ViewModels/Services indexes.
This commit is contained in:
@@ -84,10 +84,11 @@ public sealed class RoundClipInteractionTests
|
||||
// of PreviewGrid); otherwise Window_PreviewMouseLeftButtonDown
|
||||
// deselects the source and the handle can never be grabbed.
|
||||
// UIElement.InputHitTest IS the input pipeline — what Mouse uses.
|
||||
// Do NOT use VisualTreeHelper.HitTest here: it returned the window's
|
||||
// non-hit-testable WebViewHostPanel overlay for EVERY point (it does
|
||||
// not model IsHitTestVisible input semantics) — the bug this test
|
||||
// "found" for months was this wrong API (root-caused 2026-09-01).
|
||||
// Do NOT use VisualTreeHelper.HitTest here: it ignores IsHitTestVisible
|
||||
// input semantics (the old invisible WebView2 host overlay for web
|
||||
// sources used to win every visual hit — the wrong-API false bug this
|
||||
// test "found" for months, root-caused 2026-09-01; the overlay is gone
|
||||
// with the composition-based web render but the API lesson stays).
|
||||
var hit = window.InputHitTest(cornerInWindow) as DependencyObject;
|
||||
var grabbable = hit != null && IsDescendantOf(hit, previewGrid);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user