diff --git a/.editorconfig b/.editorconfig
index c7a381b730..25e0135725 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -137,7 +137,7 @@ space_within_single_line_array_initializer_braces = true
csharp_wrap_before_ternary_opsigns = false
# Xaml files
-[*.xaml]
+[*.{xaml,axaml}]
indent_size = 2
# Xml project files
diff --git a/.gitignore b/.gitignore
index 9b15011929..44fe5e4ba4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -192,13 +192,12 @@ dirs.sln
##################
-# XCode
+# Xcode
##################
Index/
Logs/
ModuleCache.noindex/
Build/Intermediates.noindex/
-info.plist
build-intermediate
obj-Direct2D1/
obj-Skia/
diff --git a/.ncrunch/Avalonia.IntegrationTests.Appium.v3.ncrunchproject b/.ncrunch/Avalonia.IntegrationTests.Appium.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.IntegrationTests.Appium.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject b/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/Avalonia.IntegrationTests.Win32.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/.ncrunch/IntegrationTestApp.v3.ncrunchproject b/.ncrunch/IntegrationTestApp.v3.ncrunchproject
new file mode 100644
index 0000000000..319cd523ce
--- /dev/null
+++ b/.ncrunch/IntegrationTestApp.v3.ncrunchproject
@@ -0,0 +1,5 @@
+
+
+ True
+
+
\ No newline at end of file
diff --git a/Avalonia.sln b/Avalonia.sln
index 0354e20d4f..a792774d94 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -77,7 +77,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Android", "Android", "{7CF9
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Android", "src\Android\Avalonia.Android\Avalonia.Android.csproj", "{7B92AF71-6287-4693-9DCB-BD5B6E927E23}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.AndroidTestApplication", "src\Android\Avalonia.AndroidTestApplication\Avalonia.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.AndroidTestApplication", "src\Android\Avalonia.AndroidTestApplication\Avalonia.AndroidTestApplication.csproj", "{FF69B927-C545-49AE-8E16-3D14D621AA12}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "iOS", "iOS", "{0CB0B92E-6CFF-4240-80A5-CCAFE75D91E1}"
EndProject
@@ -95,8 +95,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog", "samples\C
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Desktop", "samples\ControlCatalog.Desktop\ControlCatalog.Desktop.csproj", "{2B888490-D14A-4BCA-AB4B-48676FA93C9B}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{52F55355-D120-42AC-8116-8410A7D602FA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
@@ -107,7 +105,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderDemo", "samples\RenderDemo\RenderDemo.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
EndProject
@@ -115,14 +113,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
- build\AndroidWorkarounds.props = build\AndroidWorkarounds.props
build\ApiDiff.props = build\ApiDiff.props
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
build\CoreLibraries.props = build\CoreLibraries.props
build\EmbedXaml.props = build\EmbedXaml.props
build\HarfBuzzSharp.props = build\HarfBuzzSharp.props
- build\iOSWorkarounds.props = build\iOSWorkarounds.props
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props
@@ -178,8 +174,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.OpenGL", "src\Aval
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Native", "src\Avalonia.Native\Avalonia.Native.csproj", "{12A91A62-C064-42CA-9A8C-A1272F354388}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesktopRuntime", "src\Avalonia.DesktopRuntime\Avalonia.DesktopRuntime.csproj", "{878FEFE0-CD14-41CB-90B0-DBCB163E8F15}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Packages", "Packages", "{E870DCD7-F46A-498D-83FC-D0FD13E0A11C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia", "packages\Avalonia\Avalonia.csproj", "{D49233F8-F29C-47DD-9975-C4C9E4502720}"
@@ -222,6 +216,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MicroCom", "src\Av
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MiniMvvm", "samples\MiniMvvm\MiniMvvm.csproj", "{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTestApp", "samples\IntegrationTestApp\IntegrationTestApp.csproj", "{676D6BFD-029D-4E43-BFC7-3892265CE251}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.IntegrationTests.Appium", "tests\Avalonia.IntegrationTests.Appium\Avalonia.IntegrationTests.Appium.csproj", "{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}"
+EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Blazor", "src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj", "{25831348-EB2A-483E-9576-E8F6528674A5}"
@@ -234,6 +232,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\S
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.PlatformSupport", "src\Avalonia.PlatformSupport\Avalonia.PlatformSupport.csproj", "{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.PlatformSupport.UnitTests", "tests\Avalonia.PlatformSupport.UnitTests\Avalonia.PlatformSupport.UnitTests.csproj", "{CE910927-CE5A-456F-BC92-E4C757354A5C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Ad-Hoc|Any CPU = Ad-Hoc|Any CPU
@@ -1096,26 +1098,6 @@ Global
{2B888490-D14A-4BCA-AB4B-48676FA93C9B}.Release|iPhone.Build.0 = Release|Any CPU
{2B888490-D14A-4BCA-AB4B-48676FA93C9B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{2B888490-D14A-4BCA-AB4B-48676FA93C9B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Ad-Hoc|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Ad-Hoc|iPhoneSimulator.Build.0 = Ad-Hoc|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.AppStore|Any CPU.ActiveCfg = AppStore|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.AppStore|iPhone.Build.0 = AppStore|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.AppStore|iPhoneSimulator.ActiveCfg = AppStore|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.AppStore|iPhoneSimulator.Build.0 = AppStore|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Debug|Any CPU.ActiveCfg = Debug|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Debug|iPhone.ActiveCfg = Debug|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Debug|iPhone.Build.0 = Debug|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Release|Any CPU.ActiveCfg = Release|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Release|iPhone.ActiveCfg = Release|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Release|iPhone.Build.0 = Release|iPhone
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{52F55355-D120-42AC-8116-8410A7D602FA}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{52F55355-D120-42AC-8116-8410A7D602FA}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{52F55355-D120-42AC-8116-8410A7D602FA}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@@ -1560,30 +1542,6 @@ Global
{12A91A62-C064-42CA-9A8C-A1272F354388}.Release|iPhone.Build.0 = Release|Any CPU
{12A91A62-C064-42CA-9A8C-A1272F354388}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{12A91A62-C064-42CA-9A8C-A1272F354388}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|Any CPU.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|iPhone.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|iPhone.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|iPhone.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|Any CPU.Build.0 = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|iPhone.ActiveCfg = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|iPhone.Build.0 = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
- {878FEFE0-CD14-41CB-90B0-DBCB163E8F15}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{D49233F8-F29C-47DD-9975-C4C9E4502720}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{D49233F8-F29C-47DD-9975-C4C9E4502720}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{D49233F8-F29C-47DD-9975-C4C9E4502720}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -2064,6 +2022,54 @@ Global
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhone.Build.0 = Release|Any CPU
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|Any CPU.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhone.Build.0 = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {676D6BFD-029D-4E43-BFC7-3892265CE251}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhone.Build.0 = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@@ -2184,6 +2190,54 @@ Global
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhone.Build.0 = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E8A597F0-2AB5-4BDA-A235-41162DAF53CF}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|iPhone.Build.0 = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|iPhone.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|iPhone.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhone.ActiveCfg = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhone.Build.0 = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+ {CE910927-CE5A-456F-BC92-E4C757354A5C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2213,7 +2267,6 @@ Global
{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{D0A739B9-3C68-4BA6-A328-41606954B6BD} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{2B888490-D14A-4BCA-AB4B-48676FA93C9B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
- {57E0455D-D565-44BB-B069-EE1AA20F8337} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{52F55355-D120-42AC-8116-8410A7D602FA} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{F1381F98-4D24-409A-A6C5-1C5B1E08BB08} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{FBCAF3D0-2808-4934-8E96-3F607594517B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@@ -2222,6 +2275,7 @@ Global
{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} = {A689DEF5-D50F-4975-8B72-124C9EB54066}
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{638580B0-7910-40EF-B674-DCB34DA308CD} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
@@ -2241,10 +2295,14 @@ Global
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{BC594FD5-4AF2-409E-A1E6-04123F54D7C5} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{26A98DA1-D89D-4A95-8152-349F404DA2E2} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+ {CE910927-CE5A-456F-BC92-E4C757354A5C} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}
diff --git a/Directory.Build.props b/Directory.Build.props
index c6610695c4..835decc672 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -4,5 +4,6 @@
$(MSBuildThisFileDirectory)\src\tools\Avalonia.Designer.HostApp\bin\$(Configuration)\netcoreapp2.0\Avalonia.Designer.HostApp.dll
false
+ false
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 40669f4f53..79456b117b 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,6 +1,3 @@
-variables:
- MSBuildEnableWorkloadResolver: 'false'
-
jobs:
- job: GetPRNumber
@@ -41,7 +38,7 @@ jobs:
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.100'
inputs:
- version: 6.0.100
+ version: 6.0.200
- task: CmdLine@2
displayName: 'Run Build'
@@ -72,7 +69,7 @@ jobs:
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.100'
inputs:
- version: 6.0.100
+ version: 6.0.200
- task: CmdLine@2
displayName: 'Install Mono 5.18'
@@ -144,7 +141,13 @@ jobs:
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.100'
inputs:
- version: 6.0.100
+ version: 6.0.200
+
+ - task: CmdLine@2
+ displayName: 'Install Workloads'
+ inputs:
+ script: |
+ dotnet workload install --no-cache --disable-parallel android ios --skip-manifest-update --source "https://api.nuget.org/v3/index.json"
- task: CmdLine@2
displayName: 'Install Nuke'
diff --git a/build/AndroidWorkarounds.props b/build/AndroidWorkarounds.props
deleted file mode 100644
index de86acc6de..0000000000
--- a/build/AndroidWorkarounds.props
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
diff --git a/build/CoreLibraries.props b/build/CoreLibraries.props
index 3fccad2641..6bf69603c0 100644
--- a/build/CoreLibraries.props
+++ b/build/CoreLibraries.props
@@ -16,7 +16,6 @@
-
diff --git a/build/HarfBuzzSharp.props b/build/HarfBuzzSharp.props
index 1d84d5289a..6dd6cccb53 100644
--- a/build/HarfBuzzSharp.props
+++ b/build/HarfBuzzSharp.props
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index 7f24ef35bc..3d9548ab9d 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -11,7 +11,7 @@
latest
MIT
Icon.png
- Avalonia is a WPF/UWP-inspired cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows (.NET Framework, .NET Core), Linux (via Xorg), MacOS and with experimental support for Android and iOS.
+ Avalonia is a cross-platform UI framework for .NET providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS and with experimental support for Android, iOS and WebAssembly.
avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin
https://github.com/AvaloniaUI/Avalonia/releases
git
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index bb370256f9..60bebaad40 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,7 +1,7 @@
-
-
-
+
+
+
diff --git a/build/XUnit.props b/build/XUnit.props
index a75e1bac86..17ead91aa3 100644
--- a/build/XUnit.props
+++ b/build/XUnit.props
@@ -1,14 +1,14 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/dirs.proj b/dirs.proj
index 594f2c22d3..396e0c915c 100644
--- a/dirs.proj
+++ b/dirs.proj
@@ -1,5 +1,7 @@
+
+
@@ -8,21 +10,21 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/global.json b/global.json
index b160e4561d..30265268dc 100644
--- a/global.json
+++ b/global.json
@@ -1,9 +1,11 @@
{
"sdk": {
- "version": "6.0.100"
+ "version": "6.0.200",
+ "rollForward": "latestFeature"
},
"msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43",
+ "Xamarin.Legacy.Sdk": "0.1.2-alpha6",
"MSBuild.Sdk.Extras": "3.0.22",
"AggregatePackage.NuGet.Sdk" : "0.1.12"
}
diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
index 85fcf20034..7571d51c9f 100644
--- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
+++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
@@ -30,6 +30,8 @@
AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; };
AB661C202148286E00291242 /* window.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB661C1F2148286E00291242 /* window.mm */; };
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 */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -64,6 +66,8 @@
AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; };
AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = ""; };
+ BC11A5BC2608D58F0017BAD0 /* automation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = automation.h; sourceTree = ""; };
+ BC11A5BD2608D58F0017BAD0 /* automation.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = automation.mm; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -97,6 +101,8 @@
AB7A61E62147C814003C5833 = {
isa = PBXGroup;
children = (
+ BC11A5BC2608D58F0017BAD0 /* automation.h */,
+ BC11A5BD2608D58F0017BAD0 /* automation.mm */,
1A1852DB23E05814008F0DED /* deadlock.mm */,
1A002B9D232135EE00021753 /* app.mm */,
37DDA9B121933371002E132B /* AvnString.h */,
@@ -143,6 +149,7 @@
buildActionMask = 2147483647;
files = (
37155CE4233C00EB0034DCE9 /* menu.h in Headers */,
+ BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -213,6 +220,7 @@
AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */,
1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */,
+ BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */,
37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
520624B322973F4100C4DCEF /* menu.mm in Sources */,
37A517B32159597E00FBA241 /* Screens.mm in Sources */,
diff --git a/native/Avalonia.Native/src/OSX/AvnString.h b/native/Avalonia.Native/src/OSX/AvnString.h
index 3ce83d370a..3b750b11db 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.h
+++ b/native/Avalonia.Native/src/OSX/AvnString.h
@@ -14,4 +14,5 @@ extern IAvnStringArray* CreateAvnStringArray(NSArray* array);
extern IAvnStringArray* CreateAvnStringArray(NSArray* array);
extern IAvnStringArray* CreateAvnStringArray(NSString* string);
extern IAvnString* CreateByteArray(void* data, int len);
+extern NSString* GetNSStringAndRelease(IAvnString* s);
#endif /* AvnString_h */
diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm
index cd0e2cdf94..5e50068c51 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.mm
+++ b/native/Avalonia.Native/src/OSX/AvnString.mm
@@ -153,3 +153,19 @@ IAvnString* CreateByteArray(void* data, int len)
{
return new AvnStringImpl(data, len);
}
+
+NSString* GetNSStringAndRelease(IAvnString* s)
+{
+ NSString* result = nil;
+
+ if (s != nullptr)
+ {
+ char* p;
+ if (s->Pointer((void**)&p) == S_OK && p != nullptr)
+ result = [NSString stringWithUTF8String:p];
+
+ s->Release();
+ }
+
+ return result;
+}
diff --git a/native/Avalonia.Native/src/OSX/automation.h b/native/Avalonia.Native/src/OSX/automation.h
new file mode 100644
index 0000000000..4a12a965fd
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/automation.h
@@ -0,0 +1,12 @@
+#import
+#include "window.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+class IAvnAutomationPeer;
+
+@interface AvnAccessibilityElement : NSAccessibilityElement
++ (AvnAccessibilityElement *) acquire:(IAvnAutomationPeer *) peer;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/native/Avalonia.Native/src/OSX/automation.mm b/native/Avalonia.Native/src/OSX/automation.mm
new file mode 100644
index 0000000000..7d697140c2
--- /dev/null
+++ b/native/Avalonia.Native/src/OSX/automation.mm
@@ -0,0 +1,496 @@
+#include "common.h"
+#include "automation.h"
+#include "AvnString.h"
+#include "window.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
+{
+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;
+};
+
+@implementation AvnAccessibilityElement
+{
+ IAvnAutomationPeer* _peer;
+ AutomationNode* _node;
+ NSMutableArray* _children;
+}
+
++ (AvnAccessibilityElement *)acquire:(IAvnAutomationPeer *)peer
+{
+ if (peer == nullptr)
+ return nil;
+
+ auto instance = peer->GetNode();
+
+ if (instance != nullptr)
+ return dynamic_cast(instance)->GetOwner();
+
+ if (peer->IsRootProvider())
+ {
+ auto window = peer->RootProvider_GetWindow();
+ auto holder = dynamic_cast(window);
+ auto view = holder->GetNSView();
+ return [[AvnRootAccessibilityElement alloc] initWithPeer:peer owner:view];
+ }
+ else
+ {
+ return [[AvnAccessibilityElement alloc] initWithPeer:peer];
+ }
+}
+
+- (AvnAccessibilityElement *)initWithPeer:(IAvnAutomationPeer *)peer
+{
+ self = [super init];
+ _peer = peer;
+ _node = new AutomationNode(self);
+ _peer->SetNode(_node);
+ return self;
+}
+
+- (void)dealloc
+{
+ if (_node)
+ delete _node;
+ _node = nullptr;
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"%@ '%@' (%p)",
+ GetNSStringAndRelease(_peer->GetClassName()),
+ GetNSStringAndRelease(_peer->GetName()),
+ _peer];
+}
+
+- (IAvnAutomationPeer *)peer
+{
+ return _peer;
+}
+
+- (BOOL)isAccessibilityElement
+{
+ return _peer->IsControlElement();
+}
+
+- (NSAccessibilityRole)accessibilityRole
+{
+ auto controlType = _peer->GetAutomationControlType();
+
+ switch (controlType) {
+ case AutomationButton: return NSAccessibilityButtonRole;
+ case AutomationCalendar: return NSAccessibilityGridRole;
+ case AutomationCheckBox: return NSAccessibilityCheckBoxRole;
+ case AutomationComboBox: return NSAccessibilityPopUpButtonRole;
+ case AutomationComboBoxItem: return NSAccessibilityMenuItemRole;
+ case AutomationEdit: return NSAccessibilityTextFieldRole;
+ case AutomationHyperlink: return NSAccessibilityLinkRole;
+ case AutomationImage: return NSAccessibilityImageRole;
+ case AutomationListItem: return NSAccessibilityRowRole;
+ case AutomationList: return NSAccessibilityTableRole;
+ case AutomationMenu: return NSAccessibilityMenuBarRole;
+ case AutomationMenuBar: return NSAccessibilityMenuBarRole;
+ case AutomationMenuItem: return NSAccessibilityMenuItemRole;
+ case AutomationProgressBar: return NSAccessibilityProgressIndicatorRole;
+ case AutomationRadioButton: return NSAccessibilityRadioButtonRole;
+ case AutomationScrollBar: return NSAccessibilityScrollBarRole;
+ case AutomationSlider: return NSAccessibilitySliderRole;
+ case AutomationSpinner: return NSAccessibilityIncrementorRole;
+ case AutomationStatusBar: return NSAccessibilityTableRole;
+ case AutomationTab: return NSAccessibilityTabGroupRole;
+ case AutomationTabItem: return NSAccessibilityRadioButtonRole;
+ case AutomationText: return NSAccessibilityStaticTextRole;
+ case AutomationToolBar: return NSAccessibilityToolbarRole;
+ case AutomationToolTip: return NSAccessibilityPopoverRole;
+ case AutomationTree: return NSAccessibilityOutlineRole;
+ case AutomationTreeItem: return NSAccessibilityCellRole;
+ case AutomationCustom: return NSAccessibilityUnknownRole;
+ case AutomationGroup: return NSAccessibilityGroupRole;
+ case AutomationThumb: return NSAccessibilityHandleRole;
+ case AutomationDataGrid: return NSAccessibilityGridRole;
+ case AutomationDataItem: return NSAccessibilityCellRole;
+ case AutomationDocument: return NSAccessibilityStaticTextRole;
+ case AutomationSplitButton: return NSAccessibilityPopUpButtonRole;
+ case AutomationWindow: return NSAccessibilityWindowRole;
+ case AutomationPane: return NSAccessibilityGroupRole;
+ case AutomationHeader: return NSAccessibilityGroupRole;
+ case AutomationHeaderItem: return NSAccessibilityButtonRole;
+ case AutomationTable: return NSAccessibilityTableRole;
+ case AutomationTitleBar: return NSAccessibilityGroupRole;
+ // Treat unknown roles as generic group container items. Returning
+ // NSAccessibilityUnknownRole is also possible but makes the screen
+ // reader focus on the item instead of passing focus to child items.
+ default: return NSAccessibilityGroupRole;
+ }
+}
+
+- (NSString *)accessibilityIdentifier
+{
+ return GetNSStringAndRelease(_peer->GetAutomationId());
+}
+
+- (NSString *)accessibilityTitle
+{
+ // StaticText exposes its text via the value property.
+ if (_peer->GetAutomationControlType() != AutomationText)
+ {
+ return GetNSStringAndRelease(_peer->GetName());
+ }
+
+ return [super accessibilityTitle];
+}
+
+- (id)accessibilityValue
+{
+ if (_peer->IsRangeValueProvider())
+ {
+ return [NSNumber numberWithDouble:_peer->RangeValueProvider_GetValue()];
+ }
+ else if (_peer->IsToggleProvider())
+ {
+ switch (_peer->ToggleProvider_GetToggleState()) {
+ case 0: return [NSNumber numberWithBool:NO];
+ case 1: return [NSNumber numberWithBool:YES];
+ default: return [NSNumber numberWithInt:2];
+ }
+ }
+ else if (_peer->IsValueProvider())
+ {
+ return GetNSStringAndRelease(_peer->ValueProvider_GetValue());
+ }
+ else if (_peer->GetAutomationControlType() == AutomationText)
+ {
+ return GetNSStringAndRelease(_peer->GetName());
+ }
+
+ return [super accessibilityValue];
+}
+
+- (id)accessibilityMinValue
+{
+ if (_peer->IsRangeValueProvider())
+ {
+ return [NSNumber numberWithDouble:_peer->RangeValueProvider_GetMinimum()];
+ }
+
+ return [super accessibilityMinValue];
+}
+
+- (id)accessibilityMaxValue
+{
+ if (_peer->IsRangeValueProvider())
+ {
+ return [NSNumber numberWithDouble:_peer->RangeValueProvider_GetMaximum()];
+ }
+
+ return [super accessibilityMaxValue];
+}
+
+- (BOOL)isAccessibilityEnabled
+{
+ return _peer->IsEnabled();
+}
+
+- (BOOL)isAccessibilityFocused
+{
+ return _peer->HasKeyboardFocus();
+}
+
+- (NSArray *)accessibilityChildren
+{
+ if (_children == nullptr && _peer != nullptr)
+ [self recalculateChildren];
+ return _children;
+}
+
+- (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;
+}
+
+- (id)accessibilityParent
+{
+ auto parentPeer = _peer->GetParent();
+ return parentPeer ? [AvnAccessibilityElement acquire:parentPeer] : [NSApplication sharedApplication];
+}
+
+- (id)accessibilityTopLevelUIElement
+{
+ auto rootPeer = _peer->GetRootPeer();
+ return [AvnAccessibilityElement acquire:rootPeer];
+}
+
+- (id)accessibilityWindow
+{
+ id topLevel = [self accessibilityTopLevelUIElement];
+ return [topLevel isKindOfClass:[NSWindow class]] ? topLevel : nil;
+}
+
+- (BOOL)isAccessibilityExpanded
+{
+ if (!_peer->IsExpandCollapseProvider())
+ return NO;
+ return _peer->ExpandCollapseProvider_GetIsExpanded();
+}
+
+- (void)setAccessibilityExpanded:(BOOL)accessibilityExpanded
+{
+ if (!_peer->IsExpandCollapseProvider())
+ return;
+ if (accessibilityExpanded)
+ _peer->ExpandCollapseProvider_Expand();
+ else
+ _peer->ExpandCollapseProvider_Collapse();
+}
+
+- (BOOL)accessibilityPerformPress
+{
+ if (_peer->IsInvokeProvider())
+ {
+ _peer->InvokeProvider_Invoke();
+ }
+ else if (_peer->IsExpandCollapseProvider())
+ {
+ _peer->ExpandCollapseProvider_Expand();
+ }
+ else if (_peer->IsToggleProvider())
+ {
+ _peer->ToggleProvider_Toggle();
+ }
+ return YES;
+}
+
+- (BOOL)accessibilityPerformIncrement
+{
+ if (!_peer->IsRangeValueProvider())
+ return NO;
+ auto value = _peer->RangeValueProvider_GetValue();
+ value += _peer->RangeValueProvider_GetSmallChange();
+ _peer->RangeValueProvider_SetValue(value);
+ return YES;
+}
+
+- (BOOL)accessibilityPerformDecrement
+{
+ if (!_peer->IsRangeValueProvider())
+ return NO;
+ auto value = _peer->RangeValueProvider_GetValue();
+ value -= _peer->RangeValueProvider_GetSmallChange();
+ _peer->RangeValueProvider_SetValue(value);
+ return YES;
+}
+
+- (BOOL)accessibilityPerformShowMenu
+{
+ if (!_peer->IsExpandCollapseProvider())
+ return NO;
+ _peer->ExpandCollapseProvider_Expand();
+ return YES;
+}
+
+- (BOOL)isAccessibilitySelected
+{
+ if (_peer->IsSelectionItemProvider())
+ return _peer->SelectionItemProvider_IsSelected();
+ return NO;
+}
+
+- (BOOL)isAccessibilitySelectorAllowed:(SEL)selector
+{
+ if (selector == @selector(accessibilityPerformShowMenu))
+ {
+ return _peer->IsExpandCollapseProvider() && _peer->ExpandCollapseProvider_GetShowsMenu();
+ }
+ else if (selector == @selector(isAccessibilityExpanded))
+ {
+ return _peer->IsExpandCollapseProvider();
+ }
+ else if (selector == @selector(accessibilityPerformPress))
+ {
+ return _peer->IsInvokeProvider() || _peer->IsExpandCollapseProvider() || _peer->IsToggleProvider();
+ }
+ else if (selector == @selector(accessibilityPerformIncrement) ||
+ selector == @selector(accessibilityPerformDecrement) ||
+ selector == @selector(accessibilityMinValue) ||
+ selector == @selector(accessibilityMaxValue))
+ {
+ return _peer->IsRangeValueProvider();
+ }
+
+ return [super isAccessibilitySelectorAllowed:selector];
+}
+
+- (void)raiseChildrenChanged
+{
+ auto changed = _children ? [NSMutableSet setWithArray:_children] : [NSMutableSet set];
+
+ [self recalculateChildren];
+
+ if (_children)
+ [changed addObjectsFromArray:_children];
+
+ NSAccessibilityPostNotificationWithUserInfo(
+ self,
+ NSAccessibilityLayoutChangedNotification,
+ @{ NSAccessibilityUIElementsKey: [changed allObjects]});
+}
+
+- (void)raisePropertyChanged
+{
+}
+
+- (void)setAccessibilityFocused:(BOOL)accessibilityFocused
+{
+ if (accessibilityFocused)
+ _peer->SetFocus();
+}
+
+- (void)recalculateChildren
+{
+ auto childPeers = _peer->GetChildren();
+ auto childCount = childPeers != nullptr ? childPeers->GetCount() : 0;
+
+ if (childCount > 0)
+ {
+ _children = [[NSMutableArray alloc] initWithCapacity:childCount];
+
+ for (int i = 0; i < childCount; ++i)
+ {
+ IAvnAutomationPeer* child;
+
+ if (childPeers->Get(i, &child) == S_OK)
+ {
+ auto element = [AvnAccessibilityElement acquire:child];
+ [_children addObject:element];
+ }
+ }
+ }
+ else
+ {
+ _children = nil;
+ }
+}
+
+@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
diff --git a/native/Avalonia.Native/src/OSX/common.h b/native/Avalonia.Native/src/OSX/common.h
index 126c9aa87b..9186d9e15a 100644
--- a/native/Avalonia.Native/src/OSX/common.h
+++ b/native/Avalonia.Native/src/OSX/common.h
@@ -35,6 +35,7 @@ extern NSMenuItem* GetAppMenuItem ();
extern void InitializeAvnApp(IAvnApplicationEvents* events);
extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;
extern NSPoint ToNSPoint (AvnPoint p);
+extern NSRect ToNSRect (AvnRect r);
extern AvnPoint ToAvnPoint (NSPoint p);
extern AvnPoint ConvertPointY (AvnPoint p);
extern CGFloat PrimaryDisplayHeight();
diff --git a/native/Avalonia.Native/src/OSX/controlhost.mm b/native/Avalonia.Native/src/OSX/controlhost.mm
index f8e9a3b6d1..5683a5a975 100644
--- a/native/Avalonia.Native/src/OSX/controlhost.mm
+++ b/native/Avalonia.Native/src/OSX/controlhost.mm
@@ -36,7 +36,10 @@ public:
virtual void DestroyDefaultChild(void* child) override
{
// ARC will release the object for us
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wunused-value"
(__bridge_transfer NSView*) child;
+ #pragma clang diagnostic pop
}
};
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index 69f2995847..ea79c494d7 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -1,6 +1,7 @@
//This file will contain actual IID structures
#define COM_GUIDS_MATERIALIZE
#include "common.h"
+#include "window.h"
static NSString* s_appTitle = @"Avalonia";
@@ -335,7 +336,7 @@ public:
return S_OK;
}
}
-
+
virtual HRESULT SetAppMenu (IAvnMenu* appMenu) override
{
START_COM_CALL;
@@ -400,6 +401,15 @@ NSPoint ToNSPoint (AvnPoint p)
return result;
}
+NSRect ToNSRect (AvnRect r)
+{
+ return NSRect
+ {
+ NSPoint { r.X, r.Y },
+ NSSize { r.Width, r.Height }
+ };
+}
+
AvnPoint ToAvnPoint (NSPoint p)
{
AvnPoint result;
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index 1dc091a48d..1369ceaea0 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -43,6 +43,7 @@ class WindowBaseImpl;
struct INSWindowHolder
{
virtual AvnWindow* _Nonnull GetNSWindow () = 0;
+ virtual AvnView* _Nonnull GetNSView () = 0;
};
struct IWindowStateChanged
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 40180274e1..620b750a40 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -5,14 +5,22 @@
#include "menu.h"
#include
#include "rendertarget.h"
+#include "AvnString.h"
+#include "automation.h"
-class WindowBaseImpl : public virtual ComSingleObject, public INSWindowHolder
+class WindowBaseImpl : public virtual ComObject,
+ public virtual IAvnWindowBase,
+ public INSWindowHolder
{
private:
NSCursor* cursor;
public:
FORWARD_IUNKNOWN()
+ BEGIN_INTERFACE_MAP()
+ INTERFACE_MAP_ENTRY(IAvnWindowBase, IID_IAvnWindowBase)
+ END_INTERFACE_MAP()
+
virtual ~WindowBaseImpl()
{
View = NULL;
@@ -115,7 +123,12 @@ public:
{
return Window;
}
-
+
+ virtual AvnView* GetNSView() override
+ {
+ return View;
+ }
+
virtual HRESULT Show(bool activate, bool isDialog) override
{
START_COM_CALL;
@@ -444,7 +457,8 @@ public:
}
point = ConvertPointY(point);
- auto viewPoint = [Window convertScreenToBase:ToNSPoint(point)];
+ NSRect convertRect = [Window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
+ auto viewPoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
*ret = [View translateLocalPoint:ToAvnPoint(viewPoint)];
@@ -464,7 +478,8 @@ public:
}
auto cocoaViewPoint = ToNSPoint([View translateLocalPoint:point]);
- auto cocoaScreenPoint = [Window convertBaseToScreen:cocoaViewPoint];
+ 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;
@@ -560,7 +575,8 @@ public:
if(!((nseventType >= NSEventTypeLeftMouseDown && nseventType <= NSEventTypeMouseExited)
|| (nseventType >= NSEventTypeOtherMouseDown && nseventType <= NSEventTypeOtherMouseDragged)))
{
- auto nspoint = [Window convertBaseToScreen: ToNSPoint(point)];
+ NSRect convertRect = [Window convertRectToScreen:NSMakeRect(point.X, point.Y, 0.0, 0.0)];
+ auto nspoint = NSMakePoint(convertRect.origin.x, convertRect.origin.y);
CGPoint cgpoint = NSPointToCGPoint(nspoint);
auto cgevent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, cgpoint, kCGMouseButtonLeft);
nsevent = [NSEvent eventWithCGEvent: cgevent];
@@ -722,7 +738,7 @@ private:
return E_INVALIDARG;
// 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
+ // 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);
@@ -1396,6 +1412,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
AvnPixelSize _lastPixelSize;
NSObject* _renderTarget;
AvnPlatformResizeReason _resizeReason;
+ AvnAccessibilityElement* _accessibilityChild;
}
- (void)onClosed
@@ -2050,6 +2067,37 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_resizeReason = reason;
}
+- (AvnAccessibilityElement *) accessibilityChild
+{
+ if (_accessibilityChild == nil)
+ {
+ auto peer = _parent->BaseEvents->GetAutomationPeer();
+
+ if (peer == nil)
+ return nil;
+
+ _accessibilityChild = [AvnAccessibilityElement acquire:peer];
+ }
+
+ return _accessibilityChild;
+}
+
+- (NSArray *)accessibilityChildren
+{
+ auto child = [self accessibilityChild];
+ return NSAccessibilityUnignoredChildrenForOnlyChild(child);
+}
+
+- (id)accessibilityHitTest:(NSPoint)point
+{
+ return [[self accessibilityChild] accessibilityHitTest:point];
+}
+
+- (id)accessibilityFocusedUIElement
+{
+ return [[self accessibilityChild] accessibilityFocusedUIElement];
+}
+
@end
@@ -2062,6 +2110,8 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
bool _isExtended;
AvnMenu* _menu;
double _lastScaling;
+ IAvnAutomationPeer* _automationPeer;
+ NSMutableArray* _automationChildren;
}
-(void) setIsExtended:(bool)value;
@@ -2465,6 +2515,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
}
}
+
@end
class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index f0b894b596..72d90abbf3 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -87,7 +87,8 @@ partial class Build : NukeBuild
Console.WriteLine(preamble);
Process.Start(new ProcessStartInfo(command, args) {UseShellExecute = false}).WaitForExit();
}
- ExecWait("dotnet version:", "dotnet", "--version");
+ ExecWait("dotnet version:", "dotnet", "--info");
+ ExecWait("dotnet workloads:", "dotnet", "workload list");
}
IReadOnlyCollection
diff --git a/readme.md b/readme.md
index 96c7937559..1cdaf3b8f8 100644
--- a/readme.md
+++ b/readme.md
@@ -1,11 +1,11 @@
[](https://t.me/Avalonia)
[](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) []( https://aka.ms/dotnet-discord) [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [](#backers) [](#sponsors) 
-[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) [](https://www.myget.org/gallery/avalonia-ci) 
+[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) 
## 📖 About
-Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, MacOs. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM.
+Avalonia is a cross-platform UI framework for dotnet, providing a flexible styling system and supporting a wide range of Operating Systems such as Windows, Linux, macOS. Avalonia is mature and production ready. We also have in beta release support for iOS, Android and in early stages support for browser via WASM.

diff --git a/samples/ControlCatalog.Android/Assets/AboutAssets.txt b/samples/ControlCatalog.Android/Assets/AboutAssets.txt
deleted file mode 100644
index a9b0638eb1..0000000000
--- a/samples/ControlCatalog.Android/Assets/AboutAssets.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Any raw assets you want to be deployed with your application can be placed in
-this directory (and child directories) and given a Build Action of "AndroidAsset".
-
-These files will be deployed with your package and will be accessible using Android's
-AssetManager, like this:
-
-public class ReadAsset : Activity
-{
- protected override void OnCreate (Bundle bundle)
- {
- base.OnCreate (bundle);
-
- InputStream input = Assets.Open ("my_asset.txt");
- }
-}
-
-Additionally, some Android functions will automatically load asset files:
-
-Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
diff --git a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
index 617b6b6ab0..9777bb46c3 100644
--- a/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
+++ b/samples/ControlCatalog.Android/ControlCatalog.Android.csproj
@@ -1,165 +1,47 @@
-
-
+
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {29132311-1848-4FD6-AE0C-4FF841151BD3}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Library
- Properties
- ControlCatalog.Android
- ControlCatalog.Android
- 512
- true
- Resources\Resource.Designer.cs
- Off
- False
- v11.0
- Properties\AndroidManifest.xml
+ net6.0-android
+ 21
+ Exe
+ enable
+ com.Avalonia.ControlCatalog
+ 1
+ 1.0
+ apk
+ true
-
- True
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- True
- None
- True
- False
- False
- armeabi-v7a;x86;x86_64
- Xamarin
- False
- False
- False
- False
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
- False
- Full
- True
- False
- False
- armeabi-v7a,x86;x86_64
- Xamarin
- False
- False
- False
- False
- False
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
Resources\drawable\Icon.png
+
+
+ True
+ True
+ True
+ True
+
+
+
+ False
+ False
+
+
+
+ True
+
+
-
+
+
+
-
- {7B92AF71-6287-4693-9DCB-BD5B6E927E23}
- Avalonia.Android
-
-
- {d211e587-d8bc-45b9-95a4-f297c8fa5200}
- Avalonia.Animation
-
-
- {b09b78d8-9b26-48b0-9149-d64a2f120f3f}
- Avalonia.Base
-
-
- {d2221c82-4a25-4583-9b43-d791e3f6820c}
- Avalonia.Controls
-
-
- {7062ae20-5dcc-4442-9645-8195bdece63e}
- Avalonia.Diagnostics
-
-
- {62024b2d-53eb-4638-b26b-85eeaa54866e}
- Avalonia.Input
-
-
- {6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}
- Avalonia.Interactivity
-
-
- {42472427-4774-4c81-8aff-9f27b8e31721}
- Avalonia.Layout
-
-
- {c42d2fc1-a531-4ed4-84b9-89aec7c962fc}
- Avalonia.Themes.Fluent
-
-
- {eb582467-6abb-43a1-b052-e981ba910e3a}
- Avalonia.Visuals
-
-
- {f1baa01a-f176-4c6a-b39d-5b40bb1b148f}
- Avalonia.Styling
-
-
- {3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}
- Avalonia.Themes.Default
-
-
- {3e53a01a-b331-47f3-b828-4a5717e77a24}
- Avalonia.Markup.Xaml
-
-
- {6417e941-21bc-467b-a771-0de389353ce6}
- Avalonia.Markup
-
-
- {7d2d3083-71dd-4cc9-8907-39a0d86fb322}
- Avalonia.Skia
-
-
- {d0a739b9-3c68-4ba6-a328-41606954b6bd}
- ControlCatalog
-
+
+
-
-
-
-
diff --git a/samples/ControlCatalog.Android/MainActivity.cs b/samples/ControlCatalog.Android/MainActivity.cs
index 2ab03551b6..44290d9816 100644
--- a/samples/ControlCatalog.Android/MainActivity.cs
+++ b/samples/ControlCatalog.Android/MainActivity.cs
@@ -1,19 +1,16 @@
using Android.App;
-using Android.OS;
using Android.Content.PM;
+using Avalonia;
using Avalonia.Android;
namespace ControlCatalog.Android
{
- [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)]
- public class MainActivity : AvaloniaActivity
+ [Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
+ public class MainActivity : AvaloniaActivity
{
- protected override void OnCreate(Bundle savedInstanceState)
+ protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
- base.OnCreate(savedInstanceState);
-
- Content = new MainView();
+ return base.CustomizeAppBuilder(builder);
}
}
}
-
diff --git a/samples/ControlCatalog.Android/Properties/AndroidManifest.xml b/samples/ControlCatalog.Android/Properties/AndroidManifest.xml
index 9effda7e79..aa570ec504 100644
--- a/samples/ControlCatalog.Android/Properties/AndroidManifest.xml
+++ b/samples/ControlCatalog.Android/Properties/AndroidManifest.xml
@@ -1,5 +1,4 @@
-
-
-
-
\ No newline at end of file
+
+
+
diff --git a/samples/ControlCatalog.Android/Properties/AssemblyInfo.cs b/samples/ControlCatalog.Android/Properties/AssemblyInfo.cs
deleted file mode 100644
index baeec94648..0000000000
--- a/samples/ControlCatalog.Android/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using Android.App;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ControlCatalog.Android")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ControlCatalog.Android")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/samples/ControlCatalog.Android/Resources/Resource.Designer.cs b/samples/ControlCatalog.Android/Resources/Resource.Designer.cs
deleted file mode 100644
index dccc3f7159..0000000000
--- a/samples/ControlCatalog.Android/Resources/Resource.Designer.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-#pragma warning disable 1591
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-[assembly: global::Android.Runtime.ResourceDesignerAttribute("ControlCatalog.Android.Resource", IsApplication=true)]
-
-namespace ControlCatalog.Android
-{
-
-
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "12.1.99.62")]
- public partial class Resource
- {
-
- static Resource()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- public static void UpdateIdValues()
- {
- }
-
- public partial class Attribute
- {
-
- static Attribute()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Attribute()
- {
- }
- }
-
- public partial class Color
- {
-
- // aapt resource value: 0x7F010000
- public const int splash_background = 2130771968;
-
- static Color()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Color()
- {
- }
- }
-
- public partial class Drawable
- {
-
- // aapt resource value: 0x7F020000
- public const int Icon = 2130837504;
-
- // aapt resource value: 0x7F020001
- public const int splash_screen = 2130837505;
-
- static Drawable()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Drawable()
- {
- }
- }
-
- public partial class Style
- {
-
- // aapt resource value: 0x7F030000
- public const int MyTheme = 2130903040;
-
- // aapt resource value: 0x7F030001
- public const int MyTheme_NoActionBar = 2130903041;
-
- // aapt resource value: 0x7F030002
- public const int MyTheme_Splash = 2130903042;
-
- static Style()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Style()
- {
- }
- }
- }
-}
-#pragma warning restore 1591
diff --git a/samples/ControlCatalog.Android/Resources/values/styles.xml b/samples/ControlCatalog.Android/Resources/values/styles.xml
index e017b6facf..2759d2904a 100644
--- a/samples/ControlCatalog.Android/Resources/values/styles.xml
+++ b/samples/ControlCatalog.Android/Resources/values/styles.xml
@@ -4,7 +4,7 @@
-
diff --git a/samples/ControlCatalog.Android/SplashActivity.cs b/samples/ControlCatalog.Android/SplashActivity.cs
index 6d7c6bc116..dc292fd37b 100644
--- a/samples/ControlCatalog.Android/SplashActivity.cs
+++ b/samples/ControlCatalog.Android/SplashActivity.cs
@@ -1,16 +1,13 @@
using Android.App;
using Android.Content;
using Android.OS;
-using Application = Android.App.Application;
-
-using Avalonia;
namespace ControlCatalog.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity
{
- protected override void OnCreate(Bundle savedInstanceState)
+ protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
@@ -19,13 +16,6 @@ namespace ControlCatalog.Android
{
base.OnResume();
- if (Avalonia.Application.Current == null)
- {
- AppBuilder.Configure()
- .UseAndroid()
- .SetupWithoutStarting();
- }
-
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
}
diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
index 2d4fc45171..d1b657722c 100644
--- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
+++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
@@ -6,7 +6,14 @@
true
+
+ true
+ https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json
+ 7.0.0-*
+
+
+
@@ -15,6 +22,14 @@
+
+
+
+
+
+
+
+
en
diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs
index 0c8fd9465c..4b81935452 100644
--- a/samples/ControlCatalog.NetCore/Program.cs
+++ b/samples/ControlCatalog.NetCore/Program.cs
@@ -118,6 +118,13 @@ namespace ControlCatalog.NetCore
})
.UseSkia()
.UseManagedSystemDialogs()
+ .AfterSetup(builder =>
+ {
+ builder.Instance!.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
+ {
+ StartupScreenIndex = 1,
+ });
+ })
.LogToTrace();
static void SilenceConsole()
diff --git a/samples/ControlCatalog.NetCore/rd.xml b/samples/ControlCatalog.NetCore/rd.xml
new file mode 100644
index 0000000000..27db7f34ca
--- /dev/null
+++ b/samples/ControlCatalog.NetCore/rd.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
index 199fa85ad2..520bbdf32b 100644
--- a/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
+++ b/samples/ControlCatalog.Web/ControlCatalog.Web.csproj
@@ -1,6 +1,7 @@
net6.0
+ false
enable
True
diff --git a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
index db1e16166a..12d1d5645e 100644
--- a/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
+++ b/samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
@@ -1,186 +1,16 @@
-
-
+
- Debug
- iPhoneSimulator
- {57E0455D-D565-44BB-B069-EE1AA20F8337}
- {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
Exe
- ControlCatalog.iOS
- Resources
- ControlCatalogiOS
- true
- NSUrlSessionHandler
- PackageReference
- automatic
+ manual
+ net6.0-ios
+ 10.0
+
+ True
+ iossimulator-x64
+
-
- true
- full
- false
- bin\iPhoneSimulator\Debug
- DEBUG
- prompt
- 4
- false
- x86_64
- None
- True
- 9.1
- False
- False
- False
- False
- False
- False
- False
- False
- True
- Default
- HttpClientHandler
- False
-
-
- none
- true
- bin\iPhoneSimulator\Release
- prompt
- 4
- None
- x86_64
- false
-
-
- true
- full
- false
- bin\iPhone\Debug
- DEBUG
- prompt
- 4
- false
- ARMv7, ARM64
- Entitlements.plist
- iPhone Developer
- true
-
-
- none
- true
- bin\iPhone\Release
- prompt
- 4
- Entitlements.plist
- ARMv7, ARM64
- false
- iPhone Developer
-
-
- none
- True
- bin\iPhone\Ad-Hoc
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- True
- Automatic:AdHoc
- iPhone Distribution
-
-
- none
- True
- bin\iPhone\AppStore
- prompt
- 4
- False
- ARMv7, ARM64
- Entitlements.plist
- Automatic:AppStore
- iPhone Distribution
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {4488AD85-1495-4809-9AA4-DDFE0A48527E}
- Avalonia.iOS
- false
- false
-
-
- {3E53A01A-B331-47F3-B828-4A5717E77A24}
- Avalonia.Markup.Xaml
-
-
- {6417E941-21BC-467B-A771-0DE389353CE6}
- Avalonia.Markup
-
-
- {D211E587-D8BC-45B9-95A4-F297C8FA5200}
- Avalonia.Animation
-
-
- {B09B78D8-9B26-48B0-9149-D64A2F120F3F}
- Avalonia.Base
-
-
- {D2221C82-4A25-4583-9B43-D791E3F6820C}
- Avalonia.Controls
-
-
- {7062AE20-5DCC-4442-9645-8195BDECE63E}
- Avalonia.Diagnostics
-
-
- {62024B2D-53EB-4638-B26B-85EEAA54866E}
- Avalonia.Input
-
-
- {6B0ED19D-A08B-461C-A9D9-A9EE40B0C06B}
- Avalonia.Interactivity
-
-
- {42472427-4774-4C81-8AFF-9F27B8E31721}
- Avalonia.Layout
-
-
- {EB582467-6ABB-43A1-B052-E981BA910E3A}
- Avalonia.Visuals
-
-
- {F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}
- Avalonia.Styling
-
-
- {3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}
- Avalonia.Themes.Default
-
-
- {7d2d3083-71dd-4cc9-8907-39a0d86fb322}
- Avalonia.Skia
-
-
- {d0a739b9-3c68-4ba6-a328-41606954b6bd}
- ControlCatalog
-
-
+
+
-
-
-
-
diff --git a/samples/ControlCatalog.iOS/Info.plist b/samples/ControlCatalog.iOS/Info.plist
index 216fd9c333..6ffe3ba662 100644
--- a/samples/ControlCatalog.iOS/Info.plist
+++ b/samples/ControlCatalog.iOS/Info.plist
@@ -5,7 +5,7 @@
CFBundleDisplayName
ControlCatalog.iOS
CFBundleIdentifier
- com.companyname.ControlCatalog.iOS
+ Avalonia.ControlCatalog
CFBundleShortVersionString
1.0
CFBundleVersion
@@ -13,7 +13,7 @@
LSRequiresIPhoneOS
MinimumOSVersion
- 8.0
+ 10.0
UIDeviceFamily
1
@@ -28,6 +28,7 @@
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
@@ -38,5 +39,9 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIStatusBarHidden
+
+ UIViewControllerBasedStatusBarAppearance
+
diff --git a/samples/ControlCatalog.iOS/Main.cs b/samples/ControlCatalog.iOS/Main.cs
index fe039ba69e..2400115041 100644
--- a/samples/ControlCatalog.iOS/Main.cs
+++ b/samples/ControlCatalog.iOS/Main.cs
@@ -9,7 +9,7 @@ namespace ControlCatalog.iOS
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
- UIApplication.Main(args, null, "AppDelegate");
+ UIApplication.Main(args, null, typeof(AppDelegate));
}
}
-}
\ No newline at end of file
+}
diff --git a/samples/ControlCatalog.iOS/Properties/AssemblyInfo.cs b/samples/ControlCatalog.iOS/Properties/AssemblyInfo.cs
deleted file mode 100644
index 0a5a598651..0000000000
--- a/samples/ControlCatalog.iOS/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("ControlCatalog.iOS")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("ControlCatalog.iOS")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("57e0455d-d565-44bb-b069-ee1aa20f8337")]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/samples/ControlCatalog.iOS/Resources/LaunchScreen.xib b/samples/ControlCatalog.iOS/Resources/LaunchScreen.xib
index be4abb2b43..5d3ccc97db 100644
--- a/samples/ControlCatalog.iOS/Resources/LaunchScreen.xib
+++ b/samples/ControlCatalog.iOS/Resources/LaunchScreen.xib
@@ -11,7 +11,7 @@
-
+
{d0a739b9-3c68-4ba6-a328-41606954b6bd}
diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs
index 7e49cb5dfa..880b210a6c 100644
--- a/src/Android/Avalonia.Android/AndroidInputMethod.cs
+++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs
@@ -13,7 +13,6 @@ namespace Avalonia.Android
{
private readonly TView _host;
private readonly InputMethodManager _imm;
- private IInputElement _inputElement;
public AndroidInputMethod(TView host)
{
@@ -25,7 +24,7 @@ namespace Avalonia.Android
_host.Focusable = true;
_host.FocusableInTouchMode = true;
- _host.ViewTreeObserver.AddOnGlobalLayoutListener(new SoftKeyboardListner(_host));
+ _host.ViewTreeObserver.AddOnGlobalLayoutListener(new SoftKeyboardListener(_host));
}
public void Reset()
@@ -33,8 +32,10 @@ namespace Avalonia.Android
_imm.RestartInput(_host);
}
- public void SetActive(bool active)
+ public void SetClient(ITextInputMethodClient client)
{
+ var active = client is { };
+
if (active)
{
_host.RequestFocus();
@@ -49,20 +50,8 @@ namespace Avalonia.Android
{
}
- public void SetOptions(TextInputOptionsQueryEventArgs options)
+ public void SetOptions(TextInputOptions options)
{
- if (_inputElement != null)
- {
- _inputElement.PointerReleased -= RestoreSoftKeyboard;
- }
-
- _inputElement = options.Source as InputElement;
-
- if (_inputElement == null)
- {
- _imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None);
- }
-
_host.InitEditorInfo((outAttrs) =>
{
outAttrs.InputType = options.ContentType switch
@@ -70,7 +59,7 @@ namespace Avalonia.Android
TextInputContentType.Email => global::Android.Text.InputTypes.TextVariationEmailAddress,
TextInputContentType.Number => global::Android.Text.InputTypes.ClassNumber,
TextInputContentType.Password => global::Android.Text.InputTypes.TextVariationPassword,
- TextInputContentType.Phone => global::Android.Text.InputTypes.ClassPhone,
+ TextInputContentType.Digits => global::Android.Text.InputTypes.ClassPhone,
TextInputContentType.Url => global::Android.Text.InputTypes.TextVariationUri,
_ => global::Android.Text.InputTypes.ClassText
};
@@ -83,9 +72,9 @@ namespace Avalonia.Android
if (options.Multiline)
outAttrs.InputType |= global::Android.Text.InputTypes.TextFlagMultiLine;
- });
- //_inputElement.PointerReleased += RestoreSoftKeyboard;
+ outAttrs.ImeOptions |= ImeFlags.NoFullscreen | ImeFlags.NoExtractUi;
+ });
}
private void RestoreSoftKeyboard(object sender, PointerReleasedEventArgs e)
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index 2d4f6a305f..61aa6ce946 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -1,16 +1,15 @@
using System;
-
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Android;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Input;
-using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
using Avalonia.Rendering;
-using Avalonia.PlatformSupport;
using Avalonia.Skia;
namespace Avalonia
@@ -20,9 +19,10 @@ namespace Avalonia
public static T UseAndroid(this T builder) where T : AppBuilderBase, new()
{
var options = AvaloniaLocator.Current.GetService() ?? new AndroidPlatformOptions();
- builder.UseWindowingSubsystem(() => AndroidPlatform.Initialize(builder.ApplicationType, options), "Android");
- builder.UseSkia();
- return builder;
+
+ return builder
+ .UseWindowingSubsystem(() => AndroidPlatform.Initialize(options), "Android")
+ .UseSkia();
}
}
}
@@ -44,7 +44,7 @@ namespace Avalonia.Android
public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500);
- public static void Initialize(Type appType, AndroidPlatformOptions options)
+ public static void Initialize(AndroidPlatformOptions options)
{
Options = options;
diff --git a/src/Android/Avalonia.Android/AppBuilder.cs b/src/Android/Avalonia.Android/AppBuilder.cs
deleted file mode 100644
index 04f1ff00d0..0000000000
--- a/src/Android/Avalonia.Android/AppBuilder.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Avalonia.Controls;
-using Avalonia.PlatformSupport;
-
-namespace Avalonia
-{
- public sealed class AppBuilder : AppBuilderBase
- {
- public AppBuilder() : base(new StandardRuntimePlatform(),
- builder => StandardRuntimePlatformServices.Register(builder.Instance?.GetType()?.Assembly))
- {
-
- }
- }
-}
diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj
index 5c33dbcea6..203c3accd6 100644
--- a/src/Android/Avalonia.Android/Avalonia.Android.csproj
+++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj
@@ -1,15 +1,19 @@
-
+
- monoandroid11.0
+ net6.0-android
+ $(TargetFrameworks);monoandroid11.0
+ 21
true
+ true
+ portable
-
- TargetFramework=netstandard2.0
-
+
+
+
+
+
-
-
diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs
index 3c9f373a66..f5d620a97a 100644
--- a/src/Android/Avalonia.Android/AvaloniaActivity.cs
+++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs
@@ -1,35 +1,82 @@
-using Android.App;
using Android.OS;
-using Android.Views;
+using AndroidX.AppCompat.App;
+using Android.Content.Res;
+using AndroidX.Lifecycle;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Controls;
namespace Avalonia.Android
{
- public abstract class AvaloniaActivity : Activity
+ public abstract class AvaloniaActivity : AppCompatActivity where TApp : Application, new()
{
+ internal class SingleViewLifetime : ISingleViewApplicationLifetime
+ {
+ public AvaloniaView View { get; internal set; }
+
+ public Control MainView
+ {
+ get => (Control)View.Content;
+ set => View.Content = value;
+ }
+ }
+
internal AvaloniaView View;
- object _content;
+ internal AvaloniaViewModel _viewModel;
+
+ protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
protected override void OnCreate(Bundle savedInstanceState)
{
+ var builder = AppBuilder.Configure();
+
+ CustomizeAppBuilder(builder);
+
View = new AvaloniaView(this);
- if (_content != null)
- View.Content = _content;
SetContentView(View);
+
+ var lifetime = new SingleViewLifetime();
+ lifetime.View = View;
+
+ builder.AfterSetup(x =>
+ {
+ _viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel;
+
+ if (_viewModel.Content != null)
+ {
+ View.Content = _viewModel.Content;
+ }
+
+ View.Prepare();
+ });
+
+ builder.SetupWithLifetime(lifetime);
+
base.OnCreate(savedInstanceState);
}
-
public object Content
{
get
{
- return _content;
+ return _viewModel.Content;
}
set
{
- _content = value;
+ _viewModel.Content = value;
if (View != null)
View.Content = value;
}
}
+
+ public override void OnConfigurationChanged(Configuration newConfig)
+ {
+ base.OnConfigurationChanged(newConfig);
+ }
+
+ protected override void OnDestroy()
+ {
+ View.Content = null;
+
+ base.OnDestroy();
+ }
}
}
diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs
index 8de3657283..8177cf1f69 100644
--- a/src/Android/Avalonia.Android/AvaloniaView.cs
+++ b/src/Android/Avalonia.Android/AvaloniaView.cs
@@ -12,7 +12,7 @@ namespace Avalonia.Android
{
public class AvaloniaView : FrameLayout
{
- private readonly EmbeddableControlRoot _root;
+ private EmbeddableControlRoot _root;
private readonly ViewImpl _view;
private IDisposable? _timerSubscription;
@@ -21,6 +21,11 @@ namespace Avalonia.Android
{
_view = new ViewImpl(context);
AddView(_view.View);
+
+ }
+
+ internal void Prepare ()
+ {
_root = new EmbeddableControlRoot(_view);
_root.Prepare();
}
diff --git a/src/Android/Avalonia.Android/AvaloniaViewModel.cs b/src/Android/Avalonia.Android/AvaloniaViewModel.cs
new file mode 100644
index 0000000000..1b2c00987a
--- /dev/null
+++ b/src/Android/Avalonia.Android/AvaloniaViewModel.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Avalonia.Android
+{
+ internal class AvaloniaViewModel : AndroidX.Lifecycle.ViewModel
+ {
+ public object Content { get; set; }
+ }
+}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
index 34784612f1..5343b57251 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
@@ -2,18 +2,22 @@ using System;
using Android.Content;
using Android.Graphics;
using Android.OS;
+using Android.Runtime;
using Android.Util;
using Android.Views;
+using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Platform;
namespace Avalonia.Android
{
- public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
+ public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformNativeSurfaceHandle
{
bool _invalidateQueued;
readonly object _lock = new object();
private readonly Handler _handler;
-
+
+ IntPtr IPlatformHandle.Handle =>
+ AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, Holder.Surface.Handle);
public InvalidationAwareSurfaceView(Context context) : base(context)
{
@@ -25,7 +29,7 @@ namespace Avalonia.Android
{
lock (_lock)
{
- if(_invalidateQueued)
+ if (_invalidateQueued)
return;
_handler.Post(() =>
{
@@ -70,7 +74,7 @@ namespace Avalonia.Android
public void SurfaceDestroyed(ISurfaceHolder holder)
{
Log.Info("AVALONIA", "Surface Destroyed");
-
+
}
protected void DoDraw()
@@ -83,5 +87,9 @@ namespace Avalonia.Android
}
protected abstract void Draw();
public string HandleDescriptor => "SurfaceView";
+
+ public PixelSize Size => new PixelSize(Holder.SurfaceFrame.Width(), Holder.SurfaceFrame.Height());
+
+ public double Scaling => Resources.DisplayMetrics.Density;
}
}
diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
index 0afb1db141..8a475676a5 100644
--- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
+++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using Android.Content;
using Android.Graphics;
-using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.OpenGL;
@@ -38,11 +37,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_keyboardHelper = new AndroidKeyboardEventsHelper(this);
_touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot,
GetAvaloniaPointFromEvent);
-
_gl = GlPlatformSurface.TryCreate(this);
_framebuffer = new FramebufferManager(this);
- RenderScaling = (int)_view.Resources.DisplayMetrics.Density;
+ RenderScaling = (int)_view.Scaling;
MaxClientSize = new PixelSize(_view.Resources.DisplayMetrics.WidthPixels,
_view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling);
@@ -77,7 +75,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public IPlatformHandle Handle => _view;
- public IEnumerable
-
+