Browse Source
# Conflicts: # api/Avalonia.nupkg.xml # src/Tizen/Avalonia.Tizen/TopLevelImpl.cspull/16340/head
1057 changed files with 26964 additions and 29713 deletions
@ -1,22 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Android.AvaloniaMainActivity`1</Target> |
|
||||
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left> |
|
||||
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Android.AndroidViewControlHandle.get_HandleDescriptor</Target> |
|
||||
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left> |
|
||||
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.Android.AndroidViewControlHandle</Target> |
|
||||
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left> |
|
||||
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,22 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Browser.JSObjectControlHandle.get_Handle</Target> |
|
||||
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left> |
|
||||
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Browser.JSObjectControlHandle.get_HandleDescriptor</Target> |
|
||||
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left> |
|
||||
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.Browser.JSObjectControlHandle</Target> |
|
||||
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left> |
|
||||
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,10 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Tmds.DBus.SourceGenerator.PropertyChanges`1</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.FreeDesktop.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.FreeDesktop.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Skia.SkiaSharpExtensions.ToSKFilterQuality(Avalonia.Media.Imaging.BitmapInterpolationMode)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Skia.ISkiaGpuWithPlatformGraphicsContext.TryGetGrContext</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0008</DiagnosticId> |
|
||||
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,214 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.DockPosition</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IDockProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IExpandCollapseProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IGridItemProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IGridProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IInvokeProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IMultipleViewProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRangeValueProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderAdviseEvents</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderFragment</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderFragmentRoot</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderSimple</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderSimple2</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IScrollItemProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IScrollProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ISelectionItemProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ISelectionProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ISynchronizedInputProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ITableItemProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ITableProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ITextProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ITextRangeProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IToggleProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ITransformProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IValueProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.IWindowProvider</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.NavigateDirection</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.ProviderOptions</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.RowOrColumnMajor</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.SupportedTextSelection</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.SynchronizedInputType</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.TextPatternRangeEndpoint</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.TextUnit</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.WindowInteractionState</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Win32.Interop.Automation.WindowVisualState</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,16 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
|
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.iOS.UIViewControlHandle.get_HandleDescriptor</Target> |
|
||||
<Left>baseline/net8.0-tvos17.0/Avalonia.iOS.dll</Left> |
|
||||
<Right>target/net8.0-tvos17.0/Avalonia.iOS.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.iOS.UIViewControlHandle</Target> |
|
||||
<Left>baseline/net8.0-tvos17.0/Avalonia.iOS.dll</Left> |
|
||||
<Right>target/net8.0-tvos17.0/Avalonia.iOS.dll</Right> |
|
||||
</Suppression> |
|
||||
</Suppressions> |
|
||||
@ -1,272 +1,40 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> |
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids --> |
||||
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> |
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Controls.PseudolassesExtensions</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.CastTypePropertyPathElement</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.ChildTraversalPropertyPathElement</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.EnsureTypePropertyPathElement</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.IPropertyPathElement</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.PropertyPath</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.PropertyPathBuilder</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Data.Core.PropertyPropertyPathElement</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Utilities.CharacterReader</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Utilities.IdentifierParser</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Utilities.KeywordParser</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0001</DiagnosticId> |
|
||||
<Target>T:Avalonia.Utilities.StyleClassParser</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_HasActivator</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_IsActive</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_Style</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.StyledElementExtensions.GetStyleDiagnostics(Avalonia.StyledElement)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.StyleDiagnostics.#ctor(System.Collections.Generic.IReadOnlyList{Avalonia.Diagnostics.AppliedStyle})</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Diagnostics.StyleDiagnostics.get_AppliedStyles</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0002</DiagnosticId> |
<DiagnosticId>CP0002</DiagnosticId> |
||||
<Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> |
<Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
|
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.get_IsCompleted</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.GetAwaiter</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.GetResult</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
</Suppression> |
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0002</DiagnosticId> |
<DiagnosticId>CP0002</DiagnosticId> |
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.OnCompleted(System.Action)</Target> |
<Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
</Suppression> |
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0002</DiagnosticId> |
<DiagnosticId>CP0002</DiagnosticId> |
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable`1.GetAwaiter</Target> |
<Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable`1.GetResult</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0002</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Primitives.IPopupHost.ConfigurePosition(Avalonia.Visual,Avalonia.Controls.PlacementMode,Avalonia.Point,Avalonia.Controls.Primitives.PopupPositioning.PopupAnchor,Avalonia.Controls.Primitives.PopupPositioning.PopupGravity,Avalonia.Controls.Primitives.PopupPositioning.PopupPositionerConstraintAdjustment,System.Nullable{Avalonia.Rect})</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
</Suppression> |
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0002</DiagnosticId> |
<DiagnosticId>CP0002</DiagnosticId> |
||||
<Target>M:Avalonia.Controls.Screens.#ctor(Avalonia.Platform.IScreenImpl)</Target> |
<Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Input.Platform.IClipboard.FlushAsync</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetInProcessDataObjectAsync</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Platform.Storage.IStorageFolder.GetFileAsync(System.String)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Platform.Storage.IStorageFolder.GetFolderAsync(System.String)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Notifications.IManagedNotificationManager.Close(System.Object)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Notifications.INotificationManager.Close(Avalonia.Controls.Notifications.INotification)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Notifications.INotificationManager.CloseAll</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Primitives.IPopupHost.ConfigurePosition(Avalonia.Controls.Primitives.PopupPositioning.PopupPositionRequest)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0006</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Primitives.IPopupHost.TakeFocus</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
</Suppression> |
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0006</DiagnosticId> |
<DiagnosticId>CP0006</DiagnosticId> |
||||
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplayEdgeToEdgePreference</Target> |
<Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(System.Nullable{Avalonia.Platform.PlatformThemeVariant})</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
</Suppression> |
||||
<Suppression> |
<Suppression> |
||||
<DiagnosticId>CP0006</DiagnosticId> |
<DiagnosticId>CP0006</DiagnosticId> |
||||
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplaysEdgeToEdge</Target> |
<Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(System.Nullable{Avalonia.Platform.PlatformThemeVariant})</Target> |
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left> |
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right> |
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0007</DiagnosticId> |
|
||||
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable`1</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0008</DiagnosticId> |
|
||||
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0008</DiagnosticId> |
|
||||
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable`1</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0009</DiagnosticId> |
|
||||
<Target>T:Avalonia.Diagnostics.StyleDiagnostics</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0009</DiagnosticId> |
|
||||
<Target>T:Avalonia.Controls.Screens</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
|
||||
<Suppression> |
|
||||
<DiagnosticId>CP0012</DiagnosticId> |
|
||||
<Target>M:Avalonia.Controls.Button.OnAccessKey(Avalonia.Interactivity.RoutedEventArgs)</Target> |
|
||||
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> |
|
||||
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> |
|
||||
</Suppression> |
</Suppression> |
||||
</Suppressions> |
</Suppressions> |
||||
|
|||||
@ -1,12 +1,8 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<!-- '!NET6_0_OR_GREATER' equivalent --> |
<!-- '!NET8_0_OR_GREATER' equivalent --> |
||||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))"> |
|
||||
<PackageReference Include="System.Memory" Version="4.5.5" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))"> |
|
||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" /> |
|
||||
</ItemGroup> |
|
||||
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))"> |
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))"> |
||||
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" /> |
<PackageReference Include="System.Memory" Version="4.5.5" /> |
||||
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" /> |
||||
|
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.10" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,7 +1,7 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="HarfBuzzSharp" Version="8.3.1.1" /> |
<PackageReference Include="HarfBuzzSharp" Version="8.3.1.2" /> |
||||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.1" /> |
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.2" /> |
||||
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.1" /> |
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.2" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.10" /> |
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.12" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,5 +0,0 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||
<ItemGroup> |
|
||||
<PackageReference Include="JetBrains.DotMemoryUnit" Version="3.2.20220510" /> |
|
||||
</ItemGroup> |
|
||||
</Project> |
|
||||
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="Microsoft.Reactive.Testing" Version="4.1.6" /> |
<PackageReference Include="Microsoft.Reactive.Testing" Version="6.1.0" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="Moq" Version="4.18.4" /> |
<PackageReference Include="Moq" Version="4.20.72" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,5 +0,0 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||
<ItemGroup> |
|
||||
<PackageReference Include="ReactiveUI" Version="20.1.1" /> |
|
||||
</ItemGroup> |
|
||||
</Project> |
|
||||
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="System.Reactive" Version="6.0.1" /> |
<PackageReference Include="System.Reactive" Version="6.1.0" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,7 +1,7 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="SkiaSharp" Version="3.119.0" /> |
<PackageReference Include="SkiaSharp" Version="3.119.1" /> |
||||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="3.119.0" /> |
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="3.119.1" /> |
||||
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.0" /> |
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.1" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1 +1 @@ |
|||||
Subproject commit 83567b8a50bbf612a0b1420a3dc6d8e8ebee2399 |
Subproject commit c32d3040e536ae9768233ea5a445697632578bd0 |
||||
@ -0,0 +1,7 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "common.h" |
||||
|
|
||||
|
@interface WriteableClipboardItem : NSObject <NSPasteboardWriting> |
||||
|
- (nonnull instancetype) initWithItem:(nonnull IAvnClipboardDataItem*)item source:(nonnull IAvnClipboardDataSource*)source; |
||||
|
@end |
||||
@ -1,206 +1,354 @@ |
|||||
|
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h> |
||||
#include "common.h" |
#include "common.h" |
||||
|
#include "clipboard.h" |
||||
#include "AvnString.h" |
#include "AvnString.h" |
||||
|
|
||||
class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard> |
class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard> |
||||
{ |
{ |
||||
private: |
private: |
||||
NSPasteboard* _pb; |
NSPasteboard* _pasteboard; |
||||
NSPasteboardItem* _item; |
|
||||
public: |
public: |
||||
FORWARD_IUNKNOWN() |
FORWARD_IUNKNOWN() |
||||
|
|
||||
Clipboard(NSPasteboard* pasteboard, NSPasteboardItem* item) |
Clipboard(NSPasteboard* pasteboard) |
||||
{ |
{ |
||||
if(pasteboard == nil && item == nil) |
if (pasteboard == nil) |
||||
pasteboard = [NSPasteboard generalPasteboard]; |
pasteboard = [NSPasteboard generalPasteboard]; |
||||
|
|
||||
_pb = pasteboard; |
_pasteboard = pasteboard; |
||||
_item = item; |
|
||||
} |
} |
||||
|
|
||||
NSPasteboardItem* TryGetItem() |
virtual HRESULT GetFormats(int64_t changeCount, IAvnStringArray** ret) override |
||||
{ |
{ |
||||
return _item; |
START_COM_ARP_CALL; |
||||
|
|
||||
|
if (ret == nullptr) |
||||
|
return E_POINTER; |
||||
|
|
||||
|
if (changeCount != [_pasteboard changeCount]) |
||||
|
return COR_E_OBJECTDISPOSED; |
||||
|
|
||||
|
*ret = ConvertPasteboardTypes([_pasteboard types]); |
||||
|
return S_OK; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT GetText (char* type, IAvnString**ppv) override |
virtual HRESULT GetItemCount(int64_t changeCount, int* ret) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
@autoreleasepool |
if (ret == nullptr) |
||||
|
return E_POINTER; |
||||
|
|
||||
|
if (changeCount != [_pasteboard changeCount]) |
||||
|
return COR_E_OBJECTDISPOSED; |
||||
|
|
||||
|
auto items = [_pasteboard pasteboardItems]; |
||||
|
*ret = items == nil ? 0 : (int)[items count]; |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
virtual HRESULT GetItemFormats(int index, int64_t changeCount, IAvnStringArray** ret) override |
||||
|
{ |
||||
|
START_COM_ARP_CALL; |
||||
|
|
||||
|
if (ret == nullptr) |
||||
|
return E_POINTER; |
||||
|
|
||||
|
if (changeCount != [_pasteboard changeCount]) |
||||
|
return COR_E_OBJECTDISPOSED; |
||||
|
|
||||
|
auto item = [[_pasteboard pasteboardItems] objectAtIndex:index]; |
||||
|
|
||||
|
*ret = ConvertPasteboardTypes([item types]); |
||||
|
return S_OK; |
||||
|
} |
||||
|
|
||||
|
static IAvnStringArray* ConvertPasteboardTypes(NSArray<NSPasteboardType> *types) |
||||
|
{ |
||||
|
if (types != nil) |
||||
{ |
{ |
||||
if(ppv == nullptr) |
NSMutableArray<NSString *> *mutableTypes = [types mutableCopy]; |
||||
|
|
||||
|
// Add png if format list doesn't have PNG, |
||||
|
// but has any other image type that can be converter into PNG |
||||
|
if (![mutableTypes containsObject:NSPasteboardTypePNG]) |
||||
{ |
{ |
||||
return E_POINTER; |
if ([mutableTypes containsObject:NSPasteboardTypeTIFF] |
||||
|
|| [mutableTypes containsObject:@"public.jpeg"]) |
||||
|
{ |
||||
|
[mutableTypes addObject: NSPasteboardTypePNG]; |
||||
|
} |
||||
} |
} |
||||
NSString* typeString = [NSString stringWithUTF8String:(const char*)type]; |
|
||||
NSString* string = _item == nil ? [_pb stringForType:typeString] : [_item stringForType:typeString]; |
return CreateAvnStringArray(mutableTypes); |
||||
|
|
||||
*ppv = CreateAvnString(string); |
|
||||
|
|
||||
return S_OK; |
|
||||
} |
} |
||||
|
|
||||
|
return nil; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT SetStrings(char* type, IAvnStringArray*ppv) override |
virtual HRESULT GetItemValueAsString(int index, int64_t changeCount, const char* format, IAvnString** ret) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
@autoreleasepool |
if (ret == nullptr) |
||||
{ |
return E_POINTER; |
||||
NSArray<NSString*>* data = GetNSArrayOfStringsAndRelease(ppv); |
|
||||
NSString* typeString = [NSString stringWithUTF8String:(const char*)type]; |
if (changeCount != [_pasteboard changeCount]) |
||||
if(_item == nil) |
return COR_E_OBJECTDISPOSED; |
||||
[_pb setPropertyList: data forType: typeString]; |
|
||||
else |
auto item = [[_pasteboard pasteboardItems] objectAtIndex:index]; |
||||
[_item setPropertyList: data forType:typeString]; |
auto value = [item stringForType:[NSString stringWithUTF8String:format]]; |
||||
return S_OK; |
*ret = value == nil ? nullptr : CreateAvnString(value); |
||||
} |
return S_OK; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override |
virtual HRESULT GetItemValueAsBytes(int index, int64_t changeCount, const char* format, IAvnString** ret) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
@autoreleasepool |
if (ret == nullptr) |
||||
|
return E_POINTER; |
||||
|
|
||||
|
if (changeCount != [_pasteboard changeCount]) |
||||
|
return COR_E_OBJECTDISPOSED; |
||||
|
|
||||
|
auto item = [[_pasteboard pasteboardItems] objectAtIndex:index]; |
||||
|
auto formatStr = [NSString stringWithUTF8String:format]; |
||||
|
|
||||
|
auto value = [item dataForType: formatStr]; |
||||
|
|
||||
|
// If PNG wasn't found, try to convert TIFF or JPEG to PNG |
||||
|
if (value == nil && [formatStr isEqualToString: NSPasteboardTypePNG]) |
||||
{ |
{ |
||||
*ppv= nil; |
NSData *imageData = nil; |
||||
NSString* typeString = [NSString stringWithUTF8String:(const char*)type]; |
|
||||
NSObject* data = _item == nil ? [_pb propertyListForType: typeString] : [_item propertyListForType: typeString]; |
// Try TIFF first |
||||
if(data == nil) |
imageData = [item dataForType:NSPasteboardTypeTIFF]; |
||||
return S_OK; |
|
||||
|
// If no TIFF, try JPEG |
||||
if([data isKindOfClass: [NSString class]]) |
if (imageData == nil) { |
||||
|
imageData = [item dataForType:@"public.jpeg"]; |
||||
|
} |
||||
|
|
||||
|
if (imageData != nil) |
||||
{ |
{ |
||||
*ppv = CreateAvnStringArray((NSString*) data); |
auto image = [[NSImage alloc] initWithData:imageData]; |
||||
return S_OK; |
|
||||
|
NSBitmapImageRep *bitmapRep = nil; |
||||
|
for (NSImageRep *rep in image.representations) { |
||||
|
if ([rep isKindOfClass:[NSBitmapImageRep class]]) { |
||||
|
bitmapRep = (NSBitmapImageRep *)rep; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!bitmapRep) { |
||||
|
[image lockFocus]; |
||||
|
bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, image.size.width, image.size.height)]; |
||||
|
[image unlockFocus]; |
||||
|
} |
||||
|
|
||||
|
value = [bitmapRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; |
||||
} |
} |
||||
|
|
||||
NSArray<NSString*>* arr = (NSArray*)data; |
|
||||
|
|
||||
for(int c = 0; c < [arr count]; c++) |
|
||||
if(![[arr objectAtIndex:c] isKindOfClass:[NSString class]]) |
|
||||
return E_INVALIDARG; |
|
||||
|
|
||||
*ppv = CreateAvnStringArray(arr); |
|
||||
return S_OK; |
|
||||
} |
} |
||||
|
|
||||
|
*ret = value == nil || [value length] == 0 |
||||
|
? nullptr |
||||
|
: CreateByteArray((void*)[value bytes], (int)[value length]); |
||||
|
return S_OK; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT SetText (char* type, char* utf8String) override |
virtual HRESULT Clear(int64_t* ret) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
@autoreleasepool |
*ret = [_pasteboard clearContents]; |
||||
{ |
return S_OK; |
||||
auto string = [NSString stringWithUTF8String:(const char*)utf8String]; |
} |
||||
auto typeString = [NSString stringWithUTF8String:(const char*)type]; |
|
||||
if(_item == nil) |
virtual HRESULT GetChangeCount(int64_t* ret) override |
||||
[_pb setString: string forType: typeString]; |
{ |
||||
else |
START_COM_ARP_CALL; |
||||
[_item setString: string forType:typeString]; |
|
||||
|
|
||||
return S_OK; |
*ret = [_pasteboard changeCount]; |
||||
} |
return S_OK; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT SetBytes(char* type, void* bytes, int len) override |
virtual HRESULT SetData(IAvnClipboardDataSource* source) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
@autoreleasepool |
auto count = source->GetItemCount(); |
||||
|
auto writeableItems = [NSMutableArray<WriteableClipboardItem*> arrayWithCapacity:count]; |
||||
|
|
||||
|
for (auto i = 0; i < count; ++i) |
||||
{ |
{ |
||||
auto typeString = [NSString stringWithUTF8String:(const char*)type]; |
auto item = source->GetItem(i); |
||||
auto data = [NSData dataWithBytes:bytes length:len]; |
auto writeableItem = [[WriteableClipboardItem alloc] initWithItem:item source:source]; |
||||
if(_item == nil) |
[writeableItems addObject:writeableItem]; |
||||
[_pb setData:data forType:typeString]; |
|
||||
else |
|
||||
[_item setData:data forType:typeString]; |
|
||||
return S_OK; |
|
||||
} |
} |
||||
|
|
||||
|
[_pasteboard writeObjects:writeableItems]; |
||||
|
return S_OK; |
||||
} |
} |
||||
|
|
||||
virtual HRESULT GetBytes(char* type, IAvnString**ppv) override |
virtual bool IsTextFormat(const char *format) override |
||||
{ |
{ |
||||
START_COM_CALL; |
START_COM_ARP_CALL; |
||||
|
|
||||
|
auto formatString = [NSString stringWithUTF8String:format]; |
||||
|
|
||||
@autoreleasepool |
if (@available(macOS 11.0, *)) |
||||
{ |
{ |
||||
*ppv = nil; |
auto type = [UTType typeWithIdentifier:formatString]; |
||||
auto typeString = [NSString stringWithUTF8String:(const char*)type]; |
return type != nil && [type conformsToType:UTTypeText]; |
||||
NSData*data; |
} |
||||
@try |
else |
||||
{ |
{ |
||||
if(_item) |
return UTTypeConformsTo((__bridge CFStringRef)formatString, kUTTypeText); |
||||
data = [_item dataForType:typeString]; |
|
||||
else |
|
||||
data = [_pb dataForType:typeString]; |
|
||||
if(data == nil) |
|
||||
return E_FAIL; |
|
||||
} |
|
||||
@catch(NSException* e) |
|
||||
{ |
|
||||
return E_FAIL; |
|
||||
} |
|
||||
*ppv = CreateByteArray((void*)data.bytes, (int)data.length); |
|
||||
return S_OK; |
|
||||
} |
} |
||||
} |
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
virtual HRESULT Clear(int64_t* rv) override |
extern IAvnClipboard* CreateClipboard(NSPasteboard* pb) |
||||
|
{ |
||||
|
return new Clipboard(pb); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
@implementation WriteableClipboardItem |
||||
|
{ |
||||
|
IAvnClipboardDataItem* _item; |
||||
|
IAvnClipboardDataSource* _source; |
||||
|
} |
||||
|
|
||||
|
- (nonnull WriteableClipboardItem*) initWithItem:(nonnull IAvnClipboardDataItem*)item source:(nonnull IAvnClipboardDataSource*)source |
||||
|
{ |
||||
|
self = [super init]; |
||||
|
_item = item; |
||||
|
_source = source; |
||||
|
|
||||
|
// Each item references its source so it doesn't get disposed too early. |
||||
|
source->AddRef(); |
||||
|
|
||||
|
return self; |
||||
|
} |
||||
|
|
||||
|
NSString* TryConvertFormatToUti(NSString* format) |
||||
|
{ |
||||
|
if (@available(macOS 11.0, *)) |
||||
{ |
{ |
||||
START_COM_CALL; |
auto type = [UTType typeWithIdentifier:format]; |
||||
|
if (type == nil) |
||||
@autoreleasepool |
|
||||
{ |
{ |
||||
if(_item != nil) |
if ([format containsString:@"/"]) |
||||
{ |
type = [UTType typeWithMIMEType:format]; |
||||
_item = [NSPasteboardItem new]; |
|
||||
return 0; |
|
||||
} |
|
||||
else |
else |
||||
|
type = [UTType exportedTypeWithIdentifier:format]; |
||||
|
|
||||
|
if (type == nil) |
||||
{ |
{ |
||||
*rv = [_pb clearContents]; |
// For now, we need to use the deprecated UTTypeCreatePreferredIdentifierForTag to create a dynamic UTI for arbitrary strings. |
||||
[_pb setString:@"" forType:NSPasteboardTypeString]; |
// This is only necessary because the old IDataObject can provide arbitrary types that aren't UTIs nor mime types. |
||||
|
// With the new DataFormat: |
||||
|
// - If the format is an application format, the managed side provides a UTI like net.avaloniaui.app.uti.xxx. |
||||
|
// - If the format is an OS format, the user has been warned that they MUST provide a name which is valid for the OS. |
||||
|
// TODO12: remove! |
||||
|
auto fromPasteboardType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, (__bridge CFStringRef)format, nil); |
||||
|
if (fromPasteboardType != nil) |
||||
|
return (__bridge_transfer NSString*)fromPasteboardType; |
||||
} |
} |
||||
|
|
||||
return S_OK; |
|
||||
} |
} |
||||
|
|
||||
|
return type == nil ? nil : [type identifier]; |
||||
} |
} |
||||
|
else |
||||
virtual HRESULT GetChangeCount(int64_t* rv) override |
|
||||
{ |
{ |
||||
START_COM_CALL; |
auto bridgedFormat = (__bridge CFStringRef)format; |
||||
if(_item == nil) |
if (UTTypeIsDeclared(bridgedFormat)) |
||||
{ |
return format; |
||||
*rv = [_pb changeCount]; |
|
||||
return S_OK; |
auto fromMimeType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, bridgedFormat, nil); |
||||
} |
if (fromMimeType != nil) |
||||
return E_NOTIMPL; |
return (__bridge_transfer NSString*)fromMimeType; |
||||
|
|
||||
|
auto fromPasteboardType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, bridgedFormat, nil); |
||||
|
if (fromPasteboardType != nil) |
||||
|
return (__bridge_transfer NSString*)fromPasteboardType; |
||||
|
|
||||
|
return nil; |
||||
} |
} |
||||
|
} |
||||
|
|
||||
|
- (nonnull NSArray<NSPasteboardType>*) writableTypesForPasteboard:(nonnull NSPasteboard*)pasteboard |
||||
|
{ |
||||
|
auto formats = _item->ProvideFormats(); |
||||
|
if (formats == nullptr) |
||||
|
return [NSArray array]; |
||||
|
|
||||
virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override |
auto count = formats->GetCount(); |
||||
|
if (count == 0) |
||||
|
return [NSArray array]; |
||||
|
|
||||
|
auto utis = [NSMutableArray arrayWithCapacity:count]; |
||||
|
IAvnString* format; |
||||
|
for (auto i = 0; i < count; ++i) |
||||
{ |
{ |
||||
START_COM_CALL; |
if (formats->Get(i, &format) != S_OK) |
||||
|
continue; |
||||
@autoreleasepool |
|
||||
{ |
// Only UTIs must be returned from writableTypesForPasteboard or an exception will be thrown |
||||
*ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]); |
auto formatString = GetNSStringAndRelease(format); |
||||
return S_OK; |
auto uti = TryConvertFormatToUti(formatString); |
||||
} |
if (uti != nil) |
||||
|
[utis addObject:uti]; |
||||
} |
} |
||||
}; |
formats->Release(); |
||||
|
|
||||
|
[utis addObject:GetAvnCustomDataType()]; |
||||
|
|
||||
|
return utis; |
||||
|
} |
||||
|
|
||||
extern IAvnClipboard* CreateClipboard(NSPasteboard* pb, NSPasteboardItem* item) |
- (NSPasteboardWritingOptions) writingOptionsForType:(NSPasteboardType)type pasteboard:(NSPasteboard*)pasteboard |
||||
{ |
{ |
||||
return new Clipboard(pb, item); |
return [type isEqualToString:NSPasteboardTypeString] || [type isEqualToString:GetAvnCustomDataType()] |
||||
|
? 0 |
||||
|
: NSPasteboardWritingPromised; |
||||
} |
} |
||||
|
|
||||
extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*cb) |
- (nullable id) pasteboardPropertyListForType:(nonnull NSPasteboardType)type |
||||
{ |
{ |
||||
auto clipboard = dynamic_cast<Clipboard*>(cb); |
if ([type isEqualToString:GetAvnCustomDataType()]) |
||||
if(clipboard == nil) |
return @""; |
||||
|
|
||||
|
ComPtr<IAvnClipboardDataValue> value(_item->GetValue([type UTF8String]), true); |
||||
|
if (value.getRaw() == nullptr) |
||||
return nil; |
return nil; |
||||
return clipboard->TryGetItem(); |
|
||||
|
if (value->IsString()) |
||||
|
return GetNSStringAndRelease(value->AsString()); |
||||
|
|
||||
|
auto length = value->GetByteLength(); |
||||
|
auto buffer = malloc(length); |
||||
|
value->CopyBytesTo(buffer); |
||||
|
return [NSData dataWithBytesNoCopy:buffer length:length]; |
||||
|
} |
||||
|
|
||||
|
- (void) dealloc |
||||
|
{ |
||||
|
if (_item != nullptr) |
||||
|
{ |
||||
|
_item->Release(); |
||||
|
_item = nullptr; |
||||
|
} |
||||
|
|
||||
|
if (_source != nullptr) |
||||
|
{ |
||||
|
_source->Release(); |
||||
|
_source = nullptr; |
||||
|
} |
||||
} |
} |
||||
|
|
||||
|
@end |
||||
|
|||||
@ -0,0 +1,9 @@ |
|||||
|
// The only reason this file exists is Appium which limits our highest Xcode version to 15.2. Please, purge Appium from our codebase
|
||||
|
#ifndef crapium_h |
||||
|
#define crapium_h |
||||
|
#import <Foundation/Foundation.h> |
||||
|
@protocol MTLSharedEvent; |
||||
|
|
||||
|
API_AVAILABLE(macos(12)) |
||||
|
extern BOOL MtlSharedEventWaitUntilSignaledValueHack(id<MTLSharedEvent> ev, uint64_t value, uint64_t milliseconds); |
||||
|
#endif /* crapium_h */ |
||||
@ -0,0 +1,21 @@ |
|||||
|
// The only reason this file exists is Appium which limits our highest Xcode version to 15.2. Please, purge Appium from our codebase |
||||
|
#import <Foundation/Foundation.h> |
||||
|
#import "crapium.h" |
||||
|
@class MTLSharedEventHandle; |
||||
|
@protocol MTLSharedEvent; |
||||
|
@protocol MTLEvent; |
||||
|
|
||||
|
typedef void (^MTLSharedEventNotificationBlock)(id <MTLSharedEvent>, uint64_t value); |
||||
|
|
||||
|
API_AVAILABLE(macos(10.14), ios(12.0)) |
||||
|
@protocol MTLSharedEvent <MTLEvent> |
||||
|
// Synchronously wait for the signaledValue to be greater than or equal to 'value', with a timeout |
||||
|
// specified in milliseconds. Returns YES if the value was signaled before the timeout, otherwise NO. |
||||
|
- (BOOL)waitUntilSignaledValue:(uint64_t)value timeoutMS:(uint64_t)milliseconds API_AVAILABLE(macos(12.0), ios(15.0)); |
||||
|
@end |
||||
|
|
||||
|
API_AVAILABLE(macos(12)) |
||||
|
extern BOOL MtlSharedEventWaitUntilSignaledValueHack(id<MTLSharedEvent> ev, uint64_t value, uint64_t milliseconds) |
||||
|
{ |
||||
|
return [ev waitUntilSignaledValue:value timeoutMS:milliseconds]; |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
#include "common.h" |
||||
|
class MemHelper : public ComSingleObject<IAvnNativeObjectsMemoryManagement, &IID_IAvnNativeObjectsMemoryManagement> |
||||
|
{ |
||||
|
FORWARD_IUNKNOWN() |
||||
|
void RetainNSObject(void *object) override |
||||
|
{ |
||||
|
::RetainNSObject(object); |
||||
|
} |
||||
|
|
||||
|
void ReleaseNSObject(void *object) override |
||||
|
{ |
||||
|
::ReleaseNSObject(object); |
||||
|
} |
||||
|
|
||||
|
void RetainCFObject(void *object) override |
||||
|
{ |
||||
|
CFRetain(object); |
||||
|
} |
||||
|
|
||||
|
void ReleaseCFObject(void *object) override |
||||
|
{ |
||||
|
CFRelease(object); |
||||
|
} |
||||
|
|
||||
|
uint64_t GetRetainCountForNSObject(void *obj) override { |
||||
|
return ::GetRetainCountForNSObject(obj); |
||||
|
} |
||||
|
|
||||
|
int64_t GetRetainCountForCFObject(void *obj) override { |
||||
|
return CFGetRetainCount(obj); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
extern IAvnNativeObjectsMemoryManagement* CreateMemoryManagementHelper() |
||||
|
{ |
||||
|
return new MemHelper(); |
||||
|
} |
||||
@ -1,313 +1,488 @@ |
|||||
|
#nullable enable |
||||
|
|
||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Diagnostics; |
using System.Collections.Immutable; |
||||
using System.IO; |
using System.IO; |
||||
using System.IO.Compression; |
using System.IO.Compression; |
||||
using System.Linq; |
using System.Linq; |
||||
using System.Net; |
using System.Security.Cryptography; |
||||
using System.Net.Http; |
|
||||
using System.Text.RegularExpressions; |
using System.Text.RegularExpressions; |
||||
|
using System.Threading; |
||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
using NuGet.Common; |
||||
|
using NuGet.Configuration; |
||||
|
using NuGet.Frameworks; |
||||
|
using NuGet.Packaging; |
||||
|
using NuGet.Protocol; |
||||
|
using NuGet.Protocol.Core.Types; |
||||
|
using NuGet.Versioning; |
||||
|
using Nuke.Common.IO; |
||||
using Nuke.Common.Tooling; |
using Nuke.Common.Tooling; |
||||
using Serilog; |
|
||||
using static Serilog.Log; |
using static Serilog.Log; |
||||
|
|
||||
public static class ApiDiffHelper |
public static class ApiDiffHelper |
||||
{ |
{ |
||||
static readonly HttpClient s_httpClient = new(); |
const string NightlyFeedUri = "https://nuget-feed-nightly.avaloniaui.net/v3/index.json"; |
||||
|
const string MainPackageName = "Avalonia"; |
||||
|
const string FolderLib = "lib"; |
||||
|
|
||||
|
private static readonly Regex s_suppressionPathRegex = |
||||
|
new("<(Left|Right)>(.*?)</(Left|Right)>", RegexOptions.Compiled); |
||||
|
|
||||
|
public static void ValidatePackage( |
||||
|
Tool apiCompatTool, |
||||
|
PackageDiffInfo packageDiff, |
||||
|
AbsolutePath rootAssembliesFolderPath, |
||||
|
AbsolutePath suppressionFilesFolderPath, |
||||
|
bool updateSuppressionFile) |
||||
|
{ |
||||
|
Information("Validating API for package {Id}", packageDiff.PackageId); |
||||
|
|
||||
|
Directory.CreateDirectory(suppressionFilesFolderPath); |
||||
|
|
||||
|
var suppressionFilePath = suppressionFilesFolderPath / (packageDiff.PackageId + ".nupkg.xml"); |
||||
|
var replaceDirectorySeparators = Path.DirectorySeparatorChar == '\\'; |
||||
|
var allErrors = new List<string>(); |
||||
|
|
||||
|
foreach (var framework in packageDiff.Frameworks) |
||||
|
{ |
||||
|
var relativeBaselinePath = rootAssembliesFolderPath.GetRelativePathTo(framework.BaselineFolderPath); |
||||
|
var relativeCurrentPath = rootAssembliesFolderPath.GetRelativePathTo(framework.CurrentFolderPath); |
||||
|
var args = ""; |
||||
|
|
||||
|
if (suppressionFilePath.FileExists()) |
||||
|
{ |
||||
|
args += $""" --suppression-file="{suppressionFilePath}" --permit-unnecessary-suppressions """; |
||||
|
|
||||
|
if (replaceDirectorySeparators) |
||||
|
ReplaceDirectorySeparators(suppressionFilePath, '/', '\\'); |
||||
|
} |
||||
|
|
||||
|
if (updateSuppressionFile) |
||||
|
args += $""" --suppression-output-file="{suppressionFilePath}" --generate-suppression-file --preserve-unnecessary-suppressions """; |
||||
|
|
||||
|
args += $""" -l="{relativeBaselinePath}" -r="{relativeCurrentPath}" """; |
||||
|
|
||||
|
var localErrors = GetErrors(apiCompatTool($"{args:nq}", rootAssembliesFolderPath, exitHandler: _ => { })); |
||||
|
|
||||
|
if (replaceDirectorySeparators) |
||||
|
ReplaceDirectorySeparators(suppressionFilePath, '\\', '/'); |
||||
|
|
||||
|
allErrors.AddRange(localErrors); |
||||
|
} |
||||
|
|
||||
|
ThrowOnErrors(allErrors, packageDiff.PackageId, "ValidateApiDiff"); |
||||
|
} |
||||
|
|
||||
public static async Task GetDiff( |
/// <summary>
|
||||
Tool apiDiffTool, string outputFolder, |
/// The ApiCompat tool treats paths with '/' and '\' separators as different files.
|
||||
string packagePath, string baselineVersion) |
/// Before running the tool, adjust the existing separators (using a dirty regex) to match the current platform.
|
||||
|
/// After running the tool, change all separators back to '/'.
|
||||
|
/// </summary>
|
||||
|
static void ReplaceDirectorySeparators(AbsolutePath suppressionFilePath, char oldSeparator, char newSeparator) |
||||
{ |
{ |
||||
await using var baselineStream = await DownloadBaselinePackage(packagePath, baselineVersion); |
if (!File.Exists(suppressionFilePath)) |
||||
if (baselineStream == null) |
|
||||
return; |
return; |
||||
|
|
||||
if (!Directory.Exists(outputFolder)) |
var lines = File.ReadAllLines(suppressionFilePath); |
||||
|
|
||||
|
for (var i = 0; i < lines.Length; i++) |
||||
{ |
{ |
||||
Directory.CreateDirectory(outputFolder!); |
var original = lines[i]; |
||||
|
|
||||
|
var replacement = s_suppressionPathRegex.Replace(original, match => |
||||
|
{ |
||||
|
var path = match.Groups[2].Value.Replace(oldSeparator, newSeparator); |
||||
|
return $"<{match.Groups[1].Value}>{path}</{match.Groups[3].Value}>"; |
||||
|
}); |
||||
|
|
||||
|
lines[i] = replacement; |
||||
} |
} |
||||
|
|
||||
using (var target = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.Read), ZipArchiveMode.Read)) |
File.WriteAllLines(suppressionFilePath, lines); |
||||
using (var baseline = new ZipArchive(baselineStream, ZipArchiveMode.Read)) |
} |
||||
using (Helpers.UseTempDir(out var tempFolder)) |
|
||||
{ |
|
||||
var targetDlls = GetDlls(target); |
|
||||
var baselineDlls = GetDlls(baseline); |
|
||||
|
|
||||
var pairs = new List<(string baseline, string target)>(); |
public static void GenerateMarkdownDiff( |
||||
|
Tool apiDiffTool, |
||||
|
PackageDiffInfo packageDiff, |
||||
|
AbsolutePath rootOutputFolderPath, |
||||
|
string baselineDisplay, |
||||
|
string currentDisplay) |
||||
|
{ |
||||
|
Information("Creating markdown diff for package {Id}", packageDiff.PackageId); |
||||
|
|
||||
var packageId = GetPackageId(packagePath); |
var packageOutputFolderPath = rootOutputFolderPath / packageDiff.PackageId; |
||||
|
Directory.CreateDirectory(packageOutputFolderPath); |
||||
|
|
||||
// Don't use Path.Combine with these left and right tool parameters.
|
// Not specifying -eattrs incorrectly tries to load AttributesToExclude.txt, create an empty file instead.
|
||||
// Microsoft.DotNet.ApiCompat.Tool is stupid and treats '/' and '\' as different assemblies in suppression files.
|
// See https://github.com/dotnet/sdk/issues/49719
|
||||
// So, always use Unix '/'
|
var excludedAttributesFilePath = (AbsolutePath)Path.Join(Path.GetTempPath(), Guid.NewGuid().ToString()); |
||||
foreach (var baselineDll in baselineDlls) |
File.WriteAllBytes(excludedAttributesFilePath!, []); |
||||
{ |
|
||||
var baselineDllPath = await ExtractDll("baseline", baselineDll, tempFolder); |
|
||||
|
|
||||
var targetTfm = baselineDll.target; |
try |
||||
var targetDll = targetDlls.FirstOrDefault(e => |
{ |
||||
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); |
var allErrors = new List<string>(); |
||||
if (targetDll is null) |
|
||||
|
// The API diff tool is unbelievably slow, process in parallel.
|
||||
|
Parallel.ForEach( |
||||
|
packageDiff.Frameworks, |
||||
|
framework => |
||||
{ |
{ |
||||
if (s_tfmRedirects.FirstOrDefault(t => baselineDll.target.StartsWith(t.oldTfm) && (t.package is null || packageId == t.package)).newTfm is {} newTfm) |
var frameworkOutputFolderPath = packageOutputFolderPath / framework.Framework.GetShortFolderName(); |
||||
|
var args = $""" -b="{framework.BaselineFolderPath}" -bfn="{baselineDisplay}" -a="{framework.CurrentFolderPath}" -afn="{currentDisplay}" -o="{frameworkOutputFolderPath}" -eattrs="{excludedAttributesFilePath}" """; |
||||
|
|
||||
|
var localErrors = GetErrors(apiDiffTool($"{args:nq}")); |
||||
|
|
||||
|
if (localErrors.Length > 0) |
||||
{ |
{ |
||||
targetTfm = newTfm; |
lock (allErrors) |
||||
targetDll = targetDlls.FirstOrDefault(e => |
allErrors.AddRange(localErrors); |
||||
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); |
|
||||
} |
} |
||||
} |
}); |
||||
|
|
||||
if (targetDll?.entry is null) |
ThrowOnErrors(allErrors, packageDiff.PackageId, "OutputApiDiff"); |
||||
{ |
|
||||
throw new InvalidOperationException($"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}"); |
|
||||
} |
|
||||
|
|
||||
var targetDllPath = await ExtractDll("target", targetDll, tempFolder); |
MergeFrameworkMarkdownDiffFiles( |
||||
|
rootOutputFolderPath, |
||||
|
packageOutputFolderPath, |
||||
|
[..packageDiff.Frameworks.Select(info => info.Framework)]); |
||||
|
|
||||
pairs.Add((baselineDllPath, targetDllPath)); |
Directory.Delete(packageOutputFolderPath, true); |
||||
} |
} |
||||
|
finally |
||||
|
{ |
||||
|
File.Delete(excludedAttributesFilePath); |
||||
|
} |
||||
|
} |
||||
|
|
||||
await Task.WhenAll(pairs.Select(p => Task.Run(() => |
static void MergeFrameworkMarkdownDiffFiles( |
||||
|
AbsolutePath rootOutputFolderPath, |
||||
|
AbsolutePath packageOutputFolderPath, |
||||
|
ImmutableArray<NuGetFramework> frameworks) |
||||
|
{ |
||||
|
// At this point, the hierarchy looks like:
|
||||
|
// markdown/
|
||||
|
// ├─ net8.0/
|
||||
|
// │ ├─ api_diff_Avalonia.md
|
||||
|
// │ ├─ api_diff_Avalonia.Controls.md
|
||||
|
// ├─ netstandard2.0/
|
||||
|
// │ ├─ api_diff_Avalonia.md
|
||||
|
// │ ├─ api_diff_Avalonia.Controls.md
|
||||
|
//
|
||||
|
// We want one file per assembly: merge all files with the same name.
|
||||
|
// However, it's very likely that the diff is the same for several frameworks: in this case, keep only one file.
|
||||
|
|
||||
|
var assemblyGroups = frameworks |
||||
|
.SelectMany(GetFrameworkDiffFiles, (framework, filePath) => (framework, filePath)) |
||||
|
.GroupBy(x => x.filePath.Name) |
||||
|
.OrderBy(x => x.Key, StringComparer.OrdinalIgnoreCase); |
||||
|
|
||||
|
foreach (var assemblyGroup in assemblyGroups) |
||||
|
{ |
||||
|
using var writer = File.CreateText(rootOutputFolderPath / assemblyGroup.Key.Replace("api_diff_", "")); |
||||
|
var addSeparator = false; |
||||
|
|
||||
|
foreach (var similarDiffGroup in assemblyGroup.GroupBy(x => HashFile(x.filePath), ByteArrayEqualityComparer.Instance)) |
||||
{ |
{ |
||||
var baselineApi = p.baseline + Random.Shared.Next() + ".api.cs"; |
if (addSeparator) |
||||
var targetApi = p.target + Random.Shared.Next() + ".api.cs"; |
writer.WriteLine(); |
||||
var resultDiff = p.target + ".api.diff.cs"; |
|
||||
|
|
||||
GenerateApiListing(apiDiffTool, p.baseline, baselineApi, tempFolder); |
|
||||
GenerateApiListing(apiDiffTool, p.target, targetApi, tempFolder); |
|
||||
|
|
||||
var args = $"""-c core.autocrlf=false diff --no-index --minimal """; |
|
||||
args += """--ignore-matching-lines="^\[assembly: System.Reflection.AssemblyVersionAttribute" """; |
|
||||
args += $""" --output {resultDiff} {baselineApi} {targetApi}"""; |
|
||||
|
|
||||
using (var gitProcess = new Process()) |
|
||||
{ |
|
||||
gitProcess.StartInfo = new ProcessStartInfo |
|
||||
{ |
|
||||
CreateNoWindow = true, |
|
||||
RedirectStandardError = false, |
|
||||
RedirectStandardOutput = false, |
|
||||
FileName = "git", |
|
||||
Arguments = args, |
|
||||
WorkingDirectory = tempFolder |
|
||||
}; |
|
||||
gitProcess.Start(); |
|
||||
gitProcess.WaitForExit(); |
|
||||
} |
|
||||
|
|
||||
var resultFile = new FileInfo(Path.Combine(tempFolder, resultDiff)); |
using var reader = File.OpenText(similarDiffGroup.First().filePath); |
||||
if (resultFile.Length > 0) |
var firstLine = reader.ReadLine(); |
||||
{ |
|
||||
resultFile.CopyTo(Path.Combine(outputFolder, Path.GetFileName(resultDiff)), true); |
writer.Write(firstLine); |
||||
} |
writer.WriteLine(" (" + string.Join(", ", similarDiffGroup.Select(x => x.framework.GetShortFolderName())) + ")"); |
||||
}))); |
|
||||
|
while (reader.ReadLine() is { } line) |
||||
|
writer.WriteLine(line); |
||||
|
|
||||
|
addSeparator = true; |
||||
|
} |
||||
} |
} |
||||
} |
|
||||
|
|
||||
private static readonly (string package, string oldTfm, string newTfm)[] s_tfmRedirects = new[] |
AbsolutePath[] GetFrameworkDiffFiles(NuGetFramework framework) |
||||
{ |
|
||||
// We use StartsWith below comparing these tfm, as we ignore platform versions (like, net6.0-ios16.1).
|
|
||||
("Avalonia.Android", "net6.0-android", "net8.0-android"), |
|
||||
("Avalonia.iOS", "net6.0-ios", "net8.0-ios"), |
|
||||
// Browser was changed from net7.0 to net8.0-browser.
|
|
||||
("Avalonia.Browser", "net7.0", "net8.0-browser"), |
|
||||
("Avalonia.Browser.Blazor", "net7.0", "net8.0-browser"), |
|
||||
// Designer was moved from netcoreapp to netstandard.
|
|
||||
("Avalonia", "netcoreapp2.0", "netstandard2.0"), |
|
||||
("Avalonia", "net461", "netstandard2.0") |
|
||||
}; |
|
||||
|
|
||||
public static async Task ValidatePackage( |
|
||||
Tool apiCompatTool, string packagePath, string baselineVersion, |
|
||||
string suppressionFilesFolder, bool updateSuppressionFile) |
|
||||
{ |
|
||||
if (!Directory.Exists(suppressionFilesFolder)) |
|
||||
{ |
{ |
||||
Directory.CreateDirectory(suppressionFilesFolder!); |
var frameworkFolderPath = packageOutputFolderPath / framework.GetShortFolderName(); |
||||
|
if (!frameworkFolderPath.DirectoryExists()) |
||||
|
return []; |
||||
|
|
||||
|
return Directory.GetFiles(frameworkFolderPath, "*.md") |
||||
|
.Where(filePath => Path.GetFileName(filePath) != "api_diff.md") |
||||
|
.Select(filePath => (AbsolutePath)filePath) |
||||
|
.ToArray(); |
||||
} |
} |
||||
|
|
||||
await using var baselineStream = await DownloadBaselinePackage(packagePath, baselineVersion); |
static byte[] HashFile(AbsolutePath filePath) |
||||
if (baselineStream == null) |
{ |
||||
return; |
using var stream = File.OpenRead(filePath); |
||||
|
return SHA256.HashData(stream); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void MergePackageMarkdownDiffFiles( |
||||
|
AbsolutePath rootOutputFolderPath, |
||||
|
string baselineDisplay, |
||||
|
string currentDisplay) |
||||
|
{ |
||||
|
const string mergedFileName = "_diff.md"; |
||||
|
|
||||
using (var target = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.Read), ZipArchiveMode.Read)) |
var filePaths = Directory.EnumerateFiles(rootOutputFolderPath, "*.md") |
||||
using (var baseline = new ZipArchive(baselineStream, ZipArchiveMode.Read)) |
.Where(filePath => Path.GetFileName(filePath) != mergedFileName) |
||||
using (Helpers.UseTempDir(out var tempFolder)) |
.Order(StringComparer.OrdinalIgnoreCase) |
||||
|
.ToArray(); |
||||
|
|
||||
|
using var writer = File.CreateText(rootOutputFolderPath / mergedFileName); |
||||
|
|
||||
|
writer.WriteLine($"# API diff between {baselineDisplay} and {currentDisplay}"); |
||||
|
|
||||
|
if (filePaths.Length == 0) |
||||
{ |
{ |
||||
var targetDlls = GetDlls(target); |
writer.WriteLine(); |
||||
var baselineDlls = GetDlls(baseline); |
writer.WriteLine("No changes."); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
var left = new List<string>(); |
foreach (var filePath in filePaths) |
||||
var right = new List<string>(); |
{ |
||||
|
writer.WriteLine(); |
||||
|
|
||||
var packageId = GetPackageId(packagePath); |
using var reader = File.OpenText(filePath); |
||||
var suppressionFile = Path.Combine(suppressionFilesFolder, packageId + ".nupkg.xml"); |
|
||||
|
|
||||
// Don't use Path.Combine with these left and right tool parameters.
|
while (reader.ReadLine() is { } line) |
||||
// Microsoft.DotNet.ApiCompat.Tool is stupid and treats '/' and '\' as different assemblies in suppression files.
|
|
||||
// So, always use Unix '/'
|
|
||||
foreach (var baselineDll in baselineDlls) |
|
||||
{ |
{ |
||||
var baselineDllPath = await ExtractDll("baseline", baselineDll, tempFolder); |
if (line.StartsWith('#')) |
||||
|
writer.Write('#'); |
||||
|
|
||||
var targetTfm = baselineDll.target; |
writer.WriteLine(line); |
||||
var targetDll = targetDlls.FirstOrDefault(e => |
} |
||||
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); |
} |
||||
if (targetDll?.entry is null) |
} |
||||
{ |
|
||||
if (s_tfmRedirects.FirstOrDefault(t => baselineDll.target.StartsWith(t.oldTfm) && (t.package is null || packageId == t.package)).newTfm is {} newTfm) |
|
||||
{ |
|
||||
targetTfm = newTfm; |
|
||||
targetDll = targetDlls.FirstOrDefault(e => |
|
||||
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); |
|
||||
} |
|
||||
} |
|
||||
if (targetDll?.entry is null && targetDlls.Count == 1) |
|
||||
{ |
|
||||
targetDll = targetDlls.First(); |
|
||||
Warning( |
|
||||
$"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}." + |
|
||||
$"Resolved: {targetDll.target} ({targetDll.entry.Name})"); |
|
||||
} |
|
||||
|
|
||||
if (targetDll?.entry is null) |
static string[] GetErrors(IEnumerable<Output> outputs) |
||||
{ |
=> outputs |
||||
if (packageId == "Avalonia" |
.Where(output => output.Type == OutputType.Err) |
||||
&& baselineDll.target is "net461" or "netcoreapp2.0") |
.Select(output => output.Text) |
||||
{ |
.ToArray(); |
||||
// In 11.1 we have removed net461 and netcoreapp2.0 targets from Avalonia package.
|
|
||||
continue; |
static void ThrowOnErrors(List<string> errors, string packageId, string taskName) |
||||
} |
{ |
||||
|
if (errors.Count > 0) |
||||
var actualTargets = string.Join(", ", |
{ |
||||
targetDlls.Select(d => $"{d.target} ({d.entry.Name})")); |
throw new AggregateException( |
||||
throw new InvalidOperationException( |
$"{taskName} task has failed for \"{packageId}\" package", |
||||
$"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}." |
errors.Select(error => new Exception(error))); |
||||
+ $"\r\nActual targets: {actualTargets}."); |
} |
||||
} |
} |
||||
|
|
||||
|
public static async Task<GlobalDiffInfo> DownloadAndExtractPackagesAsync( |
||||
|
IEnumerable<AbsolutePath> currentPackagePaths, |
||||
|
NuGetVersion currentVersion, |
||||
|
bool isReleaseBranch, |
||||
|
AbsolutePath outputFolderPath, |
||||
|
NuGetVersion? forcedBaselineVersion) |
||||
|
{ |
||||
|
var downloadContext = await CreateNuGetDownloadContextAsync(); |
||||
|
var baselineVersion = forcedBaselineVersion ?? |
||||
|
await GetBaselineVersionAsync(downloadContext, currentVersion, isReleaseBranch); |
||||
|
|
||||
var targetDllPath = await ExtractDll("target", targetDll, tempFolder); |
Information("API baseline version is {Baseline} for current version {Current}", baselineVersion, currentVersion); |
||||
|
|
||||
left.Add(baselineDllPath); |
var memoryStream = new MemoryStream(); |
||||
right.Add(targetDllPath); |
var packageDiffs = ImmutableArray.CreateBuilder<PackageDiffInfo>(); |
||||
|
|
||||
|
foreach (var packagePath in currentPackagePaths) |
||||
|
{ |
||||
|
string packageId; |
||||
|
AbsolutePath currentFolderPath; |
||||
|
AbsolutePath baselineFolderPath; |
||||
|
Dictionary<NuGetFramework, string> currentFolderNames; |
||||
|
Dictionary<NuGetFramework, string> baselineFolderNames; |
||||
|
|
||||
|
// Extract current package
|
||||
|
using (var currentArchive = new ZipArchive(File.OpenRead(packagePath), ZipArchiveMode.Read, leaveOpen: false)) |
||||
|
{ |
||||
|
using var packageReader = new PackageArchiveReader(currentArchive); |
||||
|
packageId = packageReader.NuspecReader.GetId(); |
||||
|
currentFolderPath = outputFolderPath / "current" / packageId; |
||||
|
currentFolderNames = ExtractDiffableAssembliesFromPackage(currentArchive, currentFolderPath); |
||||
} |
} |
||||
|
|
||||
if (left.Any()) |
// Download baseline package
|
||||
|
memoryStream.Position = 0L; |
||||
|
memoryStream.SetLength(0L); |
||||
|
await DownloadBaselinePackageAsync(memoryStream, downloadContext, packageId, baselineVersion); |
||||
|
memoryStream.Position = 0L; |
||||
|
|
||||
|
// Extract baseline package
|
||||
|
using (var baselineArchive = new ZipArchive(memoryStream, ZipArchiveMode.Read, leaveOpen: true)) |
||||
{ |
{ |
||||
var args = $""" -l={string.Join(',', left)} -r="{string.Join(',', right)}" """; |
baselineFolderPath = outputFolderPath / "baseline" / packageId; |
||||
if (File.Exists(suppressionFile)) |
baselineFolderNames = ExtractDiffableAssembliesFromPackage(baselineArchive, baselineFolderPath); |
||||
{ |
} |
||||
args += $""" --suppression-file="{suppressionFile}" """; |
|
||||
} |
|
||||
|
|
||||
if (updateSuppressionFile) |
if (currentFolderNames.Count == 0 && baselineFolderNames.Count == 0) |
||||
{ |
continue; |
||||
args += $""" --suppression-output-file="{suppressionFile}" --generate-suppression-file=true """; |
|
||||
} |
|
||||
|
|
||||
var result = apiCompatTool(args, tempFolder) |
var frameworkDiffs = new List<FrameworkDiffInfo>(); |
||||
.Where(t => t.Type == OutputType.Err).ToArray(); |
|
||||
if (result.Any()) |
foreach (var (framework, currentFolderName) in currentFolderNames) |
||||
{ |
{ |
||||
throw new AggregateException( |
// Ignore new frameworks that didn't exist in the baseline package. Empty folders make the ApiDiff tool crash.
|
||||
$"ApiDiffValidation task has failed for \"{Path.GetFileName(packagePath)}\" package", |
if (!baselineFolderNames.TryGetValue(framework, out var baselineFolderName)) |
||||
result.Select(r => new Exception(r.Text))); |
continue; |
||||
} |
|
||||
|
frameworkDiffs.Add(new FrameworkDiffInfo( |
||||
|
framework, |
||||
|
baselineFolderPath / FolderLib / baselineFolderName, |
||||
|
currentFolderPath / FolderLib / currentFolderName)); |
||||
} |
} |
||||
|
|
||||
|
packageDiffs.Add(new PackageDiffInfo(packageId, [..frameworkDiffs])); |
||||
} |
} |
||||
|
|
||||
|
return new GlobalDiffInfo(baselineVersion, currentVersion, packageDiffs.DrainToImmutable()); |
||||
} |
} |
||||
|
|
||||
record DllEntry(string target, ZipArchiveEntry entry); |
static async Task<NuGetDownloadContext> CreateNuGetDownloadContextAsync() |
||||
|
|
||||
static IReadOnlyCollection<DllEntry> GetDlls(ZipArchive archive) |
|
||||
{ |
{ |
||||
return archive.Entries |
var packageSource = new PackageSource(NightlyFeedUri) { ProtocolVersion = 3 }; |
||||
.Where(e => Path.GetExtension(e.FullName) == ".dll" |
var repository = Repository.Factory.GetCoreV3(packageSource); |
||||
// Exclude analyzers and build task, as we don't care about breaking changes there
|
var findPackageByIdResource = await repository.GetResourceAsync<FindPackageByIdResource>(); |
||||
&& !e.FullName.Contains("analyzers/") && !e.FullName.Contains("analyzers\\") |
return new NuGetDownloadContext(packageSource, findPackageByIdResource); |
||||
&& !e.Name.Contains("Avalonia.Build.Tasks")) |
|
||||
.Select(e => ( |
|
||||
entry: e, |
|
||||
isRef: e.FullName.Contains("ref/") || e.FullName.Contains("ref\\"), |
|
||||
target: Path.GetDirectoryName(e.FullName)!.Split(new [] { '/', '\\' }).Last()) |
|
||||
) |
|
||||
.GroupBy(e => (e.target, e.entry.Name)) |
|
||||
.Select(g => g.MaxBy(e => e.isRef)) |
|
||||
.Select(e => new DllEntry(e.target, e.entry)) |
|
||||
.ToArray(); |
|
||||
} |
} |
||||
|
|
||||
static async Task<Stream> DownloadBaselinePackage(string packagePath, string baselineVersion) |
/// <summary>
|
||||
|
/// Finds the baseline version to diff against.
|
||||
|
/// On release branches, use the latest stable version.
|
||||
|
/// On the main branch and on PRs, use the latest nightly version.
|
||||
|
/// This method assumes all packages share the same version.
|
||||
|
/// </summary>
|
||||
|
static async Task<NuGetVersion> GetBaselineVersionAsync( |
||||
|
NuGetDownloadContext context, |
||||
|
NuGetVersion currentVersion, |
||||
|
bool isReleaseBranch) |
||||
{ |
{ |
||||
if (baselineVersion is null) |
var versions = await context.FindPackageByIdResource.GetAllVersionsAsync( |
||||
|
MainPackageName, |
||||
|
context.CacheContext, |
||||
|
NullLogger.Instance, |
||||
|
CancellationToken.None); |
||||
|
|
||||
|
versions = versions.Where(v => v < currentVersion); |
||||
|
|
||||
|
if (isReleaseBranch) |
||||
|
versions = versions.Where(v => !v.IsPrerelease); |
||||
|
|
||||
|
return versions.OrderDescending().FirstOrDefault() |
||||
|
?? throw new InvalidOperationException( |
||||
|
$"Could not find a version less than {currentVersion} for package {MainPackageName} in source {context.PackageSource.Source}"); |
||||
|
} |
||||
|
|
||||
|
static async Task DownloadBaselinePackageAsync( |
||||
|
Stream destinationStream, |
||||
|
NuGetDownloadContext context, |
||||
|
string packageId, |
||||
|
NuGetVersion version) |
||||
|
{ |
||||
|
Information("Downloading {Id} {Version} baseline package", packageId, version); |
||||
|
|
||||
|
var downloaded = await context.FindPackageByIdResource.CopyNupkgToStreamAsync( |
||||
|
packageId, |
||||
|
version, |
||||
|
destinationStream, |
||||
|
context.CacheContext, |
||||
|
NullLogger.Instance, |
||||
|
CancellationToken.None); |
||||
|
|
||||
|
if (!downloaded) |
||||
{ |
{ |
||||
throw new InvalidOperationException( |
throw new InvalidOperationException( |
||||
"Build \"api-baseline\" parameter must be set when running Nuke CreatePackages"); |
$"Could not download version {version} for package {packageId} in source {context.PackageSource.Source}"); |
||||
} |
} |
||||
|
} |
||||
|
|
||||
/* |
static Dictionary<NuGetFramework, string> ExtractDiffableAssembliesFromPackage( |
||||
Gets package name from versions like: |
ZipArchive packageArchive, |
||||
Avalonia.0.10.0-preview1 |
AbsolutePath destinationFolderPath) |
||||
Avalonia.11.0.999-cibuild0037534-beta |
{ |
||||
Avalonia.11.0.0 |
var folderByFramework = new Dictionary<NuGetFramework, string>(); |
||||
*/ |
|
||||
var packageId = GetPackageId(packagePath); |
|
||||
Information("Downloading {0} {1} baseline package", packageId, baselineVersion); |
|
||||
|
|
||||
try |
foreach (var entry in packageArchive.Entries) |
||||
{ |
{ |
||||
using var response = await s_httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, |
if (TryGetFrameworkFolderName(entry.FullName) is not { } folderName) |
||||
$"https://www.nuget.org/api/v2/package/{packageId}/{baselineVersion}"), HttpCompletionOption.ResponseHeadersRead); |
continue; |
||||
response.EnsureSuccessStatusCode(); |
|
||||
|
// Ignore platform versions: assume that e.g. net8.0-android34 and net8.0-android35 are the same for diff purposes.
|
||||
await using var stream = await response.Content.ReadAsStreamAsync(); |
var framework = WithoutPlatformVersion(NuGetFramework.ParseFolder(folderName)); |
||||
var memoryStream = new MemoryStream(); |
|
||||
await stream.CopyToAsync(memoryStream); |
if (folderByFramework.TryGetValue(framework, out var existingFolderName)) |
||||
memoryStream.Seek(0, SeekOrigin.Begin); |
{ |
||||
return memoryStream; |
if (existingFolderName != folderName) |
||||
} |
{ |
||||
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound) |
throw new InvalidOperationException( |
||||
{ |
$"Found two similar frameworks with different platform versions: {existingFolderName} and {folderName}"); |
||||
return null; |
} |
||||
|
} |
||||
|
else |
||||
|
folderByFramework.Add(framework, folderName); |
||||
|
|
||||
|
var targetFilePath = destinationFolderPath / entry.FullName; |
||||
|
Directory.CreateDirectory(targetFilePath.Parent); |
||||
|
entry.ExtractToFile(targetFilePath, overwrite: true); |
||||
} |
} |
||||
catch (Exception ex) |
|
||||
|
return folderByFramework; |
||||
|
|
||||
|
static string? TryGetFrameworkFolderName(string entryPath) |
||||
{ |
{ |
||||
throw new InvalidOperationException($"Downloading baseline package for {packageId} {baselineVersion} failed.\r" + ex.Message, ex); |
if (!entryPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) |
||||
|
return null; |
||||
|
|
||||
|
var segments = entryPath.Split('/'); |
||||
|
if (segments is not [FolderLib, var name, ..]) |
||||
|
return null; |
||||
|
|
||||
|
return name; |
||||
} |
} |
||||
|
|
||||
|
// e.g. net8.0-android34.0 to net8.0-android
|
||||
|
static NuGetFramework WithoutPlatformVersion(NuGetFramework value) |
||||
|
=> value.HasPlatform && value.PlatformVersion != FrameworkConstants.EmptyVersion ? |
||||
|
new NuGetFramework(value.Framework, value.Version, value.Platform, FrameworkConstants.EmptyVersion) : |
||||
|
value; |
||||
} |
} |
||||
|
|
||||
static async Task<string> ExtractDll(string basePath, DllEntry dllEntry, string targetFolder) |
public sealed class GlobalDiffInfo( |
||||
|
NuGetVersion baselineVersion, |
||||
|
NuGetVersion currentVersion, |
||||
|
ImmutableArray<PackageDiffInfo> packages) |
||||
{ |
{ |
||||
var dllPath = $"{basePath}/{dllEntry.target}/{dllEntry.entry.Name}"; |
public NuGetVersion BaselineVersion { get; } = baselineVersion; |
||||
var dllRealPath = Path.Combine(targetFolder, dllPath); |
public NuGetVersion CurrentVersion { get; } = currentVersion; |
||||
Directory.CreateDirectory(Path.GetDirectoryName(dllRealPath)!); |
public ImmutableArray<PackageDiffInfo> Packages { get; } = packages; |
||||
await using (var dllFile = File.Create(dllRealPath)) |
} |
||||
{ |
|
||||
await dllEntry.entry.Open().CopyToAsync(dllFile); |
|
||||
} |
|
||||
|
|
||||
return dllPath; |
public sealed class PackageDiffInfo(string packageId, ImmutableArray<FrameworkDiffInfo> frameworks) |
||||
|
{ |
||||
|
public string PackageId { get; } = packageId; |
||||
|
public ImmutableArray<FrameworkDiffInfo> Frameworks { get; } = frameworks; |
||||
} |
} |
||||
|
|
||||
static void GenerateApiListing(Tool apiDiffTool, string inputFile, string outputFile, string workingDif) |
public sealed class FrameworkDiffInfo( |
||||
|
NuGetFramework framework, |
||||
|
AbsolutePath baselineFolderPath, |
||||
|
AbsolutePath currentFolderPath) |
||||
{ |
{ |
||||
var args = $""" --assembly={inputFile} --output-path={outputFile} --include-assembly-attributes=true"""; |
public NuGetFramework Framework { get; } = framework; |
||||
var result = apiDiffTool(args, workingDif) |
public AbsolutePath BaselineFolderPath { get; } = baselineFolderPath; |
||||
.Where(t => t.Type == OutputType.Err).ToArray(); |
public AbsolutePath CurrentFolderPath { get; } = currentFolderPath; |
||||
if (result.Any()) |
|
||||
{ |
|
||||
throw new AggregateException($"GetApi tool failed task has failed", |
|
||||
result.Select(r => new Exception(r.Text))); |
|
||||
} |
|
||||
} |
} |
||||
|
|
||||
static string GetPackageId(string packagePath) |
sealed class NuGetDownloadContext(PackageSource packageSource, FindPackageByIdResource findPackageByIdResource) |
||||
{ |
{ |
||||
return Regex.Replace( |
public SourceCacheContext CacheContext { get; } = new(); |
||||
Path.GetFileNameWithoutExtension(packagePath), |
public PackageSource PackageSource { get; } = packageSource; |
||||
"""(\.\d+\.\d+\.\d+(?:-.+)?)$""", ""); |
public FindPackageByIdResource FindPackageByIdResource { get; } = findPackageByIdResource; |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,25 @@ |
|||||
|
#nullable enable |
||||
|
|
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
public sealed class ByteArrayEqualityComparer : IEqualityComparer<byte[]> |
||||
|
{ |
||||
|
public static ByteArrayEqualityComparer Instance { get; } = new(); |
||||
|
|
||||
|
public bool Equals(byte[]? x, byte[]? y) { |
||||
|
if (ReferenceEquals(x, y)) |
||||
|
return true; |
||||
|
if (x is null || y is null) |
||||
|
return false; |
||||
|
|
||||
|
return x.AsSpan().SequenceEqual(y.AsSpan()); |
||||
|
} |
||||
|
|
||||
|
public int GetHashCode(byte[]? obj) |
||||
|
{ |
||||
|
var hashCode = new HashCode(); |
||||
|
hashCode.AddBytes(obj.AsSpan()); |
||||
|
return hashCode.ToHashCode(); |
||||
|
} |
||||
|
} |
||||
@ -1,10 +0,0 @@ |
|||||
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true"> |
|
||||
<Found Context="routeData"> |
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> |
|
||||
</Found> |
|
||||
<NotFound> |
|
||||
<LayoutView Layout="@typeof(MainLayout)"> |
|
||||
<p>Sorry, there's nothing at this address.</p> |
|
||||
</LayoutView> |
|
||||
</NotFound> |
|
||||
</Router> |
|
||||
@ -1,10 +0,0 @@ |
|||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia; |
|
||||
using Avalonia.Browser.Blazor; |
|
||||
|
|
||||
namespace ControlCatalog.Browser.Blazor; |
|
||||
|
|
||||
public partial class App |
|
||||
{ |
|
||||
} |
|
||||
@ -1,29 +0,0 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
|
||||
<PropertyGroup> |
|
||||
<TargetFramework>$(AvsCurrentBrowserTargetFramework)</TargetFramework> |
|
||||
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier> |
|
||||
<Nullable>enable</Nullable> |
|
||||
<EmccTotalMemory>16777216</EmccTotalMemory> |
|
||||
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport> |
|
||||
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" /> |
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" PrivateAssets="all" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<ItemGroup> |
|
||||
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" /> |
|
||||
<ProjectReference Include="..\..\src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj" /> |
|
||||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
|
||||
</ItemGroup> |
|
||||
|
|
||||
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
|
||||
<Import Project="..\..\build\BuildTargets.targets" /> |
|
||||
|
|
||||
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.props" /> |
|
||||
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.targets" /> |
|
||||
|
|
||||
</Project> |
|
||||
|
|
||||
@ -1,5 +0,0 @@ |
|||||
@page "/" |
|
||||
|
|
||||
@using Avalonia.Browser.Blazor |
|
||||
|
|
||||
<AvaloniaView /> |
|
||||
@ -1,39 +0,0 @@ |
|||||
using System; |
|
||||
using System.Net.Http; |
|
||||
using System.Threading.Tasks; |
|
||||
using Avalonia; |
|
||||
using Avalonia.Browser.Blazor; |
|
||||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|
||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using ControlCatalog.Browser.Blazor; |
|
||||
|
|
||||
public class Program |
|
||||
{ |
|
||||
public static async Task Main(string[] args) |
|
||||
{ |
|
||||
var host = CreateHostBuilder(args).Build(); |
|
||||
await StartAvaloniaApp(); |
|
||||
await host.RunAsync(); |
|
||||
} |
|
||||
|
|
||||
public static async Task StartAvaloniaApp() |
|
||||
{ |
|
||||
await AppBuilder.Configure<ControlCatalog.App>() |
|
||||
.StartBlazorAppAsync(); |
|
||||
} |
|
||||
|
|
||||
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args) |
|
||||
{ |
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
|
||||
|
|
||||
builder.RootComponents.Add<App>("#app"); |
|
||||
|
|
||||
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) }); |
|
||||
|
|
||||
return builder; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
@ -1,22 +0,0 @@ |
|||||
{ |
|
||||
"iisSettings": { |
|
||||
"windowsAuthentication": false, |
|
||||
"anonymousAuthentication": true, |
|
||||
"iisExpress": { |
|
||||
"applicationUrl": "http://localhost:13961", |
|
||||
"sslPort": 44319 |
|
||||
} |
|
||||
}, |
|
||||
"profiles": { |
|
||||
"ControlCatalog.Web": { |
|
||||
"commandName": "Project", |
|
||||
"dotnetRunMessages": "true", |
|
||||
"launchBrowser": true, |
|
||||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000", |
|
||||
"environmentVariables": { |
|
||||
"ASPNETCORE_ENVIRONMENT": "Development" |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
@inherits LayoutComponentBase |
|
||||
|
|
||||
<div class="page"> |
|
||||
<div class="main"> |
|
||||
@Body |
|
||||
</div> |
|
||||
</div> |
|
||||
@ -1,10 +0,0 @@ |
|||||
@using System.Net.Http |
|
||||
@using System.Net.Http.Json |
|
||||
@using Microsoft.AspNetCore.Components.Forms |
|
||||
@using Microsoft.AspNetCore.Components.Routing |
|
||||
@using Microsoft.AspNetCore.Components.Web |
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization |
|
||||
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
|
||||
@using Microsoft.JSInterop |
|
||||
@using ControlCatalog.Browser.Blazor.Shared |
|
||||
@using SkiaSharp |
|
||||
@ -1,56 +0,0 @@ |
|||||
html, body { |
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; |
|
||||
margin: 0; |
|
||||
height: 100vh; |
|
||||
overflow: hidden; |
|
||||
touch-action: none; |
|
||||
} |
|
||||
|
|
||||
a, .btn-link { |
|
||||
color: #0366d6; |
|
||||
} |
|
||||
|
|
||||
.btn-primary { |
|
||||
color: #fff; |
|
||||
background-color: #1b6ec2; |
|
||||
border-color: #1861ac; |
|
||||
} |
|
||||
|
|
||||
.content { |
|
||||
padding-top: 1.1rem; |
|
||||
} |
|
||||
|
|
||||
.valid.modified:not([type=checkbox]) { |
|
||||
outline: 1px solid #26b050; |
|
||||
} |
|
||||
|
|
||||
.invalid { |
|
||||
outline: 1px solid red; |
|
||||
} |
|
||||
|
|
||||
.validation-message { |
|
||||
color: red; |
|
||||
} |
|
||||
|
|
||||
#blazor-error-ui { |
|
||||
background: lightyellow; |
|
||||
bottom: 0; |
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); |
|
||||
display: none; |
|
||||
left: 0; |
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem; |
|
||||
position: fixed; |
|
||||
width: 100%; |
|
||||
z-index: 1000; |
|
||||
} |
|
||||
|
|
||||
#blazor-error-ui .dismiss { |
|
||||
cursor: pointer; |
|
||||
position: absolute; |
|
||||
right: 0.75rem; |
|
||||
top: 0.5rem; |
|
||||
} |
|
||||
|
|
||||
#app, .page { |
|
||||
height: 100%; |
|
||||
} |
|
||||
|
Before Width: | Height: | Size: 172 KiB |
@ -1,22 +0,0 @@ |
|||||
<!DOCTYPE html> |
|
||||
<html> |
|
||||
|
|
||||
<head> |
|
||||
<meta charset="utf-8" /> |
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|
||||
<title>Avalonia Sample</title> |
|
||||
<base href="/" /> |
|
||||
<link href="css/app.css" rel="stylesheet" /> |
|
||||
</head> |
|
||||
|
|
||||
<body> |
|
||||
<div id="app">Powered by Avalonia</div> |
|
||||
|
|
||||
<div id="blazor-error-ui"> |
|
||||
An unhandled error has occurred. |
|
||||
<a href="" class="reload">Reload</a> |
|
||||
<a class="dismiss">🗙</a> |
|
||||
</div> |
|
||||
<script src="_framework/blazor.webassembly.js"></script> |
|
||||
</body> |
|
||||
</html> |
|
||||
@ -1,22 +1,41 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<PropertyGroup> |
<PropertyGroup> |
||||
<OutputType>Exe</OutputType> |
<OutputType>WinExe</OutputType> |
||||
<TargetFramework>net461</TargetFramework> |
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework> |
||||
<PlatformTarget>x64</PlatformTarget> |
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch> |
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> |
||||
<ApplicationManifest>../ControlCatalog.NetCore/app.manifest</ApplicationManifest> |
|
||||
</PropertyGroup> |
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
<Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" /> |
||||
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
<Compile Include="..\..\src\Avalonia.X11\Interop\Glib.cs" Link="NativeControls\Gtk\Glib.cs" /> |
||||
|
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Content Include="NativeControls\Gtk\nodes.mp4"> |
||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> |
||||
|
</Content> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<Compile Include="..\ControlCatalog.NetCore\NativeControls\Win\*.cs" Link="NativeControls\*" /> |
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" /> |
||||
|
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> |
||||
|
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" /> |
||||
|
<!-- For native controls test --> |
||||
|
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<!-- For Microsoft.CodeAnalysis --> |
||||
|
<SatelliteResourceLanguages>en</SatelliteResourceLanguages> |
||||
|
<ApplicationManifest>app.manifest</ApplicationManifest> |
||||
|
</PropertyGroup> |
||||
|
|
||||
<Import Project="..\..\build\SampleApp.props" /> |
<Import Project="..\..\build\SampleApp.props" /> |
||||
<Import Project="..\..\build\NetFX.props" /> |
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,7 +1,7 @@ |
|||||
using System; |
using System; |
||||
using System.Runtime.InteropServices; |
using System.Runtime.InteropServices; |
||||
|
|
||||
namespace ControlCatalog.NetCore; |
namespace ControlCatalog.Desktop; |
||||
|
|
||||
internal unsafe class WinApi |
internal unsafe class WinApi |
||||
{ |
{ |
||||
@ -1,38 +1,180 @@ |
|||||
using System; |
using System; |
||||
|
using System.Diagnostics; |
||||
|
using System.Globalization; |
||||
|
using System.Linq; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
using Avalonia; |
using Avalonia; |
||||
using Avalonia.Platform; |
using Avalonia.Controls; |
||||
using ControlCatalog.NetCore; |
using Avalonia.Controls.ApplicationLifetimes; |
||||
|
using Avalonia.Fonts.Inter; |
||||
|
using Avalonia.Headless; |
||||
|
using Avalonia.LinuxFramebuffer.Output; |
||||
|
using Avalonia.LogicalTree; |
||||
|
using Avalonia.Rendering.Composition; |
||||
|
using Avalonia.Threading; |
||||
|
using Avalonia.Vulkan; |
||||
using ControlCatalog.Pages; |
using ControlCatalog.Pages; |
||||
|
|
||||
namespace ControlCatalog |
namespace ControlCatalog.Desktop |
||||
{ |
{ |
||||
internal class Program |
static class Program |
||||
{ |
{ |
||||
|
private static bool s_useFramebuffer; |
||||
|
|
||||
[STAThread] |
[STAThread] |
||||
public static int Main(string[] args) |
static int Main(string[] args) |
||||
=> BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); |
{ |
||||
|
if (args.Contains("--fbdev")) |
||||
|
{ |
||||
|
s_useFramebuffer = true; |
||||
|
} |
||||
|
|
||||
|
if (args.Contains("--wait-for-attach")) |
||||
|
{ |
||||
|
Console.WriteLine("Attach debugger and use 'Set next statement'"); |
||||
|
while (true) |
||||
|
{ |
||||
|
Thread.Sleep(100); |
||||
|
if (Debugger.IsAttached) |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var builder = BuildAvaloniaApp(); |
||||
|
|
||||
|
double GetScaling() |
||||
|
{ |
||||
|
var idx = Array.IndexOf(args, "--scaling"); |
||||
|
if (idx != 0 && args.Length > idx + 1 && |
||||
|
double.TryParse(args[idx + 1], NumberStyles.Any, CultureInfo.InvariantCulture, out var scaling)) |
||||
|
return scaling; |
||||
|
return 1; |
||||
|
} |
||||
|
if (s_useFramebuffer) |
||||
|
{ |
||||
|
SilenceConsole(); |
||||
|
return builder.StartLinuxFbDev(args, new FbDevOutputOptions() |
||||
|
{ |
||||
|
Scaling = GetScaling() |
||||
|
}); |
||||
|
} |
||||
|
else if (args.Contains("--vnc")) |
||||
|
{ |
||||
|
return builder.StartWithHeadlessVncPlatform(null, 5901, args, ShutdownMode.OnMainWindowClose); |
||||
|
} |
||||
|
else if (args.Contains("--full-headless")) |
||||
|
{ |
||||
|
return builder |
||||
|
.UseHeadless(new AvaloniaHeadlessPlatformOptions |
||||
|
{ |
||||
|
UseHeadlessDrawing = true |
||||
|
}) |
||||
|
.AfterSetup(_ => |
||||
|
{ |
||||
|
DispatcherTimer.RunOnce(async () => |
||||
|
{ |
||||
|
var window = ((IClassicDesktopStyleApplicationLifetime)Application.Current.ApplicationLifetime) |
||||
|
.MainWindow; |
||||
|
var tc = window.GetLogicalDescendants().OfType<TabControl>().First(); |
||||
|
foreach (var page in tc.Items.Cast<TabItem>().ToList()) |
||||
|
{ |
||||
|
if (page.Header.ToString() == "DatePicker" || page.Header.ToString() == "TreeView") |
||||
|
continue; |
||||
|
Console.WriteLine("Selecting " + page.Header); |
||||
|
tc.SelectedItem = page; |
||||
|
await Task.Delay(50); |
||||
|
} |
||||
|
Console.WriteLine("Selecting the first page"); |
||||
|
tc.SelectedItem = tc.Items.OfType<object>().First(); |
||||
|
await Task.Delay(500); |
||||
|
Console.WriteLine("Clicked through all pages, triggering GC"); |
||||
|
for (var c = 0; c < 3; c++) |
||||
|
{ |
||||
|
GC.Collect(2, GCCollectionMode.Forced); |
||||
|
await Task.Delay(50); |
||||
|
} |
||||
|
|
||||
|
void FormatMem(string metric, long bytes) |
||||
|
{ |
||||
|
Console.WriteLine(metric + ": " + bytes / 1024 / 1024 + "MB"); |
||||
|
} |
||||
|
|
||||
|
FormatMem("GC allocated bytes", GC.GetTotalMemory(true)); |
||||
|
FormatMem("WorkingSet64", Process.GetCurrentProcess().WorkingSet64); |
||||
|
}, TimeSpan.FromSeconds(1)); |
||||
|
}) |
||||
|
.StartWithClassicDesktopLifetime(args); |
||||
|
} |
||||
|
else if (args.Contains("--drm")) |
||||
|
{ |
||||
|
SilenceConsole(); |
||||
|
return builder.StartLinuxDrm(args, scaling: GetScaling()); |
||||
|
} |
||||
|
else if (args.Contains("--dxgi")) |
||||
|
{ |
||||
|
builder.With(new Win32PlatformOptions() |
||||
|
{ |
||||
|
CompositionMode = new [] { Win32CompositionMode.LowLatencyDxgiSwapChain } |
||||
|
}); |
||||
|
return builder.StartWithClassicDesktopLifetime(args); |
||||
|
} |
||||
|
else |
||||
|
return builder.StartWithClassicDesktopLifetime(args); |
||||
|
} |
||||
|
|
||||
/// <summary>
|
/// <summary>
|
||||
/// This method is needed for IDE previewer infrastructure
|
/// This method is needed for IDE previewer infrastructure
|
||||
/// </summary>
|
/// </summary>
|
||||
public static AppBuilder BuildAvaloniaApp() |
public static AppBuilder BuildAvaloniaApp() |
||||
=> AppBuilder.Configure<App>() |
=> AppBuilder.Configure<App>() |
||||
.LogToTrace() |
.UsePlatformDetect() |
||||
|
.With(new X11PlatformOptions |
||||
|
{ |
||||
|
EnableMultiTouch = true, |
||||
|
UseDBusMenu = true, |
||||
|
EnableIme = true, |
||||
|
}) |
||||
|
|
||||
|
.With(new VulkanOptions |
||||
|
{ |
||||
|
VulkanInstanceCreationOptions = new () |
||||
|
{ |
||||
|
UseDebug = true |
||||
|
} |
||||
|
}) |
||||
|
.With(new CompositionOptions() |
||||
|
{ |
||||
|
UseRegionDirtyRectClipping = true |
||||
|
}) |
||||
|
.UseSkia() |
||||
|
.WithInterFont() |
||||
.AfterSetup(builder => |
.AfterSetup(builder => |
||||
{ |
{ |
||||
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() |
if (!s_useFramebuffer) |
||||
{ |
{ |
||||
StartupScreenIndex = 1, |
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() |
||||
}); |
{ |
||||
|
StartupScreenIndex = 1, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
EmbedSample.Implementation = new EmbedSampleWin(); |
EmbedSample.Implementation = OperatingSystem.IsWindows() ? (INativeDemoControl)new EmbedSampleWin() |
||||
|
: OperatingSystem.IsMacOS() ? new EmbedSampleMac() |
||||
|
: OperatingSystem.IsLinux() ? new EmbedSampleGtk() |
||||
|
: null; |
||||
}) |
}) |
||||
.UseWin32() |
.LogToTrace(); |
||||
.UseSkia(); |
|
||||
|
|
||||
private static void ConfigureAssetAssembly(AppBuilder builder) |
static void SilenceConsole() |
||||
{ |
{ |
||||
AssetLoader.SetDefaultAssembly(typeof(App).Assembly); |
new Thread(() => |
||||
|
{ |
||||
|
Console.CursorVisible = false; |
||||
|
while (true) |
||||
|
Console.ReadKey(true); |
||||
|
}) |
||||
|
{ IsBackground = true }.Start(); |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,6 +1,6 @@ |
|||||
{ |
{ |
||||
"profiles": { |
"profiles": { |
||||
"ControlCatalog.NetCore": { |
"ControlCatalog.Desktop": { |
||||
"commandName": "Project" |
"commandName": "Project" |
||||
}, |
}, |
||||
"Dxgi": { |
"Dxgi": { |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue