diff --git a/Controls/PreviewPane.xaml b/Controls/PreviewPane.xaml index 97b092c..705f97a 100644 --- a/Controls/PreviewPane.xaml +++ b/Controls/PreviewPane.xaml @@ -90,6 +90,15 @@ @@ -476,6 +485,7 @@ diff --git a/Controls/PreviewPane.xaml.cs b/Controls/PreviewPane.xaml.cs index ff93a58..23f7155 100644 --- a/Controls/PreviewPane.xaml.cs +++ b/Controls/PreviewPane.xaml.cs @@ -677,6 +677,13 @@ public partial class PreviewPane : UserControl if (vm.SelectedElement is { } selected && IsHitTestable(selected) && Contains(selected, p)) return selected; + // The brand logo is drawn ABOVE everything (the compositor blits it after the blur group, + // and the preview renders it in BrandLogoOverlay), so a click inside it must select it — + // otherwise you see the logo on top and grab the webcam underneath it. + var brand = vm.StagedBrandLogo; + if (brand is { IsVisible: true } && Contains(brand, p)) + return brand; + for (var i = scene.Elements.Count - 1; i >= 0; i--) { var element = scene.Elements[i]; diff --git a/ytLive.Tests/SelectedLayerPreviewHitTestingTests.cs b/ytLive.Tests/SelectedLayerPreviewHitTestingTests.cs index d3117fe..d24c769 100644 --- a/ytLive.Tests/SelectedLayerPreviewHitTestingTests.cs +++ b/ytLive.Tests/SelectedLayerPreviewHitTestingTests.cs @@ -71,26 +71,35 @@ public sealed class SelectedLayerPreviewHitTestingTests var pointInCanvas = new Point(logo.X + 100, logo.Y + 60); var pointInWindow = canvasGrid.TransformToVisual(window).Transform(pointInCanvas); - Assert.True(ReferenceEquals(webcam, ElementAt(window.InputHitTest(pointInWindow)))); - Assert.Same(webcam, preview.HitElementAt(vm, pointInCanvas)); - Assert.Equal(0, Panel.GetZIndex(logoContainer)); + // The brand logo is drawn in BrandLogoOverlay above the blur host (2026-11-01), so its + // canvas presenter is collapsed and the overlay is what the eye sees. Hit-testing + // follows the eye: the logo wins a click inside its bounds. + Assert.Equal(Visibility.Collapsed, logoContainer.Visibility); + Assert.Same(logo, preview.HitElementAt(vm, pointInCanvas)); sourceList.SelectedItem = logo; window.UpdateLayout(); Assert.True(ReferenceEquals(logo, vm.SelectedElement), "Selecting the layer-list row must select the brand logo."); - Assert.True(Panel.GetZIndex(logoContainer) > Panel.GetZIndex(webcamContainer)); - Assert.Same(logo, ElementAt(window.InputHitTest(pointInWindow))); Assert.Same(logo, preview.HitElementAt(vm, pointInCanvas)); + + // …and with nothing selected the logo still wins inside its own bounds, because it is + // drawn above every layer. The webcam shares that rect in this test, so it is the + // covered case: you reach it from the layer list, not by clicking through the logo. + vm.SelectedElement = null; + window.UpdateLayout(); + Assert.Same(logo, preview.HitElementAt(vm, new Point(logo.X + 5, logo.Y + 5))); Assert.Equal(originalOrder, scene.Elements); sourceList.SelectedItem = null; window.UpdateLayout(); Assert.Null(vm.SelectedElement); - Assert.Equal(0, Panel.GetZIndex(logoContainer)); - Assert.Same(webcam, ElementAt(window.InputHitTest(pointInWindow))); - Assert.Same(webcam, preview.HitElementAt(vm, pointInCanvas)); + // The logo still owns a click inside its bounds after deselection (it is the topmost + // layer in both the compositor and the preview), and the canvas presenter stays + // collapsed because BrandLogoOverlay is what draws it. + Assert.Equal(Visibility.Collapsed, logoContainer.Visibility); + Assert.Same(logo, preview.HitElementAt(vm, pointInCanvas)); Assert.Equal(originalOrder, scene.Elements); } finally