浏览代码

Merge branch 'master' into fixes/ClearType

Dan Walmsley 3 年之前
父节点
当前提交
d706d98c21

+ 4 - 1
build/SourceLink.props

@@ -3,7 +3,6 @@
     <PublishRepositoryUrl>true</PublishRepositoryUrl>
     <IncludeSymbols>false</IncludeSymbols>
     <EmbedUntrackedSources>true</EmbedUntrackedSources>
-    <DebugType>embedded</DebugType>
     <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
   </PropertyGroup>
   
@@ -15,6 +14,10 @@
     <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
   </PropertyGroup>
   
+  <PropertyGroup>
+    <DebugType Condition="$(ContinuousIntegrationBuild) == 'true'">embedded</DebugType>
+  </PropertyGroup>
+  
   <ItemGroup>
     <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
   </ItemGroup>

+ 1 - 1
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@@ -101,7 +101,7 @@ namespace Avalonia.Controls.Platform
                 root.Deactivated -= WindowDeactivated;
             }
             
-            if (_root is TopLevel tl)
+            if (_root is TopLevel tl && tl.PlatformImpl != null)
                 tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus;
 
             _inputManagerSubscription?.Dispose();

+ 1 - 1
src/Avalonia.Controls/Primitives/PopupRoot.cs

@@ -44,7 +44,7 @@ namespace Avalonia.Controls.Primitives
         /// The dependency resolver to use. If null the default dependency resolver will be used.
         /// </param>
         public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver)
-            : base(impl, dependencyResolver)
+            : base(ValidatingPopupImpl.Wrap(impl), dependencyResolver)
         {
             _parent = parent;
         }

+ 6 - 3
src/Avalonia.Controls/TopLevel.cs

@@ -134,6 +134,8 @@ namespace Avalonia.Controls
                     "Could not create window implementation: maybe no windowing subsystem was initialized?");
             }
 
+            impl = ValidatingToplevelImpl.Wrap(impl);
+            
             PlatformImpl = impl;
 
             _actualTransparencyLevel = PlatformImpl.TransparencyLevel;            
@@ -367,14 +369,15 @@ namespace Avalonia.Controls
             Renderer?.Dispose();
             Renderer = null;
             
+            (this as IInputRoot).MouseDevice?.TopLevelClosed(this);
+            PlatformImpl = null;
+            
             var logicalArgs = new LogicalTreeAttachmentEventArgs(this, this, null);
             ((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs);
 
             var visualArgs = new VisualTreeAttachmentEventArgs(this, this);
             OnDetachedFromVisualTreeCore(visualArgs);
-
-            (this as IInputRoot).MouseDevice?.TopLevelClosed(this);
-            PlatformImpl = null;
+            
             OnClosed(EventArgs.Empty);
 
             LayoutManager?.Dispose();

+ 326 - 0
src/Avalonia.Controls/ValidatingToplevel.cs

@@ -0,0 +1,326 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Controls.Platform;
+using Avalonia.Controls.Primitives.PopupPositioning;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Input.TextInput;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+
+namespace Avalonia.Controls;
+
+internal class ValidatingToplevelImpl : ITopLevelImpl, ITopLevelImplWithNativeControlHost,
+    ITopLevelImplWithNativeMenuExporter, ITopLevelImplWithTextInputMethod
+{
+    private readonly ITopLevelImpl _impl;
+    private bool _disposed;
+
+    public ValidatingToplevelImpl(ITopLevelImpl impl)
+    {
+        _impl = impl ?? throw new InvalidOperationException(
+            "Could not create TopLevel implementation: maybe no windowing subsystem was initialized?");
+    }
+
+    public void Dispose()
+    {
+        _disposed = true;
+        _impl.Dispose();
+    }
+
+    protected void CheckDisposed()
+    {
+        if (_disposed)
+            throw new ObjectDisposedException(_impl.GetType().FullName);
+    }
+
+    protected ITopLevelImpl Inner
+    {
+        get
+        {
+            CheckDisposed();
+            return _impl;
+        }
+    }
+
+    public static ITopLevelImpl Wrap(ITopLevelImpl impl)
+    {
+#if DEBUG
+        if (impl is ValidatingToplevelImpl)
+            return impl;
+        return new ValidatingToplevelImpl(impl);
+#else
+        return impl;
+#endif
+    }
+
+    public Size ClientSize => Inner.ClientSize;
+    public Size? FrameSize => Inner.FrameSize;
+    public double RenderScaling => Inner.RenderScaling;
+    public IEnumerable<object> Surfaces => Inner.Surfaces;
+
+    public Action<RawInputEventArgs> Input
+    {
+        get => Inner.Input;
+        set => Inner.Input = value;
+    }
+
+    public Action<Rect> Paint
+    {
+        get => Inner.Paint;
+        set => Inner.Paint = value;
+    }
+
+    public Action<Size, PlatformResizeReason> Resized
+    {
+        get => Inner.Resized;
+        set => Inner.Resized = value;
+    }
+
+    public Action<double> ScalingChanged
+    {
+        get => Inner.ScalingChanged;
+        set => Inner.ScalingChanged = value;
+    }
+
+    public Action<WindowTransparencyLevel> TransparencyLevelChanged
+    {
+        get => Inner.TransparencyLevelChanged;
+        set => Inner.TransparencyLevelChanged = value;
+    }
+
+    public IRenderer CreateRenderer(IRenderRoot root) => Inner.CreateRenderer(root);
+
+    public void Invalidate(Rect rect) => Inner.Invalidate(rect);
+
+    public void SetInputRoot(IInputRoot inputRoot) => Inner.SetInputRoot(inputRoot);
+
+    public Point PointToClient(PixelPoint point) => Inner.PointToClient(point);
+
+    public PixelPoint PointToScreen(Point point) => Inner.PointToScreen(point);
+
+    public void SetCursor(ICursorImpl cursor) => Inner.SetCursor(cursor);
+
+    public Action Closed
+    {
+        get => Inner.Closed;
+        set => Inner.Closed = value;
+    }
+
+    public Action LostFocus
+    {
+        get => Inner.LostFocus;
+        set => Inner.LostFocus = value;
+    }
+
+    // Exception: for some reason we are notifying platform mouse device from TopLevel.cs
+    public IMouseDevice MouseDevice => _impl.MouseDevice;
+    public IPopupImpl CreatePopup() => Inner.CreatePopup();
+
+    public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) =>
+        Inner.SetTransparencyLevelHint(transparencyLevel);
+
+
+    public WindowTransparencyLevel TransparencyLevel => Inner.TransparencyLevel;
+    public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => Inner.AcrylicCompensationLevels;
+    public INativeControlHostImpl NativeControlHost => (Inner as ITopLevelImplWithNativeControlHost)?.NativeControlHost;
+
+    public ITopLevelNativeMenuExporter NativeMenuExporter =>
+        (Inner as ITopLevelImplWithNativeMenuExporter)?.NativeMenuExporter;
+
+    public ITextInputMethodImpl TextInputMethod => (Inner as ITopLevelImplWithTextInputMethod)?.TextInputMethod;
+}
+
+internal class ValidatingWindowBaseImpl : ValidatingToplevelImpl, IWindowBaseImpl
+{
+    private readonly IWindowBaseImpl _impl;
+
+    public ValidatingWindowBaseImpl(IWindowBaseImpl impl) : base(impl)
+    {
+        _impl = impl;
+    }
+
+    protected new IWindowBaseImpl Inner
+    {
+        get
+        {
+            CheckDisposed();
+            return _impl;
+        }
+    }
+    
+    public static IWindowBaseImpl Wrap(IWindowBaseImpl impl)
+    {
+#if DEBUG
+        if (impl is ValidatingToplevelImpl)
+            return impl;
+        return new ValidatingWindowBaseImpl(impl);
+#else
+        return impl;
+#endif
+    }
+
+    public void Show(bool activate, bool isDialog) => Inner.Show(activate, isDialog);
+
+    public void Hide() => Inner.Hide();
+
+    public double DesktopScaling => Inner.DesktopScaling;
+    public PixelPoint Position => Inner.Position;
+
+    public Action<PixelPoint> PositionChanged
+    {
+        get => Inner.PositionChanged;
+        set => Inner.PositionChanged = value;
+    }
+
+    public void Activate() => Inner.Activate();
+
+    public Action Deactivated
+    {
+        get => Inner.Deactivated;
+        set => Inner.Deactivated = value;
+    }
+
+    public Action Activated
+    {
+        get => Inner.Activated;
+        set => Inner.Deactivated = value;
+    }
+
+    public IPlatformHandle Handle => Inner.Handle;
+    public Size MaxAutoSizeHint => Inner.MaxAutoSizeHint;
+    public void SetTopmost(bool value) => Inner.SetTopmost(value);
+    public IScreenImpl Screen => Inner.Screen;
+}
+
+internal class ValidatingWindowImpl : ValidatingWindowBaseImpl, IWindowImpl
+{
+    private readonly IWindowImpl _impl;
+
+    public ValidatingWindowImpl(IWindowImpl impl) : base(impl)
+    {
+        _impl = impl;
+    }
+
+    protected new IWindowImpl Inner
+    {
+        get
+        {
+            CheckDisposed();
+            return _impl;
+        }
+    }
+    
+    public static IWindowImpl Wrap(IWindowImpl impl)
+    {
+#if DEBUG
+        if (impl is ValidatingToplevelImpl)
+            return impl;
+        return new ValidatingWindowImpl(impl);
+#else
+        return impl;
+#endif
+    }
+
+    public WindowState WindowState
+    {
+        get => Inner.WindowState;
+        set => Inner.WindowState = value;
+    }
+
+    public Action<WindowState> WindowStateChanged
+    {
+        get => Inner.WindowStateChanged;
+        set => Inner.WindowStateChanged = value;
+    }
+
+    public void SetTitle(string title) => Inner.SetTitle(title);
+
+    public void SetParent(IWindowImpl parent) => Inner.SetParent(parent);
+
+    public void SetEnabled(bool enable) => Inner.SetEnabled(enable);
+
+    public Action GotInputWhenDisabled
+    {
+        get => Inner.GotInputWhenDisabled;
+        set => Inner.GotInputWhenDisabled = value;
+    }
+
+    public void SetSystemDecorations(SystemDecorations enabled) => Inner.SetSystemDecorations(enabled);
+
+    public void SetIcon(IWindowIconImpl icon) => Inner.SetIcon(icon);
+
+    public void ShowTaskbarIcon(bool value) => Inner.ShowTaskbarIcon(value);
+
+    public void CanResize(bool value) => Inner.CanResize(value);
+
+    public Func<bool> Closing
+    {
+        get => Inner.Closing;
+        set => Inner.Closing = value;
+    }
+
+    public bool IsClientAreaExtendedToDecorations => Inner.IsClientAreaExtendedToDecorations;
+
+    public Action<bool> ExtendClientAreaToDecorationsChanged
+    {
+        get => Inner.ExtendClientAreaToDecorationsChanged;
+        set => Inner.ExtendClientAreaToDecorationsChanged = value;
+    }
+
+    public bool NeedsManagedDecorations => Inner.NeedsManagedDecorations;
+    public Thickness ExtendedMargins => Inner.ExtendedMargins;
+    public Thickness OffScreenMargin => Inner.OffScreenMargin;
+    public void BeginMoveDrag(PointerPressedEventArgs e) => Inner.BeginMoveDrag(e);
+
+    public void BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e) => Inner.BeginResizeDrag(edge, e);
+
+    public void Resize(Size clientSize, PlatformResizeReason reason) =>
+        Inner.Resize(clientSize, reason);
+
+    public void Move(PixelPoint point) => Inner.Move(point);
+
+    public void SetMinMaxSize(Size minSize, Size maxSize) => Inner.SetMinMaxSize(minSize, maxSize);
+
+    public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint) =>
+        Inner.SetExtendClientAreaToDecorationsHint(extendIntoClientAreaHint);
+
+    public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints) =>
+        Inner.SetExtendClientAreaChromeHints(hints);
+
+    public void SetExtendClientAreaTitleBarHeightHint(double titleBarHeight) =>
+        Inner.SetExtendClientAreaTitleBarHeightHint(titleBarHeight);
+}
+
+internal class ValidatingPopupImpl : ValidatingWindowBaseImpl, IPopupImpl
+{
+    private readonly IPopupImpl _impl;
+
+    public ValidatingPopupImpl(IPopupImpl impl) : base(impl)
+    {
+        _impl = impl;
+    }
+
+    protected new IPopupImpl Inner
+    {
+        get
+        {
+            CheckDisposed();
+            return _impl;
+        }
+    }
+    
+    public static IPopupImpl Wrap(IPopupImpl impl)
+    {
+#if DEBUG
+        if (impl is ValidatingToplevelImpl)
+            return impl;
+        return new ValidatingPopupImpl(impl);
+#else
+        return impl;
+#endif
+    }
+
+    public IPopupPositioner PopupPositioner => Inner.PopupPositioner;
+    public void SetWindowManagerAddShadowHint(bool enabled) => Inner.SetWindowManagerAddShadowHint(enabled);
+}

+ 6 - 5
src/Avalonia.Controls/Window.cs

@@ -237,13 +237,14 @@ namespace Avalonia.Controls
         /// </summary>
         /// <param name="impl">The window implementation.</param>
         public Window(IWindowImpl impl)
-            : base(impl)
+            : base(ValidatingWindowImpl.Wrap(impl))
         {
-            impl.Closing = HandleClosing;
-            impl.GotInputWhenDisabled = OnGotInputWhenDisabled;
-            impl.WindowStateChanged = HandleWindowStateChanged;
+            var wrapped = (IWindowImpl)base.PlatformImpl!;
+            wrapped.Closing = HandleClosing;
+            wrapped.GotInputWhenDisabled = OnGotInputWhenDisabled;
+            wrapped.WindowStateChanged = HandleWindowStateChanged;
             _maxPlatformClientSize = PlatformImpl?.MaxAutoSizeHint ?? default(Size);
-            impl.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged;            
+            wrapped.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged;            
             this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x, PlatformResizeReason.Application));
 
             PlatformImpl?.ShowTaskbarIcon(ShowInTaskbar);

+ 5 - 4
src/Avalonia.Controls/WindowBase.cs

@@ -57,12 +57,13 @@ namespace Avalonia.Controls
         {
         }
 
-        public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver)
+        public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(ValidatingWindowBaseImpl.Wrap(impl), dependencyResolver)
         {
             Screens = new Screens(PlatformImpl?.Screen);
-            impl.Activated = HandleActivated;
-            impl.Deactivated = HandleDeactivated;
-            impl.PositionChanged = HandlePositionChanged;
+            var wrapped = PlatformImpl!;
+            wrapped.Activated = HandleActivated;
+            wrapped.Deactivated = HandleDeactivated;
+            wrapped.PositionChanged = HandlePositionChanged;
         }
 
         /// <summary>

+ 1 - 1
src/Avalonia.Themes.Fluent/Controls/CalendarButton.xaml

@@ -11,7 +11,7 @@
     <Setter Property="MinWidth" Value="40"/>
     <Setter Property="MinHeight" Value="40"/>
     <Setter Property="Margin" Value="1"/>
-    <Setter Property="Padding" Value="0,0,0,4"/>
+    <Setter Property="Padding" Value="0,0,0,0"/>
     <!--These are actually set on the CalendarView in WinUI-->
     <Setter Property="Foreground" Value="{DynamicResource CalendarViewCalendarItemForeground}"/>
     <Setter Property="Background" Value="{DynamicResource CalendarViewCalendarItemRevealBackground}"/>

+ 1 - 1
src/Avalonia.Themes.Fluent/Controls/CalendarDayButton.xaml

@@ -11,7 +11,7 @@
     <Setter Property="MinWidth" Value="40"/>
     <Setter Property="MinHeight" Value="40"/>
     <Setter Property="Margin" Value="1"/>
-    <Setter Property="Padding" Value="0,0,0,4"/>
+    <Setter Property="Padding" Value="0,0,0,0"/>
     <!--These are actually set on the CalendarView in WinUI-->
     <Setter Property="Foreground" Value="{DynamicResource CalendarViewCalendarItemForeground}"/>
     <Setter Property="Background" Value="{DynamicResource CalendarViewCalendarItemRevealBackground}"/>

+ 1 - 0
src/Avalonia.Themes.Fluent/Controls/CalendarItem.xaml

@@ -32,6 +32,7 @@
             <Style Selector="Button.CalendarHeader">
               <Setter Property="HorizontalAlignment" Value="Stretch" />
               <Setter Property="VerticalAlignment" Value="Stretch" />
+              <Setter Property="VerticalContentAlignment" Value="Center" />
               <Setter Property="FontSize" Value="20" />
               <Setter Property="Background" Value="{DynamicResource CalendarViewNavigationButtonBackground}"/>
               <Setter Property="Template">

+ 9 - 4
src/Avalonia.X11/X11Window.cs

@@ -341,9 +341,13 @@ namespace Avalonia.X11
 
         public Action<WindowTransparencyLevel> TransparencyLevelChanged
         {
-            get => _transparencyHelper.TransparencyLevelChanged;
-            set => _transparencyHelper.TransparencyLevelChanged = value;
-        }        
+            get => _transparencyHelper?.TransparencyLevelChanged;
+            set
+            {
+                if (_transparencyHelper != null)
+                    _transparencyHelper.TransparencyLevelChanged = value;
+            }
+        }
 
         public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
 
@@ -1163,7 +1167,8 @@ namespace Avalonia.X11
         {
         }
 
-        public WindowTransparencyLevel TransparencyLevel => _transparencyHelper.CurrentLevel;
+        public WindowTransparencyLevel TransparencyLevel =>
+            _transparencyHelper?.CurrentLevel ?? WindowTransparencyLevel.None;
 
         public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; } = new AcrylicPlatformCompensationLevels(1, 0.8, 0.8);
 

+ 1 - 1
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -480,7 +480,7 @@ namespace Avalonia.Skia
         public void PushClip(RoundedRect clip)
         {
             Canvas.Save();
-            Canvas.ClipRoundRect(clip.ToSKRoundRect());
+            Canvas.ClipRoundRect(clip.ToSKRoundRect(), antialias:true);
         }
 
         /// <inheritdoc />