c01206fb8a
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.
106 lines
4.3 KiB
XML
106 lines
4.3 KiB
XML
<Window x:Class="ytLive.MainWindow"
|
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
|
xmlns:vm="clr-namespace:ytLive.ViewModels"
|
|
xmlns:models="clr-namespace:ytLive.Models"
|
|
xmlns:Helpers="clr-namespace:ytLive.Helpers"
|
|
xmlns:controls="clr-namespace:ytLive.Controls"
|
|
xmlns:notifications="clr-namespace:Notification.Wpf.Controls;assembly=Notification.Wpf"
|
|
mc:Ignorable="d"
|
|
Title="{Binding WindowTitle}" Height="1040" Width="1920"
|
|
MinWidth="1366" MinHeight="768"
|
|
Icon="/ytLive;component/Assets/llamacasty-icon.png"
|
|
Background="#1a1a2e"
|
|
WindowStartupLocation="Manual"
|
|
Closing="MainWindow_Closing"
|
|
Loaded="MainWindow_Loaded"
|
|
Activated="MainWindow_Activated"
|
|
Deactivated="MainWindow_Deactivated"
|
|
PreviewMouseLeftButtonDown="Window_PreviewMouseLeftButtonDown"
|
|
ContextMenuOpening="Window_ContextMenuOpening">
|
|
|
|
<Window.DataContext>
|
|
<vm:MainViewModel/>
|
|
</Window.DataContext>
|
|
|
|
<Window.TaskbarItemInfo>
|
|
<TaskbarItemInfo x:Name="TaskbarInfo"/>
|
|
</Window.TaskbarItemInfo>
|
|
|
|
<Window.Resources>
|
|
<ResourceDictionary>
|
|
|
|
<!-- Red dot shown in the taskbar icon while live -->
|
|
<DrawingImage x:Key="LiveOverlay">
|
|
<DrawingImage.Drawing>
|
|
<DrawingGroup>
|
|
<GeometryDrawing Brush="#e94560">
|
|
<GeometryDrawing.Geometry>
|
|
<EllipseGeometry Center="8,8" RadiusX="8" RadiusY="8"/>
|
|
</GeometryDrawing.Geometry>
|
|
</GeometryDrawing>
|
|
</DrawingGroup>
|
|
</DrawingImage.Drawing>
|
|
</DrawingImage>
|
|
|
|
<!-- EyeButton/EyeIconStyle MOVED to Themes/Controls.xaml (2026-09-01): Controls/
|
|
LeftPanel.xaml consumes them via StaticResource, and window-scope resources
|
|
are invisible to a UserControl at parse time — the "known test failure" that
|
|
was actually an app-crash regression from the LeftPanel extraction. -->
|
|
</ResourceDictionary>
|
|
</Window.Resources>
|
|
|
|
<Grid>
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- ═══ TOP BAR: Stream Controls ═══ -->
|
|
<Border Grid.Row="0" Background="{Binding TopBarBackground}" Padding="16,10">
|
|
<controls:TopBar x:Name="TopBar"/>
|
|
</Border>
|
|
|
|
<!-- ═══ MIDDLE: Main Content ═══ -->
|
|
<controls:HealthBanner Grid.Row="1"/>
|
|
|
|
<Grid Grid.Row="2" Margin="8">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="1*" MinWidth="220" MaxWidth="360"/>
|
|
<ColumnDefinition Width="3*"/>
|
|
</Grid.ColumnDefinitions>
|
|
|
|
<!-- ═══ THUMBNAIL STRIP ═══ -->
|
|
<controls:SceneThumbnailStrip Grid.Row="0" Grid.ColumnSpan="2"/>
|
|
|
|
<!-- LEFT PANEL: one panel, two states.
|
|
Offline (edit mode): LAYERS + PROPERTIES
|
|
Live/Recording: YouTube Live Chat -->
|
|
<controls:LeftPanel x:Name="LeftPanel" Grid.Row="1" Grid.Column="0"/>
|
|
|
|
|
|
<!-- CENTER: Preview Area -->
|
|
<controls:PreviewPane x:Name="PreviewPane" Grid.Row="1" Grid.Column="1"/>
|
|
</Grid>
|
|
|
|
|
|
<controls:BottomBar Grid.Row="3"/>
|
|
<!-- ═══ OVERLAY: Settings / Bug / Feature / About ═══ -->
|
|
<controls:OverlayHost Grid.RowSpan="3"/>
|
|
|
|
<!-- ═══ TOASTS: non-blocking notifications (bottom-right, above footer) ═══ -->
|
|
<notifications:NotificationArea x:Name="ToastArea"
|
|
Grid.RowSpan="4"
|
|
Position="BottomRight" MaxItems="4"
|
|
Margin="0,0,12,96"/>
|
|
</Grid>
|
|
</Window>
|