Browse Source

Merge branch 'master' into android-auto-detect-night-mode

# Conflicts:
#	api/Avalonia.nupkg.xml
#	src/Tizen/Avalonia.Tizen/TopLevelImpl.cs
pull/16340/head
Julien Lebosquain 2 months ago
parent
commit
bfdb095412
No known key found for this signature in database GPG Key ID: 1833CAD10ACC46FD
  1. 3
      .editorconfig
  2. 192
      .nuke/build.schema.json
  3. 10
      Avalonia.Desktop.slnf
  4. 139
      Avalonia.sln
  5. 4
      CONTRIBUTING.md
  6. 4
      Directory.Build.props
  7. 16
      NuGet.Config
  8. 22
      api/Avalonia.Android.nupkg.xml
  9. 22
      api/Avalonia.Browser.nupkg.xml
  10. 10
      api/Avalonia.FreeDesktop.nupkg.xml
  11. 16
      api/Avalonia.Skia.nupkg.xml
  12. 16
      api/Avalonia.Themes.Fluent.nupkg.xml
  13. 214
      api/Avalonia.Win32.nupkg.xml
  14. 16
      api/Avalonia.iOS.nupkg.xml
  15. 272
      api/Avalonia.nupkg.xml
  16. 28
      azure-pipelines-integrationtests.yml
  17. 34
      azure-pipelines.yml
  18. 2
      build/AnalyzerProject.targets
  19. 12
      build/Base.props
  20. 2
      build/DevSingleProject.targets
  21. 6
      build/HarfBuzzSharp.props
  22. 2
      build/ImageSharp.props
  23. 5
      build/JetBrains.dotMemoryUnit.props
  24. 2
      build/Microsoft.Reactive.Testing.props
  25. 2
      build/Moq.props
  26. 5
      build/ReactiveUI.props
  27. 2
      build/Rx.props
  28. 1
      build/SharedVersion.props
  29. 6
      build/SkiaSharp.props
  30. 4
      build/SourceLink.props
  31. 19
      build/TargetFrameworks.props
  32. 5
      build/UnitTests.NetCore.targets
  33. 18
      build/XUnit.props
  34. 10
      dirs.proj
  35. 2
      docs/api-compat.md
  36. 9
      docs/build.md
  37. 2
      docs/porting-code-from-3rd-party-sources.md
  38. 2
      external/XamlX
  39. 2
      global.json
  40. 3
      native/Avalonia.Native/inc/com.h
  41. 5
      native/Avalonia.Native/inc/noarc.h
  42. 16
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  43. 1
      native/Avalonia.Native/src/OSX/AvnView.h
  44. 25
      native/Avalonia.Native/src/OSX/AvnView.mm
  45. 155
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  46. 2
      native/Avalonia.Native/src/OSX/KeyTransform.mm
  47. 43
      native/Avalonia.Native/src/OSX/StorageProvider.mm
  48. 8
      native/Avalonia.Native/src/OSX/TopLevelImpl.h
  49. 62
      native/Avalonia.Native/src/OSX/TopLevelImpl.mm
  50. 4
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  51. 45
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  52. 4
      native/Avalonia.Native/src/OSX/WindowImpl.h
  53. 54
      native/Avalonia.Native/src/OSX/automation.mm
  54. 55
      native/Avalonia.Native/src/OSX/cgl.mm
  55. 7
      native/Avalonia.Native/src/OSX/clipboard.h
  56. 420
      native/Avalonia.Native/src/OSX/clipboard.mm
  57. 5
      native/Avalonia.Native/src/OSX/common.h
  58. 9
      native/Avalonia.Native/src/OSX/crapium.h
  59. 21
      native/Avalonia.Native/src/OSX/crapium.mm
  60. 14
      native/Avalonia.Native/src/OSX/dnd.mm
  61. 29
      native/Avalonia.Native/src/OSX/main.mm
  62. 40
      native/Avalonia.Native/src/OSX/memhelp.mm
  63. 4
      native/Avalonia.Native/src/OSX/menu.mm
  64. 169
      native/Avalonia.Native/src/OSX/metal.mm
  65. 16
      native/Avalonia.Native/src/OSX/noarc.mm
  66. 6
      native/Avalonia.Native/src/OSX/trayicon.mm
  67. 639
      nukebuild/ApiDiffHelper.cs
  68. 199
      nukebuild/Build.cs
  69. 52
      nukebuild/BuildParameters.cs
  70. 2
      nukebuild/BuildTasksPatcher.cs
  71. 25
      nukebuild/ByteArrayEqualityComparer.cs
  72. 20
      nukebuild/_build.csproj
  73. 12
      packages/Avalonia/Avalonia.csproj
  74. 5
      packages/Avalonia/Avalonia.props
  75. 2
      packages/Avalonia/AvaloniaPrivateApis.targets
  76. 4
      packages/Avalonia/AvaloniaSingleProject.targets
  77. 2
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  78. 10
      samples/ControlCatalog.Browser.Blazor/App.razor
  79. 10
      samples/ControlCatalog.Browser.Blazor/App.razor.cs
  80. 29
      samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj
  81. 5
      samples/ControlCatalog.Browser.Blazor/Pages/Index.razor
  82. 39
      samples/ControlCatalog.Browser.Blazor/Program.cs
  83. 22
      samples/ControlCatalog.Browser.Blazor/Properties/launchSettings.json
  84. 7
      samples/ControlCatalog.Browser.Blazor/Shared/MainLayout.razor
  85. 10
      samples/ControlCatalog.Browser.Blazor/_Imports.razor
  86. 56
      samples/ControlCatalog.Browser.Blazor/wwwroot/css/app.css
  87. BIN
      samples/ControlCatalog.Browser.Blazor/wwwroot/favicon.ico
  88. 22
      samples/ControlCatalog.Browser.Blazor/wwwroot/index.html
  89. 35
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  90. 2
      samples/ControlCatalog.Desktop/NativeControls/Gtk/EmbedSample.Gtk.cs
  91. 2
      samples/ControlCatalog.Desktop/NativeControls/Gtk/GtkHelper.cs
  92. 0
      samples/ControlCatalog.Desktop/NativeControls/Gtk/nodes-license.md
  93. 0
      samples/ControlCatalog.Desktop/NativeControls/Gtk/nodes.mp4
  94. 2
      samples/ControlCatalog.Desktop/NativeControls/Mac/EmbedSample.Mac.cs
  95. 2
      samples/ControlCatalog.Desktop/NativeControls/Mac/MacHelper.cs
  96. 2
      samples/ControlCatalog.Desktop/NativeControls/Win/EmbedSample.Win.cs
  97. 2
      samples/ControlCatalog.Desktop/NativeControls/Win/WinApi.cs
  98. 172
      samples/ControlCatalog.Desktop/Program.cs
  99. 2
      samples/ControlCatalog.Desktop/Properties/launchSettings.json
  100. 0
      samples/ControlCatalog.Desktop/app.manifest

3
.editorconfig

@ -141,9 +141,6 @@ dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomme
# CS0649: Field 'field' is never assigned to, and will always have its default value 'value' # CS0649: Field 'field' is never assigned to, and will always have its default value 'value'
dotnet_diagnostic.CS0649.severity = error dotnet_diagnostic.CS0649.severity = error
# CS1591: Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS1591.severity = suggestion
# CS0162: Remove unreachable code # CS0162: Remove unreachable code
dotnet_diagnostic.CS0162.severity = error dotnet_diagnostic.CS0162.severity = error
# CA1018: Mark attributes with AttributeUsageAttribute # CA1018: Mark attributes with AttributeUsageAttribute

192
.nuke/build.schema.json

@ -1,48 +1,78 @@
{ {
"$schema": "http://json-schema.org/draft-04/schema#", "$schema": "http://json-schema.org/draft-04/schema#",
"title": "Build Schema",
"$ref": "#/definitions/build",
"definitions": { "definitions": {
"build": { "Host": {
"type": "object", "type": "string",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
},
"ExecutableTarget": {
"type": "string",
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"DownloadApiBaselinePackages",
"GenerateCppHeaders",
"InitDnx",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
},
"Verbosity": {
"type": "string",
"description": "",
"enum": [
"Verbose",
"Normal",
"Minimal",
"Quiet"
]
},
"NukeBuild": {
"properties": { "properties": {
"api-baseline": {
"type": "string"
},
"configuration": {
"type": "string"
},
"Continue": { "Continue": {
"type": "boolean", "type": "boolean",
"description": "Indicates to continue a previously failed build attempt" "description": "Indicates to continue a previously failed build attempt"
}, },
"force-nuget-version": {
"type": "string"
},
"Help": { "Help": {
"type": "boolean", "type": "boolean",
"description": "Shows the help text for this build assembly" "description": "Shows the help text for this build assembly"
}, },
"Host": { "Host": {
"type": "string",
"description": "Host for execution. Default is 'automatic'", "description": "Host for execution. Default is 'automatic'",
"enum": [ "$ref": "#/definitions/Host"
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
}, },
"NoLogo": { "NoLogo": {
"type": "boolean", "type": "boolean",
@ -71,89 +101,51 @@
"type": "array", "type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies", "description": "List of targets to be skipped. Empty list skips all dependencies",
"items": { "items": {
"type": "string", "$ref": "#/definitions/ExecutableTarget"
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"GenerateCppHeaders",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
} }
}, },
"skip-previewer": {
"type": "boolean"
},
"skip-tests": {
"type": "boolean"
},
"Target": { "Target": {
"type": "array", "type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'", "description": "List of targets to be invoked. Default is '{default_target}'",
"items": { "items": {
"type": "string", "$ref": "#/definitions/ExecutableTarget"
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"GenerateCppHeaders",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
} }
}, },
"update-api-suppression": {
"type": "boolean"
},
"Verbosity": { "Verbosity": {
"type": "string",
"description": "Logging verbosity during build execution. Default is 'Normal'", "description": "Logging verbosity during build execution. Default is 'Normal'",
"enum": [ "$ref": "#/definitions/Verbosity"
"Minimal", }
"Normal", }
"Quiet", }
"Verbose" },
"allOf": [
{
"properties": {
"configuration": {
"type": "string"
},
"force-api-baseline": {
"type": "string"
},
"force-nuget-version": {
"type": "string"
},
"skip-tests": {
"type": "boolean"
},
"update-api-suppression": {
"type": [
"boolean",
"null"
] ]
}, },
"version-output-dir": { "version-output-dir": {
"type": "string" "type": "string"
} }
} }
},
{
"$ref": "#/definitions/NukeBuild"
} }
} ]
} }

10
Avalonia.Desktop.slnf

@ -1,16 +1,15 @@
{ {
"solution": { "solution": {
"path": "Avalonia.sln", "path": "Avalonia.sln",
"projects": [ "projects": [
"packages\\Avalonia\\Avalonia.csproj", "packages\\Avalonia\\Avalonia.csproj",
"samples\\AppWithoutLifetime\\AppWithoutLifetime.csproj", "samples\\AppWithoutLifetime\\AppWithoutLifetime.csproj",
"samples\\ControlCatalog.NetCore\\ControlCatalog.NetCore.csproj", "samples\\ControlCatalog.Desktop\\ControlCatalog.Desktop.csproj",
"samples\\ControlCatalog\\ControlCatalog.csproj", "samples\\ControlCatalog\\ControlCatalog.csproj",
"samples\\GpuInterop\\GpuInterop.csproj", "samples\\GpuInterop\\GpuInterop.csproj",
"samples\\IntegrationTestApp\\IntegrationTestApp.csproj", "samples\\IntegrationTestApp\\IntegrationTestApp.csproj",
"samples\\TextTestApp\\TextTestApp.csproj", "samples\\TextTestApp\\TextTestApp.csproj",
"samples\\MiniMvvm\\MiniMvvm.csproj", "samples\\MiniMvvm\\MiniMvvm.csproj",
"samples\\ReactiveUIDemo\\ReactiveUIDemo.csproj",
"samples\\RenderDemo\\RenderDemo.csproj", "samples\\RenderDemo\\RenderDemo.csproj",
"samples\\SampleControls\\ControlSamples.csproj", "samples\\SampleControls\\ControlSamples.csproj",
"samples\\Sandbox\\Sandbox.csproj", "samples\\Sandbox\\Sandbox.csproj",
@ -32,7 +31,6 @@
"src\\Avalonia.Native\\Avalonia.Native.csproj", "src\\Avalonia.Native\\Avalonia.Native.csproj",
"src\\Avalonia.OpenGL\\Avalonia.OpenGL.csproj", "src\\Avalonia.OpenGL\\Avalonia.OpenGL.csproj",
"src\\Avalonia.Vulkan\\Avalonia.Vulkan.csproj", "src\\Avalonia.Vulkan\\Avalonia.Vulkan.csproj",
"src\\Avalonia.ReactiveUI\\Avalonia.ReactiveUI.csproj",
"src\\Avalonia.Remote.Protocol\\Avalonia.Remote.Protocol.csproj", "src\\Avalonia.Remote.Protocol\\Avalonia.Remote.Protocol.csproj",
"src\\Avalonia.Themes.Fluent\\Avalonia.Themes.Fluent.csproj", "src\\Avalonia.Themes.Fluent\\Avalonia.Themes.Fluent.csproj",
"src\\Avalonia.Themes.Simple\\Avalonia.Themes.Simple.csproj", "src\\Avalonia.Themes.Simple\\Avalonia.Themes.Simple.csproj",
@ -48,7 +46,6 @@
"src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj", "src\\tools\\Avalonia.Generators\\Avalonia.Generators.csproj",
"src\\tools\\DevAnalyzers\\DevAnalyzers.csproj", "src\\tools\\DevAnalyzers\\DevAnalyzers.csproj",
"src\\tools\\DevGenerators\\DevGenerators.csproj", "src\\tools\\DevGenerators\\DevGenerators.csproj",
"src\\Windows\\Avalonia.Direct2D1\\Avalonia.Direct2D1.csproj",
"src\\Windows\\Avalonia.Win32.Automation\\Avalonia.Win32.Automation.csproj", "src\\Windows\\Avalonia.Win32.Automation\\Avalonia.Win32.Automation.csproj",
"src\\Windows\\Avalonia.Win32.Interoperability\\Avalonia.Win32.Interoperability.csproj", "src\\Windows\\Avalonia.Win32.Interoperability\\Avalonia.Win32.Interoperability.csproj",
"src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj", "src\\Windows\\Avalonia.Win32\\Avalonia.Win32.csproj",
@ -58,14 +55,11 @@
"tests\\Avalonia.Controls.UnitTests\\Avalonia.Controls.UnitTests.csproj", "tests\\Avalonia.Controls.UnitTests\\Avalonia.Controls.UnitTests.csproj",
"tests\\Avalonia.DesignerSupport.TestApp\\Avalonia.DesignerSupport.TestApp.csproj", "tests\\Avalonia.DesignerSupport.TestApp\\Avalonia.DesignerSupport.TestApp.csproj",
"tests\\Avalonia.DesignerSupport.Tests\\Avalonia.DesignerSupport.Tests.csproj", "tests\\Avalonia.DesignerSupport.Tests\\Avalonia.DesignerSupport.Tests.csproj",
"tests\\Avalonia.Direct2D1.RenderTests\\Avalonia.Direct2D1.RenderTests.csproj",
"tests\\Avalonia.Direct2D1.UnitTests\\Avalonia.Direct2D1.UnitTests.csproj",
"tests\\Avalonia.Generators.Tests\\Avalonia.Generators.Tests.csproj", "tests\\Avalonia.Generators.Tests\\Avalonia.Generators.Tests.csproj",
"tests\\Avalonia.IntegrationTests.Appium\\Avalonia.IntegrationTests.Appium.csproj", "tests\\Avalonia.IntegrationTests.Appium\\Avalonia.IntegrationTests.Appium.csproj",
"tests\\Avalonia.LeakTests\\Avalonia.LeakTests.csproj", "tests\\Avalonia.LeakTests\\Avalonia.LeakTests.csproj",
"tests\\Avalonia.Markup.UnitTests\\Avalonia.Markup.UnitTests.csproj", "tests\\Avalonia.Markup.UnitTests\\Avalonia.Markup.UnitTests.csproj",
"tests\\Avalonia.Markup.Xaml.UnitTests\\Avalonia.Markup.Xaml.UnitTests.csproj", "tests\\Avalonia.Markup.Xaml.UnitTests\\Avalonia.Markup.Xaml.UnitTests.csproj",
"tests\\Avalonia.ReactiveUI.UnitTests\\Avalonia.ReactiveUI.UnitTests.csproj",
"tests\\Avalonia.RenderTests.WpfCompare\\Avalonia.RenderTests.WpfCompare.csproj", "tests\\Avalonia.RenderTests.WpfCompare\\Avalonia.RenderTests.WpfCompare.csproj",
"tests\\Avalonia.Skia.RenderTests\\Avalonia.Skia.RenderTests.csproj", "tests\\Avalonia.Skia.RenderTests\\Avalonia.Skia.RenderTests.csproj",
"tests\\Avalonia.Skia.UnitTests\\Avalonia.Skia.UnitTests.csproj", "tests\\Avalonia.Skia.UnitTests\\Avalonia.Skia.UnitTests.csproj",

139
Avalonia.sln

@ -9,8 +9,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Windows", "Windows", "{B39A
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Win32", "src\Windows\Avalonia.Win32\Avalonia.Win32.csproj", "{811A76CF-1CF6-440F-963B-BBE31BD72A82}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1", "src\Windows\Avalonia.Direct2D1\Avalonia.Direct2D1.csproj", "{3E908F67-5543-4879-A1DC-08EACE79B3CD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls", "src\Avalonia.Controls\Avalonia.Controls.csproj", "{D2221C82-4A25-4583-9B43-D791E3F6820C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls", "src\Avalonia.Controls\Avalonia.Controls.csproj", "{D2221C82-4A25-4583-9B43-D791E3F6820C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Simple", "src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj", "{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Simple", "src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj", "{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}"
@ -23,10 +21,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.UnitTests
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Base.UnitTests", "tests\Avalonia.Base.UnitTests\Avalonia.Base.UnitTests.csproj", "{2905FF23-53FB-45E6-AA49-6AF47A172056}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Base.UnitTests", "tests\Avalonia.Base.UnitTests\Avalonia.Base.UnitTests.csproj", "{2905FF23-53FB-45E6-AA49-6AF47A172056}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1.RenderTests", "tests\Avalonia.Direct2D1.RenderTests\Avalonia.Direct2D1.RenderTests.csproj", "{DABFD304-D6A4-4752-8123-C2CCF7AC7831}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Direct2D1.UnitTests", "tests\Avalonia.Direct2D1.UnitTests\Avalonia.Direct2D1.UnitTests.csproj", "{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.Xaml.UnitTests", "tests\Avalonia.Markup.Xaml.UnitTests\Avalonia.Markup.Xaml.UnitTests.csproj", "{99135EAB-653D-47E4-A378-C96E1278CA44}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.Xaml.UnitTests", "tests\Avalonia.Markup.Xaml.UnitTests\Avalonia.Markup.Xaml.UnitTests.csproj", "{99135EAB-653D-47E4-A378-C96E1278CA44}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Markup", "Markup", "{8B6A8209-894F-4BA1-B880-965FD453982C}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Markup", "Markup", "{8B6A8209-894F-4BA1-B880-965FD453982C}"
@ -38,15 +32,14 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig .editorconfig = .editorconfig
src\Shared\CallerArgumentExpressionAttribute.cs = src\Shared\CallerArgumentExpressionAttribute.cs
src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs src\Shared\IsExternalInit.cs = src\Shared\IsExternalInit.cs
src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs src\Shared\ModuleInitializer.cs = src\Shared\ModuleInitializer.cs
src\Shared\NullableAttributes.cs = src\Shared\NullableAttributes.cs
src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs src\Shared\SourceGeneratorAttributes.cs = src\Shared\SourceGeneratorAttributes.cs
src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs src\Shared\StringCompatibilityExtensions.cs = src\Shared\StringCompatibilityExtensions.cs
src\Shared\StreamCompatibilityExtensions.cs = src\Shared\StreamCompatibilityExtensions.cs
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Markup\Avalonia.Markup\Avalonia.Markup.csproj", "{6417E941-21BC-467B-A771-0DE389353CE6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
@ -87,8 +80,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Android", "s
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "samples\ControlCatalog.NetCore\ControlCatalog.NetCore.csproj", "{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props
@ -99,7 +90,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\EmbedXaml.props = build\EmbedXaml.props build\EmbedXaml.props = build\EmbedXaml.props
build\HarfBuzzSharp.props = build\HarfBuzzSharp.props build\HarfBuzzSharp.props = build\HarfBuzzSharp.props
build\ImageSharp.props = build\ImageSharp.props build\ImageSharp.props = build\ImageSharp.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props build\Moq.props = build\Moq.props
@ -107,12 +97,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\NetCore.props = build\NetCore.props build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props build\NetFX.props = build\NetFX.props
build\NullableEnable.props = build\NullableEnable.props build\NullableEnable.props = build\NullableEnable.props
build\ReactiveUI.props = build\ReactiveUI.props
build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props
build\Rx.props = build\Rx.props build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.props build\SampleApp.props = build\SampleApp.props
build\SharedVersion.props = build\SharedVersion.props build\SharedVersion.props = build\SharedVersion.props
build\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props build\SkiaSharp.props = build\SkiaSharp.props
build\SourceGenerators.props = build\SourceGenerators.props build\SourceGenerators.props = build\SourceGenerators.props
build\SourceLink.props = build\SourceLink.props build\SourceLink.props = build\SourceLink.props
@ -170,8 +158,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.X11", "src\Avaloni
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.UnitTests", "tests\Avalonia.ReactiveUI.UnitTests\Avalonia.ReactiveUI.UnitTests.csproj", "{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Dialogs", "src\Avalonia.Dialogs\Avalonia.Dialogs.csproj", "{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Dialogs", "src\Avalonia.Dialogs\Avalonia.Dialogs.csproj", "{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.FreeDesktop", "src\Avalonia.FreeDesktop\Avalonia.FreeDesktop.csproj", "{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.FreeDesktop", "src\Avalonia.FreeDesktop\Avalonia.FreeDesktop.csproj", "{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}"
@ -216,14 +202,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SingleProjectSandbox", "sam
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser", "src\Browser\Avalonia.Browser\Avalonia.Browser.csproj", "{4A39637C-9338-4925-A4DB-D072E292EC78}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Browser.Blazor", "src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj", "{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser", "samples\ControlCatalog.Browser\ControlCatalog.Browser.csproj", "{15B93A4C-1B46-43F6-B534-7B25B6E99932}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Browser.Blazor", "samples\ControlCatalog.Browser.Blazor\ControlCatalog.Browser.Blazor.csproj", "{90B08091-9BBD-4362-B712-E9F2CC62B218}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveUIDemo", "samples\ReactiveUIDemo\ReactiveUIDemo.csproj", "{75C47156-C5D8-44BC-A5A7-E8657C2248D6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GpuInterop", "samples\GpuInterop\GpuInterop.csproj", "{C810060E-3809-4B74-A125-F11533AF9C1B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GpuInterop", "samples\GpuInterop\GpuInterop.csproj", "{C810060E-3809-4B74-A125-F11533AF9C1B}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Analyzers", "src\tools\Avalonia.Analyzers\Avalonia.Analyzers.csproj", "{C692FE73-43DB-49CE-87FC-F03ED61F25C9}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Analyzers", "src\tools\Avalonia.Analyzers\Avalonia.Analyzers.csproj", "{C692FE73-43DB-49CE-87FC-F03ED61F25C9}"
@ -269,16 +249,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Headless.NUnit", "
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Generators.Tests", "tests\Avalonia.Generators.Tests\Avalonia.Generators.Tests.csproj", "{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Generators.Tests", "tests\Avalonia.Generators.Tests\Avalonia.Generators.Tests.csproj", "{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Headless.NUnit.UnitTests", "tests\Avalonia.Headless.NUnit.UnitTests\Avalonia.Headless.NUnit.UnitTests.csproj", "{2999D79E-3C20-4A90-B651-CA7E0AC92D35}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Headless.XUnit.UnitTests", "tests\Avalonia.Headless.XUnit.UnitTests\Avalonia.Headless.XUnit.UnitTests.csproj", "{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tizen", "Tizen", "{D1300000-7217-4693-8B0F-57CBD5814302}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Tizen", "src\Tizen\Avalonia.Tizen\Avalonia.Tizen.csproj", "{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Tizen", "samples\ControlCatalog.Tizen\ControlCatalog.Tizen.csproj", "{A0B29221-2B6F-4B29-A4D5-2227811B5915}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Metal", "src\Avalonia.Metal\Avalonia.Metal.csproj", "{60B4ED1F-ECFA-453B-8A70-1788261C8355}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Metal", "src\Avalonia.Metal\Avalonia.Metal.csproj", "{60B4ED1F-ECFA-453B-8A70-1788261C8355}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Build.Tasks.UnitTest", "tests\Avalonia.Build.Tasks.UnitTest\Avalonia.Build.Tasks.UnitTest.csproj", "{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Build.Tasks.UnitTest", "tests\Avalonia.Build.Tasks.UnitTest\Avalonia.Build.Tasks.UnitTest.csproj", "{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}"
@ -303,9 +273,19 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32.Automation",
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XEmbedSample", "samples\XEmbedSample\XEmbedSample.csproj", "{255614F5-CB64-4ECA-A026-E0B1AF6A2EF4}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XEmbedSample", "samples\XEmbedSample\XEmbedSample.csproj", "{255614F5-CB64-4ECA-A026-E0B1AF6A2EF4}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.MacCatalyst", "samples\ControlCatalog.iOS\ControlCatalog.MacCatalyst.csproj", "{DE3C28DD-B602-4750-831D-345102A54CA0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.MacCatalyst", "samples\ControlCatalog.MacCatalyst\ControlCatalog.MacCatalyst.csproj", "{DE3C28DD-B602-4750-831D-345102A54CA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.tvOS", "samples\ControlCatalog.tvOS\ControlCatalog.tvOS.csproj", "{14342787-B4EF-4076-8C91-BA6C523DE8DF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.NUnit.PerAssembly.UnitTests", "tests\Avalonia.Headless.NUnit.PerAssembly.UnitTests\Avalonia.Headless.NUnit.PerAssembly.UnitTests.csproj", "{A175EFAE-476C-4DAA-87D5-742C18CFCC27}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.NUnit.PerTest.UnitTests", "tests\Avalonia.Headless.NUnit.PerTest.UnitTests\Avalonia.Headless.NUnit.PerTest.UnitTests.csproj", "{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.XUnit.PerAssembly.UnitTests", "tests\Avalonia.Headless.XUnit.PerAssembly.UnitTests\Avalonia.Headless.XUnit.PerAssembly.UnitTests.csproj", "{342D2657-2F84-493C-B74B-9D2CAE5D9DAB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless.XUnit.PerTest.UnitTests", "tests\Avalonia.Headless.XUnit.PerTest.UnitTests\Avalonia.Headless.XUnit.PerTest.UnitTests.csproj", "{26918642-829D-4FA2-B60A-BE8D83F4E063}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.tvOS", "samples\ControlCatalog.iOS\ControlCatalog.tvOS.csproj", "{14342787-B4EF-4076-8C91-BA6C523DE8DF}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.IntegrationTests.Win32", "tests\Avalonia.IntegrationTests.Win32\Avalonia.IntegrationTests.Win32.csproj", "{11522B0D-BF31-42D5-8FC5-41E58F319AF9}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -321,10 +301,6 @@ Global
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|Any CPU.Build.0 = Debug|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.ActiveCfg = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.Build.0 = Release|Any CPU {811A76CF-1CF6-440F-963B-BBE31BD72A82}.Release|Any CPU.Build.0 = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|Any CPU.Build.0 = Release|Any CPU
{D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2221C82-4A25-4583-9B43-D791E3F6820C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D2221C82-4A25-4583-9B43-D791E3F6820C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2221C82-4A25-4583-9B43-D791E3F6820C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -345,14 +321,6 @@ Global
{2905FF23-53FB-45E6-AA49-6AF47A172056}.Debug|Any CPU.Build.0 = Debug|Any CPU {2905FF23-53FB-45E6-AA49-6AF47A172056}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2905FF23-53FB-45E6-AA49-6AF47A172056}.Release|Any CPU.ActiveCfg = Release|Any CPU {2905FF23-53FB-45E6-AA49-6AF47A172056}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2905FF23-53FB-45E6-AA49-6AF47A172056}.Release|Any CPU.Build.0 = Release|Any CPU {2905FF23-53FB-45E6-AA49-6AF47A172056}.Release|Any CPU.Build.0 = Release|Any CPU
{DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DABFD304-D6A4-4752-8123-C2CCF7AC7831}.Release|Any CPU.Build.0 = Release|Any CPU
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8}.Release|Any CPU.Build.0 = Release|Any CPU
{99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.Build.0 = Debug|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99135EAB-653D-47E4-A378-C96E1278CA44}.Release|Any CPU.ActiveCfg = Release|Any CPU {99135EAB-653D-47E4-A378-C96E1278CA44}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -361,10 +329,6 @@ Global
{3E53A01A-B331-47F3-B828-4A5717E77A24}.Debug|Any CPU.Build.0 = Debug|Any CPU {3E53A01A-B331-47F3-B828-4A5717E77A24}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|Any CPU.ActiveCfg = Release|Any CPU {3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|Any CPU.Build.0 = Release|Any CPU {3E53A01A-B331-47F3-B828-4A5717E77A24}.Release|Any CPU.Build.0 = Release|Any CPU
{6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6417B24E-49C2-4985-8DB2-3AB9D898EC91}.Release|Any CPU.Build.0 = Release|Any CPU
{6417E941-21BC-467B-A771-0DE389353CE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6417E941-21BC-467B-A771-0DE389353CE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6417E941-21BC-467B-A771-0DE389353CE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {6417E941-21BC-467B-A771-0DE389353CE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6417E941-21BC-467B-A771-0DE389353CE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {6417E941-21BC-467B-A771-0DE389353CE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -431,10 +395,6 @@ Global
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.Build.0 = Debug|Any CPU {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.ActiveCfg = Release|Any CPU {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.Build.0 = Release|Any CPU {7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.Build.0 = Release|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Release|Any CPU.Build.0 = Release|Any CPU
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU {854568D5-13D1-4B4F-B50D-534DC7EFD3C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -497,10 +457,6 @@ Global
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.Build.0 = Release|Any CPU {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|Any CPU.Build.0 = Release|Any CPU
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.Build.0 = Release|Any CPU
{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.Build.0 = Debug|Any CPU {4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|Any CPU.ActiveCfg = Release|Any CPU {4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -585,22 +541,10 @@ Global
{4A39637C-9338-4925-A4DB-D072E292EC78}.Debug|Any CPU.Build.0 = Debug|Any CPU {4A39637C-9338-4925-A4DB-D072E292EC78}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.Build.0 = Release|Any CPU {4A39637C-9338-4925-A4DB-D072E292EC78}.Release|Any CPU.Build.0 = Release|Any CPU
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D}.Release|Any CPU.Build.0 = Release|Any CPU
{15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.Build.0 = Debug|Any CPU {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Debug|Any CPU.Build.0 = Debug|Any CPU
{15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.ActiveCfg = Release|Any CPU {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.ActiveCfg = Release|Any CPU
{15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.Build.0 = Release|Any CPU {15B93A4C-1B46-43F6-B534-7B25B6E99932}.Release|Any CPU.Build.0 = Release|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90B08091-9BBD-4362-B712-E9F2CC62B218}.Release|Any CPU.Build.0 = Release|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75C47156-C5D8-44BC-A5A7-E8657C2248D6}.Release|Any CPU.Build.0 = Release|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU {C810060E-3809-4B74-A125-F11533AF9C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C810060E-3809-4B74-A125-F11533AF9C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU {C810060E-3809-4B74-A125-F11533AF9C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -657,24 +601,6 @@ Global
{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Release|Any CPU.Build.0 = Release|Any CPU {4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64}.Release|Any CPU.Build.0 = Release|Any CPU
{2999D79E-3C20-4A90-B651-CA7E0AC92D35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2999D79E-3C20-4A90-B651-CA7E0AC92D35}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2999D79E-3C20-4A90-B651-CA7E0AC92D35}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2999D79E-3C20-4A90-B651-CA7E0AC92D35}.Release|Any CPU.Build.0 = Release|Any CPU
{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3}.Release|Any CPU.Build.0 = Release|Any CPU
{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Release|Any CPU.Build.0 = Release|Any CPU
{A0B29221-2B6F-4B29-A4D5-2227811B5915}.Release|Any CPU.Deploy.0 = Release|Any CPU
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {60B4ED1F-ECFA-453B-8A70-1788261C8355}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Debug|Any CPU.Build.0 = Debug|Any CPU {60B4ED1F-ECFA-453B-8A70-1788261C8355}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60B4ED1F-ECFA-453B-8A70-1788261C8355}.Release|Any CPU.ActiveCfg = Release|Any CPU {60B4ED1F-ECFA-453B-8A70-1788261C8355}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -719,17 +645,34 @@ Global
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Debug|Any CPU.Build.0 = Debug|Any CPU {14342787-B4EF-4076-8C91-BA6C523DE8DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.Build.0 = Release|Any CPU {14342787-B4EF-4076-8C91-BA6C523DE8DF}.Release|Any CPU.Build.0 = Release|Any CPU
{A175EFAE-476C-4DAA-87D5-742C18CFCC27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A175EFAE-476C-4DAA-87D5-742C18CFCC27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A175EFAE-476C-4DAA-87D5-742C18CFCC27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A175EFAE-476C-4DAA-87D5-742C18CFCC27}.Release|Any CPU.Build.0 = Release|Any CPU
{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C}.Release|Any CPU.Build.0 = Release|Any CPU
{342D2657-2F84-493C-B74B-9D2CAE5D9DAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{342D2657-2F84-493C-B74B-9D2CAE5D9DAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{342D2657-2F84-493C-B74B-9D2CAE5D9DAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{342D2657-2F84-493C-B74B-9D2CAE5D9DAB}.Release|Any CPU.Build.0 = Release|Any CPU
{26918642-829D-4FA2-B60A-BE8D83F4E063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26918642-829D-4FA2-B60A-BE8D83F4E063}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26918642-829D-4FA2-B60A-BE8D83F4E063}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26918642-829D-4FA2-B60A-BE8D83F4E063}.Release|Any CPU.Build.0 = Release|Any CPU
{11522B0D-BF31-42D5-8FC5-41E58F319AF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11522B0D-BF31-42D5-8FC5-41E58F319AF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11522B0D-BF31-42D5-8FC5-41E58F319AF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11522B0D-BF31-42D5-8FC5-41E58F319AF9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{811A76CF-1CF6-440F-963B-BBE31BD72A82} = {B39A8919-9F95-48FE-AD7B-76E08B509888} {811A76CF-1CF6-440F-963B-BBE31BD72A82} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{3E908F67-5543-4879-A1DC-08EACE79B3CD} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{5CCB5571-7C30-4E7D-967D-0E2158EBD91F} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {5CCB5571-7C30-4E7D-967D-0E2158EBD91F} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{2905FF23-53FB-45E6-AA49-6AF47A172056} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {2905FF23-53FB-45E6-AA49-6AF47A172056} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{DABFD304-D6A4-4752-8123-C2CCF7AC7831} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{EFB11458-9CDF-41C0-BE4F-44AF45A4CAB8} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {99135EAB-653D-47E4-A378-C96E1278CA44} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C} {3E53A01A-B331-47F3-B828-4A5717E77A24} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C} {6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
@ -748,7 +691,6 @@ Global
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098} {F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098} {29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E} {7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E} = {B39A8919-9F95-48FE-AD7B-76E08B509888} {CBC4FF2F-92D4-420B-BE21-9FE0B930B04E} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
{E1582370-37B3-403C-917F-8209551B1634} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {E1582370-37B3-403C-917F-8209551B1634} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
@ -760,7 +702,6 @@ Global
{3C471044-3640-45E3-B1B2-16D2FF8399EE} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C} {3C471044-3640-45E3-B1B2-16D2FF8399EE} = {E870DCD7-F46A-498D-83FC-D0FD13E0A11C}
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{8C89950F-F5D9-47FC-8066-CBC1EC3DF8FC} = {FF237916-7150-496B-89ED-6CA3292896E7} {8C89950F-F5D9-47FC-8066-CBC1EC3DF8FC} = {FF237916-7150-496B-89ED-6CA3292896E7}
{B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E} = {FF237916-7150-496B-89ED-6CA3292896E7} {B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E} = {FF237916-7150-496B-89ED-6CA3292896E7}
@ -778,10 +719,7 @@ Global
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098} {3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{4A39637C-9338-4925-A4DB-D072E292EC78} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268} {4A39637C-9338-4925-A4DB-D072E292EC78} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{47F8530C-F19B-4B1A-B4D6-EB231522AE5D} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{15B93A4C-1B46-43F6-B534-7B25B6E99932} = {9B9E3891-2366-4253-A952-D08BCEB71098} {15B93A4C-1B46-43F6-B534-7B25B6E99932} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{90B08091-9BBD-4362-B712-E9F2CC62B218} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{75C47156-C5D8-44BC-A5A7-E8657C2248D6} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C810060E-3809-4B74-A125-F11533AF9C1B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {C810060E-3809-4B74-A125-F11533AF9C1B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C692FE73-43DB-49CE-87FC-F03ED61F25C9} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {C692FE73-43DB-49CE-87FC-F03ED61F25C9} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{DDA28789-C21A-4654-86CE-D01E81F095C5} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {DDA28789-C21A-4654-86CE-D01E81F095C5} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
@ -794,10 +732,6 @@ Global
{F47F8316-4D4B-4026-8EF3-16B2CFDA8119} = {FF237916-7150-496B-89ED-6CA3292896E7} {F47F8316-4D4B-4026-8EF3-16B2CFDA8119} = {FF237916-7150-496B-89ED-6CA3292896E7}
{ED976634-B118-43F8-8B26-0279C7A7044F} = {FF237916-7150-496B-89ED-6CA3292896E7} {ED976634-B118-43F8-8B26-0279C7A7044F} = {FF237916-7150-496B-89ED-6CA3292896E7}
{4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {4B8EBBEB-A1AD-49EC-8B69-B93ED15BFA64} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{2999D79E-3C20-4A90-B651-CA7E0AC92D35} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{F83FC908-A4E3-40DE-B4CF-A4BA1E92CDB3} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{DFFBDBF5-5DBE-47ED-9EAE-D40B75AC99E8} = {D1300000-7217-4693-8B0F-57CBD5814302}
{A0B29221-2B6F-4B29-A4D5-2227811B5915} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {B0FD6A48-FBAB-4676-B36A-DE76B0922B12} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{9D6AEF22-221F-4F4B-B335-A4BA510F002C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {9D6AEF22-221F-4F4B-B335-A4BA510F002C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{5BF0C3B8-E595-4940-AB30-2DA206C2F085} = {9D6AEF22-221F-4F4B-B335-A4BA510F002C} {5BF0C3B8-E595-4940-AB30-2DA206C2F085} = {9D6AEF22-221F-4F4B-B335-A4BA510F002C}
@ -810,6 +744,11 @@ Global
{255614F5-CB64-4ECA-A026-E0B1AF6A2EF4} = {9B9E3891-2366-4253-A952-D08BCEB71098} {255614F5-CB64-4ECA-A026-E0B1AF6A2EF4} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{DE3C28DD-B602-4750-831D-345102A54CA0} = {9B9E3891-2366-4253-A952-D08BCEB71098} {DE3C28DD-B602-4750-831D-345102A54CA0} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{14342787-B4EF-4076-8C91-BA6C523DE8DF} = {9B9E3891-2366-4253-A952-D08BCEB71098} {14342787-B4EF-4076-8C91-BA6C523DE8DF} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{A175EFAE-476C-4DAA-87D5-742C18CFCC27} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{09EC467F-0F25-4E6F-A836-2BAEC8F6AB0C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{342D2657-2F84-493C-B74B-9D2CAE5D9DAB} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{26918642-829D-4FA2-B60A-BE8D83F4E063} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{11522B0D-BF31-42D5-8FC5-41E58F319AF9} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

4
CONTRIBUTING.md

@ -10,7 +10,7 @@ A bug fix will ideally be accompanied by tests. There are a few types of tests:
- Unit tests are for issues that aren't related to platform features. These tests are located in the `tests` directly, categorised by the assembly which they're testing. - Unit tests are for issues that aren't related to platform features. These tests are located in the `tests` directly, categorised by the assembly which they're testing.
- Integration tests are for issues that are related to platform features (for example fixing a bug with Window resizing). These tests are located in the `tests/Avalonia.IntegrationTests.Appium` directory. Integration tests should be run on Windows and macOS. See the readme in that directory for more information - Integration tests are for issues that are related to platform features (for example fixing a bug with Window resizing). These tests are located in the `tests/Avalonia.IntegrationTests.Appium` directory. Integration tests should be run on Windows and macOS. See the readme in that directory for more information
- Render tests are for issues with rendering. These tests are located in `tests/Avalonia.RenderTests` with separate project files for Skia and Direct2D. The Direct2D backend is currently mostly unmaintained so render tests that just run on Skia are acceptable - Render tests are for issues with rendering. These tests are located in `tests/Avalonia.RenderTests` and are imported in the `Avalonia.Skia.RenderTests` project.
It's not always feasible to accompany a bug fix with a test, but doing so will speed up the review process. It's not always feasible to accompany a bug fix with a test, but doing so will speed up the review process.
@ -88,4 +88,4 @@ Render tests should describe what the produced image is:
## Code of Conduct ## Code of Conduct
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
For more information see the [Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct) For more information see the [Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct)

4
Directory.Build.props

@ -4,11 +4,11 @@
<Import Project="$(MSBuildThisFileDirectory)/build/WarnAsErrors.props" /> <Import Project="$(MSBuildThisFileDirectory)/build/WarnAsErrors.props" />
<PropertyGroup> <PropertyGroup>
<PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)build-intermediate/nuget</PackageOutputPath> <PackageOutputPath Condition="'$(PackageOutputPath)' == ''">$(MSBuildThisFileDirectory)build-intermediate/nuget</PackageOutputPath>
<AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)\src\tools\Avalonia.Designer.HostApp\bin\$(Configuration)\netstandard2.0\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath> <AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)\src\tools\Avalonia.Designer.HostApp\bin\$(Configuration)\$(AvsCurrentTargetFramework)\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath>
<!-- https://github.com/dotnet/msbuild/issues/2661 --> <!-- https://github.com/dotnet/msbuild/issues/2661 -->
<AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies> <AddSyntheticProjectReferencesForSolutionDependencies>false</AddSyntheticProjectReferencesForSolutionDependencies>
<RunApiCompat>False</RunApiCompat> <RunApiCompat>False</RunApiCompat>
<LangVersion>12</LangVersion> <LangVersion>14.0</LangVersion>
<CreateHardLinksForCopyAdditionalFilesIfPossible>true</CreateHardLinksForCopyAdditionalFilesIfPossible> <CreateHardLinksForCopyAdditionalFilesIfPossible>true</CreateHardLinksForCopyAdditionalFilesIfPossible>
<CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>true</CreateHardLinksForCopyFilesToOutputDirectoryIfPossible> <CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>true</CreateHardLinksForCopyFilesToOutputDirectoryIfPossible>
<CreateHardLinksForCopyLocalIfPossible>true</CreateHardLinksForCopyLocalIfPossible> <CreateHardLinksForCopyLocalIfPossible>true</CreateHardLinksForCopyLocalIfPossible>

16
NuGet.Config

@ -3,7 +3,19 @@
<configuration> <configuration>
<packageSources> <packageSources>
<clear /> <clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="skiasharp" value="https://aka.ms/skiasharp-eap/index.json" /> <add key="azure-dotnet10-transport" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet10-transport/nuget/v3/index.json" />
</packageSources> </packageSources>
<packageSourceMapping>
<clear />
</packageSourceMapping>
<auditSources>
<clear />
</auditSources>
<disabledPackageSources>
<clear />
</disabledPackageSources>
<fallbackPackageFolders>
<clear />
</fallbackPackageFolders>
</configuration> </configuration>

22
api/Avalonia.Android.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>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.AvaloniaMainActivity`1</Target>
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Android.AndroidViewControlHandle.get_HandleDescriptor</Target>
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.Android.AndroidViewControlHandle</Target>
<Left>baseline/net8.0-android34.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
</Suppressions>

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.JSObjectControlHandle.get_Handle</Target>
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Browser.JSObjectControlHandle.get_HandleDescriptor</Target>
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.Browser.JSObjectControlHandle</Target>
<Left>baseline/net8.0-browser1.0/Avalonia.Browser.dll</Left>
<Right>target/net8.0-browser1.0/Avalonia.Browser.dll</Right>
</Suppression>
</Suppressions>

10
api/Avalonia.FreeDesktop.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>CP0001</DiagnosticId>
<Target>T:Tmds.DBus.SourceGenerator.PropertyChanges`1</Target>
<Left>baseline/netstandard2.0/Avalonia.FreeDesktop.dll</Left>
<Right>target/netstandard2.0/Avalonia.FreeDesktop.dll</Right>
</Suppression>
</Suppressions>

16
api/Avalonia.Skia.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>CP0002</DiagnosticId>
<Target>M:Avalonia.Skia.SkiaSharpExtensions.ToSKFilterQuality(Avalonia.Media.Imaging.BitmapInterpolationMode)</Target>
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaGpuWithPlatformGraphicsContext.TryGetGrContext</Target>
<Left>baseline/netstandard2.0/Avalonia.Skia.dll</Left>
<Right>target/netstandard2.0/Avalonia.Skia.dll</Right>
</Suppression>
</Suppressions>

16
api/Avalonia.Themes.Fluent.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>CP0007</DiagnosticId>
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
</Suppressions>

214
api/Avalonia.Win32.nupkg.xml

@ -1,214 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.DockPosition</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IDockProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IExpandCollapseProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IGridItemProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IGridProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IInvokeProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IMultipleViewProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRangeValueProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderAdviseEvents</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderFragment</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderFragmentRoot</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderSimple</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IRawElementProviderSimple2</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IScrollItemProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IScrollProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ISelectionItemProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ISelectionProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ISynchronizedInputProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ITableItemProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ITableProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ITextProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ITextRangeProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IToggleProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ITransformProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IValueProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.IWindowProvider</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.NavigateDirection</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.ProviderOptions</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.RowOrColumnMajor</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.SupportedTextSelection</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.SynchronizedInputType</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.TextPatternRangeEndpoint</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.TextUnit</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.WindowInteractionState</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Win32.Interop.Automation.WindowVisualState</Target>
<Left>baseline/netstandard2.0/Avalonia.Win32.dll</Left>
<Right>target/netstandard2.0/Avalonia.Win32.dll</Right>
</Suppression>
</Suppressions>

16
api/Avalonia.iOS.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>CP0002</DiagnosticId>
<Target>M:Avalonia.iOS.UIViewControlHandle.get_HandleDescriptor</Target>
<Left>baseline/net8.0-tvos17.0/Avalonia.iOS.dll</Left>
<Right>target/net8.0-tvos17.0/Avalonia.iOS.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.iOS.UIViewControlHandle</Target>
<Left>baseline/net8.0-tvos17.0/Avalonia.iOS.dll</Left>
<Right>target/net8.0-tvos17.0/Avalonia.iOS.dll</Right>
</Suppression>
</Suppressions>

272
api/Avalonia.nupkg.xml

@ -1,272 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids --> <!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Controls.PseudolassesExtensions</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.CastTypePropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.ChildTraversalPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.EnsureTypePropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.IPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPath</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPathBuilder</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Data.Core.PropertyPropertyPathElement</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Utilities.CharacterReader</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Utilities.IdentifierParser</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Utilities.KeywordParser</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Utilities.StyleClassParser</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_HasActivator</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_IsActive</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.AppliedStyle.get_Style</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.StyledElementExtensions.GetStyleDiagnostics(Avalonia.StyledElement)</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.StyleDiagnostics.#ctor(System.Collections.Generic.IReadOnlyList{Avalonia.Diagnostics.AppliedStyle})</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Diagnostics.StyleDiagnostics.get_AppliedStyles</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target> <Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> <Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> <Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.get_IsCompleted</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.GetAwaiter</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.GetResult</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression> </Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable.OnCompleted(System.Action)</Target> <Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> <Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> <Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression> </Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable`1.GetAwaiter</Target> <Target>M:Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left> <Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right> <Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Threading.DispatcherPriorityAwaitable`1.GetResult</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Controls.Primitives.IPopupHost.ConfigurePosition(Avalonia.Visual,Avalonia.Controls.PlacementMode,Avalonia.Point,Avalonia.Controls.Primitives.PopupPositioning.PopupAnchor,Avalonia.Controls.Primitives.PopupPositioning.PopupGravity,Avalonia.Controls.Primitives.PopupPositioning.PopupPositionerConstraintAdjustment,System.Nullable{Avalonia.Rect})</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression> </Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Controls.Screens.#ctor(Avalonia.Platform.IScreenImpl)</Target> <Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(Avalonia.Platform.PlatformThemeVariant)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> <Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> <Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Input.Platform.IClipboard.FlushAsync</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Input.Platform.IClipboard.TryGetInProcessDataObjectAsync</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Platform.Storage.IStorageFolder.GetFileAsync(System.String)</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Platform.Storage.IStorageFolder.GetFolderAsync(System.String)</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Controls.Notifications.IManagedNotificationManager.Close(System.Object)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Controls.Notifications.INotificationManager.Close(Avalonia.Controls.Notifications.INotification)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Controls.Notifications.INotificationManager.CloseAll</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Controls.Primitives.IPopupHost.ConfigurePosition(Avalonia.Controls.Primitives.PopupPositioning.PopupPositionRequest)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Controls.Primitives.IPopupHost.TakeFocus</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression> </Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0006</DiagnosticId> <DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplayEdgeToEdgePreference</Target> <Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(System.Nullable{Avalonia.Platform.PlatformThemeVariant})</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> <Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> <Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression> </Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0006</DiagnosticId> <DiagnosticId>CP0006</DiagnosticId>
<Target>P:Avalonia.Controls.Platform.IInsetsManager.DisplaysEdgeToEdge</Target> <Target>M:Avalonia.Platform.ITopLevelImpl.SetFrameThemeVariant(System.Nullable{Avalonia.Platform.PlatformThemeVariant})</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left> <Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right> <Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0007</DiagnosticId>
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable`1</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Avalonia.Threading.DispatcherPriorityAwaitable`1</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0009</DiagnosticId>
<Target>T:Avalonia.Diagnostics.StyleDiagnostics</Target>
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0009</DiagnosticId>
<Target>T:Avalonia.Controls.Screens</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0012</DiagnosticId>
<Target>M:Avalonia.Controls.Button.OnAccessKey(Avalonia.Interactivity.RoutedEventArgs)</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression> </Suppression>
</Suppressions> </Suppressions>

28
azure-pipelines-integrationtests.yml

@ -5,13 +5,13 @@ jobs:
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime' displayName: 'Use .NET 8.0 Runtime'
inputs: inputs:
packageType: runtime packageType: runtime
version: 6.0.x version: 8.0.x
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -25,16 +25,16 @@ jobs:
arch="arm64" arch="arm64"
fi fi
git clean -ffdx git clean -ffdx
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
pkill node pkill node
pkill testmanagerd pkill testmanagerd
appium > appium.out & appium > appium.out &
pkill IntegrationTestApp pkill IntegrationTestApp
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
./build.sh CompileNative ./build.sh CompileNative
rm -rf $(osascript -e "POSIX path of (path to application id \"net.avaloniaui.avalonia.integrationtestapp\")") rm -rf $(osascript -e "POSIX path of (path to application id \"net.avaloniaui.avalonia.integrationtestapp\")")
pkill IntegrationTestApp pkill IntegrationTestApp
./samples/IntegrationTestApp/bundle.sh ./samples/IntegrationTestApp/bundle.sh
open -n ./samples/IntegrationTestApp/bin/Debug/net8.0/osx-$arch/publish/IntegrationTestApp.app open -n ./samples/IntegrationTestApp/bin/Debug/net10.0/osx-$arch/publish/IntegrationTestApp.app
pkill IntegrationTestApp pkill IntegrationTestApp
displayName: 'Build IntegrationTestApp' displayName: 'Build IntegrationTestApp'
@ -56,17 +56,17 @@ jobs:
- job: Windows - job: Windows
pool: pool:
vmImage: 'windows-2022' vmImage: 'windows-2025'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime' displayName: 'Use .NET 8.0 Runtime'
inputs: inputs:
packageType: runtime packageType: runtime
version: 6.0.x version: 8.0.x
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -87,10 +87,16 @@ jobs:
displayName: 'Build test project' displayName: 'Build test project'
inputs: inputs:
command: 'build' command: 'build'
projects: 'tests\Avalonia.IntegrationTests.Appium\Avalonia.IntegrationTests.Appium.csproj' projects: 'tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj'
- task: DotNetCoreCLI@2
displayName: 'Run Win32 Integration Tests'
inputs:
command: 'run'
projects: 'tests/Avalonia.IntegrationTests.Win32/Avalonia.IntegrationTests.Win32.csproj'
- task: VSTest@2 - task: VSTest@2
displayName: 'Run Integration Tests' displayName: 'Run Appium Integration Tests'
inputs: inputs:
testAssemblyVer2: '**\bin\**\Avalonia.IntegrationTests.Appium.dll' testAssemblyVer2: '**\bin\**\Avalonia.IntegrationTests.Appium.dll'
runSettingsFile: 'tests\Avalonia.IntegrationTests.Appium\record-video.runsettings' runSettingsFile: 'tests\Avalonia.IntegrationTests.Appium\record-video.runsettings'

34
azure-pipelines.yml

@ -2,12 +2,12 @@ jobs:
- job: GetPRNumber - job: GetPRNumber
pool: pool:
vmImage: 'ubuntu-22.04' vmImage: 'ubuntu-24.04'
variables: variables:
SolutionDir: '$(Build.SourcesDirectory)' SolutionDir: '$(Build.SourcesDirectory)'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -23,16 +23,16 @@ jobs:
- job: Linux - job: Linux
pool: pool:
vmImage: 'ubuntu-22.04' vmImage: 'ubuntu-24.04'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime' displayName: 'Use .NET 8.0 Runtime'
inputs: inputs:
packageType: runtime packageType: runtime
version: 6.0.x version: 8.0.x
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -62,16 +62,16 @@ jobs:
variables: variables:
SolutionDir: '$(Build.SourcesDirectory)' SolutionDir: '$(Build.SourcesDirectory)'
pool: pool:
vmImage: 'macos-13' vmImage: 'macos-15'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime' displayName: 'Use .NET 8.0 Runtime'
inputs: inputs:
packageType: runtime packageType: runtime
version: 6.0.x version: 8.0.x
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -95,11 +95,11 @@ jobs:
inputs: inputs:
actions: 'build' actions: 'build'
scheme: '' scheme: ''
sdk: 'macosx13.0' sdk: 'macosx26.0'
configuration: 'Release' configuration: 'Release'
xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace' xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
xcodeVersion: 'specifyPath' # Options: 8, 9, default, specifyPath xcodeVersion: 'specifyPath' # Options: 8, 9, default, specifyPath
xcodeDeveloperDir: '/Applications/Xcode_14.1.app/Contents/Developer' xcodeDeveloperDir: '/Applications/Xcode_26.0.app/Contents/Developer'
args: '-derivedDataPath ./' args: '-derivedDataPath ./'
- task: CmdLine@2 - task: CmdLine@2
@ -134,18 +134,18 @@ jobs:
- job: Windows - job: Windows
pool: pool:
vmImage: 'windows-2022' vmImage: 'windows-2025'
variables: variables:
SolutionDir: '$(Build.SourcesDirectory)' SolutionDir: '$(Build.SourcesDirectory)'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 6.0 Runtime' displayName: 'Use .NET 8.0 Runtime'
inputs: inputs:
packageType: runtime packageType: runtime
version: 6.0.x version: 8.0.x
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET 8.0 SDK' displayName: 'Use .NET 10.0 SDK'
inputs: inputs:
packageType: sdk packageType: sdk
useGlobalJson: true useGlobalJson: true
@ -160,7 +160,7 @@ jobs:
displayName: 'Install Nuke' displayName: 'Install Nuke'
inputs: inputs:
script: | script: |
dotnet tool install --global Nuke.GlobalTool --version 6.2.1 dotnet tool install --global Nuke.GlobalTool --version 9.0.4
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Run Nuke' displayName: 'Run Nuke'

2
build/AnalyzerProject.targets

@ -6,7 +6,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all"/> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" PrivateAssets="all"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.5.0" PrivateAssets="all" /> <PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.5.0" PrivateAssets="all" />
</ItemGroup> </ItemGroup>

12
build/Base.props

@ -1,12 +1,8 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- '!NET6_0_OR_GREATER' equivalent --> <!-- '!NET8_0_OR_GREATER' equivalent -->
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="System.Memory" Version="4.5.5" />
</ItemGroup>
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
</ItemGroup>
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))"> <ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '8.0')))">
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" /> <PackageReference Include="System.Memory" Version="4.5.5" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="9.0.10" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.10" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
build/DevSingleProject.targets

@ -9,8 +9,6 @@
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" Condition="'$(_AvaloniaAndroidTarget)' == 'true'" /> <ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" Condition="'$(_AvaloniaAndroidTarget)' == 'true'" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\iOS\Avalonia.iOS\Avalonia.iOS.csproj" Condition="'$(_AvaloniaIOSTarget)' == 'true'" /> <ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\iOS\Avalonia.iOS\Avalonia.iOS.csproj" Condition="'$(_AvaloniaIOSTarget)' == 'true'" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Browser\Avalonia.Browser\Avalonia.Browser.csproj" Condition="'$(_AvaloniaBrowserTarget)' == 'true'" /> <ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Browser\Avalonia.Browser\Avalonia.Browser.csproj" Condition="'$(_AvaloniaBrowserTarget)' == 'true'" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Tizen\Avalonia.Tizen\Avalonia.Tizen.csproj" Condition="'$(_AvaloniaTizenTarget)' == 'true'" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Tizen\Avalonia.Tizen\Avalonia.Tizen.csproj" Condition="'$(_AvaloniaTizenTarget)' == 'true'" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" Condition="'$(_AvaloniaDesktopTarget)' == 'true'" /> <ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" Condition="'$(_AvaloniaDesktopTarget)' == 'true'" />
</ItemGroup> </ItemGroup>

6
build/HarfBuzzSharp.props

@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="HarfBuzzSharp" Version="8.3.1.1" /> <PackageReference Include="HarfBuzzSharp" Version="8.3.1.2" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.1" /> <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="8.3.1.2" />
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.1" /> <PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="8.3.1.2" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
build/ImageSharp.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.10" /> <PackageReference Include="SixLabors.ImageSharp" Version="2.1.12" />
</ItemGroup> </ItemGroup>
</Project> </Project>

5
build/JetBrains.dotMemoryUnit.props

@ -1,5 +0,0 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="JetBrains.DotMemoryUnit" Version="3.2.20220510" />
</ItemGroup>
</Project>

2
build/Microsoft.Reactive.Testing.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Reactive.Testing" Version="4.1.6" /> <PackageReference Include="Microsoft.Reactive.Testing" Version="6.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

2
build/Moq.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="Moq" Version="4.18.4" /> <PackageReference Include="Moq" Version="4.20.72" />
</ItemGroup> </ItemGroup>
</Project> </Project>

5
build/ReactiveUI.props

@ -1,5 +0,0 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="ReactiveUI" Version="20.1.1" />
</ItemGroup>
</Project>

2
build/Rx.props

@ -1,5 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Reactive" Version="6.0.1" /> <PackageReference Include="System.Reactive" Version="6.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

1
build/SharedVersion.props

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

6
build/SkiaSharp.props

@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="SkiaSharp" Version="3.119.0" /> <PackageReference Include="SkiaSharp" Version="3.119.1" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="3.119.0" /> <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="3.119.1" />
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.0" /> <PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="3.119.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

4
build/SourceLink.props

@ -14,10 +14,6 @@
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
</ItemGroup>
<!-- Workaround for https://github.com/dotnet/sdk/issues/11105 --> <!-- Workaround for https://github.com/dotnet/sdk/issues/11105 -->
<ItemGroup> <ItemGroup>
<SourceRoot Include="$([MSBuild]::EnsureTrailingSlash($(NuGetPackageRoot)))" Condition="'$(NuGetPackageRoot)' != ''" /> <SourceRoot Include="$([MSBuild]::EnsureTrailingSlash($(NuGetPackageRoot)))" Condition="'$(NuGetPackageRoot)' != ''" />

19
build/TargetFrameworks.props

@ -1,19 +1,17 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<AvsCurrentTargetFramework>net8.0</AvsCurrentTargetFramework> <AvsCurrentTargetFramework>net10.0</AvsCurrentTargetFramework>
<AvsCurrentWindowsTargetFramework>$(AvsCurrentTargetFramework)-windows</AvsCurrentWindowsTargetFramework> <AvsCurrentWindowsTargetFramework>$(AvsCurrentTargetFramework)-windows</AvsCurrentWindowsTargetFramework>
<AvsCurrentMacOSTargetFramework>$(AvsCurrentTargetFramework)-macos</AvsCurrentMacOSTargetFramework> <AvsCurrentMacOSTargetFramework>$(AvsCurrentTargetFramework)-macos</AvsCurrentMacOSTargetFramework>
<AvsCurrentAndroidTargetFramework>$(AvsCurrentTargetFramework)-android34.0</AvsCurrentAndroidTargetFramework> <AvsCurrentAndroidTargetFramework>$(AvsCurrentTargetFramework)-android36.0</AvsCurrentAndroidTargetFramework>
<AvsCurrentMacCatalystTargetFramework>$(AvsCurrentTargetFramework)-maccatalyst17.0</AvsCurrentMacCatalystTargetFramework> <AvsCurrentMacCatalystTargetFramework>$(AvsCurrentTargetFramework)-maccatalyst26.0</AvsCurrentMacCatalystTargetFramework>
<AvsCurrentIOSTargetFramework>$(AvsCurrentTargetFramework)-ios17.0</AvsCurrentIOSTargetFramework> <AvsCurrentIOSTargetFramework>$(AvsCurrentTargetFramework)-ios26.0</AvsCurrentIOSTargetFramework>
<AvsCurrentTvOSTargetFramework>$(AvsCurrentTargetFramework)-tvos17.0</AvsCurrentTvOSTargetFramework> <AvsCurrentTvOSTargetFramework>$(AvsCurrentTargetFramework)-tvos26.0</AvsCurrentTvOSTargetFramework>
<AvsCurrentBrowserTargetFramework>$(AvsCurrentTargetFramework)-browser</AvsCurrentBrowserTargetFramework> <AvsCurrentBrowserTargetFramework>$(AvsCurrentTargetFramework)-browser</AvsCurrentBrowserTargetFramework>
<AvsCurrentTizenTargetFramework>$(AvsCurrentTargetFramework)-tizen</AvsCurrentTizenTargetFramework>
<AvsCurrentTizenTargetSdk>8.0.155</AvsCurrentTizenTargetSdk>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(AvsSkipBuildingLegacyTargetFrameworks)' != 'True'"> <PropertyGroup Condition="'$(AvsSkipBuildingLegacyTargetFrameworks)' != 'True'">
<AvsLegacyTargetFrameworks>net6.0</AvsLegacyTargetFrameworks> <AvsLegacyTargetFrameworks>net8.0</AvsLegacyTargetFrameworks>
<AvsLegacyWindowsTargetFrameworks>net6.0-windows</AvsLegacyWindowsTargetFrameworks> <AvsLegacyWindowsTargetFrameworks>net8.0-windows</AvsLegacyWindowsTargetFrameworks>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
@ -22,8 +20,7 @@
<AvsMinSupportedIOSVersion>13.0</AvsMinSupportedIOSVersion> <AvsMinSupportedIOSVersion>13.0</AvsMinSupportedIOSVersion>
<AvsMinSupportedTvOSVersion>13.0</AvsMinSupportedTvOSVersion> <AvsMinSupportedTvOSVersion>13.0</AvsMinSupportedTvOSVersion>
<AvsMinSupportedMacCatalystVersion>13.1</AvsMinSupportedMacCatalystVersion> <AvsMinSupportedMacCatalystVersion>13.1</AvsMinSupportedMacCatalystVersion>
<AvsMinSupportedTizenVersion>6.5</AvsMinSupportedTizenVersion> <AvsMinSupportedAndroidVersion>24.0</AvsMinSupportedAndroidVersion>
<AvsMinSupportedAndroidVersion>21.0</AvsMinSupportedAndroidVersion>
<!-- Desktop OS min version is not set in any of ours backends, but only used in some samples. --> <!-- Desktop OS min version is not set in any of ours backends, but only used in some samples. -->
<!-- Avalonia technically supports 10.12. --> <!-- Avalonia technically supports 10.12. -->
<AvsMinSupportedMacOsVersion>10.15</AvsMinSupportedMacOsVersion> <AvsMinSupportedMacOsVersion>10.15</AvsMinSupportedMacOsVersion>

5
build/UnitTests.NetCore.targets

@ -3,7 +3,4 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
</PropertyGroup> </PropertyGroup>
<ItemGroup> </Project>
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup>
</Project>

18
build/XUnit.props

@ -1,14 +1,14 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="xunit" Version="2.9.2" /> <PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.assert" Version="2.9.2" /> <PackageReference Include="xunit.assert" Version="2.9.3" />
<PackageReference Include="xunit.core" Version="2.9.2" /> <PackageReference Include="xunit.core" Version="2.9.3" />
<PackageReference Include="xunit.extensibility.core" Version="2.9.2" /> <PackageReference Include="xunit.extensibility.core" Version="2.9.3" />
<PackageReference Include="xunit.extensibility.execution" Version="2.9.2" /> <PackageReference Include="xunit.extensibility.execution" Version="2.9.3" />
<PackageReference Include="xunit.runner.console" Version="2.9.2" /> <PackageReference Include="xunit.runner.console" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" Condition="'$(TargetFramework)' != 'netstandard2.0'" /> <PackageReference Include="xunit.runner.visualstudio" Version="3.1.5" Condition="'$(TargetFramework)' != 'netstandard2.0'" />
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" /> <PackageReference Include="Xunit.SkippableFact" Version="1.5.23" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)\avalonia.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)\avalonia.snk</AssemblyOriginatorKeyFile>

10
dirs.proj

@ -9,23 +9,17 @@
<ProjectReference Remove="**/*.shproj" /> <ProjectReference Remove="**/*.shproj" />
<!-- Exclude iOS, Android and Browser samples from build --> <!-- Exclude iOS, Android and Browser samples from build -->
<ProjectReference Remove="samples/*.iOS/*.csproj" /> <ProjectReference Remove="samples/*.iOS/*.csproj" />
<ProjectReference Remove="samples/*.tvOS/*.csproj" />
<ProjectReference Remove="samples/*.MacCatalyst/*.csproj" />
<ProjectReference Remove="samples/*.Android/*.csproj" /> <ProjectReference Remove="samples/*.Android/*.csproj" />
<ProjectReference Remove="samples/*.Browser/*.csproj" /> <ProjectReference Remove="samples/*.Browser/*.csproj" />
<ProjectReference Remove="samples/*.Blazor/*.csproj" />
<ProjectReference Remove="samples/*.Tizen/*.csproj" />
<ProjectReference Remove="samples/SingleProjectSandbox/*.csproj" /> <ProjectReference Remove="samples/SingleProjectSandbox/*.csproj" />
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))"> <ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))">
<!-- Build mobile backends only on Windows, where we have installed android workload --> <!-- Build mobile backends only on Windows, where we have installed android workload -->
<ProjectReference Remove="src/Android/**/*.*proj" /> <ProjectReference Remove="src/Android/**/*.*proj" />
<ProjectReference Remove="src/iOS/**/*.*proj" /> <ProjectReference Remove="src/iOS/**/*.*proj" />
<ProjectReference Remove="src/Tizen/**/*.*proj" />
</ItemGroup>
<ItemGroup Condition="'$(SkipObscurePlatforms)' == 'True'">
<ProjectReference Remove="**/*Tizen/**/*.*proj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

2
docs/api-compat.md

@ -29,4 +29,4 @@ API changes are validated against a **baseline version**—the reference point f
## Additional Resources ## Additional Resources
- [API Validation Tool Implementation](https://github.com/AvaloniaUI/Avalonia/pull/12072) - Pull request that introduced this feature - [API Validation Tool Implementation](https://github.com/AvaloniaUI/Avalonia/pull/12072) - Pull request that introduced this feature

9
docs/build.md

@ -33,7 +33,7 @@ curl -sSL https://raw.githubusercontent.com/Samsung/Tizen.NET/main/workload/scri
## Build and Run Avalonia ## Build and Run Avalonia
```bash ```bash
cd samples\ControlCatalog.NetCore cd samples\ControlCatalog.Desktop
dotnet restore dotnet restore
dotnet run dotnet run
``` ```
@ -47,7 +47,7 @@ If you want to open Avalonia in Visual Studio you have two options:
Avalonia requires Visual Studio 2022 or newer. The free Visual Studio Community edition works fine. Avalonia requires Visual Studio 2022 or newer. The free Visual Studio Community edition works fine.
Build and run `ControlCatalog.NetCore` project to see the sample application. Build and run `ControlCatalog.Desktop` project to see the sample application.
### Visual Studio Troubleshooting ### Visual Studio Troubleshooting
@ -71,6 +71,9 @@ And run tests:
Or if you need to create nuget packages as well (it will compile and run tests automatically): Or if you need to create nuget packages as well (it will compile and run tests automatically):
`nuke --target Package --configuration Release` `nuke --target Package --configuration Release`
Alternatively, you can run nuke build direclty without installing Nuke global tool:
`dotnet run --project nukebuild/_build.csproj -- --configuration Debug`
# Linux/macOS # Linux/macOS
It's *not* possible to build the *whole* project on Linux/macOS. You can only build the subset targeting .NET Standard and .NET Core (which is, however, sufficient to get UI working on Linux/macOS). If you want to something that involves changing platform-specific APIs you'll need a Windows machine. It's *not* possible to build the *whole* project on Linux/macOS. You can only build the subset targeting .NET Standard and .NET Core (which is, however, sufficient to get UI working on Linux/macOS). If you want to something that involves changing platform-specific APIs you'll need a Windows machine.
@ -108,4 +111,4 @@ It is possible to run some .NET Framework samples and tests using .NET Framework
## Building Avalonia into a local NuGet cache ## Building Avalonia into a local NuGet cache
See [Building Local NuGet Packages](nuget.md) See [Building Local NuGet Packages](nuget.md)

2
docs/porting-code-from-3rd-party-sources.md

@ -9,4 +9,4 @@ When porting code or adapting code from other projects with a MIT compatible lic
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation. // Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
``` ```
If the file is a port of a specific commit of file from a 3rd party source, then consider including a permalink to the source file. If the file is a port of a specific commit of file from a 3rd party source, then consider including a permalink to the source file.

2
external/XamlX

@ -1 +1 @@
Subproject commit 83567b8a50bbf612a0b1420a3dc6d8e8ebee2399 Subproject commit c32d3040e536ae9768233ea5a445697632578bd0

2
global.json

@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "8.0.411", "version": "10.0.101",
"rollForward": "latestFeature" "rollForward": "latestFeature"
}, },
"msbuild-sdks": { "msbuild-sdks": {

3
native/Avalonia.Native/inc/com.h

@ -28,7 +28,8 @@ typedef DWORD ULONG;
#define E_UNEXPECTED 0x8000FFFFL #define E_UNEXPECTED 0x8000FFFFL
#define E_HANDLE 0x80070006L #define E_HANDLE 0x80070006L
#define E_INVALIDARG 0x80070057L #define E_INVALIDARG 0x80070057L
#define COR_E_INVALIDOPERATION 0x80131509L #define COR_E_INVALIDOPERATION 0x80131509L
#define COR_E_OBJECTDISPOSED 0x80131622L
struct IUnknown struct IUnknown
{ {

5
native/Avalonia.Native/inc/noarc.h

@ -8,4 +8,7 @@ public:
~CppAutoreleasePool(); ~CppAutoreleasePool();
}; };
#define START_ARP_CALL CppAutoreleasePool __autoreleasePool #define START_ARP_CALL CppAutoreleasePool __autoreleasePool
extern void ReleaseNSObject(void* obj);
extern void RetainNSObject(void* obj);
extern uint64_t GetRetainCountForNSObject(void* obj);

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

@ -31,6 +31,8 @@
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; }; 1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; }; 1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; }; 1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.mm */; };
1AC7F1432DCA0C2E003A161B /* crapium.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AC7F1422DCA0C2E003A161B /* crapium.mm */; };
1AE55B8C2DC1060E00FD0BB3 /* memhelp.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AE55B8B2DC1060E00FD0BB3 /* memhelp.mm */; };
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; }; 1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; }; 37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; }; 37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
@ -63,6 +65,7 @@
EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; }; EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; };
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = F10084832BFF1F9E0024303E /* TopLevelImpl.h */; }; F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = F10084832BFF1F9E0024303E /* TopLevelImpl.h */; };
F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = F10084852BFF1FB40024303E /* TopLevelImpl.mm */; }; F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = F10084852BFF1FB40024303E /* TopLevelImpl.mm */; };
F931F8682E2D43A7004E081E /* clipboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F931F8672E2D43A4004E081E /* clipboard.h */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -90,6 +93,9 @@
1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = "<group>"; }; 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = "<group>"; };
1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = "<group>"; }; 1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = "<group>"; };
1AC7F1422DCA0C2E003A161B /* crapium.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objcpp; path = crapium.mm; sourceTree = "<group>"; };
1AC7F1442DCA0D6A003A161B /* crapium.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = crapium.h; sourceTree = "<group>"; };
1AE55B8B2DC1060E00FD0BB3 /* memhelp.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = memhelp.mm; sourceTree = "<group>"; };
1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = "<group>"; }; 1AFD334023E03C4F0042899B /* controlhost.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = controlhost.mm; sourceTree = "<group>"; };
37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; }; 37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; };
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; }; 379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
@ -130,6 +136,7 @@
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = "<group>"; }; EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = "<group>"; };
F10084832BFF1F9E0024303E /* TopLevelImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLevelImpl.h; sourceTree = "<group>"; }; F10084832BFF1F9E0024303E /* TopLevelImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TopLevelImpl.h; sourceTree = "<group>"; };
F10084852BFF1FB40024303E /* TopLevelImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TopLevelImpl.mm; sourceTree = "<group>"; }; F10084852BFF1FB40024303E /* TopLevelImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TopLevelImpl.mm; sourceTree = "<group>"; };
F931F8672E2D43A4004E081E /* clipboard.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = clipboard.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -169,6 +176,9 @@
AB7A61E62147C814003C5833 = { AB7A61E62147C814003C5833 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
1AC7F1442DCA0D6A003A161B /* crapium.h */,
1AC7F1422DCA0C2E003A161B /* crapium.mm */,
1AE55B8B2DC1060E00FD0BB3 /* memhelp.mm */,
F10084852BFF1FB40024303E /* TopLevelImpl.mm */, F10084852BFF1FB40024303E /* TopLevelImpl.mm */,
BC7C33832C066F1100945A48 /* AvnAccessibility.h */, BC7C33832C066F1100945A48 /* AvnAccessibility.h */,
BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */, BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */,
@ -189,6 +199,7 @@
1AFD334023E03C4F0042899B /* controlhost.mm */, 1AFD334023E03C4F0042899B /* controlhost.mm */,
5BF943652167AD1D009CAE35 /* cursor.h */, 5BF943652167AD1D009CAE35 /* cursor.h */,
5B21A981216530F500CEE36E /* cursor.mm */, 5B21A981216530F500CEE36E /* cursor.mm */,
F931F8672E2D43A4004E081E /* clipboard.h */,
5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */, 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
1A465D0F246AB61600C5858B /* dnd.mm */, 1A465D0F246AB61600C5858B /* dnd.mm */,
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */, AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
@ -246,6 +257,7 @@
files = ( files = (
37155CE4233C00EB0034DCE9 /* menu.h in Headers */, 37155CE4233C00EB0034DCE9 /* menu.h in Headers */,
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */, F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */,
F931F8682E2D43A7004E081E /* clipboard.h in Headers */,
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */, BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */,
183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */, 183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */,
1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */, 1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */,
@ -329,6 +341,7 @@
523484CA26EA688F00EA0C2C /* trayicon.mm in Sources */, 523484CA26EA688F00EA0C2C /* trayicon.mm in Sources */,
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */, AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */, 1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */,
1AE55B8C2DC1060E00FD0BB3 /* memhelp.mm in Sources */,
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */, 1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */,
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */, BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */,
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */, 37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
@ -349,6 +362,7 @@
ED754D262A97306B0078B4DF /* PlatformRenderTimer.mm in Sources */, ED754D262A97306B0078B4DF /* PlatformRenderTimer.mm in Sources */,
1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */, 1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */,
18391AC16726CBC45856233B /* AvnWindow.mm in Sources */, 18391AC16726CBC45856233B /* AvnWindow.mm in Sources */,
1AC7F1432DCA0C2E003A161B /* crapium.mm in Sources */,
18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */, 18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */,
EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */, EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */,
64B1EA48E308E574685AFB07 /* metal.mm in Sources */, 64B1EA48E308E574685AFB07 /* metal.mm in Sources */,
@ -471,6 +485,7 @@
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib; EXECUTABLE_PREFIX = lib;
HEADER_SEARCH_PATHS = ../../inc; HEADER_SEARCH_PATHS = ../../inc;
MACOSX_DEPLOYMENT_TARGET = 10.13;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Debug; name = Debug;
@ -482,6 +497,7 @@
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
EXECUTABLE_PREFIX = lib; EXECUTABLE_PREFIX = lib;
HEADER_SEARCH_PATHS = ../../inc; HEADER_SEARCH_PATHS = ../../inc;
MACOSX_DEPLOYMENT_TARGET = 10.13;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
}; };
name = Release; name = Release;

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

@ -19,7 +19,6 @@
-(AvnPoint) translateLocalPoint:(AvnPoint)pt; -(AvnPoint) translateLocalPoint:(AvnPoint)pt;
-(void) onClosed; -(void) onClosed;
-(void) setModifiers:(NSEventModifierFlags)modifierFlags; -(void) setModifiers:(NSEventModifierFlags)modifierFlags;
-(void) resetPressedMouseButtons;
-(AvnPlatformResizeReason) getResizeReason; -(AvnPlatformResizeReason) getResizeReason;
-(void) setResizeReason:(AvnPlatformResizeReason)reason; -(void) setResizeReason:(AvnPlatformResizeReason)reason;

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

@ -456,13 +456,12 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
switch(event.buttonNumber) switch(event.buttonNumber)
{ {
case 2: case 2:
case 3:
[self mouseEvent:event withType:MiddleButtonDown]; [self mouseEvent:event withType:MiddleButtonDown];
break; break;
case 4: case 3:
[self mouseEvent:event withType:XButton1Down]; [self mouseEvent:event withType:XButton1Down];
break; break;
case 5: case 4:
[self mouseEvent:event withType:XButton2Down]; [self mouseEvent:event withType:XButton2Down];
break; break;
@ -487,13 +486,12 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
switch(event.buttonNumber) switch(event.buttonNumber)
{ {
case 2: case 2:
case 3:
[self mouseEvent:event withType:MiddleButtonUp]; [self mouseEvent:event withType:MiddleButtonUp];
break; break;
case 4: case 3:
[self mouseEvent:event withType:XButton1Up]; [self mouseEvent:event withType:XButton1Up];
break; break;
case 5: case 4:
[self mouseEvent:event withType:XButton2Up]; [self mouseEvent:event withType:XButton2Up];
break; break;
@ -856,9 +854,10 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id <NSDraggingInfo>)info - (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id <NSDraggingInfo>)info
{ {
auto localPoint = [self convertPoint:[info draggingLocation] toView:self]; NSPoint eventLocation = [info draggingLocation];
auto avnPoint = ToAvnPoint(localPoint); auto viewLocation = [self convertPoint:NSMakePoint(0, 0) toView:nil];
auto point = [self translateLocalPoint:avnPoint]; auto localPoint = NSMakePoint(eventLocation.x - viewLocation.x, viewLocation.y - eventLocation.y);
auto point = ToAvnPoint(localPoint);
auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]]; auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
NSDragOperation nsop = [info draggingSourceOperationMask]; NSDragOperation nsop = [info draggingSourceOperationMask];
@ -868,7 +867,7 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
return NSDragOperationNone; return NSDragOperationNone;
int reffects = (int)parent->TopLevelEvents int reffects = (int)parent->TopLevelEvents
->DragEvent(type, point, modifiers, effects, ->DragEvent(type, point, modifiers, effects,
CreateClipboard([info draggingPasteboard], nil), CreateClipboard([info draggingPasteboard]),
GetAvnDataObjectHandleFromDraggingInfo(info)); GetAvnDataObjectHandleFromDraggingInfo(info));
NSDragOperation ret = static_cast<NSDragOperation>(0); NSDragOperation ret = static_cast<NSDragOperation>(0);
@ -943,7 +942,7 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
auto window = (AvnWindow*)[self window]; auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer]; auto peer = [window automationPeer];
if (!peer->IsRootProvider()) if (peer == nullptr || !peer->IsRootProvider())
return nil; return nil;
auto clientPoint = [window convertPointFromScreen:point]; auto clientPoint = [window convertPointFromScreen:point];
@ -980,6 +979,10 @@ static void ConvertTilt(NSPoint tilt, float* xTilt, float* yTilt)
// of the AvnView. // of the AvnView.
auto window = (AvnWindow*)[self window]; auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer]; auto peer = [window automationPeer];
if (peer == nullptr)
{
return;
}
auto childPeers = peer->GetChildren(); auto childPeers = peer->GetChildren();
auto childCount = childPeers != nullptr ? childPeers->GetCount() : 0; auto childCount = childPeers != nullptr ? childPeers->GetCount() : 0;

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

@ -35,6 +35,7 @@
bool _canBecomeKeyWindow; bool _canBecomeKeyWindow;
bool _isExtended; bool _isExtended;
bool _isTransitioningToFullScreen; bool _isTransitioningToFullScreen;
bool _isTitlebarSession;
AvnMenu* _menu; AvnMenu* _menu;
IAvnAutomationPeer* _automationPeer; IAvnAutomationPeer* _automationPeer;
AvnAutomationNode* _automationNode; AvnAutomationNode* _automationNode;
@ -435,23 +436,28 @@
return; return;
} }
// If the window has been moved into a position where it's "zoomed" // Don't adjust window state during fullscreen transitions
// Then it should be set as Maximized. // as this can interfere with proper decoration restoration
if (window->WindowState() != Maximized && window->IsZoomed()) if(!window->IsTransitioningWindowState())
{ {
window->SetWindowState(Maximized, false); // If the window has been moved into a position where it's "zoomed"
} // Then it should be set as Maximized.
// We should only return the window state to normal if if (window->WindowState() != Maximized && window->IsZoomed())
// the internal window state is maximized, and macOS says {
// the window is no longer zoomed (I.E, the user has moved it) window->SetWindowState(Maximized, false);
// Stage Manager will "move" the window when repositioning it }
// So if the window was "maximized" before, it should stay maximized // We should only return the window state to normal if
else if(window->WindowState() == Maximized && !window->IsZoomed()) // the internal window state is maximized, and macOS says
{ // the window is no longer zoomed (I.E, the user has moved it)
// If we're moving the window while maximized, // Stage Manager will "move" the window when repositioning it
// we need to let macOS handle if it should be resized // So if the window was "maximized" before, it should stay maximized
// And not handle it ourselves. else if(window->WindowState() == Maximized && !window->IsZoomed())
window->SetWindowState(Normal, false); {
// If we're moving the window while maximized,
// we need to let macOS handle if it should be resized
// And not handle it ourselves.
window->SetWindowState(Normal, false);
}
} }
} }
@ -501,68 +507,10 @@
return NO; return NO;
} }
- (void)forwardToAvnView:(NSEvent *)event
{
auto parent = _parent.tryGetWithCast<WindowImpl>();
if (!parent) {
return;
}
switch(event.type) {
case NSEventTypeLeftMouseDown:
[parent->View mouseDown:event];
break;
case NSEventTypeLeftMouseUp:
[parent->View mouseUp:event];
break;
case NSEventTypeLeftMouseDragged:
[parent->View mouseDragged:event];
break;
case NSEventTypeRightMouseDown:
[parent->View rightMouseDown:event];
break;
case NSEventTypeRightMouseUp:
[parent->View rightMouseUp:event];
break;
case NSEventTypeRightMouseDragged:
[parent->View rightMouseDragged:event];
break;
case NSEventTypeOtherMouseDown:
[parent->View otherMouseDown:event];
break;
case NSEventTypeOtherMouseUp:
[parent->View otherMouseUp:event];
break;
case NSEventTypeOtherMouseDragged:
[parent->View otherMouseDragged:event];
break;
case NSEventTypeMouseMoved:
[parent->View mouseMoved:event];
break;
default:
break;
}
}
- (void)sendEvent:(NSEvent *_Nonnull)event - (void)sendEvent:(NSEvent *_Nonnull)event
{ {
// Event-tracking loop for thick titlebar mouse events if (event.type == NSEventTypeLeftMouseDown) {
if (event.type == NSEventTypeLeftMouseDown && [self isPointInTitlebar:event.locationInWindow]) _isTitlebarSession = [self isPointInTitlebar:event.locationInWindow];
{
NSEventMask mask = NSEventMaskLeftMouseDragged | NSEventMaskLeftMouseUp;
NSEvent *ev = event;
while (ev.type != NSEventTypeLeftMouseUp)
{
[self forwardToAvnView:ev];
[super sendEvent:ev];
ev = [NSApp nextEventMatchingMask:mask
untilDate:[NSDate distantFuture]
inMode:NSEventTrackingRunLoopMode
dequeue:YES];
}
[self forwardToAvnView:ev];
[super sendEvent:ev];
return;
} }
[super sendEvent:event]; [super sendEvent:event];
@ -603,6 +551,37 @@
} }
break; break;
case NSEventTypeLeftMouseDragged:
case NSEventTypeMouseMoved:
case NSEventTypeLeftMouseUp:
{
// Usually NSToolbar events are passed natively to AvnView when the mouse is inside the control.
// When a drag operation started in NSToolbar leaves the control region, the view does not get any
// events. We will detect this scenario and pass events ourselves.
if(!_isTitlebarSession || [self isPointInTitlebar:event.locationInWindow])
break;
AvnView* view = parent->View;
if(!view)
break;
if(event.type == NSEventTypeLeftMouseDragged)
{
[view mouseDragged:event];
}
else if(event.type == NSEventTypeMouseMoved)
{
[view mouseMoved:event];
}
else if(event.type == NSEventTypeLeftMouseUp)
{
[view mouseUp:event];
}
}
break;
case NSEventTypeMouseEntered: case NSEventTypeMouseEntered:
{ {
parent->UpdateCursor(); parent->UpdateCursor();
@ -618,6 +597,10 @@
default: default:
break; break;
} }
if(event.type == NSEventTypeLeftMouseUp) {
_isTitlebarSession = NO;
}
} }
} }
@ -627,21 +610,30 @@
- (id _Nullable) accessibilityFocusedUIElement - (id _Nullable) accessibilityFocusedUIElement
{ {
if (![self automationPeer]->IsRootProvider()) auto automationPeer = [self automationPeer];
if (automationPeer == nullptr || !automationPeer->IsRootProvider())
return nil; return nil;
auto focusedPeer = [self automationPeer]->RootProvider_GetFocus();
auto focusedPeer = automationPeer->RootProvider_GetFocus();
if (focusedPeer == nullptr)
return nil;
return [AvnAccessibilityElement acquire:focusedPeer]; return [AvnAccessibilityElement acquire:focusedPeer];
} }
- (NSString * _Nullable) accessibilityIdentifier - (NSString * _Nullable) accessibilityIdentifier
{ {
return GetNSStringAndRelease([self automationPeer]->GetAutomationId()); auto automationPeer = [self automationPeer];
if (automationPeer == nullptr)
return nil;
return GetNSStringAndRelease(automationPeer->GetAutomationId());
} }
- (IAvnAutomationPeer* _Nonnull) automationPeer - (IAvnAutomationPeer* _Nonnull) automationPeer
{ {
auto parent = _parent.tryGet(); auto parent = _parent.tryGet();
if (_automationPeer == nullptr) if (parent && _automationPeer == nullptr)
{ {
_automationPeer = parent->BaseEvents->GetAutomationPeer(); _automationPeer = parent->BaseEvents->GetAutomationPeer();
_automationNode = new AvnAutomationNode(self); _automationNode = new AvnAutomationNode(self);
@ -654,7 +646,8 @@
- (void)raiseChildrenChanged - (void)raiseChildrenChanged
{ {
auto parent = _parent.tryGet(); auto parent = _parent.tryGet();
[parent->View raiseAccessibilityChildrenChanged]; if(parent)
[parent->View raiseAccessibilityChildrenChanged];
} }
- (void)raiseFocusChanged - (void)raiseFocusChanged

2
native/Avalonia.Native/src/OSX/KeyTransform.mm

@ -33,7 +33,7 @@ const KeyInfo keyInfos[] =
{ 0x1A, AvnPhysicalKeyDigit7, AvnKeyD7, '7' }, { 0x1A, AvnPhysicalKeyDigit7, AvnKeyD7, '7' },
{ 0x1C, AvnPhysicalKeyDigit8, AvnKeyD8, '8' }, { 0x1C, AvnPhysicalKeyDigit8, AvnKeyD8, '8' },
{ 0x19, AvnPhysicalKeyDigit9, AvnKeyD9, '9' }, { 0x19, AvnPhysicalKeyDigit9, AvnKeyD9, '9' },
{ 0x18, AvnPhysicalKeyEqual, AvnKeyOemMinus, '-' }, { 0x18, AvnPhysicalKeyEqual, AvnKeyOemPlus, '=' },
{ 0x0A, AvnPhysicalKeyIntlBackslash, AvnKeyOem102, 0 }, { 0x0A, AvnPhysicalKeyIntlBackslash, AvnKeyOem102, 0 },
{ 0x5E, AvnPhysicalKeyIntlRo, AvnKeyOem102, 0 }, { 0x5E, AvnPhysicalKeyIntlRo, AvnKeyOem102, 0 },
{ 0x5D, AvnPhysicalKeyIntlYen, AvnKeyOem5, 0 }, { 0x5D, AvnPhysicalKeyIntlYen, AvnKeyOem5, 0 },

43
native/Avalonia.Native/src/OSX/StorageProvider.mm

@ -320,12 +320,22 @@ public:
} }
auto handler = ^(NSModalResponse result) { auto handler = ^(NSModalResponse result) {
int selectedIndex = -1;
if (panel.accessoryView != nil)
{
auto popup = [panel.accessoryView viewWithTag:kFileTypePopupTag];
if ([popup isKindOfClass:[NSPopUpButton class]])
{
selectedIndex = (int)[(NSPopUpButton*)popup indexOfSelectedItem];
}
}
if(result == NSFileHandlingPanelOKButton) if(result == NSFileHandlingPanelOKButton)
{ {
auto url = [panel URL]; auto url = [panel URL];
auto urls = [NSArray<NSURL*> arrayWithObject:url]; auto urls = [NSArray<NSURL*> arrayWithObject:url];
auto uriStrings = CreateAvnStringArray(urls); auto uriStrings = CreateAvnStringArray(urls);
events->OnCompleted(uriStrings); events->OnCompletedWithFilter(uriStrings, selectedIndex);
[panel orderOut:panel]; [panel orderOut:panel];
@ -338,7 +348,7 @@ public:
return; return;
} }
events->OnCompleted(nullptr); events->OnCompletedWithFilter(nullptr, selectedIndex);
}; };
@ -355,6 +365,35 @@ public:
} }
} }
virtual HRESULT TryResolveFileReferenceUri(IAvnString* fileUriStr, IAvnString** ret) override {
if (ret == nullptr)
return E_POINTER;
if (fileUriStr == nullptr)
{
*ret = nullptr;
return S_OK;
}
auto fileUri = [NSURL URLWithString:GetNSStringAndRelease(fileUriStr)];
if (fileUri == nil)
{
*ret = nullptr;
return S_OK;
}
auto filePathUri = [fileUri filePathURL];
if (fileUri == nil)
{
*ret = nullptr;
return S_OK;
}
*ret = CreateAvnString([filePathUri absoluteString]);
return S_OK;
}
private: private:
NSView* CreateAccessoryView() { NSView* CreateAccessoryView() {
// The label. Add attributes per-OS to match the labels that macOS uses. // The label. Add attributes per-OS to match the labels that macOS uses.

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

@ -60,6 +60,14 @@ public:
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override; virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override; virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override;
virtual HRESULT BeginDragAndDropOperation(
AvnDragDropEffects effects,
AvnPoint point,
IAvnClipboardDataSource* source,
IAvnDndResultCallback* callback,
void* sourceHandle) override;
protected: protected:
NSCursor *cursor; NSCursor *cursor;
virtual void UpdateAppearance(); virtual void UpdateAppearance();

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

@ -6,6 +6,8 @@
#include "TopLevelImpl.h" #include "TopLevelImpl.h"
#include "AvnTextInputMethod.h" #include "AvnTextInputMethod.h"
#include "AvnView.h" #include "AvnView.h"
#include "common.h"
#include "clipboard.h"
TopLevelImpl::~TopLevelImpl() { TopLevelImpl::~TopLevelImpl() {
View = nullptr; View = nullptr;
@ -271,6 +273,66 @@ void TopLevelImpl::UpdateAppearance() {
} }
HRESULT TopLevelImpl::BeginDragAndDropOperation(
AvnDragDropEffects effects,
AvnPoint point,
IAvnClipboardDataSource* source,
IAvnDndResultCallback* callback,
void* sourceHandle)
{
START_COM_CALL;
if (View == NULL)
return E_FAIL;
auto nsevent = [NSApp currentEvent];
auto nseventType = [nsevent type];
// If current event isn't a mouse one (probably due to malfunctioning user app)
// attempt to forge a new one
if (!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
|| (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged))) {
// For TopLevelImpl, we don't have a Window so we use the View's window
auto window = [View window];
if (window != nil) {
NSRect convertRect = [window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto nspoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
CGPoint cgpoint = NSPointToCGPoint(nspoint);
auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
nsevent = [NSEvent eventWithCGEvent:cgevent];
CFRelease(cgevent);
}
}
auto itemCount = source->GetItemCount();
auto draggingItems = [NSMutableArray<NSDraggingItem*> arrayWithCapacity:itemCount];
auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
NSRect dragItemRect = {(float) point.X, (float) point.Y, [dragItemImage size].width, [dragItemImage size].height};
for (auto i = 0; i < itemCount; ++i)
{
auto item = source->GetItem(i);
auto writeableItem = [[WriteableClipboardItem alloc] initWithItem:item source:source];
auto draggingItem = [[NSDraggingItem alloc] initWithPasteboardWriter:writeableItem];
[draggingItem setDraggingFrame:dragItemRect contents:dragItemImage];
[draggingItems addObject:draggingItem];
}
int op = 0;
int ieffects = (int) effects;
if ((ieffects & (int) AvnDragDropEffects::Copy) != 0)
op |= NSDragOperationCopy;
if ((ieffects & (int) AvnDragDropEffects::Link) != 0)
op |= NSDragOperationLink;
if ((ieffects & (int) AvnDragDropEffects::Move) != 0)
op |= NSDragOperationMove;
[View beginDraggingSessionWithItems:draggingItems
event:nsevent
source:CreateDraggingSource((NSDragOperation) op, callback, sourceHandle)];
return S_OK;
}
void TopLevelImpl::SetClientSize(NSSize size){ void TopLevelImpl::SetClientSize(NSSize size){
[View setFrameSize:size]; [View setFrameSize:size];
} }

4
native/Avalonia.Native/src/OSX/WindowBaseImpl.h

@ -69,10 +69,6 @@ public:
virtual HRESULT SetFrameThemeVariant(AvnPlatformThemeVariant variant) override; virtual HRESULT SetFrameThemeVariant(AvnPlatformThemeVariant variant) override;
virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
IAvnClipboard *clipboard, IAvnDndResultCallback *cb,
void *sourceHandle) override;
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override; virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual bool IsModal(); virtual bool IsModal();

45
native/Avalonia.Native/src/OSX/WindowBaseImpl.mm

@ -411,51 +411,6 @@ HRESULT WindowBaseImpl::SetFrameThemeVariant(AvnPlatformThemeVariant variant) {
return S_OK; return S_OK;
} }
HRESULT WindowBaseImpl::BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point, IAvnClipboard *clipboard, IAvnDndResultCallback *cb, void *sourceHandle) {
START_COM_CALL;
auto item = TryGetPasteboardItem(clipboard);
[item setString:@"" forType:GetAvnCustomDataType()];
if (item == nil)
return E_INVALIDARG;
if (View == NULL)
return E_FAIL;
auto nsevent = [NSApp currentEvent];
auto nseventType = [nsevent type];
// If current event isn't a mouse one (probably due to malfunctioning user app)
// attempt to forge a new one
if (!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
|| (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged))) {
NSRect convertRect = [Window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto nspoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
CGPoint cgpoint = NSPointToCGPoint(nspoint);
auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
nsevent = [NSEvent eventWithCGEvent:cgevent];
CFRelease(cgevent);
}
auto dragItem = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
auto dragItemImage = [NSImage imageNamed:NSImageNameMultipleDocuments];
NSRect dragItemRect = {(float) point.X, (float) point.Y, [dragItemImage size].width, [dragItemImage size].height};
[dragItem setDraggingFrame:dragItemRect contents:dragItemImage];
int op = 0;
int ieffects = (int) effects;
if ((ieffects & (int) AvnDragDropEffects::Copy) != 0)
op |= NSDragOperationCopy;
if ((ieffects & (int) AvnDragDropEffects::Link) != 0)
op |= NSDragOperationLink;
if ((ieffects & (int) AvnDragDropEffects::Move) != 0)
op |= NSDragOperationMove;
[View resetPressedMouseButtons];
[View beginDraggingSessionWithItems:@[dragItem] event:nsevent
source:CreateDraggingSource((NSDragOperation) op, cb, sourceHandle)];
return S_OK;
}
bool WindowBaseImpl::IsModal() { bool WindowBaseImpl::IsModal() {
return false; return false;
} }

4
native/Avalonia.Native/src/OSX/WindowImpl.h

@ -87,7 +87,9 @@ BEGIN_INTERFACE_MAP()
bool CanBecomeKeyWindow (); bool CanBecomeKeyWindow ();
bool CanZoom() override { return _isEnabled && _canMaximize; } bool CanZoom() override { return _isEnabled && _canMaximize; }
bool IsTransitioningWindowState() { return _transitioningWindowState; }
protected: protected:
virtual NSWindowStyleMask CalculateStyleMask() override; virtual NSWindowStyleMask CalculateStyleMask() override;
virtual void UpdateAppearance() override; virtual void UpdateAppearance() override;

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

@ -122,7 +122,7 @@
case AutomationSplitButton: return NSAccessibilityPopUpButtonRole; case AutomationSplitButton: return NSAccessibilityPopUpButtonRole;
case AutomationWindow: return NSAccessibilityWindowRole; case AutomationWindow: return NSAccessibilityWindowRole;
case AutomationPane: return NSAccessibilityGroupRole; case AutomationPane: return NSAccessibilityGroupRole;
case AutomationHeader: return NSAccessibilityGroupRole; case AutomationHeader: return @"AXHeading";
case AutomationHeaderItem: return NSAccessibilityButtonRole; case AutomationHeaderItem: return NSAccessibilityButtonRole;
case AutomationTable: return NSAccessibilityTableRole; case AutomationTable: return NSAccessibilityTableRole;
case AutomationTitleBar: return NSAccessibilityGroupRole; case AutomationTitleBar: return NSAccessibilityGroupRole;
@ -133,6 +133,38 @@
} }
} }
- (NSAccessibilitySubrole)accessibilitySubrole
{
auto landmarkType = _peer->GetLandmarkType();
switch (landmarkType) {
case LandmarkBanner: return @"AXLandmarkBanner";
case LandmarkComplementary: return @"AXLandmarkComplementary";
case LandmarkContentInfo: return @"AXLandmarkContentInfo";
case LandmarkRegion: return @"AXLandmarkRegion";
case LandmarkForm: return @"AXLandmarkForm";
case LandmarkMain: return @"AXLandmarkMain";
case LandmarkNavigation: return @"AXLandmarkNavigation";
case LandmarkSearch: return @"AXLandmarkSearch";
default: return NSAccessibilityUnknownSubrole;
}
}
- (NSString *)accessibilityRoleDescription
{
auto landmarkType = _peer->GetLandmarkType();
switch (landmarkType) {
case LandmarkBanner: return @"banner";
case LandmarkComplementary: return @"complementary";
case LandmarkContentInfo: return @"content";
case LandmarkRegion: return @"region";
case LandmarkForm: return @"form";
case LandmarkMain: return @"main";
case LandmarkNavigation: return @"navigation";
case LandmarkSearch: return @"search";
}
return NSAccessibilityRoleDescription([self accessibilityRole], [self accessibilitySubrole]);
}
- (NSString *)accessibilityIdentifier - (NSString *)accessibilityIdentifier
{ {
return GetNSStringAndRelease(_peer->GetAutomationId()); return GetNSStringAndRelease(_peer->GetAutomationId());
@ -176,10 +208,30 @@
{ {
return GetNSStringAndRelease(_peer->GetName()); return GetNSStringAndRelease(_peer->GetName());
} }
else if (_peer->GetAutomationControlType() == AutomationHeader)
{
return [NSNumber numberWithInt:_peer->GetHeadingLevel()];
}
return [super accessibilityValue]; return [super accessibilityValue];
} }
- (void)setAccessibilityValue:(id)newValue
{
if (_peer->IsValueProvider())
{
if (newValue == nil)
_peer->ValueProvider_SetValue(nil);
else if ([newValue isKindOfClass:[NSString class]])
_peer->ValueProvider_SetValue([(NSString*)newValue UTF8String]);
}
else if (_peer->IsRangeValueProvider())
{
if ([newValue isKindOfClass:[NSNumber class]])
_peer->RangeValueProvider_SetValue([(NSNumber*)newValue doubleValue]);
}
}
- (id)accessibilityMinValue - (id)accessibilityMinValue
{ {
if (_peer->IsRangeValueProvider()) if (_peer->IsRangeValueProvider())

55
native/Avalonia.Native/src/OSX/cgl.mm

@ -107,6 +107,61 @@ public:
return Context; return Context;
} }
int texImageIOSurface2D(int target, int internal_format,
int width, int height, int format, int type, void* ioSurface, int plane) override
{
return CGLTexImageIOSurface2D(Context, target, internal_format, width, height, format, type, (IOSurfaceRef)ioSurface, plane);
}
bool GetIOKitRegistryId(uint64_t *value) override {
if (@available(macOS 10.13, *))
{
GLint rendererId;
if(CGLGetParameter(Context, kCGLCPCurrentRendererID, &rendererId) != 0)
return false;
GLint rendererCount = 0;
CGLRendererInfoObj rendererInfo;
if(CGLQueryRendererInfo(0xFFFFFFFF, &rendererInfo, &rendererCount))
return false;
@try
{
for(auto i = 0; i < rendererCount; i++)
{
GLint thisRendererID;
CGLDescribeRenderer(rendererInfo, i, kCGLRPRendererID, &thisRendererID);
if(thisRendererID == rendererId)
{
GLint gpuIDLow = 0;
GLint gpuIDHigh = 0;
if(CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDLow, &gpuIDLow))
return false;
if(CGLDescribeRenderer(rendererInfo, 0, kCGLRPRegistryIDHigh, &gpuIDHigh))
return false;
*value = ((uint64_t)gpuIDHigh << 32) | gpuIDLow;
return true;
}
}
return false;
}
@finally
{
CGLDestroyRendererInfo(rendererInfo);
}
}
else
return false;
}
~AvnGlContext() ~AvnGlContext()
{ {
CGLReleaseContext(Context); CGLReleaseContext(Context);

7
native/Avalonia.Native/src/OSX/clipboard.h

@ -0,0 +1,7 @@
#pragma once
#include "common.h"
@interface WriteableClipboardItem : NSObject <NSPasteboardWriting>
- (nonnull instancetype) initWithItem:(nonnull IAvnClipboardDataItem*)item source:(nonnull IAvnClipboardDataSource*)source;
@end

420
native/Avalonia.Native/src/OSX/clipboard.mm

@ -1,206 +1,354 @@
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
#include "common.h" #include "common.h"
#include "clipboard.h"
#include "AvnString.h" #include "AvnString.h"
class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard> class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard>
{ {
private: private:
NSPasteboard* _pb; NSPasteboard* _pasteboard;
NSPasteboardItem* _item;
public: public:
FORWARD_IUNKNOWN() FORWARD_IUNKNOWN()
Clipboard(NSPasteboard* pasteboard, NSPasteboardItem* item) Clipboard(NSPasteboard* pasteboard)
{ {
if(pasteboard == nil && item == nil) if (pasteboard == nil)
pasteboard = [NSPasteboard generalPasteboard]; pasteboard = [NSPasteboard generalPasteboard];
_pb = pasteboard; _pasteboard = pasteboard;
_item = item;
} }
NSPasteboardItem* TryGetItem() virtual HRESULT GetFormats(int64_t changeCount, IAvnStringArray** ret) override
{ {
return _item; START_COM_ARP_CALL;
if (ret == nullptr)
return E_POINTER;
if (changeCount != [_pasteboard changeCount])
return COR_E_OBJECTDISPOSED;
*ret = ConvertPasteboardTypes([_pasteboard types]);
return S_OK;
} }
virtual HRESULT GetText (char* type, IAvnString**ppv) override virtual HRESULT GetItemCount(int64_t changeCount, int* ret) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
@autoreleasepool if (ret == nullptr)
return E_POINTER;
if (changeCount != [_pasteboard changeCount])
return COR_E_OBJECTDISPOSED;
auto items = [_pasteboard pasteboardItems];
*ret = items == nil ? 0 : (int)[items count];
return S_OK;
}
virtual HRESULT GetItemFormats(int index, int64_t changeCount, IAvnStringArray** ret) override
{
START_COM_ARP_CALL;
if (ret == nullptr)
return E_POINTER;
if (changeCount != [_pasteboard changeCount])
return COR_E_OBJECTDISPOSED;
auto item = [[_pasteboard pasteboardItems] objectAtIndex:index];
*ret = ConvertPasteboardTypes([item types]);
return S_OK;
}
static IAvnStringArray* ConvertPasteboardTypes(NSArray<NSPasteboardType> *types)
{
if (types != nil)
{ {
if(ppv == nullptr) NSMutableArray<NSString *> *mutableTypes = [types mutableCopy];
// Add png if format list doesn't have PNG,
// but has any other image type that can be converter into PNG
if (![mutableTypes containsObject:NSPasteboardTypePNG])
{ {
return E_POINTER; if ([mutableTypes containsObject:NSPasteboardTypeTIFF]
|| [mutableTypes containsObject:@"public.jpeg"])
{
[mutableTypes addObject: NSPasteboardTypePNG];
}
} }
NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
NSString* string = _item == nil ? [_pb stringForType:typeString] : [_item stringForType:typeString]; return CreateAvnStringArray(mutableTypes);
*ppv = CreateAvnString(string);
return S_OK;
} }
return nil;
} }
virtual HRESULT SetStrings(char* type, IAvnStringArray*ppv) override virtual HRESULT GetItemValueAsString(int index, int64_t changeCount, const char* format, IAvnString** ret) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
@autoreleasepool if (ret == nullptr)
{ return E_POINTER;
NSArray<NSString*>* data = GetNSArrayOfStringsAndRelease(ppv);
NSString* typeString = [NSString stringWithUTF8String:(const char*)type]; if (changeCount != [_pasteboard changeCount])
if(_item == nil) return COR_E_OBJECTDISPOSED;
[_pb setPropertyList: data forType: typeString];
else auto item = [[_pasteboard pasteboardItems] objectAtIndex:index];
[_item setPropertyList: data forType:typeString]; auto value = [item stringForType:[NSString stringWithUTF8String:format]];
return S_OK; *ret = value == nil ? nullptr : CreateAvnString(value);
} return S_OK;
} }
virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override virtual HRESULT GetItemValueAsBytes(int index, int64_t changeCount, const char* format, IAvnString** ret) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
@autoreleasepool if (ret == nullptr)
return E_POINTER;
if (changeCount != [_pasteboard changeCount])
return COR_E_OBJECTDISPOSED;
auto item = [[_pasteboard pasteboardItems] objectAtIndex:index];
auto formatStr = [NSString stringWithUTF8String:format];
auto value = [item dataForType: formatStr];
// If PNG wasn't found, try to convert TIFF or JPEG to PNG
if (value == nil && [formatStr isEqualToString: NSPasteboardTypePNG])
{ {
*ppv= nil; NSData *imageData = nil;
NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
NSObject* data = _item == nil ? [_pb propertyListForType: typeString] : [_item propertyListForType: typeString]; // Try TIFF first
if(data == nil) imageData = [item dataForType:NSPasteboardTypeTIFF];
return S_OK;
// If no TIFF, try JPEG
if([data isKindOfClass: [NSString class]]) if (imageData == nil) {
imageData = [item dataForType:@"public.jpeg"];
}
if (imageData != nil)
{ {
*ppv = CreateAvnStringArray((NSString*) data); auto image = [[NSImage alloc] initWithData:imageData];
return S_OK;
NSBitmapImageRep *bitmapRep = nil;
for (NSImageRep *rep in image.representations) {
if ([rep isKindOfClass:[NSBitmapImageRep class]]) {
bitmapRep = (NSBitmapImageRep *)rep;
break;
}
}
if (!bitmapRep) {
[image lockFocus];
bitmapRep = [[NSBitmapImageRep alloc] initWithFocusedViewRect:NSMakeRect(0, 0, image.size.width, image.size.height)];
[image unlockFocus];
}
value = [bitmapRep representationUsingType:NSBitmapImageFileTypePNG properties:@{}];
} }
NSArray<NSString*>* arr = (NSArray*)data;
for(int c = 0; c < [arr count]; c++)
if(![[arr objectAtIndex:c] isKindOfClass:[NSString class]])
return E_INVALIDARG;
*ppv = CreateAvnStringArray(arr);
return S_OK;
} }
*ret = value == nil || [value length] == 0
? nullptr
: CreateByteArray((void*)[value bytes], (int)[value length]);
return S_OK;
} }
virtual HRESULT SetText (char* type, char* utf8String) override virtual HRESULT Clear(int64_t* ret) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
@autoreleasepool *ret = [_pasteboard clearContents];
{ return S_OK;
auto string = [NSString stringWithUTF8String:(const char*)utf8String]; }
auto typeString = [NSString stringWithUTF8String:(const char*)type];
if(_item == nil) virtual HRESULT GetChangeCount(int64_t* ret) override
[_pb setString: string forType: typeString]; {
else START_COM_ARP_CALL;
[_item setString: string forType:typeString];
return S_OK; *ret = [_pasteboard changeCount];
} return S_OK;
} }
virtual HRESULT SetBytes(char* type, void* bytes, int len) override virtual HRESULT SetData(IAvnClipboardDataSource* source) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
@autoreleasepool auto count = source->GetItemCount();
auto writeableItems = [NSMutableArray<WriteableClipboardItem*> arrayWithCapacity:count];
for (auto i = 0; i < count; ++i)
{ {
auto typeString = [NSString stringWithUTF8String:(const char*)type]; auto item = source->GetItem(i);
auto data = [NSData dataWithBytes:bytes length:len]; auto writeableItem = [[WriteableClipboardItem alloc] initWithItem:item source:source];
if(_item == nil) [writeableItems addObject:writeableItem];
[_pb setData:data forType:typeString];
else
[_item setData:data forType:typeString];
return S_OK;
} }
[_pasteboard writeObjects:writeableItems];
return S_OK;
} }
virtual HRESULT GetBytes(char* type, IAvnString**ppv) override virtual bool IsTextFormat(const char *format) override
{ {
START_COM_CALL; START_COM_ARP_CALL;
auto formatString = [NSString stringWithUTF8String:format];
@autoreleasepool if (@available(macOS 11.0, *))
{ {
*ppv = nil; auto type = [UTType typeWithIdentifier:formatString];
auto typeString = [NSString stringWithUTF8String:(const char*)type]; return type != nil && [type conformsToType:UTTypeText];
NSData*data; }
@try else
{ {
if(_item) return UTTypeConformsTo((__bridge CFStringRef)formatString, kUTTypeText);
data = [_item dataForType:typeString];
else
data = [_pb dataForType:typeString];
if(data == nil)
return E_FAIL;
}
@catch(NSException* e)
{
return E_FAIL;
}
*ppv = CreateByteArray((void*)data.bytes, (int)data.length);
return S_OK;
} }
} }
};
virtual HRESULT Clear(int64_t* rv) override extern IAvnClipboard* CreateClipboard(NSPasteboard* pb)
{
return new Clipboard(pb);
}
@implementation WriteableClipboardItem
{
IAvnClipboardDataItem* _item;
IAvnClipboardDataSource* _source;
}
- (nonnull WriteableClipboardItem*) initWithItem:(nonnull IAvnClipboardDataItem*)item source:(nonnull IAvnClipboardDataSource*)source
{
self = [super init];
_item = item;
_source = source;
// Each item references its source so it doesn't get disposed too early.
source->AddRef();
return self;
}
NSString* TryConvertFormatToUti(NSString* format)
{
if (@available(macOS 11.0, *))
{ {
START_COM_CALL; auto type = [UTType typeWithIdentifier:format];
if (type == nil)
@autoreleasepool
{ {
if(_item != nil) if ([format containsString:@"/"])
{ type = [UTType typeWithMIMEType:format];
_item = [NSPasteboardItem new];
return 0;
}
else else
type = [UTType exportedTypeWithIdentifier:format];
if (type == nil)
{ {
*rv = [_pb clearContents]; // For now, we need to use the deprecated UTTypeCreatePreferredIdentifierForTag to create a dynamic UTI for arbitrary strings.
[_pb setString:@"" forType:NSPasteboardTypeString]; // This is only necessary because the old IDataObject can provide arbitrary types that aren't UTIs nor mime types.
// With the new DataFormat:
// - If the format is an application format, the managed side provides a UTI like net.avaloniaui.app.uti.xxx.
// - If the format is an OS format, the user has been warned that they MUST provide a name which is valid for the OS.
// TODO12: remove!
auto fromPasteboardType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, (__bridge CFStringRef)format, nil);
if (fromPasteboardType != nil)
return (__bridge_transfer NSString*)fromPasteboardType;
} }
return S_OK;
} }
return type == nil ? nil : [type identifier];
} }
else
virtual HRESULT GetChangeCount(int64_t* rv) override
{ {
START_COM_CALL; auto bridgedFormat = (__bridge CFStringRef)format;
if(_item == nil) if (UTTypeIsDeclared(bridgedFormat))
{ return format;
*rv = [_pb changeCount];
return S_OK; auto fromMimeType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, bridgedFormat, nil);
} if (fromMimeType != nil)
return E_NOTIMPL; return (__bridge_transfer NSString*)fromMimeType;
auto fromPasteboardType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassNSPboardType, bridgedFormat, nil);
if (fromPasteboardType != nil)
return (__bridge_transfer NSString*)fromPasteboardType;
return nil;
} }
}
- (nonnull NSArray<NSPasteboardType>*) writableTypesForPasteboard:(nonnull NSPasteboard*)pasteboard
{
auto formats = _item->ProvideFormats();
if (formats == nullptr)
return [NSArray array];
virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override auto count = formats->GetCount();
if (count == 0)
return [NSArray array];
auto utis = [NSMutableArray arrayWithCapacity:count];
IAvnString* format;
for (auto i = 0; i < count; ++i)
{ {
START_COM_CALL; if (formats->Get(i, &format) != S_OK)
continue;
@autoreleasepool
{ // Only UTIs must be returned from writableTypesForPasteboard or an exception will be thrown
*ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]); auto formatString = GetNSStringAndRelease(format);
return S_OK; auto uti = TryConvertFormatToUti(formatString);
} if (uti != nil)
[utis addObject:uti];
} }
}; formats->Release();
[utis addObject:GetAvnCustomDataType()];
return utis;
}
extern IAvnClipboard* CreateClipboard(NSPasteboard* pb, NSPasteboardItem* item) - (NSPasteboardWritingOptions) writingOptionsForType:(NSPasteboardType)type pasteboard:(NSPasteboard*)pasteboard
{ {
return new Clipboard(pb, item); return [type isEqualToString:NSPasteboardTypeString] || [type isEqualToString:GetAvnCustomDataType()]
? 0
: NSPasteboardWritingPromised;
} }
extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*cb) - (nullable id) pasteboardPropertyListForType:(nonnull NSPasteboardType)type
{ {
auto clipboard = dynamic_cast<Clipboard*>(cb); if ([type isEqualToString:GetAvnCustomDataType()])
if(clipboard == nil) return @"";
ComPtr<IAvnClipboardDataValue> value(_item->GetValue([type UTF8String]), true);
if (value.getRaw() == nullptr)
return nil; return nil;
return clipboard->TryGetItem();
if (value->IsString())
return GetNSStringAndRelease(value->AsString());
auto length = value->GetByteLength();
auto buffer = malloc(length);
value->CopyBytesTo(buffer);
return [NSData dataWithBytesNoCopy:buffer length:length];
}
- (void) dealloc
{
if (_item != nullptr)
{
_item->Release();
_item = nullptr;
}
if (_source != nullptr)
{
_source->Release();
_source = nullptr;
}
} }
@end

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

@ -16,8 +16,7 @@ extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events); extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events);
extern IAvnStorageProvider* CreateStorageProvider(); extern IAvnStorageProvider* CreateStorageProvider();
extern IAvnScreens* CreateScreens(IAvnScreenEvents* cb); extern IAvnScreens* CreateScreens(IAvnScreenEvents* cb);
extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*); extern IAvnClipboard* CreateClipboard(NSPasteboard* pb);
extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle); extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject<NSDraggingInfo>* info); extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject<NSDraggingInfo>* info);
extern NSString* GetAvnCustomDataType(); extern NSString* GetAvnCustomDataType();
@ -34,6 +33,7 @@ extern IAvnPlatformBehaviorInhibition* CreatePlatformBehaviorInhibition();
extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent); extern IAvnNativeControlHost* CreateNativeControlHost(NSView* parent);
extern IAvnPlatformSettings* CreatePlatformSettings(); extern IAvnPlatformSettings* CreatePlatformSettings();
extern IAvnPlatformRenderTimer* CreatePlatformRenderTimer(); extern IAvnPlatformRenderTimer* CreatePlatformRenderTimer();
extern IAvnNativeObjectsMemoryManagement* CreateMemoryManagementHelper();
extern void SetAppMenu(IAvnMenu *menu); extern void SetAppMenu(IAvnMenu *menu);
extern void SetServicesMenu (IAvnMenu* menu); extern void SetServicesMenu (IAvnMenu* menu);
extern IAvnMenu* GetAppMenu (); extern IAvnMenu* GetAppMenu ();
@ -48,6 +48,7 @@ extern AvnPoint ToAvnPoint (NSPoint p);
extern AvnPoint ConvertPointY (AvnPoint p); extern AvnPoint ConvertPointY (AvnPoint p);
extern NSSize ToNSSize (AvnSize s); extern NSSize ToNSSize (AvnSize s);
extern AvnSize FromNSSize (NSSize s); extern AvnSize FromNSSize (NSSize s);
extern IAvnMTLSharedEvent* ImportMTLSharedEvent(void* object);
#ifdef DEBUG #ifdef DEBUG
#define NSDebugLog(...) NSLog(__VA_ARGS__) #define NSDebugLog(...) NSLog(__VA_ARGS__)
#else #else

9
native/Avalonia.Native/src/OSX/crapium.h

@ -0,0 +1,9 @@
// The only reason this file exists is Appium which limits our highest Xcode version to 15.2. Please, purge Appium from our codebase
#ifndef crapium_h
#define crapium_h
#import <Foundation/Foundation.h>
@protocol MTLSharedEvent;
API_AVAILABLE(macos(12))
extern BOOL MtlSharedEventWaitUntilSignaledValueHack(id<MTLSharedEvent> ev, uint64_t value, uint64_t milliseconds);
#endif /* crapium_h */

21
native/Avalonia.Native/src/OSX/crapium.mm

@ -0,0 +1,21 @@
// The only reason this file exists is Appium which limits our highest Xcode version to 15.2. Please, purge Appium from our codebase
#import <Foundation/Foundation.h>
#import "crapium.h"
@class MTLSharedEventHandle;
@protocol MTLSharedEvent;
@protocol MTLEvent;
typedef void (^MTLSharedEventNotificationBlock)(id <MTLSharedEvent>, uint64_t value);
API_AVAILABLE(macos(10.14), ios(12.0))
@protocol MTLSharedEvent <MTLEvent>
// Synchronously wait for the signaledValue to be greater than or equal to 'value', with a timeout
// specified in milliseconds. Returns YES if the value was signaled before the timeout, otherwise NO.
- (BOOL)waitUntilSignaledValue:(uint64_t)value timeoutMS:(uint64_t)milliseconds API_AVAILABLE(macos(12.0), ios(15.0));
@end
API_AVAILABLE(macos(12))
extern BOOL MtlSharedEventWaitUntilSignaledValueHack(id<MTLSharedEvent> ev, uint64_t value, uint64_t milliseconds)
{
return [ev waitUntilSignaledValue:value timeoutMS:milliseconds];
}

14
native/Avalonia.Native/src/OSX/dnd.mm

@ -14,9 +14,17 @@ extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop)
extern NSString* GetAvnCustomDataType() extern NSString* GetAvnCustomDataType()
{ {
char buffer[256]; static NSString* result = nil;
sprintf(buffer, "net.avaloniaui.inproc.uti.n%in", getpid());
return [NSString stringWithUTF8String:buffer]; if (result == nil)
{
const size_t bufferSize = 256;
char buffer[bufferSize];
snprintf(buffer, bufferSize, "net.avaloniaui.inproc.uti.n%in", getpid());
result = [NSString stringWithUTF8String:buffer];
}
return result;
} }
@interface AvnDndSource : NSObject<NSDraggingSource> @interface AvnDndSource : NSObject<NSDraggingSource>

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

@ -312,18 +312,7 @@ public:
@autoreleasepool @autoreleasepool
{ {
*ppv = ::CreateClipboard (nil, nil); *ppv = ::CreateClipboard(nil);
return S_OK;
}
}
virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
return S_OK; return S_OK;
} }
} }
@ -478,6 +467,22 @@ public:
return S_OK; return S_OK;
} }
} }
virtual HRESULT ImportMTLSharedEvent(void* event, IAvnMTLSharedEvent** ppv) override
{
START_COM_CALL;
*ppv = ::ImportMTLSharedEvent(event);
return *ppv != nullptr ? S_OK : E_FAIL;
}
HRESULT CreateMemoryManagementHelper(IAvnNativeObjectsMemoryManagement **ppv) override {
START_COM_CALL;
*ppv = ::CreateMemoryManagementHelper();
return S_OK;
}
}; };
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative() extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()

40
native/Avalonia.Native/src/OSX/memhelp.mm

@ -0,0 +1,40 @@
#include "common.h"
class MemHelper : public ComSingleObject<IAvnNativeObjectsMemoryManagement, &IID_IAvnNativeObjectsMemoryManagement>
{
FORWARD_IUNKNOWN()
void RetainNSObject(void *object) override
{
::RetainNSObject(object);
}
void ReleaseNSObject(void *object) override
{
::ReleaseNSObject(object);
}
void RetainCFObject(void *object) override
{
CFRetain(object);
}
void ReleaseCFObject(void *object) override
{
CFRelease(object);
}
uint64_t GetRetainCountForNSObject(void *obj) override {
return ::GetRetainCountForNSObject(obj);
}
int64_t GetRetainCountForCFObject(void *obj) override {
return CFGetRetainCount(obj);
}
};
extern IAvnNativeObjectsMemoryManagement* CreateMemoryManagementHelper()
{
return new MemHelper();
}

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

@ -262,10 +262,10 @@ HRESULT AvnAppMenuItem::SetIcon(void *data, size_t length)
NSSize originalSize = [image size]; NSSize originalSize = [image size];
NSSize size; NSSize size;
size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333; size.height = floor([[NSFont menuFontOfSize:0] pointSize] * 1.333333);
auto scaleFactor = size.height / originalSize.height; auto scaleFactor = size.height / originalSize.height;
size.width = originalSize.width * scaleFactor; size.width = floor(originalSize.width * scaleFactor);
[image setSize: size]; [image setSize: size];
[_native setImage:image]; [_native setImage:image];

169
native/Avalonia.Native/src/OSX/metal.mm

@ -3,6 +3,74 @@
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
#include "common.h" #include "common.h"
#include "rendertarget.h" #include "rendertarget.h"
#import "crapium.h"
class API_AVAILABLE(macos(12.0)) AvnMTLSharedEvent : public ComSingleObject<IAvnMTLSharedEvent, &IID_IAvnMTLSharedEvent>
{
id<MTLSharedEvent> _event;
public:
AvnMTLSharedEvent(id<MTLSharedEvent> ev) : _event(ev)
{
}
FORWARD_IUNKNOWN()
id<MTLSharedEvent> GetEvent()
{
return _event;
}
void *GetNativeHandle() override {
return (__bridge void*)_event;
}
bool Wait(uint64_t value, uint64_t timeoutMS) override {
return MtlSharedEventWaitUntilSignaledValueHack(_event, value, timeoutMS);
}
void SetSignaledValue(uint64_t value) override {
_event.signaledValue = value;
}
uint64_t GetSignaledValue() override {
return _event.signaledValue;
}
};
class AvnMetalTexture : public ComSingleObject<IAvnMetalTexture, &IID_IAvnMetalTexture>
{
id<MTLTexture> _texture;
public:
FORWARD_IUNKNOWN()
AvnMetalTexture(id<MTLTexture> texture) : _texture(texture)
{
}
void *GetNativeHandle() override
{
return (__bridge void*)_texture;
}
int GetWidth() override
{
return (int)_texture.width;
}
int GetHeight() override
{
return (int)_texture.height;
}
int GetSampleCount() override
{
return (int)_texture.sampleCount;
}
};
class AvnMetalDevice : public ComSingleObject<IAvnMetalDevice, &IID_IAvnMetalDevice> class AvnMetalDevice : public ComSingleObject<IAvnMetalDevice, &IID_IAvnMetalDevice>
{ {
@ -18,7 +86,86 @@ public:
void *GetQueue() override { void *GetQueue() override {
return (__bridge void*) queue; return (__bridge void*) queue;
} }
HRESULT ImportIOSurface(void *handle, AvnPixelFormat pixelFormat, IAvnMetalTexture **ppv) override {
auto surf = (IOSurfaceRef)handle;
auto width = IOSurfaceGetWidth(surf);
auto height = IOSurfaceGetHeight(surf);
auto desc = [MTLTextureDescriptor new];
if(pixelFormat == kAvnRgba8888)
desc.pixelFormat = MTLPixelFormatRGBA8Unorm;
else if(pixelFormat == kAvnBgra8888)
desc.pixelFormat = MTLPixelFormatBGRA8Unorm;
else
return E_INVALIDARG;
desc.textureType = MTLTextureType2D;
desc.width = width;
desc.height = height;
desc.depth = 1;
desc.mipmapLevelCount = 1;
desc.sampleCount = 1;
desc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
auto texture = [device newTextureWithDescriptor:desc iosurface:surf plane:0];
if(texture == nullptr)
return E_FAIL;
*ppv = new AvnMetalTexture(texture);
return S_OK;
}
HRESULT ImportSharedEvent(void *mtlSharedEventInstance, IAvnMTLSharedEvent**ppv) override {
if (@available(macOS 12.0, *)) {
auto external = (__bridge id<MTLSharedEvent>)mtlSharedEventInstance;
auto handle = external.newSharedEventHandle;
auto imported = [device newSharedEventWithHandle: handle];
*ppv = new AvnMTLSharedEvent(imported);
return S_OK;
}
else
{
return E_NOTIMPL;
}
}
HRESULT SignalOrWait(IAvnMTLSharedEvent *ev, uint64_t value, bool wait)
{
if (@available(macOS 12.0, *))
{
auto e = dynamic_cast<AvnMTLSharedEvent*>(ev);
if(e == nullptr)
return E_FAIL;;
auto buf = [queue commandBuffer];
if(wait)
[buf encodeWaitForEvent:e->GetEvent() value:value];
else
[buf encodeSignalEvent:e->GetEvent() value:value];
[buf commit];
return S_OK;
}
else
return E_FAIL;
}
HRESULT SubmitWait(IAvnMTLSharedEvent *ev, uint64_t value) override {
return SignalOrWait(ev, value, true);
}
HRESULT SubmitSignal(IAvnMTLSharedEvent *ev, uint64_t value) override {
return SignalOrWait(ev, value, false);
}
bool GetIOKitRegistryId(uint64_t *value) override {
if (@available(macOS 10.13, *)) {
*value = [device registryID];
return true;
} else {
return false;
}
}
AvnMetalDevice(id <MTLDevice> device, id <MTLCommandQueue> queue) : device(device), queue(queue) { AvnMetalDevice(id <MTLDevice> device, id <MTLCommandQueue> queue) : device(device), queue(queue) {
} }
@ -160,3 +307,23 @@ extern IAvnMetalDisplay* GetMetalDisplay()
{ {
return _display; return _display;
} }
extern IAvnMTLSharedEvent* ImportMTLSharedEvent(void* object)
{
if (@available(macOS 12.0, *)) {
if(object == nullptr)
return nil;
auto evId = (__bridge id<MTLSharedEvent>)object;
if(evId == nil)
return nil;
return new AvnMTLSharedEvent(evId);
}
else
{
return nil;
}
}

16
native/Avalonia.Native/src/OSX/noarc.mm

@ -1,5 +1,5 @@
#include "noarc.h" #include "noarc.h"
#include "avalonia-native.h"
CppAutoreleasePool::CppAutoreleasePool() CppAutoreleasePool::CppAutoreleasePool()
{ {
_pool = [[NSAutoreleasePool alloc] init]; _pool = [[NSAutoreleasePool alloc] init];
@ -9,3 +9,17 @@ CppAutoreleasePool::~CppAutoreleasePool() {
auto ptr = (NSAutoreleasePool*)_pool; auto ptr = (NSAutoreleasePool*)_pool;
[ptr release]; [ptr release];
} }
extern void ReleaseNSObject(void* obj)
{
[(NSObject*)obj release];
}
extern void RetainNSObject(void* obj)
{
[(NSObject*)obj retain];
}
extern uint64_t GetRetainCountForNSObject(void* obj)
{
return [(NSObject*)obj retainCount];
}

6
native/Avalonia.Native/src/OSX/trayicon.mm

@ -39,10 +39,10 @@ HRESULT AvnTrayIcon::SetIcon (void* data, size_t length)
NSSize originalSize = [image size]; NSSize originalSize = [image size];
NSSize size; NSSize size;
size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333; size.height = floor([[NSFont menuFontOfSize:0] pointSize] * 1.333333);
auto scaleFactor = size.height / originalSize.height; auto scaleFactor = size.height / originalSize.height;
size.width = originalSize.width * scaleFactor; size.width = floor(originalSize.width * scaleFactor);
[image setSize: size]; [image setSize: size];
[image setTemplate: _isTemplateIcon]; [image setTemplate: _isTemplateIcon];

639
nukebuild/ApiDiffHelper.cs

@ -1,313 +1,488 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Collections.Immutable;
using System.IO; using System.IO;
using System.IO.Compression; using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net; using System.Security.Cryptography;
using System.Net.Http;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NuGet.Common;
using NuGet.Configuration;
using NuGet.Frameworks;
using NuGet.Packaging;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using Nuke.Common.IO;
using Nuke.Common.Tooling; using Nuke.Common.Tooling;
using Serilog;
using static Serilog.Log; using static Serilog.Log;
public static class ApiDiffHelper public static class ApiDiffHelper
{ {
static readonly HttpClient s_httpClient = new(); const string NightlyFeedUri = "https://nuget-feed-nightly.avaloniaui.net/v3/index.json";
const string MainPackageName = "Avalonia";
const string FolderLib = "lib";
private static readonly Regex s_suppressionPathRegex =
new("<(Left|Right)>(.*?)</(Left|Right)>", RegexOptions.Compiled);
public static void ValidatePackage(
Tool apiCompatTool,
PackageDiffInfo packageDiff,
AbsolutePath rootAssembliesFolderPath,
AbsolutePath suppressionFilesFolderPath,
bool updateSuppressionFile)
{
Information("Validating API for package {Id}", packageDiff.PackageId);
Directory.CreateDirectory(suppressionFilesFolderPath);
var suppressionFilePath = suppressionFilesFolderPath / (packageDiff.PackageId + ".nupkg.xml");
var replaceDirectorySeparators = Path.DirectorySeparatorChar == '\\';
var allErrors = new List<string>();
foreach (var framework in packageDiff.Frameworks)
{
var relativeBaselinePath = rootAssembliesFolderPath.GetRelativePathTo(framework.BaselineFolderPath);
var relativeCurrentPath = rootAssembliesFolderPath.GetRelativePathTo(framework.CurrentFolderPath);
var args = "";
if (suppressionFilePath.FileExists())
{
args += $""" --suppression-file="{suppressionFilePath}" --permit-unnecessary-suppressions """;
if (replaceDirectorySeparators)
ReplaceDirectorySeparators(suppressionFilePath, '/', '\\');
}
if (updateSuppressionFile)
args += $""" --suppression-output-file="{suppressionFilePath}" --generate-suppression-file --preserve-unnecessary-suppressions """;
args += $""" -l="{relativeBaselinePath}" -r="{relativeCurrentPath}" """;
var localErrors = GetErrors(apiCompatTool($"{args:nq}", rootAssembliesFolderPath, exitHandler: _ => { }));
if (replaceDirectorySeparators)
ReplaceDirectorySeparators(suppressionFilePath, '\\', '/');
allErrors.AddRange(localErrors);
}
ThrowOnErrors(allErrors, packageDiff.PackageId, "ValidateApiDiff");
}
public static async Task GetDiff( /// <summary>
Tool apiDiffTool, string outputFolder, /// The ApiCompat tool treats paths with '/' and '\' separators as different files.
string packagePath, string baselineVersion) /// Before running the tool, adjust the existing separators (using a dirty regex) to match the current platform.
/// After running the tool, change all separators back to '/'.
/// </summary>
static void ReplaceDirectorySeparators(AbsolutePath suppressionFilePath, char oldSeparator, char newSeparator)
{ {
await using var baselineStream = await DownloadBaselinePackage(packagePath, baselineVersion); if (!File.Exists(suppressionFilePath))
if (baselineStream == null)
return; return;
if (!Directory.Exists(outputFolder)) var lines = File.ReadAllLines(suppressionFilePath);
for (var i = 0; i < lines.Length; i++)
{ {
Directory.CreateDirectory(outputFolder!); var original = lines[i];
var replacement = s_suppressionPathRegex.Replace(original, match =>
{
var path = match.Groups[2].Value.Replace(oldSeparator, newSeparator);
return $"<{match.Groups[1].Value}>{path}</{match.Groups[3].Value}>";
});
lines[i] = replacement;
} }
using (var target = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.Read), ZipArchiveMode.Read)) File.WriteAllLines(suppressionFilePath, lines);
using (var baseline = new ZipArchive(baselineStream, ZipArchiveMode.Read)) }
using (Helpers.UseTempDir(out var tempFolder))
{
var targetDlls = GetDlls(target);
var baselineDlls = GetDlls(baseline);
var pairs = new List<(string baseline, string target)>(); public static void GenerateMarkdownDiff(
Tool apiDiffTool,
PackageDiffInfo packageDiff,
AbsolutePath rootOutputFolderPath,
string baselineDisplay,
string currentDisplay)
{
Information("Creating markdown diff for package {Id}", packageDiff.PackageId);
var packageId = GetPackageId(packagePath); var packageOutputFolderPath = rootOutputFolderPath / packageDiff.PackageId;
Directory.CreateDirectory(packageOutputFolderPath);
// Don't use Path.Combine with these left and right tool parameters. // Not specifying -eattrs incorrectly tries to load AttributesToExclude.txt, create an empty file instead.
// Microsoft.DotNet.ApiCompat.Tool is stupid and treats '/' and '\' as different assemblies in suppression files. // See https://github.com/dotnet/sdk/issues/49719
// So, always use Unix '/' var excludedAttributesFilePath = (AbsolutePath)Path.Join(Path.GetTempPath(), Guid.NewGuid().ToString());
foreach (var baselineDll in baselineDlls) File.WriteAllBytes(excludedAttributesFilePath!, []);
{
var baselineDllPath = await ExtractDll("baseline", baselineDll, tempFolder);
var targetTfm = baselineDll.target; try
var targetDll = targetDlls.FirstOrDefault(e => {
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); var allErrors = new List<string>();
if (targetDll is null)
// The API diff tool is unbelievably slow, process in parallel.
Parallel.ForEach(
packageDiff.Frameworks,
framework =>
{ {
if (s_tfmRedirects.FirstOrDefault(t => baselineDll.target.StartsWith(t.oldTfm) && (t.package is null || packageId == t.package)).newTfm is {} newTfm) var frameworkOutputFolderPath = packageOutputFolderPath / framework.Framework.GetShortFolderName();
var args = $""" -b="{framework.BaselineFolderPath}" -bfn="{baselineDisplay}" -a="{framework.CurrentFolderPath}" -afn="{currentDisplay}" -o="{frameworkOutputFolderPath}" -eattrs="{excludedAttributesFilePath}" """;
var localErrors = GetErrors(apiDiffTool($"{args:nq}"));
if (localErrors.Length > 0)
{ {
targetTfm = newTfm; lock (allErrors)
targetDll = targetDlls.FirstOrDefault(e => allErrors.AddRange(localErrors);
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name);
} }
} });
if (targetDll?.entry is null) ThrowOnErrors(allErrors, packageDiff.PackageId, "OutputApiDiff");
{
throw new InvalidOperationException($"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}");
}
var targetDllPath = await ExtractDll("target", targetDll, tempFolder); MergeFrameworkMarkdownDiffFiles(
rootOutputFolderPath,
packageOutputFolderPath,
[..packageDiff.Frameworks.Select(info => info.Framework)]);
pairs.Add((baselineDllPath, targetDllPath)); Directory.Delete(packageOutputFolderPath, true);
} }
finally
{
File.Delete(excludedAttributesFilePath);
}
}
await Task.WhenAll(pairs.Select(p => Task.Run(() => static void MergeFrameworkMarkdownDiffFiles(
AbsolutePath rootOutputFolderPath,
AbsolutePath packageOutputFolderPath,
ImmutableArray<NuGetFramework> frameworks)
{
// At this point, the hierarchy looks like:
// markdown/
// ├─ net8.0/
// │ ├─ api_diff_Avalonia.md
// │ ├─ api_diff_Avalonia.Controls.md
// ├─ netstandard2.0/
// │ ├─ api_diff_Avalonia.md
// │ ├─ api_diff_Avalonia.Controls.md
//
// We want one file per assembly: merge all files with the same name.
// However, it's very likely that the diff is the same for several frameworks: in this case, keep only one file.
var assemblyGroups = frameworks
.SelectMany(GetFrameworkDiffFiles, (framework, filePath) => (framework, filePath))
.GroupBy(x => x.filePath.Name)
.OrderBy(x => x.Key, StringComparer.OrdinalIgnoreCase);
foreach (var assemblyGroup in assemblyGroups)
{
using var writer = File.CreateText(rootOutputFolderPath / assemblyGroup.Key.Replace("api_diff_", ""));
var addSeparator = false;
foreach (var similarDiffGroup in assemblyGroup.GroupBy(x => HashFile(x.filePath), ByteArrayEqualityComparer.Instance))
{ {
var baselineApi = p.baseline + Random.Shared.Next() + ".api.cs"; if (addSeparator)
var targetApi = p.target + Random.Shared.Next() + ".api.cs"; writer.WriteLine();
var resultDiff = p.target + ".api.diff.cs";
GenerateApiListing(apiDiffTool, p.baseline, baselineApi, tempFolder);
GenerateApiListing(apiDiffTool, p.target, targetApi, tempFolder);
var args = $"""-c core.autocrlf=false diff --no-index --minimal """;
args += """--ignore-matching-lines="^\[assembly: System.Reflection.AssemblyVersionAttribute" """;
args += $""" --output {resultDiff} {baselineApi} {targetApi}""";
using (var gitProcess = new Process())
{
gitProcess.StartInfo = new ProcessStartInfo
{
CreateNoWindow = true,
RedirectStandardError = false,
RedirectStandardOutput = false,
FileName = "git",
Arguments = args,
WorkingDirectory = tempFolder
};
gitProcess.Start();
gitProcess.WaitForExit();
}
var resultFile = new FileInfo(Path.Combine(tempFolder, resultDiff)); using var reader = File.OpenText(similarDiffGroup.First().filePath);
if (resultFile.Length > 0) var firstLine = reader.ReadLine();
{
resultFile.CopyTo(Path.Combine(outputFolder, Path.GetFileName(resultDiff)), true); writer.Write(firstLine);
} writer.WriteLine(" (" + string.Join(", ", similarDiffGroup.Select(x => x.framework.GetShortFolderName())) + ")");
})));
while (reader.ReadLine() is { } line)
writer.WriteLine(line);
addSeparator = true;
}
} }
}
private static readonly (string package, string oldTfm, string newTfm)[] s_tfmRedirects = new[] AbsolutePath[] GetFrameworkDiffFiles(NuGetFramework framework)
{
// We use StartsWith below comparing these tfm, as we ignore platform versions (like, net6.0-ios16.1).
("Avalonia.Android", "net6.0-android", "net8.0-android"),
("Avalonia.iOS", "net6.0-ios", "net8.0-ios"),
// Browser was changed from net7.0 to net8.0-browser.
("Avalonia.Browser", "net7.0", "net8.0-browser"),
("Avalonia.Browser.Blazor", "net7.0", "net8.0-browser"),
// Designer was moved from netcoreapp to netstandard.
("Avalonia", "netcoreapp2.0", "netstandard2.0"),
("Avalonia", "net461", "netstandard2.0")
};
public static async Task ValidatePackage(
Tool apiCompatTool, string packagePath, string baselineVersion,
string suppressionFilesFolder, bool updateSuppressionFile)
{
if (!Directory.Exists(suppressionFilesFolder))
{ {
Directory.CreateDirectory(suppressionFilesFolder!); var frameworkFolderPath = packageOutputFolderPath / framework.GetShortFolderName();
if (!frameworkFolderPath.DirectoryExists())
return [];
return Directory.GetFiles(frameworkFolderPath, "*.md")
.Where(filePath => Path.GetFileName(filePath) != "api_diff.md")
.Select(filePath => (AbsolutePath)filePath)
.ToArray();
} }
await using var baselineStream = await DownloadBaselinePackage(packagePath, baselineVersion); static byte[] HashFile(AbsolutePath filePath)
if (baselineStream == null) {
return; using var stream = File.OpenRead(filePath);
return SHA256.HashData(stream);
}
}
public static void MergePackageMarkdownDiffFiles(
AbsolutePath rootOutputFolderPath,
string baselineDisplay,
string currentDisplay)
{
const string mergedFileName = "_diff.md";
using (var target = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.Read), ZipArchiveMode.Read)) var filePaths = Directory.EnumerateFiles(rootOutputFolderPath, "*.md")
using (var baseline = new ZipArchive(baselineStream, ZipArchiveMode.Read)) .Where(filePath => Path.GetFileName(filePath) != mergedFileName)
using (Helpers.UseTempDir(out var tempFolder)) .Order(StringComparer.OrdinalIgnoreCase)
.ToArray();
using var writer = File.CreateText(rootOutputFolderPath / mergedFileName);
writer.WriteLine($"# API diff between {baselineDisplay} and {currentDisplay}");
if (filePaths.Length == 0)
{ {
var targetDlls = GetDlls(target); writer.WriteLine();
var baselineDlls = GetDlls(baseline); writer.WriteLine("No changes.");
return;
}
var left = new List<string>(); foreach (var filePath in filePaths)
var right = new List<string>(); {
writer.WriteLine();
var packageId = GetPackageId(packagePath); using var reader = File.OpenText(filePath);
var suppressionFile = Path.Combine(suppressionFilesFolder, packageId + ".nupkg.xml");
// Don't use Path.Combine with these left and right tool parameters. while (reader.ReadLine() is { } line)
// Microsoft.DotNet.ApiCompat.Tool is stupid and treats '/' and '\' as different assemblies in suppression files.
// So, always use Unix '/'
foreach (var baselineDll in baselineDlls)
{ {
var baselineDllPath = await ExtractDll("baseline", baselineDll, tempFolder); if (line.StartsWith('#'))
writer.Write('#');
var targetTfm = baselineDll.target; writer.WriteLine(line);
var targetDll = targetDlls.FirstOrDefault(e => }
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name); }
if (targetDll?.entry is null) }
{
if (s_tfmRedirects.FirstOrDefault(t => baselineDll.target.StartsWith(t.oldTfm) && (t.package is null || packageId == t.package)).newTfm is {} newTfm)
{
targetTfm = newTfm;
targetDll = targetDlls.FirstOrDefault(e =>
e.target.StartsWith(targetTfm) && e.entry.Name == baselineDll.entry.Name);
}
}
if (targetDll?.entry is null && targetDlls.Count == 1)
{
targetDll = targetDlls.First();
Warning(
$"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}." +
$"Resolved: {targetDll.target} ({targetDll.entry.Name})");
}
if (targetDll?.entry is null) static string[] GetErrors(IEnumerable<Output> outputs)
{ => outputs
if (packageId == "Avalonia" .Where(output => output.Type == OutputType.Err)
&& baselineDll.target is "net461" or "netcoreapp2.0") .Select(output => output.Text)
{ .ToArray();
// In 11.1 we have removed net461 and netcoreapp2.0 targets from Avalonia package.
continue; static void ThrowOnErrors(List<string> errors, string packageId, string taskName)
} {
if (errors.Count > 0)
var actualTargets = string.Join(", ", {
targetDlls.Select(d => $"{d.target} ({d.entry.Name})")); throw new AggregateException(
throw new InvalidOperationException( $"{taskName} task has failed for \"{packageId}\" package",
$"Some assemblies are missing in the new package {packageId}: {baselineDll.entry.Name} for {baselineDll.target}." errors.Select(error => new Exception(error)));
+ $"\r\nActual targets: {actualTargets}."); }
} }
public static async Task<GlobalDiffInfo> DownloadAndExtractPackagesAsync(
IEnumerable<AbsolutePath> currentPackagePaths,
NuGetVersion currentVersion,
bool isReleaseBranch,
AbsolutePath outputFolderPath,
NuGetVersion? forcedBaselineVersion)
{
var downloadContext = await CreateNuGetDownloadContextAsync();
var baselineVersion = forcedBaselineVersion ??
await GetBaselineVersionAsync(downloadContext, currentVersion, isReleaseBranch);
var targetDllPath = await ExtractDll("target", targetDll, tempFolder); Information("API baseline version is {Baseline} for current version {Current}", baselineVersion, currentVersion);
left.Add(baselineDllPath); var memoryStream = new MemoryStream();
right.Add(targetDllPath); var packageDiffs = ImmutableArray.CreateBuilder<PackageDiffInfo>();
foreach (var packagePath in currentPackagePaths)
{
string packageId;
AbsolutePath currentFolderPath;
AbsolutePath baselineFolderPath;
Dictionary<NuGetFramework, string> currentFolderNames;
Dictionary<NuGetFramework, string> baselineFolderNames;
// Extract current package
using (var currentArchive = new ZipArchive(File.OpenRead(packagePath), ZipArchiveMode.Read, leaveOpen: false))
{
using var packageReader = new PackageArchiveReader(currentArchive);
packageId = packageReader.NuspecReader.GetId();
currentFolderPath = outputFolderPath / "current" / packageId;
currentFolderNames = ExtractDiffableAssembliesFromPackage(currentArchive, currentFolderPath);
} }
if (left.Any()) // Download baseline package
memoryStream.Position = 0L;
memoryStream.SetLength(0L);
await DownloadBaselinePackageAsync(memoryStream, downloadContext, packageId, baselineVersion);
memoryStream.Position = 0L;
// Extract baseline package
using (var baselineArchive = new ZipArchive(memoryStream, ZipArchiveMode.Read, leaveOpen: true))
{ {
var args = $""" -l={string.Join(',', left)} -r="{string.Join(',', right)}" """; baselineFolderPath = outputFolderPath / "baseline" / packageId;
if (File.Exists(suppressionFile)) baselineFolderNames = ExtractDiffableAssembliesFromPackage(baselineArchive, baselineFolderPath);
{ }
args += $""" --suppression-file="{suppressionFile}" """;
}
if (updateSuppressionFile) if (currentFolderNames.Count == 0 && baselineFolderNames.Count == 0)
{ continue;
args += $""" --suppression-output-file="{suppressionFile}" --generate-suppression-file=true """;
}
var result = apiCompatTool(args, tempFolder) var frameworkDiffs = new List<FrameworkDiffInfo>();
.Where(t => t.Type == OutputType.Err).ToArray();
if (result.Any()) foreach (var (framework, currentFolderName) in currentFolderNames)
{ {
throw new AggregateException( // Ignore new frameworks that didn't exist in the baseline package. Empty folders make the ApiDiff tool crash.
$"ApiDiffValidation task has failed for \"{Path.GetFileName(packagePath)}\" package", if (!baselineFolderNames.TryGetValue(framework, out var baselineFolderName))
result.Select(r => new Exception(r.Text))); continue;
}
frameworkDiffs.Add(new FrameworkDiffInfo(
framework,
baselineFolderPath / FolderLib / baselineFolderName,
currentFolderPath / FolderLib / currentFolderName));
} }
packageDiffs.Add(new PackageDiffInfo(packageId, [..frameworkDiffs]));
} }
return new GlobalDiffInfo(baselineVersion, currentVersion, packageDiffs.DrainToImmutable());
} }
record DllEntry(string target, ZipArchiveEntry entry); static async Task<NuGetDownloadContext> CreateNuGetDownloadContextAsync()
static IReadOnlyCollection<DllEntry> GetDlls(ZipArchive archive)
{ {
return archive.Entries var packageSource = new PackageSource(NightlyFeedUri) { ProtocolVersion = 3 };
.Where(e => Path.GetExtension(e.FullName) == ".dll" var repository = Repository.Factory.GetCoreV3(packageSource);
// Exclude analyzers and build task, as we don't care about breaking changes there var findPackageByIdResource = await repository.GetResourceAsync<FindPackageByIdResource>();
&& !e.FullName.Contains("analyzers/") && !e.FullName.Contains("analyzers\\") return new NuGetDownloadContext(packageSource, findPackageByIdResource);
&& !e.Name.Contains("Avalonia.Build.Tasks"))
.Select(e => (
entry: e,
isRef: e.FullName.Contains("ref/") || e.FullName.Contains("ref\\"),
target: Path.GetDirectoryName(e.FullName)!.Split(new [] { '/', '\\' }).Last())
)
.GroupBy(e => (e.target, e.entry.Name))
.Select(g => g.MaxBy(e => e.isRef))
.Select(e => new DllEntry(e.target, e.entry))
.ToArray();
} }
static async Task<Stream> DownloadBaselinePackage(string packagePath, string baselineVersion) /// <summary>
/// Finds the baseline version to diff against.
/// On release branches, use the latest stable version.
/// On the main branch and on PRs, use the latest nightly version.
/// This method assumes all packages share the same version.
/// </summary>
static async Task<NuGetVersion> GetBaselineVersionAsync(
NuGetDownloadContext context,
NuGetVersion currentVersion,
bool isReleaseBranch)
{ {
if (baselineVersion is null) var versions = await context.FindPackageByIdResource.GetAllVersionsAsync(
MainPackageName,
context.CacheContext,
NullLogger.Instance,
CancellationToken.None);
versions = versions.Where(v => v < currentVersion);
if (isReleaseBranch)
versions = versions.Where(v => !v.IsPrerelease);
return versions.OrderDescending().FirstOrDefault()
?? throw new InvalidOperationException(
$"Could not find a version less than {currentVersion} for package {MainPackageName} in source {context.PackageSource.Source}");
}
static async Task DownloadBaselinePackageAsync(
Stream destinationStream,
NuGetDownloadContext context,
string packageId,
NuGetVersion version)
{
Information("Downloading {Id} {Version} baseline package", packageId, version);
var downloaded = await context.FindPackageByIdResource.CopyNupkgToStreamAsync(
packageId,
version,
destinationStream,
context.CacheContext,
NullLogger.Instance,
CancellationToken.None);
if (!downloaded)
{ {
throw new InvalidOperationException( throw new InvalidOperationException(
"Build \"api-baseline\" parameter must be set when running Nuke CreatePackages"); $"Could not download version {version} for package {packageId} in source {context.PackageSource.Source}");
} }
}
/* static Dictionary<NuGetFramework, string> ExtractDiffableAssembliesFromPackage(
Gets package name from versions like: ZipArchive packageArchive,
Avalonia.0.10.0-preview1 AbsolutePath destinationFolderPath)
Avalonia.11.0.999-cibuild0037534-beta {
Avalonia.11.0.0 var folderByFramework = new Dictionary<NuGetFramework, string>();
*/
var packageId = GetPackageId(packagePath);
Information("Downloading {0} {1} baseline package", packageId, baselineVersion);
try foreach (var entry in packageArchive.Entries)
{ {
using var response = await s_httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Get, if (TryGetFrameworkFolderName(entry.FullName) is not { } folderName)
$"https://www.nuget.org/api/v2/package/{packageId}/{baselineVersion}"), HttpCompletionOption.ResponseHeadersRead); continue;
response.EnsureSuccessStatusCode();
// Ignore platform versions: assume that e.g. net8.0-android34 and net8.0-android35 are the same for diff purposes.
await using var stream = await response.Content.ReadAsStreamAsync(); var framework = WithoutPlatformVersion(NuGetFramework.ParseFolder(folderName));
var memoryStream = new MemoryStream();
await stream.CopyToAsync(memoryStream); if (folderByFramework.TryGetValue(framework, out var existingFolderName))
memoryStream.Seek(0, SeekOrigin.Begin); {
return memoryStream; if (existingFolderName != folderName)
} {
catch (HttpRequestException e) when (e.StatusCode == HttpStatusCode.NotFound) throw new InvalidOperationException(
{ $"Found two similar frameworks with different platform versions: {existingFolderName} and {folderName}");
return null; }
}
else
folderByFramework.Add(framework, folderName);
var targetFilePath = destinationFolderPath / entry.FullName;
Directory.CreateDirectory(targetFilePath.Parent);
entry.ExtractToFile(targetFilePath, overwrite: true);
} }
catch (Exception ex)
return folderByFramework;
static string? TryGetFrameworkFolderName(string entryPath)
{ {
throw new InvalidOperationException($"Downloading baseline package for {packageId} {baselineVersion} failed.\r" + ex.Message, ex); if (!entryPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
return null;
var segments = entryPath.Split('/');
if (segments is not [FolderLib, var name, ..])
return null;
return name;
} }
// e.g. net8.0-android34.0 to net8.0-android
static NuGetFramework WithoutPlatformVersion(NuGetFramework value)
=> value.HasPlatform && value.PlatformVersion != FrameworkConstants.EmptyVersion ?
new NuGetFramework(value.Framework, value.Version, value.Platform, FrameworkConstants.EmptyVersion) :
value;
} }
static async Task<string> ExtractDll(string basePath, DllEntry dllEntry, string targetFolder) public sealed class GlobalDiffInfo(
NuGetVersion baselineVersion,
NuGetVersion currentVersion,
ImmutableArray<PackageDiffInfo> packages)
{ {
var dllPath = $"{basePath}/{dllEntry.target}/{dllEntry.entry.Name}"; public NuGetVersion BaselineVersion { get; } = baselineVersion;
var dllRealPath = Path.Combine(targetFolder, dllPath); public NuGetVersion CurrentVersion { get; } = currentVersion;
Directory.CreateDirectory(Path.GetDirectoryName(dllRealPath)!); public ImmutableArray<PackageDiffInfo> Packages { get; } = packages;
await using (var dllFile = File.Create(dllRealPath)) }
{
await dllEntry.entry.Open().CopyToAsync(dllFile);
}
return dllPath; public sealed class PackageDiffInfo(string packageId, ImmutableArray<FrameworkDiffInfo> frameworks)
{
public string PackageId { get; } = packageId;
public ImmutableArray<FrameworkDiffInfo> Frameworks { get; } = frameworks;
} }
static void GenerateApiListing(Tool apiDiffTool, string inputFile, string outputFile, string workingDif) public sealed class FrameworkDiffInfo(
NuGetFramework framework,
AbsolutePath baselineFolderPath,
AbsolutePath currentFolderPath)
{ {
var args = $""" --assembly={inputFile} --output-path={outputFile} --include-assembly-attributes=true"""; public NuGetFramework Framework { get; } = framework;
var result = apiDiffTool(args, workingDif) public AbsolutePath BaselineFolderPath { get; } = baselineFolderPath;
.Where(t => t.Type == OutputType.Err).ToArray(); public AbsolutePath CurrentFolderPath { get; } = currentFolderPath;
if (result.Any())
{
throw new AggregateException($"GetApi tool failed task has failed",
result.Select(r => new Exception(r.Text)));
}
} }
static string GetPackageId(string packagePath) sealed class NuGetDownloadContext(PackageSource packageSource, FindPackageByIdResource findPackageByIdResource)
{ {
return Regex.Replace( public SourceCacheContext CacheContext { get; } = new();
Path.GetFileNameWithoutExtension(packagePath), public PackageSource PackageSource { get; } = packageSource;
"""(\.\d+\.\d+\.\d+(?:-.+)?)$""", ""); public FindPackageByIdResource FindPackageByIdResource { get; } = findPackageByIdResource;
} }
} }

199
nukebuild/Build.cs

@ -9,17 +9,12 @@ using System.Xml.Linq;
using Nuke.Common; using Nuke.Common;
using Nuke.Common.Tooling; using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet; using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.Npm;
using static Nuke.Common.EnvironmentInfo; using static Nuke.Common.EnvironmentInfo;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
using static Nuke.Common.Tools.DotNet.DotNetTasks; using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
using static Serilog.Log; using static Serilog.Log;
using MicroCom.CodeGenerator; using MicroCom.CodeGenerator;
using NuGet.Configuration; using NuGet.Configuration;
using NuGet.Versioning;
using Nuke.Common.CI.AzurePipelines; using Nuke.Common.CI.AzurePipelines;
using Nuke.Common.IO; using Nuke.Common.IO;
@ -35,15 +30,19 @@ partial class Build : NukeBuild
{ {
BuildParameters Parameters { get; set; } BuildParameters Parameters { get; set; }
[PackageExecutable("Microsoft.DotNet.ApiCompat.Tool", "Microsoft.DotNet.ApiCompat.Tool.dll", Framework = "net6.0")] #nullable enable
ApiDiffHelper.GlobalDiffInfo? GlobalDiff { get; set; }
#nullable restore
[NuGetPackage("Microsoft.DotNet.ApiCompat.Tool", "Microsoft.DotNet.ApiCompat.Tool.dll", Framework = "net8.0")]
Tool ApiCompatTool; Tool ApiCompatTool;
[PackageExecutable("Microsoft.DotNet.GenAPI.Tool", "Microsoft.DotNet.GenAPI.Tool.dll", Framework = "net8.0")]
Tool ApiGenTool;
[PackageExecutable("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")] [NuGetPackage("Microsoft.DotNet.ApiDiff.Tool", "Microsoft.DotNet.ApiDiff.Tool.dll", Framework = "net8.0")]
Tool ApiDiffTool;
[NuGetPackage("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")]
Tool IlRepackTool; Tool IlRepackTool;
protected override void OnBuildInitialized() protected override void OnBuildInitialized()
{ {
Parameters = new BuildParameters(this, ScheduledTargets.Contains(BuildToNuGetCache)); Parameters = new BuildParameters(this, ScheduledTargets.Contains(BuildToNuGetCache));
@ -58,6 +57,7 @@ partial class Build : NukeBuild
Information("Repository Name: " + Parameters.RepositoryName); Information("Repository Name: " + Parameters.RepositoryName);
Information("Repository Branch: " + Parameters.RepositoryBranch); Information("Repository Branch: " + Parameters.RepositoryBranch);
} }
Information("Configuration: " + Parameters.Configuration); Information("Configuration: " + Parameters.Configuration);
Information("IsLocalBuild: " + Parameters.IsLocalBuild); Information("IsLocalBuild: " + Parameters.IsLocalBuild);
Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix); Information("IsRunningOnUnix: " + Parameters.IsRunningOnUnix);
@ -74,8 +74,9 @@ partial class Build : NukeBuild
void ExecWait(string preamble, string command, string args) void ExecWait(string preamble, string command, string args)
{ {
Console.WriteLine(preamble); Console.WriteLine(preamble);
Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit(); Process.Start(new ProcessStartInfo(command, args) { UseShellExecute = false }).WaitForExit();
} }
ExecWait("dotnet version:", "dotnet", "--info"); ExecWait("dotnet version:", "dotnet", "--info");
ExecWait("dotnet workloads:", "dotnet", "workload list"); ExecWait("dotnet workloads:", "dotnet", "workload list");
Information("Processor count: " + Environment.ProcessorCount); Information("Processor count: " + Environment.ProcessorCount);
@ -91,7 +92,7 @@ partial class Build : NukeBuild
c.AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_11_X64")); c.AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_11_X64"));
c.AddProperty("PackageVersion", Parameters.Version) c.AddProperty("PackageVersion", Parameters.Version)
.SetConfiguration(Parameters.Configuration) .SetConfiguration(Parameters.Configuration)
.SetVerbosity(DotNetVerbosity.Minimal); .SetVerbosity(DotNetVerbosity.minimal);
if (Parameters.IsPackingToLocalCache) if (Parameters.IsPackingToLocalCache)
c c
.AddProperty("ForcePackAvaloniaNative", "True") .AddProperty("ForcePackAvaloniaNative", "True")
@ -100,6 +101,7 @@ partial class Build : NukeBuild
.AddProperty("SkipBuildingTests", "True"); .AddProperty("SkipBuildingTests", "True");
return c; return c;
} }
DotNetBuildSettings ApplySetting(DotNetBuildSettings c, Configure<DotNetBuildSettings> configurator = null) => DotNetBuildSettings ApplySetting(DotNetBuildSettings c, Configure<DotNetBuildSettings> configurator = null) =>
ApplySettingCore(c).Build.Apply(configurator); ApplySettingCore(c).Build.Apply(configurator);
@ -111,27 +113,34 @@ partial class Build : NukeBuild
Target Clean => _ => _.Executes(() => Target Clean => _ => _.Executes(() =>
{ {
Parameters.BuildDirs.ForEach(DeleteDirectory); foreach (var buildDir in Parameters.BuildDirs)
EnsureCleanDirectory(Parameters.ArtifactsDir); {
EnsureCleanDirectory(Parameters.NugetIntermediateRoot); Information("Deleting {Directory}", buildDir);
EnsureCleanDirectory(Parameters.NugetRoot); buildDir.DeleteDirectory();
EnsureCleanDirectory(Parameters.ZipRoot); }
EnsureCleanDirectory(Parameters.TestResultsRoot);
CleanDirectory(Parameters.ArtifactsDir);
CleanDirectory(Parameters.NugetIntermediateRoot);
CleanDirectory(Parameters.NugetRoot);
CleanDirectory(Parameters.ZipRoot);
CleanDirectory(Parameters.TestResultsRoot);
void CleanDirectory(AbsolutePath path)
{
Information("Cleaning {Path}", path);
path.CreateOrCleanDirectory();
}
}); });
Target CompileHtmlPreviewer => _ => _ // Ensure that Bun.Official.Tool is downloaded at least once on CI to work around https://github.com/dotnet/sdk/issues/51831
.DependsOn(Clean) Target InitDnx => _ => _
.OnlyWhenStatic(() => !Parameters.SkipPreviewer)
.Executes(() => .Executes(() =>
{ {
var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp"; var process = ProcessTasks.StartProcess(
"dnx",
NpmTasks.NpmInstall(c => c "Bun.Unofficial.Tool --yes -- install",
.SetProcessWorkingDirectory(webappDir) $"{RootDirectory}/src/Browser/Avalonia.Browser/webapp");
.SetProcessArgumentConfigurator(a => a.Add("--silent"))); process.AssertZeroExitCode();
NpmTasks.NpmRun(c => c
.SetProcessWorkingDirectory(webappDir)
.SetCommand("dist"));
}); });
Target CompileNative => _ => _ Target CompileNative => _ => _
@ -146,8 +155,7 @@ partial class Build : NukeBuild
}); });
Target Compile => _ => _ Target Compile => _ => _
.DependsOn(Clean, CompileNative) .DependsOn(Clean, CompileNative, InitDnx)
.DependsOn(CompileHtmlPreviewer)
.Executes(() => .Executes(() =>
{ {
DotNetBuild(c => ApplySetting(c) DotNetBuild(c => ApplySetting(c)
@ -171,6 +179,14 @@ partial class Build : NukeBuild
}); });
void RunCoreTest(string projectName) void RunCoreTest(string projectName)
{
RunCoreTest(projectName, (project, tfm) =>
{
DotNetTest(c => ApplySetting(c, project,tfm));
});
}
void RunCoreTest(string projectName, Action<string, string> runTest)
{ {
Information($"Running tests from {projectName}"); Information($"Running tests from {projectName}");
var project = RootDirectory.GlobFiles(@$"**\{projectName}.csproj").FirstOrDefault() var project = RootDirectory.GlobFiles(@$"**\{projectName}.csproj").FirstOrDefault()
@ -199,11 +215,11 @@ partial class Build : NukeBuild
var tfm = fw; var tfm = fw;
if (tfm == "$(AvsCurrentTargetFramework)") if (tfm == "$(AvsCurrentTargetFramework)")
{ {
tfm = "net8.0"; tfm = "net10.0";
} }
if (tfm == "$(AvsLegacyTargetFrameworks)") if (tfm == "$(AvsLegacyTargetFrameworks)")
{ {
tfm = "net6.0"; tfm = "net8.0";
} }
if (tfm.StartsWith("net4") if (tfm.StartsWith("net4")
@ -216,30 +232,29 @@ partial class Build : NukeBuild
Information($"Running for {projectName} ({tfm}) ..."); Information($"Running for {projectName} ({tfm}) ...");
DotNetTest(c => ApplySetting(c) runTest(project, tfm);
.SetProjectFile(project)
.SetFramework(tfm)
.EnableNoBuild()
.EnableNoRestore()
.When(Parameters.PublishTestResults, _ => _
.SetLoggers("trx")
.SetResultsDirectory(Parameters.TestResultsRoot)));
} }
} }
DotNetTestSettings ApplySetting(DotNetTestSettings settings, string project, string tfm) =>
ApplySetting(settings)
.SetProjectFile(project)
.SetFramework(tfm)
.EnableNoBuild()
.EnableNoRestore()
.When(_ => Parameters.PublishTestResults, _ => _
.SetLoggers("trx")
.SetResultsDirectory(Parameters.TestResultsRoot));
Target RunHtmlPreviewerTests => _ => _ Target RunHtmlPreviewerTests => _ => _
.DependsOn(CompileHtmlPreviewer) .OnlyWhenStatic(() => !(Parameters.SkipTests))
.OnlyWhenStatic(() => !(Parameters.SkipPreviewer || Parameters.SkipTests))
.Executes(() => .Executes(() =>
{ {
var webappTestDir = RootDirectory / "tests" / "Avalonia.DesignerSupport.Tests" / "Remote" / "HtmlTransport" / "webapp"; var webappTest = RootDirectory / "tests" / "Avalonia.DesignerSupport.Tests";
NpmTasks.NpmInstall(c => c DotNetMSBuild(o => o
.SetProcessWorkingDirectory(webappTestDir) .SetProcessWorkingDirectory(webappTest)
.SetProcessArgumentConfigurator(a => a.Add("--silent"))); .SetTargets("BunRunTests"));
NpmTasks.NpmRun(c => c
.SetProcessWorkingDirectory(webappTestDir)
.SetCommand("test"));
}); });
Target RunCoreLibsTests => _ => _ Target RunCoreLibsTests => _ => _
@ -252,9 +267,10 @@ partial class Build : NukeBuild
RunCoreTest("Avalonia.Markup.UnitTests"); RunCoreTest("Avalonia.Markup.UnitTests");
RunCoreTest("Avalonia.Markup.Xaml.UnitTests"); RunCoreTest("Avalonia.Markup.Xaml.UnitTests");
RunCoreTest("Avalonia.Skia.UnitTests"); RunCoreTest("Avalonia.Skia.UnitTests");
RunCoreTest("Avalonia.ReactiveUI.UnitTests"); RunCoreTest("Avalonia.Headless.NUnit.PerAssembly.UnitTests");
RunCoreTest("Avalonia.Headless.NUnit.UnitTests"); RunCoreTest("Avalonia.Headless.NUnit.PerTest.UnitTests");
RunCoreTest("Avalonia.Headless.XUnit.UnitTests"); RunCoreTest("Avalonia.Headless.XUnit.PerAssembly.UnitTests");
RunCoreTest("Avalonia.Headless.XUnit.PerTest.UnitTests");
}); });
Target RunRenderTests => _ => _ Target RunRenderTests => _ => _
@ -263,8 +279,6 @@ partial class Build : NukeBuild
.Executes(() => .Executes(() =>
{ {
RunCoreTest("Avalonia.Skia.RenderTests"); RunCoreTest("Avalonia.Skia.RenderTests");
if (Parameters.IsRunningOnWindows)
RunCoreTest("Avalonia.Direct2D1.RenderTests");
}); });
Target RunToolsTests => _ => _ Target RunToolsTests => _ => _
@ -282,11 +296,7 @@ partial class Build : NukeBuild
.DependsOn(Compile) .DependsOn(Compile)
.Executes(() => .Executes(() =>
{ {
void DoMemoryTest() RunCoreTest("Avalonia.LeakTests");
{
RunCoreTest("Avalonia.LeakTests");
}
ControlFlow.ExecuteWithRetry(DoMemoryTest, delay: TimeSpan.FromMilliseconds(3));
}); });
Target ZipFiles => _ => _ Target ZipFiles => _ => _
@ -313,7 +323,7 @@ partial class Build : NukeBuild
Parameters.Version + ".nupkg", Parameters.Version + ".nupkg",
IlRepackTool); IlRepackTool);
var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config"); var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
EnsureCleanDirectory(Parameters.NugetRoot); Parameters.NugetRoot.CreateOrCleanDirectory();
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config, if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
new NumergeNukeLogger())) new NumergeNukeLogger()))
throw new Exception("Package merge failed"); throw new Exception("Package merge failed");
@ -321,27 +331,56 @@ partial class Build : NukeBuild
Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.nupkg", Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.nupkg",
Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.snupkg"); Parameters.NugetRoot / $"Avalonia.{Parameters.Version}.snupkg");
}); });
Target ValidateApiDiff => _ => _ Target DownloadApiBaselinePackages => _ => _
.DependsOn(CreateNugetPackages) .DependsOn(CreateNugetPackages)
.Executes(async () => .Executes(async () =>
{ {
await Task.WhenAll( GlobalDiff = await ApiDiffHelper.DownloadAndExtractPackagesAsync(
Directory.GetFiles(Parameters.NugetRoot, "*.nupkg").Select(nugetPackage => ApiDiffHelper.ValidatePackage( Directory.EnumerateFiles(Parameters.NugetRoot, "*.nupkg").Select(path => (AbsolutePath)path),
ApiCompatTool, nugetPackage, Parameters.ApiValidationBaseline, NuGetVersion.Parse(Parameters.Version),
Parameters.ApiValidationSuppressionFiles, Parameters.UpdateApiValidationSuppression))); Parameters.IsReleaseBranch,
Parameters.ArtifactsDir / "api-diff" / "assemblies",
Parameters.ForceApiValidationBaseline is { } forcedBaseline ? NuGetVersion.Parse(forcedBaseline) : null);
});
Target ValidateApiDiff => _ => _
.DependsOn(DownloadApiBaselinePackages)
.Executes(() =>
{
var globalDiff = GlobalDiff!;
Parallel.ForEach(
globalDiff.Packages,
packageDiff => ApiDiffHelper.ValidatePackage(
ApiCompatTool,
packageDiff,
Parameters.ArtifactsDir / "api-diff" / "assemblies",
Parameters.ApiValidationSuppressionFiles,
Parameters.UpdateApiValidationSuppression));
}); });
Target OutputApiDiff => _ => _ Target OutputApiDiff => _ => _
.DependsOn(CreateNugetPackages) .DependsOn(DownloadApiBaselinePackages)
.Executes(async () => .Executes(() =>
{ {
await Task.WhenAll( var globalDiff = GlobalDiff!;
Directory.GetFiles(Parameters.NugetRoot, "*.nupkg").Select(nugetPackage => ApiDiffHelper.GetDiff( var outputFolderPath = Parameters.ArtifactsDir / "api-diff" / "markdown";
ApiGenTool, RootDirectory / "api" / "diff", var baselineDisplay = globalDiff.BaselineVersion.ToString();
nugetPackage, Parameters.ApiValidationBaseline))); var currentDisplay = globalDiff.CurrentVersion.ToString();
Parallel.ForEach(
globalDiff.Packages,
packageDiff => ApiDiffHelper.GenerateMarkdownDiff(
ApiDiffTool,
packageDiff,
outputFolderPath,
baselineDisplay,
currentDisplay));
ApiDiffHelper.MergePackageMarkdownDiffFiles(outputFolderPath, baselineDisplay, currentDisplay);
}); });
Target RunTests => _ => _ Target RunTests => _ => _
.DependsOn(RunCoreLibsTests) .DependsOn(RunCoreLibsTests)
.DependsOn(RunRenderTests) .DependsOn(RunRenderTests)
@ -418,7 +457,7 @@ partial class Build : NukeBuild
var artifactsDirectory = buildTestsDirectory / "artifacts"; var artifactsDirectory = buildTestsDirectory / "artifacts";
var nugetCacheDirectory = artifactsDirectory / "nuget-cache"; var nugetCacheDirectory = artifactsDirectory / "nuget-cache";
DeleteDirectory(artifactsDirectory); artifactsDirectory.DeleteDirectory();
BuildTestsAndVerify("Debug"); BuildTestsAndVerify("Debug");
BuildTestsAndVerify("Release"); BuildTestsAndVerify("Release");
@ -432,7 +471,7 @@ partial class Build : NukeBuild
.SetProperty("NuGetPackageRoot", nugetCacheDirectory) .SetProperty("NuGetPackageRoot", nugetCacheDirectory)
.SetPackageDirectory(nugetCacheDirectory) .SetPackageDirectory(nugetCacheDirectory)
.SetProjectFile(buildTestsDirectory / "BuildTests.sln") .SetProjectFile(buildTestsDirectory / "BuildTests.sln")
.SetProcessArgumentConfigurator(arguments => arguments.Add("--nodeReuse:false"))); .SetProcessAdditionalArguments("--nodeReuse:false"));
// Standard compilation - should have compiled XAML // Standard compilation - should have compiled XAML
VerifyBuildTestAssembly("bin", "BuildTests"); VerifyBuildTestAssembly("bin", "BuildTests");
@ -461,7 +500,7 @@ partial class Build : NukeBuild
.SetPackageDirectory(nugetCacheDirectory) .SetPackageDirectory(nugetCacheDirectory)
.SetNoBuild(noBuild) .SetNoBuild(noBuild)
.SetProject(buildTestsDirectory / projectName / (projectName + ".csproj")) .SetProject(buildTestsDirectory / projectName / (projectName + ".csproj"))
.SetProcessArgumentConfigurator(arguments => arguments.Add("--nodeReuse:false"))); .SetProcessAdditionalArguments("--nodeReuse:false"));
void VerifyBuildTestAssembly(string folder, string projectName) void VerifyBuildTestAssembly(string folder, string projectName)
=> XamlCompilationVerifier.VerifyAssemblyCompiledXaml( => XamlCompilationVerifier.VerifyAssemblyCompiledXaml(

52
nukebuild/BuildParameters.cs

@ -1,3 +1,5 @@
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -7,40 +9,35 @@ using System.Xml.Linq;
using Nuke.Common; using Nuke.Common;
using Nuke.Common.CI.AzurePipelines; using Nuke.Common.CI.AzurePipelines;
using Nuke.Common.IO; using Nuke.Common.IO;
using static Nuke.Common.IO.PathConstruction;
public partial class Build public partial class Build
{ {
[Parameter(Name = "configuration")] [Parameter(Name = "configuration")]
public string Configuration { get; set; } public string? Configuration { get; set; }
[Parameter(Name = "skip-tests")] [Parameter(Name = "skip-tests")]
public bool SkipTests { get; set; } public bool SkipTests { get; set; }
[Parameter(Name = "force-nuget-version")] [Parameter(Name = "force-nuget-version")]
public string ForceNugetVersion { get; set; } public string? ForceNugetVersion { get; set; }
[Parameter(Name = "skip-previewer")]
public bool SkipPreviewer { get; set; }
[Parameter(Name = "api-baseline")] [Parameter(Name = "force-api-baseline")]
public string ApiValidationBaseline { get; set; } public string? ForceApiValidationBaseline { get; set; }
[Parameter(Name = "update-api-suppression")] [Parameter(Name = "update-api-suppression")]
public bool? UpdateApiValidationSuppression { get; set; } public bool? UpdateApiValidationSuppression { get; set; }
[Parameter(Name = "version-output-dir")] [Parameter(Name = "version-output-dir")]
public AbsolutePath VersionOutputDir { get; set; } public AbsolutePath? VersionOutputDir { get; set; }
public class BuildParameters public class BuildParameters
{ {
public string Configuration { get; } public string Configuration { get; }
public bool SkipTests { get; } public bool SkipTests { get; }
public bool SkipPreviewer {get;}
public string MainRepo { get; } public string MainRepo { get; }
public string MasterBranch { get; } public string MasterBranch { get; }
public string RepositoryName { get; } public string? RepositoryName { get; }
public string RepositoryBranch { get; } public string? RepositoryBranch { get; }
public string ReleaseConfiguration { get; } public string ReleaseConfiguration { get; }
public Regex ReleaseBranchRegex { get; } public Regex ReleaseBranchRegex { get; }
public string MSBuildSolution { get; } public string MSBuildSolution { get; }
@ -66,21 +63,20 @@ public partial class Build
public AbsolutePath ZipRoot { get; } public AbsolutePath ZipRoot { get; }
public AbsolutePath TestResultsRoot { get; } public AbsolutePath TestResultsRoot { get; }
public string DirSuffix { get; } public string DirSuffix { get; }
public List<string> BuildDirs { get; } public List<AbsolutePath> BuildDirs { get; }
public string FileZipSuffix { get; } public string FileZipSuffix { get; }
public AbsolutePath ZipCoreArtifacts { get; } public AbsolutePath ZipCoreArtifacts { get; }
public AbsolutePath ZipNuGetArtifacts { get; } public AbsolutePath ZipNuGetArtifacts { get; }
public string ApiValidationBaseline { get; } public string? ForceApiValidationBaseline { get; }
public bool UpdateApiValidationSuppression { get; } public bool UpdateApiValidationSuppression { get; }
public AbsolutePath ApiValidationSuppressionFiles { get; } public AbsolutePath ApiValidationSuppressionFiles { get; }
public AbsolutePath VersionOutputDir { get; } public AbsolutePath? VersionOutputDir { get; }
public BuildParameters(Build b, bool isPackingToLocalCache) public BuildParameters(Build b, bool isPackingToLocalCache)
{ {
// ARGUMENTS // ARGUMENTS
Configuration = b.Configuration ?? "Release"; Configuration = b.Configuration ?? "Release";
SkipTests = b.SkipTests; SkipTests = b.SkipTests;
SkipPreviewer = b.SkipPreviewer;
// CONFIGURATION // CONFIGURATION
MainRepo = "https://github.com/AvaloniaUI/Avalonia"; MainRepo = "https://github.com/AvaloniaUI/Avalonia";
@ -115,10 +111,9 @@ public partial class Build
IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch; IsNuGetRelease = IsMainRepo && IsReleasable && IsReleaseBranch;
// VERSION // VERSION
var (propsVersion, propsApiCompatVersion) = GetVersion(); Version = b.ForceNugetVersion ?? GetVersion();
Version = b.ForceNugetVersion ?? propsVersion;
ApiValidationBaseline = b.ApiValidationBaseline ?? propsApiCompatVersion; ForceApiValidationBaseline = b.ForceApiValidationBaseline;
UpdateApiValidationSuppression = b.UpdateApiValidationSuppression ?? IsLocalBuild; UpdateApiValidationSuppression = b.UpdateApiValidationSuppression ?? IsLocalBuild;
if (IsRunningOnAzure) if (IsRunningOnAzure)
@ -126,7 +121,9 @@ public partial class Build
if (!IsNuGetRelease) if (!IsNuGetRelease)
{ {
// Use AssemblyVersion with Build as version // Use AssemblyVersion with Build as version
Version += "-cibuild" + int.Parse(Environment.GetEnvironmentVariable("BUILD_BUILDID")).ToString("0000000") + "-alpha"; var buildId = Environment.GetEnvironmentVariable("BUILD_BUILDID") ??
throw new InvalidOperationException("Missing environment variable BUILD_BUILDID");
Version += "-cibuild" + int.Parse(buildId).ToString("0000000") + "-alpha";
} }
PublishTestResults = true; PublishTestResults = true;
@ -144,10 +141,10 @@ public partial class Build
NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget"; NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget";
ZipRoot = ArtifactsDir / "zip"; ZipRoot = ArtifactsDir / "zip";
TestResultsRoot = ArtifactsDir / "test-results"; TestResultsRoot = ArtifactsDir / "test-results";
BuildDirs = GlobDirectories(RootDirectory, "**/bin") BuildDirs = RootDirectory.GlobDirectories("**/bin")
.Concat(GlobDirectories(RootDirectory, "**/obj")) .Concat(RootDirectory.GlobDirectories("**/obj"))
.Where(dir => !dir.Contains("nukebuild")) .Where(dir => !((string)dir).Contains("nukebuild"))
.Concat(GlobDirectories(RootDirectory, "**/node_modules")) .Concat(RootDirectory.GlobDirectories("**/node_modules"))
.ToList(); .ToList();
DirSuffix = Configuration; DirSuffix = Configuration;
FileZipSuffix = Version + ".zip"; FileZipSuffix = Version + ".zip";
@ -157,13 +154,10 @@ public partial class Build
VersionOutputDir = b.VersionOutputDir; VersionOutputDir = b.VersionOutputDir;
} }
(string Version, string ApiCompatVersion) GetVersion() string GetVersion()
{ {
var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props"); var xdoc = XDocument.Load(RootDirectory / "build/SharedVersion.props");
return ( return xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value;
xdoc.Descendants().First(x => x.Name.LocalName == "Version").Value,
xdoc.Descendants().First(x => x.Name.LocalName == "ApiCompatVersion").Value
);
} }
} }

2
nukebuild/BuildTasksPatcher.cs

@ -85,7 +85,7 @@ public class BuildTasksPatcher
var cecilMdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Mdb.MdbReaderProvider)); var cecilMdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Mdb.MdbReaderProvider));
ilRepackTool.Invoke( ilRepackTool.Invoke(
$"/internalize /out:\"{output}\" \"{temp}\" \"{cecilAsm}\" \"{cecilRocksAsm}\" \"{cecilPdbAsm}\" \"{cecilMdbAsm}\"", $"/internalize /out:\"{output:nq}\" \"{temp:nq}\" \"{cecilAsm:nq}\" \"{cecilRocksAsm:nq}\" \"{cecilPdbAsm:nq}\" \"{cecilMdbAsm:nq}\"",
tempDir); tempDir);
// 'hurr-durr assembly with the same name is already loaded' prevention // 'hurr-durr assembly with the same name is already loaded' prevention

25
nukebuild/ByteArrayEqualityComparer.cs

@ -0,0 +1,25 @@
#nullable enable
using System;
using System.Collections.Generic;
public sealed class ByteArrayEqualityComparer : IEqualityComparer<byte[]>
{
public static ByteArrayEqualityComparer Instance { get; } = new();
public bool Equals(byte[]? x, byte[]? y) {
if (ReferenceEquals(x, y))
return true;
if (x is null || y is null)
return false;
return x.AsSpan().SequenceEqual(y.AsSpan());
}
public int GetHashCode(byte[]? obj)
{
var hashCode = new HashCode();
hashCode.AddBytes(obj.AsSpan());
return hashCode.ToHashCode();
}
}

20
nukebuild/_build.csproj

@ -9,25 +9,17 @@
<TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework> <TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework>
<!-- See https://github.com/nuke-build/nuke/issues/818 --> <!-- See https://github.com/nuke-build/nuke/issues/818 -->
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
<!-- Necessary for Microsoft.DotNet.GenAPI.Tool -->
<RestoreAdditionalProjectSources>https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8-transport/nuget/v3/index.json</RestoreAdditionalProjectSources>
</PropertyGroup> </PropertyGroup>
<Import Project="..\build\JetBrains.dotMemoryUnit.props" />
<ItemGroup> <ItemGroup>
<PackageReference Include="Nuke.Common" Version="6.2.1" /> <PackageReference Include="Nuke.Common" Version="9.0.4" />
<PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " />
<PackageReference Include="MicroCom.CodeGenerator" Version="0.11.0" /> <PackageReference Include="MicroCom.CodeGenerator" Version="0.11.0" />
<!-- Keep in sync with Avalonia.Build.Tasks --> <!-- Keep in sync with Avalonia.Build.Tasks -->
<PackageReference Include="Mono.Cecil" Version="0.11.5" /> <PackageReference Include="Mono.Cecil" Version="0.11.6" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.3.2" PrivateAssets="All" /> <PackageReference Include="Microsoft.Build.Framework" Version="18.0.2" PrivateAssets="All" />
<PackageReference Include="xunit.runner.console" Version="2.4.2"> <PackageReference Include="NuGet.Protocol" Version="7.0.1" />
<PrivateAssets>all</PrivateAssets> <PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[10.0.100]" />
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PackageDownload Include="Microsoft.DotNet.ApiDiff.Tool" Version="[10.0.100-rtm.25531.102]" />
</PackageReference>
<PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[8.0.200]" />
<PackageDownload Include="Microsoft.DotNet.GenAPI.Tool" Version="[8.0.300-preview.24115.44]" />
<PackageDownload Include="dotnet-ilrepack" Version="[1.0.0]" /> <PackageDownload Include="dotnet-ilrepack" Version="[1.0.0]" />
</ItemGroup> </ItemGroup>

12
packages/Avalonia/Avalonia.csproj

@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>$(AvsCurrentTargetFramework);$(AvsLegacyTargetFrameworks);netstandard2.0</TargetFrameworks> <TargetFrameworks>$(AvsCurrentTargetFramework);$(AvsLegacyTargetFrameworks)</TargetFrameworks>
<PackageId>Avalonia</PackageId> <PackageId>Avalonia</PackageId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Avalonia.BuildServices" Version="0.0.31" /> <PackageReference Include="Avalonia.BuildServices" Version="11.3.2" />
<ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" /> <ProjectReference Include="../../src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj" />
<ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj" <ProjectReference Include="../../src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj"
PrivateAssets="all" /> PrivateAssets="all" />
@ -27,13 +27,13 @@
<MSBuild Projects="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj" Properties="Configuration=$(Configuration);&#xA;Platform=$(Platform)" /> <MSBuild Projects="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj" Properties="Configuration=$(Configuration);&#xA;Platform=$(Platform)" />
<ItemGroup> <ItemGroup>
<_PackageFiles Include="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/bin/$(Configuration)/netstandard2.0/Avalonia.Designer.HostApp.dll"> <_PackageFiles Include="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/bin/$(Configuration)/$(AvsCurrentTargetFramework)/Avalonia.Designer.HostApp.dll">
<PackagePath>tools/netstandard2.0/designer</PackagePath> <PackagePath>tools/$(AvsCurrentTargetFramework)/designer</PackagePath>
<Visible>false</Visible> <Visible>false</Visible>
<BuildAction>None</BuildAction> <BuildAction>None</BuildAction>
</_PackageFiles> </_PackageFiles>
<_PackageFiles Include="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/bin/$(Configuration)/net461/Avalonia.Designer.HostApp.exe"> <_PackageFiles Include="$(DesignerHostAppPath)/Avalonia.Designer.HostApp/bin/$(Configuration)/$(AvsLegacyTargetFrameworks)/Avalonia.Designer.HostApp.dll">
<PackagePath>tools/net461/designer</PackagePath> <PackagePath>tools/$(AvsLegacyTargetFrameworks)/designer</PackagePath>
<Visible>false</Visible> <Visible>false</Visible>
<BuildAction>None</BuildAction> <BuildAction>None</BuildAction>
</_PackageFiles> </_PackageFiles>

5
packages/Avalonia/Avalonia.props

@ -1,12 +1,11 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\designer\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath> <AvaloniaPreviewerNetCoreToolPath>$(MSBuildThisFileDirectory)\..\tools\$(AvsCurrentTargetFramework)\designer\Avalonia.Designer.HostApp.dll</AvaloniaPreviewerNetCoreToolPath>
<AvaloniaPreviewerNetFullToolPath>$(MSBuildThisFileDirectory)\..\tools\net461\designer\Avalonia.Designer.HostApp.exe</AvaloniaPreviewerNetFullToolPath>
<AvaloniaBuildTasksLocation>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Avalonia.Build.Tasks.dll</AvaloniaBuildTasksLocation> <AvaloniaBuildTasksLocation>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Avalonia.Build.Tasks.dll</AvaloniaBuildTasksLocation>
<UsedAvaloniaProducts>$(UsedAvaloniaProducts);AvaloniaUI</UsedAvaloniaProducts> <UsedAvaloniaProducts>$(UsedAvaloniaProducts);AvaloniaUI</UsedAvaloniaProducts>
<EnableAvaloniaXamlCompilation Condition="'$(EnableAvaloniaXamlCompilation)'==''">true</EnableAvaloniaXamlCompilation> <EnableAvaloniaXamlCompilation Condition="'$(EnableAvaloniaXamlCompilation)'==''">true</EnableAvaloniaXamlCompilation>
<AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)'==''">false</AvaloniaXamlIlVerifyIl> <AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)'==''">false</AvaloniaXamlIlVerifyIl>
<AvaloniaUseCompiledBindingsByDefault Condition="'$(AvaloniaUseCompiledBindingsByDefault)'==''">false</AvaloniaUseCompiledBindingsByDefault> <AvaloniaUseCompiledBindingsByDefault Condition="'$(AvaloniaUseCompiledBindingsByDefault)'==''">true</AvaloniaUseCompiledBindingsByDefault>
<AvaloniaNameGeneratorAttachDevTools Condition="'$(AvaloniaNameGeneratorAttachDevTools)' == ''">true</AvaloniaNameGeneratorAttachDevTools> <AvaloniaNameGeneratorAttachDevTools Condition="'$(AvaloniaNameGeneratorAttachDevTools)' == ''">true</AvaloniaNameGeneratorAttachDevTools>
</PropertyGroup> </PropertyGroup>
<Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.props"/> <Import Project="$(MSBuildThisFileDirectory)\AvaloniaBuildTasks.props"/>

2
packages/Avalonia/AvaloniaPrivateApis.targets

@ -13,7 +13,7 @@
</Target> </Target>
<Target Name="AddReferencePathsToRealAvaloniaAssemblies" BeforeTargets="CoreCompile" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'"> <Target Name="AddReferencePathsToRealAvaloniaAssemblies" BeforeTargets="CoreCompile" Condition="'$(AvaloniaAccessUnstablePrivateApis.ToLowerInvariant())'=='true'">
<PropertyGroup> <PropertyGroup>
<AvaloniaUnstableApiFrameworkToUse>net6.0</AvaloniaUnstableApiFrameworkToUse> <AvaloniaUnstableApiFrameworkToUse>net8.0</AvaloniaUnstableApiFrameworkToUse>
<AvaloniaUnstableApiFrameworkToUse Condition="$(TargetFramework.StartsWith('net4')) == 'true' or $(TargetFramework.StartsWith('net5')) == 'true' or $(TargetFramework.StartsWith('netsta')) == 'true' or $(TargetFramework.StartsWith('netcore')) == 'true'">netstandard2.0</AvaloniaUnstableApiFrameworkToUse> <AvaloniaUnstableApiFrameworkToUse Condition="$(TargetFramework.StartsWith('net4')) == 'true' or $(TargetFramework.StartsWith('net5')) == 'true' or $(TargetFramework.StartsWith('netsta')) == 'true' or $(TargetFramework.StartsWith('netcore')) == 'true'">netstandard2.0</AvaloniaUnstableApiFrameworkToUse>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

4
packages/Avalonia/AvaloniaSingleProject.targets

@ -98,7 +98,7 @@
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tvos'">13.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tvos'">13.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">10.15</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'macos'">10.15</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">13.1</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
</PropertyGroup> </PropertyGroup>
@ -278,7 +278,7 @@
Include="$(TizenSharedPrefix)\**\*" Include="$(TizenSharedPrefix)\**\*"
Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);@(TizenTpkUserExcludeFiles)" /> Exclude="$(DefaultItemExcludes);$(DefaultExcludesInProjectFolder);@(TizenTpkUserExcludeFiles)" />
</ItemGroup> </ItemGroup>
<!-- Android workaround to allow projects without AndroidManifest.xml, as it used to be supported --> <!-- Android workaround to allow projects without AndroidManifest.xml, as it used to be supported -->
<Target Name="BeforeGetAndroidPackageName" <Target Name="BeforeGetAndroidPackageName"
BeforeTargets="_GetAndroidPackageName"> BeforeTargets="_GetAndroidPackageName">

2
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -26,7 +26,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.4" /> <PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1.17" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

10
samples/ControlCatalog.Browser.Blazor/App.razor

@ -1,10 +0,0 @@
<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

10
samples/ControlCatalog.Browser.Blazor/App.razor.cs

@ -1,10 +0,0 @@
using System;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Browser.Blazor;
namespace ControlCatalog.Browser.Blazor;
public partial class App
{
}

29
samples/ControlCatalog.Browser.Blazor/ControlCatalog.Browser.Blazor.csproj

@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>$(AvsCurrentBrowserTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<Nullable>enable</Nullable>
<EmccTotalMemory>16777216</EmccTotalMemory>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Browser\Avalonia.Browser.Blazor\Avalonia.Browser.Blazor.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.props" />
<Import Project="..\..\src\Browser\Avalonia.Browser\build\Avalonia.Browser.targets" />
</Project>

5
samples/ControlCatalog.Browser.Blazor/Pages/Index.razor

@ -1,5 +0,0 @@
@page "/"
@using Avalonia.Browser.Blazor
<AvaloniaView />

39
samples/ControlCatalog.Browser.Blazor/Program.cs

@ -1,39 +0,0 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Browser.Blazor;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using ControlCatalog.Browser.Blazor;
public class Program
{
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await StartAvaloniaApp();
await host.RunAsync();
}
public static async Task StartAvaloniaApp()
{
await AppBuilder.Configure<ControlCatalog.App>()
.StartBlazorAppAsync();
}
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
return builder;
}
}

22
samples/ControlCatalog.Browser.Blazor/Properties/launchSettings.json

@ -1,22 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:13961",
"sslPort": 44319
}
},
"profiles": {
"ControlCatalog.Web": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

7
samples/ControlCatalog.Browser.Blazor/Shared/MainLayout.razor

@ -1,7 +0,0 @@
@inherits LayoutComponentBase
<div class="page">
<div class="main">
@Body
</div>
</div>

10
samples/ControlCatalog.Browser.Blazor/_Imports.razor

@ -1,10 +0,0 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using ControlCatalog.Browser.Blazor.Shared
@using SkiaSharp

56
samples/ControlCatalog.Browser.Blazor/wwwroot/css/app.css

@ -1,56 +0,0 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
margin: 0;
height: 100vh;
overflow: hidden;
touch-action: none;
}
a, .btn-link {
color: #0366d6;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.content {
padding-top: 1.1rem;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid red;
}
.validation-message {
color: red;
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
#app, .page {
height: 100%;
}

BIN
samples/ControlCatalog.Browser.Blazor/wwwroot/favicon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

22
samples/ControlCatalog.Browser.Blazor/wwwroot/index.html

@ -1,22 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Avalonia Sample</title>
<base href="/" />
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<div id="app">Powered by Avalonia</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>

35
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@ -1,22 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>WinExe</OutputType>
<TargetFramework>net461</TargetFramework> <TargetFramework>$(AvsCurrentTargetFramework)</TargetFramework>
<PlatformTarget>x64</PlatformTarget> <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>../ControlCatalog.NetCore/app.manifest</ApplicationManifest>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> <Compile Include="..\..\src\Avalonia.X11\NativeDialogs\Gtk.cs" Link="NativeControls\Gtk\Gtk.cs" />
<ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" /> <Compile Include="..\..\src\Avalonia.X11\Interop\Glib.cs" Link="NativeControls\Gtk\Glib.cs" />
<Compile Include="..\..\src\Avalonia.Base\Platform\Interop\Utf8Buffer.cs" Link="NativeControls\Utf8Buffer.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="NativeControls\Gtk\nodes.mp4">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\ControlCatalog.NetCore\NativeControls\Win\*.cs" Link="NativeControls\*" /> <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
<ProjectReference Include="..\..\src\Headless\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
<ProjectReference Include="..\..\src\Avalonia.X11\Avalonia.X11.csproj" />
<!-- For native controls test -->
<PackageReference Include="MonoMac.NetStandard" Version="0.0.4" />
</ItemGroup> </ItemGroup>
<PropertyGroup>
<!-- For Microsoft.CodeAnalysis -->
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<Import Project="..\..\build\SampleApp.props" /> <Import Project="..\..\build\SampleApp.props" />
<Import Project="..\..\build\NetFX.props" /> <Import Project="..\..\build\ReferenceCoreLibraries.props" />
</Project> </Project>

2
samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs → samples/ControlCatalog.Desktop/NativeControls/Gtk/EmbedSample.Gtk.cs

@ -5,7 +5,7 @@ using Avalonia.Controls.Platform;
using System; using System;
using ControlCatalog.Pages; using ControlCatalog.Pages;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
public class EmbedSampleGtk : INativeDemoControl public class EmbedSampleGtk : INativeDemoControl
{ {

2
samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs → samples/ControlCatalog.Desktop/NativeControls/Gtk/GtkHelper.cs

@ -7,7 +7,7 @@ using Avalonia.X11.NativeDialogs;
using static Avalonia.X11.NativeDialogs.Gtk; using static Avalonia.X11.NativeDialogs.Gtk;
using static Avalonia.X11.Interop.Glib; using static Avalonia.X11.Interop.Glib;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
internal class GtkHelper internal class GtkHelper
{ {

0
samples/ControlCatalog.NetCore/NativeControls/Gtk/nodes-license.md → samples/ControlCatalog.Desktop/NativeControls/Gtk/nodes-license.md

0
samples/ControlCatalog.NetCore/NativeControls/Gtk/nodes.mp4 → samples/ControlCatalog.Desktop/NativeControls/Gtk/nodes.mp4

2
samples/ControlCatalog.NetCore/NativeControls/Mac/EmbedSample.Mac.cs → samples/ControlCatalog.Desktop/NativeControls/Mac/EmbedSample.Mac.cs

@ -8,7 +8,7 @@ using ControlCatalog.Pages;
using MonoMac.Foundation; using MonoMac.Foundation;
using MonoMac.WebKit; using MonoMac.WebKit;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
public class EmbedSampleMac : INativeDemoControl public class EmbedSampleMac : INativeDemoControl
{ {

2
samples/ControlCatalog.NetCore/NativeControls/Mac/MacHelper.cs → samples/ControlCatalog.Desktop/NativeControls/Mac/MacHelper.cs

@ -3,7 +3,7 @@ using System;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using MonoMac.AppKit; using MonoMac.AppKit;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
internal class MacHelper internal class MacHelper
{ {

2
samples/ControlCatalog.NetCore/NativeControls/Win/EmbedSample.Win.cs → samples/ControlCatalog.Desktop/NativeControls/Win/EmbedSample.Win.cs

@ -6,7 +6,7 @@ using Avalonia.Platform;
using ControlCatalog.Pages; using ControlCatalog.Pages;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
public class EmbedSampleWin : INativeDemoControl public class EmbedSampleWin : INativeDemoControl
{ {

2
samples/ControlCatalog.NetCore/NativeControls/Win/WinApi.cs → samples/ControlCatalog.Desktop/NativeControls/Win/WinApi.cs

@ -1,7 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ControlCatalog.NetCore; namespace ControlCatalog.Desktop;
internal unsafe class WinApi internal unsafe class WinApi
{ {

172
samples/ControlCatalog.Desktop/Program.cs

@ -1,38 +1,180 @@
using System; using System;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Avalonia; using Avalonia;
using Avalonia.Platform; using Avalonia.Controls;
using ControlCatalog.NetCore; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Fonts.Inter;
using Avalonia.Headless;
using Avalonia.LinuxFramebuffer.Output;
using Avalonia.LogicalTree;
using Avalonia.Rendering.Composition;
using Avalonia.Threading;
using Avalonia.Vulkan;
using ControlCatalog.Pages; using ControlCatalog.Pages;
namespace ControlCatalog namespace ControlCatalog.Desktop
{ {
internal class Program static class Program
{ {
private static bool s_useFramebuffer;
[STAThread] [STAThread]
public static int Main(string[] args) static int Main(string[] args)
=> BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); {
if (args.Contains("--fbdev"))
{
s_useFramebuffer = true;
}
if (args.Contains("--wait-for-attach"))
{
Console.WriteLine("Attach debugger and use 'Set next statement'");
while (true)
{
Thread.Sleep(100);
if (Debugger.IsAttached)
break;
}
}
var builder = BuildAvaloniaApp();
double GetScaling()
{
var idx = Array.IndexOf(args, "--scaling");
if (idx != 0 && args.Length > idx + 1 &&
double.TryParse(args[idx + 1], NumberStyles.Any, CultureInfo.InvariantCulture, out var scaling))
return scaling;
return 1;
}
if (s_useFramebuffer)
{
SilenceConsole();
return builder.StartLinuxFbDev(args, new FbDevOutputOptions()
{
Scaling = GetScaling()
});
}
else if (args.Contains("--vnc"))
{
return builder.StartWithHeadlessVncPlatform(null, 5901, args, ShutdownMode.OnMainWindowClose);
}
else if (args.Contains("--full-headless"))
{
return builder
.UseHeadless(new AvaloniaHeadlessPlatformOptions
{
UseHeadlessDrawing = true
})
.AfterSetup(_ =>
{
DispatcherTimer.RunOnce(async () =>
{
var window = ((IClassicDesktopStyleApplicationLifetime)Application.Current.ApplicationLifetime)
.MainWindow;
var tc = window.GetLogicalDescendants().OfType<TabControl>().First();
foreach (var page in tc.Items.Cast<TabItem>().ToList())
{
if (page.Header.ToString() == "DatePicker" || page.Header.ToString() == "TreeView")
continue;
Console.WriteLine("Selecting " + page.Header);
tc.SelectedItem = page;
await Task.Delay(50);
}
Console.WriteLine("Selecting the first page");
tc.SelectedItem = tc.Items.OfType<object>().First();
await Task.Delay(500);
Console.WriteLine("Clicked through all pages, triggering GC");
for (var c = 0; c < 3; c++)
{
GC.Collect(2, GCCollectionMode.Forced);
await Task.Delay(50);
}
void FormatMem(string metric, long bytes)
{
Console.WriteLine(metric + ": " + bytes / 1024 / 1024 + "MB");
}
FormatMem("GC allocated bytes", GC.GetTotalMemory(true));
FormatMem("WorkingSet64", Process.GetCurrentProcess().WorkingSet64);
}, TimeSpan.FromSeconds(1));
})
.StartWithClassicDesktopLifetime(args);
}
else if (args.Contains("--drm"))
{
SilenceConsole();
return builder.StartLinuxDrm(args, scaling: GetScaling());
}
else if (args.Contains("--dxgi"))
{
builder.With(new Win32PlatformOptions()
{
CompositionMode = new [] { Win32CompositionMode.LowLatencyDxgiSwapChain }
});
return builder.StartWithClassicDesktopLifetime(args);
}
else
return builder.StartWithClassicDesktopLifetime(args);
}
/// <summary> /// <summary>
/// This method is needed for IDE previewer infrastructure /// This method is needed for IDE previewer infrastructure
/// </summary> /// </summary>
public static AppBuilder BuildAvaloniaApp() public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>() => AppBuilder.Configure<App>()
.LogToTrace() .UsePlatformDetect()
.With(new X11PlatformOptions
{
EnableMultiTouch = true,
UseDBusMenu = true,
EnableIme = true,
})
.With(new VulkanOptions
{
VulkanInstanceCreationOptions = new ()
{
UseDebug = true
}
})
.With(new CompositionOptions()
{
UseRegionDirtyRectClipping = true
})
.UseSkia()
.WithInterFont()
.AfterSetup(builder => .AfterSetup(builder =>
{ {
builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions() if (!s_useFramebuffer)
{ {
StartupScreenIndex = 1, builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
}); {
StartupScreenIndex = 1,
});
}
EmbedSample.Implementation = new EmbedSampleWin(); EmbedSample.Implementation = OperatingSystem.IsWindows() ? (INativeDemoControl)new EmbedSampleWin()
: OperatingSystem.IsMacOS() ? new EmbedSampleMac()
: OperatingSystem.IsLinux() ? new EmbedSampleGtk()
: null;
}) })
.UseWin32() .LogToTrace();
.UseSkia();
private static void ConfigureAssetAssembly(AppBuilder builder) static void SilenceConsole()
{ {
AssetLoader.SetDefaultAssembly(typeof(App).Assembly); new Thread(() =>
{
Console.CursorVisible = false;
while (true)
Console.ReadKey(true);
})
{ IsBackground = true }.Start();
} }
} }
} }

2
samples/ControlCatalog.NetCore/Properties/launchSettings.json → samples/ControlCatalog.Desktop/Properties/launchSettings.json

@ -1,6 +1,6 @@
{ {
"profiles": { "profiles": {
"ControlCatalog.NetCore": { "ControlCatalog.Desktop": {
"commandName": "Project" "commandName": "Project"
}, },
"Dxgi": { "Dxgi": {

0
samples/ControlCatalog.NetCore/app.manifest → samples/ControlCatalog.Desktop/app.manifest

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

Loading…
Cancel
Save