فهرست منبع

dont cover titlebar, and allow titlebar to have a background placed in an underlay layer so it doesnt cover content.

Dan Walmsley 5 سال پیش
والد
کامیت
4be53b2d8a

+ 1 - 2
samples/ControlCatalog/MainView.xaml

@@ -1,8 +1,7 @@
 <UserControl xmlns="https://github.com/avaloniaui"
         xmlns:pages="clr-namespace:ControlCatalog.Pages"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-        x:Class="ControlCatalog.MainView"
-        Background="Transparent"
+        x:Class="ControlCatalog.MainView"        
         Foreground="{DynamicResource ThemeForegroundBrush}"
         FontSize="{DynamicResource FontSizeNormal}">
   <Grid>

+ 5 - 0
samples/ControlCatalog/MainWindow.xaml

@@ -60,6 +60,11 @@
       </NativeMenuItem>
     </NativeMenu>
   </NativeMenu.Menu>
+  <Window.Styles>
+    <Style Selector="TitleBar">
+      <Setter Property="Background" Value="Green" />
+    </Style>
+  </Window.Styles>
 
   <Window.DataTemplates>
     <DataTemplate DataType="vm:NotificationViewModel">

+ 26 - 12
src/Avalonia.Controls/Chrome/TitleBar.cs

@@ -14,28 +14,32 @@ namespace Avalonia.Controls.Chrome
         private CompositeDisposable? _disposables;
         private readonly Window? _hostWindow;
         private CaptionButtons? _captionButtons;
+        private Panel _underlay;
 
-        public TitleBar(Window hostWindow)
+        public TitleBar(Window hostWindow) : this()
         {
             _hostWindow = hostWindow;
         }
 
         public TitleBar()
         {
-
+            _underlay = new Panel
+            {
+                IsHitTestVisible = false,
+                [~Panel.BackgroundProperty] = this[~BackgroundProperty],
+                VerticalAlignment = Layout.VerticalAlignment.Top
+            };
         }
 
         public void Attach()
         {
-            if (_disposables == null)
+            if (_disposables == null && _hostWindow != null)
             {
-                var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
+                var overlay = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
 
-                layer?.Children.Add(this);
+                overlay?.Children.Add(this);
 
-                if (_hostWindow != null)
-                {
-                    _disposables = new CompositeDisposable
+                _disposables = new CompositeDisposable
                     {
                         _hostWindow.GetObservable(Window.WindowDecorationMarginsProperty)
                             .Subscribe(x => UpdateSize()),
@@ -56,11 +60,15 @@ namespace Avalonia.Controls.Chrome
                             })
                     };
 
-                    _captionButtons?.Attach(_hostWindow);
-                }
+                _captionButtons?.Attach(_hostWindow);
+
+                var underlay = ChromeUnderlayLayer.GetUnderlayLayer(_hostWindow);
+
+                underlay?.Children.Add(_underlay);
 
                 UpdateSize();
             }
+
         }
 
         private void UpdateSize()
@@ -76,6 +84,7 @@ namespace Avalonia.Controls.Chrome
                 if (_hostWindow.WindowState != WindowState.FullScreen)
                 {
                     Height = _hostWindow.WindowDecorationMargins.Top;
+                    _underlay.Height = Height;
 
                     if (_captionButtons != null)
                     {
@@ -89,9 +98,14 @@ namespace Avalonia.Controls.Chrome
         {
             if (_disposables != null)
             {
-                var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
+                if (_hostWindow != null)
+                {
+                    var overlay = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
+                    overlay?.Children.Remove(this);
 
-                layer?.Children.Remove(this);
+                    var underlay = ChromeUnderlayLayer.GetUnderlayLayer(_hostWindow);
+                    underlay?.Children.Remove(_underlay);
+                }
 
                 _disposables.Dispose();
                 _disposables = null;

+ 21 - 0
src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs

@@ -6,6 +6,27 @@ using Avalonia.VisualTree;
 
 namespace Avalonia.Controls.Primitives
 {
+    public class ChromeUnderlayLayer : Panel, ICustomSimpleHitTest
+    {
+        public static ChromeUnderlayLayer? GetUnderlayLayer(IVisual visual)
+        {
+            foreach (var v in visual.GetVisualAncestors())
+                if (v is VisualLayerManager vlm)
+                    if (vlm.OverlayLayer != null)
+                        return vlm.ChromeUnderlayLayer;
+
+            if (visual is TopLevel tl)
+            {
+                var layers = tl.GetVisualDescendants().OfType<VisualLayerManager>().FirstOrDefault();
+                return layers?.ChromeUnderlayLayer;
+            }
+
+            return null;
+        }
+
+        public bool HitTest(Point point) => Children.HitTestCustom(point);
+    }
+
     public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest
     {
         public static ChromeOverlayLayer? GetOverlayLayer(IVisual visual)

+ 12 - 0
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@@ -8,6 +8,7 @@ namespace Avalonia.Controls.Primitives
         private const int AdornerZIndex = int.MaxValue - 100;
         private const int ChromeZIndex = int.MaxValue - 99;
         private const int OverlayZIndex = int.MaxValue - 98;
+        private const int UnderlayZIndex = int.MinValue;
 
         private ILogicalRoot _logicalRoot;
         private readonly List<Control> _layers = new List<Control>();
@@ -26,6 +27,17 @@ namespace Avalonia.Controls.Primitives
             }
         }
 
+        public ChromeUnderlayLayer ChromeUnderlayLayer
+        {
+            get
+            {
+                var rv = FindLayer<ChromeUnderlayLayer>();
+                if (rv == null)
+                    AddLayer(rv = new ChromeUnderlayLayer(), UnderlayZIndex);
+                return rv;
+            }
+        }
+
         public ChromeOverlayLayer ChromeOverlayLayer
         {
             get

+ 1 - 1
src/Avalonia.Themes.Fluent/TitleBar.xaml

@@ -14,7 +14,7 @@
         <Panel HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="Stretch">
           <Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" />
           <Panel x:Name="PART_Container">
-            <Border x:Name="PART_Background" Background="{TemplateBinding Background}" />
+            <Border x:Name="PART_Background" Background="{x:Null}" />
             <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" MaxHeight="30" />
           </Panel>
         </Panel>

+ 2 - 2
src/Avalonia.Themes.Fluent/Window.xaml

@@ -1,11 +1,11 @@
 <Style xmlns="https://github.com/avaloniaui" Selector="Window">
-  <Setter Property="Background" Value="{DynamicResource SystemControlBackgroundChromeMediumBrush}"/>
+  <Setter Property="Background" Value="{DynamicResource SystemControlBackgroundChromeBlackHighBrush}"/>
   <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
   <Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}"/>
   <Setter Property="Template">
     <ControlTemplate>
       <Panel>
-        <Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
+        <Border Name="PART_TransparencyFallback" IsHitTestVisible="False" Margin="{TemplateBinding WindowDecorationMargins}" />
         <Border Background="{TemplateBinding Background}">
           <VisualLayerManager>
             <ContentPresenter Name="PART_ContentPresenter"