Browse Source

Merge branch 'master' into aot-test-pipeline

pull/16108/head
Julien Lebosquain 2 years ago
committed by GitHub
parent
commit
3d116cca64
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      .github/pr_labels.yml
  2. 9
      Documentation/build.md
  3. 94
      api/Avalonia.Android.nupkg.xml
  4. 22
      api/Avalonia.Browser.nupkg.xml
  5. 76
      api/Avalonia.Controls.ColorPicker.nupkg.xml
  6. 16
      api/Avalonia.Controls.DataGrid.nupkg.xml
  7. 64
      api/Avalonia.Diagnostics.nupkg.xml
  8. 10
      api/Avalonia.Skia.nupkg.xml
  9. 448
      api/Avalonia.Themes.Fluent.nupkg.xml
  10. 424
      api/Avalonia.Themes.Simple.nupkg.xml
  11. 1112
      api/Avalonia.nupkg.xml
  12. 1
      build/SharedVersion.props
  13. 2
      build/SourceLink.props
  14. 14
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  15. 13
      native/Avalonia.Native/src/OSX/AvnAccessibility.h
  16. 18
      native/Avalonia.Native/src/OSX/AvnAutomationNode.h
  17. 2
      native/Avalonia.Native/src/OSX/AvnView.h
  18. 117
      native/Avalonia.Native/src/OSX/AvnView.mm
  19. 49
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  20. 93
      native/Avalonia.Native/src/OSX/Screens.mm
  21. 144
      native/Avalonia.Native/src/OSX/StorageProvider.mm
  22. 3
      native/Avalonia.Native/src/OSX/TopLevelImpl.h
  23. 50
      native/Avalonia.Native/src/OSX/TopLevelImpl.mm
  24. 8
      native/Avalonia.Native/src/OSX/WindowInterfaces.h
  25. 2
      native/Avalonia.Native/src/OSX/WindowProtocol.h
  26. 5
      native/Avalonia.Native/src/OSX/automation.h
  27. 163
      native/Avalonia.Native/src/OSX/automation.mm
  28. 11
      native/Avalonia.Native/src/OSX/common.h
  29. 8
      native/Avalonia.Native/src/OSX/main.mm
  30. 1
      native/Avalonia.Native/src/OSX/menu.mm
  31. 10
      nukebuild/Build.cs
  32. 12
      nukebuild/BuildParameters.cs
  33. 26
      packages/Avalonia/AvaloniaBuildTasks.targets
  34. 21
      samples/ControlCatalog.Android/MainActivity.cs
  35. 5
      samples/ControlCatalog.Browser/wwwroot/Logo.svg
  36. 46
      samples/ControlCatalog.Browser/wwwroot/app.css
  37. 16
      samples/ControlCatalog.Browser/wwwroot/index.html
  38. 8
      samples/ControlCatalog.Browser/wwwroot/main.js
  39. 3
      samples/ControlCatalog/MainView.xaml
  40. 10
      samples/ControlCatalog/MainView.xaml.cs
  41. 74
      samples/ControlCatalog/Pages/DateTimePickerPage.xaml
  42. 2
      samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs
  43. 50
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  44. 78
      samples/ControlCatalog/Pages/ScreenPage.cs
  45. 11
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  46. 6
      samples/ControlCatalog/Pages/ToolTipPage.xaml.cs
  47. 3
      samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs
  48. 27
      samples/IntegrationTestApp/App.axaml
  49. 20
      samples/IntegrationTestApp/App.axaml.cs
  50. 19
      samples/IntegrationTestApp/DelegateCommand.cs
  51. 9
      samples/IntegrationTestApp/IntegrationTestApp.csproj
  52. 68
      samples/IntegrationTestApp/MainWindow.axaml
  53. 210
      samples/IntegrationTestApp/MainWindow.axaml.cs
  54. 2
      samples/IntegrationTestApp/ShowWindowTest.axaml
  55. 22
      samples/IntegrationTestApp/ShowWindowTest.axaml.cs
  56. 17
      samples/IntegrationTestApp/TopmostWindowTest.axaml
  57. 21
      samples/IntegrationTestApp/TopmostWindowTest.axaml.cs
  58. 32
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  59. 18
      src/Android/Avalonia.Android/AvaloniaMainActivity.cs
  60. 65
      src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs
  61. 25
      src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs
  62. 1
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  63. 4
      src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs
  64. 22
      src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
  65. 2
      src/Android/Avalonia.Android/SingleViewLifetime.cs
  66. 4
      src/Avalonia.Base/ApiCompatBaseline.txt
  67. 4
      src/Avalonia.Base/AvaloniaObject.cs
  68. 2
      src/Avalonia.Base/Data/BindingNotification.cs
  69. 19
      src/Avalonia.Base/Data/BindingOperations.cs
  70. 2
      src/Avalonia.Base/Data/BindingValue.cs
  71. 14
      src/Avalonia.Base/Data/Core/BindingExpression.cs
  72. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/ArrayIndexerNode.cs
  73. 3
      src/Avalonia.Base/Data/Core/ExpressionNodes/AvaloniaPropertyAccessorNode.cs
  74. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/CollectionNodeBase.cs
  75. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/DataContextNode.cs
  76. 63
      src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs
  77. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/FuncTransformNode.cs
  78. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalAncestorElementNode.cs
  79. 4
      src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalNotNode.cs
  80. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/MethodCommandNode.cs
  81. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/NamedElementNode.cs
  82. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/ParentDataContextNode.cs
  83. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/PropertyAccessorNode.cs
  84. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginPropertyAccessorNode.cs
  85. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
  86. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ReflectionIndexerNode.cs
  87. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ReflectionTypeCastNode.cs
  88. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/StreamNode.cs
  89. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/TemplatedParentNode.cs
  90. 5
      src/Avalonia.Base/Data/Core/ExpressionNodes/VisualAncestorElementNode.cs
  91. 15
      src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs
  92. 4
      src/Avalonia.Base/Data/TemplateBinding.cs
  93. 5
      src/Avalonia.Base/Input/MouseDevice.cs
  94. 6
      src/Avalonia.Base/Input/TouchDevice.cs
  95. 4
      src/Avalonia.Base/Media/Fonts/Tables/HorizontalHeadTable.cs
  96. 32
      src/Avalonia.Base/Media/Fonts/Tables/Name/NameTable.cs
  97. 7
      src/Avalonia.Base/Media/GlyphRun.cs
  98. 4
      src/Avalonia.Base/Media/IGlyphTypeface2.cs
  99. 15
      src/Avalonia.Base/Media/TextDecoration.cs
  100. 5
      src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs

8
.github/pr_labels.yml

@ -1,6 +1,8 @@
version: '1.1.0'
invalidStatus: "pending"
labelRule:
# Allow any label, while requiring at least some
startsWith:
- ""
values:
- "bug"
- "feature"
- "enhancement"
- "area-infrastructure"

9
Documentation/build.md

@ -100,7 +100,14 @@ On macOS it is necessary to build and manually install the respective native lib
# Building Avalonia into a local NuGet cache
It is possible to build Avalonia locally and generate NuGet packages that can be used locally to test local changes.
To do so you need to run:
First, install Nuke's dotnet global tool like so:
```bash
dotnet tool install Nuke.GlobalTool --global
```
Then you need to run:
```bash
nuke --target BuildToNuGetCache --configuration Release
```

94
api/Avalonia.Android.nupkg.xml

@ -1,94 +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.Internal.Resource.Animation</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Animator</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Attribute</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Boolean</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Color</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Dimension</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Drawable</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Id</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Integer</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Interpolator</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Layout</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.String</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Style</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Styleable</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
</Suppressions>

22
api/Avalonia.Browser.nupkg.xml

@ -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.AvaloniaView.get_IsComposing</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Browser.AvaloniaView.OnDragEvent(System.Runtime.InteropServices.JavaScript.JSObject)</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.Browser.AvaloniaView</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
</Suppressions>

76
api/Avalonia.Controls.ColorPicker.nupkg.xml

@ -1,76 +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:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorPicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorPreviewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorSlider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorSpectrum.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/Fluent.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorPicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorPreviewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorSlider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorSpectrum.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/Simple.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
</Suppressions>

16
api/Avalonia.Controls.DataGrid.nupkg.xml

@ -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>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.DataGrid.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.DataGrid.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.DataGrid.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.DataGrid.dll</Right>
</Suppression>
</Suppressions>

64
api/Avalonia.Diagnostics.nupkg.xml

@ -1,64 +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:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/BrushEditor.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/FilterTextBox.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/ThicknessEditor.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/ConsoleView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/ControlDetailsView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/EventsPageView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/LayoutExplorerView.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/MainView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/MainWindow.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/TreePageView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
</Suppressions>

10
api/Avalonia.Skia.nupkg.xml

@ -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>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaSharpApiLease.TryLeasePlatformGraphicsApi</Target>
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
</Suppression>
</Suppressions>

448
api/Avalonia.Themes.Fluent.nupkg.xml

@ -1,448 +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:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/BaseColorsPalette.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/BaseResources.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/FluentControlResources.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AdornerLayer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AutoCompleteBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Button.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ButtonSpinner.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Calendar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDayButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CaptionButtons.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Carousel.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CheckBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContextMenu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DataValidationErrors.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DateTimePickerShared.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DropDownButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/EmbeddableControlRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Expander.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FluentControls.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/GridSplitter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ItemsControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Label.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ManagedFileChooser.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Menu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuFlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NativeMenuBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NotificationCard.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NumericUpDown.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/OverlayPopupHost.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PathIcon.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PopupRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ProgressBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RadioButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshContainer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshVisualizer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RepeatButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SelectableTextBlock.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Separator.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Slider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStrip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStripItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TextBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ThemeVariantScope.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TimePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TitleBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleSwitch.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToolTip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TransitioningContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeViewItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/UserControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Window.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/WindowNotificationManager.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/DensityStyles/Compact.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/FluentTheme.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
</Suppressions>

424
api/Avalonia.Themes.Simple.nupkg.xml

@ -1,424 +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:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/Base.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AdornerLayer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AutoCompleteBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Button.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ButtonSpinner.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Calendar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDayButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CaptionButtons.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Carousel.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CheckBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContextMenu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DataValidationErrors.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DateTimePickerShared.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DropDownButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/EmbeddableControlRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Expander.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/GridSplitter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ItemsControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Label.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ManagedFileChooser.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Menu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuFlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NativeMenuBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NotificationCard.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NumericUpDown.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/OverlayPopupHost.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PathIcon.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PopupRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ProgressBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RadioButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshContainer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshVisualizer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RepeatButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SelectableTextBlock.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Separator.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SimpleControls.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Slider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStrip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStripItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TextBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ThemeVariantScope.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TimePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TitleBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleSwitch.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToolTip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TransitioningContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeViewItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/UserControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Window.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/WindowNotificationManager.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/SimpleTheme.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
</Suppressions>

1112
api/Avalonia.nupkg.xml

File diff suppressed because it is too large

1
build/SharedVersion.props

@ -3,6 +3,7 @@
<PropertyGroup>
<Product>Avalonia</Product>
<Version>11.2.999</Version>
<ApiCompatVersion>11.1.0</ApiCompatVersion>
<Authors>Avalonia Team</Authors>
<Copyright>Copyright 2013-$([System.DateTime]::Now.ToString(`yyyy`)) &#169; The AvaloniaUI Project</Copyright>
<PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>

2
build/SourceLink.props

@ -20,6 +20,6 @@
<!-- Workaround for https://github.com/dotnet/sdk/issues/11105 -->
<ItemGroup>
<SourceRoot Include="$(NuGetPackageRoot)" Condition="'$(NuGetPackageRoot)' != ''" />
<SourceRoot Include="$([MSBuild]::EnsureTrailingSlash($(NuGetPackageRoot)))" Condition="'$(NuGetPackageRoot)' != ''" />
</ItemGroup>
</Project>

14
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@ -34,7 +34,7 @@
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
37C09D8821580FE4006A6758 /* StorageProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* StorageProvider.mm */; };
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
@ -57,6 +57,7 @@
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; };
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; };
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; };
BC7C33822C066DBF00945A48 /* AvnAutomationNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */; };
ED3791C42862E1F40080BD62 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */; };
ED754D262A97306B0078B4DF /* PlatformRenderTimer.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */; };
EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; };
@ -94,7 +95,7 @@
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; };
37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* StorageProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = StorageProvider.mm; sourceTree = "<group>"; };
37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; };
37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
@ -122,6 +123,8 @@
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; };
BC11A5BC2608D58F0017BAD0 /* automation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = automation.h; sourceTree = "<group>"; };
BC11A5BD2608D58F0017BAD0 /* automation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = automation.mm; sourceTree = "<group>"; };
BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnAutomationNode.h; sourceTree = "<group>"; };
BC7C33832C066F1100945A48 /* AvnAccessibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnAccessibility.h; sourceTree = "<group>"; };
ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformRenderTimer.mm; sourceTree = "<group>"; };
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = "<group>"; };
@ -167,6 +170,8 @@
isa = PBXGroup;
children = (
F10084852BFF1FB40024303E /* TopLevelImpl.mm */,
BC7C33832C066F1100945A48 /* AvnAccessibility.h */,
BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */,
ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */,
855EDC9E28C6546F00807998 /* PlatformBehaviorInhibition.mm */,
8D2F3511292F6AAE007FCF54 /* AvnTextInputMethodDelegate.h */,
@ -197,7 +202,7 @@
523484CB26EA68AA00EA0C2C /* trayicon.h */,
1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */,
37A517B22159597E00FBA241 /* Screens.mm */,
37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
37C09D8721580FE4006A6758 /* StorageProvider.mm */,
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */,
AB7A61F02147C815003C5833 /* Products */,
AB661C1C2148230E00291242 /* Frameworks */,
@ -245,6 +250,7 @@
183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */,
1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */,
183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */,
BC7C33822C066DBF00945A48 /* AvnAutomationNode.h in Headers */,
18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */,
8D300D65292D0A6800320C49 /* AvnTextInputMethod.h in Headers */,
8D2F3512292F6AAE007FCF54 /* AvnTextInputMethodDelegate.h in Headers */,
@ -333,7 +339,7 @@
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */,
1A465D10246AB61600C5858B /* dnd.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
37C09D8821580FE4006A6758 /* StorageProvider.mm in Sources */,
1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */,
F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */,
1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */,

13
native/Avalonia.Native/src/OSX/AvnAccessibility.h

@ -0,0 +1,13 @@
#pragma once
#import <Cocoa/Cocoa.h>
#import "avalonia-native.h"
// Defines the interface between AvnAutomationNode and objects which implement
// NSAccessibility such as AvnAccessibilityElement or AvnWindow.
@protocol AvnAccessibility <NSAccessibility>
@required
- (void) raiseChildrenChanged;
@optional
- (void) raiseFocusChanged;
- (void) raisePropertyChanged:(AvnAutomationProperty)property;
@end

18
native/Avalonia.Native/src/OSX/AvnAutomationNode.h

@ -0,0 +1,18 @@
#pragma once
#include "avalonia-native.h"
#include "AvnAccessibility.h"
// Defines a means for managed code to raise accessibility events.
class AvnAutomationNode : public ComSingleObject<IAvnAutomationNode, &IID_IAvnAutomationNode>
{
public:
FORWARD_IUNKNOWN()
AvnAutomationNode(id <AvnAccessibility> owner) { _owner = owner; }
AvnAccessibilityElement* GetOwner() { return _owner; }
virtual void Dispose() override { _owner = nil; }
virtual void ChildrenChanged () override { [_owner raiseChildrenChanged]; }
virtual void PropertyChanged (AvnAutomationProperty property) override { [_owner raisePropertyChanged:property]; }
virtual void FocusChanged () override { [_owner raiseFocusChanged]; }
private:
__strong id <AvnAccessibility> _owner;
};

2
native/Avalonia.Native/src/OSX/AvnView.h

@ -22,5 +22,5 @@
-(AvnPlatformResizeReason) getResizeReason;
-(void) setResizeReason:(AvnPlatformResizeReason)reason;
-(void) setRenderTarget:(NSObject<IRenderTarget>* _Nonnull)target;
+ (AvnPoint)toAvnPoint:(CGPoint)p;
-(void) raiseAccessibilityChildrenChanged;
@end

117
native/Avalonia.Native/src/OSX/AvnView.mm

@ -19,12 +19,12 @@
AvnPixelSize _lastPixelSize;
NSObject<IRenderTarget>* _currentRenderTarget;
AvnPlatformResizeReason _resizeReason;
AvnAccessibilityElement* _accessibilityChild;
NSRect _cursorRect;
NSMutableAttributedString* _text;
NSRange _selectedRange;
NSRange _markedRange;
NSEvent* _lastKeyDownEvent;
NSMutableArray* _accessibilityChildren;
}
- (void)onClosed
@ -189,16 +189,6 @@
return pt;
}
+ (AvnPoint)toAvnPoint:(CGPoint)p
{
AvnPoint result;
result.X = p.x;
result.Y = p.y;
return result;
}
- (void) viewDidChangeBackingProperties
{
auto fsize = [self convertSizeToBacking: [self frame].size];
@ -255,9 +245,13 @@
return;
}
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
auto avnPoint = [AvnView toAvnPoint:localPoint];
auto point = [self translateLocalPoint:avnPoint];
NSPoint eventLocation = [event locationInWindow];
auto viewLocation = [self convertPoint:NSMakePoint(0, 0) toView:nil];
auto localPoint = NSMakePoint(eventLocation.x - viewLocation.x, viewLocation.y - eventLocation.y);
auto point = ToAvnPoint(localPoint);
AvnVector delta = { 0, 0};
if(type == Wheel)
@ -303,7 +297,22 @@
)
)
)
[self becomeFirstResponder];
{
WindowBaseImpl* windowBase = dynamic_cast<WindowBaseImpl*>(_parent.getRaw());
if(windowBase != nullptr){
WindowBaseImpl* parent = windowBase->Parent;
if(parent != nullptr){
auto parentWindow = parent->Window;
[parentWindow makeFirstResponder:parent->View];
}
} else{
[self becomeFirstResponder];
}
}
if(_parent != nullptr)
{
@ -442,6 +451,7 @@
- (void)mouseEntered:(NSEvent *)event
{
[self mouseEvent:event withType:Move];
[super mouseEntered:event];
}
@ -733,7 +743,7 @@
- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id <NSDraggingInfo>)info
{
auto localPoint = [self convertPoint:[info draggingLocation] toView:self];
auto avnPoint = [AvnView toAvnPoint:localPoint];
auto avnPoint = ToAvnPoint(localPoint);
auto point = [self translateLocalPoint:avnPoint];
auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
NSDragOperation nsop = [info draggingSourceOperationMask];
@ -801,35 +811,74 @@
_resizeReason = reason;
}
- (AvnAccessibilityElement *) accessibilityChild
- (NSArray *)accessibilityChildren
{
if (_accessibilityChild == nil)
{
auto peer = _parent->TopLevelEvents->GetAutomationPeer();
if (_accessibilityChildren == nil)
[self recalculateAccessibiltyChildren];
return _accessibilityChildren;
}
if (peer == nil)
return nil;
- (id _Nullable) accessibilityHitTest:(NSPoint)point
{
if (![[self window] isKindOfClass:[AvnWindow class]])
return self;
_accessibilityChild = [AvnAccessibilityElement acquire:peer];
}
auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer];
return _accessibilityChild;
}
if (!peer->IsRootProvider())
return nil;
- (NSArray *)accessibilityChildren
{
auto child = [self accessibilityChild];
return NSAccessibilityUnignoredChildrenForOnlyChild(child);
auto clientPoint = [window convertPointFromScreen:point];
auto localPoint = [self translateLocalPoint:ToAvnPoint(clientPoint)];
auto hit = peer->RootProvider_GetPeerFromPoint(localPoint);
return [AvnAccessibilityElement acquire:hit];
}
- (id)accessibilityHitTest:(NSPoint)point
- (void)raiseAccessibilityChildrenChanged
{
return [[self accessibilityChild] accessibilityHitTest:point];
auto changed = _accessibilityChildren ? [NSMutableSet setWithArray:_accessibilityChildren] : [NSMutableSet set];
[self recalculateAccessibiltyChildren];
if (_accessibilityChildren)
[changed addObjectsFromArray:_accessibilityChildren];
NSAccessibilityPostNotificationWithUserInfo(
self,
NSAccessibilityLayoutChangedNotification,
@{ NSAccessibilityUIElementsKey: [changed allObjects]});
}
- (id)accessibilityFocusedUIElement
- (void)recalculateAccessibiltyChildren
{
return [[self accessibilityChild] accessibilityFocusedUIElement];
_accessibilityChildren = [[NSMutableArray alloc] init];
if (![[self window] isKindOfClass:[AvnWindow class]])
{
return;
}
// The accessibility children of the Window are exposed as children
// of the AvnView.
auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer];
auto childPeers = peer->GetChildren();
auto childCount = childPeers != nullptr ? childPeers->GetCount() : 0;
if (childCount > 0)
{
for (int i = 0; i < childCount; ++i)
{
IAvnAutomationPeer* child;
if (childPeers->Get(i, &child) == S_OK)
{
id element = [AvnAccessibilityElement acquire:child];
[_accessibilityChildren addObject:element];
}
}
}
}
- (void) setText:(NSString *)text{

49
native/Avalonia.Native/src/OSX/AvnWindow.mm

@ -24,6 +24,8 @@
#include "WindowImpl.h"
#include "AvnView.h"
#include "WindowInterfaces.h"
#include "AvnAutomationNode.h"
#include "AvnString.h"
@implementation CLASS_NAME
{
@ -34,6 +36,13 @@
bool _isExtended;
bool _isTransitioningToFullScreen;
AvnMenu* _menu;
IAvnAutomationPeer* _automationPeer;
AvnAutomationNode* _automationNode;
}
-(AvnView* _Nullable) view
{
return _parent->View;
}
-(void) setIsExtended:(bool)value;
@ -208,7 +217,7 @@
ComPtr<WindowBaseImpl> parent = _parent;
_parent = NULL;
auto window = dynamic_cast<WindowImpl*>(parent.getRaw());
auto window = dynamic_cast<WindowImpl*>(parent.getRaw());
if(window != nullptr)
{
@ -453,7 +462,7 @@
if (!NSPointInRect(viewPoint, view.bounds))
{
auto avnPoint = [AvnView toAvnPoint:windowPoint];
auto avnPoint = ToAvnPoint(windowPoint);
auto point = [self translateLocalPoint:avnPoint];
AvnVector delta = { 0, 0 };
@ -489,5 +498,41 @@
_parent = nullptr;
}
- (id _Nullable) accessibilityFocusedUIElement
{
if (![self automationPeer]->IsRootProvider())
return nil;
auto focusedPeer = [self automationPeer]->RootProvider_GetFocus();
return [AvnAccessibilityElement acquire:focusedPeer];
}
- (NSString * _Nullable) accessibilityIdentifier
{
return GetNSStringAndRelease([self automationPeer]->GetAutomationId());
}
- (IAvnAutomationPeer* _Nonnull) automationPeer
{
if (_automationPeer == nullptr)
{
_automationPeer = _parent->BaseEvents->GetAutomationPeer();
_automationNode = new AvnAutomationNode(self);
_automationPeer->SetNode(_automationNode);
}
return _automationPeer;
}
- (void)raiseChildrenChanged
{
[_parent->View raiseAccessibilityChildrenChanged];
}
- (void)raiseFocusChanged
{
id focused = [self accessibilityFocusedUIElement];
NSAccessibilityPostNotification(focused, NSAccessibilityFocusedUIElementChangedNotification);
}
@end

93
native/Avalonia.Native/src/OSX/Screens.mm

@ -1,36 +1,62 @@
#include "common.h"
#include "AvnString.h"
class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens>
{
public:
FORWARD_IUNKNOWN()
private:
ComPtr<IAvnScreenEvents> _events;
public:
virtual HRESULT GetScreenCount (int* ret) override
FORWARD_IUNKNOWN()
Screens(IAvnScreenEvents* events) {
_events = events;
CGDisplayRegisterReconfigurationCallback(CGDisplayReconfigurationCallBack, this);
}
virtual HRESULT GetScreenIds (
unsigned int* ptrFirstResult,
int* screenCound) override
{
START_COM_CALL;
@autoreleasepool
{
*ret = (int)[NSScreen screens].count;
auto screens = [NSScreen screens];
*screenCound = (int)screens.count;
if (ptrFirstResult == nil)
return S_OK;
for (int i = 0; i < screens.count; i++) {
ptrFirstResult[i] = [[screens objectAtIndex:i] av_displayId];
}
return S_OK;
}
}
virtual HRESULT GetScreen (int index, AvnScreen* ret) override
{
virtual HRESULT GetScreen (
CGDirectDisplayID displayId,
void** localizedName,
AvnScreen* ret
) override {
START_COM_CALL;
@autoreleasepool
{
if(index < 0 || index >= [NSScreen screens].count)
{
return E_INVALIDARG;
NSScreen* screen;
for (NSScreen *s in NSScreen.screens) {
if (s.av_displayId == displayId)
{
screen = s;
break;
}
}
auto screen = [[NSScreen screens] objectAtIndex:index];
if (screen == nil) {
return E_INVALIDARG;
}
ret->Bounds.Height = [screen frame].size.height;
ret->Bounds.Width = [screen frame].size.width;
ret->Bounds.X = [screen frame].origin.x;
@ -43,14 +69,45 @@ public:
ret->Scaling = 1;
ret->IsPrimary = index == 0;
ret->IsPrimary = CGDisplayIsMain(displayId);
// Compute natural orientation:
auto naturalScreenSize = CGDisplayScreenSize(displayId);
auto isNaturalLandscape = naturalScreenSize.width > naturalScreenSize.height;
// Normalize rotation:
auto rotation = (int)CGDisplayRotation(displayId) % 360;
if (rotation < 0) rotation = 360 - rotation;
// Get current orientation relative to the natural
if (rotation >= 0 && rotation < 90) {
ret->Orientation = isNaturalLandscape ? AvnScreenOrientation::Landscape : AvnScreenOrientation::Portrait;
} else if (rotation >= 90 && rotation < 180) {
ret->Orientation = isNaturalLandscape ? AvnScreenOrientation::Portrait : AvnScreenOrientation::Landscape;
} else if (rotation >= 180 && rotation < 270) {
ret->Orientation = isNaturalLandscape ? AvnScreenOrientation::LandscapeFlipped : AvnScreenOrientation::PortraitFlipped;
} else {
ret->Orientation = isNaturalLandscape ? AvnScreenOrientation::PortraitFlipped : AvnScreenOrientation::LandscapeFlipped;
}
if (@available(macOS 10.15, *)) {
*localizedName = CreateAvnString([screen localizedName]);
}
return S_OK;
}
}
private:
static void CGDisplayReconfigurationCallBack(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *screens)
{
auto object = (Screens *)screens;
auto events = object->_events;
if (events != nil) {
events->OnChanged();
}
}
};
extern IAvnScreens* CreateScreens()
extern IAvnScreens* CreateScreens(IAvnScreenEvents* events)
{
return new Screens();
return new Screens(events);
}

144
native/Avalonia.Native/src/OSX/SystemDialogs.mm → native/Avalonia.Native/src/OSX/StorageProvider.mm

@ -64,12 +64,91 @@ const int kFileTypePopupTag = 10975;
@end
class SystemDialogs : public ComSingleObject<IAvnSystemDialogs, &IID_IAvnSystemDialogs>
class StorageProvider : public ComSingleObject<IAvnStorageProvider, &IID_IAvnStorageProvider>
{
ExtensionDropdownHandler* __strong _extension_dropdown_handler;
public:
FORWARD_IUNKNOWN()
virtual HRESULT SaveBookmarkToBytes (
IAvnString* fileUriStr,
void** err,
IAvnString** ppv
) override
{
@autoreleasepool
{
if(ppv == nullptr)
return E_POINTER;
NSError* error;
auto fileUri = [NSURL URLWithString: GetNSStringAndRelease(fileUriStr)];
auto bookmarkData = [fileUri bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error];
if (bookmarkData)
{
*ppv = CreateByteArray((void*)bookmarkData.bytes, (int)bookmarkData.length);
}
if (error != nil)
{
*err = CreateAvnString([error localizedDescription]);
}
return S_OK;
}
}
virtual HRESULT ReadBookmarkFromBytes (
void* ptr,
int len,
IAvnString** ppv
) override {
@autoreleasepool
{
if(ppv == nullptr)
return E_POINTER;
auto bookmarkData = [[NSData alloc] initWithBytes:ptr length:len];
auto fileUri = [NSURL URLByResolvingBookmarkData: bookmarkData
options:NSURLBookmarkResolutionWithSecurityScope|NSURLBookmarkResolutionWithoutUI
relativeToURL:nil
bookmarkDataIsStale:nil
error:nil];
if (fileUri)
{
*ppv = CreateAvnString([fileUri absoluteString]);
}
return S_OK;
}
}
virtual void ReleaseBookmark (
IAvnString* fileUriStr
) override {
// no-op
}
virtual bool OpenSecurityScope (
IAvnString* fileUriStr
) override {
@autoreleasepool
{
auto fileUri = [NSURL URLWithString: GetNSStringAndRelease(fileUriStr)];
auto success = [fileUri startAccessingSecurityScopedResource];
return success;
}
}
virtual void CloseSecurityScope (
IAvnString* fileUriStr
) override {
@autoreleasepool
{
auto fileUri = [NSURL URLWithString: GetNSStringAndRelease(fileUriStr)];
[fileUri stopAccessingSecurityScopedResource];
}
}
virtual void SelectFolderDialog (IAvnWindow* parentWindowHandle,
IAvnSystemDialogEvents* events,
bool allowMultiple,
@ -94,7 +173,8 @@ public:
if(initialDirectory != nullptr)
{
auto directoryString = [NSString stringWithUTF8String:initialDirectory];
panel.directoryURL = [NSURL fileURLWithPath:directoryString];
panel.directoryURL = [NSURL fileURLWithPath:directoryString
isDirectory:true];
}
auto handler = ^(NSModalResponse result) {
@ -104,19 +184,9 @@ public:
if(urls.count > 0)
{
void* strings[urls.count];
for(int i = 0; i < urls.count; i++)
{
auto url = [urls objectAtIndex:i];
auto string = [url path];
strings[i] = (void*)[string UTF8String];
}
events->OnCompleted((int)urls.count, &strings[0]);
auto uriStrings = CreateAvnStringArray(urls);
events->OnCompleted(uriStrings);
[panel orderOut:panel];
if(parentWindowHandle != nullptr)
@ -129,7 +199,7 @@ public:
}
}
events->OnCompleted(0, nullptr);
events->OnCompleted(nullptr);
};
@ -169,7 +239,8 @@ public:
if(initialDirectory != nullptr)
{
auto directoryString = [NSString stringWithUTF8String:initialDirectory];
panel.directoryURL = [NSURL fileURLWithPath:directoryString];
panel.directoryURL = [NSURL fileURLWithPath:directoryString
isDirectory:true];
}
if(initialFile != nullptr)
@ -186,19 +257,9 @@ public:
if(urls.count > 0)
{
void* strings[urls.count];
for(int i = 0; i < urls.count; i++)
{
auto url = [urls objectAtIndex:i];
auto string = [url path];
strings[i] = (void*)[string UTF8String];
}
events->OnCompleted((int)urls.count, &strings[0]);
auto uriStrings = CreateAvnStringArray(urls);
events->OnCompleted(uriStrings);
[panel orderOut:panel];
if(parentWindowHandle != nullptr)
@ -211,7 +272,7 @@ public:
}
}
events->OnCompleted(0, nullptr);
events->OnCompleted(nullptr);
};
@ -248,7 +309,8 @@ public:
if(initialDirectory != nullptr)
{
auto directoryString = [NSString stringWithUTF8String:initialDirectory];
panel.directoryURL = [NSURL fileURLWithPath:directoryString];
panel.directoryURL = [NSURL fileURLWithPath:directoryString
isDirectory:true];
}
if(initialFile != nullptr)
@ -261,15 +323,11 @@ public:
auto handler = ^(NSModalResponse result) {
if(result == NSFileHandlingPanelOKButton)
{
void* strings[1];
auto url = [panel URL];
auto string = [url path];
strings[0] = (void*)[string UTF8String];
events->OnCompleted(1, &strings[0]);
auto urls = [NSArray<NSURL*> arrayWithObject:url];
auto uriStrings = CreateAvnStringArray(urls);
events->OnCompleted(uriStrings);
[panel orderOut:panel];
if(parentWindowHandle != nullptr)
@ -281,7 +339,7 @@ public:
return;
}
events->OnCompleted(0, nullptr);
events->OnCompleted(nullptr);
};
@ -516,7 +574,7 @@ private:
};
};
extern IAvnSystemDialogs* CreateSystemDialogs()
extern IAvnStorageProvider* CreateStorageProvider()
{
return new SystemDialogs();
return new StorageProvider();
}

3
native/Avalonia.Native/src/OSX/TopLevelImpl.h

@ -58,7 +58,8 @@ public:
virtual HRESULT PointToScreen(AvnPoint point, AvnPoint *ret) override;
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override;
protected:
NSCursor *cursor;
virtual void UpdateAppearance();

50
native/Avalonia.Native/src/OSX/TopLevelImpl.mm

@ -192,11 +192,23 @@ HRESULT TopLevelImpl::PointToClient(AvnPoint point, AvnPoint *ret) {
return S_OK;
}
point = ConvertPointY(point);
NSRect convertRect = [window convertRectFromScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto viewPoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
auto frame = [View frame];
auto viewRect = [View convertRect:frame toView:nil];
auto viewScreenRect = [window convertRectToScreen:viewRect];
auto primaryDisplayHeight = NSMaxY([[[NSScreen screens] firstObject] frame]);
//Window coord are bottom to top so we need to adjust by primaryScreenHeight
auto viewScreenLocation = NSMakePoint(viewScreenRect.origin.x, primaryDisplayHeight - viewScreenRect.origin.y - frame.size.height);
//Substract client point from screen position of the view
auto localPoint = NSMakePoint(point.X - viewScreenLocation.x, point.Y - viewScreenLocation.y);
point = ToAvnPoint(localPoint);
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
*ret = point;
return S_OK;
}
@ -217,11 +229,24 @@ HRESULT TopLevelImpl::PointToScreen(AvnPoint point, AvnPoint *ret) {
return S_OK;
}
auto frame = [View frame];
//Get rect inside current window
auto viewRect = [View convertRect:frame toView:nil];
//Get screen rect of the view
auto viewScreenRect = [window convertRectToScreen:viewRect];
auto primaryDisplayHeight = NSMaxY([[[NSScreen screens] firstObject] frame]);
//Window coord are bottom to top so we need to adjust by primaryScreenHeight
auto viewScreenLocation = NSMakePoint(viewScreenRect.origin.x, primaryDisplayHeight - viewScreenRect.origin.y - frame.size.height);
auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]);
NSRect convertRect = [window convertRectToScreen:NSMakeRect(cocoaViewPoint.x, cocoaViewPoint.y, 0.0, 0.0)];
auto cocoaScreenPoint = NSPointFromCGPoint(NSMakePoint(convertRect.origin.x, convertRect.origin.y));
*ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
//Add client point to screen position of the view
auto screenPoint = ToAvnPoint(NSMakePoint(viewScreenLocation.x + point.X, viewScreenLocation.y + point.Y));
*ret = screenPoint;
return S_OK;
}
@ -233,6 +258,15 @@ HRESULT TopLevelImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
return S_OK;
}
HRESULT TopLevelImpl::GetCurrentDisplayId (CGDirectDisplayID* ret) {
START_COM_CALL;
auto window = [View window];
*ret = [window.screen av_displayId];
return S_OK;
}
void TopLevelImpl::UpdateAppearance() {
}

8
native/Avalonia.Native/src/OSX/WindowInterfaces.h

@ -7,11 +7,13 @@
#import <AppKit/AppKit.h>
#include "WindowProtocol.h"
#include "WindowBaseImpl.h"
#include "AvnAccessibility.h"
@interface AvnWindow : NSWindow <AvnWindowProtocol, NSWindowDelegate>
@interface AvnWindow : NSWindow <AvnWindowProtocol, NSWindowDelegate, AvnAccessibility>
-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
-(AvnView* _Nullable) view;
@end
@interface AvnPanel : NSPanel <AvnWindowProtocol, NSWindowDelegate>
@interface AvnPanel : NSPanel <AvnWindowProtocol, NSWindowDelegate, AvnAccessibility>
-(AvnPanel* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask;
@end
@end

2
native/Avalonia.Native/src/OSX/WindowProtocol.h

@ -8,6 +8,7 @@
#import <AppKit/AppKit.h>
@class AvnMenu;
struct IAvnAutomationPeer;
@protocol AvnWindowProtocol
-(void) pollModalSession: (NSModalSession _Nonnull) session;
@ -16,6 +17,7 @@
-(void) showAppMenuOnly;
-(void) showWindowMenuWithAppMenu;
-(void) applyMenu:(AvnMenu* _Nullable)menu;
-(IAvnAutomationPeer* _Nonnull) automationPeer;
-(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value;

5
native/Avalonia.Native/src/OSX/automation.h

@ -1,12 +1,13 @@
#pragma once
#import <Cocoa/Cocoa.h>
#include "AvnAccessibility.h"
NS_ASSUME_NONNULL_BEGIN
class IAvnAutomationPeer;
@interface AvnAccessibilityElement : NSAccessibilityElement
+ (AvnAccessibilityElement *) acquire:(IAvnAutomationPeer *) peer;
@interface AvnAccessibilityElement : NSAccessibilityElement <AvnAccessibility>
+ (id _Nullable) acquire:(IAvnAutomationPeer *) peer;
@end
NS_ASSUME_NONNULL_END

163
native/Avalonia.Native/src/OSX/automation.mm

@ -1,66 +1,19 @@
#include "common.h"
#include "automation.h"
#include "AvnAutomationNode.h"
#include "AvnString.h"
#include "INSWindowHolder.h"
#include "AvnView.h"
@interface AvnAccessibilityElement (Events)
- (void) raiseChildrenChanged;
@end
@interface AvnRootAccessibilityElement : AvnAccessibilityElement
- (AvnView *) ownerView;
- (AvnRootAccessibilityElement *) initWithPeer:(IAvnAutomationPeer *) peer owner:(AvnView*) owner;
- (void) raiseFocusChanged;
@end
class AutomationNode : public ComSingleObject<IAvnAutomationNode, &IID_IAvnAutomationNode>
{
public:
FORWARD_IUNKNOWN()
AutomationNode(AvnAccessibilityElement* owner)
{
_owner = owner;
}
AvnAccessibilityElement* GetOwner()
{
return _owner;
}
virtual void Dispose() override
{
_owner = nil;
}
virtual void ChildrenChanged () override
{
[_owner raiseChildrenChanged];
}
virtual void PropertyChanged (AvnAutomationProperty property) override
{
}
virtual void FocusChanged () override
{
[(AvnRootAccessibilityElement*)_owner raiseFocusChanged];
}
private:
__strong AvnAccessibilityElement* _owner;
};
#include "WindowInterfaces.h"
@implementation AvnAccessibilityElement
{
IAvnAutomationPeer* _peer;
AutomationNode* _node;
AvnAutomationNode* _node;
NSMutableArray* _children;
}
+ (AvnAccessibilityElement *)acquire:(IAvnAutomationPeer *)peer
+ (id _Nullable)acquire:(IAvnAutomationPeer *)peer
{
if (peer == nullptr)
return nil;
@ -68,7 +21,7 @@ private:
auto instance = peer->GetNode();
if (instance != nullptr)
return dynamic_cast<AutomationNode*>(instance)->GetOwner();
return dynamic_cast<AvnAutomationNode*>(instance)->GetOwner();
if (peer->IsRootProvider())
{
@ -82,7 +35,7 @@ private:
auto holder = dynamic_cast<INSViewHolder*>(window);
auto view = holder->GetNSView();
return [[AvnRootAccessibilityElement alloc] initWithPeer:peer owner:view];
return [view window];
}
else
{
@ -94,7 +47,7 @@ private:
{
self = [super init];
_peer = peer;
_node = new AutomationNode(self);
_node = new AvnAutomationNode(self);
_peer->SetNode(_node);
return self;
}
@ -256,25 +209,8 @@ private:
- (NSRect)accessibilityFrame
{
id topLevel = [self accessibilityTopLevelUIElement];
auto result = NSZeroRect;
if ([topLevel isKindOfClass:[AvnRootAccessibilityElement class]])
{
auto root = (AvnRootAccessibilityElement*)topLevel;
auto view = [root ownerView];
if (view)
{
auto window = [view window];
auto bounds = ToNSRect(_peer->GetBoundingRectangle());
auto windowBounds = [view convertRect:bounds toView:nil];
auto screenBounds = [window convertRectToScreen:windowBounds];
result = screenBounds;
}
}
return result;
auto bounds = _peer->GetBoundingRectangle();
return [self rectToScreen:bounds];
}
- (id)accessibilityParent
@ -389,6 +325,24 @@ private:
return [super isAccessibilitySelectorAllowed:selector];
}
- (NSRect)rectToScreen:(AvnRect)rect
{
id topLevel = [self accessibilityTopLevelUIElement];
if (![topLevel isKindOfClass:[AvnWindow class]])
return NSZeroRect;
auto window = (AvnWindow*)topLevel;
auto view = [window view];
if (view == nil)
return NSZeroRect;
auto nsRect = ToNSRect(rect);
auto windowRect = [view convertRect:nsRect toView:nil];
return [window convertRectToScreen:windowRect];
}
- (void)raiseChildrenChanged
{
auto changed = _children ? [NSMutableSet setWithArray:_children] : [NSMutableSet set];
@ -429,7 +383,7 @@ private:
if (childPeers->Get(i, &child) == S_OK)
{
auto element = [AvnAccessibilityElement acquire:child];
id element = [AvnAccessibilityElement acquire:child];
[_children addObject:element];
}
}
@ -441,64 +395,3 @@ private:
}
@end
@implementation AvnRootAccessibilityElement
{
AvnView* _owner;
}
- (AvnRootAccessibilityElement *)initWithPeer:(IAvnAutomationPeer *)peer owner:(AvnView *)owner
{
self = [super initWithPeer:peer];
_owner = owner;
// Seems we need to raise a focus changed notification here if we have focus
auto focusedPeer = [self peer]->RootProvider_GetFocus();
id focused = [AvnAccessibilityElement acquire:focusedPeer];
if (focused)
NSAccessibilityPostNotification(focused, NSAccessibilityFocusedUIElementChangedNotification);
return self;
}
- (AvnView *)ownerView
{
return _owner;
}
- (id)accessibilityFocusedUIElement
{
auto focusedPeer = [self peer]->RootProvider_GetFocus();
return [AvnAccessibilityElement acquire:focusedPeer];
}
- (id)accessibilityHitTest:(NSPoint)point
{
auto clientPoint = [[_owner window] convertPointFromScreen:point];
auto localPoint = [_owner translateLocalPoint:ToAvnPoint(clientPoint)];
auto hit = [self peer]->RootProvider_GetPeerFromPoint(localPoint);
return [AvnAccessibilityElement acquire:hit];
}
- (id)accessibilityParent
{
return _owner;
}
- (void)raiseFocusChanged
{
id focused = [self accessibilityFocusedUIElement];
NSAccessibilityPostNotification(focused, NSAccessibilityFocusedUIElementChangedNotification);
}
// Although this method is marked as deprecated we get runtime warnings if we don't handle it.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (void)accessibilityPerformAction:(NSAccessibilityActionName)action
{
[_owner accessibilityPerformAction:action];
}
#pragma clang diagnostic pop
@end

11
native/Avalonia.Native/src/OSX/common.h

@ -14,8 +14,8 @@ extern void PostDispatcherCallback(IAvnActionCallback* cb);
extern IAvnTopLevel* CreateAvnTopLevel(IAvnTopLevelEvents* events);
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events);
extern IAvnSystemDialogs* CreateSystemDialogs();
extern IAvnScreens* CreateScreens();
extern IAvnStorageProvider* CreateStorageProvider();
extern IAvnScreens* CreateScreens(IAvnScreenEvents* cb);
extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*);
extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
@ -89,6 +89,13 @@ public:
- (void) action;
@end
@implementation NSScreen (AvNSScreen)
- (CGDirectDisplayID)av_displayId
{
return [self.deviceDescription[@"NSScreenNumber"] unsignedIntValue];
}
@end
class AvnInsidePotentialDeadlock
{
public:

8
native/Avalonia.Native/src/OSX/main.mm

@ -276,24 +276,24 @@ public:
}
}
virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) override
virtual HRESULT CreateStorageProvider(IAvnStorageProvider** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateSystemDialogs();
*ppv = ::CreateStorageProvider();
return S_OK;
}
}
virtual HRESULT CreateScreens (IAvnScreens** ppv) override
virtual HRESULT CreateScreens (IAvnScreenEvents* cb, IAvnScreens** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateScreens ();
*ppv = ::CreateScreens (cb);
return S_OK;
}
}

1
native/Avalonia.Native/src/OSX/menu.mm

@ -1,4 +1,5 @@
#include "common.h"
#include "menu.h"
#include "KeyTransform.h"

10
nukebuild/Build.cs

@ -19,6 +19,7 @@ using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
using static Serilog.Log;
using MicroCom.CodeGenerator;
using NuGet.Configuration;
using Nuke.Common.IO;
/*
@ -369,6 +370,9 @@ partial class Build : NukeBuild
{
if (!Parameters.IsPackingToLocalCache)
throw new InvalidOperationException();
var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(
Settings.LoadDefaultSettings(RootDirectory));
foreach (var path in Parameters.NugetRoot.GlobFiles("*.nupkg"))
{
@ -379,11 +383,11 @@ partial class Build : NukeBuild
.Elements().First(x => x.Name.LocalName == "metadata")
.Elements().First(x => x.Name.LocalName == "id").Value;
var packagePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
".nuget",
"packages",
var packagePath = Path.Combine(
globalPackagesFolder,
packageId.ToLowerInvariant(),
BuildParameters.LocalBuildVersion);
if (Directory.Exists(packagePath))
Directory.Delete(packagePath, true);
Directory.CreateDirectory(packagePath);

12
nukebuild/BuildParameters.cs

@ -116,9 +116,10 @@ public partial class Build
IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
// VERSION
Version = b.ForceNugetVersion ?? GetVersion();
var (propsVersion, propsApiCompatVersion) = GetVersion();
Version = b.ForceNugetVersion ?? propsVersion;
ApiValidationBaseline = b.ApiValidationBaseline ?? new Version(new Version(Version.Split('-', StringSplitOptions.None).First()).Major, 0).ToString();
ApiValidationBaseline = b.ApiValidationBaseline ?? propsApiCompatVersion;
UpdateApiValidationSuppression = b.UpdateApiValidationSuppression ?? IsLocalBuild;
if (IsRunningOnAzure)
@ -153,10 +154,13 @@ public partial class Build
VersionOutputDir = b.VersionOutputDir;
}
string GetVersion()
(string Version, string ApiCompatVersion) GetVersion()
{
var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props");
return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
return (
xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value,
xdoc.Descendants().First(x => x.Name.LocalName == "ApiCompatVersion").Value
);
}
}

26
packages/Avalonia/AvaloniaBuildTasks.targets

@ -135,6 +135,14 @@
Outputs="@(CompileAvaloniaXamlOutputs)"
Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(DesignTimeBuild) != true AND $(EnableAvaloniaXamlCompilation) != false">
<!--
$(IntermediateOutputPath)/Avalonia/references is using from AvaloniaVS for retrieve library references.
-->
<WriteLinesToFile
File="$(IntermediateOutputPath)/Avalonia/references"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
<CompileAvaloniaXamlTask
AssemblyFile="@(IntermediateAssembly)"
References="@(ReferencePathWithRefAssemblies)"
@ -245,22 +253,4 @@
'$(SkipCopyBuildProduct)' != 'true'">
<Delete Files="$(TargetRefPath)" Condition="Exists('$(TargetRefPath)')" />
</Target>
<!--
$(IntermediateOutputPath)/Avalonia/references is using from AvaloniaVS for retrieve library references.
This target generate $(IntermediateOutputPath)/Avalonia/references for in xplat Template
(see: https://github.com/AvaloniaUI/avalonia-dotnet-templates/tree/e4a489ae828f005f625145c563785174403e267c/templates/csharp/xplat).
-->
<Target Name="GenerateIntellisenseReferences"
AfterTargets="AfterCompile"
Condition="('@(AvaloniaResource->Count())' == 0) and ('@(AvaloniaXaml->Count())' == 0)">
<PropertyGroup>
<AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>
</PropertyGroup>
<WriteLinesToFile
Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'"
File="$(AvaloniaXamlReferencesTemporaryFilePath)"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
</Target>
</Project>

21
samples/ControlCatalog.Android/MainActivity.cs

@ -1,5 +1,6 @@
using Android.App;
using Android.Content.PM;
using Android.OS;
using Avalonia;
using Avalonia.Android;
using static Android.Content.Intent;
@ -10,10 +11,9 @@ using static Android.Content.Intent;
namespace ControlCatalog.Android
{
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", MainLauncher = true, Exported = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
// CategoryBrowsable and DataScheme are required for Protocol activation.
[Activity(Name = "com.Avalonia.ControlCatalog.MainActivity", Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", MainLauncher = true, Exported = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
// CategoryLeanbackLauncher is required for Android TV.
[IntentFilter(new [] { ActionView }, Categories = new [] { CategoryDefault, CategoryBrowsable, CategoryLeanbackLauncher }, DataScheme = "avln" )]
[IntentFilter(new [] { ActionView }, Categories = new [] { CategoryDefault, CategoryLeanbackLauncher })]
public class MainActivity : AvaloniaMainActivity<App>
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
@ -25,4 +25,19 @@ namespace ControlCatalog.Android
});
}
}
/// <summary>
/// Special activity to handle OpenUri activation.
/// `AvaloniaActivity` internally will redirect parameters to the Avalonia Application.
/// </summary>
[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true, Theme = "@android:style/Theme.NoDisplay")]
[IntentFilter(new[] {ActionView}, Categories = new[] {CategoryDefault, CategoryBrowsable}, DataScheme = "avln")]
public class DataSchemeActivity : AvaloniaActivity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
Finish();
}
}
}

5
samples/ControlCatalog.Browser/wwwroot/Logo.svg

@ -1,5 +0,0 @@
<svg viewBox="0 0 35 35" xmlns="http://www.w3.org/2000/svg">
<path d="M30.466 34.928h.21a4.256 4.256 0 0 0 4.23-3.753l.03-14.18C34.686 7.567 26.965 0 17.476 0 7.832 0 .014 7.82.014 17.463c0 9.542 7.652 17.3 17.155 17.464h13.297z" fill="#fff"/>
<path d="M17.524 5.948c-5.497 0-10.094 3.853-11.238 9.006a2.603 2.603 0 0 1 0 5.01c1.144 5.154 5.74 9.007 11.238 9.007 2.001 0 3.883-.51 5.522-1.409v1.33h5.99V17.938c.005-.146 0-.33 0-.477 0-6.358-5.154-11.511-11.512-11.511zM12.01 17.459a5.514 5.514 0 1 1 11.028 0 5.514 5.514 0 0 1-11.028 0z" clip-rule="evenodd" fill="#8B44AC" fill-rule="evenodd"/>
<path d="M7.368 17.452a1.842 1.842 0 1 1-3.684 0 1.842 1.842 0 0 1 3.684 0z" fill="#8B44AC"/>
</svg>

Before

Width:  |  Height:  |  Size: 701 B

46
samples/ControlCatalog.Browser/wwwroot/app.css

@ -3,8 +3,8 @@
position: absolute;
height: 100%;
width: 100%;
background: #1b2a4e;
font-family: 'Nunito', sans-serif;
background: white;
font-family: 'Outfit', sans-serif;
justify-content: center;
align-items: center;
display: flex;
@ -12,23 +12,14 @@
}
.avalonia-splash h2 {
font-weight: 400;
font-size: 1.5rem;
color: #8b44ac;
}
.avalonia-splash a {
color: white;
text-decoration: none;
font-size: 2.5rem;
display: block;
}
.avalonia-splash img {
opacity: 0.05;
height: 35%;
position: absolute;
right: 3%;
bottom: 3%;
display: block;
}
.avalonia-splash.splash-close {
@ -36,3 +27,32 @@
display: none;
opacity: 0;
}
/* Light theme styles */
@media (prefers-color-scheme: light) {
.avalonia-splash {
background: white;
}
.avalonia-splash h2 {
color: #1b2a4e;
}
.avalonia-splash a {
color: #0D6EFD;
}
}
@media (prefers-color-scheme: dark) {
.avalonia-splash {
background: #1b2a4e;
}
.avalonia-splash h2 {
color: white;
}
.avalonia-splash a {
color: white;
}
}

16
samples/ControlCatalog.Browser/wwwroot/index.html

@ -15,9 +15,21 @@
<div class="avalonia-splash">
<h2>
Powered by
<a href="https://www.avaloniaui.net/" target="_blank">Avalonia UI</a>
<a href="https://www.avaloniaui.net/" target="_blank">
<svg width="266" height="52" viewBox="0 0 266 52" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M55.8592 47.3941C54.9035 47.3941 54.1184 47.1723 53.504 46.7285C52.9237 46.2848 52.5483 45.6875 52.3776 44.9365C52.2411 44.1856 52.3947 43.3493 52.8384 42.4277L65.9456 13.7045C66.4917 12.544 67.1403 11.7077 67.8912 11.1957C68.6421 10.6496 69.5125 10.3765 70.5024 10.3765C71.4923 10.3765 72.3627 10.6496 73.1136 11.1957C73.8645 11.7077 74.496 12.544 75.008 13.7045L88.2176 42.4277C88.6613 43.3493 88.8149 44.2027 88.6784 44.9877C88.576 45.7387 88.2347 46.336 87.6544 46.7797C87.0741 47.1893 86.3232 47.3941 85.4016 47.3941C84.2411 47.3941 83.3365 47.1211 82.688 46.5749C82.0736 46.0288 81.5275 45.1755 81.0496 44.0149L78.9279 39.0997H62.0415L59.9552 44.0149C59.4432 45.2096 58.8971 46.08 58.3168 46.6261C57.7707 47.1381 56.9515 47.3941 55.8592 47.3941ZM70.4 19.2853L64.6844 32.9045H76.2627L70.5024 19.2853H70.4Z" fill="currentColor"/>
<path d="M101.869 47.3941C100.879 47.3941 100.009 47.1381 99.258 46.6261C98.5071 46.08 97.9096 45.2779 97.4659 44.2197L89.7348 26.4021C89.3593 25.5147 89.2228 24.6955 89.3252 23.9445C89.4276 23.1595 89.786 22.5451 90.4004 22.1013C91.0489 21.6235 91.9364 21.3845 93.0628 21.3845C93.9844 21.3845 94.7353 21.6064 95.3156 22.0501C95.8959 22.4597 96.4079 23.2619 96.8516 24.4565L102.018 37.95L107.552 24.4053C108.03 23.2448 108.559 22.4597 109.14 22.0501C109.72 21.6064 110.522 21.3845 111.546 21.3845C112.433 21.3845 113.133 21.6235 113.645 22.1013C114.191 22.5451 114.516 23.1424 114.618 23.8933C114.755 24.6443 114.618 25.4635 114.208 26.3509L106.324 44.2197C105.88 45.312 105.283 46.1141 104.532 46.6261C103.815 47.1381 102.927 47.3941 101.869 47.3941Z" fill="currentColor"/>
<path d="M126.569 47.4965C124.726 47.4965 123.07 47.1381 121.602 46.4213C120.135 45.7045 118.991 44.7317 118.172 43.5029C117.353 42.2741 116.943 40.8917 116.943 39.3557C116.943 37.5125 117.421 36.0619 118.377 35.0037C119.333 33.9115 120.886 33.1435 123.036 32.6997C125.186 32.2219 128.037 31.9829 131.586 31.9829H133.43V35.9765H131.638C129.897 35.9765 128.48 36.0789 127.388 36.2837C126.33 36.4544 125.562 36.7616 125.084 37.2053C124.64 37.6491 124.418 38.2635 124.418 39.0485C124.418 40.0043 124.743 40.7893 125.391 41.4037C126.074 42.0181 127.047 42.3253 128.31 42.3253C129.299 42.3253 130.17 42.1035 130.921 41.6597C131.706 41.1819 132.32 40.5504 132.764 39.7653C133.208 38.9461 133.43 38.0245 133.43 37.0005V31.1125C133.43 29.6107 133.088 28.5525 132.406 27.9381C131.723 27.2896 130.562 26.9653 128.924 26.9653C128.002 26.9653 126.995 27.0848 125.903 27.3237C124.845 27.5285 123.667 27.8869 122.37 28.3989C121.619 28.7403 120.954 28.8256 120.374 28.6549C119.793 28.4501 119.35 28.1088 119.042 27.6309C118.735 27.1189 118.582 26.5728 118.582 25.9925C118.582 25.3781 118.752 24.7979 119.094 24.2517C119.435 23.6715 119.998 23.2448 120.783 22.9717C122.387 22.3232 123.889 21.8795 125.289 21.6405C126.722 21.4016 128.037 21.2821 129.231 21.2821C131.859 21.2821 134.01 21.6747 135.682 22.4597C137.389 23.2107 138.669 24.3883 139.522 25.9925C140.376 27.5627 140.802 29.5936 140.802 32.0853V43.4517C140.802 44.7147 140.495 45.6875 139.881 46.3701C139.266 47.0528 138.379 47.3941 137.218 47.3941C136.058 47.3941 135.153 47.0528 134.505 46.3701C133.89 45.6875 133.583 44.7147 133.583 43.4517L133.594 43.15C133.594 43.15 133.293 44.032 132.61 44.8853C131.962 45.7045 131.126 46.3531 130.102 46.8309C129.078 47.2747 127.9 47.4965 126.569 47.4965Z" fill="currentColor"/>
<path d="M155.632 47.4965C152.594 47.4965 150.324 46.6603 148.822 44.9877C147.321 43.2811 146.57 40.7552 146.57 37.4101V14.3189C146.57 13.0219 146.894 12.0491 147.542 11.4005C148.225 10.7179 149.198 10.3765 150.461 10.3765C151.69 10.3765 152.628 10.7179 153.277 11.4005C153.959 12.0491 154.301 13.0219 154.301 14.3189V37.1029C154.301 38.5024 154.591 39.5435 155.171 40.2261C155.786 40.8747 156.588 41.1989 157.578 41.1989C157.851 41.1989 158.107 41.1819 158.346 41.1477C158.585 41.1136 158.841 41.0965 159.114 41.0965C159.66 41.0283 160.035 41.1989 160.24 41.6085C160.479 41.984 160.598 42.752 160.598 43.9125C160.598 44.9365 160.394 45.7216 159.984 46.2677C159.574 46.7797 158.943 47.1211 158.09 47.2917C157.748 47.3259 157.356 47.36 156.912 47.3941C156.468 47.4624 156.042 47.4965 155.632 47.4965Z" fill="currentColor"/>
<path d="M175.453 47.4965C172.756 47.4965 170.401 46.9675 168.387 45.9093C166.407 44.8512 164.871 43.3323 163.779 41.3525C162.687 39.3728 162.141 37.0347 162.141 34.3381C162.141 32.3243 162.448 30.5152 163.062 28.9109C163.677 27.3067 164.564 25.9413 165.725 24.8149C166.919 23.6544 168.336 22.784 169.974 22.2037C171.613 21.5893 173.439 21.2821 175.453 21.2821C178.149 21.2821 180.487 21.8112 182.467 22.8693C184.481 23.9275 186.034 25.4293 187.126 27.3749C188.253 29.3205 188.816 31.6416 188.816 34.3381C188.816 36.3861 188.492 38.2123 187.843 39.8165C187.229 41.4208 186.341 42.8032 185.181 43.9637C184.02 45.1243 182.604 46.0117 180.931 46.6261C179.293 47.2064 177.467 47.4965 175.453 47.4965ZM175.453 41.7109C176.579 41.7109 177.552 41.4379 178.371 40.8917C179.19 40.3456 179.839 39.5435 180.317 38.4853C180.795 37.3931 181.034 36.0107 181.034 34.3381C181.034 31.8464 180.522 30.0203 179.498 28.8597C178.474 27.6651 177.125 27.0677 175.453 27.0677C174.361 27.0677 173.388 27.3237 172.534 27.8357C171.715 28.3477 171.067 29.1499 170.589 30.2421C170.145 31.3003 169.923 32.6656 169.923 34.3381C169.923 36.8299 170.435 38.6901 171.459 39.9189C172.483 41.1136 173.814 41.7109 175.453 41.7109Z" fill="currentColor"/>
<path d="M197.411 47.3941C196.148 47.3941 195.175 47.0528 194.492 46.3701C193.844 45.6875 193.52 44.7147 193.52 43.4517V25.2757C193.52 24.0128 193.844 23.0571 194.492 22.4085C195.175 21.7259 196.114 21.3845 197.308 21.3845C198.537 21.3845 199.476 21.7259 200.124 22.4085C200.773 23.0571 201.112 24.1871 201.112 25.45C201.141 25.3955 202.48 23.552 204.016 22.6645C205.586 21.7429 207.361 21.2821 209.34 21.2821C211.354 21.2821 213.01 21.6747 214.307 22.4597C215.604 23.2107 216.577 24.3712 217.225 25.9413C217.874 27.4773 218.198 29.44 218.198 31.8293V43.4517C218.198 44.7147 217.857 45.6875 217.174 46.3701C216.525 47.0528 215.57 47.3941 214.307 47.3941C213.078 47.3941 212.122 47.0528 211.44 46.3701C210.791 45.6875 210.467 44.7147 210.467 43.4517V32.1877C210.467 30.4469 210.143 29.2011 209.494 28.4501C208.88 27.6651 207.924 27.2725 206.627 27.2725C204.988 27.2725 203.674 27.7845 202.684 28.8085C201.729 29.8325 201.251 31.1979 201.251 32.9045V43.4517C201.251 46.08 199.971 47.3941 197.411 47.3941Z" fill="currentColor"/>
<path d="M227.861 47.3429C226.598 47.3429 225.625 46.9845 224.942 46.2677C224.294 45.5168 223.97 44.4757 223.97 43.1445V25.6341C223.97 24.2688 224.294 23.2277 224.942 22.5109C225.625 21.76 226.598 21.3845 227.861 21.3845C229.09 21.3845 230.028 21.76 230.677 22.5109C231.359 23.2277 231.701 24.2688 231.701 25.6341V43.1445C231.701 44.4757 231.377 45.5168 230.728 46.2677C230.079 46.9845 229.124 47.3429 227.861 47.3429ZM227.861 17.1861C226.427 17.1861 225.318 16.8619 224.533 16.2133C223.782 15.5307 223.406 14.5749 223.406 13.3461C223.406 12.0832 223.782 11.1275 224.533 10.4789C225.318 9.79629 226.427 9.45496 227.861 9.45496C229.294 9.45496 230.387 9.79629 231.138 10.4789C231.889 11.1275 232.264 12.0832 232.264 13.3461C232.264 14.5749 231.889 15.5307 231.138 16.2133C230.387 16.8619 229.294 17.1861 227.861 17.1861Z" fill="currentColor"/>
<path d="M246.169 47.4965C244.326 47.4965 242.67 47.1381 241.202 46.4213C239.735 45.7045 238.591 44.7317 237.772 43.5029C236.953 42.2741 236.543 40.8917 236.543 39.3557C236.543 37.5125 237.021 36.0619 237.977 35.0037C238.933 33.9115 240.486 33.1435 242.636 32.6997C244.786 32.2219 247.637 31.9829 251.186 31.9829H253.03V35.9765H251.238C249.497 35.9765 248.08 36.0789 246.988 36.2837C245.93 36.4544 245.162 36.7616 244.684 37.2053C244.24 37.6491 244.018 38.2635 244.018 39.0485C244.018 40.0043 244.343 40.7893 244.991 41.4037C245.674 42.0181 246.647 42.3253 247.91 42.3253C248.899 42.3253 249.77 42.1035 250.521 41.6597C251.306 41.1819 251.92 40.5504 252.364 39.7653C252.808 38.9461 253.03 38.0245 253.03 37.0005V31.1125C253.03 29.6107 252.688 28.5525 252.006 27.9381C251.323 27.2896 250.162 26.9653 248.524 26.9653C247.602 26.9653 246.595 27.0848 245.503 27.3237C244.445 27.5285 243.267 27.8869 241.97 28.3989C241.219 28.7403 240.554 28.8256 239.974 28.6549C239.393 28.4501 238.95 28.1088 238.642 27.6309C238.335 27.1189 238.182 26.5728 238.182 25.9925C238.182 25.3781 238.352 24.7979 238.694 24.2517C239.035 23.6715 239.598 23.2448 240.383 22.9717C241.987 22.3232 243.489 21.8795 244.889 21.6405C246.322 21.4016 247.637 21.2821 248.831 21.2821C251.459 21.2821 253.61 21.6747 255.282 22.4597C256.989 23.2107 258.269 24.3883 259.122 25.9925C259.976 27.5627 260.402 29.5936 260.402 32.0853V43.4517C260.402 44.7147 260.095 45.6875 259.481 46.3701C258.866 47.0528 257.979 47.3941 256.818 47.3941C255.658 47.3941 254.753 47.0528 254.105 46.3701C253.49 45.6875 253.183 44.7147 253.183 43.4517V43.1789C253.183 43.3144 252.893 44.032 252.21 44.8853C251.562 45.7045 250.726 46.3531 249.702 46.8309C248.678 47.2747 247.5 47.4965 246.169 47.4965Z" fill="currentColor"/>
<path d="M22.3444 20.9916C18.7895 20.9916 15.9077 24.0073 15.9077 27.7274C15.9077 31.4475 18.7895 34.4632 22.3444 34.4632C25.8993 34.4632 28.7811 31.4475 28.7811 27.7274C28.7811 24.0073 25.8993 20.9916 22.3444 20.9916Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M37.6937 49.0667H21.9271C10.8346 48.8653 1.90173 39.3893 1.90173 27.7333C1.90173 15.9513 11.0289 6.40002 22.2878 6.40002C33.3638 6.40002 42.3768 15.6435 42.6667 27.161L42.6314 44.4824C42.338 47.0679 40.2434 49.0667 37.6937 49.0667ZM9.22617 24.667C10.5612 18.3725 15.9275 13.6656 22.3444 13.6656C29.7657 13.6656 35.7818 19.9613 35.7818 27.7274C35.7818 27.7857 35.7825 27.8488 35.7831 27.9136C35.7846 28.0483 35.7861 28.1901 35.7818 28.3103V41.6939H28.7907V40.0685C26.877 41.1655 24.6803 41.7892 22.3444 41.7892C15.9275 41.7892 10.5612 37.0823 9.22617 30.7878C10.5043 30.4129 11.4416 29.1847 11.4416 27.7274C11.4416 26.2701 10.5043 25.0419 9.22617 24.667ZM8.33937 29.9683C9.52696 29.9683 10.4897 28.9609 10.4897 27.7181C10.4897 26.4753 9.52696 25.4678 8.33937 25.4678C7.15178 25.4678 6.18904 26.4753 6.18904 27.7181C6.18904 28.9609 7.15178 29.9683 8.33937 29.9683Z" fill="currentColor"/>
</svg>
</a>
</h2>
<img src="Logo.svg" alt="Avalonia Logo" />
</div>
</div>
<!--<div id="common-root" style="display: grid; grid-template-columns: 50% 50%; position: absolute; width:100%; height: 100%">-->

8
samples/ControlCatalog.Browser/wwwroot/main.js

@ -1,15 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { dotnet } from './_framework/dotnet.js'
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
const dotnetRuntime = await dotnet
.withDiagnosticTracing(false)
.withApplicationArgumentsFromQuery()
.create();
const config = dotnetRuntime.getConfig();
await dotnetRuntime.runMain(config.mainAssemblyName, [globalThis.location.href]);
await dotnet.run();

3
samples/ControlCatalog/MainView.xaml

@ -196,6 +196,9 @@
<TabItem Header="HeaderedContentControl">
<pages:HeaderedContentPage />
</TabItem>
<TabItem Header="Screens">
<pages:ScreenPage />
</TabItem>
<FlyoutBase.AttachedFlyout>
<Flyout>
<StackPanel Width="152" Spacing="8">

10
samples/ControlCatalog/MainView.xaml.cs

@ -25,16 +25,6 @@ namespace ControlCatalog
var sideBar = this.Get<TabControl>("Sidebar");
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
{
var tabItems = (sideBar.Items as IList);
tabItems?.Add(new TabItem()
{
Header = "Screens",
Content = new ScreenPage()
});
}
var themes = this.Get<ComboBox>("Themes");
themes.SelectedItem = App.CurrentTheme;
themes.SelectionChanged += (sender, e) =>

74
samples/ControlCatalog/Pages/DateTimePickerPage.xaml

@ -77,6 +77,23 @@
</Panel>
</StackPanel>
<TextBlock FontSize="18">A TimePicker with seconds enabled.</TextBlock>
<StackPanel Orientation="Vertical">
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
<TimePicker UseSeconds="True" />
</Border>
<Panel Background="{DynamicResource CatalogBaseLowColor}">
<TextBlock Padding="15">
<TextBlock.Text>
<x:String>
&lt;TimePicker UseSeconds="True" /&gt;
</x:String>
</TextBlock.Text>
</TextBlock>
</Panel>
</StackPanel>
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
<TimePicker>
@ -85,8 +102,8 @@
</DataValidationErrors.Error>
</TimePicker>
</Border>
<TextBlock FontSize="18">A TimePicker with minute increments specified.</TextBlock>
<TextBlock FontSize="18">A TimePicker with minute increment specified.</TextBlock>
<StackPanel Orientation="Vertical">
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
@ -96,7 +113,24 @@
<TextBlock Padding="15">
<TextBlock.Text>
<x:String>
&lt;TimePicker MinuteIncrement="15" /&gt;
&lt;TimePicker MinuteIncrement="15" SecondIncrement="30" /&gt;
</x:String>
</TextBlock.Text>
</TextBlock>
</Panel>
</StackPanel>
<TextBlock FontSize="18">A TimePicker with seconds enabled and minute &amp; second increments specified.</TextBlock>
<StackPanel Orientation="Vertical">
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
<TimePicker UseSeconds="True" MinuteIncrement="15" SecondIncrement="30" />
</Border>
<Panel Background="{DynamicResource CatalogBaseLowColor}">
<TextBlock Padding="15">
<TextBlock.Text>
<x:String>
&lt;TimePicker UseSeconds="True" MinuteIncrement="15" SecondIncrement="30" /&gt;
</x:String>
</TextBlock.Text>
</TextBlock>
@ -137,6 +171,40 @@
</Panel>
</StackPanel>
<TextBlock FontSize="18">A TimePicker using a 12-hour clock and seconds.</TextBlock>
<StackPanel Orientation="Vertical">
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
<TimePicker ClockIdentifier="12HourClock" UseSeconds="True" />
</Border>
<Panel Background="{DynamicResource CatalogBaseLowColor}">
<TextBlock Padding="15">
<TextBlock.Text>
<x:String>
&lt;TimePicker ClockIdentifier="12HourClock" UseSeconds="True" /&gt;
</x:String>
</TextBlock.Text>
</TextBlock>
</Panel>
</StackPanel>
<TextBlock FontSize="18">A TimePicker using a 24-hour clock and seconds.</TextBlock>
<StackPanel Orientation="Vertical">
<Border BorderBrush="{DynamicResource CatalogBaseLowColor}"
BorderThickness="1" Padding="15">
<TimePicker ClockIdentifier="24HourClock" UseSeconds="True" />
</Border>
<Panel Background="{DynamicResource CatalogBaseLowColor}">
<TextBlock Padding="15">
<TextBlock.Text>
<x:String>
&lt;TimePicker ClockIdentifier="24HourClock" UseSeconds="True" /&gt;
</x:String>
</TextBlock.Text>
</TextBlock>
</Panel>
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

2
samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs

@ -15,7 +15,7 @@ namespace ControlCatalog.Pages
"Order of month, day, and year is dynamically set based on user date settings";
this.Get<TextBlock>("TimePickerDesc").Text = "Use a TimePicker to let users set a time in your app, for example " +
"to set a reminder. The TimePicker displays three controls for hour, minute, and AM / PM(if necessary).These controls " +
"to set a reminder. The TimePicker displays four controls for hour, minute, seconds(optional), and AM / PM(if necessary).These controls " +
"are easy to use with touch or mouse, and they can be styled and configured in several different ways. " +
"12 - hour or 24 - hour clock and visibility of AM / PM is dynamically set based on user time settings, or can be overridden.";

50
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -254,17 +254,24 @@ namespace ControlCatalog.Pages
if (file is not null)
{
// Sync disposal of StreamWriter is not supported on WASM
try
{
// Sync disposal of StreamWriter is not supported on WASM
#if NET6_0_OR_GREATER
await using var stream = await file.OpenWriteAsync();
await using var writer = new System.IO.StreamWriter(stream);
await using var stream = await file.OpenWriteAsync();
await using var writer = new System.IO.StreamWriter(stream);
#else
using var stream = await file.OpenWriteAsync();
using var writer = new System.IO.StreamWriter(stream);
using var stream = await file.OpenWriteAsync();
using var writer = new System.IO.StreamWriter(stream);
#endif
await writer.WriteLineAsync(openedFileContent.Text);
await writer.WriteLineAsync(openedFileContent.Text);
SetFolder(await file.GetParentAsync());
SetFolder(await file.GetParentAsync());
}
catch (Exception ex)
{
openedFileContent.Text = ex.ToString();
}
}
await SetPickerResult(file is null ? null : new[] { file });
@ -280,8 +287,6 @@ namespace ControlCatalog.Pages
});
await SetPickerResult(folders);
SetFolder(folders.FirstOrDefault());
};
this.Get<Button>("OpenFileFromBookmark").Click += async delegate
{
@ -298,7 +303,6 @@ namespace ControlCatalog.Pages
: null;
await SetPickerResult(folder is null ? null : new[] { folder });
SetFolder(folder);
};
this.Get<Button>("LaunchUri").Click += async delegate
@ -360,16 +364,30 @@ namespace ControlCatalog.Pages
Content:
";
resultText += await ReadTextFromFile(file, 500);
try
{
resultText += await ReadTextFromFile(file, 500);
}
catch (Exception ex)
{
resultText += ex.ToString();
}
}
openedFileContent.Text = resultText;
var parent = await item.GetParentAsync();
SetFolder(parent);
if (parent is not null)
if (item is IStorageFolder storageFolder)
{
mappedResults.Add(FullPathOrName(parent));
SetFolder(storageFolder);
}
else
{
var parent = await item.GetParentAsync();
SetFolder(parent);
if (parent is not null)
{
mappedResults.Add(FullPathOrName(parent));
}
}
foreach (var selectedItem in items)
@ -391,7 +409,7 @@ namespace ControlCatalog.Pages
}
}
public static async Task<string> ReadTextFromFile(IStorageFile file, int length)
internal static async Task<string> ReadTextFromFile(IStorageFile file, int length)
{
#if NET6_0_OR_GREATER
await using var stream = await file.OpenReadAsync();

78
samples/ControlCatalog/Pages/ScreenPage.cs

@ -20,33 +20,62 @@ namespace ControlCatalog.Pages
private IPen _activePen = new Pen(Brushes.Black);
private IPen _defaultPen = new Pen(Brushes.DarkGray);
public ScreenPage()
{
var button = new Button();
button.Content = "Request ScreenDetails";
button.VerticalAlignment = Avalonia.Layout.VerticalAlignment.Top;
button.Click += async (sender, args) =>
{
var success = TopLevel.GetTopLevel(this)!.Screens is { } screens ?
await screens.RequestScreenDetails() :
false;
button.Content = "Request ScreenDetails: " + (success ? "Granted" : "Denied");
};
Content = button;
}
protected override bool BypassFlowDirectionPolicies => true;
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
if(VisualRoot is Window w)
var topLevel = TopLevel.GetTopLevel(this);
if (topLevel is Window w)
{
w.PositionChanged += (_, _) => InvalidateVisual();
}
if (topLevel?.Screens is { } screens)
{
screens.Changed += (_, _) =>
{
Console.WriteLine("Screens Changed");
InvalidateVisual();
};
}
}
public override void Render(DrawingContext context)
{
base.Render(context);
if (!(VisualRoot is Window w))
double beginOffset = (Content as Visual)?.Bounds.Height + 10 ?? 0;
var topLevel = TopLevel.GetTopLevel(this)!;
if (topLevel.Screens is not { } screens)
{
var formattedText = CreateFormattedText("Current platform doesn't support Screens API.");
context.DrawText(formattedText, new Point(15, 15 + beginOffset));
return;
}
var screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;
var activeScreen = w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling)));
var activeScreen = screens.ScreenFromTopLevel(topLevel);
double maxBottom = 0;
for (int i = 0; i<screens.Count; i++ )
for (int i = 0; i<screens.ScreenCount; i++ )
{
var screen = screens[i];
var screen = screens.All[i];
if (screen.Bounds.X / 10f < _leftMost)
{
@ -63,16 +92,16 @@ namespace ControlCatalog.Pages
bool primary = screen.IsPrimary;
bool active = screen.Equals(activeScreen);
Rect boundsRect = new Rect(screen.Bounds.X / 10f + Math.Abs(_leftMost), screen.Bounds.Y / 10f+Math.Abs(_topMost), screen.Bounds.Width / 10f,
Rect boundsRect = new Rect(screen.Bounds.X / 10f + Math.Abs(_leftMost), screen.Bounds.Y / 10f+Math.Abs(_topMost) + beginOffset, screen.Bounds.Width / 10f,
screen.Bounds.Height / 10f);
Rect workingAreaRect = new Rect(screen.WorkingArea.X / 10f + Math.Abs(_leftMost), screen.WorkingArea.Y / 10f+Math.Abs(_topMost), screen.WorkingArea.Width / 10f,
Rect workingAreaRect = new Rect(screen.WorkingArea.X / 10f + Math.Abs(_leftMost), screen.WorkingArea.Y / 10f+Math.Abs(_topMost) + beginOffset, screen.WorkingArea.Width / 10f,
screen.WorkingArea.Height / 10f);
context.DrawRectangle(primary ? _primaryBrush : _defaultBrush, active ? _activePen : _defaultPen, boundsRect);
context.DrawRectangle(primary ? _primaryBrush : _defaultBrush, active ? _activePen : _defaultPen, workingAreaRect);
var identifier = CreateScreenIdentifier((i+1).ToString(), primary);
var center = boundsRect.Center - new Point(identifier.Width / 2.0f, identifier.Height / 2.0f);
var center = boundsRect.Center - new Point(identifier.Width / 2.0f, identifier.Height / 2.0f + beginOffset);
context.DrawText(identifier, center);
maxBottom = Math.Max(maxBottom, boundsRect.Bottom);
@ -80,14 +109,22 @@ namespace ControlCatalog.Pages
double currentHeight = maxBottom;
for(int i = 0; i< screens.Count; i++)
for(int i = 0; i< screens.ScreenCount; i++)
{
var screen = screens[i];
var screen = screens.All[i];
var formattedText = CreateFormattedText($"Screen {i+1}", 18);
context.DrawText(formattedText, new Point(0, currentHeight));
currentHeight += 25;
formattedText = CreateFormattedText($"DisplayName: {screen.DisplayName}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 20;
formattedText = CreateFormattedText($"Handle: {screen.TryGetPlatformHandle()}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 20;
formattedText = CreateFormattedText($"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 20;
@ -101,17 +138,26 @@ namespace ControlCatalog.Pages
currentHeight += 20;
formattedText = CreateFormattedText($"IsPrimary: {screen.IsPrimary}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 20;
formattedText = CreateFormattedText($"CurrentOrientation: {screen.CurrentOrientation}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 20;
formattedText = CreateFormattedText( $"Current: {screen.Equals(activeScreen)}");
context.DrawText(formattedText, new Point(15, currentHeight));
currentHeight += 30;
}
context.DrawRectangle(_activePen, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10f+Math.Abs(_topMost), w.Bounds.Width / 10, w.Bounds.Height / 10));
if (topLevel is Window w)
{
var wPos = w.Position;
var wSize = PixelSize.FromSize(w.FrameSize ?? w.ClientSize, w.DesktopScaling);
context.DrawRectangle(_activePen,
new Rect(wPos.X / 10f + Math.Abs(_leftMost), wPos.Y / 10f + Math.Abs(_topMost) + beginOffset,
wSize.Width / 10d, wSize.Height / 10d));
}
}
private static FormattedText CreateFormattedText(string textToFormat, double size = 12)

11
samples/ControlCatalog/Pages/ToolTipPage.xaml

@ -77,12 +77,23 @@
</Button>
<Border Grid.Row="3"
Grid.Column="0"
Background="{DynamicResource SystemAccentColor}"
Margin="5"
Padding="50"
ToolTip.Tip="Outer tooltip">
<TextBlock Background="{StaticResource SystemAccentColorDark1}" Padding="10" ToolTip.Tip="Inner tooltip" VerticalAlignment="Center">Nested ToolTips</TextBlock>
</Border>
<Border Grid.Row="3"
Grid.Column="1"
Background="{DynamicResource SystemAccentColor}"
Margin="5"
Padding="50"
ToolTip.ToolTipOpening="ToolTipOpening"
ToolTip.Tip="Should never be visible">
<TextBlock VerticalAlignment="Center">ToolTip replaced on the fly</TextBlock>
</Border>
</Grid>
</StackPanel>
</UserControl>

6
samples/ControlCatalog/Pages/ToolTipPage.xaml.cs

@ -1,4 +1,5 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace ControlCatalog.Pages
@ -14,5 +15,10 @@ namespace ControlCatalog.Pages
{
AvaloniaXamlLoader.Load(this);
}
private void ToolTipOpening(object? sender, CancelRoutedEventArgs args)
{
((Control)args.Source!).SetValue(ToolTip.TipProperty, "New tip set from ToolTipOpening.");
}
}
}

3
samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs

@ -49,9 +49,8 @@ namespace ControlCatalog.ViewModels
{
while (SelectedItems.Count > 0)
{
Node lastItem = (Node)SelectedItems[0];
var lastItem = SelectedItems[0];
RecursiveRemove(Items, lastItem);
SelectedItems.RemoveAt(0);
}
bool RecursiveRemove(ObservableCollection<Node> items, Node selectedItem)

27
samples/IntegrationTestApp/App.axaml

@ -1,13 +1,26 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="IntegrationTestApp.App">
xmlns:self="using:IntegrationTestApp"
x:Class="IntegrationTestApp.App"
x:DataType="self:App"
RequestedThemeVariant="Default">
<Application.Styles>
<FluentTheme />
</Application.Styles>
<TrayIcon.Icons>
<TrayIcons>
<TrayIcon Icon="/Assets/icon.ico">
</TrayIcon>
</TrayIcons>
</TrayIcon.Icons>
<TrayIcon.Icons>
<TrayIcons>
<TrayIcon Icon="/Assets/icon.ico"
ToolTipText="IntegrationTestApp TrayIcon"
Command="{Binding TrayIconCommand}"
CommandParameter="TrayIconClicked">
<TrayIcon.Menu>
<NativeMenu>
<NativeMenuItem Header="Raise Menu Clicked"
Command="{Binding TrayIconCommand}"
CommandParameter="TrayIconMenuClicked" />
</NativeMenu>
</TrayIcon.Menu>
</TrayIcon>
</TrayIcons>
</TrayIcon.Icons>
</Application>

20
samples/IntegrationTestApp/App.axaml.cs

@ -1,11 +1,27 @@
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using MiniMvvm;
namespace IntegrationTestApp
{
public class App : Application
{
private MainWindow? _mainWindow;
public App()
{
TrayIconCommand = MiniCommand.Create<string>(name =>
{
_mainWindow!.Get<CheckBox>(name).IsChecked = true;
});
DataContext = this;
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@ -15,10 +31,12 @@ namespace IntegrationTestApp
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
desktop.MainWindow = _mainWindow = new MainWindow();
}
base.OnFrameworkInitializationCompleted();
}
public ICommand TrayIconCommand { get; }
}
}

19
samples/IntegrationTestApp/DelegateCommand.cs

@ -0,0 +1,19 @@
using System;
using System.Windows.Input;
namespace IntegrationTestApp;
internal class DelegateCommand : ICommand
{
private readonly Action _action;
private readonly Func<object?, bool> _canExecute;
public DelegateCommand(Action action, Func<object?, bool>? canExecute = default)
{
_action = action;
_canExecute = canExecute ?? new(_ => true);
}
public event EventHandler? CanExecuteChanged { add { } remove { } }
public bool CanExecute(object? parameter) => _canExecute(parameter);
public void Execute(object? parameter) => _action();
}

9
samples/IntegrationTestApp/IntegrationTestApp.csproj

@ -4,6 +4,7 @@
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework>
<Nullable>enable</Nullable>
<NoWarn>$(NoWarn);AVP1012</NoWarn>
<IncludeAvaloniaGenerators>true</IncludeAvaloniaGenerators>
</PropertyGroup>
<PropertyGroup>
@ -25,10 +26,18 @@
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="TopmostWindowTest.axaml.cs">
<DependentUpon>TopmostWindowTest.axaml</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\SampleApp.props" />
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\SourceGenerators.props" />
</Project>

68
samples/IntegrationTestApp/MainWindow.axaml

@ -5,7 +5,6 @@
xmlns:integrationTestApp="using:IntegrationTestApp"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="IntegrationTestApp.MainWindow"
Name="MainWindow"
Icon="/Assets/icon.ico"
Title="IntegrationTestApp"
x:DataType="integrationTestApp:MainWindow">
@ -24,7 +23,7 @@
</NativeMenuItem>
</NativeMenu>
</NativeMenu.Menu>
<DockPanel>
<DockPanel Background="{DynamicResource SystemRegionBrush}">
<NativeMenuBar DockPanel.Dock="Top"/>
<StackPanel DockPanel.Dock="Bottom" Margin="4" Orientation="Horizontal">
<TextBlock Margin="0,0,4,0">WindowState:</TextBlock>
@ -94,6 +93,27 @@
</StackPanel>
</TabItem>
<TabItem Header="ContextMenu">
<StackPanel>
<Button Name="ShowContextMenu" Content="Right-click to show context menu.">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Name="ContextMenuItem1" Header="Item 1"/>
<MenuItem Name="ContextMenuItem2" Header="Item 2"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
</StackPanel>
</TabItem>
<TabItem Header="Desktop">
<StackPanel>
<CheckBox x:FieldModifier="public" Name="TrayIconClicked">Tray Icon Clicked</CheckBox>
<CheckBox x:FieldModifier="public" Name="TrayIconMenuClicked">Tray Icon Menu Clicked</CheckBox>
<Button Name="ToggleTrayIconVisible" Content="Toggle TrayIcon Visible" />
</StackPanel>
</TabItem>
<TabItem Header="Gestures">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
@ -137,6 +157,21 @@
</StackPanel>
</DockPanel>
</TabItem>
<TabItem Header="Pointer">
<StackPanel>
<!-- Trigger with PointerPressed rather using a Button so we have access to the pointer. -->
<Border Name="PointerPageShowDialog"
Background="{DynamicResource ButtonBackground}"
HorizontalAlignment="Left"
Padding="{DynamicResource ButtonPadding}"
AutomationProperties.AccessibilityView="Control"
PointerPressed="PointerPageShowDialogPressed">
<TextBlock>Show Dialog</TextBlock>
</Border>
<TextBlock Name="PointerCaptureStatus"/>
</StackPanel>
</TabItem>
<TabItem Header="Window">
<Grid ColumnDefinitions="*,8,*">
@ -170,6 +205,7 @@
<Button Name="EnterFullscreen">Enter Fullscreen</Button>
<Button Name="ExitFullscreen">Exit Fullscreen</Button>
<Button Name="RestoreAll">Restore All</Button>
<Button Name="ShowTopmostWindow">Show Topmost Window</Button>
</StackPanel>
<StackPanel Grid.Column="2">
<Button Name="ShowTransparentWindow">Transparent Window</Button>
@ -177,7 +213,20 @@
</StackPanel>
</Grid>
</TabItem>
<TabItem Header="Window Decorations">
<StackPanel Spacing="4">
<CheckBox Name="WindowExtendClientAreaToDecorationsHint" Content="Extend Client Area to Decorations" />
<CheckBox Name="WindowForceSystemChrome" Content="Force SystemChrome" />
<CheckBox Name="WindowPreferSystemChrome" Content="Prefer SystemChrome" />
<CheckBox Name="WindowMacThickSystemChrome" Content="Mac Thick SystemChrome" />
<TextBox Name="WindowTitleBarHeightHint" Text="-1" Watermark="In dips" />
<Button Name="ApplyWindowDecorations" Content="Apply decorations on this Window" />
<Button Name="ShowNewWindowDecorations" Content="Show new Window with decorations" />
<TextBox Name="WindowDecorationProperties" AcceptsReturn="True" />
</StackPanel>
</TabItem>
<TabItem Header="Slider">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
@ -194,6 +243,19 @@
<TabItem Header="ScrollBar">
<ScrollBar Name="MyScrollBar" Orientation="Horizontal" AllowAutoHide="False" Width="200" Height="30" Value="20"/>
</TabItem>
<TabItem Header="Screens">
<StackPanel Spacing="4">
<Button Name="ScreenRefresh" Content="Refresh" />
<TextBox Name="ScreenName" Watermark="DisplayName" UseFloatingWatermark="true" />
<TextBox Name="ScreenHandle" Watermark="Handle" UseFloatingWatermark="true" />
<TextBox Name="ScreenScaling" Watermark="Scaling" UseFloatingWatermark="true" />
<TextBox Name="ScreenBounds" Watermark="Bounds" UseFloatingWatermark="true" />
<TextBox Name="ScreenWorkArea" Watermark="WorkArea" UseFloatingWatermark="true" />
<TextBox Name="ScreenOrientation" Watermark="Orientation" UseFloatingWatermark="true" />
<TextBox Name="ScreenSameReference" Watermark="Is same reference" UseFloatingWatermark="true" />
</StackPanel>
</TabItem>
</TabControl>
</DockPanel>
</Window>

210
samples/IntegrationTestApp/MainWindow.axaml.cs

@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Avalonia;
using Avalonia.Automation;
@ -8,24 +10,25 @@ using Avalonia.Controls.Primitives;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.VisualTree;
using Microsoft.CodeAnalysis;
namespace IntegrationTestApp
{
public class MainWindow : Window
public partial class MainWindow : Window
{
public MainWindow()
{
// Set name in code behind, so source generator will ignore it.
Name = "MainWindow";
InitializeComponent();
InitializeViewMenu();
InitializeGesturesTab();
this.AttachDevTools();
var overlayPopups = this.Get<TextBlock>("AppOverlayPopups");
overlayPopups.Text = Program.OverlayPopups ? "Overlay Popups" : "Native Popups";
AppOverlayPopups.Text = Program.OverlayPopups ? "Overlay Popups" : "Native Popups";
AddHandler(Button.ClickEvent, OnButtonClick);
ListBoxItems = Enumerable.Range(0, 100).Select(x => "Item " + x).ToList();
@ -34,17 +37,11 @@ namespace IntegrationTestApp
public List<string> ListBoxItems { get; }
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void InitializeViewMenu()
{
var mainTabs = this.Get<TabControl>("MainTabs");
var viewMenu = (NativeMenuItem?)NativeMenu.GetMenu(this)?.Items[1];
foreach (var tabItem in mainTabs.Items.Cast<TabItem>())
foreach (var tabItem in MainTabs.Items.Cast<TabItem>())
{
var menuItem = new NativeMenuItem
{
@ -59,16 +56,16 @@ namespace IntegrationTestApp
}
}
private void ShowWindow()
private void OnShowWindow()
{
var sizeTextBox = this.GetControl<TextBox>("ShowWindowSize");
var modeComboBox = this.GetControl<ComboBox>("ShowWindowMode");
var locationComboBox = this.GetControl<ComboBox>("ShowWindowLocation");
var stateComboBox = this.GetControl<ComboBox>("ShowWindowState");
var sizeTextBox = ShowWindowSize;
var modeComboBox = ShowWindowMode;
var locationComboBox = ShowWindowLocation;
var stateComboBox = ShowWindowState;
var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
var systemDecorations = this.GetControl<ComboBox>("ShowWindowSystemDecorations");
var extendClientArea = this.GetControl<CheckBox>("ShowWindowExtendClientAreaToDecorationsHint");
var canResizeCheckBox = this.GetControl<CheckBox>("ShowWindowCanResize");
var systemDecorations = ShowWindowSystemDecorations;
var extendClientArea = ShowWindowExtendClientAreaToDecorationsHint;
var canResizeCheckBox = ShowWindowCanResize;
var owner = (Window)this.GetVisualRoot()!;
var window = new ShowWindowTest
@ -113,7 +110,7 @@ namespace IntegrationTestApp
}
}
private void ShowTransparentWindow()
private void OnShowTransparentWindow()
{
// Show a background window to make sure the color behind the transparent window is
// a known color (green).
@ -155,7 +152,7 @@ namespace IntegrationTestApp
window.Show(backgroundWindow);
}
private void ShowTransparentPopup()
private void OnShowTransparentPopup()
{
var popup = new Popup
{
@ -196,7 +193,7 @@ namespace IntegrationTestApp
popup.Open();
}
private void SendToBack()
private void OnSendToBack()
{
var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!;
@ -206,7 +203,7 @@ namespace IntegrationTestApp
}
}
private void RestoreAll()
private void OnRestoreAll()
{
var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!;
@ -217,13 +214,28 @@ namespace IntegrationTestApp
window.WindowState = WindowState.Normal;
}
}
private void OnShowTopmostWindow()
{
var mainWindow = new TopmostWindowTest("OwnerWindow") { Topmost = true, Title = "Owner Window"};
var ownedWindow = new TopmostWindowTest("OwnedWindow") { WindowStartupLocation = WindowStartupLocation.CenterOwner, Title = "Owned Window"};
mainWindow.Show();
ownedWindow.Show(mainWindow);
}
private void OnToggleTrayIconVisible()
{
var icon = TrayIcon.GetIcons(Application.Current!)!.FirstOrDefault()!;
icon.IsVisible = !icon.IsVisible;
}
private void InitializeGesturesTab()
{
var gestureBorder = this.GetControl<Border>("GestureBorder");
var gestureBorder2 = this.GetControl<Border>("GestureBorder2");
var lastGesture = this.GetControl<TextBlock>("LastGesture");
var resetGestures = this.GetControl<Button>("ResetGestures");
var gestureBorder = GestureBorder;
var gestureBorder2 = GestureBorder2;
var lastGesture = LastGesture;
var resetGestures = ResetGestures;
gestureBorder.Tapped += (_, _) => lastGesture.Text = "Tapped";
gestureBorder.DoubleTapped += (_, _) =>
@ -252,7 +264,7 @@ namespace IntegrationTestApp
private void MenuClicked(object? sender, RoutedEventArgs e)
{
var clickedMenuItemTextBlock = this.Get<TextBlock>("ClickedMenuItem");
var clickedMenuItemTextBlock = ClickedMenuItem;
clickedMenuItemTextBlock.Text = (sender as MenuItem)?.Header?.ToString();
}
@ -260,30 +272,126 @@ namespace IntegrationTestApp
{
var source = e.Source as Button;
if (source?.Name == "ComboBoxSelectionClear")
this.Get<ComboBox>("BasicComboBox").SelectedIndex = -1;
if (source?.Name == "ComboBoxSelectFirst")
this.Get<ComboBox>("BasicComboBox").SelectedIndex = 0;
if (source?.Name == "ListBoxSelectionClear")
this.Get<ListBox>("BasicListBox").SelectedIndex = -1;
if (source?.Name == "MenuClickedMenuItemReset")
this.Get<TextBlock>("ClickedMenuItem").Text = "None";
if (source?.Name == "ResetSliders")
this.Get<Slider>("HorizontalSlider").Value = 50;
if (source?.Name == "ShowTransparentWindow")
ShowTransparentWindow();
if (source?.Name == "ShowTransparentPopup")
ShowTransparentPopup();
if (source?.Name == "ShowWindow")
ShowWindow();
if (source?.Name == "SendToBack")
SendToBack();
if (source?.Name == "EnterFullscreen")
if (source?.Name == nameof(ComboBoxSelectionClear))
BasicComboBox.SelectedIndex = -1;
if (source?.Name == nameof(ComboBoxSelectFirst))
BasicComboBox.SelectedIndex = 0;
if (source?.Name == nameof(ListBoxSelectionClear))
BasicListBox.SelectedIndex = -1;
if (source?.Name == nameof(MenuClickedMenuItemReset))
ClickedMenuItem.Text = "None";
if (source?.Name == nameof(ResetSliders))
HorizontalSlider.Value = 50;
if (source?.Name == nameof(ShowTransparentWindow))
OnShowTransparentWindow();
if (source?.Name == nameof(ShowTransparentPopup))
OnShowTransparentPopup();
if (source?.Name == nameof(ShowWindow))
OnShowWindow();
if (source?.Name == nameof(SendToBack))
OnSendToBack();
if (source?.Name == nameof(EnterFullscreen))
WindowState = WindowState.FullScreen;
if (source?.Name == "ExitFullscreen")
if (source?.Name == nameof(ExitFullscreen))
WindowState = WindowState.Normal;
if (source?.Name == "RestoreAll")
RestoreAll();
if (source?.Name == nameof(ShowTopmostWindow))
OnShowTopmostWindow();
if (source?.Name == nameof(RestoreAll))
OnRestoreAll();
if (source?.Name == nameof(ApplyWindowDecorations))
OnApplyWindowDecorations(this);
if (source?.Name == nameof(ShowNewWindowDecorations))
OnShowNewWindowDecorations();
if (source?.Name == nameof(ToggleTrayIconVisible))
OnToggleTrayIconVisible();
if (source?.Name == nameof(ScreenRefresh))
OnScreenRefresh();
}
private void OnApplyWindowDecorations(Window window)
{
window.ExtendClientAreaToDecorationsHint = WindowExtendClientAreaToDecorationsHint.IsChecked!.Value;
window.ExtendClientAreaTitleBarHeightHint =
int.TryParse(WindowTitleBarHeightHint.Text, out var val) ? val / DesktopScaling : -1;
window.ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome
| (WindowForceSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.SystemChrome : 0)
| (WindowPreferSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.PreferSystemChrome : 0)
| (WindowMacThickSystemChrome.IsChecked == true ? ExtendClientAreaChromeHints.OSXThickTitleBar : 0);
AdjustOffsets(window);
window.Background = Brushes.Transparent;
window.PropertyChanged += WindowOnPropertyChanged;
void WindowOnPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
var window = (Window)sender!;
if (e.Property == OffScreenMarginProperty || e.Property == WindowDecorationMarginProperty)
{
AdjustOffsets(window);
}
}
void AdjustOffsets(Window window)
{
window.Padding = window.OffScreenMargin;
((Control)window.Content!).Margin = window.WindowDecorationMargin;
WindowDecorationProperties.Text =
$"{window.OffScreenMargin.Top * DesktopScaling} {window.WindowDecorationMargin.Top * DesktopScaling} {window.IsExtendedIntoWindowDecorations}";
}
}
private void OnShowNewWindowDecorations()
{
var window = new ShowWindowTest();
OnApplyWindowDecorations(window);
window.Show();
}
private void PointerPageShowDialogPressed(object? sender, PointerPressedEventArgs e)
{
void CaptureLost(object? sender, PointerCaptureLostEventArgs e)
{
PointerCaptureStatus.Text = "None";
((Control)sender!).PointerCaptureLost -= CaptureLost;
}
var captured = e.Pointer.Captured as Control;
if (captured is not null)
{
captured.PointerCaptureLost += CaptureLost;
}
PointerCaptureStatus.Text = captured?.ToString() ?? "None";
var dialog = new Window
{
Width = 200,
Height = 200,
};
dialog.Content = new Button
{
Content = "Close",
Command = new DelegateCommand(() => dialog.Close()),
};
dialog.ShowDialog(this);
}
private Screen? _lastScreen;
private void OnScreenRefresh()
{
var lastScreen = _lastScreen;
var screen = _lastScreen = Screens.ScreenFromWindow(this);
ScreenName.Text = screen?.DisplayName;
ScreenHandle.Text = screen?.TryGetPlatformHandle()?.ToString();
ScreenBounds.Text = screen?.Bounds.ToString();
ScreenWorkArea.Text = screen?.WorkingArea.ToString();
ScreenScaling.Text = screen?.Scaling.ToString(CultureInfo.InvariantCulture);
ScreenOrientation.Text = screen?.CurrentOrientation.ToString();
ScreenSameReference.Text = ReferenceEquals(lastScreen, screen).ToString();
}
}
}

2
samples/IntegrationTestApp/ShowWindowTest.axaml

@ -5,7 +5,7 @@
Name="SecondaryWindow"
x:DataType="Window"
Title="Show Window Test">
<integrationTestApp:MeasureBorder Name="MyBorder">
<integrationTestApp:MeasureBorder Name="MyBorder" Background="{DynamicResource SystemRegionBrush}">
<Grid ColumnDefinitions="Auto,Auto" RowDefinitions="Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto">
<Label Grid.Column="0" Grid.Row="1">Client Size</Label>
<TextBox Name="CurrentClientSize" Grid.Column="1" Grid.Row="1" IsReadOnly="True"

22
samples/IntegrationTestApp/ShowWindowTest.axaml.cs

@ -26,44 +26,38 @@ namespace IntegrationTestApp
}
}
public class ShowWindowTest : Window
public partial class ShowWindowTest : Window
{
private readonly DispatcherTimer? _timer;
private readonly TextBox? _orderTextBox;
public ShowWindowTest()
{
InitializeComponent();
DataContext = this;
PositionChanged += (s, e) => this.GetControl<TextBox>("CurrentPosition").Text = $"{Position}";
PositionChanged += (s, e) => CurrentPosition.Text = $"{Position}";
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
_orderTextBox = this.GetControl<TextBox>("CurrentOrder");
_orderTextBox = CurrentOrder;
_timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(250) };
_timer.Tick += TimerOnTick;
_timer.Start();
}
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
var scaling = PlatformImpl!.DesktopScaling;
this.GetControl<TextBox>("CurrentPosition").Text = $"{Position}";
this.GetControl<TextBox>("CurrentScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}";
this.GetControl<TextBox>("CurrentScaling").Text = $"{scaling}";
CurrentPosition.Text = $"{Position}";
CurrentScreenRect.Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}";
CurrentScaling.Text = $"{scaling}";
if (Owner is not null)
{
var ownerRect = this.GetControl<TextBox>("CurrentOwnerRect");
var owner = (Window)Owner;
ownerRect.Text = $"{owner.Position}, {PixelSize.FromSize(owner.FrameSize!.Value, scaling)}";
CurrentOwnerRect.Text = $"{owner.Position}, {PixelSize.FromSize(owner.FrameSize!.Value, scaling)}";
}
}

17
samples/IntegrationTestApp/TopmostWindowTest.axaml

@ -0,0 +1,17 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="IntegrationTestApp.TopmostWindowTest"
Title="TopmostWindowTest"
Width="640"
Height="480">
<Grid>
<TextBox Name="CurrentPosition"
Grid.Column="1"
Grid.Row="3"
IsReadOnly="True" />
<Button HorizontalAlignment="Center" Name="MoveButton" VerticalAlignment="Center" Click="Button_OnClick">Move</Button>
</Grid>
</Window>

21
samples/IntegrationTestApp/TopmostWindowTest.axaml.cs

@ -0,0 +1,21 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace IntegrationTestApp;
public partial class TopmostWindowTest : Window
{
public TopmostWindowTest(string name)
{
Name = name;
InitializeComponent();
PositionChanged += (s, e) => CurrentPosition.Text = $"{Position}";
}
private void Button_OnClick(object? sender, RoutedEventArgs e)
{
Position += new PixelPoint(100, 100);
}
}

32
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -8,6 +8,8 @@ using Android.OS;
using Android.Runtime;
using Android.Views;
using AndroidX.AppCompat.App;
using Avalonia.Platform;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Storage;
using Avalonia.Controls.ApplicationLifetimes;
@ -22,6 +24,7 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
private EventHandler<ActivatedEventArgs>? _onActivated, _onDeactivated;
private GlobalLayoutListener? _listener;
private object? _content;
private bool _contentViewSet;
internal AvaloniaView? _view;
public Action<int, Result, Intent?>? ActivityResult { get; set; }
@ -39,6 +42,17 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
_content = value;
if (_view is not null)
{
if (!_contentViewSet)
{
_contentViewSet = true;
SetContentView(_view);
_listener = new GlobalLayoutListener(_view);
_view.ViewTreeObserver?.AddOnGlobalLayoutListener(_listener);
}
_view.Content = _content;
}
}
@ -76,14 +90,13 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
base.OnCreate(savedInstanceState);
SetContentView(_view);
_listener = new GlobalLayoutListener(_view);
_view.ViewTreeObserver?.AddOnGlobalLayoutListener(_listener);
if (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>()
is AndroidActivatableLifetime activatableLifetime)
{
activatableLifetime.CurrentIntendActivity = this;
}
// TODO: we probably don't need to create AvaloniaView, if it's just a protocol activation, and main activity is already created.
if (Intent?.Data is {} androidUri
if (Intent?.Data is { } androidUri
&& androidUri.IsAbsolute
&& Uri.TryCreate(androidUri.ToString(), UriKind.Absolute, out var uri))
{
@ -131,8 +144,11 @@ public class AvaloniaActivity : AppCompatActivity, IAvaloniaActivity
{
if (_view is not null)
{
if (_listener is not null)
{
_view.ViewTreeObserver?.RemoveOnGlobalLayoutListener(_listener);
}
_view.Content = null;
_view.ViewTreeObserver?.RemoveOnGlobalLayoutListener(_listener);
_view.Dispose();
_view = null;
}

18
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@ -10,18 +10,6 @@ public class AvaloniaMainActivity : AvaloniaActivity
{
private protected static SingleViewLifetime? Lifetime;
public override void OnCreate(Bundle? savedInstanceState, PersistableBundle? persistentState)
{
// Global IActivatableLifetime expects a main activity, so we need to replace it on each OnCreate.
if (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>()
is AndroidActivatableLifetime activatableLifetime)
{
activatableLifetime.Activity = this;
}
base.OnCreate(savedInstanceState, persistentState);
}
private protected override void InitializeAvaloniaView(object? initialContent)
{
// Android can run OnCreate + InitializeAvaloniaView multiple times per process lifetime.
@ -55,6 +43,12 @@ public class AvaloniaMainActivity : AvaloniaActivity
if (_view is null)
throw new InvalidOperationException("Unknown error: AvaloniaView initialization has failed.");
}
if (Avalonia.Application.Current?.TryGetFeature<IActivatableLifetime>()
is AndroidActivatableLifetime activatableLifetime)
{
activatableLifetime.CurrentMainActivity = this;
}
}
protected virtual AppBuilder CreateAppBuilder() => AppBuilder.Configure<Application>().UseAndroid();

65
src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs

@ -5,32 +5,71 @@ namespace Avalonia.Android.Platform;
internal class AndroidActivatableLifetime : ActivatableLifetimeBase
{
private IAvaloniaActivity? _activity;
private IAvaloniaActivity? _mainActivity, _intendActivity;
public IAvaloniaActivity? Activity
/// <summary>
/// While we primarily handle main activity lifecycle events.
/// Any secondary activity might send protocol or file activation.
/// </summary>
public IAvaloniaActivity? CurrentIntendActivity
{
get => _activity;
get => _intendActivity;
set
{
if (_activity is not null)
if (_intendActivity is not null)
{
_activity.Activated -= ActivityOnActivated;
_activity.Deactivated -= ActivityOnDeactivated;
_intendActivity.Activated -= IntendActivityOnActivated;
}
_activity = value;
_intendActivity = value;
if (_activity is not null)
if (_intendActivity is not null)
{
_activity.Activated += ActivityOnActivated;
_activity.Deactivated += ActivityOnDeactivated;
_intendActivity.Activated += IntendActivityOnActivated;
}
}
}
public IAvaloniaActivity? CurrentMainActivity
{
get => _mainActivity;
set
{
if (_mainActivity is not null)
{
_mainActivity.Activated -= MainActivityOnActivated;
_mainActivity.Deactivated -= MainActivityOnDeactivated;
}
_mainActivity = value;
if (_mainActivity is not null)
{
_mainActivity.Activated += MainActivityOnActivated;
_mainActivity.Deactivated += MainActivityOnDeactivated;
}
}
}
public override bool TryEnterBackground() => (_activity as Activity)?.MoveTaskToBack(true) == true;
public override bool TryEnterBackground() => (_mainActivity as Activity)?.MoveTaskToBack(true) == true;
private void ActivityOnDeactivated(object? sender, ActivatedEventArgs e) => OnDeactivated(e);
private void MainActivityOnDeactivated(object? sender, ActivatedEventArgs e) => OnDeactivated(e);
private void MainActivityOnActivated(object? sender, ActivatedEventArgs e)
{
if (!IsIntendActivation(e.Kind))
{
OnActivated(e);
}
}
private void IntendActivityOnActivated(object? sender, ActivatedEventArgs e)
{
if (IsIntendActivation(e.Kind))
{
OnActivated(e);
}
}
private void ActivityOnActivated(object? sender, ActivatedEventArgs e) => OnActivated(e);
private static bool IsIntendActivation(ActivationKind kind) => kind is ActivationKind.File or ActivationKind.OpenUri;
}

25
src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs

@ -4,6 +4,7 @@ using Android.App;
using Android.OS;
using Android.Views;
using Android.Views.Animations;
using AndroidX.Core.Graphics;
using AndroidX.Core.View;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Animation.Easings;
@ -25,6 +26,7 @@ namespace Avalonia.Android.Platform
private Color? _systemBarColor;
private InputPaneState _state;
private Rect _previousRect;
private Insets? _previousImeInset;
private readonly bool _usesLegacyLayouts;
private AndroidWindow Window => _activity.Window ?? throw new InvalidOperationException("Activity.Window must be set.");
@ -148,6 +150,19 @@ namespace Avalonia.Android.Platform
State = insets.IsVisible(WindowInsetsCompat.Type.Ime()) ? InputPaneState.Open : InputPaneState.Closed;
// Workaround for weird inset values for android 11
if(Build.VERSION.SdkInt == BuildVersionCodes.R)
{
var imeInset = insets.GetInsets(WindowInsetsCompat.Type.Ime());
if(_previousImeInset == default)
_previousImeInset = imeInset;
if(imeInset.Bottom != _previousImeInset.Bottom)
{
NotifyStateChanged(State, _previousRect, OccludedRect, TimeSpan.Zero, null);
}
_previousImeInset = imeInset;
}
return insets;
}
@ -191,11 +206,6 @@ namespace Avalonia.Android.Platform
{
_statusBarTheme = value;
if (!_topLevel.View.IsShown)
{
return;
}
var compat = new WindowInsetsControllerCompat(Window, _topLevel.View);
if (_isDefaultSystemBarLightTheme == null)
@ -229,11 +239,6 @@ namespace Avalonia.Android.Platform
{
_systemUiVisibility = value;
if (!_topLevel.View.IsShown)
{
return;
}
var compat = WindowCompat.GetInsetsController(Window, _topLevel.View);
if (value == null || value.Value)

1
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -101,7 +101,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
internal InvalidationAwareSurfaceView InternalView => _view;
public double DesktopScaling => RenderScaling;
public IScreenImpl? Screen { get; }
public IPlatformHandle Handle => _view;
public IEnumerable<object> Surfaces { get; }

4
src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs

@ -10,6 +10,7 @@ using Android.Provider;
using Android.Webkit;
using Avalonia.Logging;
using Avalonia.Platform.Storage;
using Avalonia.Platform.Storage.FileIO;
using Java.Lang;
using AndroidUri = Android.Net.Uri;
using Exception = System.Exception;
@ -53,7 +54,8 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem
}
Activity.ContentResolver?.TakePersistableUriPermission(Uri, ActivityFlags.GrantWriteUriPermission | ActivityFlags.GrantReadUriPermission);
return Uri.ToString();
return StorageBookmarkHelper.EncodeBookmark(AndroidStorageProvider.AndroidKey, Uri.ToString()!);
}
public async Task ReleaseBookmarkAsync()

22
src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Android;
using Android.App;
using Android.Content;
using Android.Provider;
using Avalonia.Platform.Storage;
using Avalonia.Platform.Storage.FileIO;
using AndroidUri = Android.Net.Uri;
using Exception = System.Exception;
using JavaFile = Java.IO.File;
@ -15,6 +17,7 @@ namespace Avalonia.Android.Platform.Storage;
internal class AndroidStorageProvider : IStorageProvider
{
public static ReadOnlySpan<byte> AndroidKey => "android"u8;
private readonly Activity _activity;
public AndroidStorageProvider(Activity activity)
@ -30,8 +33,8 @@ internal class AndroidStorageProvider : IStorageProvider
public Task<IStorageBookmarkFolder?> OpenFolderBookmarkAsync(string bookmark)
{
var uri = AndroidUri.Parse(bookmark) ?? throw new ArgumentException("Couldn't parse Bookmark value", nameof(bookmark));
return Task.FromResult<IStorageBookmarkFolder?>(new AndroidStorageFolder(_activity, uri, false));
var uri = DecodeUriFromBookmark(bookmark);
return Task.FromResult<IStorageBookmarkFolder?>(uri is null ? null : new AndroidStorageFolder(_activity, uri, false));
}
public async Task<IStorageFile?> TryGetFileFromPathAsync(Uri filePath)
@ -129,8 +132,19 @@ internal class AndroidStorageProvider : IStorageProvider
public Task<IStorageBookmarkFile?> OpenFileBookmarkAsync(string bookmark)
{
var uri = AndroidUri.Parse(bookmark) ?? throw new ArgumentException("Couldn't parse Bookmark value", nameof(bookmark));
return Task.FromResult<IStorageBookmarkFile?>(new AndroidStorageFile(_activity, uri));
var uri = DecodeUriFromBookmark(bookmark);
return Task.FromResult<IStorageBookmarkFile?>(uri is null ? null : new AndroidStorageFile(_activity, uri));
}
private static AndroidUri? DecodeUriFromBookmark(string bookmark)
{
return StorageBookmarkHelper.TryDecodeBookmark(AndroidKey, bookmark, out var bytes) switch
{
StorageBookmarkHelper.DecodeResult.Success => AndroidUri.Parse(Encoding.UTF8.GetString(bytes!)),
// Attempt to decode 11.0 android bookmarks
StorageBookmarkHelper.DecodeResult.InvalidFormat => AndroidUri.Parse(bookmark),
_ => null
};
}
public async Task<IReadOnlyList<IStorageFile>> OpenFilePickerAsync(FilePickerOpenOptions options)

2
src/Android/Avalonia.Android/SingleViewLifetime.cs

@ -10,7 +10,7 @@ internal class SingleViewLifetime : ISingleViewApplicationLifetime, ISingleTopLe
private AvaloniaMainActivity? _activity;
/// <summary>
/// Since Main Activity can be swapped, we should adjust litetime as well.
/// Since Main Activity can be swapped, we should adjust lifetime as well.
/// </summary>
public AvaloniaMainActivity Activity
{

4
src/Avalonia.Base/ApiCompatBaseline.txt

@ -1,4 +0,0 @@
Compat issues with assembly Avalonia.Base:
MembersMustExist : Member 'public System.Int32 System.Int32 Avalonia.Threading.DispatcherPriority.value__' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Threading.IDispatcher.Post<T>(System.Action<T>, T, Avalonia.Threading.DispatcherPriority)' is present in the implementation but not in the contract.
Total Issues: 2

4
src/Avalonia.Base/AvaloniaObject.cs

@ -818,11 +818,9 @@ namespace Avalonia
var fallback = value.HasValue ? value : value.WithValue(property.GetUnsetValue(this));
property.InvokeSetter(this, fallback);
break;
case BindingValueType.DataValidationError:
property.InvokeSetter(this, value);
break;
case BindingValueType.Value:
case BindingValueType.BindingErrorWithFallback:
case BindingValueType.DataValidationError:
case BindingValueType.DataValidationErrorWithFallback:
property.InvokeSetter(this, value);
break;

2
src/Avalonia.Base/Data/BindingNotification.cs

@ -178,7 +178,7 @@ namespace Avalonia.Data
/// to <paramref name="value"/>. If <paramref name="value"/> is a
/// <see cref="BindingNotification"/> then the value will first be extracted.
/// </remarks>
public static object? UpdateValue(object o, object value)
public static object? UpdateValue(object? o, object value)
{
if (o is BindingNotification n)
{

19
src/Avalonia.Base/Data/BindingOperations.cs

@ -101,6 +101,25 @@ namespace Avalonia.Data
return Apply(target, property, binding);
}
/// <summary>
/// Retrieves the <see cref="BindingExpressionBase"/> that is currently active on the
/// specified property.
/// </summary>
/// <param name="target">
/// The <see cref="AvaloniaObject"/> from which to retrieve the binding expression.
/// </param>
/// <param name="property">
/// The binding target property from which to retrieve the binding expression.
/// </param>
/// <returns>
/// The <see cref="BindingExpressionBase"/> object that is active on the given property or
/// null if no binding expression is active on the given property.
/// </returns>
public static BindingExpressionBase? GetBindingExpressionBase(AvaloniaObject target, AvaloniaProperty property)
{
return target.GetValueStore().GetExpression(property);
}
private sealed class TwoWayBindingDisposable : IDisposable
{
private readonly IDisposable _toTargetSubscription;

2
src/Avalonia.Base/Data/BindingValue.cs

@ -459,7 +459,7 @@ namespace Avalonia.Data
{
if (value is UnsetValueType)
{
throw new InvalidOperationException("AvaloniaValue.UnsetValue is not a valid value for BindingValue<>.");
throw new InvalidOperationException("AvaloniaProperty.UnsetValue is not a valid value for BindingValue<>.");
}
if (value is DoNothingType)

14
src/Avalonia.Base/Data/Core/BindingExpression.cs

@ -160,7 +160,7 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
var source = _nodes[0].Source;
for (var i = 0; i < _nodes.Count; ++i)
_nodes[i].SetSource(null, null);
_nodes[i].SetSource(AvaloniaProperty.UnsetValue, null);
_nodes[0].SetSource(source, null);
}
@ -253,10 +253,6 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
_nodes[nodeIndex + 1].SetSource(value, dataValidationError);
WriteTargetValueToSource();
}
else if (value is null)
{
OnNodeError(nodeIndex, "Value is null.");
}
else
{
_nodes[nodeIndex + 1].SetSource(value, dataValidationError);
@ -273,11 +269,11 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
/// <param name="error">The error message.</param>
internal void OnNodeError(int nodeIndex, string error)
{
// Set the source of all nodes after the one that errored to null. This needs to be done
// for each node individually because setting the source to null will not result in
// Set the source of all nodes after the one that errored to unset. This needs to be done
// for each node individually because setting the source to unset will not result in
// OnNodeValueChanged or OnNodeError being called.
for (var i = nodeIndex + 1; i < _nodes.Count; ++i)
_nodes[i].SetSource(null, null);
_nodes[i].SetSource(AvaloniaProperty.UnsetValue, null);
if (_mode == BindingMode.OneWayToSource)
return;
@ -394,7 +390,7 @@ internal partial class BindingExpression : UntypedBindingExpressionBase, IDescri
protected override void StopCore()
{
foreach (var node in _nodes)
node.Reset();
node.SetSource(AvaloniaProperty.UnsetValue, null);
if (_mode is BindingMode.TwoWay or BindingMode.OneWayToSource &&
TryGetTarget(out var target))

5
src/Avalonia.Base/Data/Core/ExpressionNodes/ArrayIndexerNode.cs

@ -44,8 +44,11 @@ internal sealed class ArrayIndexerNode : ExpressionNode, ISettableNode
return false;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is Array array)
SetValue(array.GetValue(_indexes));
else

3
src/Avalonia.Base/Data/Core/ExpressionNodes/AvaloniaPropertyAccessorNode.cs

@ -38,6 +38,9 @@ internal sealed class AvaloniaPropertyAccessorNode :
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is AvaloniaObject newObject)
{
WeakEvents.AvaloniaPropertyChanged.Subscribe(newObject, this);

5
src/Avalonia.Base/Data/Core/ExpressionNodes/CollectionNodeBase.cs

@ -22,8 +22,11 @@ internal abstract class CollectionNodeBase : ExpressionNode,
UpdateValueOrSetError(sender);
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
Subscribe(source);
UpdateValue(source);
}

5
src/Avalonia.Base/Data/Core/ExpressionNodes/DataContextNode.cs

@ -4,8 +4,11 @@ namespace Avalonia.Data.Core.ExpressionNodes;
internal sealed class DataContextNode : DataContextNodeBase
{
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is IDataContextProvider && source is AvaloniaObject ao)
{
ao.PropertyChanged += OnPropertyChanged;

63
src/Avalonia.Base/Data/Core/ExpressionNodes/ExpressionNode.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text;
@ -60,16 +61,6 @@ internal abstract class ExpressionNode
BuildString(builder);
}
/// <summary>
/// Resets the node to its uninitialized state when the <see cref="Owner"/> is unsubscribed.
/// </summary>
public void Reset()
{
SetSource(null, null);
_source = null;
_value = AvaloniaProperty.UnsetValue;
}
/// <summary>
/// Sets the owner binding.
/// </summary>
@ -101,28 +92,26 @@ internal abstract class ExpressionNode
/// </param>
public void SetSource(object? source, Exception? dataValidationError)
{
var oldSource = Source;
if (source == AvaloniaProperty.UnsetValue)
source = null;
if (_source?.TryGetTarget(out var oldSource) != true)
oldSource = AvaloniaProperty.UnsetValue;
if (source == oldSource)
return;
if (oldSource is not null)
if (oldSource is not null && oldSource != AvaloniaProperty.UnsetValue)
Unsubscribe(oldSource);
_source = new(source);
if (source is null)
if (source == AvaloniaProperty.UnsetValue)
{
// If the source is null then the value is null. We explicitly do not want to call
// If the source is unset then the value is unset. We explicitly do not want to call
// OnSourceChanged as we don't want to raise errors for subsequent nodes in the
// binding change.
_source = null;
_value = AvaloniaProperty.UnsetValue;
}
else
{
_source = new(source);
try { OnSourceChanged(source, dataValidationError); }
catch (Exception e) { SetError(e); }
}
@ -222,24 +211,28 @@ internal abstract class ExpressionNode
protected void SetValue(object? value, Exception? dataValidationError = null)
{
Debug.Assert(value is not BindingNotification);
_value = value;
Owner?.OnNodeValueChanged(Index, value, dataValidationError);
}
if (Owner is null)
return;
// We raise a change notification if:
//
// - This is the initial value (_value is null)
// - There is a data validation error
// - There is no data validation error, but the owner has one
// - The new value is different to the old value
if (_value is null ||
dataValidationError is not null ||
(dataValidationError is null && Owner.ErrorType == BindingErrorType.DataValidationError) ||
!Equals(value, _value))
/// <summary>
/// Called from <see cref="OnSourceChanged(object?, Exception?)"/> to validate that the source
/// is non-null and raise a node error if it is not.
/// </summary>
/// <param name="source">The expression node source.</param>
/// <returns>
/// True if the source is non-null; otherwise, false.
/// </returns>
protected bool ValidateNonNullSource([NotNullWhen(true)] object? source)
{
if (source is null)
{
_value = value;
Owner.OnNodeValueChanged(Index, value, dataValidationError);
Owner?.OnNodeError(Index - 1, "Value is null.");
_value = null;
return false;
}
return true;
}
/// <summary>
@ -250,7 +243,7 @@ internal abstract class ExpressionNode
/// <param name="dataValidationError">
/// Any data validation error reported by the previous expression node.
/// </param>
protected abstract void OnSourceChanged(object source, Exception? dataValidationError);
protected abstract void OnSourceChanged(object? source, Exception? dataValidationError);
/// <summary>
/// When implemented in a derived class, unsubscribes from the previous source.

5
src/Avalonia.Base/Data/Core/ExpressionNodes/FuncTransformNode.cs

@ -21,8 +21,11 @@ internal sealed class FuncTransformNode : ExpressionNode
// We don't have enough information to add anything here.
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
SetValue(_transform(source));
}
}

5
src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalAncestorElementNode.cs

@ -56,8 +56,11 @@ internal sealed class LogicalAncestorElementNode : SourceNode
return target is ILogical logical && logical.IsAttachedToLogicalTree;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is ILogical logical)
{
var locator = ControlLocator.Track(logical, _ancestorLevel, _ancestorType);

4
src/Avalonia.Base/Data/Core/ExpressionNodes/LogicalNotNode.cs

@ -28,14 +28,12 @@ internal sealed class LogicalNotNode : ExpressionNode, ISettableNode
return false;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
var v = BindingNotification.ExtractValue(source);
if (TryConvert(v, out var value))
{
SetValue(BindingNotification.UpdateValue(source, !value), dataValidationError);
}
else
SetError($"Unable to convert '{source}' to bool.");
}

5
src/Avalonia.Base/Data/Core/ExpressionNodes/MethodCommandNode.cs

@ -39,8 +39,11 @@ internal sealed class MethodCommandNode : ExpressionNode, IWeakEventSubscriber<P
builder.Append("()");
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is INotifyPropertyChanged newInpc)
WeakEvents.ThreadSafePropertyChanged.Subscribe(newInpc, this);

5
src/Avalonia.Base/Data/Core/ExpressionNodes/NamedElementNode.cs

@ -30,8 +30,11 @@ internal sealed class NamedElementNode : SourceNode
return target is not ILogical logical || logical.IsAttachedToLogicalTree;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (_nameScope.TryGetTarget(out var scope))
_subscription = NameScopeLocator.Track(scope, _name).Subscribe(SetValue);
else

5
src/Avalonia.Base/Data/Core/ExpressionNodes/ParentDataContextNode.cs

@ -11,8 +11,11 @@ internal sealed class ParentDataContextNode : DataContextNodeBase
private static readonly AvaloniaObject s_unset = new();
private AvaloniaObject? _parent = s_unset;
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is AvaloniaObject newElement)
newElement.PropertyChanged += OnPropertyChanged;

5
src/Avalonia.Base/Data/Core/ExpressionNodes/PropertyAccessorNode.cs

@ -48,8 +48,11 @@ internal sealed class PropertyAccessorNode : ExpressionNode, IPropertyAccessorNo
}
[UnconditionalSuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "<Pending>")]
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
var reference = new WeakReference<object?>(source);
if (_plugin.Start(reference, PropertyName) is { } accessor)

5
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginPropertyAccessorNode.cs

@ -42,8 +42,11 @@ internal sealed class DynamicPluginPropertyAccessorNode : ExpressionNode, IPrope
return _accessor?.SetValue(value, BindingPriority.LocalValue) ?? false;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
var reference = new WeakReference<object?>(source);
if (GetPlugin(source) is { } plugin &&

5
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs

@ -16,8 +16,11 @@ internal sealed class DynamicPluginStreamNode : ExpressionNode
builder.Append('^');
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
var reference = new WeakReference<object?>(source);
if (GetPlugin(reference) is { } plugin &&

5
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ReflectionIndexerNode.cs

@ -52,8 +52,11 @@ internal sealed class ReflectionIndexerNode : CollectionNodeBase, ISettableNode
return true;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
_indexes = null;
if (GetIndexer(source.GetType(), out _getter, out _setter))

5
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ReflectionTypeCastNode.cs

@ -19,8 +19,11 @@ internal sealed class ReflectionTypeCastNode : ExpressionNode
builder.Append(')');
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (_targetType.IsInstanceOfType(source))
SetValue(source);
else

5
src/Avalonia.Base/Data/Core/ExpressionNodes/StreamNode.cs

@ -23,8 +23,11 @@ internal sealed class StreamNode : ExpressionNode, IObserver<object?>
void IObserver<object?>.OnError(Exception error) { }
void IObserver<object?>.OnNext(object? value) => SetValue(value);
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (_plugin.Start(new(source)) is { } accessor)
{
_subscription = accessor.Subscribe(this);

5
src/Avalonia.Base/Data/Core/ExpressionNodes/TemplatedParentNode.cs

@ -22,8 +22,11 @@ internal sealed class TemplatedParentNode : SourceNode
throw new InvalidOperationException("Cannot find a StyledElement to get a TemplatedParent.");
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is StyledElement newElement)
{
newElement.PropertyChanged += OnPropertyChanged;

5
src/Avalonia.Base/Data/Core/ExpressionNodes/VisualAncestorElementNode.cs

@ -56,8 +56,11 @@ internal sealed class VisualAncestorElementNode : SourceNode
return target is Visual visual && visual.IsAttachedToVisualTree;
}
protected override void OnSourceChanged(object source, Exception? dataValidationError)
protected override void OnSourceChanged(object? source, Exception? dataValidationError)
{
if (!ValidateNonNullSource(source))
return;
if (source is Visual visual)
{
var locator = VisualLocator.Track(visual, _ancestorLevel, _ancestorType);

15
src/Avalonia.Base/Data/Core/UntypedObservableBindingExpression.cs

@ -30,5 +30,18 @@ internal class UntypedObservableBindingExpression : UntypedBindingExpressionBase
void IObserver<object?>.OnCompleted() { }
void IObserver<object?>.OnError(Exception error) { }
void IObserver<object?>.OnNext(object? value) => PublishValue(value);
void IObserver<object?>.OnNext(object? value)
{
if (value is BindingNotification n)
{
var v = n.Value;
var e = n.Error is not null ? new BindingError(n.Error, n.ErrorType) : null;
PublishValue(v, e);
}
else
{
PublishValue(value);
}
}
}

4
src/Avalonia.Base/Data/TemplateBinding.cs

@ -5,6 +5,7 @@ using System.Globalization;
using Avalonia.Data.Converters;
using Avalonia.Data.Core;
using Avalonia.Logging;
using Avalonia.Metadata;
using Avalonia.Styling;
namespace Avalonia.Data
@ -26,7 +27,7 @@ namespace Avalonia.Data
{
}
public TemplateBinding(AvaloniaProperty property)
public TemplateBinding([InheritDataTypeFrom(InheritDataTypeFromScopeKind.ControlTemplate)] AvaloniaProperty property)
: base(BindingPriority.Template)
{
Property = property;
@ -64,6 +65,7 @@ namespace Avalonia.Data
/// <summary>
/// Gets or sets the name of the source property on the templated parent.
/// </summary>
[InheritDataTypeFrom(InheritDataTypeFromScopeKind.ControlTemplate)]
public AvaloniaProperty? Property { get; set; }
/// <inheritdoc/>

5
src/Avalonia.Base/Input/MouseDevice.cs

@ -305,5 +305,10 @@ namespace Avalonia.Input
{
return _pointer;
}
internal void PlatformCaptureLost()
{
_pointer.Capture(null);
}
}
}

6
src/Avalonia.Base/Input/TouchDevice.cs

@ -160,5 +160,11 @@ namespace Avalonia.Input
? pointer
: null;
}
internal void PlatformCaptureLost()
{
foreach (var pointer in _pointers.Values)
pointer.Capture(null);
}
}
}

4
src/Avalonia.Base/Media/Fonts/Tables/HorizontalHeadTable.cs

@ -59,11 +59,11 @@ namespace Avalonia.Media.Fonts.Tables
public short XMaxExtent { get; }
public static HorizontalHeadTable Load(IGlyphTypeface glyphTypeface)
public static HorizontalHeadTable? Load(IGlyphTypeface glyphTypeface)
{
if (!glyphTypeface.TryGetTable(Tag, out var table))
{
throw new MissingFontTableException("Could not load table", "name");
return null;
}
using var stream = new MemoryStream(table);

32
src/Avalonia.Base/Media/Fonts/Tables/Name/NameTable.cs

@ -3,26 +3,24 @@
// Ported from: https://github.com/SixLabors/Fonts/blob/034a440aece357341fcc6b02db58ffbe153e54ef/src/SixLabors.Fonts
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
namespace Avalonia.Media.Fonts.Tables.Name
{
internal class NameTable
{
internal const string TableName = "name";
internal static OpenTypeTag Tag = OpenTypeTag.Parse(TableName);
internal static readonly OpenTypeTag Tag = OpenTypeTag.Parse(TableName);
private readonly NameRecord[] _names;
internal NameTable(NameRecord[] names, IReadOnlyList<CultureInfo> languages)
internal NameTable(NameRecord[] names, IReadOnlyList<ushort> languages)
{
_names = names;
Languages = languages;
}
public IReadOnlyList<CultureInfo> Languages { get; }
public IReadOnlyList<ushort> Languages { get; }
/// <summary>
/// Gets the name of the font.
@ -30,7 +28,7 @@ namespace Avalonia.Media.Fonts.Tables.Name
/// <value>
/// The name of the font.
/// </value>
public string Id(CultureInfo culture)
public string Id(ushort culture)
=> GetNameById(culture, KnownNameIds.UniqueFontID);
/// <summary>
@ -39,7 +37,7 @@ namespace Avalonia.Media.Fonts.Tables.Name
/// <value>
/// The name of the font.
/// </value>
public string FontName(CultureInfo culture)
public string FontName(ushort culture)
=> GetNameById(culture, KnownNameIds.FullFontName);
/// <summary>
@ -48,7 +46,7 @@ namespace Avalonia.Media.Fonts.Tables.Name
/// <value>
/// The name of the font.
/// </value>
public string FontFamilyName(CultureInfo culture)
public string FontFamilyName(ushort culture)
=> GetNameById(culture, KnownNameIds.FontFamilyName);
/// <summary>
@ -57,12 +55,12 @@ namespace Avalonia.Media.Fonts.Tables.Name
/// <value>
/// The name of the font.
/// </value>
public string FontSubFamilyName(CultureInfo culture)
public string FontSubFamilyName(ushort culture)
=> GetNameById(culture, KnownNameIds.FontSubfamilyName);
public string GetNameById(CultureInfo culture, KnownNameIds nameId)
public string GetNameById(ushort culture, KnownNameIds nameId)
{
var languageId = culture.LCID;
var languageId = culture;
NameRecord? usaVersion = null;
NameRecord? firstWindows = null;
NameRecord? first = null;
@ -97,7 +95,7 @@ namespace Avalonia.Media.Fonts.Tables.Name
string.Empty;
}
public string GetNameById(CultureInfo culture, ushort nameId)
public string GetNameById(ushort culture, ushort nameId)
=> GetNameById(culture, (KnownNameIds)nameId);
public static NameTable Load(IGlyphTypeface glyphTypeface)
@ -160,7 +158,7 @@ namespace Avalonia.Media.Fonts.Tables.Name
readable.LoadValue(reader);
}
var cultures = new List<CultureInfo>();
var cultures = new List<ushort>();
foreach (var nameRecord in names)
{
@ -169,16 +167,12 @@ namespace Avalonia.Media.Fonts.Tables.Name
continue;
}
var culture = new CultureInfo(nameRecord.LanguageID);
if (!cultures.Contains(culture))
if (!cultures.Contains(nameRecord.LanguageID))
{
cultures.Add(culture);
cultures.Add(nameRecord.LanguageID);
}
}
//var languages = languageNames.Select(x => x.Value).ToArray();
return new NameTable(names, cultures);
}
}

7
src/Avalonia.Base/Media/GlyphRun.cs

@ -574,7 +574,10 @@ namespace Avalonia.Media
}
}
nextCluster = _glyphInfos[currentIndex].GlyphCluster;
if (_glyphInfos.Count > 0 && currentIndex <= _glyphInfos.Count)
{
nextCluster = _glyphInfos[currentIndex].GlyphCluster;
}
}
var clusterLength = Math.Max(0, nextCluster - cluster);
@ -639,7 +642,7 @@ namespace Avalonia.Media
{
int firstCluster, lastCluster;
if (Characters.IsEmpty)
if (Characters.IsEmpty || _glyphInfos.Count == 0)
{
firstCluster = 0;
lastCluster = 0;

4
src/Avalonia.Base/Media/IGlyphTypeface2.cs

@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using Avalonia.Media.Fonts;
@ -17,8 +16,9 @@ namespace Avalonia.Media
/// <summary>
/// Gets the localized family names.
/// <para>Keys are culture identifiers.</para>
/// </summary>
IReadOnlyDictionary<CultureInfo, string> FamilyNames { get; }
IReadOnlyDictionary<ushort, string> FamilyNames { get; }
/// <summary>
/// Gets supported font features.

15
src/Avalonia.Base/Media/TextDecoration.cs

@ -182,18 +182,18 @@ namespace Avalonia.Media
break;
}
var origin = new Point();
var origin = baselineOrigin;
switch (Location)
{
case TextDecorationLocation.Baseline:
origin += glyphRun.BaselineOrigin;
case TextDecorationLocation.Overline:
origin += new Point(0, textMetrics.Ascent);
break;
case TextDecorationLocation.Strikethrough:
origin += new Point(baselineOrigin.X, baselineOrigin.Y + textMetrics.StrikethroughPosition);
origin += new Point(0, textMetrics.StrikethroughPosition);
break;
case TextDecorationLocation.Underline:
origin += new Point(baselineOrigin.X, baselineOrigin.Y + textMetrics.UnderlinePosition);
origin += new Point(0, textMetrics.UnderlinePosition);
break;
}
@ -255,7 +255,10 @@ namespace Avalonia.Media
}
}
drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Metrics.Width, 0));
var p1 = origin;
var p2 = p1 + new Point(glyphRun.Metrics.Width, 0);
drawingContext.DrawLine(pen, p1, p2);
}
}
}

5
src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs

@ -64,7 +64,7 @@ namespace Avalonia.Media.TextFormatting
if (Properties.BackgroundBrush != null)
{
drawingContext.DrawRectangle(Properties.BackgroundBrush, null, GlyphRun.Bounds);
drawingContext.DrawRectangle(Properties.BackgroundBrush, null, GlyphRun.Bounds.Translate(new Vector(0, -Baseline)));
}
drawingContext.DrawGlyphRun(Properties.ForegroundBrush, GlyphRun);
@ -204,7 +204,8 @@ namespace Avalonia.Media.TextFormatting
ShapedBuffer.FontRenderingEmSize,
Text,
ShapedBuffer,
biDiLevel: BidiLevel);
biDiLevel: BidiLevel,
baselineOrigin: new Point());
}
public void Dispose()

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

Loading…
Cancel
Save