Web source: off-screen WebView2 capture + layout persistence + transparent bg
Bundle exception (2026-08-27): this lands prior-session work plus today's transparency fix as one commit per creator instruction. WebView2Manager (new): off-screen WebView2 control parked at -5000/-5000 in the window's visual tree, captures via CapturePreviewAsync every 100 ms into a BGRA8 VideoFrame. Source Width/Height sync to the control via PropertyChanged. JS transparent-background injection runs on every NavigationStarting/NavigationCompleted so the page's own CSS does not paint white over the capture. Transparency fix: DefaultBackgroundColor = System.Drawing.Color.Transparent set on the WPF control before EnsureCoreWebView2Async. The WPF SDK doc says the value is forwarded to the controller on init; the IDL (ICoreWebView2- Controller2) confirms alpha=0 makes the capture alpha-preserving. The prior-session 'CoreWebView2.BackgroundColor' path was the wrong property name and has been replaced. LayoutStore: WebUri column added (idempotent ALTER TABLE) and round-tripped on save/load (schema v11). MainViewModel: WebView2Manager constructed on Loaded; loaded web sources re-registered; Source.WebUri PropertyChanged forwards to manager. MainWindow: off-screen host Canvas added to visual tree. Tests: 3 scale-sync + WebView2_DefaultBackgroundColor_Is_Transparent + LayoutStorePersistenceTests.WebSource_WebUri_Persists. 234/236 pass (2 pre-existing failures unchanged). Scale bug (DPI/physical-pixel mismatch) still open.
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Threading;
|
||||
using Microsoft.Web.WebView2.Wpf;
|
||||
using Xunit;
|
||||
using ytLive.Models;
|
||||
using ytLive.Services;
|
||||
|
||||
namespace ytLive.Tests;
|
||||
|
||||
[Collection("RealApp")]
|
||||
public sealed class WebView2ManagerTests
|
||||
{
|
||||
private readonly RealAppHost _app;
|
||||
|
||||
public WebView2ManagerTests(RealAppHost app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebView2_Control_Size_Tracks_Source_Dimensions()
|
||||
{
|
||||
_app.Run(() =>
|
||||
{
|
||||
var panel = new Canvas();
|
||||
var source = new Source
|
||||
{
|
||||
Type = SourceType.WebSource,
|
||||
Width = 640,
|
||||
Height = 480,
|
||||
};
|
||||
|
||||
using var manager = new WebView2Manager(panel, Dispatcher.CurrentDispatcher);
|
||||
manager.Register(source);
|
||||
|
||||
var webView = panel.Children.OfType<WebView2>().First();
|
||||
Assert.Equal(640.0, webView.Width);
|
||||
Assert.Equal(480.0, webView.Height);
|
||||
|
||||
source.Width = 1024;
|
||||
source.Height = 768;
|
||||
|
||||
Assert.Equal(1024.0, webView.Width);
|
||||
Assert.Equal(768.0, webView.Height);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebView2_Control_Size_Does_Not_Drift_On_Minor_Rounding()
|
||||
{
|
||||
_app.Run(() =>
|
||||
{
|
||||
var panel = new Canvas();
|
||||
var source = new Source
|
||||
{
|
||||
Type = SourceType.WebSource,
|
||||
Width = 640,
|
||||
Height = 480,
|
||||
};
|
||||
|
||||
using var manager = new WebView2Manager(panel, Dispatcher.CurrentDispatcher);
|
||||
manager.Register(source);
|
||||
|
||||
var webView = panel.Children.OfType<WebView2>().First();
|
||||
|
||||
source.Width = 640.4;
|
||||
Assert.Equal(640.0, webView.Width);
|
||||
|
||||
source.Height = 480.4;
|
||||
Assert.Equal(480.0, webView.Height);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebView2_Control_Size_Minimum_Is_One()
|
||||
{
|
||||
_app.Run(() =>
|
||||
{
|
||||
var panel = new Canvas();
|
||||
var source = new Source
|
||||
{
|
||||
Type = SourceType.WebSource,
|
||||
Width = 640,
|
||||
Height = 480,
|
||||
};
|
||||
|
||||
using var manager = new WebView2Manager(panel, Dispatcher.CurrentDispatcher);
|
||||
manager.Register(source);
|
||||
|
||||
var webView = panel.Children.OfType<WebView2>().First();
|
||||
|
||||
source.Width = 0;
|
||||
source.Height = 0;
|
||||
|
||||
Assert.Equal(1.0, webView.Width);
|
||||
Assert.Equal(1.0, webView.Height);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WebView2_DefaultBackgroundColor_Is_Transparent()
|
||||
{
|
||||
_app.Run(() =>
|
||||
{
|
||||
var panel = new Canvas();
|
||||
var source = new Source
|
||||
{
|
||||
Type = SourceType.WebSource,
|
||||
Width = 640,
|
||||
Height = 480,
|
||||
};
|
||||
|
||||
using var manager = new WebView2Manager(panel, Dispatcher.CurrentDispatcher);
|
||||
manager.Register(source);
|
||||
|
||||
var webView = panel.Children.OfType<WebView2>().First();
|
||||
|
||||
Assert.Equal(System.Drawing.Color.Transparent, webView.DefaultBackgroundColor);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user