瀏覽代碼

Merge branch 'master' into fixes/textProcessingBugs

Benedikt Stebner 3 年之前
父節點
當前提交
88fd8f007a
共有 100 個文件被更改,包括 369 次插入112 次删除
  1. 2 0
      build/ApiCompatAttributeExcludeList.txt
  2. 1 1
      native/Avalonia.Native/src/OSX/AutoFitContentView.mm
  3. 19 4
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  4. 5 16
      native/Avalonia.Native/src/OSX/PopupImpl.mm
  5. 3 0
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  6. 39 17
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  7. 3 3
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  8. 1 2
      samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
  9. 2 0
      src/Avalonia.Base/Animation/IAnimation.cs
  10. 3 0
      src/Avalonia.Base/Animation/IAnimationSetter.cs
  11. 2 0
      src/Avalonia.Base/Animation/IAnimator.cs
  12. 2 2
      src/Avalonia.Base/Animation/IClock.cs
  13. 2 3
      src/Avalonia.Base/Animation/IGlobalClock.cs
  14. 2 0
      src/Avalonia.Base/Animation/ITransition.cs
  15. 2 2
      src/Avalonia.Base/Controls/INameScope.cs
  16. 2 0
      src/Avalonia.Base/Controls/IPseudoClasses.cs
  17. 2 2
      src/Avalonia.Base/Controls/IResourceHost.cs
  18. 2 2
      src/Avalonia.Base/Controls/IResourceNode.cs
  19. 2 1
      src/Avalonia.Base/Controls/ISetInheritanceParent.cs
  20. 2 2
      src/Avalonia.Base/Controls/ISetLogicalParent.cs
  21. 23 23
      src/Avalonia.Base/Data/Core/ExpressionNode.cs
  22. 2 0
      src/Avalonia.Base/Data/Core/IPropertyInfo.cs
  23. 3 0
      src/Avalonia.Base/Data/IBinding.cs
  24. 2 0
      src/Avalonia.Base/IAvaloniaObject.cs
  25. 2 1
      src/Avalonia.Base/IDataContextProvider.cs
  26. 1 0
      src/Avalonia.Base/IDirectPropertyAccessor.cs
  27. 3 0
      src/Avalonia.Base/IDirectPropertyMetadata.cs
  28. 2 2
      src/Avalonia.Base/IStyledElement.cs
  29. 3 0
      src/Avalonia.Base/IStyledPropertyMetadata.cs
  30. 3 0
      src/Avalonia.Base/Input/IAccessKeyHandler.cs
  31. 3 0
      src/Avalonia.Base/Input/IFocusManager.cs
  32. 2 0
      src/Avalonia.Base/Input/IInputDevice.cs
  33. 2 0
      src/Avalonia.Base/Input/IInputElement.cs
  34. 2 0
      src/Avalonia.Base/Input/IInputManager.cs
  35. 3 0
      src/Avalonia.Base/Input/IInputRoot.cs
  36. 2 0
      src/Avalonia.Base/Input/IKeyboardDevice.cs
  37. 3 0
      src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs
  38. 2 0
      src/Avalonia.Base/Input/IMainMenu.cs
  39. 2 0
      src/Avalonia.Base/Input/IMouseDevice.cs
  40. 3 0
      src/Avalonia.Base/Input/IPointer.cs
  41. 2 0
      src/Avalonia.Base/Input/IPointerDevice.cs
  42. 2 0
      src/Avalonia.Base/Input/Platform/IClipboard.cs
  43. 2 0
      src/Avalonia.Base/Input/Platform/IPlatformDragSource.cs
  44. 4 1
      src/Avalonia.Base/Input/Raw/IDragDropDevice.cs
  45. 4 0
      src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs
  46. 2 0
      src/Avalonia.Base/Interactivity/IInteractive.cs
  47. 2 2
      src/Avalonia.Base/Layout/ILayoutManager.cs
  48. 3 0
      src/Avalonia.Base/Layout/ILayoutRoot.cs
  49. 2 2
      src/Avalonia.Base/Layout/ILayoutable.cs
  50. 19 1
      src/Avalonia.Base/Layout/Layoutable.cs
  51. 2 0
      src/Avalonia.Base/LogicalTree/ILogical.cs
  52. 4 1
      src/Avalonia.Base/LogicalTree/ILogicalRoot.cs
  53. 2 0
      src/Avalonia.Base/Media/IBrush.cs
  54. 4 1
      src/Avalonia.Base/Media/IConicGradientBrush.cs
  55. 2 0
      src/Avalonia.Base/Media/IDashStyle.cs
  56. 4 1
      src/Avalonia.Base/Media/IExperimentalAcrylicMaterial.cs
  57. 2 0
      src/Avalonia.Base/Media/IGradientBrush.cs
  58. 4 1
      src/Avalonia.Base/Media/IGradientStop.cs
  59. 3 1
      src/Avalonia.Base/Media/IImageBrush.cs
  60. 5 2
      src/Avalonia.Base/Media/ILinearGradientBrush.cs
  61. 2 0
      src/Avalonia.Base/Media/IMutableBrush.cs
  62. 4 1
      src/Avalonia.Base/Media/IMutableExperimentalAcrylicMaterial.cs
  63. 1 0
      src/Avalonia.Base/Media/IMutableTransform.cs
  64. 4 1
      src/Avalonia.Base/Media/IPen.cs
  65. 5 2
      src/Avalonia.Base/Media/IRadialGradientBrush.cs
  66. 4 1
      src/Avalonia.Base/Media/ISolidColorBrush.cs
  67. 3 1
      src/Avalonia.Base/Media/ITileBrush.cs
  68. 4 2
      src/Avalonia.Base/Media/IVisualBrush.cs
  69. 2 0
      src/Avalonia.Base/Media/Imaging/IBitmap.cs
  70. 3 1
      src/Avalonia.Base/Media/TextFormatting/ITextSource.cs
  71. 17 0
      src/Avalonia.Base/Metadata/NotClientImplementableAttribute.cs
  72. 12 0
      src/Avalonia.Base/Metadata/UnstableAttribute.cs
  73. 2 0
      src/Avalonia.Base/Platform/IAssetLoader.cs
  74. 2 0
      src/Avalonia.Base/Platform/IBitmapImpl.cs
  75. 2 0
      src/Avalonia.Base/Platform/ICursorImpl.cs
  76. 2 0
      src/Avalonia.Base/Platform/IDrawingContextImpl.cs
  77. 2 0
      src/Avalonia.Base/Platform/IFontManagerImpl.cs
  78. 2 0
      src/Avalonia.Base/Platform/IGeometryImpl.cs
  79. 2 0
      src/Avalonia.Base/Platform/IGlyphRunImpl.cs
  80. 2 0
      src/Avalonia.Base/Platform/IGlyphTypefaceImpl.cs
  81. 2 0
      src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs
  82. 2 0
      src/Avalonia.Base/Platform/IPlatformRenderInterface.cs
  83. 2 0
      src/Avalonia.Base/Platform/IPlatformSettings.cs
  84. 2 0
      src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs
  85. 2 0
      src/Avalonia.Base/Platform/IRenderTargetBitmapImpl.cs
  86. 5 0
      src/Avalonia.Base/Platform/IRuntimePlatform.cs
  87. 3 0
      src/Avalonia.Base/Platform/IStreamGeometryContextImpl.cs
  88. 3 0
      src/Avalonia.Base/Platform/IStreamGeometryImpl.cs
  89. 2 0
      src/Avalonia.Base/Platform/ITextShaperImpl.cs
  90. 4 1
      src/Avalonia.Base/Platform/ITransformedGeometryImpl.cs
  91. 4 1
      src/Avalonia.Base/Platform/IWriteableBitmapImpl.cs
  92. 2 0
      src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs
  93. 2 0
      src/Avalonia.Base/Rendering/IDeferredRendererLock.cs
  94. 4 1
      src/Avalonia.Base/Rendering/IRenderLoop.cs
  95. 2 0
      src/Avalonia.Base/Rendering/IRenderRoot.cs
  96. 2 0
      src/Avalonia.Base/Rendering/IRenderTimer.cs
  97. 2 0
      src/Avalonia.Base/Rendering/IVisualBrushInitialize.cs
  98. 2 0
      src/Avalonia.Base/Rendering/IVisualBrushRenderer.cs
  99. 3 3
      src/Avalonia.Base/Styling/Activators/IStyleActivator.cs
  100. 2 1
      src/Avalonia.Base/Styling/Activators/IStyleActivatorSink.cs

+ 2 - 0
build/ApiCompatAttributeExcludeList.txt

@@ -0,0 +1,2 @@
+T:Avalonia.Metadata.NotClientImplementableAttribute
+T:Avalonia.Metadata.UnstableAttribute

+ 1 - 1
native/Avalonia.Native/src/OSX/AutoFitContentView.mm

@@ -85,7 +85,7 @@
     _settingSize = true;
     [super setFrameSize:newSize];
 
-    auto window = static_cast<id <AvnWindowProtocol>>([self window]);
+    auto window = (id <AvnWindowProtocol>) [self window];
 
     // TODO get actual titlebar size
 

+ 19 - 4
native/Avalonia.Native/src/OSX/AvnWindow.mm

@@ -174,6 +174,11 @@
     [self setBackgroundColor: [NSColor clearColor]];
 
     _isExtended = false;
+
+#ifdef IS_NSPANEL
+    [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces|NSWindowCollectionBehaviorFullScreenAuxiliary];
+#endif
+
     return self;
 }
 
@@ -194,6 +199,8 @@
     [self backingScaleFactor];
 }
 
+
+
 - (void)windowWillClose:(NSNotification *)notification
 {
     _closed = true;
@@ -212,11 +219,14 @@
     // If the window has a child window being shown as a dialog then don't allow it to become the key window.
     for(NSWindow* uch in [self childWindows])
     {
-        auto ch = static_cast<id <AvnWindowProtocol>>(uch);
-        if(ch == nil)
+        if (![uch conformsToProtocol:@protocol(AvnWindowProtocol)])
+        {
             continue;
-        if (ch.isDialog)
-            return false;
+        }
+
+        id <AvnWindowProtocol> ch = (id <AvnWindowProtocol>) uch;
+
+        return !ch.isDialog;
     }
 
     return true;
@@ -372,6 +382,11 @@
 
         if(cparent != nullptr)
         {
+            if(!cparent->IsShown())
+            {
+                return;
+            }
+
             if(cparent->WindowState() == Maximized)
             {
                 cparent->SetWindowState(Normal);

+ 5 - 16
native/Avalonia.Native/src/OSX/PopupImpl.mm

@@ -34,27 +34,16 @@ protected:
         return NSWindowStyleMaskBorderless;
     }
 
-    virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override
-    {
-        START_COM_CALL;
-
-        @autoreleasepool
-        {
-            if (Window != nullptr)
-            {
-                [Window setContentSize:NSSize{x, y}];
-
-                [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))];
-            }
-
-            return S_OK;
-        }
-    }
 public:
     virtual bool ShouldTakeFocusOnShow() override
     {
         return false;
     }
+
+    virtual HRESULT Show(bool activate, bool isDialog) override
+    {
+        return WindowBaseImpl::Show(activate, true);
+    }
 };
 
 

+ 3 - 0
native/Avalonia.Native/src/OSX/WindowBaseImpl.h

@@ -35,6 +35,7 @@ BEGIN_INTERFACE_MAP()
     ComPtr<IAvnGlContext> _glContext;
     NSObject <IRenderTarget> *renderTarget;
     AvnPoint lastPositionSet;
+    bool hasPosition;
     NSSize lastSize;
     NSSize lastMinSize;
     NSSize lastMaxSize;
@@ -60,6 +61,8 @@ BEGIN_INTERFACE_MAP()
 
     virtual HRESULT Show(bool activate, bool isDialog) override;
 
+    virtual bool IsShown ();
+
     virtual bool ShouldTakeFocusOnShow();
 
     virtual HRESULT Hide() override;

+ 39 - 17
native/Avalonia.Native/src/OSX/WindowBaseImpl.mm

@@ -30,8 +30,8 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl)
     View = [[AvnView alloc] initWithParent:this];
     StandardContainer = [[AutoFitContentView new] initWithContent:View];
 
-    lastPositionSet.X = 100;
-    lastPositionSet.Y = 100;
+    lastPositionSet = { 0, 0 };
+    hasPosition = false;
     lastSize = NSSize { 100, 100 };
     lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX};
     lastMinSize = NSSize { 0, 0 };
@@ -92,7 +92,14 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) {
         CreateNSWindow(isDialog);
         InitialiseNSWindow();
 
-        SetPosition(lastPositionSet);
+        if(hasPosition)
+        {
+            SetPosition(lastPositionSet);
+        } else
+        {
+            [Window center];
+        }
+
         UpdateStyle();
 
         [Window setTitle:_lastTitle];
@@ -112,6 +119,11 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) {
     }
 }
 
+bool WindowBaseImpl::IsShown ()
+{
+    return _shown;
+}
+
 bool WindowBaseImpl::ShouldTakeFocusOnShow() {
     return true;
 }
@@ -191,9 +203,8 @@ HRESULT WindowBaseImpl::GetClientSize(AvnSize *ret) {
         if (ret == nullptr)
             return E_POINTER;
 
-        auto frame = [View frame];
-        ret->Width = frame.size.width;
-        ret->Height = frame.size.height;
+        ret->Width = lastSize.width;
+        ret->Height = lastSize.height;
 
         return S_OK;
     }
@@ -206,9 +217,11 @@ HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) {
         if (ret == nullptr)
             return E_POINTER;
 
-        auto frame = [Window frame];
-        ret->Width = frame.size.width;
-        ret->Height = frame.size.height;
+        if(Window != nullptr){
+            auto frame = [Window frame];
+            ret->Width = frame.size.width;
+            ret->Height = frame.size.height;
+        }
 
         return S_OK;
     }
@@ -278,12 +291,12 @@ HRESULT WindowBaseImpl::Resize(double x, double y, AvnPlatformResizeReason reaso
         }
 
         @try {
+            lastSize = NSSize {x, y};
+
             if (!_shown) {
                 BaseEvents->Resized(AvnSize{x, y}, reason);
             }
 
-            lastSize = NSSize {x, y};
-
             if(Window != nullptr) {
                 [Window setContentSize:lastSize];
             }
@@ -354,12 +367,17 @@ HRESULT WindowBaseImpl::GetPosition(AvnPoint *ret) {
             return E_POINTER;
         }
 
-        auto frame = [Window frame];
+        if(Window != nullptr) {
+            auto frame = [Window frame];
 
-        ret->X = frame.origin.x;
-        ret->Y = frame.origin.y + frame.size.height;
+            ret->X = frame.origin.x;
+            ret->Y = frame.origin.y + frame.size.height;
 
-        *ret = ConvertPointY(*ret);
+            *ret = ConvertPointY(*ret);
+        } else
+        {
+            *ret = lastPositionSet;
+        }
 
         return S_OK;
     }
@@ -370,7 +388,11 @@ HRESULT WindowBaseImpl::SetPosition(AvnPoint point) {
 
     @autoreleasepool {
         lastPositionSet = point;
-        [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
+        hasPosition = true;
+
+        if(Window != nullptr) {
+            [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))];
+        }
 
         return S_OK;
     }
@@ -576,7 +598,7 @@ id <AvnWindowProtocol> WindowBaseImpl::GetWindowProtocol() {
         return nullptr;
     }
 
-    return static_cast<id <AvnWindowProtocol>>(Window);
+    return (id <AvnWindowProtocol>) Window;
 }
 
 extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl)

+ 3 - 3
native/Avalonia.Native/src/OSX/WindowImpl.mm

@@ -430,6 +430,9 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) {
     START_COM_CALL;
 
     @autoreleasepool {
+        auto currentState = _actualWindowState;
+        _lastWindowState = state;
+
         if (Window == nullptr) {
             return S_OK;
         }
@@ -440,9 +443,6 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) {
 
         _inSetWindowState = true;
 
-        auto currentState = _actualWindowState;
-        _lastWindowState = state;
-
         if (currentState == Normal) {
             _preZoomSize = [Window frame];
         }

+ 1 - 2
samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml

@@ -10,8 +10,7 @@
                 Margin="0,16,0,0"
                 HorizontalAlignment="Center"
                 Spacing="16">
-      <StackPanel Orientation="Vertical"
-                  Width="200">
+      <StackPanel Orientation="Vertical">
         <TextBlock Text="SelectedDateFormat: Short"/>
         <CalendarDatePicker Name="DatePicker1"
                     SelectedDateFormat="Short"

+ 2 - 0
src/Avalonia.Base/Animation/IAnimation.cs

@@ -1,12 +1,14 @@
 using System;
 using System.Threading;
 using System.Threading.Tasks;
+using Avalonia.Metadata;
 
 namespace Avalonia.Animation
 {
     /// <summary>
     /// Interface for Animation objects
     /// </summary>
+    [NotClientImplementable]
     public interface IAnimation
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Animation/IAnimationSetter.cs

@@ -1,5 +1,8 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Animation
 {
+    [NotClientImplementable]
     public interface IAnimationSetter
     {
         AvaloniaProperty? Property { get; set; }

+ 2 - 0
src/Avalonia.Base/Animation/IAnimator.cs

@@ -1,11 +1,13 @@
 using System;
 using System.Collections.Generic;
+using Avalonia.Metadata;
 
 namespace Avalonia.Animation
 {
     /// <summary>
     /// Interface for Animator objects
     /// </summary>
+    [NotClientImplementable]
     public interface IAnimator : IList<AnimatorKeyFrame>
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Animation/IClock.cs

@@ -1,9 +1,9 @@
 using System;
-using System.Collections.Generic;
-using System.Text;
+using Avalonia.Metadata;
 
 namespace Avalonia.Animation
 {
+    [NotClientImplementable]
     public interface IClock : IObservable<TimeSpan>
     {
         PlayState PlayState { get; set; }

+ 2 - 3
src/Avalonia.Base/Animation/IGlobalClock.cs

@@ -1,9 +1,8 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
+using Avalonia.Metadata;
 
 namespace Avalonia.Animation
 {
+    [NotClientImplementable]
     public interface IGlobalClock : IClock
     {
     }

+ 2 - 0
src/Avalonia.Base/Animation/ITransition.cs

@@ -1,10 +1,12 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Animation
 {
     /// <summary>
     /// Interface for Transition objects.
     /// </summary>
+    [NotClientImplementable]
     public interface ITransition
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Controls/INameScope.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Threading.Tasks;
+using Avalonia.Metadata;
 using Avalonia.Utilities;
 
 namespace Avalonia.Controls
@@ -7,6 +6,7 @@ namespace Avalonia.Controls
     /// <summary>
     /// Defines a name scope.
     /// </summary>
+    [NotClientImplementable]
     public interface INameScope
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Controls/IPseudoClasses.cs

@@ -1,9 +1,11 @@
+using Avalonia.Metadata;
 
 namespace Avalonia.Controls
 {
     /// <summary>
     /// Exposes an interface for setting pseudoclasses on a <see cref="Classes"/> collection.
     /// </summary>
+    [NotClientImplementable]
     public interface IPseudoClasses
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Controls/IResourceHost.cs

@@ -1,6 +1,5 @@
 using System;
-
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Controls
 {
@@ -10,6 +9,7 @@ namespace Avalonia.Controls
     /// <remarks>
     /// This interface is implemented by <see cref="StyledElement"/> and `Application`.
     /// </remarks>
+    [NotClientImplementable]
     public interface IResourceHost : IResourceNode
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Controls/IResourceNode.cs

@@ -1,6 +1,5 @@
 using System;
-
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Controls
 {
@@ -12,6 +11,7 @@ namespace Avalonia.Controls
     /// (<see cref="IResourceHost"/>) and resource providers such as <see cref="ResourceDictionary"/>
     /// (see <see cref="IResourceProvider"/>).
     /// </remarks>
+    [NotClientImplementable]
     public interface IResourceNode
     {
         /// <summary>

+ 2 - 1
src/Avalonia.Base/Controls/ISetInheritanceParent.cs

@@ -1,4 +1,4 @@
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Controls
 {
@@ -10,6 +10,7 @@ namespace Avalonia.Controls
     /// Additionally, <see cref="ISetLogicalParent"/> also sets the inheritance parent; this
     /// interface is only needed where the logical and inheritance parents differ.
     /// </remarks>
+    [NotClientImplementable]
     public interface ISetInheritanceParent
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Controls/ISetLogicalParent.cs

@@ -1,6 +1,5 @@
 using Avalonia.LogicalTree;
-
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Controls
 {
@@ -10,6 +9,7 @@ namespace Avalonia.Controls
     /// <remarks>
     /// You should not usually need to use this interface - it is for advanced scenarios only.
     /// </remarks>
+    [NotClientImplementable]
     public interface ISetLogicalParent
     {
         /// <summary>

+ 23 - 23
src/Avalonia.Base/Data/Core/ExpressionNode.cs

@@ -98,36 +98,36 @@ namespace Avalonia.Data.Core
 
         private void ValueChanged(object? value, bool notify)
         {
-            if (_subscriber is null)
-                return;
-
-            var notification = value as BindingNotification;
-
-            if (notification == null)
+            if (_subscriber is { } subscriber)
             {
-                LastValue = value != null ? new WeakReference<object?>(value) : NullReference;
+                var notification = value as BindingNotification;
+                var next = Next;
 
-                if (Next != null)
+                if (notification == null)
                 {
-                    Next.Target = LastValue;
+                    LastValue = value != null ? new WeakReference<object?>(value) : NullReference;
+                    if (next != null)
+                    {
+                        next.Target = LastValue;
+                    }
+                    else if (notify)
+                    {
+                        subscriber(value);
+                    }
                 }
-                else if (notify)
+                else
                 {
-                    _subscriber(value);
-                }
-            }
-            else
-            {
-                LastValue = notification.Value != null ? new WeakReference<object?>(notification.Value) : NullReference;
+                    LastValue = notification.Value != null ? new WeakReference<object?>(notification.Value) : NullReference;
 
-                if (Next != null)
-                {
-                    Next.Target = LastValue;
-                }
+                    if (next != null)
+                    {
+                        next.Target = LastValue;
+                    }
 
-                if (Next == null || notification.Error != null)
-                {
-                    _subscriber(value);
+                    if (next == null || notification.Error != null)
+                    {
+                        subscriber(value);
+                    }
                 }
             }
         }

+ 2 - 0
src/Avalonia.Base/Data/Core/IPropertyInfo.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Data.Core
 {
+    [NotClientImplementable]
     public interface IPropertyInfo
     {
         string Name { get; }

+ 3 - 0
src/Avalonia.Base/Data/IBinding.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Data
 {
     /// <summary>
     /// Holds a binding that can be applied to a property on an object.
     /// </summary>
+    [NotClientImplementable]
     public interface IBinding
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/IAvaloniaObject.cs

@@ -1,11 +1,13 @@
 using System;
 using Avalonia.Data;
+using Avalonia.Metadata;
 
 namespace Avalonia
 {
     /// <summary>
     /// Interface for getting/setting <see cref="AvaloniaProperty"/> values on an object.
     /// </summary>
+    [NotClientImplementable]
     public interface IAvaloniaObject
     {
         /// <summary>

+ 2 - 1
src/Avalonia.Base/IDataContextProvider.cs

@@ -1,10 +1,11 @@
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia
 {
     /// <summary>
     /// Defines an element with a data context that can be used for binding.
     /// </summary>
+    [NotClientImplementable]
     public interface IDataContextProvider : IAvaloniaObject
     {
         /// <summary>

+ 1 - 0
src/Avalonia.Base/IDirectPropertyAccessor.cs

@@ -1,4 +1,5 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia
 {

+ 3 - 0
src/Avalonia.Base/IDirectPropertyMetadata.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia
 {
     /// <summary>
     /// Untyped interface to <see cref="DirectPropertyMetadata{TValue}"/>
     /// </summary>
+    [NotClientImplementable]
     public interface IDirectPropertyMetadata
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/IStyledElement.cs

@@ -2,12 +2,12 @@
 using System.ComponentModel;
 using Avalonia.Controls;
 using Avalonia.LogicalTree;
+using Avalonia.Metadata;
 using Avalonia.Styling;
 
-#nullable enable
-
 namespace Avalonia
 {
+    [NotClientImplementable]
     public interface IStyledElement :
         IStyleable,
         IStyleHost,

+ 3 - 0
src/Avalonia.Base/IStyledPropertyMetadata.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia
 {
     /// <summary>
     /// Untyped interface to <see cref="StyledPropertyMetadata{TValue}"/>
     /// </summary>
+    [NotClientImplementable]
     public interface IStyledPropertyMetadata
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Input/IAccessKeyHandler.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input
 {
     /// <summary>
     /// Defines the interface for classes that handle access keys for a window.
     /// </summary>
+    [Unstable]
     public interface IAccessKeyHandler
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Input/IFocusManager.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input
 {
     /// <summary>
     /// Manages focus for the application.
     /// </summary>
+    [NotClientImplementable]
     public interface IFocusManager
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IInputDevice.cs

@@ -1,7 +1,9 @@
 using Avalonia.Input.Raw;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input
 {
+    [NotClientImplementable]
     public interface IInputDevice
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IInputElement.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using Avalonia.Interactivity;
+using Avalonia.Metadata;
 using Avalonia.VisualTree;
 
 #nullable enable
@@ -10,6 +11,7 @@ namespace Avalonia.Input
     /// <summary>
     /// Defines input-related functionality for a control.
     /// </summary>
+    [NotClientImplementable]
     public interface IInputElement : IInteractive, IVisual
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IInputManager.cs

@@ -1,5 +1,6 @@
 using System;
 using Avalonia.Input.Raw;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input
 {
@@ -7,6 +8,7 @@ namespace Avalonia.Input
     /// Receives input from the windowing subsystem and dispatches it to interested parties
     /// for processing.
     /// </summary>
+    [NotClientImplementable]
     public interface IInputManager
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Input/IInputRoot.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input
 {
     /// <summary>
     /// Defines the interface for top-level input elements.
     /// </summary>
+    [NotClientImplementable]
     public interface IInputRoot : IInputElement
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IKeyboardDevice.cs

@@ -1,5 +1,6 @@
 using System;
 using System.ComponentModel;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input
 {
@@ -50,6 +51,7 @@ namespace Avalonia.Input
         KeyboardMask = Alt | Control | Shift | Meta
     }
 
+    [NotClientImplementable]
     public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged
     {
         IInputElement? FocusedElement { get; }

+ 3 - 0
src/Avalonia.Base/Input/IKeyboardNavigationHandler.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input
 {
     /// <summary>
     /// Defines the interface for classes that handle keyboard navigation for a window.
     /// </summary>
+    [Unstable]
     public interface IKeyboardNavigationHandler
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IMainMenu.cs

@@ -1,5 +1,6 @@
 using System;
 using Avalonia.Interactivity;
+using Avalonia.Metadata;
 using Avalonia.VisualTree;
 
 namespace Avalonia.Input
@@ -7,6 +8,7 @@ namespace Avalonia.Input
     /// <summary>
     /// Defines the interface for a window's main menu.
     /// </summary>
+    [NotClientImplementable]
     public interface IMainMenu : IVisual
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Input/IMouseDevice.cs

@@ -1,10 +1,12 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input
 {
     /// <summary>
     /// Represents a mouse device.
     /// </summary>
+    [NotClientImplementable]
     public interface IMouseDevice : IPointerDevice
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Input/IPointer.cs

@@ -1,5 +1,8 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input
 {
+    [NotClientImplementable]
     public interface IPointer
     {
         int Id { get; }

+ 2 - 0
src/Avalonia.Base/Input/IPointerDevice.cs

@@ -1,9 +1,11 @@
 using System;
 using Avalonia.VisualTree;
 using Avalonia.Input.Raw;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input
 {
+    [NotClientImplementable]
     public interface IPointerDevice : IInputDevice
     {
         /// <inheritdoc cref="IPointer.Captured" />

+ 2 - 0
src/Avalonia.Base/Input/Platform/IClipboard.cs

@@ -1,7 +1,9 @@
 using System.Threading.Tasks;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input.Platform
 {
+    [NotClientImplementable]
     public interface IClipboard
     {
         Task<string> GetTextAsync();

+ 2 - 0
src/Avalonia.Base/Input/Platform/IPlatformDragSource.cs

@@ -1,7 +1,9 @@
 using System.Threading.Tasks;
+using Avalonia.Metadata;
 
 namespace Avalonia.Input.Platform
 {
+    [Unstable]
     public interface IPlatformDragSource
     {
         Task<DragDropEffects> DoDragDrop(PointerEventArgs triggerEvent, IDataObject data, DragDropEffects allowedEffects);

+ 4 - 1
src/Avalonia.Base/Input/Raw/IDragDropDevice.cs

@@ -1,5 +1,8 @@
-namespace Avalonia.Input.Raw
+using Avalonia.Metadata;
+
+namespace Avalonia.Input.Raw
 {
+    [NotClientImplementable]
     public interface IDragDropDevice : IInputDevice
     {
     }

+ 4 - 0
src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs

@@ -1,5 +1,8 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Input.TextInput
 {
+    [Unstable]
     public interface ITextInputMethodImpl
     {
         void SetClient(ITextInputMethodClient? client);
@@ -8,6 +11,7 @@ namespace Avalonia.Input.TextInput
         void Reset();
     }
     
+    [NotClientImplementable]
     public interface ITextInputMethodRoot : IInputRoot
     {
         ITextInputMethodImpl? InputMethod { get; }

+ 2 - 0
src/Avalonia.Base/Interactivity/IInteractive.cs

@@ -1,4 +1,5 @@
 using System;
+using Avalonia.Metadata;
 
 #nullable enable
 
@@ -7,6 +8,7 @@ namespace Avalonia.Interactivity
     /// <summary>
     /// Interface for objects that raise routed events.
     /// </summary>
+    [NotClientImplementable]
     public interface IInteractive
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Layout/ILayoutManager.cs

@@ -1,12 +1,12 @@
 using System;
-
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Layout
 {
     /// <summary>
     /// Manages measuring and arranging of controls.
     /// </summary>
+    [NotClientImplementable]
     public interface ILayoutManager : IDisposable
     {
         /// <summary>

+ 3 - 0
src/Avalonia.Base/Layout/ILayoutRoot.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Layout
 {
     /// <summary>
     /// Defines the root of a layoutable tree.
     /// </summary>
+    [NotClientImplementable]
     public interface ILayoutRoot : ILayoutable
     {
         /// <summary>

+ 2 - 2
src/Avalonia.Base/Layout/ILayoutable.cs

@@ -1,12 +1,12 @@
+using Avalonia.Metadata;
 using Avalonia.VisualTree;
 
-#nullable enable
-
 namespace Avalonia.Layout
 {
     /// <summary>
     /// Defines layout-related functionality for a control.
     /// </summary>
+    [NotClientImplementable]
     public interface ILayoutable : IVisual
     {
         /// <summary>

+ 19 - 1
src/Avalonia.Base/Layout/Layoutable.cs

@@ -141,7 +141,6 @@ namespace Avalonia.Layout
         static Layoutable()
         {
             AffectsMeasure<Layoutable>(
-                IsVisibleProperty,
                 WidthProperty,
                 HeightProperty,
                 MinWidthProperty,
@@ -791,6 +790,25 @@ namespace Avalonia.Layout
         {
         }
 
+        protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+        {
+            base.OnPropertyChanged(change);
+
+            if (change.Property == IsVisibleProperty)
+            {
+                DesiredSize = default;
+
+                // All changes to visibility cause the parent element to be notified.
+                this.GetVisualParent<ILayoutable>()?.ChildDesiredSizeChanged(this);
+
+                // We only invalidate outselves when visibility is changed to true.
+                if (change.GetNewValue<bool>())
+                {
+                    InvalidateMeasure();
+                }
+            }
+        }
+
         /// <inheritdoc/>
         protected sealed override void OnVisualParentChanged(IVisual? oldParent, IVisual? newParent)
         {

+ 2 - 0
src/Avalonia.Base/LogicalTree/ILogical.cs

@@ -1,12 +1,14 @@
 using System;
 using Avalonia.Collections;
 using Avalonia.Controls;
+using Avalonia.Metadata;
 
 namespace Avalonia.LogicalTree
 {
     /// <summary>
     /// Represents a node in the logical tree.
     /// </summary>
+    [NotClientImplementable]
     public interface ILogical
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/LogicalTree/ILogicalRoot.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.LogicalTree
+using Avalonia.Metadata;
+
+namespace Avalonia.LogicalTree
 {
     /// <summary>
     /// Represents a root of a logical tree.
     /// </summary>
+    [NotClientImplementable]
     public interface ILogicalRoot : ILogical
     {
     }

+ 2 - 0
src/Avalonia.Base/Media/IBrush.cs

@@ -1,4 +1,5 @@
 using System.ComponentModel;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {
@@ -6,6 +7,7 @@ namespace Avalonia.Media
     /// Describes how an area is painted.
     /// </summary>
     [TypeConverter(typeof(BrushConverter))]
+    [NotClientImplementable]
     public interface IBrush
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Media/IConicGradientBrush.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Paints an area with a conic gradient.
     /// </summary>
+    [NotClientImplementable]
     public interface IConicGradientBrush : IGradientBrush
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Media/IDashStyle.cs

@@ -1,10 +1,12 @@
 using System.Collections.Generic;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {
     /// <summary>
     /// Represents the sequence of dashes and gaps that will be applied by a <see cref="Pen"/>.
     /// </summary>
+    [NotClientImplementable]
     public interface IDashStyle
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Media/IExperimentalAcrylicMaterial.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Experimental Interface for producing Acrylic-like materials.
     /// </summary>
+    [NotClientImplementable]
     public interface IExperimentalAcrylicMaterial
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Media/IGradientBrush.cs

@@ -1,10 +1,12 @@
 using System.Collections.Generic;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {
     /// <summary>
     /// A brush that draws with a gradient.
     /// </summary>
+    [NotClientImplementable]
     public interface IGradientBrush : IBrush
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Media/IGradientStop.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Describes the location and color of a transition point in a gradient.
     /// </summary>
+    [NotClientImplementable]
     public interface IGradientStop
     {
         /// <summary>

+ 3 - 1
src/Avalonia.Base/Media/IImageBrush.cs

@@ -1,10 +1,12 @@
 using Avalonia.Media.Imaging;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {
     /// <summary>
     /// Paints an area with an <see cref="IBitmap"/>.
     /// </summary>
+    [NotClientImplementable]
     public interface IImageBrush : ITileBrush
     {
         /// <summary>
@@ -12,4 +14,4 @@ namespace Avalonia.Media
         /// </summary>
         IBitmap Source { get; }
     }
-}
+}

+ 5 - 2
src/Avalonia.Base/Media/ILinearGradientBrush.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// A brush that draws with a linear gradient.
     /// </summary>
+    [NotClientImplementable]
     public interface ILinearGradientBrush : IGradientBrush
     {
         /// <summary>
@@ -15,4 +18,4 @@
         /// </summary>
         RelativePoint EndPoint { get; }
     }
-}
+}

+ 2 - 0
src/Avalonia.Base/Media/IMutableBrush.cs

@@ -1,10 +1,12 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {
     /// <summary>
     /// Represents a mutable brush which can return an immutable clone of itself.
     /// </summary>
+    [NotClientImplementable]
     public interface IMutableBrush : IBrush, IAffectsRender
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Media/IMutableExperimentalAcrylicMaterial.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Represents a mutable brush which can return an immutable clone of itself.
     /// </summary>
+    [NotClientImplementable]
     public interface IMutableExperimentalAcrylicMaterial : IExperimentalAcrylicMaterial, IAffectsRender
     {
         /// <summary>

+ 1 - 0
src/Avalonia.Base/Media/IMutableTransform.cs

@@ -1,4 +1,5 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
 {

+ 4 - 1
src/Avalonia.Base/Media/IPen.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Describes how a stroke is drawn.
     /// </summary>
+    [NotClientImplementable]
     public interface IPen
     {
         /// <summary>

+ 5 - 2
src/Avalonia.Base/Media/IRadialGradientBrush.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Media
+using Avalonia.Metadata;
+
+namespace Avalonia.Media
 {
     /// <summary>
     /// Paints an area with a radial gradient.
     /// </summary>
+    [NotClientImplementable]
     public interface IRadialGradientBrush : IGradientBrush
     {
         /// <summary>
@@ -21,4 +24,4 @@
         /// </summary>
         double Radius { get; }
     }
-}
+}

+ 4 - 1
src/Avalonia.Base/Media/ISolidColorBrush.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Media
 {
     /// <summary>
     /// Fills an area with a solid color.
     /// </summary>
+    [NotClientImplementable]
     public interface ISolidColorBrush : IBrush
     {
         /// <summary>
@@ -10,4 +13,4 @@ namespace Avalonia.Media
         /// </summary>
         Color Color { get; }
     }
-}
+}

+ 3 - 1
src/Avalonia.Base/Media/ITileBrush.cs

@@ -1,10 +1,12 @@
 using Avalonia.Media.Imaging;
+using Avalonia.Metadata;
 
 namespace Avalonia.Media
-{  
+{
     /// <summary>
     /// A brush which displays a repeating image.
     /// </summary>
+    [NotClientImplementable]
     public interface ITileBrush : IBrush
     {
         /// <summary>

+ 4 - 2
src/Avalonia.Base/Media/IVisualBrush.cs

@@ -1,10 +1,12 @@
-using Avalonia.VisualTree;
+using Avalonia.Metadata;
+using Avalonia.VisualTree;
 
 namespace Avalonia.Media
 {
     /// <summary>
     /// Paints an area with an <see cref="IVisual"/>.
     /// </summary>
+    [NotClientImplementable]
     public interface IVisualBrush : ITileBrush
     {
         /// <summary>
@@ -12,4 +14,4 @@ namespace Avalonia.Media
         /// </summary>
         IVisual Visual { get; }
     }
-}
+}

+ 2 - 0
src/Avalonia.Base/Media/Imaging/IBitmap.cs

@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using Avalonia.Metadata;
 using Avalonia.Platform;
 using Avalonia.Utilities;
 
@@ -8,6 +9,7 @@ namespace Avalonia.Media.Imaging
     /// <summary>
     /// Represents a bitmap image.
     /// </summary>
+    [NotClientImplementable]
     public interface IBitmap : IImage, IDisposable
     {
         /// <summary>

+ 3 - 1
src/Avalonia.Base/Media/TextFormatting/ITextSource.cs

@@ -1,4 +1,6 @@
-namespace Avalonia.Media.TextFormatting
+using Avalonia.Metadata;
+
+namespace Avalonia.Media.TextFormatting
 {
     /// <summary>
     /// Produces <see cref="TextRun"/> objects that are used by the <see cref="TextFormatter"/>.

+ 17 - 0
src/Avalonia.Base/Metadata/NotClientImplementableAttribute.cs

@@ -0,0 +1,17 @@
+using System;
+
+namespace Avalonia.Metadata
+{
+    /// <summary>
+    /// This interface is not intended to be implemented outside of the core Avalonia framework as
+    /// its API may change without warning.
+    /// </summary>
+    /// <remarks>
+    /// This interface is stable for consumption by a client, but should not be implemented as members
+    /// may be added to its API.
+    /// </remarks>
+    [AttributeUsage(AttributeTargets.Interface)]
+    public class NotClientImplementableAttribute : Attribute
+    {
+    }
+}

+ 12 - 0
src/Avalonia.Base/Metadata/UnstableAttribute.cs

@@ -0,0 +1,12 @@
+using System;
+
+namespace Avalonia.Metadata
+{
+    /// <summary>
+    /// This API is unstable and is not covered by API compatibility guarantees between minor and
+    /// patch releases.
+    /// </summary>
+    public class UnstableAttribute : Attribute
+    {
+    }
+}

+ 2 - 0
src/Avalonia.Base/Platform/IAssetLoader.cs

@@ -2,12 +2,14 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Loads assets compiled into the application binary.
     /// </summary>
+    [Unstable]
     public interface IAssetLoader
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IBitmapImpl.cs

@@ -1,11 +1,13 @@
 using System;
 using System.IO;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the platform-specific interface for a <see cref="Avalonia.Media.Imaging.Bitmap"/>.
     /// </summary>
+    [Unstable]
     public interface IBitmapImpl : IDisposable
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/ICursorImpl.cs

@@ -1,5 +1,6 @@
 using System;
 using Avalonia.Input;
+using Avalonia.Metadata;
 
 #nullable enable
 
@@ -8,6 +9,7 @@ namespace Avalonia.Platform
     /// <summary>
     /// Represents a platform implementation of a <see cref="Cursor"/>.
     /// </summary>
+    [Unstable]
     public interface ICursorImpl : IDisposable
     {
     }

+ 2 - 0
src/Avalonia.Base/Platform/IDrawingContextImpl.cs

@@ -3,12 +3,14 @@ using Avalonia.Media;
 using Avalonia.Rendering.SceneGraph;
 using Avalonia.Utilities;
 using Avalonia.Media.Imaging;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the interface through which drawing occurs.
     /// </summary>
+    [Unstable]
     public interface IDrawingContextImpl : IDisposable
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IFontManagerImpl.cs

@@ -1,9 +1,11 @@
 using System.Collections.Generic;
 using System.Globalization;
 using Avalonia.Media;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
+    [Unstable]
     public interface IFontManagerImpl
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IGeometryImpl.cs

@@ -1,10 +1,12 @@
 using Avalonia.Media;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the platform-specific interface for a <see cref="Geometry"/>.
     /// </summary>
+    [Unstable]
     public interface IGeometryImpl
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IGlyphRunImpl.cs

@@ -1,9 +1,11 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     ///     Actual implementation of a glyph run that stores platform dependent resources.
     /// </summary>
+    [Unstable]
     public interface IGlyphRunImpl : IDisposable { }
 }

+ 2 - 0
src/Avalonia.Base/Platform/IGlyphTypefaceImpl.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
+    [Unstable]
     public interface IGlyphTypefaceImpl : IDisposable
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IMacOSTopLevelPlatformHandle.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
+    [Unstable]
     public interface IMacOSTopLevelPlatformHandle
     {
         IntPtr NSView { get; }

+ 2 - 0
src/Avalonia.Base/Platform/IPlatformRenderInterface.cs

@@ -3,12 +3,14 @@ using System.Collections.Generic;
 using System.IO;
 using Avalonia.Media;
 using Avalonia.Media.Imaging;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the main platform-specific interface for the rendering subsystem.
     /// </summary>
+    [Unstable]
     public interface IPlatformRenderInterface
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/IPlatformSettings.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
+    [Unstable]
     public interface IPlatformSettings
     {
         Size DoubleClickSize { get; }

+ 2 - 0
src/Avalonia.Base/Platform/IPlatformThreadingInterface.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Threading;
+using Avalonia.Metadata;
 using Avalonia.Threading;
 
 namespace Avalonia.Platform
@@ -7,6 +8,7 @@ namespace Avalonia.Platform
     /// <summary>
     /// Provides platform-specific services relating to threading.
     /// </summary>
+    [Unstable]
     public interface IPlatformThreadingInterface
     {
         void RunLoop(CancellationToken cancellationToken);

+ 2 - 0
src/Avalonia.Base/Platform/IRenderTargetBitmapImpl.cs

@@ -1,3 +1,4 @@
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
@@ -5,6 +6,7 @@ namespace Avalonia.Platform
     /// Defines the platform-specific interface for a
     /// <see cref="Avalonia.Media.Imaging.RenderTargetBitmap"/>.
     /// </summary>
+    [Unstable]
     public interface IRenderTargetBitmapImpl : IBitmapImpl, IRenderTarget
     {
     }

+ 5 - 0
src/Avalonia.Base/Platform/IRuntimePlatform.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform
 {
+    [Unstable]
     public interface IRuntimePlatform
     {
         IDisposable StartSystemTimer(TimeSpan interval, Action tick);
@@ -9,6 +11,7 @@ namespace Avalonia.Platform
         IUnmanagedBlob AllocBlob(int size);
     }
 
+    [Unstable]
     public interface IUnmanagedBlob : IDisposable
     {
         IntPtr Address { get; }
@@ -17,6 +20,7 @@ namespace Avalonia.Platform
         
     }
 
+    [Unstable]
     public struct RuntimePlatformInfo
     {
         public OperatingSystemType OperatingSystem { get; set; }
@@ -29,6 +33,7 @@ namespace Avalonia.Platform
         public bool IsUnix { get; set; }
     }
 
+    [Unstable]
     public enum OperatingSystemType
     {
         Unknown,

+ 3 - 0
src/Avalonia.Base/Platform/IStreamGeometryContextImpl.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Describes a geometry using drawing commands.
     /// </summary>
+    [Unstable]
     public interface IStreamGeometryContextImpl : IGeometryContext
     {      
     }

+ 3 - 0
src/Avalonia.Base/Platform/IStreamGeometryImpl.cs

@@ -1,8 +1,11 @@
+using Avalonia.Metadata;
+
 namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the platform-specific interface for a <see cref="Avalonia.Media.StreamGeometry"/>.
     /// </summary>
+    [Unstable]
     public interface IStreamGeometryImpl : IGeometryImpl
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Platform/ITextShaperImpl.cs

@@ -1,4 +1,5 @@
 using Avalonia.Media.TextFormatting;
+using Avalonia.Metadata;
 using Avalonia.Utilities;
 
 namespace Avalonia.Platform
@@ -6,6 +7,7 @@ namespace Avalonia.Platform
     /// <summary>
     /// An abstraction that is used produce shaped text.
     /// </summary>
+    [Unstable]
     public interface ITextShaperImpl
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Platform/ITransformedGeometryImpl.cs

@@ -1,4 +1,6 @@
-namespace Avalonia.Platform
+using Avalonia.Metadata;
+
+namespace Avalonia.Platform
 {
     /// <summary>
     /// Represents a geometry with a transform applied.
@@ -7,6 +9,7 @@
     /// An <see cref="ITransformedGeometryImpl"/> transforms a geometry without transforming its
     /// stroke thickness.
     /// </remarks>
+    [Unstable]
     public interface ITransformedGeometryImpl : IGeometryImpl
     {
         /// <summary>

+ 4 - 1
src/Avalonia.Base/Platform/IWriteableBitmapImpl.cs

@@ -1,8 +1,11 @@
-namespace Avalonia.Platform
+using Avalonia.Metadata;
+
+namespace Avalonia.Platform
 {
     /// <summary>
     /// Defines the platform-specific interface for a <see cref="Avalonia.Media.Imaging.WriteableBitmap"/>.
     /// </summary>
+    [Unstable]
     public interface IWriteableBitmapImpl : IBitmapImpl
     {
         ILockedFramebuffer Lock();

+ 2 - 0
src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Platform.Interop
 {
+    [Unstable]
     public interface IDynamicLibraryLoader
     {
         IntPtr LoadLibrary(string dll);

+ 2 - 0
src/Avalonia.Base/Rendering/IDeferredRendererLock.cs

@@ -1,7 +1,9 @@
 using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Rendering
 {
+    [Unstable]
     public interface IDeferredRendererLock
     {
         IDisposable? TryLock();

+ 4 - 1
src/Avalonia.Base/Rendering/IRenderLoop.cs

@@ -1,4 +1,6 @@
-namespace Avalonia.Rendering
+using Avalonia.Metadata;
+
+namespace Avalonia.Rendering
 {
     /// <summary>
     /// The application render loop.
@@ -7,6 +9,7 @@
     /// The render loop is responsible for advancing the animation timer and updating the scene
     /// graph for visible windows.
     /// </remarks>
+    [NotClientImplementable]
     public interface IRenderLoop
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Rendering/IRenderRoot.cs

@@ -1,3 +1,4 @@
+using Avalonia.Metadata;
 using Avalonia.Platform;
 using Avalonia.VisualTree;
 
@@ -6,6 +7,7 @@ namespace Avalonia.Rendering
     /// <summary>
     /// Represents the root of a renderable tree.
     /// </summary>
+    [NotClientImplementable]
     public interface IRenderRoot : IVisual
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Rendering/IRenderTimer.cs

@@ -1,11 +1,13 @@
 using System;
 using System.Threading.Tasks;
+using Avalonia.Metadata;
 
 namespace Avalonia.Rendering
 {
     /// <summary>
     /// Defines the interface implemented by an application render timer.
     /// </summary>
+    [NotClientImplementable]
     public interface IRenderTimer
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Rendering/IVisualBrushInitialize.cs

@@ -1,4 +1,5 @@
 using Avalonia.Media;
+using Avalonia.Metadata;
 
 namespace Avalonia.Rendering
 {
@@ -6,6 +7,7 @@ namespace Avalonia.Rendering
     /// Internal interface for initializing controls that are to be used as the visual in a
     /// <see cref="VisualBrush"/>.
     /// </summary>
+    [Unstable]
     public interface IVisualBrushInitialize
     {
         /// <summary>

+ 2 - 0
src/Avalonia.Base/Rendering/IVisualBrushRenderer.cs

@@ -1,4 +1,5 @@
 using Avalonia.Media;
+using Avalonia.Metadata;
 using Avalonia.Platform;
 
 namespace Avalonia.Rendering
@@ -6,6 +7,7 @@ namespace Avalonia.Rendering
     /// <summary>
     /// Defines a renderer used to render a visual brush to a bitmap.
     /// </summary>
+    [Unstable]
     public interface IVisualBrushRenderer
     {
         /// <summary>

+ 3 - 3
src/Avalonia.Base/Styling/Activators/IStyleActivator.cs

@@ -1,6 +1,5 @@
-#nullable enable
-
-using System;
+using System;
+using Avalonia.Metadata;
 
 namespace Avalonia.Styling.Activators
 {
@@ -16,6 +15,7 @@ namespace Avalonia.Styling.Activators
     /// - The subscription can have a tag associated with it, allowing a subscriber to index
     ///   into a list of subscriptions without having to allocate additional objects.
     /// </remarks>
+    [Unstable]
     public interface IStyleActivator : IDisposable
     {
         /// <summary>

+ 2 - 1
src/Avalonia.Base/Styling/Activators/IStyleActivatorSink.cs

@@ -1,10 +1,11 @@
-#nullable enable
+using Avalonia.Metadata;
 
 namespace Avalonia.Styling.Activators
 {
     /// <summary>
     /// Receives notifications from an <see cref="IStyleActivator"/>.
     /// </summary>
+    [Unstable]
     public interface IStyleActivatorSink
     {
         /// <summary>

Some files were not shown because too many files changed in this diff