Browse Source

Merge branch 'master' into feature/media-queries

pull/7938/head
Emmanuel Hansen 2 years ago
committed by GitHub
parent
commit
c4172b0d3c
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 8
      .github/pr_labels.yml
  2. 3
      .gitmodules
  3. 29
      Avalonia.sln
  4. 13
      Avalonia.sln.DotSettings
  5. 9
      Documentation/build.md
  6. 88
      api/Avalonia.Android.nupkg.xml
  7. 14
      api/Avalonia.Browser.nupkg.xml
  8. 76
      api/Avalonia.Controls.ColorPicker.nupkg.xml
  9. 16
      api/Avalonia.Controls.DataGrid.nupkg.xml
  10. 64
      api/Avalonia.Diagnostics.nupkg.xml
  11. 10
      api/Avalonia.FreeDesktop.nupkg.xml
  12. 6
      api/Avalonia.Skia.nupkg.xml
  13. 448
      api/Avalonia.Themes.Fluent.nupkg.xml
  14. 424
      api/Avalonia.Themes.Simple.nupkg.xml
  15. 16
      api/Avalonia.iOS.nupkg.xml
  16. 1090
      api/Avalonia.nupkg.xml
  17. 18
      azure-pipelines-integrationtests.yml
  18. 3
      build/Base.props
  19. 2
      build/ImageSharp.props
  20. 13
      build/SampleApp.props
  21. 1
      build/SharedVersion.props
  22. 2
      build/SourceLink.props
  23. 3
      build/TrimmingEnable.props
  24. 2
      global.json
  25. 2
      native/Avalonia.Native/inc/comimpl.h
  26. 26
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  27. 2
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme
  28. 13
      native/Avalonia.Native/src/OSX/AvnAccessibility.h
  29. 18
      native/Avalonia.Native/src/OSX/AvnAutomationNode.h
  30. 8
      native/Avalonia.Native/src/OSX/AvnView.h
  31. 163
      native/Avalonia.Native/src/OSX/AvnView.mm
  32. 56
      native/Avalonia.Native/src/OSX/AvnWindow.mm
  33. 4
      native/Avalonia.Native/src/OSX/INSWindowHolder.h
  34. 9
      native/Avalonia.Native/src/OSX/PopupImpl.h
  35. 12
      native/Avalonia.Native/src/OSX/PopupImpl.mm
  36. 93
      native/Avalonia.Native/src/OSX/Screens.mm
  37. 144
      native/Avalonia.Native/src/OSX/StorageProvider.mm
  38. 77
      native/Avalonia.Native/src/OSX/TopLevelImpl.h
  39. 285
      native/Avalonia.Native/src/OSX/TopLevelImpl.mm
  40. 56
      native/Avalonia.Native/src/OSX/WindowBaseImpl.h
  41. 238
      native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
  42. 34
      native/Avalonia.Native/src/OSX/WindowImpl.h
  43. 66
      native/Avalonia.Native/src/OSX/WindowImpl.mm
  44. 8
      native/Avalonia.Native/src/OSX/WindowInterfaces.h
  45. 2
      native/Avalonia.Native/src/OSX/WindowProtocol.h
  46. 5
      native/Avalonia.Native/src/OSX/automation.h
  47. 172
      native/Avalonia.Native/src/OSX/automation.mm
  48. 13
      native/Avalonia.Native/src/OSX/common.h
  49. 30
      native/Avalonia.Native/src/OSX/main.mm
  50. 1
      native/Avalonia.Native/src/OSX/menu.mm
  51. 16
      nukebuild/Build.cs
  52. 12
      nukebuild/BuildParameters.cs
  53. 34
      nukebuild/BuildTasksPatcher.cs
  54. 4
      nukebuild/_build.csproj
  55. 5
      nukebuild/_build.csproj.DotSettings
  56. 1
      nukebuild/il-repack
  57. 34
      packages/Avalonia/AvaloniaBuildTasks.targets
  58. 16
      readme.md
  59. 21
      samples/ControlCatalog.Android/MainActivity.cs
  60. 15
      samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj
  61. 2
      samples/ControlCatalog.Browser/EmbedSample.Browser.cs
  62. 9
      samples/ControlCatalog.Browser/Program.cs
  63. 5
      samples/ControlCatalog.Browser/wwwroot/Logo.svg
  64. 46
      samples/ControlCatalog.Browser/wwwroot/app.css
  65. 16
      samples/ControlCatalog.Browser/wwwroot/index.html
  66. 3
      samples/ControlCatalog.Browser/wwwroot/main.js
  67. 5
      samples/ControlCatalog.Desktop/Program.cs
  68. 2
      samples/ControlCatalog/ControlCatalog.csproj
  69. 6
      samples/ControlCatalog/MainView.xaml
  70. 10
      samples/ControlCatalog/MainView.xaml.cs
  71. 5
      samples/ControlCatalog/Pages/DataGridPage.xaml
  72. 6
      samples/ControlCatalog/Pages/DataGridPage.xaml.cs
  73. 74
      samples/ControlCatalog/Pages/DateTimePickerPage.xaml
  74. 2
      samples/ControlCatalog/Pages/DateTimePickerPage.xaml.cs
  75. 52
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  76. 30
      samples/ControlCatalog/Pages/OpenGl/GlPageKnobs.xaml
  77. 70
      samples/ControlCatalog/Pages/OpenGl/GlPageKnobs.xaml.cs
  78. 311
      samples/ControlCatalog/Pages/OpenGl/OpenGlContent.cs
  79. 118
      samples/ControlCatalog/Pages/OpenGl/OpenGlFbo.cs
  80. 10
      samples/ControlCatalog/Pages/OpenGl/OpenGlLeasePage.xaml
  81. 216
      samples/ControlCatalog/Pages/OpenGl/OpenGlLeasePage.xaml.cs
  82. 30
      samples/ControlCatalog/Pages/OpenGlPage.xaml
  83. 391
      samples/ControlCatalog/Pages/OpenGlPage.xaml.cs
  84. 32
      samples/ControlCatalog/Pages/ProgressBarPage.xaml
  85. 78
      samples/ControlCatalog/Pages/ScreenPage.cs
  86. 11
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  87. 6
      samples/ControlCatalog/Pages/ToolTipPage.xaml.cs
  88. 3
      samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs
  89. 3
      samples/GpuInterop/VulkanDemo/VulkanImage.cs
  90. 27
      samples/IntegrationTestApp/App.axaml
  91. 19
      samples/IntegrationTestApp/App.axaml.cs
  92. 19
      samples/IntegrationTestApp/DelegateCommand.cs
  93. 9
      samples/IntegrationTestApp/Embedding/INativeControlFactory.cs
  94. 16
      samples/IntegrationTestApp/Embedding/MacHelper.cs
  95. 20
      samples/IntegrationTestApp/Embedding/MacOSTextBoxFactory.cs
  96. 19
      samples/IntegrationTestApp/Embedding/MacOSViewHandle.cs
  97. 20
      samples/IntegrationTestApp/Embedding/NativeTextBox.cs
  98. 21
      samples/IntegrationTestApp/Embedding/Win32TextBoxFactory.cs
  99. 11
      samples/IntegrationTestApp/Embedding/Win32WindowControlHandle.cs
  100. 82
      samples/IntegrationTestApp/Embedding/WinApi.cs

8
.github/pr_labels.yml

@ -0,0 +1,8 @@
version: '1.1.0'
invalidStatus: "pending"
labelRule:
values:
- "bug"
- "feature"
- "enhancement"
- "area-infrastructure"

3
.gitmodules

@ -4,6 +4,3 @@
[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"]
path = src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
url = https://github.com/kekekeks/XamlX.git
[submodule "nukebuild/il-repack"]
path = nukebuild/il-repack
url = https://github.com/Gillibald/il-repack

29
Avalonia.sln

@ -116,19 +116,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\SourceGenerators.props = build\SourceGenerators.props
build\SourceLink.props = build\SourceLink.props
build\System.Memory.props = build\System.Memory.props
build\TargetFrameworks.props = build\TargetFrameworks.props
build\TrimmingEnable.props = build\TrimmingEnable.props
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\XUnit.props = build\XUnit.props
build\TargetFrameworks.props = build\TargetFrameworks.props
build\WarnAsErrors.props = build\WarnAsErrors.props
build\XUnit.props = build\XUnit.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
ProjectSection(SolutionItems) = preProject
build\BuildTargets.targets = build\BuildTargets.targets
build\DevSingleProject.targets = build\DevSingleProject.targets
build\LegacyProject.targets = build\LegacyProject.targets
build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets
build\DevSingleProject.targets = build\DevSingleProject.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}"
@ -232,8 +232,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{176582E8-46AF-416A-85C1-13A5C6744497}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
azure-pipelines.yml = azure-pipelines.yml
azure-pipelines-integrationtests.yml = azure-pipelines-integrationtests.yml
azure-pipelines.yml = azure-pipelines.yml
CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md
CONTRIBUTING.md = CONTRIBUTING.md
Directory.Build.props = Directory.Build.props
@ -283,24 +283,23 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Tizen", "sam
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Metal", "src\Avalonia.Metal\Avalonia.Metal.csproj", "{60B4ED1F-ECFA-453B-8A70-1788261C8355}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "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}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestFiles", "TestFiles", "{9D6AEF22-221F-4F4B-B335-A4BA510F002C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "BuildTasks", "BuildTasks", "{5BF0C3B8-E595-4940-AB30-2DA206C2F085}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PInvoke", "tests\TestFiles\BuildTasks\PInvoke\PInvoke.csproj", "{0A948D71-99C5-43E9-BACB-B0BA59EA25B4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PInvoke", "tests\TestFiles\BuildTasks\PInvoke\PInvoke.csproj", "{0A948D71-99C5-43E9-BACB-B0BA59EA25B4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnloadableAssemblyLoadContext", "UnloadableAssemblyLoadContext", "{9CCA131B-DE95-4D44-8788-C3CAE28574CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnloadableAssemblyLoadContext", "samples\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContext.csproj", "{D7FE3E0F-3FE0-4F87-A2F5-24F1454D84C0}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnloadableAssemblyLoadContext", "samples\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContext.csproj", "{D7FE3E0F-3FE0-4F87-A2F5-24F1454D84C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnloadableAssemblyLoadContextPlug", "samples\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContextPlug\UnloadableAssemblyLoadContextPlug.csproj", "{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnloadableAssemblyLoadContextPlug", "samples\UnloadableAssemblyLoadContext\UnloadableAssemblyLoadContextPlug\UnloadableAssemblyLoadContextPlug.csproj", "{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Vulkan", "src\Avalonia.Vulkan\Avalonia.Vulkan.csproj", "{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Vulkan", "src\Avalonia.Vulkan\Avalonia.Vulkan.csproj", "{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.RenderTests.WpfCompare", "tests\Avalonia.RenderTests.WpfCompare\Avalonia.RenderTests.WpfCompare.csproj", "{9AE1B827-21AC-4063-AB22-C8804B7F931E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.RenderTests.WpfCompare", "tests\Avalonia.RenderTests.WpfCompare\Avalonia.RenderTests.WpfCompare.csproj", "{9AE1B827-21AC-4063-AB22-C8804B7F931E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -678,10 +677,6 @@ Global
{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.Build.0 = Release|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.Build.0 = Release|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B0FD6A48-FBAB-4676-B36A-DE76B0922B12}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -698,6 +693,10 @@ Global
{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA5F1FF9-4259-4C54-B443-85CFA226EE6A}.Release|Any CPU.Build.0 = Release|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E2DE2B6-13BC-4C27-BCB9-A423B86CAF77}.Release|Any CPU.Build.0 = Release|Any CPU
{9AE1B827-21AC-4063-AB22-C8804B7F931E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9AE1B827-21AC-4063-AB22-C8804B7F931E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9AE1B827-21AC-4063-AB22-C8804B7F931E}.Release|Any CPU.ActiveCfg = Release|Any CPU

13
Avalonia.sln.DotSettings

@ -36,7 +36,20 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=15b5b1f1_002D457c_002D4ca6_002Db278_002D5615aedc07d3/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static readonly fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=236f7aa5_002D7b06_002D43ca_002Dbf2a_002D9b31bfcff09a/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Private" Description="Constant fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=2c62818f_002D621b_002D4425_002Dadc9_002D78611099bfcb/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Type parameters"&gt;&lt;ElementKinds&gt;&lt;Kind Name="TYPE_PARAMETER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=61a991a4_002Dd0a3_002D4d19_002D90a5_002Df8f4d75c30c1/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Local variables"&gt;&lt;ElementKinds&gt;&lt;Kind Name="LOCAL_VARIABLE" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=669e5282_002Dfb4b_002D4e90_002D91e7_002D07d269d04b60/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Constant fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="CONSTANT_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8a85b61a_002D1024_002D4f87_002Db9ef_002D1fdae19930a1/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Parameters"&gt;&lt;ElementKinds&gt;&lt;Kind Name="PARAMETER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=8b8504e3_002Df0be_002D4c14_002D9103_002Dc732f2bddc15/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Enum members"&gt;&lt;ElementKinds&gt;&lt;Kind Name="ENUM_MEMBER" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a0b4bc4d_002Dd13b_002D4a37_002Db37e_002Dc9c6864e4302/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Types and namespaces"&gt;&lt;ElementKinds&gt;&lt;Kind Name="NAMESPACE" /&gt;&lt;Kind Name="CLASS" /&gt;&lt;Kind Name="STRUCT" /&gt;&lt;Kind Name="ENUM" /&gt;&lt;Kind Name="DELEGATE" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=a7a3339e_002D4e89_002D4319_002D9735_002Da9dc4cb74cc7/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Any" AccessRightKinds="Any" Description="Interfaces"&gt;&lt;ElementKinds&gt;&lt;Kind Name="INTERFACE" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="False" Prefix="I" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=c873eafb_002Dd57f_002D481d_002D8c93_002D77f6863c2f88/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Protected, ProtectedInternal, Internal, Public, PrivateProtected" Description="Static readonly fields (not private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EFeature_002EServices_002EDaemon_002ESettings_002EMigration_002ESwaWarningsModeSettingsMigrate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Activatable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Avalonia/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fcitx/@EntryIndexedValue">True</s:Boolean>

9
Documentation/build.md

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

88
api/Avalonia.Android.nupkg.xml

@ -2,93 +2,15 @@
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Animation</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Animator</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Attribute</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Boolean</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Color</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Dimension</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Drawable</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Id</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Integer</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Interpolator</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Layout</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.String</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Style</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<Right>target/net8.0-android34.0/Avalonia.Android.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Avalonia.Android.Internal.Resource.Styleable</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<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.Internal.Resource</Target>
<Left>baseline/net6.0-android31.0/Avalonia.Android.dll</Left>
<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>

14
api/Avalonia.Browser.nupkg.xml

@ -3,20 +3,20 @@
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Browser.AvaloniaView.get_IsComposing</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<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.AvaloniaView.OnDragEvent(System.Runtime.InteropServices.JavaScript.JSObject)</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<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>CP0008</DiagnosticId>
<Target>T:Avalonia.Browser.AvaloniaView</Target>
<Left>baseline/net7.0/Avalonia.Browser.dll</Left>
<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>

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

@ -1,76 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorPicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorPreviewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorSlider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorSpectrum.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/ColorView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent/Fluent.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorPicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorPreviewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorSlider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorSpectrum.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/ColorView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple/Simple.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.ColorPicker.dll</Right>
</Suppression>
</Suppressions>

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

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Fluent.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.DataGrid.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.DataGrid.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Themes/Simple.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Controls.DataGrid.dll</Left>
<Right>target/netstandard2.0/Avalonia.Controls.DataGrid.dll</Right>
</Suppression>
</Suppressions>

64
api/Avalonia.Diagnostics.nupkg.xml

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/BrushEditor.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/FilterTextBox.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Controls/ThicknessEditor.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/ConsoleView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/ControlDetailsView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/EventsPageView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/LayoutExplorerView.axaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/MainView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/MainWindow.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Diagnostics/Views/TreePageView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Diagnostics.dll</Left>
<Right>target/netstandard2.0/Avalonia.Diagnostics.dll</Right>
</Suppression>
</Suppressions>

10
api/Avalonia.FreeDesktop.nupkg.xml

@ -0,0 +1,10 @@
<?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>

6
api/Avalonia.Skia.nupkg.xml

@ -1,10 +1,10 @@
<?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 -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0006</DiagnosticId>
<Target>M:Avalonia.Skia.ISkiaSharpApiLease.TryLeasePlatformGraphicsApi</Target>
<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>
</Suppressions>

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

@ -1,448 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/BaseColorsPalette.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/BaseResources.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/FluentControlResources.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AdornerLayer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AutoCompleteBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Button.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ButtonSpinner.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Calendar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDayButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CaptionButtons.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Carousel.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CheckBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContextMenu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DataValidationErrors.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DateTimePickerShared.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DropDownButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/EmbeddableControlRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Expander.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FluentControls.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/GridSplitter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ItemsControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Label.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ManagedFileChooser.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Menu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuFlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NativeMenuBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NotificationCard.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NumericUpDown.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/OverlayPopupHost.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PathIcon.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PopupRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ProgressBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RadioButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshContainer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshVisualizer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RepeatButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SelectableTextBlock.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Separator.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Slider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStrip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStripItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TextBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ThemeVariantScope.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TimePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TitleBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleSwitch.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToolTip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TransitioningContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeViewItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/UserControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Window.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/WindowNotificationManager.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/DensityStyles/Compact.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/FluentTheme.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
</Suppression>
</Suppressions>

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

@ -1,424 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Accents/Base.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AdornerLayer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/AutoCompleteBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Button.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ButtonSpinner.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Calendar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarDayButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CalendarItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CaptionButtons.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Carousel.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/CheckBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ComboBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ContextMenu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DataValidationErrors.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DatePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DateTimePickerShared.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/DropDownButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/EmbeddableControlRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Expander.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/FlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/GridSplitter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ItemsControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Label.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ListBoxItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ManagedFileChooser.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Menu.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuFlyoutPresenter.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/MenuItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NativeMenuBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NotificationCard.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/NumericUpDown.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/OverlayPopupHost.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PathIcon.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/PopupRoot.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ProgressBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RadioButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshContainer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RefreshVisualizer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/RepeatButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ScrollViewer.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SelectableTextBlock.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Separator.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SimpleControls.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Slider.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/SplitView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStrip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TabStripItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TextBox.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ThemeVariantScope.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TimePicker.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TitleBar.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleButton.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToggleSwitch.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/ToolTip.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TransitioningContentControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeView.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/TreeViewItem.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/UserControl.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/Window.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/Controls/WindowNotificationManager.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:CompiledAvaloniaXaml.!AvaloniaResources.NamespaceInfo:/SimpleTheme.xaml</Target>
<Left>baseline/netstandard2.0/Avalonia.Themes.Simple.dll</Left>
<Right>target/netstandard2.0/Avalonia.Themes.Simple.dll</Right>
</Suppression>
</Suppressions>

16
api/Avalonia.iOS.nupkg.xml

@ -0,0 +1,16 @@
<?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>

1090
api/Avalonia.nupkg.xml

File diff suppressed because it is too large

18
azure-pipelines-integrationtests.yml

@ -83,11 +83,23 @@ jobs:
projects: 'samples/IntegrationTestApp/IntegrationTestApp.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build test project'
inputs:
command: 'build'
projects: 'tests\Avalonia.IntegrationTests.Appium\Avalonia.IntegrationTests.Appium.csproj'
- task: VSTest@2
displayName: 'Run Integration Tests'
retryCountOnTaskFailure: 3
inputs:
command: 'test'
projects: 'tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj'
testAssemblyVer2: '**\bin\**\Avalonia.IntegrationTests.Appium.dll'
runSettingsFile: 'tests\Avalonia.IntegrationTests.Appium\record-video.runsettings'
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
testResultsFormat: 'XUnit'
testResultsFiles: '**/*.trx'
condition: succeededOrFailed()
- task: Windows Application Driver@0
inputs:

3
build/Base.props

@ -1,9 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- '!NET6_0_OR_GREATER' equivalent -->
<ItemGroup Condition="!('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0')))">
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.6.0" />
</ItemGroup>
</Project>

2
build/ImageSharp.props

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

13
build/SampleApp.props

@ -1,13 +1,22 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(TargetFramework)'=='net461'" >
<OutputType>WinExe</OutputType>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />
<ItemGroup Condition="'$(TargetFramework)'!='net461'">
<ProjectReference Include="$(MSBuildThisFileDirectory)../src/Avalonia.Desktop/Avalonia.Desktop.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461'">
<ProjectReference Include="$(MSBuildThisFileDirectory)../src/Windows/Avalonia.Win32/Avalonia.Win32.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)../src/Skia/Avalonia.Skia/Avalonia.Skia.csproj" />
</ItemGroup>
<Target Name="GatherReferences" AfterTargets="CoreCompile">
<WriteLinesToFile File="$(TargetPath).refs"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
</Target>
</Project>

1
build/SharedVersion.props

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

2
build/SourceLink.props

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

3
build/TrimmingEnable.props

@ -11,8 +11,7 @@
<IsAotCompatible Condition="'$(IsAotCompatible)' == ''">true</IsAotCompatible>
</PropertyGroup>
<!-- Remove check for the AOT when we get rid of dependencies with reflection -->
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0')) and '$(PublishAot)' != 'true'">
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
<ILLinkTreatWarningsAsErrors>true</ILLinkTreatWarningsAsErrors>
<!-- Trim warnings -->
<WarningsAsErrors>$(WarningsAsErrors);IL2000;IL2001;IL2002;IL2003;IL2004;IL2005;IL2006;IL2007;IL2008;IL2009;IL2010;IL2011;IL2012;IL2013;IL2014;IL2015;IL2016;IL2017;IL2018;IL2019;IL2020;IL2021;IL2022;IL2023;IL2024;IL2025;IL2026;IL2027;IL2028;IL2029;IL2030;IL2031;IL2032;IL2033;IL2034;IL2035;IL2036;IL2037;IL2038;IL2039;IL2040;IL2041;IL2042;IL2043;IL2044;IL2045;IL2046;IL2047;IL2048;IL2049;IL2050;IL2051;IL2052;IL2053;IL2054;IL2055;IL2056;IL2057;IL2058;IL2059;IL2060;IL2061;IL2062;IL2063;IL2064;IL2065;IL2066;IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091;IL2092;IL2093;IL2094;IL2095;IL2096;IL2097;IL2098;IL2099;IL2100;IL2101;IL2102;IL2103;IL2104;IL2105;IL2106;IL2107;IL2108;IL2109;IL2110;IL2111;IL2112;IL2113;IL2114;IL2115;IL2116;IL2117;IL2118;IL2119;IL2120;IL2121;IL2122;IL2123;IL2124;IL2125;IL2126;IL2127;IL2128;IL2129;IL2130;IL2131;IL2132;IL2133;IL2134;IL2135;IL2136;IL2137;IL2138;IL2139;IL2140;IL2141;IL2142;IL2143;IL2144;IL2145;IL2146;IL2147;IL2148;IL2149;IL2150;IL2151;IL2152;IL2153;IL2154;IL2155;IL2156;IL2157</WarningsAsErrors>

2
global.json

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

2
native/Avalonia.Native/inc/comimpl.h

@ -9,7 +9,7 @@
#include <cstring>
/**
START_COM_CALL causes AddRef to be called at the beggining of a function.
START_COM_CALL causes AddRef to be called at the beginning of a function.
When a function is exited, it causes ReleaseRef to be called.
This ensures that the object cannot be destroyed whilst the function is running.
For example: Window Show is called, which triggers an event, and user calls Close inside the event

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

@ -17,7 +17,6 @@
183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391CD090AA776E7E841AC9 /* WindowImpl.h */; };
18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839166350F32661F3ABD70F /* AutoFitContentView.mm */; };
18391AC16726CBC45856233B /* AvnWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839155B28B20FFB672D29C6 /* AvnWindow.mm */; };
18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183910513F396141938832B5 /* PopupImpl.h */; };
18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839171D898F9BFC1373631A /* ResizeScope.h */; };
18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */ = {isa = PBXBuildFile; fileRef = 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */; };
18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839132D0E2454D911F1D1F9 /* AvnView.mm */; };
@ -35,7 +34,7 @@
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1AFD334023E03C4F0042899B /* controlhost.mm */; };
37155CE4233C00EB0034DCE9 /* menu.h in Headers */ = {isa = PBXBuildFile; fileRef = 37155CE3233C00EB0034DCE9 /* menu.h */; };
37A517B32159597E00FBA241 /* Screens.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37A517B22159597E00FBA241 /* Screens.mm */; };
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* SystemDialogs.mm */; };
37C09D8821580FE4006A6758 /* StorageProvider.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37C09D8721580FE4006A6758 /* StorageProvider.mm */; };
37DDA9B0219330F8002E132B /* AvnString.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37DDA9AF219330F8002E132B /* AvnString.mm */; };
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37E2330E21583241000CB7E2 /* KeyTransform.mm */; };
520624B322973F4100C4DCEF /* menu.mm in Sources */ = {isa = PBXBuildFile; fileRef = 520624B222973F4100C4DCEF /* menu.mm */; };
@ -58,13 +57,15 @@
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; };
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; };
BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; };
BC7C33822C066DBF00945A48 /* AvnAutomationNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */; };
ED3791C42862E1F40080BD62 /* UniformTypeIdentifiers.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */; };
ED754D262A97306B0078B4DF /* PlatformRenderTimer.mm in Sources */ = {isa = PBXBuildFile; fileRef = ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */; };
EDF8CDCD2964CB01001EE34F /* PlatformSettings.mm in Sources */ = {isa = PBXBuildFile; fileRef = EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */; };
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = F10084832BFF1F9E0024303E /* TopLevelImpl.h */; };
F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = F10084852BFF1FB40024303E /* TopLevelImpl.mm */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
183910513F396141938832B5 /* PopupImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupImpl.h; sourceTree = "<group>"; };
1839122E037567BDD1D09DEB /* WindowProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowProtocol.h; sourceTree = "<group>"; };
1839132D0E2454D911F1D1F9 /* AvnView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnView.mm; sourceTree = "<group>"; };
183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWindowStateChanged.h; sourceTree = "<group>"; };
@ -94,7 +95,7 @@
379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = "<group>"; };
37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = "<group>"; };
37C09D8721580FE4006A6758 /* StorageProvider.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = StorageProvider.mm; sourceTree = "<group>"; };
37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = "<group>"; };
37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = "<group>"; };
37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = "<group>"; };
@ -122,9 +123,13 @@
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = "<group>"; };
BC11A5BC2608D58F0017BAD0 /* automation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = automation.h; sourceTree = "<group>"; };
BC11A5BD2608D58F0017BAD0 /* automation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = automation.mm; sourceTree = "<group>"; };
BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnAutomationNode.h; sourceTree = "<group>"; };
BC7C33832C066F1100945A48 /* AvnAccessibility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnAccessibility.h; sourceTree = "<group>"; };
ED3791C32862E1F40080BD62 /* UniformTypeIdentifiers.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UniformTypeIdentifiers.framework; path = System/Library/Frameworks/UniformTypeIdentifiers.framework; sourceTree = SDKROOT; };
ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformRenderTimer.mm; sourceTree = "<group>"; };
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformSettings.mm; sourceTree = "<group>"; };
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>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -164,9 +169,13 @@
AB7A61E62147C814003C5833 = {
isa = PBXGroup;
children = (
F10084852BFF1FB40024303E /* TopLevelImpl.mm */,
BC7C33832C066F1100945A48 /* AvnAccessibility.h */,
BC7C33812C066DBF00945A48 /* AvnAutomationNode.h */,
ED754D252A97306B0078B4DF /* PlatformRenderTimer.mm */,
855EDC9E28C6546F00807998 /* PlatformBehaviorInhibition.mm */,
8D2F3511292F6AAE007FCF54 /* AvnTextInputMethodDelegate.h */,
F10084832BFF1F9E0024303E /* TopLevelImpl.h */,
8D300D68292E1E5D00320C49 /* AvnTextInputMethod.mm */,
8D300D64292D0A6800320C49 /* AvnTextInputMethod.h */,
BC11A5BC2608D58F0017BAD0 /* automation.h */,
@ -193,7 +202,7 @@
523484CB26EA68AA00EA0C2C /* trayicon.h */,
1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */,
37A517B22159597E00FBA241 /* Screens.mm */,
37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
37C09D8721580FE4006A6758 /* StorageProvider.mm */,
EDF8CDCC2964CB01001EE34F /* PlatformSettings.mm */,
AB7A61F02147C815003C5833 /* Products */,
AB661C1C2148230E00291242 /* Frameworks */,
@ -214,7 +223,6 @@
1839155B28B20FFB672D29C6 /* AvnWindow.mm */,
18391DB45C7D892E61BF388C /* WindowInterfaces.h */,
18391BB698579F40F1783F31 /* PopupImpl.mm */,
183910513F396141938832B5 /* PopupImpl.h */,
64B1EBEECBE13D8616D7C934 /* metal.mm */,
64B1E4FA7D9D6E5F47AA8606 /* noarc.mm */,
64B1E26F2B1B9C577BF52F06 /* noarc.h */,
@ -237,10 +245,12 @@
buildActionMask = 2147483647;
files = (
37155CE4233C00EB0034DCE9 /* menu.h in Headers */,
F10084842BFF1F9E0024303E /* TopLevelImpl.h in Headers */,
BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */,
183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */,
1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */,
183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */,
BC7C33822C066DBF00945A48 /* AvnAutomationNode.h in Headers */,
18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */,
8D300D65292D0A6800320C49 /* AvnTextInputMethod.h in Headers */,
8D2F3512292F6AAE007FCF54 /* AvnTextInputMethodDelegate.h in Headers */,
@ -249,7 +259,6 @@
18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */,
18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */,
183914E50CF6D2EFC1667F7C /* WindowInterfaces.h in Headers */,
18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */,
64B1ECA861163C0EFF0E502B /* noarc.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -330,8 +339,9 @@
1AFD334123E03C4F0042899B /* controlhost.mm in Sources */,
1A465D10246AB61600C5858B /* dnd.mm in Sources */,
AB00E4F72147CA920032A60A /* main.mm in Sources */,
37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
37C09D8821580FE4006A6758 /* StorageProvider.mm in Sources */,
1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */,
F10084862BFF1FB40024303E /* TopLevelImpl.mm in Sources */,
1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */,
18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */,
18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */,

2
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1000"
version = "1.3">
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">

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

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

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

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

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

@ -7,20 +7,20 @@
#import <AppKit/AppKit.h>
#include "common.h"
#include "WindowImpl.h"
#include "TopLevelImpl.h"
#include "KeyTransform.h"
@class AvnAccessibilityElement;
@protocol IRenderTarget;
@interface AvnView : NSView<NSTextInputClient, NSDraggingDestination, AvnTextInputMethodDelegate, CALayerDelegate>
-(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
-(AvnView* _Nonnull) initWithParent: (TopLevelImpl* _Nonnull) parent;
-(NSEvent* _Nonnull) lastMouseDownEvent;
-(AvnPoint) translateLocalPoint:(AvnPoint)pt;
-(void) onClosed;
-(AvnPlatformResizeReason) getResizeReason;
-(void) setResizeReason:(AvnPlatformResizeReason)reason;
-(void) setRenderTarget:(NSObject<IRenderTarget>*)target;
+ (AvnPoint)toAvnPoint:(CGPoint)p;
-(void) setRenderTarget:(NSObject<IRenderTarget>* _Nonnull)target;
-(void) raiseAccessibilityChildrenChanged;
@end

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

@ -7,10 +7,11 @@
#include "AvnView.h"
#include "automation.h"
#import "WindowInterfaces.h"
#import "WindowImpl.h"
@implementation AvnView
{
ComPtr<WindowBaseImpl> _parent;
ComPtr<TopLevelImpl> _parent;
NSTrackingArea* _area;
bool _isLeftPressed, _isMiddlePressed, _isRightPressed, _isXButton1Pressed, _isXButton2Pressed;
AvnInputModifiers _modifierState;
@ -18,12 +19,12 @@
AvnPixelSize _lastPixelSize;
NSObject<IRenderTarget>* _currentRenderTarget;
AvnPlatformResizeReason _resizeReason;
AvnAccessibilityElement* _accessibilityChild;
NSRect _cursorRect;
NSMutableAttributedString* _text;
NSRange _selectedRange;
NSRange _markedRange;
NSEvent* _lastKeyDownEvent;
NSMutableArray* _accessibilityChildren;
}
- (void)onClosed
@ -67,7 +68,7 @@
[self updateLayer];
}
-(AvnView*) initWithParent: (WindowBaseImpl*) parent
-(AvnView*) initWithParent: (TopLevelImpl*) parent
{
self = [super init];
[self setWantsLayer:YES];
@ -155,7 +156,7 @@
auto reason = [self inLiveResize] ? ResizeUser : _resizeReason;
_parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height}, reason);
_parent->TopLevelEvents->Resized(FromNSSize(newSize), reason);
}
}
@ -167,14 +168,14 @@
return;
}
_parent->BaseEvents->RunRenderPriorityJobs();
_parent->TopLevelEvents->RunRenderPriorityJobs();
if (_parent == nullptr)
{
return;
}
_parent->BaseEvents->Paint();
_parent->TopLevelEvents->Paint();
}
- (void)drawRect:(NSRect)dirtyRect
@ -188,16 +189,6 @@
return pt;
}
+ (AvnPoint)toAvnPoint:(CGPoint)p
{
AvnPoint result;
result.X = p.x;
result.Y = p.y;
return result;
}
- (void) viewDidChangeBackingProperties
{
auto fsize = [self convertSizeToBacking: [self frame].size];
@ -207,7 +198,7 @@
if(_parent != nullptr)
{
_parent->BaseEvents->ScalingChanged([_parent->Window backingScaleFactor]);
_parent->TopLevelEvents->ScalingChanged([[self window] backingScaleFactor]);
}
[super viewDidChangeBackingProperties];
@ -219,19 +210,24 @@
{
return TRUE;
}
id<AvnWindowProtocol> parentWindow = nullptr;
auto parentWindow = _parent->GetWindowProtocol();
if([[self window] conformsToProtocol:@protocol(AvnWindowProtocol)]){
parentWindow = (id<AvnWindowProtocol>)[self window];
}
if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents])
if(parentWindow != nullptr && ![parentWindow shouldTryToHandleEvents])
{
if(trigerInputWhenDisabled)
{
auto window = dynamic_cast<WindowImpl*>(_parent.getRaw());
if(window != nullptr)
{
window->WindowEvents->GotInputWhenDisabled();
WindowImpl* windowImpl = dynamic_cast<WindowImpl*>(_parent.getRaw());
if(windowImpl == nullptr){
return FALSE;
}
windowImpl->WindowEvents->GotInputWhenDisabled();
}
return TRUE;
@ -249,9 +245,13 @@
return;
}
auto localPoint = [self convertPoint:[event locationInWindow] toView:self];
auto avnPoint = [AvnView toAvnPoint:localPoint];
auto point = [self translateLocalPoint:avnPoint];
NSPoint eventLocation = [event locationInWindow];
auto viewLocation = [self convertPoint:NSMakePoint(0, 0) toView:nil];
auto localPoint = NSMakePoint(eventLocation.x - viewLocation.x, viewLocation.y - eventLocation.y);
auto point = ToAvnPoint(localPoint);
AvnVector delta = { 0, 0};
if(type == Wheel)
@ -297,11 +297,26 @@
)
)
)
[self becomeFirstResponder];
{
WindowBaseImpl* windowBase = dynamic_cast<WindowBaseImpl*>(_parent.getRaw());
if(windowBase != nullptr){
WindowBaseImpl* parent = windowBase->Parent;
if(parent != nullptr){
auto parentWindow = parent->Window;
[parentWindow makeFirstResponder:parent->View];
}
} else{
[self becomeFirstResponder];
}
}
if(_parent != nullptr)
{
_parent->BaseEvents->RawMouseEvent(type, timestamp, modifiers, point, delta);
_parent->TopLevelEvents->RawMouseEvent(type, timestamp, modifiers, point, delta);
}
[super mouseMoved:event];
@ -309,7 +324,7 @@
- (BOOL) resignFirstResponder
{
_parent->BaseEvents->LostFocus();
_parent->TopLevelEvents->LostFocus();
return YES;
}
@ -436,6 +451,7 @@
- (void)mouseEntered:(NSEvent *)event
{
[self mouseEvent:event withType:Move];
[super mouseEntered:event];
}
@ -461,7 +477,7 @@
auto timestamp = static_cast<uint64_t>([event timestamp] * 1000);
auto modifiers = [self getModifiers:[event modifierFlags]];
_parent->BaseEvents->RawKeyEvent(type, timestamp, modifiers, key, physicalKey, keySymbolUtf8);
_parent->TopLevelEvents->RawKeyEvent(type, timestamp, modifiers, key, physicalKey, keySymbolUtf8);
}
- (void)flagsChanged:(NSEvent *)event
@ -521,7 +537,7 @@
}
- (bool) handleKeyDown: (NSTimeInterval) timestamp withKey:(AvnKey)key withPhysicalKey:(AvnPhysicalKey)physicalKey withModifiers:(AvnInputModifiers)modifiers withKeySymbol:(NSString*)keySymbol {
return _parent->BaseEvents->RawKeyEvent(KeyDown, timestamp, modifiers, key, physicalKey, [keySymbol UTF8String]);
return _parent->TopLevelEvents->RawKeyEvent(KeyDown, timestamp, modifiers, key, physicalKey, [keySymbol UTF8String]);
}
- (void)keyDown:(NSEvent *)event
@ -575,7 +591,7 @@
if(keySymbol != nullptr && key != AvnKeyEnter){
auto timestamp = static_cast<uint64_t>([event timestamp] * 1000);
_parent->BaseEvents->RawTextInputEvent(timestamp, [keySymbol UTF8String]);
_parent->TopLevelEvents->RawTextInputEvent(timestamp, [keySymbol UTF8String]);
}
}
}
@ -707,7 +723,7 @@
uint64_t timestamp = static_cast<uint64_t>([NSDate timeIntervalSinceReferenceDate] * 1000);
_parent->BaseEvents->RawTextInputEvent(timestamp, [text UTF8String]);
_parent->TopLevelEvents->RawTextInputEvent(timestamp, [text UTF8String]);
}
- (NSUInteger)characterIndexForPoint:(NSPoint)point
@ -727,13 +743,13 @@
- (NSDragOperation)triggerAvnDragEvent: (AvnDragEventType) type info: (id <NSDraggingInfo>)info
{
auto localPoint = [self convertPoint:[info draggingLocation] toView:self];
auto avnPoint = [AvnView toAvnPoint:localPoint];
auto avnPoint = ToAvnPoint(localPoint);
auto point = [self translateLocalPoint:avnPoint];
auto modifiers = [self getModifiers:[[NSApp currentEvent] modifierFlags]];
NSDragOperation nsop = [info draggingSourceOperationMask];
auto effects = ConvertDragDropEffects(nsop);
int reffects = (int)_parent->BaseEvents
int reffects = (int)_parent->TopLevelEvents
->DragEvent(type, point, modifiers, effects,
CreateClipboard([info draggingPasteboard], nil),
GetAvnDataObjectHandleFromDraggingInfo(info));
@ -795,35 +811,74 @@
_resizeReason = reason;
}
- (AvnAccessibilityElement *) accessibilityChild
- (NSArray *)accessibilityChildren
{
if (_accessibilityChild == nil)
{
auto peer = _parent->BaseEvents->GetAutomationPeer();
if (_accessibilityChildren == nil)
[self recalculateAccessibiltyChildren];
return _accessibilityChildren;
}
if (peer == nil)
return nil;
- (id _Nullable) accessibilityHitTest:(NSPoint)point
{
if (![[self window] isKindOfClass:[AvnWindow class]])
return self;
_accessibilityChild = [AvnAccessibilityElement acquire:peer];
}
auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer];
return _accessibilityChild;
}
if (!peer->IsRootProvider())
return nil;
- (NSArray *)accessibilityChildren
{
auto child = [self accessibilityChild];
return NSAccessibilityUnignoredChildrenForOnlyChild(child);
auto clientPoint = [window convertPointFromScreen:point];
auto localPoint = [self translateLocalPoint:ToAvnPoint(clientPoint)];
auto hit = peer->RootProvider_GetPeerFromPoint(localPoint);
return [AvnAccessibilityElement acquire:hit];
}
- (id)accessibilityHitTest:(NSPoint)point
- (void)raiseAccessibilityChildrenChanged
{
return [[self accessibilityChild] accessibilityHitTest:point];
auto changed = _accessibilityChildren ? [NSMutableSet setWithArray:_accessibilityChildren] : [NSMutableSet set];
[self recalculateAccessibiltyChildren];
if (_accessibilityChildren)
[changed addObjectsFromArray:_accessibilityChildren];
NSAccessibilityPostNotificationWithUserInfo(
self,
NSAccessibilityLayoutChangedNotification,
@{ NSAccessibilityUIElementsKey: [changed allObjects]});
}
- (id)accessibilityFocusedUIElement
- (void)recalculateAccessibiltyChildren
{
return [[self accessibilityChild] accessibilityFocusedUIElement];
_accessibilityChildren = [[NSMutableArray alloc] init];
if (![[self window] isKindOfClass:[AvnWindow class]])
{
return;
}
// The accessibility children of the Window are exposed as children
// of the AvnView.
auto window = (AvnWindow*)[self window];
auto peer = [window automationPeer];
auto childPeers = peer->GetChildren();
auto childCount = childPeers != nullptr ? childPeers->GetCount() : 0;
if (childCount > 0)
{
for (int i = 0; i < childCount; ++i)
{
IAvnAutomationPeer* child;
if (childPeers->Get(i, &child) == S_OK)
{
id element = [AvnAccessibilityElement acquire:child];
[_accessibilityChildren addObject:element];
}
}
}
}
- (void) setText:(NSString *)text{

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

@ -24,7 +24,8 @@
#include "WindowImpl.h"
#include "AvnView.h"
#include "WindowInterfaces.h"
#include "PopupImpl.h"
#include "AvnAutomationNode.h"
#include "AvnString.h"
@implementation CLASS_NAME
{
@ -35,6 +36,13 @@
bool _isExtended;
bool _isTransitioningToFullScreen;
AvnMenu* _menu;
IAvnAutomationPeer* _automationPeer;
AvnAutomationNode* _automationNode;
}
-(AvnView* _Nullable) view
{
return _parent->View;
}
-(void) setIsExtended:(bool)value;
@ -201,8 +209,6 @@
[self backingScaleFactor];
}
- (void)windowWillClose:(NSNotification *_Nonnull)notification
{
_closed = true;
@ -211,7 +217,7 @@
ComPtr<WindowBaseImpl> parent = _parent;
_parent = NULL;
auto window = dynamic_cast<WindowImpl*>(parent.getRaw());
auto window = dynamic_cast<WindowImpl*>(parent.getRaw());
if(window != nullptr)
{
@ -231,7 +237,7 @@
//
// If we don't implement this, then isZoomed always returns true for a non-
// resizable window ¯\_(ツ)_/¯
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
- (NSRect)windowWillUseStandardFrame:(NSWindow* _Nonnull)window
defaultFrame:(NSRect)newFrame {
return newFrame;
}
@ -397,7 +403,7 @@
return _parent->CanZoom();
}
-(void)windowDidResignKey:(NSNotification *)notification
-(void)windowDidResignKey:(NSNotification* _Nonnull)notification
{
if(_parent)
_parent->BaseEvents->Deactivated();
@ -456,7 +462,7 @@
if (!NSPointInRect(viewPoint, view.bounds))
{
auto avnPoint = [AvnView toAvnPoint:windowPoint];
auto avnPoint = ToAvnPoint(windowPoint);
auto point = [self translateLocalPoint:avnPoint];
AvnVector delta = { 0, 0 };
@ -492,5 +498,41 @@
_parent = nullptr;
}
- (id _Nullable) accessibilityFocusedUIElement
{
if (![self automationPeer]->IsRootProvider())
return nil;
auto focusedPeer = [self automationPeer]->RootProvider_GetFocus();
return [AvnAccessibilityElement acquire:focusedPeer];
}
- (NSString * _Nullable) accessibilityIdentifier
{
return GetNSStringAndRelease([self automationPeer]->GetAutomationId());
}
- (IAvnAutomationPeer* _Nonnull) automationPeer
{
if (_automationPeer == nullptr)
{
_automationPeer = _parent->BaseEvents->GetAutomationPeer();
_automationNode = new AvnAutomationNode(self);
_automationPeer->SetNode(_automationNode);
}
return _automationPeer;
}
- (void)raiseChildrenChanged
{
[_parent->View raiseAccessibilityChildrenChanged];
}
- (void)raiseFocusChanged
{
id focused = [self accessibilityFocusedUIElement];
NSAccessibilityPostNotification(focused, NSAccessibilityFocusedUIElementChangedNotification);
}
@end

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

@ -11,6 +11,10 @@
struct INSWindowHolder
{
virtual NSWindow* _Nonnull GetNSWindow () = 0;
};
struct INSViewHolder
{
virtual AvnView* _Nonnull GetNSView () = 0;
};

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

@ -1,9 +0,0 @@
//
// Created by Dan Walmsley on 06/05/2022.
// Copyright (c) 2022 Avalonia. All rights reserved.
//
#ifndef AVALONIA_NATIVE_OSX_POPUPIMPL_H
#define AVALONIA_NATIVE_OSX_POPUPIMPL_H
#endif //AVALONIA_NATIVE_OSX_POPUPIMPL_H

12
native/Avalonia.Native/src/OSX/PopupImpl.mm

@ -12,7 +12,6 @@
#import "WindowBaseImpl.h"
#import "WindowProtocol.h"
#import <AppKit/AppKit.h>
#include "PopupImpl.h"
class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup
{
@ -23,7 +22,7 @@ private:
END_INTERFACE_MAP()
virtual ~PopupImpl(){}
ComPtr<IAvnWindowEvents> WindowEvents;
PopupImpl(IAvnWindowEvents* events) : WindowBaseImpl(events)
PopupImpl(IAvnWindowEvents* events) : TopLevelImpl(events), WindowBaseImpl(events)
{
WindowEvents = events;
[Window setLevel:NSPopUpMenuWindowLevel];
@ -35,13 +34,12 @@ protected:
}
public:
virtual bool ShouldTakeFocusOnShow() override
{
return false;
}
virtual HRESULT Show(bool activate, bool isDialog) override
{
auto windowProtocol = GetWindowProtocol();
[windowProtocol setEnabled:true];
return WindowBaseImpl::Show(activate, true);
}
};

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

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

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

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

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

@ -0,0 +1,77 @@
//
// TopLevelImpl.h
// Avalonia.Native.OSX
//
// Created by Benedikt Stebner on 16.05.24.
// Copyright © 2024 Avalonia. All rights reserved.
//
#ifndef TopLevelImpl_h
#define TopLevelImpl_h
#include "rendertarget.h"
#include "INSWindowHolder.h"
#include "AvnTextInputMethod.h"
#include "AutoFitContentView.h"
#include <list>
class TopLevelImpl : public virtual ComObject,
public virtual IAvnTopLevel,
public INSViewHolder{
public:
FORWARD_IUNKNOWN()
BEGIN_INTERFACE_MAP()
INTERFACE_MAP_ENTRY(IAvnTopLevel, IID_IAvnTopLevel)
END_INTERFACE_MAP()
virtual ~TopLevelImpl();
TopLevelImpl(IAvnTopLevelEvents* events);
virtual AvnView *GetNSView() override;
virtual HRESULT SetCursor(IAvnCursor* cursor) override;
virtual HRESULT GetScaling(double*ret) override;
virtual HRESULT GetClientSize(AvnSize *ret) override;
virtual HRESULT GetInputMethod(IAvnTextInputMethod **ppv) override;
virtual HRESULT ObtainNSViewHandle(void** retOut) override;
virtual HRESULT ObtainNSViewHandleRetained(void** retOut) override;
virtual HRESULT CreateSoftwareRenderTarget(IAvnSoftwareRenderTarget** ret) override;
virtual HRESULT CreateMetalRenderTarget(IAvnMetalDevice* device, IAvnMetalRenderTarget** ret) override;
virtual HRESULT CreateGlRenderTarget(IAvnGlContext* context, IAvnGlSurfaceRenderTarget** ret) override;
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost **retOut) override;
virtual HRESULT Invalidate() override;
virtual HRESULT PointToClient(AvnPoint point, AvnPoint *ret) override;
virtual HRESULT PointToScreen(AvnPoint point, AvnPoint *ret) override;
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) override;
virtual HRESULT GetCurrentDisplayId (CGDirectDisplayID* ret) override;
protected:
NSCursor *cursor;
virtual void UpdateAppearance();
public:
NSObject<IRenderTarget> *currentRenderTarget;
ComPtr<AvnTextInputMethod> InputMethod;
ComPtr<IAvnTopLevelEvents> TopLevelEvents;
AvnView *View;
void UpdateCursor();
virtual void SetClientSize(NSSize size);
};
#endif /* TopLevelImpl_h */

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

@ -0,0 +1,285 @@
#import <AppKit/AppKit.h>
#import <Cocoa/Cocoa.h>
#include "automation.h"
#include "cursor.h"
#include "AutoFitContentView.h"
#include "TopLevelImpl.h"
#include "AvnTextInputMethod.h"
#include "AvnView.h"
TopLevelImpl::~TopLevelImpl() {
View = nullptr;
}
TopLevelImpl::TopLevelImpl(IAvnTopLevelEvents *events) {
TopLevelEvents = events;
View = [[AvnView alloc] initWithParent:this];
InputMethod = new AvnTextInputMethod(View);
}
HRESULT TopLevelImpl::GetScaling(double *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr)
return E_POINTER;
if ([View window] == nullptr) {
*ret = 1;
return S_OK;
}
*ret = [[View window] backingScaleFactor];
return S_OK;
}
}
HRESULT TopLevelImpl::GetClientSize(AvnSize *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr)
return E_POINTER;
NSRect frame = [View frame];
ret->Width = frame.size.width;
ret->Height = frame.size.height;
return S_OK;
}
}
HRESULT TopLevelImpl::GetInputMethod(IAvnTextInputMethod **retOut) {
START_COM_CALL;
*retOut = InputMethod;
return S_OK;
}
HRESULT TopLevelImpl::ObtainNSViewHandle(void **ret) {
START_COM_CALL;
if (ret == nullptr) {
return E_POINTER;
}
*ret = (__bridge void *) View;
return S_OK;
}
HRESULT TopLevelImpl::ObtainNSViewHandleRetained(void **ret) {
START_COM_CALL;
if (ret == nullptr) {
return E_POINTER;
}
*ret = (__bridge_retained void *) View;
return S_OK;
}
HRESULT TopLevelImpl::SetCursor(IAvnCursor *cursor) {
START_COM_CALL;
@autoreleasepool {
Cursor *avnCursor = dynamic_cast<Cursor *>(cursor);
this->cursor = avnCursor->GetNative();
UpdateCursor();
if (avnCursor->IsHidden()) {
[NSCursor hide];
} else {
[NSCursor unhide];
}
return S_OK;
}
}
void TopLevelImpl::UpdateCursor() {
if (cursor != nil) {
[cursor set];
}
}
HRESULT TopLevelImpl::CreateSoftwareRenderTarget(IAvnSoftwareRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: nil];
*ppv = [target createSoftwareRenderTarget];
[View setRenderTarget: target];
return S_OK;
}
HRESULT TopLevelImpl::CreateGlRenderTarget(IAvnGlContext* glContext, IAvnGlSurfaceRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: glContext];
*ppv = [target createSurfaceRenderTarget];
[View setRenderTarget: target];
return S_OK;
}
HRESULT TopLevelImpl::CreateMetalRenderTarget(IAvnMetalDevice* device, IAvnMetalRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[MetalRenderTarget alloc] initWithDevice: device];
[View setRenderTarget: target];
[target getRenderTarget: ppv];
return S_OK;
}
HRESULT TopLevelImpl::CreateNativeControlHost(IAvnNativeControlHost **retOut) {
START_COM_CALL;
if (View == NULL)
return E_FAIL;
*retOut = ::CreateNativeControlHost(View);
return S_OK;
}
AvnView *TopLevelImpl::GetNSView() {
return View;
}
HRESULT TopLevelImpl::Invalidate() {
START_COM_CALL;
@autoreleasepool {
[View setNeedsDisplayInRect:[View frame]];
return S_OK;
}
}
HRESULT TopLevelImpl::PointToClient(AvnPoint point, AvnPoint *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr) {
return E_POINTER;
}
auto window = [View window];
if(window == nullptr){
ret = &point;
return S_OK;
}
auto frame = [View frame];
auto viewRect = [View convertRect:frame toView:nil];
auto viewScreenRect = [window convertRectToScreen:viewRect];
auto primaryDisplayHeight = NSMaxY([[[NSScreen screens] firstObject] frame]);
//Window coord are bottom to top so we need to adjust by primaryScreenHeight
auto viewScreenLocation = NSMakePoint(viewScreenRect.origin.x, primaryDisplayHeight - viewScreenRect.origin.y - frame.size.height);
//Substract client point from screen position of the view
auto localPoint = NSMakePoint(point.X - viewScreenLocation.x, point.Y - viewScreenLocation.y);
point = ToAvnPoint(localPoint);
*ret = point;
return S_OK;
}
}
HRESULT TopLevelImpl::PointToScreen(AvnPoint point, AvnPoint *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr) {
return E_POINTER;
}
auto window = [View window];
if(window == nullptr){
ret = &point;
return S_OK;
}
auto frame = [View frame];
//Get rect inside current window
auto viewRect = [View convertRect:frame toView:nil];
//Get screen rect of the view
auto viewScreenRect = [window convertRectToScreen:viewRect];
auto primaryDisplayHeight = NSMaxY([[[NSScreen screens] firstObject] frame]);
//Window coord are bottom to top so we need to adjust by primaryScreenHeight
auto viewScreenLocation = NSMakePoint(viewScreenRect.origin.x, primaryDisplayHeight - viewScreenRect.origin.y - frame.size.height);
//Add client point to screen position of the view
auto screenPoint = ToAvnPoint(NSMakePoint(viewScreenLocation.x + point.X, viewScreenLocation.y + point.Y));
*ret = screenPoint;
return S_OK;
}
}
HRESULT TopLevelImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
START_COM_CALL;
return S_OK;
}
HRESULT TopLevelImpl::GetCurrentDisplayId (CGDirectDisplayID* ret) {
START_COM_CALL;
auto window = [View window];
*ret = [window.screen av_displayId];
return S_OK;
}
void TopLevelImpl::UpdateAppearance() {
}
void TopLevelImpl::SetClientSize(NSSize size){
[View setFrameSize:size];
}
extern IAvnTopLevel* CreateAvnTopLevel(IAvnTopLevelEvents* events)
{
@autoreleasepool
{
IAvnTopLevel* ptr = (IAvnTopLevel*)new TopLevelImpl(events);
return ptr;
}
}

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

@ -9,19 +9,21 @@
#include "rendertarget.h"
#include "INSWindowHolder.h"
#include "AvnTextInputMethod.h"
#include "TopLevelImpl.h"
#include <list>
@class AutoFitContentView;
@class AvnMenu;
@protocol AvnWindowProtocol;
class WindowBaseImpl : public virtual ComObject,
class WindowBaseImpl : public virtual TopLevelImpl,
public virtual IAvnWindowBase,
public INSWindowHolder {
public:
FORWARD_IUNKNOWN()
BEGIN_INTERFACE_MAP()
BEGIN_INTERFACE_MAP()
INHERIT_INTERFACE_MAP(TopLevelImpl)
INTERFACE_MAP_ENTRY(IAvnWindowBase, IID_IAvnWindowBase)
END_INTERFACE_MAP()
@ -33,14 +35,8 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT ObtainNSWindowHandleRetained(void **ret) override;
virtual HRESULT ObtainNSViewHandle(void **ret) override;
virtual HRESULT ObtainNSViewHandleRetained(void **ret) override;
virtual NSWindow *GetNSWindow() override;
virtual AvnView *GetNSView() override;
virtual HRESULT Show(bool activate, bool isDialog) override;
virtual bool IsShown ();
@ -55,18 +51,12 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT Close() override;
virtual HRESULT GetClientSize(AvnSize *ret) override;
virtual HRESULT GetFrameSize(AvnSize *ret) override;
virtual HRESULT GetScaling(double *ret) override;
virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) override;
virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override;
virtual HRESULT Invalidate(__attribute__((unused)) AvnRect rect) override;
virtual HRESULT SetMainMenu(IAvnMenu *menu) override;
virtual HRESULT BeginMoveDrag() override;
@ -77,49 +67,33 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetPosition(AvnPoint point) override;
virtual HRESULT PointToClient(AvnPoint point, AvnPoint *ret) override;
virtual HRESULT PointToScreen(AvnPoint point, AvnPoint *ret) override;
virtual HRESULT SetCursor(IAvnCursor *cursor) override;
virtual void UpdateCursor();
virtual HRESULT CreateSoftwareRenderTarget(IAvnSoftwareRenderTarget **ppv) override;
virtual HRESULT CreateGlRenderTarget(IAvnGlContext* glContext, IAvnGlSurfaceRenderTarget **ppv) override;
virtual HRESULT CreateMetalRenderTarget(IAvnMetalDevice* device, IAvnMetalRenderTarget **ppv) override;
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost **retOut) override;
virtual HRESULT SetTransparencyMode(AvnWindowTransparencyMode mode) 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 bool IsModal();
id<AvnWindowProtocol> GetWindowProtocol ();
virtual void BringToFront ();
virtual HRESULT GetInputMethod(IAvnTextInputMethod **retOut) override;
virtual bool CanZoom() { return false; }
virtual HRESULT SetParent(IAvnWindowBase* parent) override;
protected:
virtual NSWindowStyleMask CalculateStyleMask() = 0;
virtual void UpdateStyle();
virtual void UpdateAppearance() override;
virtual void SetClientSize(NSSize size) override;
private:
void CreateNSWindow (bool isDialog);
void CleanNSWindow ();
NSCursor *cursor;
bool hasPosition;
NSSize lastSize;
NSSize lastMinSize;
@ -128,16 +102,16 @@ private:
bool _inResize;
protected:
AvnPoint lastPositionSet;
AutoFitContentView *StandardContainer;
AvnPoint lastPositionSet;
bool _shown;
std::list<WindowBaseImpl*> _children;
bool _isModal;
public:
NSObject <IRenderTarget> *currentRenderTarget;
WindowBaseImpl* Parent;
NSWindow * Window;
ComPtr<IAvnWindowBaseEvents> BaseEvents;
ComPtr<AvnTextInputMethod> InputMethod;
AvnView *View;
};
#endif //AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H

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

@ -15,22 +15,22 @@
#import "WindowProtocol.h"
#import "WindowInterfaces.h"
#include "WindowBaseImpl.h"
#include "WindowImpl.h"
#include "AvnTextInputMethod.h"
#include "AvnView.h"
@class AutoFitContentView;
WindowBaseImpl::~WindowBaseImpl() {
View = nullptr;
Window = nullptr;
}
WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, bool usePanel) {
WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, bool usePanel) : TopLevelImpl(events) {
_children = std::list<WindowBaseImpl*>();
_shown = false;
_inResize = false;
BaseEvents = events;
View = [[AvnView alloc] initWithParent:this];
InputMethod = new AvnTextInputMethod(View);
StandardContainer = [[AutoFitContentView new] initWithContent:View];
lastPositionSet = { 0, 0 };
hasPosition = false;
@ -41,6 +41,8 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, bool usePanel) {
CreateNSWindow(usePanel);
StandardContainer = [[AutoFitContentView new] initWithContent:View];
[Window setContentView:StandardContainer];
[Window setBackingType:NSBackingStoreBuffered];
[Window setContentMinSize:lastMinSize];
@ -48,38 +50,10 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, bool usePanel) {
[Window setOpaque:false];
}
HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) {
START_COM_CALL;
if (ret == nullptr) {
return E_POINTER;
}
*ret = (__bridge void *) View;
return S_OK;
}
HRESULT WindowBaseImpl::ObtainNSViewHandleRetained(void **ret) {
START_COM_CALL;
if (ret == nullptr) {
return E_POINTER;
}
*ret = (__bridge_retained void *) View;
return S_OK;
}
NSWindow *WindowBaseImpl::GetNSWindow() {
return Window;
}
AvnView *WindowBaseImpl::GetNSView() {
return View;
}
HRESULT WindowBaseImpl::ObtainNSWindowHandleRetained(void **ret) {
START_COM_CALL;
@ -117,7 +91,7 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) {
auto collectionBehavior = [Window collectionBehavior];
[Window setCollectionBehavior:collectionBehavior & ~NSWindowCollectionBehaviorFullScreenPrimary];
UpdateStyle();
UpdateAppearance();
[Window invalidateShadow];
@ -219,20 +193,6 @@ HRESULT WindowBaseImpl::Close() {
}
}
HRESULT WindowBaseImpl::GetClientSize(AvnSize *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr)
return E_POINTER;
ret->Width = lastSize.width;
ret->Height = lastSize.height;
return S_OK;
}
}
HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) {
START_COM_CALL;
@ -250,23 +210,6 @@ HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) {
}
}
HRESULT WindowBaseImpl::GetScaling(double *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr)
return E_POINTER;
if (Window == nullptr) {
*ret = 1;
return S_OK;
}
*ret = [Window backingScaleFactor];
return S_OK;
}
}
HRESULT WindowBaseImpl::SetMinMaxSize(AvnSize minSize, AvnSize maxSize) {
START_COM_CALL;
@ -330,7 +273,7 @@ HRESULT WindowBaseImpl::Resize(double x, double y, AvnPlatformResizeReason reaso
lastSize = NSSize{x, y};
[Window setContentSize:lastSize];
SetClientSize(lastSize);
[Window invalidateShadow];
}
}
@ -342,16 +285,6 @@ HRESULT WindowBaseImpl::Resize(double x, double y, AvnPlatformResizeReason reaso
}
}
HRESULT WindowBaseImpl::Invalidate(__attribute__((unused)) AvnRect rect) {
START_COM_CALL;
@autoreleasepool {
[View setNeedsDisplayInRect:[View frame]];
return S_OK;
}
}
HRESULT WindowBaseImpl::SetMainMenu(IAvnMenu *menu) {
START_COM_CALL;
@ -431,119 +364,6 @@ HRESULT WindowBaseImpl::SetPosition(AvnPoint point) {
}
}
HRESULT WindowBaseImpl::PointToClient(AvnPoint point, AvnPoint *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr) {
return E_POINTER;
}
point = ConvertPointY(point);
NSRect convertRect = [Window convertRectFromScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
auto viewPoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
return S_OK;
}
}
HRESULT WindowBaseImpl::PointToScreen(AvnPoint point, AvnPoint *ret) {
START_COM_CALL;
@autoreleasepool {
if (ret == nullptr) {
return E_POINTER;
}
auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]);
NSRect convertRect = [Window convertRectToScreen:NSMakeRect(cocoaViewPoint.x, cocoaViewPoint.y, 0.0, 0.0)];
auto cocoaScreenPoint = NSPointFromCGPoint(NSMakePoint(convertRect.origin.x, convertRect.origin.y));
*ret = ConvertPointY(ToAvnPoint(cocoaScreenPoint));
return S_OK;
}
}
HRESULT WindowBaseImpl::SetCursor(IAvnCursor *cursor) {
START_COM_CALL;
@autoreleasepool {
Cursor *avnCursor = dynamic_cast<Cursor *>(cursor);
this->cursor = avnCursor->GetNative();
UpdateCursor();
if (avnCursor->IsHidden()) {
[NSCursor hide];
} else {
[NSCursor unhide];
}
return S_OK;
}
}
void WindowBaseImpl::UpdateCursor() {
if (cursor != nil) {
[cursor set];
}
}
HRESULT WindowBaseImpl::CreateSoftwareRenderTarget(IAvnSoftwareRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: nil];
*ppv = [target createSoftwareRenderTarget];
[View setRenderTarget: target];
return S_OK;
}
HRESULT WindowBaseImpl::CreateGlRenderTarget(IAvnGlContext* glContext, IAvnGlSurfaceRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[IOSurfaceRenderTarget alloc] initWithOpenGlContext: glContext];
*ppv = [target createSurfaceRenderTarget];
[View setRenderTarget: target];
return S_OK;
}
HRESULT WindowBaseImpl::CreateMetalRenderTarget(IAvnMetalDevice* device, IAvnMetalRenderTarget **ppv) {
START_COM_CALL;
if(![NSThread isMainThread])
return COR_E_INVALIDOPERATION;
if (View == NULL)
return E_FAIL;
auto target = [[MetalRenderTarget alloc] initWithDevice: device];
[View setRenderTarget: target];
[target getRenderTarget: ppv];
return S_OK;
}
HRESULT WindowBaseImpl::CreateNativeControlHost(IAvnNativeControlHost **retOut) {
START_COM_CALL;
if (View == NULL)
return E_FAIL;
*retOut = ::CreateNativeControlHost(View);
return S_OK;
}
HRESULT WindowBaseImpl::SetTransparencyMode(AvnWindowTransparencyMode mode) {
START_COM_CALL;
@ -619,10 +439,14 @@ bool WindowBaseImpl::IsModal() {
return false;
}
void WindowBaseImpl::UpdateStyle() {
void WindowBaseImpl::UpdateAppearance() {
[Window setStyleMask:CalculateStyleMask()];
}
void WindowBaseImpl::SetClientSize(NSSize size){
[Window setContentSize:lastSize];
}
void WindowBaseImpl::CleanNSWindow() {
if(Window != nullptr) {
[GetWindowProtocol() disconnectParent];
@ -654,19 +478,35 @@ void WindowBaseImpl::BringToFront()
// do nothing.
}
HRESULT WindowBaseImpl::GetInputMethod(IAvnTextInputMethod **retOut) {
HRESULT WindowBaseImpl::SetParent(IAvnWindowBase *parent) {
START_COM_CALL;
*retOut = InputMethod;
@autoreleasepool {
if(Parent != nullptr)
{
Parent->_children.remove(this);
}
auto cparent = dynamic_cast<WindowImpl *>(parent);
Parent = cparent;
return S_OK;
}
_isModal = Parent != nullptr;
if(Parent != nullptr && Window != nullptr){
// If one tries to show a child window with a minimized parent window, then the parent window will be
// restored but macOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive
// state. Detect this and explicitly restore the parent window ourselves to avoid this situation.
if (cparent->WindowState() == Minimized)
cparent->SetWindowState(Normal);
[Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
cparent->_children.push_back(this);
UpdateAppearance();
}
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events)
{
@autoreleasepool
{
IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events);
return ptr;
return S_OK;
}
}

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

@ -8,26 +8,9 @@
#import "WindowBaseImpl.h"
#include "IWindowStateChanged.h"
#include <list>
class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, public IWindowStateChanged
{
private:
bool _isEnabled;
bool _canResize;
bool _fullScreenActive;
SystemDecorations _decorations;
AvnWindowState _lastWindowState;
AvnWindowState _actualWindowState;
bool _inSetWindowState;
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
bool _isModal;
WindowImpl* _parent;
std::list<WindowImpl*> _children;
AvnExtendClientAreaChromeHints _extendClientHints;
public:
FORWARD_IUNKNOWN()
BEGIN_INTERFACE_MAP()
INHERIT_INTERFACE_MAP(WindowBaseImpl)
@ -45,8 +28,6 @@ BEGIN_INTERFACE_MAP()
virtual HRESULT SetEnabled (bool enable) override;
virtual HRESULT SetParent (IAvnWindow* parent) override;
void StartStateTransition () override ;
void EndStateTransition () override ;
@ -103,12 +84,23 @@ BEGIN_INTERFACE_MAP()
protected:
virtual NSWindowStyleMask CalculateStyleMask() override;
void UpdateStyle () override;
virtual void UpdateAppearance() override;
private:
void ZOrderChildWindows();
void OnInitialiseNSWindow();
NSString *_lastTitle;
bool _isEnabled;
bool _canResize;
bool _fullScreenActive;
SystemDecorations _decorations;
AvnWindowState _lastWindowState;
AvnWindowState _actualWindowState;
bool _inSetWindowState;
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
AvnExtendClientAreaChromeHints _extendClientHints;
};
#endif //AVALONIA_NATIVE_OSX_WINDOWIMPL_H

66
native/Avalonia.Native/src/OSX/WindowImpl.mm

@ -8,10 +8,10 @@
#include "AvnView.h"
#include "automation.h"
#include "WindowProtocol.h"
#include "WindowImpl.h"
WindowImpl::WindowImpl(IAvnWindowEvents *events) : WindowBaseImpl(events) {
WindowImpl::WindowImpl(IAvnWindowEvents *events) : TopLevelImpl(events), WindowBaseImpl(events, false) {
_isEnabled = true;
_children = std::list<WindowImpl*>();
_isClientAreaExtended = false;
_extendClientHints = AvnDefaultChrome;
_fullScreenActive = false;
@ -22,7 +22,7 @@ WindowImpl::WindowImpl(IAvnWindowEvents *events) : WindowBaseImpl(events) {
_lastWindowState = Normal;
_actualWindowState = Normal;
_lastTitle = @"";
_parent = nullptr;
Parent = nullptr;
WindowEvents = events;
[Window setHasShadow:true];
@ -69,40 +69,7 @@ HRESULT WindowImpl::SetEnabled(bool enable) {
@autoreleasepool {
_isEnabled = enable;
[GetWindowProtocol() setEnabled:enable];
UpdateStyle();
return S_OK;
}
}
HRESULT WindowImpl::SetParent(IAvnWindow *parent) {
START_COM_CALL;
@autoreleasepool {
if(_parent != nullptr)
{
_parent->_children.remove(this);
}
auto cparent = dynamic_cast<WindowImpl *>(parent);
_parent = cparent;
_isModal = _parent != nullptr;
if(_parent != nullptr && Window != nullptr){
// If one tries to show a child window with a minimized parent window, then the parent window will be
// restored but macOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive
// state. Detect this and explicitly restore the parent window ourselves to avoid this situation.
if (cparent->WindowState() == Minimized)
cparent->SetWindowState(Normal);
[Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
cparent->_children.push_back(this);
UpdateStyle();
}
UpdateAppearance();
return S_OK;
}
}
@ -156,12 +123,12 @@ bool WindowImpl::CanBecomeKeyWindow()
void WindowImpl::StartStateTransition() {
_transitioningWindowState = true;
UpdateStyle();
UpdateAppearance();
}
void WindowImpl::EndStateTransition() {
_transitioningWindowState = false;
UpdateStyle();
UpdateAppearance();
// Ensure correct order of child windows after fullscreen transition.
ZOrderChildWindows();
@ -236,7 +203,7 @@ HRESULT WindowImpl::SetCanResize(bool value) {
@autoreleasepool {
_canResize = value;
UpdateStyle();
UpdateAppearance();
return S_OK;
}
}
@ -252,7 +219,7 @@ HRESULT WindowImpl::SetDecorations(SystemDecorations value) {
return S_OK;
}
UpdateStyle();
UpdateAppearance();
switch (_decorations) {
case SystemDecorationsNone:
@ -427,7 +394,7 @@ HRESULT WindowImpl::SetExtendClientArea(bool enable) {
}
[GetWindowProtocol() setIsExtended:enable];
UpdateStyle();
UpdateAppearance();
}
return S_OK;
@ -579,7 +546,7 @@ bool WindowImpl::IsModal() {
}
bool WindowImpl::IsOwned() {
return _parent != nullptr;
return Parent != nullptr;
}
NSWindowStyleMask WindowImpl::CalculateStyleMask() {
@ -620,8 +587,8 @@ NSWindowStyleMask WindowImpl::CalculateStyleMask() {
return s;
}
void WindowImpl::UpdateStyle() {
WindowBaseImpl::UpdateStyle();
void WindowImpl::UpdateAppearance() {
WindowBaseImpl::UpdateAppearance();
if (Window == nil) {
return;
@ -642,3 +609,12 @@ void WindowImpl::UpdateStyle() {
[zoomButton setHidden:!hasTrafficLights];
[zoomButton setEnabled:CanZoom()];
}
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events)
{
@autoreleasepool
{
IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events);
return ptr;
}
}

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

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

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

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

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

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

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

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

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

@ -11,10 +11,11 @@
extern IAvnPlatformThreadingInterface* CreatePlatformThreading();
extern void FreeAvnGCHandle(void* handle);
extern void PostDispatcherCallback(IAvnActionCallback* cb);
extern IAvnTopLevel* CreateAvnTopLevel(IAvnTopLevelEvents* events);
extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events);
extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events);
extern IAvnSystemDialogs* CreateSystemDialogs();
extern IAvnScreens* CreateScreens();
extern IAvnStorageProvider* CreateStorageProvider();
extern IAvnScreens* CreateScreens(IAvnScreenEvents* cb);
extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*);
extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
@ -46,6 +47,7 @@ extern NSRect ToNSRect (AvnRect r);
extern AvnPoint ToAvnPoint (NSPoint p);
extern AvnPoint ConvertPointY (AvnPoint p);
extern NSSize ToNSSize (AvnSize s);
extern AvnSize FromNSSize (NSSize s);
#ifdef DEBUG
#define NSDebugLog(...) NSLog(__VA_ARGS__)
#else
@ -87,6 +89,13 @@ public:
- (void) action;
@end
@implementation NSScreen (AvNSScreen)
- (CGDirectDisplayID)av_displayId
{
return [self.deviceDescription[@"NSScreenNumber"] unsignedIntValue];
}
@end
class AvnInsidePotentialDeadlock
{
public:

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

@ -225,6 +225,19 @@ public:
return (IAvnMacOptions*)new MacOptions();
}
virtual HRESULT CreateTopLevel(IAvnTopLevelEvents* cb,
IAvnTopLevel** ppv) override {
START_COM_CALL;
@autoreleasepool
{
if(cb == nullptr || ppv == nullptr)
return E_POINTER;
*ppv = CreateAvnTopLevel(cb);
return S_OK;
}
}
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv) override
{
START_COM_CALL;
@ -263,24 +276,24 @@ public:
}
}
virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) override
virtual HRESULT CreateStorageProvider(IAvnStorageProvider** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateSystemDialogs();
*ppv = ::CreateStorageProvider();
return S_OK;
}
}
virtual HRESULT CreateScreens (IAvnScreens** ppv) override
virtual HRESULT CreateScreens (IAvnScreenEvents* cb, IAvnScreens** ppv) override
{
START_COM_CALL;
@autoreleasepool
{
*ppv = ::CreateScreens ();
*ppv = ::CreateScreens (cb);
return S_OK;
}
}
@ -484,6 +497,15 @@ NSSize ToNSSize (AvnSize s)
return result;
}
AvnSize FromNSSize (NSSize s)
{
AvnSize result;
result.Width = s.width;
result.Height = s.height;
return result;
}
NSPoint ToNSPoint (AvnPoint p)
{
NSPoint result;

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

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

16
nukebuild/Build.cs

@ -19,6 +19,7 @@ using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
using static Serilog.Log;
using MicroCom.CodeGenerator;
using NuGet.Configuration;
using Nuke.Common.IO;
/*
@ -39,7 +40,8 @@ partial class Build : NukeBuild
[PackageExecutable("Microsoft.DotNet.GenAPI.Tool", "Microsoft.DotNet.GenAPI.Tool.dll", Framework = "net8.0")]
Tool ApiGenTool;
[PackageExecutable("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")]
Tool IlRepackTool;
protected override void OnBuildInitialized()
{
@ -306,7 +308,8 @@ partial class Build : NukeBuild
.Executes(() =>
{
BuildTasksPatcher.PatchBuildTasksInPackage(Parameters.NugetIntermediateRoot / "Avalonia.Build.Tasks." +
Parameters.Version + ".nupkg");
Parameters.Version + ".nupkg",
IlRepackTool);
var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
EnsureCleanDirectory(Parameters.NugetRoot);
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
@ -366,6 +369,9 @@ partial class Build : NukeBuild
{
if (!Parameters.IsPackingToLocalCache)
throw new InvalidOperationException();
var globalPackagesFolder = SettingsUtility.GetGlobalPackagesFolder(
Settings.LoadDefaultSettings(RootDirectory));
foreach (var path in Parameters.NugetRoot.GlobFiles("*.nupkg"))
{
@ -376,11 +382,11 @@ partial class Build : NukeBuild
.Elements().First(x => x.Name.LocalName == "metadata")
.Elements().First(x => x.Name.LocalName == "id").Value;
var packagePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
".nuget",
"packages",
var packagePath = Path.Combine(
globalPackagesFolder,
packageId.ToLowerInvariant(),
BuildParameters.LocalBuildVersion);
if (Directory.Exists(packagePath))
Directory.Delete(packagePath, true);
Directory.CreateDirectory(packagePath);

12
nukebuild/BuildParameters.cs

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

34
nukebuild/BuildTasksPatcher.cs

@ -2,9 +2,9 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
using ILRepacking;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Nuke.Common.Tooling;
public class BuildTasksPatcher
{
@ -56,7 +56,7 @@ public class BuildTasksPatcher
return null;
}
public static void PatchBuildTasksInPackage(string packagePath)
public static void PatchBuildTasksInPackage(string packagePath, Tool ilRepackTool)
{
using (var archive = new ZipArchive(File.Open(packagePath, FileMode.Open, FileAccess.ReadWrite),
ZipArchiveMode.Update))
@ -70,7 +70,7 @@ public class BuildTasksPatcher
Directory.CreateDirectory(tempDir);
var temp = Path.Combine(tempDir, entry.Name);
var output = temp + ".output";
File.Copy(typeof(Microsoft.Build.Framework.ITask).Assembly.GetModules()[0].FullyQualifiedName,
File.Copy(GetAssemblyPath(typeof(Microsoft.Build.Framework.ITask)),
Path.Combine(tempDir, "Microsoft.Build.Framework.dll"));
var patched = new MemoryStream();
try
@ -78,22 +78,15 @@ public class BuildTasksPatcher
entry.ExtractToFile(temp, true);
// Get Original SourceLinkInfo Content
var sourceLinkInfoContent = GetSourceLinkInfo(temp);
var repack = new ILRepacking.ILRepack(new RepackOptions()
{
Internalize = true,
InputAssemblies = new[]
{
temp,
typeof(Mono.Cecil.AssemblyDefinition).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Rocks.MethodBodyRocks).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Pdb.PdbReaderProvider).Assembly.GetModules()[0].FullyQualifiedName,
typeof(Mono.Cecil.Mdb.MdbReaderProvider).Assembly.GetModules()[0].FullyQualifiedName,
},
SearchDirectories = Array.Empty<string>(),
DebugInfo = true, // Allowed read debug info
OutputFile = output
});
repack.Repack();
var cecilAsm = GetAssemblyPath(typeof(Mono.Cecil.AssemblyDefinition));
var cecilRocksAsm = GetAssemblyPath(typeof(Mono.Cecil.Rocks.MethodBodyRocks));
var cecilPdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Pdb.PdbReaderProvider));
var cecilMdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Mdb.MdbReaderProvider));
ilRepackTool.Invoke(
$"/internalize /out:\"{output}\" \"{temp}\" \"{cecilAsm}\" \"{cecilRocksAsm}\" \"{cecilPdbAsm}\" \"{cecilMdbAsm}\"",
tempDir);
// 'hurr-durr assembly with the same name is already loaded' prevention
using (var asm = AssemblyDefinition.ReadAssembly(output,
@ -161,4 +154,7 @@ public class BuildTasksPatcher
}
}
}
private static string GetAssemblyPath(Type typeInAssembly)
=> typeInAssembly.Assembly.GetModules()[0].FullyQualifiedName;
}

4
nukebuild/_build.csproj

@ -20,7 +20,6 @@
<PackageReference Include="MicroCom.CodeGenerator" Version="0.11.0" />
<!-- Keep in sync with Avalonia.Build.Tasks -->
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="Microsoft.Debugging.Tools.PdbStr" Version="20230731.1609.0" GeneratePathProperty="true" PrivateAssets="All"/>
<PackageReference Include="Microsoft.Build.Framework" Version="17.3.2" PrivateAssets="All" />
<PackageReference Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
@ -29,6 +28,7 @@
<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]" />
</ItemGroup>
<ItemGroup>
@ -38,9 +38,7 @@
<!-- Common build related files -->
<Compile Remove="Numerge/**/*.*" />
<Compile Include="Numerge/Numerge/**/*.cs" Exclude="Numerge/Numerge/obj/**/*.cs" />
<EmbeddedResource Include="$(PkgMicrosoft_Debugging_Tools_PdbStr)/content/x86/pdbstr.exe" />
<EmbeddedResource Include="../build/avalonia.snk" />
<Compile Remove="il-repack\ILRepack\Application.cs" />
</ItemGroup>
<ItemGroup>

5
nukebuild/_build.csproj.DotSettings

@ -13,6 +13,8 @@
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/PLACE_SIMPLE_ANONYMOUSMETHOD_ON_SINGLE_LINE/@EntryValue">False</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=4a98fdf6_002D7d98_002D4f5a_002Dafeb_002Dea44ad98c70c/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Instance" AccessRightKinds="Private" Description="Instance fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;Kind Name="READONLY_FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/UserRules/=f9fce829_002De6f4_002D4cb2_002D80f1_002D5497c44f51df/@EntryIndexedValue">&lt;Policy&gt;&lt;Descriptor Staticness="Static" AccessRightKinds="Private" Description="Static fields (private)"&gt;&lt;ElementKinds&gt;&lt;Kind Name="FIELD" /&gt;&lt;/ElementKinds&gt;&lt;/Descriptor&gt;&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;&lt;/Policy&gt;</s:String>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpAttributeForSingleLineMethodUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
@ -21,4 +23,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EAddAccessorOwnerDeclarationBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002ECSharpPlaceAttributeOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateThisQualifierSettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EPredefinedNamingRulesToUserRulesUpgrade/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

1
nukebuild/il-repack

@ -1 +0,0 @@
Subproject commit 892f079ea8cb0c178f0a68f53a7a7eac13acdda9

34
packages/Avalonia/AvaloniaBuildTasks.targets

@ -135,6 +135,14 @@
Outputs="@(CompileAvaloniaXamlOutputs)"
Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(DesignTimeBuild) != true AND $(EnableAvaloniaXamlCompilation) != false">
<!--
$(IntermediateOutputPath)/Avalonia/references is using from AvaloniaVS for retrieve library references.
-->
<WriteLinesToFile
File="$(IntermediateOutputPath)/Avalonia/references"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
<CompileAvaloniaXamlTask
AssemblyFile="@(IntermediateAssembly)"
References="@(ReferencePathWithRefAssemblies)"
@ -169,12 +177,16 @@
</ItemGroup>
</Target>
<!-- For some reason the IL Compiler hardcodes $(IntermediateOutputPath)$(TargetName)$(TargetExt) instead of using @(IntermediateAssembly), change that to our assembly. -->
<!--
For some reason the IL Compiler hardcodes $(IntermediateOutputPath)$(TargetName)$(TargetExt)
instead of using @(IntermediateAssembly), change that to our assembly.
This is fixed in .NET 9.0 (https://github.com/dotnet/runtime/pull/99732)
-->
<Target Name="InjectIlcAvaloniaXamlOutput"
DependsOnTargets="InjectAvaloniaXamlOutput"
AfterTargets="ComputeIlcCompileInputs"
BeforeTargets="PrepareForILLink"
Condition="'@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(EnableAvaloniaXamlCompilation) != false">
Condition="$([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '9.0')) AND '@(AvaloniaResource)@(AvaloniaXaml)' != '' AND $(EnableAvaloniaXamlCompilation) != false">
<ItemGroup>
<ManagedBinary Remove="$(IntermediateOutputPath)$(TargetName)$(TargetExt)" />
<ManagedBinary Include="@(_AvaloniaXamlCompiledAssembly)" />
@ -241,22 +253,4 @@
'$(SkipCopyBuildProduct)' != 'true'">
<Delete Files="$(TargetRefPath)" Condition="Exists('$(TargetRefPath)')" />
</Target>
<!--
$(IntermediateOutputPath)/Avalonia/references is using from AvaloniaVS for retrieve library references.
This target generate $(IntermediateOutputPath)/Avalonia/references for in xplat Template
(see: https://github.com/AvaloniaUI/avalonia-dotnet-templates/tree/e4a489ae828f005f625145c563785174403e267c/templates/csharp/xplat).
-->
<Target Name="GenerateIntellisenseReferences"
AfterTargets="AfterCompile"
Condition="('@(AvaloniaResource->Count())' == 0) and ('@(AvaloniaXaml->Count())' == 0)">
<PropertyGroup>
<AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>
</PropertyGroup>
<WriteLinesToFile
Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'"
File="$(AvaloniaXamlReferencesTemporaryFilePath)"
Lines="@(ReferencePathWithRefAssemblies)"
Overwrite="true" />
</Target>
</Project>

16
readme.md

@ -1,5 +1,7 @@
![Star our repo to show support](https://user-images.githubusercontent.com/552074/235945895-1b896994-a0b6-4e7c-a522-c5688c4ec1b9.png)
![Header](https://user-images.githubusercontent.com/552074/235865745-2a8e7274-4f66-4f77-8f05-feeb76e7d478.png)
![Star Banner](https://github.com/AvaloniaUI/Avalonia/assets/552074/0f7f683f-2ddd-401f-ba28-3f703cc78ee0)
![Header](https://github.com/AvaloniaUI/Avalonia/assets/552074/d8388fc4-469e-47c5-926d-faf25233ad4e)
[![Telegram](https://raw.githubusercontent.com/Patrolavia/telegram-badge/master/chat.svg)](https://t.me/Avalonia)
[![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [![Backers on Open Collective](https://img.shields.io/opencollective/backers/Avalonia?logo=opencollective)](#backers) [![Sponsors on Open Collective](https://img.shields.io/opencollective/sponsors/Avalonia?logo=opencollective)](#sponsors) [![GitHub Sponsors](https://img.shields.io/github/sponsors/AvaloniaUI?logo=github)](https://github.com/sponsors/AvaloniaUI) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg)
@ -45,9 +47,7 @@ Install-Package Avalonia.Desktop
```
## Showcase
[![Showcase_Banner](https://user-images.githubusercontent.com/552074/235946124-bf6fda52-0c9f-4730-868b-0de957e5b97b.png)](https://avaloniaui.net/showcase)
[![Showcase_Banner@3x](https://github.com/AvaloniaUI/Avalonia/assets/552074/8a0af0e9-e45e-442c-830d-4af3767d6469)](https://avaloniaui.net/showcase)
See what others have built with Avalonia UI on our [Showcase](https://avaloniaui.net/Showcase). We welcome submissions!
@ -102,12 +102,6 @@ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com
<a href="https://opencollective.com/Avalonia#backers" target="_blank"><img src="https://opencollective.com/Avalonia/backers.svg?width=890"></a>
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Avalonia#sponsor)]
<a href="https://aws.amazon.com/developer/language/net/" target="_blank"><img src="https://github.com/AvaloniaUI/Avalonia/assets/552074/7771d8b9-ef84-4503-9889-033a87d2c852"></a>
## Commercial Support
We have a range of [support plans available](https://avaloniaui.net/support) for those looking to partner with the creators of Avalonia, enabling access to the best support at every step of the development process.

21
samples/ControlCatalog.Android/MainActivity.cs

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

15
samples/ControlCatalog.Browser/ControlCatalog.Browser.csproj

@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<PropertyGroup>
<TargetFramework>$(AvsCurrentBrowserTargetFramework)</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<WasmMainJSPath>wwwroot/main.js</WasmMainJSPath>
<OutputType>Exe</OutputType>
<WasmEnableThreads>false</WasmEnableThreads>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DebuggerSupport>true</DebuggerSupport>
<WasmDebugLevel>5</WasmDebugLevel>
</PropertyGroup>
<ItemGroup>
@ -12,9 +12,12 @@
<ProjectReference Include="../../src/Browser/Avalonia.Browser/Avalonia.Browser.csproj" />
<ProjectReference Include="../ControlCatalog/ControlCatalog.csproj" />
</ItemGroup>
<ItemGroup>
<WasmExtraFilesToDeploy Include="wwwroot/**" />
<!--
A workaround for VS and Rider being dumber than a rock when it comes to build dependency analysis
Also see https://youtrack.jetbrains.com/issue/RIDER-107175/Rider-doesnt-update-generate-transitive-Content-dependencies
-->
<AdditionalUpToDateCheckInput Include="../../src/Browser/Avalonia.Browser/**/*" Visible="false"/>
</ItemGroup>
<Import Project="../../src/Browser/Avalonia.Browser/build/Avalonia.Browser.props" />

2
samples/ControlCatalog.Browser/EmbedSample.Browser.cs

@ -29,7 +29,7 @@ public class EmbedSampleWeb : INativeDemoControl
static async void AddButton(JSObject parent)
{
await JSHost.ImportAsync("embed.js", "./embed.js");
await JSHost.ImportAsync("embed.js", "../embed.js");
EmbedInterop.AddAppButton(parent);
}
}

9
samples/ControlCatalog.Browser/Program.cs

@ -33,10 +33,13 @@ internal partial class Program
})
.StartBrowserAppAsync("out", options);
if (Application.Current!.ApplicationLifetime is ISingleTopLevelApplicationLifetime lifetime)
Dispatcher.UIThread.Invoke(() =>
{
lifetime.TopLevel!.RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
}
if (Application.Current!.ApplicationLifetime is ISingleTopLevelApplicationLifetime lifetime)
{
lifetime.TopLevel!.RendererDiagnostics.DebugOverlays = RendererDebugOverlays.Fps;
}
});
}
// Test with multiple AvaloniaView at once.

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

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

Before

Width:  |  Height:  |  Size: 701 B

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

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

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

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

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

@ -1,6 +1,3 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { dotnet } from './_framework/dotnet.js'
const is_browser = typeof window != "undefined";

5
samples/ControlCatalog.Desktop/Program.cs

@ -1,7 +1,5 @@
using System;
using System.Linq;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Platform;
using ControlCatalog.NetCore;
using ControlCatalog.Pages;
@ -29,7 +27,8 @@ namespace ControlCatalog
EmbedSample.Implementation = new EmbedSampleWin();
})
.UsePlatformDetect();
.UseWin32()
.UseSkia();
private static void ConfigureAssetAssembly(AppBuilder builder)
{

2
samples/ControlCatalog/ControlCatalog.csproj

@ -30,10 +30,12 @@
<ProjectReference Include="..\..\src\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj" />
<ProjectReference Include="..\..\src\Avalonia.Fonts.Inter\Avalonia.Fonts.Inter.csproj" />
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\MiniMvvm\MiniMvvm.csproj" />
<ProjectReference Include="..\SampleControls\ControlSamples.csproj" />
</ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\SourceGenerators.props" />
<Import Project="..\..\build\SkiaSharp.props" />
</Project>

6
samples/ControlCatalog/MainView.xaml

@ -130,6 +130,9 @@
<TabItem Header="OpenGL">
<pages:OpenGlPage />
</TabItem>
<TabItem Header="OpenGL Lease">
<pages:OpenGlLeasePage />
</TabItem>
<TabItem Header="Platform Information">
<pages:PlatformInfoPage />
</TabItem>
@ -196,6 +199,9 @@
<TabItem Header="HeaderedContentControl">
<pages:HeaderedContentPage />
</TabItem>
<TabItem Header="Screens">
<pages:ScreenPage />
</TabItem>
<FlyoutBase.AttachedFlyout>
<Flyout>
<StackPanel Width="152" Spacing="8">

10
samples/ControlCatalog/MainView.xaml.cs

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

5
samples/ControlCatalog/Pages/DataGridPage.xaml

@ -45,6 +45,11 @@
</StackPanel>
<DataGrid Name="dataGrid1" Margin="12" CanUserResizeColumns="True" CanUserReorderColumns="True" CanUserSortColumns="True" HeadersVisibility="All"
RowBackground="#1000">
<DataGrid.Styles>
<Style Selector="DataGridRow">
<Setter Property="Header" Value="{Binding $self.Index}"/>
</Style>
</DataGrid.Styles>
<DataGrid.Columns>
<!-- Using HeaderTemplate -->
<DataGridTextColumn Header="Country or Region" HeaderTemplate="{StaticResource Demo.DataTemplates.CountryHeader}" Binding="{Binding Name}" Width="6*" x:DataType="local:Country" />

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

@ -24,7 +24,6 @@ namespace ControlCatalog.Pages
collectionView1.SortDescriptions.Add(dataGridSortDescription);
var dg1 = this.Get<DataGrid>("dataGrid1");
dg1.IsReadOnly = true;
dg1.LoadingRow += Dg1_LoadingRow;
dg1.Sorting += (s, a) =>
{
var binding = (a.Column as DataGridBoundColumn)?.Binding as Binding;
@ -64,11 +63,6 @@ namespace ControlCatalog.Pages
}
public IEnumerable<Person> DataGrid3Source { get; }
private void Dg1_LoadingRow(object? sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
private void InitializeComponent()
{

74
samples/ControlCatalog/Pages/DateTimePickerPage.xaml

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

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

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

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

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

30
samples/ControlCatalog/Pages/OpenGl/GlPageKnobs.xaml

@ -0,0 +1,30 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.OpenGl.GlPageKnobs"
xmlns:pages="using:ControlCatalog.Pages"
xmlns:gl="using:ControlCatalog.Pages.OpenGl"
>
<Grid>
<StackPanel>
<TextBlock Text="{Binding $parent[gl:GlPageKnobs].Info}"/>
</StackPanel>
<Grid ColumnDefinitions="*,Auto" Margin="20">
<StackPanel Grid.Column="1" MinWidth="300">
<TextBlock>Yaw</TextBlock>
<Slider Value="{Binding $parent[gl:GlPageKnobs].Yaw, Mode=TwoWay}" Maximum="10"/>
<TextBlock>Pitch</TextBlock>
<Slider Value="{Binding $parent[gl:GlPageKnobs].Pitch, Mode=TwoWay}" Maximum="10"/>
<TextBlock>Roll</TextBlock>
<Slider Value="{Binding $parent[gl:GlPageKnobs].Roll, Mode=TwoWay}" Maximum="10"/>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="#C000C0">D</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#00C090">I</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#90C000">S</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#C09000">C</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#00C090">O</TextBlock>
</StackPanel>
<Slider Value="{Binding $parent[gl:GlPageKnobs].Disco, Mode=TwoWay}" Maximum="1"/>
</StackPanel>
</Grid>
</Grid>
</UserControl>

70
samples/ControlCatalog/Pages/OpenGl/GlPageKnobs.xaml.cs

@ -0,0 +1,70 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace ControlCatalog.Pages.OpenGl;
public partial class GlPageKnobs : UserControl
{
public GlPageKnobs()
{
AvaloniaXamlLoader.Load(this);
}
private float _yaw;
public static readonly DirectProperty<GlPageKnobs, float> YawProperty =
AvaloniaProperty.RegisterDirect<GlPageKnobs, float>("Yaw", o => o.Yaw, (o, v) => o.Yaw = v);
public float Yaw
{
get => _yaw;
set => SetAndRaise(YawProperty, ref _yaw, value);
}
private float _pitch;
public static readonly DirectProperty<GlPageKnobs, float> PitchProperty =
AvaloniaProperty.RegisterDirect<GlPageKnobs, float>("Pitch", o => o.Pitch, (o, v) => o.Pitch = v);
public float Pitch
{
get => _pitch;
set => SetAndRaise(PitchProperty, ref _pitch, value);
}
private float _roll;
public static readonly DirectProperty<GlPageKnobs, float> RollProperty =
AvaloniaProperty.RegisterDirect<GlPageKnobs, float>("Roll", o => o.Roll, (o, v) => o.Roll = v);
public float Roll
{
get => _roll;
set => SetAndRaise(RollProperty, ref _roll, value);
}
private float _disco;
public static readonly DirectProperty<GlPageKnobs, float> DiscoProperty =
AvaloniaProperty.RegisterDirect<GlPageKnobs, float>("Disco", o => o.Disco, (o, v) => o.Disco = v);
public float Disco
{
get => _disco;
set => SetAndRaise(DiscoProperty, ref _disco, value);
}
private string _info = string.Empty;
public static readonly DirectProperty<GlPageKnobs, string> InfoProperty =
AvaloniaProperty.RegisterDirect<GlPageKnobs, string>("Info", o => o.Info, (o, v) => o.Info = v);
public string Info
{
get => _info;
private set => SetAndRaise(InfoProperty, ref _info, value);
}
}

311
samples/ControlCatalog/Pages/OpenGl/OpenGlContent.cs

@ -0,0 +1,311 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.OpenGL;
using static Avalonia.OpenGL.GlConsts;
// ReSharper disable StringLiteralTypo
namespace ControlCatalog.Pages.OpenGl;
internal class OpenGlContent
{
private int _vertexShader;
private int _fragmentShader;
private int _shaderProgram;
private int _vertexBufferObject;
private int _indexBufferObject;
private int _vertexArrayObject;
private GlVersion GlVersion;
private string GetShader(bool fragment, string shader)
{
var version = (GlVersion.Type == GlProfileType.OpenGL
? RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120
: 100);
var data = "#version " + version + "\n";
if (GlVersion.Type == GlProfileType.OpenGLES)
data += "precision mediump float;\n";
if (version >= 150)
{
shader = shader.Replace("attribute", "in");
if (fragment)
shader = shader
.Replace("varying", "in")
.Replace("//DECLAREGLFRAG", "out vec4 outFragColor;")
.Replace("gl_FragColor", "outFragColor");
else
shader = shader.Replace("varying", "out");
}
data += shader;
return data;
}
private string VertexShaderSource => GetShader(false, @"
attribute vec3 aPos;
attribute vec3 aNormal;
uniform mat4 uModel;
uniform mat4 uProjection;
uniform mat4 uView;
varying vec3 FragPos;
varying vec3 VecPos;
varying vec3 Normal;
uniform float uTime;
uniform float uDisco;
void main()
{
float discoScale = sin(uTime * 10.0) / 10.0;
float distortionX = 1.0 + uDisco * cos(uTime * 20.0) / 10.0;
float scale = 1.0 + uDisco * discoScale;
vec3 scaledPos = aPos;
scaledPos.x = scaledPos.x * distortionX;
scaledPos *= scale;
gl_Position = uProjection * uView * uModel * vec4(scaledPos, 1.0);
FragPos = vec3(uModel * vec4(aPos, 1.0));
VecPos = aPos;
Normal = normalize(vec3(uModel * vec4(aNormal, 1.0)));
}
");
private string FragmentShaderSource => GetShader(true, @"
varying vec3 FragPos;
varying vec3 VecPos;
varying vec3 Normal;
uniform float uMaxY;
uniform float uMinY;
uniform float uTime;
uniform float uDisco;
//DECLAREGLFRAG
void main()
{
float y = (VecPos.y - uMinY) / (uMaxY - uMinY);
float c = cos(atan(VecPos.x, VecPos.z) * 20.0 + uTime * 40.0 + y * 50.0);
float s = sin(-atan(VecPos.z, VecPos.x) * 20.0 - uTime * 20.0 - y * 30.0);
vec3 discoColor = vec3(
0.5 + abs(0.5 - y) * cos(uTime * 10.0),
0.25 + (smoothstep(0.3, 0.8, y) * (0.5 - c / 4.0)),
0.25 + abs((smoothstep(0.1, 0.4, y) * (0.5 - s / 4.0))));
vec3 objectColor = vec3((1.0 - y), 0.40 + y / 4.0, y * 0.75 + 0.25);
objectColor = objectColor * (1.0 - uDisco) + discoColor * uDisco;
float ambientStrength = 0.3;
vec3 lightColor = vec3(1.0, 1.0, 1.0);
vec3 lightPos = vec3(uMaxY * 2.0, uMaxY * 2.0, uMaxY * 2.0);
vec3 ambient = ambientStrength * lightColor;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
vec3 result = (ambient + diffuse) * objectColor;
gl_FragColor = vec4(result, 1.0);
}
");
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct Vertex
{
public Vector3 Position;
public Vector3 Normal;
}
private readonly Vertex[] _points;
private readonly ushort[] _indices;
private readonly float _minY;
private readonly float _maxY;
public OpenGlContent()
{
var name = typeof(OpenGlPage).Assembly.GetManifestResourceNames().First(x => x.Contains("teapot.bin"));
using (var sr = new BinaryReader(typeof(OpenGlPage).Assembly.GetManifestResourceStream(name)!))
{
var buf = new byte[sr.ReadInt32()];
sr.Read(buf, 0, buf.Length);
var points = new float[buf.Length / 4];
Buffer.BlockCopy(buf, 0, points, 0, buf.Length);
buf = new byte[sr.ReadInt32()];
sr.Read(buf, 0, buf.Length);
_indices = new ushort[buf.Length / 2];
Buffer.BlockCopy(buf, 0, _indices, 0, buf.Length);
_points = new Vertex[points.Length / 3];
for (var primitive = 0; primitive < points.Length / 3; primitive++)
{
var srci = primitive * 3;
_points[primitive] = new Vertex
{
Position = new Vector3(points[srci], points[srci + 1], points[srci + 2])
};
}
for (int i = 0; i < _indices.Length; i += 3)
{
Vector3 a = _points[_indices[i]].Position;
Vector3 b = _points[_indices[i + 1]].Position;
Vector3 c = _points[_indices[i + 2]].Position;
var normal = Vector3.Normalize(Vector3.Cross(c - b, a - b));
_points[_indices[i]].Normal += normal;
_points[_indices[i + 1]].Normal += normal;
_points[_indices[i + 2]].Normal += normal;
}
for (int i = 0; i < _points.Length; i++)
{
_points[i].Normal = Vector3.Normalize(_points[i].Normal);
_maxY = Math.Max(_maxY, _points[i].Position.Y);
_minY = Math.Min(_minY, _points[i].Position.Y);
}
}
}
private static void CheckError(GlInterface gl)
{
int err;
while ((err = gl.GetError()) != GL_NO_ERROR)
Console.WriteLine(err);
}
public string Info { get; private set; } = string.Empty;
public unsafe void Init(GlInterface GL, GlVersion version)
{
GlVersion = version;
CheckError(GL);
Info = $"Renderer: {GL.GetString(GL_RENDERER)} Version: {GL.GetString(GL_VERSION)}";
// Load the source of the vertex shader and compile it.
_vertexShader = GL.CreateShader(GL_VERTEX_SHADER);
Console.WriteLine(GL.CompileShaderAndGetError(_vertexShader, VertexShaderSource));
// Load the source of the fragment shader and compile it.
_fragmentShader = GL.CreateShader(GL_FRAGMENT_SHADER);
Console.WriteLine(GL.CompileShaderAndGetError(_fragmentShader, FragmentShaderSource));
// Create the shader program, attach the vertex and fragment shaders and link the program.
_shaderProgram = GL.CreateProgram();
GL.AttachShader(_shaderProgram, _vertexShader);
GL.AttachShader(_shaderProgram, _fragmentShader);
const int positionLocation = 0;
const int normalLocation = 1;
GL.BindAttribLocationString(_shaderProgram, positionLocation, "aPos");
GL.BindAttribLocationString(_shaderProgram, normalLocation, "aNormal");
Console.WriteLine(GL.LinkProgramAndGetError(_shaderProgram));
CheckError(GL);
// Create the vertex buffer object (VBO) for the vertex data.
_vertexBufferObject = GL.GenBuffer();
// Bind the VBO and copy the vertex data into it.
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
CheckError(GL);
var vertexSize = Marshal.SizeOf<Vertex>();
fixed (void* pdata = _points)
GL.BufferData(GL_ARRAY_BUFFER, new IntPtr(_points.Length * vertexSize),
new IntPtr(pdata), GL_STATIC_DRAW);
_indexBufferObject = GL.GenBuffer();
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);
CheckError(GL);
fixed (void* pdata = _indices)
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, new IntPtr(_indices.Length * sizeof(ushort)), new IntPtr(pdata),
GL_STATIC_DRAW);
CheckError(GL);
_vertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(_vertexArrayObject);
CheckError(GL);
GL.VertexAttribPointer(positionLocation, 3, GL_FLOAT,
0, vertexSize, IntPtr.Zero);
GL.VertexAttribPointer(normalLocation, 3, GL_FLOAT,
0, vertexSize, new IntPtr(12));
GL.EnableVertexAttribArray(positionLocation);
GL.EnableVertexAttribArray(normalLocation);
CheckError(GL);
}
public void Deinit(GlInterface GL)
{
// Unbind everything
GL.BindBuffer(GL_ARRAY_BUFFER, 0);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
GL.BindVertexArray(0);
GL.UseProgram(0);
// Delete all resources.
GL.DeleteBuffer(_vertexBufferObject);
GL.DeleteBuffer(_indexBufferObject);
GL.DeleteVertexArray(_vertexArrayObject);
GL.DeleteProgram(_shaderProgram);
GL.DeleteShader(_fragmentShader);
GL.DeleteShader(_vertexShader);
}
static Stopwatch St = Stopwatch.StartNew();
public unsafe void OnOpenGlRender(GlInterface gl, int fb, PixelSize size,
float yaw, float pitch, float roll, float disco)
{
gl.Viewport(0, 0, size.Width, size.Height);
gl.ClearDepth(1);
gl.Disable(GL_CULL_FACE);
gl.Disable(GL_SCISSOR_TEST);
gl.DepthFunc(GL_LESS);
gl.DepthMask(1);
gl.ClearColor(0, 0, 0, 0);
gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.Enable(GL_DEPTH_TEST);
var GL = gl;
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);
GL.BindVertexArray(_vertexArrayObject);
GL.UseProgram(_shaderProgram);
CheckError(GL);
var projection =
Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)(size.Width / size.Height),
0.01f, 1000);
var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, 1, 0));
var model = Matrix4x4.CreateFromYawPitchRoll(yaw, pitch, roll);
var modelLoc = GL.GetUniformLocationString(_shaderProgram, "uModel");
var viewLoc = GL.GetUniformLocationString(_shaderProgram, "uView");
var projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");
var maxYLoc = GL.GetUniformLocationString(_shaderProgram, "uMaxY");
var minYLoc = GL.GetUniformLocationString(_shaderProgram, "uMinY");
var timeLoc = GL.GetUniformLocationString(_shaderProgram, "uTime");
var discoLoc = GL.GetUniformLocationString(_shaderProgram, "uDisco");
GL.UniformMatrix4fv(modelLoc, 1, false, &model);
GL.UniformMatrix4fv(viewLoc, 1, false, &view);
GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);
GL.Uniform1f(maxYLoc, _maxY);
GL.Uniform1f(minYLoc, _minY);
GL.Uniform1f(timeLoc, (float)St.Elapsed.TotalSeconds);
GL.Uniform1f(discoLoc, disco);
CheckError(GL);
GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_SHORT, IntPtr.Zero);
CheckError(GL);
}
}

118
samples/ControlCatalog/Pages/OpenGl/OpenGlFbo.cs

@ -0,0 +1,118 @@
using System;
using Avalonia;
using Avalonia.Logging;
using Avalonia.OpenGL;
using SkiaSharp;
using static Avalonia.OpenGL.GlConsts;
namespace ControlCatalog.Pages.OpenGl;
internal class OpenGlFbo : IDisposable
{
private readonly GRContext _grContext;
private int _fbo;
private int _depthBuffer;
private int _texture;
private PixelSize _size;
public PixelSize Size => _size;
public GlInterface Gl => Context.GlInterface;
public IGlContext Context { get; }
public OpenGlFbo(IGlContext context, GRContext grContext)
{
_grContext = grContext;
Context = context;
_fbo = Gl.GenFramebuffer();
}
public void Resize(PixelSize size)
{
if(_size == size)
return;
if (_texture != 0)
Gl.DeleteTexture(_texture);
_texture = 0;
if(_depthBuffer != 0)
Gl.DeleteRenderbuffer(_depthBuffer);
_depthBuffer = 0;
Gl.BindFramebuffer(GL_FRAMEBUFFER, _fbo);
_texture = Gl.GenTexture();
var textureFormat = Context.Version.Type == GlProfileType.OpenGLES && Context.Version.Major == 2
? GL_RGBA
: GL_RGBA8;
Gl.BindTexture(GL_TEXTURE_2D, _texture);
Gl.TexImage2D(GL_TEXTURE_2D, 0, textureFormat, size.Width, size.Height, 0, GL_RGBA,
GL_UNSIGNED_BYTE, IntPtr.Zero);
Gl.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
_depthBuffer = Gl.GenRenderbuffer();
var depthFormat = Context.Version.Type == GlProfileType.OpenGLES
? GL_DEPTH_COMPONENT16
: GL_DEPTH_COMPONENT;
Gl.BindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
Gl.RenderbufferStorage(GL_RENDERBUFFER, depthFormat, size.Width, size.Height);
Gl.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);
var status = Gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
IsValid = (status == GL_FRAMEBUFFER_COMPLETE);
if(!IsValid)
{
int code = Gl.GetError();
Console.WriteLine("Unable to configure OpenGL FBO: " + code);
}
_size = size;
}
public bool IsValid { get; private set; }
public int Fbo => _fbo;
public SKImage? Snapshot()
{
Gl.Flush();
_grContext.ResetContext();
using var texture = new GRBackendTexture(_size.Width, _size.Height, false,
new GRGlTextureInfo(GlConsts.GL_TEXTURE_2D, (uint)_texture, SKColorType.Rgba8888.ToGlSizedFormat()));
var surf = SKSurface.Create(_grContext, texture, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
if (surf == null)
{
using var unformatted = new GRBackendTexture(_size.Width, _size.Height, false,
new GRGlTextureInfo(GlConsts.GL_TEXTURE_2D, (uint)_texture));
surf = SKSurface.Create(_grContext, unformatted, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888);
}
SKImage? rv;
using (surf)
rv = surf?.Snapshot();
_grContext.Flush();
return rv;
/*
var target = new GRBackendRenderTarget(_size.Width, _size.Height, 0, 0,
new GRGlFramebufferInfo((uint)_fbo, SKColorType.Rgba8888.ToGlSizedFormat()));
SKImage rv;
using (var surface = SKSurface.Create(_grContext, target,
GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888,
new SKSurfaceProperties(SKPixelGeometry.RgbHorizontal)))
rv = surface.Snapshot();
_grContext.Flush();
return rv;*/
}
public void Dispose()
{
if(_fbo != 0)
Gl.DeleteFramebuffer(_fbo);
_fbo = 0;
if (_depthBuffer != 0)
Gl.DeleteRenderbuffer(_depthBuffer);
if(_texture != 0)
Gl.DeleteTexture(_texture);
}
}

10
samples/ControlCatalog/Pages/OpenGl/OpenGlLeasePage.xaml

@ -0,0 +1,10 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.OpenGlLeasePage"
xmlns:pages="using:ControlCatalog.Pages"
xmlns:openGl="clr-namespace:ControlCatalog.Pages.OpenGl">
<Grid>
<Control x:Name="Viewport" />
<openGl:GlPageKnobs x:Name="Knobs" />
</Grid>
</UserControl>

216
samples/ControlCatalog/Pages/OpenGl/OpenGlLeasePage.xaml.cs

@ -0,0 +1,216 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Rendering.Composition;
using Avalonia.Skia;
using ControlCatalog.Pages.OpenGl;
using SkiaSharp;
using static Avalonia.OpenGL.GlConsts;
namespace ControlCatalog.Pages;
public class OpenGlLeasePage : UserControl
{
private readonly Control _viewport;
private readonly GlPageKnobs _knobs;
private CompositionCustomVisual? _visual;
class GlVisual : CompositionCustomVisualHandler
{
private OpenGlContent _content;
private Parameters _parameters;
private bool _contentInitialized;
private OpenGlFbo? _fbo;
private bool _reRender;
private IGlContext? _gl;
public GlVisual(OpenGlContent content, Parameters parameters)
{
_content = content;
_parameters = parameters;
}
public override void OnRender(ImmediateDrawingContext drawingContext)
{
if (_parameters.Disco > 0.01f)
RegisterForNextAnimationFrameUpdate();
var bounds = GetRenderBounds();
var size = PixelSize.FromSize(bounds.Size, 1);
if (size.Width < 1 || size.Height < 1)
return;
if(drawingContext.TryGetFeature<ISkiaSharpApiLeaseFeature>(out var skiaFeature))
{
using var skiaLease = skiaFeature.Lease();
var grContext = skiaLease.GrContext;
if (grContext == null)
return;
SKImage? snapshot;
using (var platformApiLease = skiaLease.TryLeasePlatformGraphicsApi())
{
if (platformApiLease?.Context is not IGlContext glContext)
return;
var gl = glContext.GlInterface;
if (_gl != glContext)
{
// The old context is lost
_fbo = null;
_contentInitialized = false;
_gl = glContext;
}
gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var oldFb);
_fbo ??= new OpenGlFbo(glContext, grContext);
if (_fbo.Size != size)
_fbo.Resize(size);
gl.BindFramebuffer(GL_FRAMEBUFFER, _fbo.Fbo);
if (!_contentInitialized)
{
_content.Init(gl, glContext.Version);
_contentInitialized = true;
}
_content.OnOpenGlRender(gl, _fbo.Fbo, size, _parameters.Yaw, _parameters.Pitch,
_parameters.Roll, _parameters.Disco);
snapshot = _fbo.Snapshot();
gl.BindFramebuffer(GL_FRAMEBUFFER, oldFb);
}
using(snapshot)
if (snapshot != null)
skiaLease.SkCanvas.DrawImage(snapshot, new SKRect(0, 0,
(float)bounds.Width, (float)bounds.Height));
}
}
public override void OnAnimationFrameUpdate()
{
if (_reRender || _parameters.Disco > 0.01f)
{
_reRender = false;
Invalidate();
}
base.OnAnimationFrameUpdate();
}
public override void OnMessage(object message)
{
if (message is Parameters p)
{
_parameters = p;
_reRender = true;
RegisterForNextAnimationFrameUpdate();
}
else if (message is DisposeMessage)
{
if (_gl != null)
{
try
{
if (_fbo != null || _contentInitialized)
{
using (_gl.MakeCurrent())
{
if (_contentInitialized)
_content.Deinit(_gl.GlInterface);
_contentInitialized = false;
_fbo?.Dispose();
_fbo = null;
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
_gl = null;
}
}
base.OnMessage(message);
}
}
public class Parameters
{
public float Yaw;
public float Pitch;
public float Roll;
public float Disco;
}
public class DisposeMessage
{
}
public OpenGlLeasePage()
{
AvaloniaXamlLoader.Load(this);
_viewport = this.FindControl<Control>("Viewport")!;
_viewport.AttachedToVisualTree += ViewportAttachedToVisualTree;
_viewport.DetachedFromVisualTree += ViewportDetachedFromVisualTree;
_knobs = this.FindControl<GlPageKnobs>("Knobs")!;
_knobs.PropertyChanged += KnobsPropertyChanged;
}
private void KnobsPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs change)
{
if (change.Property == GlPageKnobs.YawProperty
|| change.Property == GlPageKnobs.RollProperty
|| change.Property == GlPageKnobs.PitchProperty
|| change.Property == GlPageKnobs.DiscoProperty)
_visual?.SendHandlerMessage(GetParameters());
}
Parameters GetParameters() => new()
{
Yaw = _knobs!.Yaw, Pitch = _knobs.Pitch, Roll = _knobs.Roll, Disco = _knobs.Disco
};
private void ViewportAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
var visual = ElementComposition.GetElementVisual(_viewport!);
if(visual == null)
return;
_visual = visual.Compositor.CreateCustomVisual(new GlVisual(new OpenGlContent(), GetParameters()));
ElementComposition.SetElementChildVisual(_viewport, _visual);
UpdateSize(Bounds.Size);
}
private void UpdateSize(Size size)
{
if (_visual != null)
_visual.Size = new Vector(size.Width, size.Height);
}
protected override Size ArrangeOverride(Size finalSize)
{
var size = base.ArrangeOverride(finalSize);
UpdateSize(size);
return size;
}
private void ViewportDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
_visual?.SendHandlerMessage(new DisposeMessage());
_visual = null;
ElementComposition.SetElementChildVisual(_viewport, null);
base.OnDetachedFromVisualTree(e);
}
}

30
samples/ControlCatalog/Pages/OpenGlPage.xaml

@ -1,29 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.Pages.OpenGlPage"
xmlns:pages="using:ControlCatalog.Pages">
<Grid>
xmlns:pages="using:ControlCatalog.Pages"
xmlns:openGl="clr-namespace:ControlCatalog.Pages.OpenGl">
<Grid x:Name="MainGrid">
<pages:OpenGlPageControl x:Name="GL"/>
<StackPanel>
<TextBlock Text="{Binding #GL.Info}"/>
</StackPanel>
<Grid ColumnDefinitions="*,Auto" Margin="20">
<StackPanel Grid.Column="1" MinWidth="300">
<TextBlock>Yaw</TextBlock>
<Slider Value="{Binding Yaw, Mode=TwoWay, ElementName=GL}" Maximum="10"/>
<TextBlock>Pitch</TextBlock>
<Slider Value="{Binding Pitch, Mode=TwoWay, ElementName=GL}" Maximum="10"/>
<TextBlock>Roll</TextBlock>
<Slider Value="{Binding Roll, Mode=TwoWay, ElementName=GL}" Maximum="10"/>
<StackPanel Orientation="Horizontal">
<TextBlock FontWeight="Bold" Foreground="#C000C0">D</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#00C090">I</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#90C000">S</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#C09000">C</TextBlock>
<TextBlock FontWeight="Bold" Foreground="#00C090">O</TextBlock>
</StackPanel>
<Slider Value="{Binding Disco, Mode=TwoWay, ElementName=GL}" Maximum="1"/>
</StackPanel>
</Grid>
<openGl:GlPageKnobs x:Name="Knobs" />
<Button x:Name="Snapshot"
IsVisible="False"
VerticalAlignment="Bottom" HorizontalAlignment="Right" Click="SnapshotClick">Snapshot</Button>
</Grid>
</UserControl>

391
samples/ControlCatalog/Pages/OpenGlPage.xaml.cs

@ -1,375 +1,84 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Controls;
using Avalonia.Platform.Interop;
using Avalonia.Threading;
using static Avalonia.OpenGL.GlConsts;
using Avalonia.Rendering.Composition;
using ControlCatalog.Pages.OpenGl;
// ReSharper disable StringLiteralTypo
namespace ControlCatalog.Pages
{
public class OpenGlPage : UserControl
{
}
public class OpenGlPageControl : OpenGlControlBase
{
private float _yaw;
public static readonly DirectProperty<OpenGlPageControl, float> YawProperty =
AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Yaw", o => o.Yaw, (o, v) => o.Yaw = v);
public float Yaw
{
get => _yaw;
set => SetAndRaise(YawProperty, ref _yaw, value);
}
private float _pitch;
public static readonly DirectProperty<OpenGlPageControl, float> PitchProperty =
AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Pitch", o => o.Pitch, (o, v) => o.Pitch = v);
public float Pitch
{
get => _pitch;
set => SetAndRaise(PitchProperty, ref _pitch, value);
}
private float _roll;
public static readonly DirectProperty<OpenGlPageControl, float> RollProperty =
AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Roll", o => o.Roll, (o, v) => o.Roll = v);
public float Roll
{
get => _roll;
set => SetAndRaise(RollProperty, ref _roll, value);
}
private float _disco;
public static readonly DirectProperty<OpenGlPageControl, float> DiscoProperty =
AvaloniaProperty.RegisterDirect<OpenGlPageControl, float>("Disco", o => o.Disco, (o, v) => o.Disco = v);
public float Disco
{
get => _disco;
set => SetAndRaise(DiscoProperty, ref _disco, value);
}
private string _info = string.Empty;
public static readonly DirectProperty<OpenGlPageControl, string> InfoProperty =
AvaloniaProperty.RegisterDirect<OpenGlPageControl, string>("Info", o => o.Info, (o, v) => o.Info = v);
public string Info
{
get => _info;
private set => SetAndRaise(InfoProperty, ref _info, value);
}
private int _vertexShader;
private int _fragmentShader;
private int _shaderProgram;
private int _vertexBufferObject;
private int _indexBufferObject;
private int _vertexArrayObject;
private string GetShader(bool fragment, string shader)
{
var version = (GlVersion.Type == GlProfileType.OpenGL ?
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120 :
100);
var data = "#version " + version + "\n";
if (GlVersion.Type == GlProfileType.OpenGLES)
data += "precision mediump float;\n";
if (version >= 150)
{
shader = shader.Replace("attribute", "in");
if (fragment)
shader = shader
.Replace("varying", "in")
.Replace("//DECLAREGLFRAG", "out vec4 outFragColor;")
.Replace("gl_FragColor", "outFragColor");
else
shader = shader.Replace("varying", "out");
}
data += shader;
return data;
}
private string VertexShaderSource => GetShader(false, @"
attribute vec3 aPos;
attribute vec3 aNormal;
uniform mat4 uModel;
uniform mat4 uProjection;
uniform mat4 uView;
varying vec3 FragPos;
varying vec3 VecPos;
varying vec3 Normal;
uniform float uTime;
uniform float uDisco;
void main()
public OpenGlPage()
{
float discoScale = sin(uTime * 10.0) / 10.0;
float distortionX = 1.0 + uDisco * cos(uTime * 20.0) / 10.0;
AvaloniaXamlLoader.Load(this);
this.FindControl<OpenGlPageControl>("GL")
!.Init(this.FindControl<GlPageKnobs>("Knobs")!);
float scale = 1.0 + uDisco * discoScale;
vec3 scaledPos = aPos;
scaledPos.x = scaledPos.x * distortionX;
scaledPos *= scale;
gl_Position = uProjection * uView * uModel * vec4(scaledPos, 1.0);
FragPos = vec3(uModel * vec4(aPos, 1.0));
VecPos = aPos;
Normal = normalize(vec3(uModel * vec4(aNormal, 1.0)));
}
");
private string FragmentShaderSource => GetShader(true, @"
varying vec3 FragPos;
varying vec3 VecPos;
varying vec3 Normal;
uniform float uMaxY;
uniform float uMinY;
uniform float uTime;
uniform float uDisco;
//DECLAREGLFRAG
void main()
{
float y = (VecPos.y - uMinY) / (uMaxY - uMinY);
float c = cos(atan(VecPos.x, VecPos.z) * 20.0 + uTime * 40.0 + y * 50.0);
float s = sin(-atan(VecPos.z, VecPos.x) * 20.0 - uTime * 20.0 - y * 30.0);
vec3 discoColor = vec3(
0.5 + abs(0.5 - y) * cos(uTime * 10.0),
0.25 + (smoothstep(0.3, 0.8, y) * (0.5 - c / 4.0)),
0.25 + abs((smoothstep(0.1, 0.4, y) * (0.5 - s / 4.0))));
vec3 objectColor = vec3((1.0 - y), 0.40 + y / 4.0, y * 0.75 + 0.25);
objectColor = objectColor * (1.0 - uDisco) + discoColor * uDisco;
float ambientStrength = 0.3;
vec3 lightColor = vec3(1.0, 1.0, 1.0);
vec3 lightPos = vec3(uMaxY * 2.0, uMaxY * 2.0, uMaxY * 2.0);
vec3 ambient = ambientStrength * lightColor;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
vec3 result = (ambient + diffuse) * objectColor;
gl_FragColor = vec4(result, 1.0);
}
");
[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct Vertex
{
public Vector3 Position;
public Vector3 Normal;
AttachedToVisualTree += delegate
{
if (TopLevel.GetTopLevel(this) is Window)
this.FindControl<Button>("Snapshot")!.IsVisible = true;
};
}
private readonly Vertex[] _points;
private readonly ushort[] _indices;
private readonly float _minY;
private readonly float _maxY;
public OpenGlPageControl()
private async void SnapshotClick(object sender, RoutedEventArgs e)
{
var name = typeof(OpenGlPage).Assembly.GetManifestResourceNames().First(x => x.Contains("teapot.bin"));
using (var sr = new BinaryReader(typeof(OpenGlPage).Assembly.GetManifestResourceStream(name)!))
var v = ElementComposition.GetElementVisual(this)!;
var snap = await v.Compositor.CreateCompositionVisualSnapshot(v, 1.5);
await new Window()
{
var buf = new byte[sr.ReadInt32()];
sr.Read(buf, 0, buf.Length);
var points = new float[buf.Length / 4];
Buffer.BlockCopy(buf, 0, points, 0, buf.Length);
buf = new byte[sr.ReadInt32()];
sr.Read(buf, 0, buf.Length);
_indices = new ushort[buf.Length / 2];
Buffer.BlockCopy(buf, 0, _indices, 0, buf.Length);
_points = new Vertex[points.Length / 3];
for (var primitive = 0; primitive < points.Length / 3; primitive++)
Content = new ScrollViewer()
{
var srci = primitive * 3;
_points[primitive] = new Vertex
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
Content = new Image()
{
Position = new Vector3(points[srci], points[srci + 1], points[srci + 2])
};
}
for (int i = 0; i < _indices.Length; i += 3)
{
Vector3 a = _points[_indices[i]].Position;
Vector3 b = _points[_indices[i + 1]].Position;
Vector3 c = _points[_indices[i + 2]].Position;
var normal = Vector3.Normalize(Vector3.Cross(c - b, a - b));
_points[_indices[i]].Normal += normal;
_points[_indices[i + 1]].Normal += normal;
_points[_indices[i + 2]].Normal += normal;
}
for (int i = 0; i < _points.Length; i++)
{
_points[i].Normal = Vector3.Normalize(_points[i].Normal);
_maxY = Math.Max(_maxY, _points[i].Position.Y);
_minY = Math.Min(_minY, _points[i].Position.Y);
Source = snap
}
}
}
}.ShowDialog((Window)TopLevel.GetTopLevel(this));
}
}
private static void CheckError(GlInterface gl)
{
int err;
while ((err = gl.GetError()) != GL_NO_ERROR)
Console.WriteLine(err);
}
protected override unsafe void OnOpenGlInit(GlInterface GL)
{
CheckError(GL);
Info = $"Renderer: {GL.GetString(GL_RENDERER)} Version: {GL.GetString(GL_VERSION)}";
// Load the source of the vertex shader and compile it.
_vertexShader = GL.CreateShader(GL_VERTEX_SHADER);
Console.WriteLine(GL.CompileShaderAndGetError(_vertexShader, VertexShaderSource));
// Load the source of the fragment shader and compile it.
_fragmentShader = GL.CreateShader(GL_FRAGMENT_SHADER);
Console.WriteLine(GL.CompileShaderAndGetError(_fragmentShader, FragmentShaderSource));
// Create the shader program, attach the vertex and fragment shaders and link the program.
_shaderProgram = GL.CreateProgram();
GL.AttachShader(_shaderProgram, _vertexShader);
GL.AttachShader(_shaderProgram, _fragmentShader);
const int positionLocation = 0;
const int normalLocation = 1;
GL.BindAttribLocationString(_shaderProgram, positionLocation, "aPos");
GL.BindAttribLocationString(_shaderProgram, normalLocation, "aNormal");
Console.WriteLine(GL.LinkProgramAndGetError(_shaderProgram));
CheckError(GL);
// Create the vertex buffer object (VBO) for the vertex data.
_vertexBufferObject = GL.GenBuffer();
// Bind the VBO and copy the vertex data into it.
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
CheckError(GL);
var vertexSize = Marshal.SizeOf<Vertex>();
fixed (void* pdata = _points)
GL.BufferData(GL_ARRAY_BUFFER, new IntPtr(_points.Length * vertexSize),
new IntPtr(pdata), GL_STATIC_DRAW);
_indexBufferObject = GL.GenBuffer();
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);
CheckError(GL);
fixed (void* pdata = _indices)
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, new IntPtr(_indices.Length * sizeof(ushort)), new IntPtr(pdata),
GL_STATIC_DRAW);
CheckError(GL);
_vertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(_vertexArrayObject);
CheckError(GL);
GL.VertexAttribPointer(positionLocation, 3, GL_FLOAT,
0, vertexSize, IntPtr.Zero);
GL.VertexAttribPointer(normalLocation, 3, GL_FLOAT,
0, vertexSize, new IntPtr(12));
GL.EnableVertexAttribArray(positionLocation);
GL.EnableVertexAttribArray(normalLocation);
CheckError(GL);
}
public class OpenGlPageControl : OpenGlControlBase
{
private OpenGlContent _content = new();
private GlPageKnobs? _knobs;
protected override void OnOpenGlDeinit(GlInterface GL)
public void Init(GlPageKnobs knobs)
{
// Unbind everything
GL.BindBuffer(GL_ARRAY_BUFFER, 0);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
GL.BindVertexArray(0);
GL.UseProgram(0);
// Delete all resources.
GL.DeleteBuffer(_vertexBufferObject);
GL.DeleteBuffer(_indexBufferObject);
GL.DeleteVertexArray(_vertexArrayObject);
GL.DeleteProgram(_shaderProgram);
GL.DeleteShader(_fragmentShader);
GL.DeleteShader(_vertexShader);
_knobs = knobs;
_knobs.PropertyChanged += KnobsPropertyChanged;
}
static Stopwatch St = Stopwatch.StartNew();
protected override unsafe void OnOpenGlRender(GlInterface gl, int fb)
private void KnobsPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs change)
{
gl.ClearColor(0, 0, 0, 0);
gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
gl.Enable(GL_DEPTH_TEST);
gl.Viewport(0, 0, (int)Bounds.Width, (int)Bounds.Height);
var GL = gl;
GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject);
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject);
GL.BindVertexArray(_vertexArrayObject);
GL.UseProgram(_shaderProgram);
CheckError(GL);
var projection =
Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)(Bounds.Width / Bounds.Height),
0.01f, 1000);
var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, 1, 0));
var model = Matrix4x4.CreateFromYawPitchRoll(_yaw, _pitch, _roll);
var modelLoc = GL.GetUniformLocationString(_shaderProgram, "uModel");
var viewLoc = GL.GetUniformLocationString(_shaderProgram, "uView");
var projectionLoc = GL.GetUniformLocationString(_shaderProgram, "uProjection");
var maxYLoc = GL.GetUniformLocationString(_shaderProgram, "uMaxY");
var minYLoc = GL.GetUniformLocationString(_shaderProgram, "uMinY");
var timeLoc = GL.GetUniformLocationString(_shaderProgram, "uTime");
var discoLoc = GL.GetUniformLocationString(_shaderProgram, "uDisco");
GL.UniformMatrix4fv(modelLoc, 1, false, &model);
GL.UniformMatrix4fv(viewLoc, 1, false, &view);
GL.UniformMatrix4fv(projectionLoc, 1, false, &projection);
GL.Uniform1f(maxYLoc, _maxY);
GL.Uniform1f(minYLoc, _minY);
GL.Uniform1f(timeLoc, (float)St.Elapsed.TotalSeconds);
GL.Uniform1f(discoLoc, _disco);
CheckError(GL);
GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_SHORT, IntPtr.Zero);
CheckError(GL);
if (_disco > 0.01)
if (change.Property == GlPageKnobs.YawProperty
|| change.Property == GlPageKnobs.RollProperty
|| change.Property == GlPageKnobs.PitchProperty
|| change.Property == GlPageKnobs.DiscoProperty)
RequestNextFrameRendering();
}
protected override unsafe void OnOpenGlInit(GlInterface GL) => _content.Init(GL, GlVersion);
protected override void OnOpenGlDeinit(GlInterface GL) => _content.Deinit(GL);
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
protected override unsafe void OnOpenGlRender(GlInterface gl, int fb)
{
if (change.Property == YawProperty || change.Property == RollProperty || change.Property == PitchProperty ||
change.Property == DiscoProperty)
if (_knobs == null)
return;
_content.OnOpenGlRender(gl, fb, new PixelSize((int)Bounds.Width, (int)Bounds.Height),
_knobs.Yaw, _knobs.Pitch, _knobs.Roll, _knobs.Disco);
if (_knobs.Disco > 0.01)
RequestNextFrameRendering();
base.OnPropertyChanged(change);
}
}
}

32
samples/ControlCatalog/Pages/ProgressBarPage.xaml

@ -1,41 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="ControlCatalog.Pages.ProgressBarPage">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h2">A progress bar control</TextBlock>
<StackPanel Spacing="5">
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock VerticalAlignment="Center">Maximum</TextBlock>
<NumericUpDown x:Name="maximum" Value="100" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock VerticalAlignment="Center">Minimum</TextBlock>
<NumericUpDown x:Name="minimum" Value="0" VerticalAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Spacing="5">
<TextBlock VerticalAlignment="Center">Progress Text Format</TextBlock>
<TextBox x:Name="stringFormat" Text="{}{0:0}%" VerticalAlignment="Center"/>
</StackPanel>
<CheckBox x:Name="showProgress" Margin="10,16,0,0" Content="Show Progress Text" />
<CheckBox x:Name="isIndeterminate" Margin="10,16,0,0" Content="Toggle Indeterminate" />
<StackPanel Orientation="Horizontal" Margin="0,16,0,0" HorizontalAlignment="Center" Spacing="16">
<StackPanel Spacing="16">
<ProgressBar IsIndeterminate="{Binding #isIndeterminate.IsChecked}" ShowProgressText="{Binding #showProgress.IsChecked}" Value="{Binding #hprogress.Value}"
Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}" ProgressTextFormat="{Binding #stringFormat.Text}"/>
</StackPanel>
<ProgressBar IsIndeterminate="{Binding #isIndeterminate.IsChecked}" ShowProgressText="{Binding #showProgress.IsChecked}" Value="{Binding #vprogress.Value}" Orientation="Vertical"
Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}" ProgressTextFormat="{Binding #stringFormat.Text}"/>
</StackPanel>
<StackPanel Margin="16">
<Slider Name="hprogress" Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}" Value="40" />
<Slider Name="vprogress" Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}" Value="60" />
</StackPanel>
<StackPanel Spacing="10">
<ProgressBar VerticalAlignment="Center" IsIndeterminate="True"
Minimum="{Binding #minimum.Value}" Maximum="{Binding #maximum.Value}"/>
<ProgressBar VerticalAlignment="Center" IsIndeterminate="True" />
<ProgressBar VerticalAlignment="Center" Value="5" Maximum="10" />
<ProgressBar VerticalAlignment="Center" Value="50" />
<ProgressBar VerticalAlignment="Center" Value="50" Minimum="25" Maximum="75" />
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>

78
samples/ControlCatalog/Pages/ScreenPage.cs

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

11
samples/ControlCatalog/Pages/ToolTipPage.xaml

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

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

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

3
samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs

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

3
samples/GpuInterop/VulkanDemo/VulkanImage.cs

@ -117,7 +117,8 @@ public unsafe class VulkanImage : IDisposable
ImportMemoryWin32HandleInfoKHR handleImport = default;
if (handleType == ExternalMemoryHandleTypeFlags.D3D11TextureBit && exportable)
{
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
var d3dDevice = vk.D3DDevice ?? throw new NotSupportedException("Vulkan D3DDevice wasn't created");
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(d3dDevice, size, Format);
using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
handleImport = new ImportMemoryWin32HandleInfoKHR

27
samples/IntegrationTestApp/App.axaml

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

19
samples/IntegrationTestApp/App.axaml.cs

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

19
samples/IntegrationTestApp/DelegateCommand.cs

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

9
samples/IntegrationTestApp/Embedding/INativeControlFactory.cs

@ -0,0 +1,9 @@
using System;
using Avalonia.Platform;
namespace IntegrationTestApp.Embedding;
internal interface INativeControlFactory
{
IPlatformHandle CreateControl(IPlatformHandle parent, Func<IPlatformHandle> createDefault);
}

16
samples/IntegrationTestApp/Embedding/MacHelper.cs

@ -0,0 +1,16 @@
using MonoMac.AppKit;
namespace IntegrationTestApp.Embedding;
internal class MacHelper
{
private static bool s_isInitialized;
public static void EnsureInitialized()
{
if (s_isInitialized)
return;
s_isInitialized = true;
NSApplication.Init();
}
}

20
samples/IntegrationTestApp/Embedding/MacOSTextBoxFactory.cs

@ -0,0 +1,20 @@
using System;
using System.Text;
using Avalonia.Platform;
using MonoMac.AppKit;
using MonoMac.WebKit;
namespace IntegrationTestApp.Embedding;
internal class MacOSTextBoxFactory : INativeControlFactory
{
public IPlatformHandle CreateControl(IPlatformHandle parent, Func<IPlatformHandle> createDefault)
{
MacHelper.EnsureInitialized();
var textView = new NSTextView();
textView.TextStorage.Append(new("Native text box"));
return new MacOSViewHandle(textView);
}
}

19
samples/IntegrationTestApp/Embedding/MacOSViewHandle.cs

@ -0,0 +1,19 @@
using System;
using Avalonia.Controls.Platform;
using MonoMac.AppKit;
namespace IntegrationTestApp.Embedding;
internal class MacOSViewHandle(NSView view) : INativeControlHostDestroyableControlHandle
{
private NSView? _view = view;
public IntPtr Handle => _view?.Handle ?? IntPtr.Zero;
public string HandleDescriptor => "NSView";
public void Destroy()
{
_view?.Dispose();
_view = null;
}
}

20
samples/IntegrationTestApp/Embedding/NativeTextBox.cs

@ -0,0 +1,20 @@
using Avalonia.Controls;
using Avalonia.Platform;
namespace IntegrationTestApp.Embedding;
internal class NativeTextBox : NativeControlHost
{
public static INativeControlFactory? Factory { get; set; }
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
return Factory?.CreateControl(parent, () => base.CreateNativeControlCore(parent))
?? base.CreateNativeControlCore(parent);
}
protected override void DestroyNativeControlCore(IPlatformHandle control)
{
base.DestroyNativeControlCore(control);
}
}

21
samples/IntegrationTestApp/Embedding/Win32TextBoxFactory.cs

@ -0,0 +1,21 @@
using System;
using System.Text;
using Avalonia.Platform;
namespace IntegrationTestApp.Embedding;
internal class Win32TextBoxFactory : INativeControlFactory
{
public IPlatformHandle CreateControl(IPlatformHandle parent, Func<IPlatformHandle> createDefault)
{
var handle = WinApi.CreateWindowEx(0, "EDIT",
@"Native text box",
(uint)(WinApi.WindowStyles.WS_CHILD | WinApi.WindowStyles.WS_VISIBLE | WinApi.WindowStyles.WS_BORDER),
0, 0, 1, 1,
parent.Handle,
IntPtr.Zero,
WinApi.GetModuleHandle(null),
IntPtr.Zero);
return new Win32WindowControlHandle(handle, "HWND");
}
}

11
samples/IntegrationTestApp/Embedding/Win32WindowControlHandle.cs

@ -0,0 +1,11 @@
using System;
using Avalonia.Controls.Platform;
using Avalonia.Platform;
namespace IntegrationTestApp.Embedding;
internal class Win32WindowControlHandle : PlatformHandle, INativeControlHostDestroyableControlHandle
{
public Win32WindowControlHandle(IntPtr handle, string descriptor) : base(handle, descriptor) { }
public void Destroy() => WinApi.DestroyWindow(Handle);
}

82
samples/IntegrationTestApp/Embedding/WinApi.cs

@ -0,0 +1,82 @@
using System;
using System.Runtime.InteropServices;
namespace IntegrationTestApp.Embedding;
internal class WinApi
{
[Flags]
public enum WindowStyles : uint
{
WS_BORDER = 0x800000,
WS_CAPTION = 0xc00000,
WS_CHILD = 0x40000000,
WS_CLIPCHILDREN = 0x2000000,
WS_CLIPSIBLINGS = 0x4000000,
WS_DISABLED = 0x8000000,
WS_DLGFRAME = 0x400000,
WS_GROUP = 0x20000,
WS_HSCROLL = 0x100000,
WS_MAXIMIZE = 0x1000000,
WS_MAXIMIZEBOX = 0x10000,
WS_MINIMIZE = 0x20000000,
WS_MINIMIZEBOX = 0x20000,
WS_OVERLAPPED = 0x0,
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
WS_POPUP = 0x80000000u,
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
WS_SYSMENU = 0x80000,
WS_TABSTOP = 0x10000,
WS_THICKFRAME = 0x40000,
WS_VISIBLE = 0x10000000,
WS_VSCROLL = 0x200000,
WS_EX_DLGMODALFRAME = 0x00000001,
WS_EX_NOPARENTNOTIFY = 0x00000004,
WS_EX_NOREDIRECTIONBITMAP = 0x00200000,
WS_EX_TOPMOST = 0x00000008,
WS_EX_ACCEPTFILES = 0x00000010,
WS_EX_TRANSPARENT = 0x00000020,
WS_EX_MDICHILD = 0x00000040,
WS_EX_TOOLWINDOW = 0x00000080,
WS_EX_WINDOWEDGE = 0x00000100,
WS_EX_CLIENTEDGE = 0x00000200,
WS_EX_CONTEXTHELP = 0x00000400,
WS_EX_RIGHT = 0x00001000,
WS_EX_LEFT = 0x00000000,
WS_EX_RTLREADING = 0x00002000,
WS_EX_LTRREADING = 0x00000000,
WS_EX_LEFTSCROLLBAR = 0x00004000,
WS_EX_RIGHTSCROLLBAR = 0x00000000,
WS_EX_CONTROLPARENT = 0x00010000,
WS_EX_STATICEDGE = 0x00020000,
WS_EX_APPWINDOW = 0x00040000,
WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
WS_EX_LAYERED = 0x00080000,
WS_EX_NOINHERITLAYOUT = 0x00100000,
WS_EX_LAYOUTRTL = 0x00400000,
WS_EX_COMPOSITED = 0x02000000,
WS_EX_NOACTIVATE = 0x08000000
}
[DllImport("user32.dll", SetLastError = true)]
public static extern bool DestroyWindow(IntPtr hwnd);
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string? lpModuleName);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr CreateWindowEx(
int dwExStyle,
string lpClassName,
string lpWindowName,
uint dwStyle,
int x,
int y,
int nWidth,
int nHeight,
IntPtr hWndParent,
IntPtr hMenu,
IntPtr hInstance,
IntPtr lpParam);
}

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

Loading…
Cancel
Save