1
0
Эх сурвалжийг харах

Merge remote-tracking branch 'origin/master' into headless-platform

# Conflicts:
#	samples/ControlCatalog.NetCore/Program.cs
Dan Walmsley 5 жил өмнө
parent
commit
31d9c03e6e
100 өөрчлөгдсөн 3746 нэмэгдсэн , 1046 устгасан
  1. 5 0
      .ncrunch/BindingDemo.v3.ncrunchproject
  2. 5 0
      .ncrunch/RenderDemo.v3.ncrunchproject
  3. 5 0
      .ncrunch/VirtualizationDemo.v3.ncrunchproject
  4. 112 33
      Avalonia.sln
  5. 1 0
      Avalonia.sln.DotSettings
  6. 130 0
      CODE_OF_CONDUCT.md
  7. 69 0
      CONTRIBUTING.md
  8. 79 0
      Documentation/build.md
  9. 305 0
      NOTICE.md
  10. 15 7
      azure-pipelines.yml
  11. 2 0
      build.sh
  12. 8 0
      build/AndroidWorkarounds.props
  13. 1 0
      build/Base.props
  14. 1 0
      build/BuildTargets.targets
  15. 2 2
      build/CoreLibraries.props
  16. 6 0
      build/HarfBuzzSharp.props
  17. 1 1
      build/Microsoft.Reactive.Testing.props
  18. 1 1
      build/Moq.props
  19. 5 9
      build/NetFX.props
  20. 1 1
      build/ReactiveUI.props
  21. 1 1
      build/Rx.props
  22. 0 7
      build/Serilog.props
  23. 9 4
      build/SharedVersion.props
  24. 2 2
      build/SkiaSharp.props
  25. 1 1
      build/System.Memory.props
  26. 1 3
      build/readme.md
  27. 2 1
      dirs.proj
  28. 4 1
      global.json
  29. 3 2
      licence.md
  30. 0 3
      native/Avalonia.Native/inc/avalonia-native-guids.h
  31. 140 29
      native/Avalonia.Native/inc/avalonia-native.h
  32. 0 3
      native/Avalonia.Native/inc/com.h
  33. 13 0
      native/Avalonia.Native/inc/comimpl.h
  34. 0 3
      native/Avalonia.Native/inc/key.h
  35. 12 0
      native/Avalonia.Native/inc/rendertarget.h
  36. 33 4
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj
  37. 8 0
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  38. 1 5
      native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme
  39. 3 1
      native/Avalonia.Native/src/OSX/AvnString.h
  40. 61 0
      native/Avalonia.Native/src/OSX/AvnString.mm
  41. 0 3
      native/Avalonia.Native/src/OSX/KeyTransform.h
  42. 0 3
      native/Avalonia.Native/src/OSX/KeyTransform.mm
  43. 2 3
      native/Avalonia.Native/src/OSX/Screens.mm
  44. 3 3
      native/Avalonia.Native/src/OSX/SystemDialogs.mm
  45. 37 0
      native/Avalonia.Native/src/OSX/app.mm
  46. 166 0
      native/Avalonia.Native/src/OSX/cgl.mm
  47. 110 17
      native/Avalonia.Native/src/OSX/clipboard.mm
  48. 23 9
      native/Avalonia.Native/src/OSX/common.h
  49. 0 3
      native/Avalonia.Native/src/OSX/cursor.h
  50. 0 3
      native/Avalonia.Native/src/OSX/cursor.mm
  51. 89 0
      native/Avalonia.Native/src/OSX/dnd.mm
  52. 0 253
      native/Avalonia.Native/src/OSX/gl.mm
  53. 157 23
      native/Avalonia.Native/src/OSX/main.mm
  54. 94 0
      native/Avalonia.Native/src/OSX/menu.h
  55. 469 0
      native/Avalonia.Native/src/OSX/menu.mm
  56. 39 36
      native/Avalonia.Native/src/OSX/platformthreading.mm
  57. 284 0
      native/Avalonia.Native/src/OSX/rendertarget.mm
  58. 15 4
      native/Avalonia.Native/src/OSX/window.h
  59. 513 231
      native/Avalonia.Native/src/OSX/window.mm
  60. 94 85
      nukebuild/Build.cs
  61. 9 12
      nukebuild/BuildParameters.cs
  62. 4 4
      nukebuild/Shims.cs
  63. 4 4
      nukebuild/_build.csproj
  64. 6 1
      packages/Avalonia/AvaloniaBuildTasks.targets
  65. 46 29
      readme.md
  66. 0 2
      samples/BindingDemo/App.xaml.cs
  67. 2 2
      samples/BindingDemo/BindingDemo.csproj
  68. 5 2
      samples/BindingDemo/MainWindow.xaml
  69. 1 4
      samples/BindingDemo/ViewModels/DataAnnotationsErrorViewModel.cs
  70. 1 4
      samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs
  71. 1 4
      samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs
  72. 7 5
      samples/BindingDemo/ViewModels/MainWindowViewModel.cs
  73. 1 1
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  74. 1 1
      samples/ControlCatalog.Android/MainActivity.cs
  75. 0 1
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  76. 0 2
      samples/ControlCatalog.Desktop/Program.cs
  77. 2 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  78. 12 6
      samples/ControlCatalog.NetCore/Program.cs
  79. 2 4
      samples/ControlCatalog/App.xaml
  80. 54 1
      samples/ControlCatalog/App.xaml.cs
  81. 4 2
      samples/ControlCatalog/ControlCatalog.csproj
  82. 25 0
      samples/ControlCatalog/DecoratedWindow.xaml
  83. 4 4
      samples/ControlCatalog/DecoratedWindow.xaml.cs
  84. 40 12
      samples/ControlCatalog/MainView.xaml
  85. 30 13
      samples/ControlCatalog/MainView.xaml.cs
  86. 65 9
      samples/ControlCatalog/MainWindow.xaml
  87. 32 4
      samples/ControlCatalog/MainWindow.xaml.cs
  88. 3 3
      samples/ControlCatalog/Models/Person.cs
  89. 7 0
      samples/ControlCatalog/Pages/BorderPage.xaml
  90. 5 1
      samples/ControlCatalog/Pages/ButtonPage.xaml
  91. 20 0
      samples/ControlCatalog/Pages/ButtonPage.xaml.cs
  92. 9 9
      samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml
  93. 7 7
      samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml.cs
  94. 1 1
      samples/ControlCatalog/Pages/ComboBoxPage.xaml
  95. 3 1
      samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs
  96. 4 0
      samples/ControlCatalog/Pages/DialogsPage.xaml
  97. 61 11
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  98. 9 3
      samples/ControlCatalog/Pages/DragAndDropPage.xaml
  99. 54 38
      samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs
  100. 62 38
      samples/ControlCatalog/Pages/ImagePage.xaml

+ 5 - 0
.ncrunch/BindingDemo.v3.ncrunchproject

@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</ProjectConfiguration>

+ 5 - 0
.ncrunch/RenderDemo.v3.ncrunchproject

@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</ProjectConfiguration>

+ 5 - 0
.ncrunch/VirtualizationDemo.v3.ncrunchproject

@@ -0,0 +1,5 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
+  </Settings>
+</ProjectConfiguration>

+ 112 - 33
Avalonia.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2027
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29102.190
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Base", "src\Avalonia.Base\Avalonia.Base.csproj", "{B09B78D8-9B26-48B0-9149-D64A2F120F3F}"
 EndProject
@@ -95,8 +95,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.UnitTests", "tests
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Benchmarks", "tests\Avalonia.Benchmarks\Avalonia.Benchmarks.csproj", "{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}"
 EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Logging.Serilog", "src\Avalonia.Logging.Serilog\Avalonia.Logging.Serilog.csproj", "{B61B66A3-B82D-4875-8001-89D3394FE0C9}"
-EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport", "src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj", "{799A7BB5-3C2C-48B6-85A7-406A12C420DA}"
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}"
@@ -128,6 +126,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 		build\Base.props = build\Base.props
 		build\Binding.props = build\Binding.props
 		build\BuildTargets.targets = build\BuildTargets.targets
+		build\HarfBuzzSharp.props = build\HarfBuzzSharp.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
@@ -139,7 +138,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
 		build\ReactiveUI.props = build\ReactiveUI.props
 		build\Rx.props = build\Rx.props
 		build\SampleApp.props = build\SampleApp.props
-		build\Serilog.props = build\Serilog.props
 		build\SharpDX.props = build\SharpDX.props
 		build\SkiaSharp.props = build\SkiaSharp.props
 		build\System.Memory.props = build\System.Memory.props
@@ -197,7 +195,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "sam
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.UnitTests", "tests\Avalonia.ReactiveUI.UnitTests\Avalonia.ReactiveUI.UnitTests.csproj", "{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Controls.DataGrid", "src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj", "{3278F3A9-9509-4A3F-A15B-BDC8B5BFF632}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.DataGrid", "src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj", "{3278F3A9-9509-4A3F-A15B-BDC8B5BFF632}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Dialogs", "src\Avalonia.Dialogs\Avalonia.Dialogs.csproj", "{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.FreeDesktop", "src\Avalonia.FreeDesktop\Avalonia.FreeDesktop.csproj", "{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.DataGrid.UnitTests", "tests\Avalonia.Controls.DataGrid.UnitTests\Avalonia.Controls.DataGrid.UnitTests.csproj", "{351337F5-D66F-461B-A957-4EF60BDB4BA6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Themes.Fluent", "src\Avalonia.Themes.Fluent\Avalonia.Themes.Fluent.csproj", "{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Headless", "src\Avalonia.Headless\Avalonia.Headless.csproj", "{8C89950F-F5D9-47FC-8066-CBC1EC3DF8FC}"
 EndProject
@@ -206,11 +212,11 @@ EndProject
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
-		src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 4
+		src\Shared\RenderHelpers\RenderHelpers.projitems*{3e908f67-5543-4879-a1dc-08eace79b3cd}*SharedItemsImports = 5
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*SharedItemsImports = 4
-		src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4
-		tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{dabfd304-d6a4-4752-8123-c2ccf7ac7831}*SharedItemsImports = 4
+		src\Shared\RenderHelpers\RenderHelpers.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 5
+		src\Shared\PlatformSupport\PlatformSupport.projitems*{88060192-33d5-4932-b0f9-8bd2763e857d}*SharedItemsImports = 5
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{e4d9629c-f168-4224-3f51-a5e482ffbc42}*SharedItemsImports = 13
 	EndGlobalSection
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1022,30 +1028,6 @@ Global
 		{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhone.Build.0 = Release|Any CPU
 		{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{410AC439-81A1-4EB5-B5E9-6A7FC6B77F4B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|Any CPU.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhone.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhone.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhone.ActiveCfg = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhone.Build.0 = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|Any CPU.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhone.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhone.Build.0 = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{B61B66A3-B82D-4875-8001-89D3394FE0C9}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 		{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
 		{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
 		{799A7BB5-3C2C-48B6-85A7-406A12C420DA}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
@@ -1894,6 +1876,102 @@ Global
 		{B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E}.Release|iPhone.Build.0 = Release|Any CPU
 		{B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 		{B859AE7C-F34F-4A9E-88AE-E0E7229FDE1E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|iPhone.Build.0 = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{4D55985A-1EE2-4F25-AD39-6EA8BC04F8FB}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|Any CPU.Build.0 = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|iPhone.Build.0 = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|Any CPU.Build.0 = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhone.Build.0 = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|Any CPU.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhone.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|Any CPU.Build.0 = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhone.Build.0 = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{C42D2FC1-A531-4ED4-84B9-89AEC7C962FC}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -1950,6 +2028,7 @@ Global
 		{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
 		{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
 		{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
+		{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

+ 1 - 0
Avalonia.sln.DotSettings

@@ -3,6 +3,7 @@
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=3E53A01A_002DB331_002D47F3_002DB828_002D4A5717E77A24_002Fd_003Aglass/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6417B24E_002D49C2_002D4985_002D8DB2_002D3AB9D898EC91/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=E3A1060B_002D50D0_002D44E8_002D88B6_002DF44EF2E5BD72_002Ff_003Ahtml_002Ehtm/@EntryIndexedValue">ExplicitlyExcluded</s:String>
+	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=MemberCanBePrivate_002EGlobal/@EntryIndexedValue">DO_NOT_SHOW</s:String>
 	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">HINT</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=DECLSPEC_005FPROPERTY/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=ENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>

+ 130 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,130 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
[email protected].
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.
+

+ 69 - 0
CONTRIBUTING.md

@@ -0,0 +1,69 @@
+# Contributing to Avalonia
+
+## Before You Start
+
+Drop into our [gitter chat room](https://gitter.im/AvaloniaUI/Avalonia) and let us know what you're thinking of doing. We might be able to give you guidance or let you know if someone else is already working on the feature.
+
+## Style
+
+The codebase uses [.net core](https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/coding-style.md) coding style.
+
+Try to keep lines of code around 100 characters in length or less, though this is not a hard limit.
+If you're a few characters over then don't worry too much.
+
+**DO NOT USE #REGIONS** full stop.
+
+## Pull requests
+
+A single pull request should be submitted for each change. If you're making more than one change,
+please submit separate pull requests for each change for easy review. Rebase your changes to make
+sense, so a history that looks like:
+
+* Add class A
+* Feature A didn't set Foo when Bar was set
+* Fix spacing
+* Add class B
+* Sort using statements
+
+Should be rebased to read:
+
+* Add class A
+* Add class B
+
+Again, this makes review much easier.
+
+Please try not to submit pull requests that don't add new features (e.g. moving stuff around)
+unless you see something that is obviously wrong or that could be written in a more terse or
+idiomatic style. It takes time to review each pull request - time that I'd prefer to spend writing
+new features!
+
+Prefer terseness to verbosity but don't try to be too clever.
+
+## Tests
+
+There are two types of tests currently in the codebase; unit tests and render tests.
+
+Unit tests should be contained in a class name that mirrors the class being tested with the suffix
+-Tests, e.g.
+
+    Avalonia.Controls.UnitTests.Presenters.TextPresenterTests
+
+Where Avalonia.Controls.UnitTests is the name of the project.
+
+Unit test methods should be named in a sentence style, separated by underscores, that describes in
+English what the test is testing, e.g.
+
+```csharp
+    void Calling_Foo_Should_Increment_Bar()
+```
+
+Render tests should describe what the produced image is:
+
+```csharp
+    void Rectangle_2px_Stroke_Filled()
+```
+
+## Code of Conduct
+
+This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
+For more information see the [Contributor Covenant Code of Conduct](https://dotnetfoundation.org/code-of-conduct)

+ 79 - 0
Documentation/build.md

@@ -0,0 +1,79 @@
+# Windows
+
+Avalonia requires at least Visual Studio 2019 and .NET Core SDK 3.1 to build on Windows.
+
+###  Clone the Avalonia repository
+
+```
+git clone https://github.com/AvaloniaUI/Avalonia.git
+git submodule update --init
+```
+
+###  Open in Visual Studio
+
+Open the `Avalonia.sln` solution in Visual Studio 2019 or newer. The free Visual Studio Community
+edition works fine. Run the `Samples\ControlCatalog.Desktop` project to see the sample application.
+
+# Linux/macOS
+
+It's *not* possible to build the *whole* project on Linux/macOS. You can only build the subset targeting .NET Standard and .NET Core (which is, however, sufficient to get UI working on Linux/macOS). If you want to something that involves changing platform-specific APIs you'll need a Windows machine.
+
+MonoDevelop, Xamarin Studio and Visual Studio for Mac aren't capable of properly opening our solution. You can use Rider (at least 2017.2 EAP) or VSCode instead. They will fail to load most of platform specific projects, but you don't need them to run on .NET Core.
+
+###  Install the latest version of .NET Core
+
+Go to https://www.microsoft.com/net/core and follow instructions for your OS. You need SDK (not just "runtime") package.
+
+###  Additional requirements for macOS
+
+The build process needs [Xcode](https://developer.apple.com/xcode/) to build the native library.  Following the install instructions at the [Xcode](https://developer.apple.com/xcode/) website to properly install.
+
+Linux operating systems ship with their own respective package managers however we will use [Homebrew](https://brew.sh/) to manage packages on macOS.  To install follow the instructions [here](https://docs.brew.sh/Installation).
+
+###  Install CastXML
+
+Avalonia requires [CastXML](https://github.com/CastXML/CastXML) for XML processing during the build process.  The easiest way to install this is via the operating system's package managers, such as below.
+
+On macOS:
+```
+brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8a004a91a7fcd3f6620d5b01b6541ff0a640ffba/Formula/castxml.rb
+```
+
+On Debian based Linux (Debian, Ubuntu, Mint, etc):
+```
+sudo apt install castxml
+```
+
+On Red Hat based Linux (Fedora, CentOS, RHEL, etc) using `yum` (`dnf` takes same arguments though):
+```
+sudo yum install castxml
+```
+
+
+###  Clone the Avalonia repository
+
+```
+git clone https://github.com/AvaloniaUI/Avalonia.git
+cd Avalonia
+git submodule update --init --recursive
+```
+
+### Build native libraries (macOS only)
+
+On macOS it is necessary to build and manually install the respective native libraries using [Xcode](https://developer.apple.com/xcode/).  The steps to get this working correctly are:
+- Navigate to the Avalonia/native/Avalonia.Native/src/OSX folder and open the `Avalonia.Native.OSX.xcodeproj` project
+- Build the library via the Product->Build menu.  This will generate binaries in your local path under ~/Library/Developer/Xcode/DerivedData/Avalonia.Native.OSX-*guid* where "guid" is uniquely generated every time you build.
+- Manually install the native library by copying it from the build artifacts folder into the shared dynamic library path:
+
+```
+cd ~/Library/Developer/Xcode/DerivedData/Avalonia.Native.OSX-[guid]/Build/Products/Debug
+cp libAvalonia.Native.OSX.dylib /usr/local/lib/libAvaloniaNative.dylib
+```
+
+###  Build and Run Avalonia
+
+```
+cd samples/ControlCatalog.NetCore
+dotnet restore
+dotnet run
+```

+ 305 - 0
NOTICE.md

@@ -0,0 +1,305 @@
+# WPF
+
+https://github.com/dotnet/wpf
+
+The MIT License (MIT)
+
+Copyright (c) .NET Foundation and Contributors
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+# SharpDX
+
+https://github.com/sharpdx/SharpDX
+
+Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+# Silverlight Toolkit
+
+https://github.com/microsoftarchive/SilverlightToolkit
+
+Microsoft Public License (MS-PL)
+
+This license governs use of the accompanying software. If you use the software, you
+accept this license. If you do not accept the license, do not use the software.
+
+1. Definitions
+The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
+same meaning here as under U.S. copyright law.
+A "contribution" is the original software, or any additions or changes to the software.
+A "contributor" is any person that distributes its contribution under this license.
+"Licensed patents" are a contributor's patent claims that read directly on its contribution.
+
+2. Grant of Rights
+(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
+(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
+
+3. Conditions and Limitations
+(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
+(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
+(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
+(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
+(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
+
+# wayland-protocols
+
+https://github.com/wayland-project/wayland-protocols
+
+Copyright © 2008-2013 Kristian Høgsberg
+Copyright © 2010-2013 Intel Corporation
+Copyright © 2013      Rafael Antognolli
+Copyright © 2013      Jasper St. Pierre
+Copyright © 2014      Jonas Ådahl
+Copyright © 2014      Jason Ekstrand
+Copyright © 2014-2015 Collabora, Ltd.
+Copyright © 2015      Red Hat Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+
+# Metsys.Bson
+
+Copyright (c) 2010, Karl Seguin - http://www.openmymind.net/
+All rights reserved.
+ 
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of the <organization> nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+ 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# RichTextKit
+
+https://github.com/toptensoftware/RichTextKit
+
+Copyright © 2019 Topten Software. All Rights Reserved.
+
+Licensed under the Apache License, Version 2.0 (the "License"); you may 
+not use this product except in compliance with the License. You may obtain 
+a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software 
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
+License for the specific language governing permissions and limitations 
+under the License.
+
+# Mono
+
+https://github.com/mono/mono
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+# Collections.Pooled
+
+https://github.com/jtmueller/Collections.Pooled
+
+The MIT License (MIT)
+
+Copyright (c) Joel Mueller
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+# EllipticalArc.java
+
+http://www.spaceroots.org/documents/ellipse/EllipticalArc.java
+http://www.spaceroots.org/documents/ellipse/elliptical-arc.pdf
+
+Copyright (c) 2003-2004, Luc Maisonobe
+All rights reserved.
+
+Redistribution and use in source and binary forms, with
+or without modification, are permitted provided that
+the following conditions are met:
+
+   Redistributions of source code must retain the
+   above copyright notice, this list of conditions and
+   the following disclaimer. 
+   Redistributions in binary form must reproduce the
+   above copyright notice, this list of conditions and
+   the following disclaimer in the documentation
+   and/or other materials provided with the
+   distribution. 
+   Neither the names of spaceroots.org, spaceroots.com
+   nor the names of their contributors may be used to
+   endorse or promote products derived from this
+   software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+# WinUI
+
+https://github.com/microsoft/microsoft-ui-xaml
+
+MIT License
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE
+
+# Chromium
+
+https://github.com/chromium/chromium
+
+// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 15 - 7
azure-pipelines.yml

@@ -14,7 +14,7 @@ jobs:
     displayName: 'Install Nuke'
     inputs:
       script: |
-         dotnet tool install --global Nuke.GlobalTool --version 0.12.3
+         dotnet tool install --global Nuke.GlobalTool --version 0.24.0
   - task: CmdLine@2
     displayName: 'Run Nuke'
     inputs:
@@ -34,9 +34,17 @@ jobs:
   pool:
     vmImage: 'macOS-10.14'
   steps:
-  - task: DotNetCoreInstaller@0
+  - task: UseDotNet@2
+    displayName: 'Use .NET Core SDK 3.1.101'
     inputs:
-      version: '2.1.403'
+      packageType: sdk
+      version: 3.1.101
+
+  - task: UseDotNet@2
+    displayName: 'Use .NET Core Runtime 3.1.1'
+    inputs:
+      packageType: runtime
+      version: 3.1.1
 
   - task: CmdLine@2
     displayName: 'Install Mono 5.18'
@@ -52,7 +60,7 @@ jobs:
       sdk: 'macosx10.14'
       configuration: 'Release'
       xcWorkspacePath: '**/*.xcodeproj/project.xcworkspace'
-      xcodeVersion: 'default' # Options: 8, 9, default, specifyPath
+      xcodeVersion: '10' # Options: 8, 9, default, specifyPath
       args: '-derivedDataPath ./'
 
   - task: CmdLine@2
@@ -60,13 +68,13 @@ jobs:
     inputs:
       script: |
         brew update
-        brew install castxml
+        brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/8a004a91a7fcd3f6620d5b01b6541ff0a640ffba/Formula/castxml.rb
 
   - task: CmdLine@2
     displayName: 'Install Nuke'
     inputs:
       script: |
-       dotnet tool install --global Nuke.GlobalTool --version 0.12.3 
+       dotnet tool install --global Nuke.GlobalTool --version 0.24.0
 
   - task: CmdLine@2
     displayName: 'Run Nuke'
@@ -108,7 +116,7 @@ jobs:
     displayName: 'Install Nuke'
     inputs:
       script: |
-       dotnet tool install --global Nuke.GlobalTool --version 0.12.3 
+       dotnet tool install --global Nuke.GlobalTool --version 0.24.0 
 
   - task: CmdLine@2
     displayName: 'Run Nuke'

+ 2 - 0
build.sh

@@ -67,6 +67,8 @@ else
     fi
 fi
 
+export PATH=$DOTNET_DIRECTORY:$PATH
+
 echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)"
 
 "$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]}

+ 8 - 0
build/AndroidWorkarounds.props

@@ -5,4 +5,12 @@
     <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
     <PackageReference Include="System.Buffers" Version="4.5.0" />
   </ItemGroup>
+  <Target Name="_RemoveNonExistingResgenFile" BeforeTargets="CoreCompile" Condition="'$(_SdkSetAndroidResgenFile)' == 'true' And '$(AndroidResgenFile)' != '' And !Exists('$(AndroidResgenFile)')">
+    <ItemGroup>
+      <Compile Remove="$(AndroidResgenFile)"/>
+    </ItemGroup>
+  </Target>
+  <PropertyGroup>
+    <DesignTimeBuild>false</DesignTimeBuild>
+  </PropertyGroup>
 </Project>

+ 1 - 0
build/Base.props

@@ -1,5 +1,6 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
     <PackageReference Include="System.ValueTuple" Version="4.5.0" />
+    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.6.0" />
   </ItemGroup>
 </Project>

+ 1 - 0
build/BuildTargets.targets

@@ -2,6 +2,7 @@
   <PropertyGroup>
     <AvaloniaBuildTasksLocation>$(MSBuildThisFileDirectory)\..\src\Avalonia.Build.Tasks\bin\$(Configuration)\netstandard2.0\Avalonia.Build.Tasks.dll</AvaloniaBuildTasksLocation>
     <AvaloniaUseExternalMSBuild>true</AvaloniaUseExternalMSBuild>
+    <AvaloniaXamlIlVerifyIl>true</AvaloniaXamlIlVerifyIl>
   </PropertyGroup>
   <Import Project="$(MSBuildThisFileDirectory)\..\packages\Avalonia\AvaloniaBuildTasks.props"/>
   <Import Project="$(MSBuildThisFileDirectory)\..\packages\Avalonia\AvaloniaBuildTasks.targets"/>

+ 2 - 2
build/CoreLibraries.props

@@ -4,15 +4,15 @@
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Animation/Avalonia.Animation.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Controls/Avalonia.Controls.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj" />
-      <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Input/Avalonia.Input.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Interactivity/Avalonia.Interactivity.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Layout/Avalonia.Layout.csproj" />
-      <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Visuals/Avalonia.Visuals.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Styling/Avalonia.Styling.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj" />
+      <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.OpenGL/Avalonia.OpenGL.csproj" />
+      <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.Dialogs/Avalonia.Dialogs.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Markup/Avalonia.Markup/Avalonia.Markup.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj" />
       <ProjectReference Include="$(MSBuildThisFileDirectory)/../src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj" Condition="'$(TargetFramework)' != 'netstandard2.0'" />

+ 6 - 0
build/HarfBuzzSharp.props

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

+ 1 - 1
build/Microsoft.Reactive.Testing.props

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

+ 1 - 1
build/Moq.props

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

+ 5 - 9
build/NetFX.props

@@ -1,11 +1,7 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <PropertyGroup Condition=" '$(TargetFramework)' == 'net461' and '$(OS)' == 'Unix' ">
-    <FrameworkPathOverride>/usr/lib/mono/4.6.1-api</FrameworkPathOverride>
-    <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.6.1-api</FrameworkPathOverride>
-  </PropertyGroup>
-  <PropertyGroup Condition=" '$(TargetFramework)' == 'net47' and '$(OS)' == 'Unix' ">
-    <FrameworkPathOverride>/usr/lib/mono/4.7-api/</FrameworkPathOverride>
-    <FrameworkPathOverride Condition="$([MSBuild]::IsOsPlatform('OSX'))">/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.7-api</FrameworkPathOverride>
-  </PropertyGroup>
+<Project>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.0-preview.2" PrivateAssets="All" />
+  </ItemGroup>
 
 </Project>

+ 1 - 1
build/ReactiveUI.props

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

+ 1 - 1
build/Rx.props

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

+ 0 - 7
build/Serilog.props

@@ -1,7 +0,0 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <PackageReference Include="Serilog" Version="2.5.0" />
-    <PackageReference Include="Serilog.Sinks.Trace" Version="2.1.0" />
-    <PackageReference Include="Serilog.Sinks.Debug" Version="1.0.0" />
-  </ItemGroup>
-</Project>

+ 9 - 4
build/SharedVersion.props

@@ -2,13 +2,18 @@
   xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
     <Product>Avalonia</Product>
-    <Version>0.8.999</Version>
-    <Copyright>Copyright 2019 &#169; The AvaloniaUI Project</Copyright>
-    <PackageLicenseUrl>https://github.com/AvaloniaUI/Avalonia/blob/master/licence.md</PackageLicenseUrl>
-    <PackageProjectUrl>https://github.com/AvaloniaUI/Avalonia/</PackageProjectUrl>
+    <Version>0.9.999</Version>
+    <Copyright>Copyright 2020 &#169; The AvaloniaUI Project</Copyright>
+    <PackageProjectUrl>https://avaloniaui.net</PackageProjectUrl>
     <RepositoryUrl>https://github.com/AvaloniaUI/Avalonia/</RepositoryUrl>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <LangVersion>latest</LangVersion>
+    <PackageLicenseExpression>MIT</PackageLicenseExpression>
+    <PackageIconUrl>https://avatars2.githubusercontent.com/u/14075148?s=200</PackageIconUrl>
+    <PackageDescription>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.</PackageDescription>
+    <PackageTags>avalonia;avaloniaui;mvvm;rx;reactive extensions;android;ios;mac;forms;wpf;net;netstandard;net461;uwp;xamarin</PackageTags>
+    <PackageReleaseNotes>https://github.com/AvaloniaUI/Avalonia/releases</PackageReleaseNotes>
+    <RepositoryType>git</RepositoryType>
   </PropertyGroup>
 </Project>

+ 2 - 2
build/SkiaSharp.props

@@ -1,6 +1,6 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
-    <PackageReference Include="SkiaSharp" Version="1.68.0" />
-    <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.68.0.2" />
+    <PackageReference Include="SkiaSharp" Version="1.68.2.1" />
+    <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="1.68.2.1" />
   </ItemGroup>
 </Project>

+ 1 - 1
build/System.Memory.props

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

+ 1 - 3
build/readme.md

@@ -9,8 +9,6 @@
 <Import Project="..\..\build\Moq.props" />
 <Import Project="..\..\build\NetCore.props" />
 <Import Project="..\..\build\Rx.props" />
-<Import Project="..\..\build\Serilog.props" />
-<Import Project="..\..\build\Serilog.Sinks.Trace.props" />
 <Import Project="..\..\build\SharpDX.props" />
 <Import Project="..\..\build\SkiaSharp.Desktop.props" />
 <Import Project="..\..\build\SkiaSharp.props" />
@@ -22,4 +20,4 @@
 
 ```XML
 <Import Project="..\..\build\UnitTests.NetCore.targets" />
-```
+```

+ 2 - 1
dirs.proj

@@ -8,7 +8,8 @@
     <ProjectReference Remove="src/Markup/Avalonia.Markup.Xaml/PortableXaml/**/*.*proj" />
     <ProjectReference Remove="src/Markup/Avalonia.Markup.Xaml/XamlIl/**/*.*proj" />
   </ItemGroup>
-  <ItemGroup Condition="!Exists('$(MSBuildExtensionsPath)\Xamarin\Android')">
+  <!--<ItemGroup Condition="!Exists('$(MSBuildExtensionsPath)\Xamarin\Android')">-->
+  <ItemGroup>
     <ProjectReference Remove="src/Android/**/*.*proj" />
     <ProjectReference Remove="samples/ControlCatalog.Android/ControlCatalog.Android.csproj" />
   </ItemGroup>

+ 4 - 1
global.json

@@ -1,7 +1,10 @@
 {
+	"sdk": {
+		"version": "3.1.101"
+	},
     "msbuild-sdks": {
         "Microsoft.Build.Traversal": "1.0.43",
-        "MSBuild.Sdk.Extras": "1.6.65",
+        "MSBuild.Sdk.Extras": "2.0.46",
         "AggregatePackage.NuGet.Sdk" : "0.1.12"
     }
 }

+ 3 - 2
licence.md

@@ -1,6 +1,7 @@
 The MIT License (MIT)
 
-Copyright (c) 2014 Steven Kirk
+Copyright (c) .NET Foundation and Contributors
+All Rights Reserved
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+SOFTWARE.

+ 0 - 3
native/Avalonia.Native/inc/avalonia-native-guids.h

@@ -1,5 +1,2 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #define COM_GUIDS_MATERIALIZE
 #include "avalonia-native.h"

+ 140 - 29
native/Avalonia.Native/inc/avalonia-native.h

@@ -1,8 +1,6 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "com.h"
 #include "key.h"
+#include "stddef.h"
 
 #define AVNCOM(name, id) COMINTERFACE(name, 2e2cda0a, 9ae5, 4f1b, 8e, 20, 08, 1a, 04, 27, 9f, id)
 
@@ -22,6 +20,18 @@ struct IAvnGlContext;
 struct IAvnGlDisplay;
 struct IAvnGlSurfaceRenderTarget;
 struct IAvnGlSurfaceRenderingSession;
+struct IAvnMenu;
+struct IAvnMenuItem;
+struct IAvnStringArray;
+struct IAvnDndResultCallback;
+struct IAvnGCHandleDeallocatorCallback;
+struct IAvnMenuEvents;
+
+enum SystemDecorations {
+    SystemDecorationsNone = 0,
+    SystemDecorationsBorderOnly = 1,
+    SystemDecorationsFull = 2,
+};
 
 struct AvnSize
 {
@@ -52,6 +62,7 @@ struct AvnScreen
 {
     AvnRect Bounds;
     AvnRect WorkingArea;
+    float PixelDensity;
     bool Primary;
 };
 
@@ -89,9 +100,17 @@ enum AvnRawMouseEventType
     RightButtonUp,
     MiddleButtonDown,
     MiddleButtonUp,
+    XButton1Down,
+    XButton1Up,
+    XButton2Down,
+    XButton2Up,
     Move,
     Wheel,
-    NonClientLeftButtonDown
+    NonClientLeftButtonDown,
+    TouchBegin,
+    TouchUpdate,
+    TouchEnd,
+    TouchCancel
 };
 
 enum AvnRawKeyEventType
@@ -109,7 +128,25 @@ enum AvnInputModifiers
     Windows = 8,
     LeftMouseButton = 16,
     RightMouseButton = 32,
-    MiddleMouseButton = 64
+    MiddleMouseButton = 64,
+    XButton1MouseButton = 128,
+    XButton2MouseButton = 256
+};
+
+enum class AvnDragDropEffects
+{
+    None = 0,
+    Copy = 1,
+    Move = 2,
+    Link = 4,
+};
+
+enum class AvnDragEventType
+{
+    Enter,
+    Over,
+    Leave,
+    Drop
 };
 
 enum AvnWindowState
@@ -117,6 +154,7 @@ enum AvnWindowState
     Normal,
     Minimized,
     Maximized,
+    FullScreen,
 };
 
 enum AvnStandardCursorType
@@ -159,19 +197,31 @@ enum AvnWindowEdge
     WindowEdgeSouthEast
 };
 
+enum AvnMenuItemToggleType
+{
+    None,
+    CheckMark,
+    Radio
+};
+
 AVNCOM(IAvaloniaNativeFactory, 01) : IUnknown
 {
 public:
-    virtual HRESULT Initialize() = 0;
+    virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) = 0;
     virtual IAvnMacOptions* GetMacOptions() = 0;
-    virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv) = 0;
-    virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnPopup** ppv) = 0;
+    virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) = 0;
+    virtual HRESULT CreatePopup (IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) = 0;
     virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) = 0;
     virtual HRESULT CreateSystemDialogs (IAvnSystemDialogs** ppv) = 0;
     virtual HRESULT CreateScreens (IAvnScreens** ppv) = 0;
     virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0;
+    virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) = 0;
     virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
-    virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) = 0;
+    virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) = 0;
+    virtual HRESULT SetAppMenu(IAvnMenu* menu) = 0;
+    virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) = 0;
+    virtual HRESULT CreateMenuItem (IAvnMenuItem** ppv) = 0;
+    virtual HRESULT CreateMenuItemSeperator (IAvnMenuItem** ppv) = 0;
 };
 
 AVNCOM(IAvnString, 17) : IUnknown
@@ -187,7 +237,6 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown
     virtual HRESULT Close() = 0;
     virtual HRESULT Activate () = 0;
     virtual HRESULT GetClientSize(AvnSize*ret) = 0;
-    virtual HRESULT GetMaxClientSize(AvnSize* ret) = 0;
     virtual HRESULT GetScaling(double*ret)=0;
     virtual HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize) = 0;
     virtual HRESULT Resize(double width, double height) = 0;
@@ -202,9 +251,14 @@ AVNCOM(IAvnWindowBase, 02) : IUnknown
     virtual HRESULT SetTopMost (bool value) = 0;
     virtual HRESULT SetCursor(IAvnCursor* cursor) = 0;
     virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ret) = 0;
-    virtual HRESULT GetSoftwareFramebuffer(AvnFramebuffer*ret) = 0;
-    virtual bool TryLock() = 0;
-    virtual void Unlock() = 0;
+    virtual HRESULT SetMainMenu(IAvnMenu* menu) = 0;
+    virtual HRESULT ObtainNSWindowHandle(void** retOut) = 0;
+    virtual HRESULT ObtainNSWindowHandleRetained(void** retOut) = 0;
+    virtual HRESULT ObtainNSViewHandle(void** retOut) = 0;
+    virtual HRESULT ObtainNSViewHandleRetained(void** retOut) = 0;
+    virtual HRESULT BeginDragAndDropOperation(AvnDragDropEffects effects, AvnPoint point,
+                                              IAvnClipboard* clipboard, IAvnDndResultCallback* cb, void* sourceHandle) = 0;
+    virtual HRESULT SetBlurEnabled (bool enable) = 0;
 };
 
 AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
@@ -214,9 +268,10 @@ AVNCOM(IAvnPopup, 03) : virtual IAvnWindowBase
 
 AVNCOM(IAvnWindow, 04) : virtual IAvnWindowBase
 {
-    virtual HRESULT ShowDialog (IAvnWindow* parent) = 0;
+    virtual HRESULT SetEnabled (bool enable) = 0;
+    virtual HRESULT SetParent (IAvnWindow* parent) = 0;
     virtual HRESULT SetCanResize(bool value) = 0;
-    virtual HRESULT SetHasDecorations(bool value) = 0;
+    virtual HRESULT SetDecorations(SystemDecorations value) = 0;
     virtual HRESULT SetTitle (void* utf8Title) = 0;
     virtual HRESULT SetTitleBarColor (AvnColor color) = 0;
     virtual HRESULT SetWindowState(AvnWindowState state) = 0;
@@ -240,6 +295,9 @@ AVNCOM(IAvnWindowBaseEvents, 05) : IUnknown
     virtual bool RawTextInputEvent (unsigned int timeStamp, const char* text) = 0;
     virtual void ScalingChanged(double scaling) = 0;
     virtual void RunRenderPriorityJobs() = 0;
+    virtual AvnDragDropEffects DragEvent(AvnDragEventType type, AvnPoint position,
+                                         AvnInputModifiers modifiers, AvnDragDropEffects effects,
+                                         IAvnClipboard* clipboard, void* dataObjectHandle) = 0;
 };
 
 
@@ -253,11 +311,14 @@ AVNCOM(IAvnWindowEvents, 06) : IAvnWindowBaseEvents
     virtual bool Closing () = 0;
     
     virtual void WindowStateChanged (AvnWindowState state) = 0;
+    
+    virtual void GotInputWhenDisabled () = 0;
 };
 
 AVNCOM(IAvnMacOptions, 07) : IUnknown
 {
     virtual HRESULT SetShowInDock(int show) = 0;
+    virtual HRESULT SetApplicationTitle (void* utf8string) = 0;
 };
 
 AVNCOM(IAvnActionCallback, 08) : IUnknown
@@ -280,7 +341,7 @@ AVNCOM(IAvnPlatformThreadingInterface, 0b) : IUnknown
     virtual bool GetCurrentThreadIsLoopThread() = 0;
     virtual void SetSignaledCallback(IAvnSignaledCallback* cb) = 0;
     virtual IAvnLoopCancellation* CreateLoopCancellation() = 0;
-    virtual void RunLoop(IAvnLoopCancellation* cancel) = 0;
+    virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) = 0;
     // Can't pass int* to sharpgentools for some reason
     virtual void Signal(int priority) = 0;
     virtual IUnknown* StartTimer(int priority, int ms, IAvnActionCallback* callback) = 0;
@@ -322,8 +383,13 @@ AVNCOM(IAvnScreens, 0e) : IUnknown
 
 AVNCOM(IAvnClipboard, 0f) : IUnknown
 {
-    virtual HRESULT GetText (IAvnString**ppv) = 0;
-    virtual HRESULT SetText (void* utf8Text) = 0;
+    virtual HRESULT GetText (char* type, IAvnString**ppv) = 0;
+    virtual HRESULT SetText (char* type, void* utf8Text) = 0;
+    virtual HRESULT ObtainFormats(IAvnStringArray**ppv) = 0;
+    virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) = 0;
+    virtual HRESULT SetBytes(char* type, void* utf8Text, int len) = 0;
+    virtual HRESULT GetBytes(char* type, IAvnString**ppv) = 0;
+    
     virtual HRESULT Clear() = 0;
 };
 
@@ -336,24 +402,21 @@ AVNCOM(IAvnCursorFactory, 11) : IUnknown
     virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) = 0;
 };
 
-
-AVNCOM(IAvnGlFeature, 12) : IUnknown
-{
-    virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut) = 0;
-    virtual HRESULT ObtainImmediateContext(IAvnGlContext**retOut) = 0;
-};
-
 AVNCOM(IAvnGlDisplay, 13) : IUnknown
 {
-    virtual HRESULT GetSampleCount(int* ret) = 0;
-    virtual HRESULT GetStencilSize(int* ret) = 0;
-    virtual HRESULT ClearContext() = 0;
+    virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) = 0;
+    virtual void LegacyClearCurrentContext() = 0;
+    virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) = 0;
     virtual void* GetProcAddress(char* proc) = 0;
 };
 
 AVNCOM(IAvnGlContext, 14) : IUnknown
 {
-    virtual HRESULT MakeCurrent() = 0;
+    virtual HRESULT MakeCurrent(IUnknown** ppv) = 0;
+    virtual HRESULT LegacyMakeCurrent() = 0;
+    virtual int GetSampleCount() = 0;
+    virtual int GetStencilSize() = 0;
+    virtual void* GetNativeHandle() = 0;
 };
 
 AVNCOM(IAvnGlSurfaceRenderTarget, 15) : IUnknown
@@ -367,4 +430,52 @@ AVNCOM(IAvnGlSurfaceRenderingSession, 16) : IUnknown
     virtual HRESULT GetScaling(double* ret) = 0;
 };
 
+AVNCOM(IAvnMenu, 17) : IUnknown
+{
+    virtual HRESULT InsertItem (int index, IAvnMenuItem* item) = 0;
+    virtual HRESULT RemoveItem (IAvnMenuItem* item) = 0;
+    virtual HRESULT SetTitle (void* utf8String) = 0;
+    virtual HRESULT Clear () = 0;
+};
+
+AVNCOM(IAvnPredicateCallback, 18) : IUnknown
+{
+    virtual bool Evaluate() = 0;
+};
+
+AVNCOM(IAvnMenuItem, 19) : IUnknown
+{
+    virtual HRESULT SetSubMenu (IAvnMenu* menu) = 0;
+    virtual HRESULT SetTitle (void* utf8String) = 0;
+    virtual HRESULT SetGesture (void* utf8String, AvnInputModifiers modifiers) = 0;
+    virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) = 0;
+    virtual HRESULT SetIsChecked (bool isChecked) = 0;
+    virtual HRESULT SetToggleType (AvnMenuItemToggleType toggleType) = 0;
+    virtual HRESULT SetIcon (void* data, size_t length) = 0;
+};
+
+AVNCOM(IAvnMenuEvents, 1A) : IUnknown
+{
+    /**
+     * NeedsUpdate
+     */
+    virtual void NeedsUpdate () = 0;
+};
+
+AVNCOM(IAvnStringArray, 20) : IUnknown
+{
+    virtual unsigned int GetCount() = 0;
+    virtual HRESULT Get(unsigned int index, IAvnString**ppv) = 0;
+};
+
+AVNCOM(IAvnDndResultCallback, 21) : IUnknown
+{
+    virtual void OnDragAndDropComplete(AvnDragDropEffects effecct) = 0;
+};
+
+AVNCOM(IAvnGCHandleDeallocatorCallback, 22) : IUnknown
+{
+    virtual void FreeGCHandle(void* handle) = 0;
+};
+
 extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative();

+ 0 - 3
native/Avalonia.Native/inc/com.h

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #pragma clang diagnostic push
 #pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
 #ifndef COM_H_INCLUDED

+ 13 - 0
native/Avalonia.Native/inc/comimpl.h

@@ -162,6 +162,19 @@ public:
         return _obj;
     }
     
+    TInterface* getRetainedReference()
+    {
+        if(_obj == NULL)
+            return NULL;
+        _obj->AddRef();
+        return _obj;
+    }
+    
+    TInterface** getPPV()
+    {
+        return &_obj;
+    }
+    
     operator TInterface*() const
     {
         return _obj;

+ 0 - 3
native/Avalonia.Native/inc/key.h

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #ifndef _KEY_H_
 #define _KEY_H_
 

+ 12 - 0
native/Avalonia.Native/inc/rendertarget.h

@@ -0,0 +1,12 @@
+
+@protocol IRenderTarget
+-(void) setNewLayer: (CALayer*) layer;
+-(HRESULT) setSwFrame: (AvnFramebuffer*) fb;
+-(void) resize: (AvnPixelSize) size withScale: (float) scale;
+-(AvnPixelSize) pixelSize;
+-(IAvnGlSurfaceRenderTarget*) createSurfaceRenderTarget;
+@end
+
+@interface IOSurfaceRenderTarget : NSObject<IRenderTarget>
+-(IOSurfaceRenderTarget*) initWithOpenGlContext: (IAvnGlContext*) context;
+@end

+ 33 - 4
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj

@@ -7,21 +7,35 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; };
+		1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; };
+		1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */; };
+		1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EAD23E9FB1300EDE661 /* cgl.mm */; };
+		1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */; };
+		1A465D10246AB61600C5858B /* dnd.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A465D0F246AB61600C5858B /* dnd.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 */; };
 		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 */; };
 		5B21A982216530F500CEE36E /* cursor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B21A981216530F500CEE36E /* cursor.mm */; };
 		5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */; };
 		AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; };
 		AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; };
-		AB573DC4217605E400D389A2 /* gl.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB573DC3217605E400D389A2 /* gl.mm */; };
 		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 */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = "<group>"; };
+		1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = rendertarget.mm; sourceTree = "<group>"; };
+		1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOSurface.framework; path = System/Library/Frameworks/IOSurface.framework; sourceTree = SDKROOT; };
+		1A3E5EAD23E9FB1300EDE661 /* cgl.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cgl.mm; sourceTree = "<group>"; };
+		1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
+		1A465D0F246AB61600C5858B /* dnd.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = dnd.mm; sourceTree = "<group>"; };
+		37155CE3233C00EB0034DCE9 /* menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = menu.h; sourceTree = "<group>"; };
 		379860FE214DA0C000CD0246 /* KeyTransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeyTransform.h; sourceTree = "<group>"; };
 		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>"; };
@@ -30,12 +44,12 @@
 		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>"; };
+		520624B222973F4100C4DCEF /* menu.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = menu.mm; sourceTree = "<group>"; };
 		5B21A981216530F500CEE36E /* cursor.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = cursor.mm; sourceTree = "<group>"; };
 		5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = clipboard.mm; sourceTree = "<group>"; };
 		5BF943652167AD1D009CAE35 /* cursor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cursor.h; sourceTree = "<group>"; };
 		AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; };
 		AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; };
-		AB573DC3217605E400D389A2 /* gl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = gl.mm; sourceTree = "<group>"; };
 		AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
 		AB661C1F2148286E00291242 /* window.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = window.mm; sourceTree = "<group>"; };
 		AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
@@ -48,6 +62,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				1A3E5EB023E9FE8300EDE661 /* QuartzCore.framework in Frameworks */,
+				1A3E5EAA23E9F26C00EDE661 /* IOSurface.framework in Frameworks */,
 				AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */,
 				AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */,
 			);
@@ -59,6 +75,8 @@
 		AB661C1C2148230E00291242 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				1A3E5EAF23E9FE8300EDE661 /* QuartzCore.framework */,
+				1A3E5EA923E9F26C00EDE661 /* IOSurface.framework */,
 				AB1E522B217613570091CD71 /* OpenGL.framework */,
 				AB661C1D2148230F00291242 /* AppKit.framework */,
 			);
@@ -68,13 +86,15 @@
 		AB7A61E62147C814003C5833 = {
 			isa = PBXGroup;
 			children = (
+				1A002B9D232135EE00021753 /* app.mm */,
 				37DDA9B121933371002E132B /* AvnString.h */,
 				37DDA9AF219330F8002E132B /* AvnString.mm */,
 				37A4E71A2178846A00EACBCD /* headers */,
-				AB573DC3217605E400D389A2 /* gl.mm */,
+				1A3E5EAD23E9FB1300EDE661 /* cgl.mm */,
 				5BF943652167AD1D009CAE35 /* cursor.h */,
 				5B21A981216530F500CEE36E /* cursor.mm */,
 				5B8BD94E215BFEA6005ED2A7 /* clipboard.mm */,
+				1A465D0F246AB61600C5858B /* dnd.mm */,
 				AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */,
 				AB661C212148288600291242 /* common.h */,
 				379860FE214DA0C000CD0246 /* KeyTransform.h */,
@@ -82,6 +102,9 @@
 				AB661C1F2148286E00291242 /* window.mm */,
 				37C09D8A21581EF2006A6758 /* window.h */,
 				AB00E4F62147CA920032A60A /* main.mm */,
+				37155CE3233C00EB0034DCE9 /* menu.h */,
+				520624B222973F4100C4DCEF /* menu.mm */,
+				1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */,
 				37A517B22159597E00FBA241 /* Screens.mm */,
 				37C09D8721580FE4006A6758 /* SystemDialogs.mm */,
 				AB7A61F02147C815003C5833 /* Products */,
@@ -104,6 +127,7 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				37155CE4233C00EB0034DCE9 /* menu.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -147,6 +171,7 @@
 			developmentRegion = English;
 			hasScannedForEncodings = 0;
 			knownRegions = (
+				English,
 				en,
 			);
 			mainGroup = AB7A61E62147C814003C5833;
@@ -164,15 +189,19 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				1A002B9E232135EE00021753 /* app.mm in Sources */,
 				5B8BD94F215BFEA6005ED2A7 /* clipboard.mm in Sources */,
 				5B21A982216530F500CEE36E /* cursor.mm in Sources */,
 				37DDA9B0219330F8002E132B /* AvnString.mm in Sources */,
 				AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */,
+				1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */,
+				1A3E5EAE23E9FB1300EDE661 /* cgl.mm in Sources */,
 				37E2330F21583241000CB7E2 /* KeyTransform.mm in Sources */,
+				520624B322973F4100C4DCEF /* menu.mm in Sources */,
 				37A517B32159597E00FBA241 /* Screens.mm in Sources */,
+				1A465D10246AB61600C5858B /* dnd.mm in Sources */,
 				AB00E4F72147CA920032A60A /* main.mm in Sources */,
 				37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */,
-				AB573DC4217605E400D389A2 /* gl.mm in Sources */,
 				AB661C202148286E00291242 /* window.mm in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;

+ 8 - 0
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>IDEDidComputeMac32BitWarning</key>
+	<true/>
+</dict>
+</plist>

+ 1 - 5
native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/xcshareddata/xcschemes/Avalonia.Native.OSX.xcscheme

@@ -29,8 +29,6 @@
       shouldUseLaunchSchemeArgsEnv = "YES">
       <Testables>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -58,12 +56,10 @@
       </MacroExpansion>
       <CommandLineArguments>
          <CommandLineArgument
-            argument = "bin/Debug/netcoreapp2.0/ControlCatalog.NetCore.dll"
+            argument = "bin/Debug/netcoreapp3.1/ControlCatalog.NetCore.dll"
             isEnabled = "YES">
          </CommandLineArgument>
       </CommandLineArguments>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"

+ 3 - 1
native/Avalonia.Native/src/OSX/AvnString.h

@@ -10,5 +10,7 @@
 #define AvnString_h
 
 extern IAvnString* CreateAvnString(NSString* string);
-
+extern IAvnStringArray* CreateAvnStringArray(NSArray<NSString*>* array);
+extern IAvnStringArray* CreateAvnStringArray(NSString* string);
+extern IAvnString* CreateByteArray(void* data, int len);
 #endif /* AvnString_h */

+ 61 - 0
native/Avalonia.Native/src/OSX/AvnString.mm

@@ -7,6 +7,7 @@
 //
 
 #include "common.h"
+#include <vector>
 
 class AvnStringImpl : public virtual ComSingleObject<IAvnString, &IID_IAvnString>
 {
@@ -28,6 +29,13 @@ public:
         memcpy((void*)_cstring, (void*)cstring, _length);
     }
     
+    AvnStringImpl(void*ptr, int len)
+    {
+        _length = len;
+        _cstring = (const char*)malloc(_length);
+        memcpy((void*)_cstring, ptr, len);
+    }
+    
     virtual ~AvnStringImpl()
     {
         free((void*)_cstring);
@@ -61,7 +69,60 @@ public:
     }
 };
 
+class AvnStringArrayImpl : public virtual ComSingleObject<IAvnStringArray, &IID_IAvnStringArray>
+{
+private:
+    std::vector<ComPtr<IAvnString>> _list;
+public:
+    FORWARD_IUNKNOWN()
+    AvnStringArrayImpl(NSArray<NSString*>* array)
+    {
+        for(int c = 0; c < [array count]; c++)
+        {
+            ComPtr<IAvnString> s;
+            *s.getPPV() = new AvnStringImpl([array objectAtIndex:c]);
+            _list.push_back(s);
+        }
+    }
+    
+    AvnStringArrayImpl(NSString* string)
+    {
+        ComPtr<IAvnString> s;
+        *s.getPPV() = new AvnStringImpl(string);
+        _list.push_back(s);
+    }
+    
+    virtual unsigned int GetCount() override
+    {
+        return (unsigned int)_list.size();
+    }
+    
+    virtual HRESULT Get(unsigned int index, IAvnString**ppv) override
+    {
+        if(_list.size() <= index)
+            return E_INVALIDARG;
+        *ppv = _list[index].getRetainedReference();
+        return S_OK;
+    }
+};
+
 IAvnString* CreateAvnString(NSString* string)
 {
     return new AvnStringImpl(string);
 }
+
+
+IAvnStringArray* CreateAvnStringArray(NSArray<NSString*> * array)
+{
+    return new AvnStringArrayImpl(array);
+}
+
+IAvnStringArray* CreateAvnStringArray(NSString* string)
+{
+    return new AvnStringArrayImpl(string);
+}
+
+IAvnString* CreateByteArray(void* data, int len)
+{
+    return new AvnStringImpl(data, len);
+}

+ 0 - 3
native/Avalonia.Native/src/OSX/KeyTransform.h

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #ifndef keytransform_h
 #define keytransform_h
 #include "common.h"

+ 0 - 3
native/Avalonia.Native/src/OSX/KeyTransform.mm

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "KeyTransform.h"
 
 const int kVK_ANSI_A = 0x00;

+ 2 - 3
native/Avalonia.Native/src/OSX/Screens.mm

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "common.h"
 
 class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens>
@@ -38,6 +35,8 @@ class Screens : public ComSingleObject<IAvnScreens, &IID_IAvnScreens>
             ret->WorkingArea.Height = [screen visibleFrame].size.height;
             ret->WorkingArea.Width = [screen visibleFrame].size.width;
             
+            ret->PixelDensity = [screen backingScaleFactor];
+            
             ret->Primary = index == 0;
             
             return S_OK;

+ 3 - 3
native/Avalonia.Native/src/OSX/SystemDialogs.mm

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "common.h"
 #include "window.h"
 
@@ -23,6 +20,7 @@ public:
             
             if(title != nullptr)
             {
+                panel.message = [NSString stringWithUTF8String:title];
                 panel.title = [NSString stringWithUTF8String:title];
             }
             
@@ -97,6 +95,7 @@ public:
             
             if(title != nullptr)
             {
+                panel.message = [NSString stringWithUTF8String:title];
                 panel.title = [NSString stringWithUTF8String:title];
             }
             
@@ -185,6 +184,7 @@ public:
             
             if(title != nullptr)
             {
+                panel.message = [NSString stringWithUTF8String:title];
                 panel.title = [NSString stringWithUTF8String:title];
             }
             

+ 37 - 0
native/Avalonia.Native/src/OSX/app.mm

@@ -0,0 +1,37 @@
+#include "common.h"
+@interface AvnAppDelegate : NSObject<NSApplicationDelegate>
+@end
+
+NSApplicationActivationPolicy AvnDesiredActivationPolicy = NSApplicationActivationPolicyRegular;
+
+@implementation AvnAppDelegate
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
+{
+    if([[NSApplication sharedApplication] activationPolicy] != AvnDesiredActivationPolicy)
+    {
+        for (NSRunningApplication * app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.dock"]) {
+            [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+            break;
+        }
+        
+        [[NSApplication sharedApplication] setActivationPolicy: AvnDesiredActivationPolicy];
+        
+        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"NSFullScreenMenuItemEverywhere"];
+        
+        [[NSApplication sharedApplication] setHelpMenu: [[NSMenu new] initWithTitle:@""]];
+    }
+}
+
+- (void)applicationDidFinishLaunching:(NSNotification *)notification
+{
+    [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+}
+
+@end
+
+extern void InitializeAvnApp()
+{
+    NSApplication* app = [NSApplication sharedApplication];
+    id delegate = [AvnAppDelegate new];
+    [app setDelegate:delegate];
+}

+ 166 - 0
native/Avalonia.Native/src/OSX/cgl.mm

@@ -0,0 +1,166 @@
+#include "common.h"
+#include <dlfcn.h>
+
+static CGLContextObj CreateCglContext(CGLContextObj share)
+{
+    int attributes[] = {
+        kCGLPFAAccelerated,
+        kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute)kCGLOGLPVersion_3_2_Core,
+        kCGLPFADepthSize, 8,
+        kCGLPFAStencilSize, 8,
+        kCGLPFAColorSize, 32,
+        0
+    };
+    
+    CGLPixelFormatObj pix;
+    CGLError errorCode;
+    GLint num; // stores the number of possible pixel formats
+    errorCode = CGLChoosePixelFormat( (CGLPixelFormatAttribute*)attributes, &pix, &num );
+    if(errorCode != 0)
+        return nil;
+    CGLContextObj ctx = nil;
+    errorCode = CGLCreateContext(pix, share, &ctx );
+    CGLDestroyPixelFormat( pix );
+    if(errorCode != 0)
+        return nil;
+    return ctx;
+};
+
+
+
+class AvnGlContext : public virtual ComSingleObject<IAvnGlContext, &IID_IAvnGlContext>
+{
+    // Debug
+    int _usageCount = 0;
+public:
+    CGLContextObj Context;
+    int SampleCount = 0, StencilBits = 0;
+    FORWARD_IUNKNOWN()
+    
+    class SavedGlContext : public virtual ComUnknownObject
+    {
+        CGLContextObj _savedContext;
+        ComPtr<AvnGlContext> _parent;
+    public:
+        SavedGlContext(CGLContextObj saved, AvnGlContext* parent)
+        {
+            _savedContext = saved;
+            _parent = parent;
+            _parent->_usageCount++;
+        }
+        
+        ~SavedGlContext()
+        {
+            if(_parent->Context == CGLGetCurrentContext())
+                CGLSetCurrentContext(_savedContext);
+            _parent->_usageCount--;
+            CGLUnlockContext(_parent->Context);
+        }
+    };
+    
+    AvnGlContext(CGLContextObj context)
+    {
+        Context = context;
+        CGLPixelFormatObj fmt = CGLGetPixelFormat(context);
+        CGLDescribePixelFormat(fmt, 0, kCGLPFASamples, &SampleCount);
+        CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &StencilBits);
+        
+    }
+    
+    virtual HRESULT LegacyMakeCurrent() override
+    {
+        if(CGLSetCurrentContext(Context) != 0)
+            return E_FAIL;
+        return S_OK;
+    }
+    
+    virtual HRESULT MakeCurrent(IUnknown** ppv) override
+    {
+        CGLContextObj saved = CGLGetCurrentContext();
+        CGLLockContext(Context);
+        if(CGLSetCurrentContext(Context) != 0)
+        {
+            CGLUnlockContext(Context);
+            return E_FAIL;
+        }
+        *ppv = new SavedGlContext(saved, this);
+        
+        return S_OK;
+    }
+    
+    virtual int GetSampleCount() override
+    {
+        return SampleCount;
+    }
+    
+    virtual int GetStencilSize() override
+    {
+        return StencilBits;
+    }
+    
+    virtual void* GetNativeHandle() override
+    {
+        return Context;
+    }
+    
+    ~AvnGlContext()
+    {
+        CGLReleaseContext(Context);
+    }
+};
+
+class AvnGlDisplay : public virtual ComSingleObject<IAvnGlDisplay, &IID_IAvnGlDisplay>
+{
+    void* _libgl;
+    
+public:
+    FORWARD_IUNKNOWN()
+    
+    AvnGlDisplay()
+    {
+        _libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", RTLD_LAZY);
+    }
+    
+    virtual void* GetProcAddress(char* proc)  override
+    {
+        return dlsym(_libgl, proc);
+    }
+    
+    virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) override
+    {
+        CGLContextObj shareContext = nil;
+        if(share != nil)
+        {
+            AvnGlContext* shareCtx = dynamic_cast<AvnGlContext*>(share);
+            if(shareCtx != nil)
+                shareContext = shareCtx->Context;
+        }
+        CGLContextObj ctx = ::CreateCglContext(shareContext);
+        if(ctx == nil)
+            return E_FAIL;
+        *ppv = new AvnGlContext(ctx);
+        return S_OK;
+    }
+    
+    virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) override
+    {
+        if(native == nil)
+            return E_INVALIDARG;
+        *ppv = new AvnGlContext((CGLContextObj) native);
+        return S_OK;
+    }
+    
+    virtual void LegacyClearCurrentContext() override
+    {
+        CGLSetCurrentContext(nil);
+    }
+};
+
+static IAvnGlDisplay* GlDisplay = new AvnGlDisplay();
+
+
+extern IAvnGlDisplay* GetGlDisplay()
+{
+    return GlDisplay;
+};
+

+ 110 - 17
native/Avalonia.Native/src/OSX/clipboard.mm

@@ -1,21 +1,29 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "common.h"
 #include "AvnString.h"
 
 class Clipboard : public ComSingleObject<IAvnClipboard, &IID_IAvnClipboard>
 {
+private:
+    NSPasteboard* _pb;
+    NSPasteboardItem* _item;
 public:
     FORWARD_IUNKNOWN()
     
-    Clipboard()
+    Clipboard(NSPasteboard* pasteboard, NSPasteboardItem* item)
     {
-        NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-        [pasteBoard stringForType:NSPasteboardTypeString];
+        if(pasteboard == nil && item == nil)
+            pasteboard = [NSPasteboard generalPasteboard];
+
+        _pb = pasteboard;
+        _item = item;
     }
     
-    virtual HRESULT GetText (IAvnString**ppv) override
+    NSPasteboardItem* TryGetItem()
+    {
+        return _item;
+    }
+   
+    virtual HRESULT GetText (char* type, IAvnString**ppv) override
     {
         @autoreleasepool
         {
@@ -23,39 +31,124 @@ public:
             {
                 return E_POINTER;
             }
+            NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+            NSString* string = _item == nil ? [_pb stringForType:typeString] : [_item stringForType:typeString];
             
-            *ppv = CreateAvnString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]);
+            *ppv = CreateAvnString(string);
             
             return S_OK;
         }
     }
     
-    virtual HRESULT SetText (void* utf8String) override
+    virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override
     {
         @autoreleasepool
         {
-            NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-            [pasteBoard clearContents];
-            [pasteBoard setString:[NSString stringWithUTF8String:(const char*)utf8String] forType:NSPasteboardTypeString];
+            *ppv= nil;
+            NSString* typeString = [NSString stringWithUTF8String:(const char*)type];
+            NSObject* data = _item == nil ? [_pb propertyListForType: typeString] : [_item propertyListForType: typeString];
+            if(data == nil)
+                return S_OK;
+            
+            if([data isKindOfClass: [NSString class]])
+            {
+                *ppv = CreateAvnStringArray((NSString*) data);
+                return S_OK;
+            }
+            
+            NSArray* arr = (NSArray*)data;
+            
+            for(int c = 0; c < [arr count]; c++)
+                if(![[arr objectAtIndex:c] isKindOfClass:[NSString class]])
+                    return E_INVALIDARG;
+            
+            *ppv = CreateAvnStringArray(arr);
+            return S_OK;
+        }
+    }
+    
+    virtual HRESULT SetText (char* type, void* utf8String) override
+    {
+        Clear();
+        @autoreleasepool
+        {
+            auto string = [NSString stringWithUTF8String:(const char*)utf8String];
+            auto typeString = [NSString stringWithUTF8String:(const char*)type];
+            if(_item == nil)
+                [_pb setString: string forType: typeString];
+            else
+                [_item setString: string forType:typeString];
         }
         
         return S_OK;
     }
+    
+    virtual HRESULT SetBytes(char* type, void* bytes, int len) override
+    {
+        auto typeString = [NSString stringWithUTF8String:(const char*)type];
+        auto data = [NSData dataWithBytes:bytes length:len];
+        if(_item == nil)
+            [_pb setData:data forType:typeString];
+        else
+            [_item setData:data forType:typeString];
+        return S_OK;
+    }
+       
+    virtual HRESULT GetBytes(char* type, IAvnString**ppv) override
+    {
+        *ppv = nil;
+        auto typeString = [NSString stringWithUTF8String:(const char*)type];
+        NSData*data;
+        @try
+        {
+            if(_item)
+                data = [_item dataForType:typeString];
+            else
+                data = [_pb dataForType:typeString];
+            if(data == nil)
+                return E_FAIL;
+        }
+        @catch(NSException* e)
+        {
+            return E_FAIL;
+        }
+        *ppv = CreateByteArray((void*)data.bytes, (int)data.length);
+        return S_OK;
+    }
+
 
     virtual HRESULT Clear() override
     {
         @autoreleasepool
         {
-            NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
-            [pasteBoard clearContents];
-            [pasteBoard setString:@"" forType:NSPasteboardTypeString];
+            if(_item != nil)
+                _item = [NSPasteboardItem new];
+            else
+            {
+                [_pb clearContents];
+                [_pb setString:@"" forType:NSPasteboardTypeString];
+            }
         }
         
         return S_OK;
     }
+    
+    virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
+    {
+        *ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
+        return S_OK;
+    }
 };
 
-extern IAvnClipboard* CreateClipboard()
+extern IAvnClipboard* CreateClipboard(NSPasteboard* pb, NSPasteboardItem* item)
+{
+    return new Clipboard(pb, item);
+}
+
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*cb)
 {
-    return new Clipboard();
+    auto clipboard = dynamic_cast<Clipboard*>(cb);
+    if(clipboard == nil)
+        return nil;
+    return clipboard->TryGetItem();
 }

+ 23 - 9
native/Avalonia.Native/src/OSX/common.h

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #ifndef common_h
 #define common_h
 #include "comimpl.h"
@@ -11,20 +8,32 @@
 #include <pthread.h>
 
 extern IAvnPlatformThreadingInterface* CreatePlatformThreading();
-extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events);
-extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events);
+extern void FreeAvnGCHandle(void* handle);
+extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl);
+extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl);
 extern IAvnSystemDialogs* CreateSystemDialogs();
 extern IAvnScreens* CreateScreens();
-extern IAvnClipboard* CreateClipboard();
+extern IAvnClipboard* CreateClipboard(NSPasteboard*, NSPasteboardItem*);
+extern NSPasteboardItem* TryGetPasteboardItem(IAvnClipboard*);
+extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle);
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject<NSDraggingInfo>* info);
+extern NSString* GetAvnCustomDataType();
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop);
 extern IAvnCursorFactory* CreateCursorFactory();
-extern IAvnGlFeature* GetGlFeature();
-extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view);
+extern IAvnGlDisplay* GetGlDisplay();
+extern IAvnMenu* CreateAppMenu(IAvnMenuEvents* events);
+extern IAvnMenuItem* CreateAppMenuItem();
+extern IAvnMenuItem* CreateAppMenuItemSeperator();
+extern void SetAppMenu (NSString* appName, IAvnMenu* appMenu);
+extern IAvnMenu* GetAppMenu ();
+extern NSMenuItem* GetAppMenuItem ();
 
+extern void InitializeAvnApp();
+extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;
 extern NSPoint ToNSPoint (AvnPoint p);
 extern AvnPoint ToAvnPoint (NSPoint p);
 extern AvnPoint ConvertPointY (AvnPoint p);
 extern NSSize ToNSSize (AvnSize s);
-
 #ifdef DEBUG
 #define NSDebugLog(...) NSLog(__VA_ARGS__)
 #else
@@ -40,4 +49,9 @@ template<typename T> inline T* objc_cast(id from) {
     return nil;
 }
 
+@interface ActionCallback : NSObject
+- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback;
+- (void) action;
+@end
+
 #endif

+ 0 - 3
native/Avalonia.Native/src/OSX/cursor.h

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #ifndef cursor_h
 #define cursor_h
 

+ 0 - 3
native/Avalonia.Native/src/OSX/cursor.mm

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "common.h"
 #include "cursor.h"
 #include <map>

+ 89 - 0
native/Avalonia.Native/src/OSX/dnd.mm

@@ -0,0 +1,89 @@
+#include "common.h"
+
+extern AvnDragDropEffects ConvertDragDropEffects(NSDragOperation nsop)
+{
+    int effects = 0;
+    if((nsop & NSDragOperationCopy) != 0)
+        effects |= (int)AvnDragDropEffects::Copy;
+    if((nsop & NSDragOperationMove) != 0)
+        effects |= (int)AvnDragDropEffects::Move;
+    if((nsop & NSDragOperationLink) != 0)
+        effects |= (int)AvnDragDropEffects::Link;
+    return (AvnDragDropEffects)effects;
+};
+
+extern NSString* GetAvnCustomDataType()
+{
+    char buffer[256];
+    sprintf(buffer, "net.avaloniaui.inproc.uti.n%in", getpid());
+    return [NSString stringWithUTF8String:buffer];
+}
+
+@interface AvnDndSource : NSObject<NSDraggingSource>
+
+@end
+
+@implementation AvnDndSource
+{
+    NSDragOperation _operation;
+    ComPtr<IAvnDndResultCallback> _cb;
+    void* _sourceHandle;
+};
+
+- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
+{
+    return NSDragOperationCopy;
+}
+
+- (AvnDndSource*) initWithOperation: (NSDragOperation)operation
+                        andCallback: (IAvnDndResultCallback*) cb
+                    andSourceHandle: (void*) handle
+{
+    self = [super init];
+    _operation = operation;
+    _cb = cb;
+    _sourceHandle = handle;
+    return self;
+}
+
+- (void)draggingSession:(NSDraggingSession *)session
+           endedAtPoint:(NSPoint)screenPoint
+              operation:(NSDragOperation)operation
+{
+    if(_cb != nil)
+    {
+        auto cb = _cb;
+        _cb = nil;
+        cb->OnDragAndDropComplete(ConvertDragDropEffects(operation));
+    }
+    if(_sourceHandle != nil)
+    {
+        FreeAvnGCHandle(_sourceHandle);
+        _sourceHandle = nil;
+    }
+}
+
+- (void*) gcHandle
+{
+    return _sourceHandle;
+}
+
+@end
+
+extern NSObject<NSDraggingSource>* CreateDraggingSource(NSDragOperation op, IAvnDndResultCallback* cb, void* handle)
+{
+    return [[AvnDndSource alloc] initWithOperation:op andCallback:cb andSourceHandle:handle];
+};
+
+extern void* GetAvnDataObjectHandleFromDraggingInfo(NSObject<NSDraggingInfo>* info)
+{
+    id obj = [info draggingSource];
+    if(obj == nil)
+        return nil;
+    if([obj isKindOfClass: [AvnDndSource class]])
+    {
+        auto src = (AvnDndSource*)obj;
+        return [src gcHandle];
+    }
+    return nil;
+}

+ 0 - 253
native/Avalonia.Native/src/OSX/gl.mm

@@ -1,253 +0,0 @@
-#include "common.h"
-#include <OpenGL/gl.h>
-#include <dlfcn.h>
-
-template <typename T, size_t N> char (&ArrayCounter(T (&a)[N]))[N];
-#define ARRAY_COUNT(a) (sizeof(ArrayCounter(a)))
-
-NSOpenGLPixelFormat* CreateFormat()
-{
-    NSOpenGLPixelFormatAttribute attribs[] =
-    {
-        NSOpenGLPFADoubleBuffer,
-        NSOpenGLPFAColorSize, 32,
-        NSOpenGLPFAStencilSize, 8,
-        NSOpenGLPFADepthSize, 8,
-        0
-    };
-    return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
-}
-
-class AvnGlContext : public virtual ComSingleObject<IAvnGlContext, &IID_IAvnGlContext>
-{
-public:
-    FORWARD_IUNKNOWN()
-    NSOpenGLContext* GlContext;
-    GLuint Framebuffer, RenderBuffer, StencilBuffer;
-    AvnGlContext(NSOpenGLContext* gl, bool offscreen)
-    {
-        Framebuffer = 0;
-        RenderBuffer = 0;
-        StencilBuffer = 0;
-        GlContext = gl;
-        if(offscreen)
-        {
-            [GlContext makeCurrentContext];
-
-            glGenFramebuffersEXT(1, &Framebuffer);
-            glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer);
-            glGenRenderbuffersEXT(1, &RenderBuffer);
-            glGenRenderbuffersEXT(1, &StencilBuffer);
-
-            glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer);
-            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer);
-            glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer);
-            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer);
-        }
-        
-    }
-    
-    
-    virtual HRESULT MakeCurrent()  override
-    {
-        [GlContext makeCurrentContext];/*
-        glBindFramebufferEXT(GL_FRAMEBUFFER, Framebuffer);
-        glBindRenderbufferEXT(GL_RENDERBUFFER, RenderBuffer);
-        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, RenderBuffer);
-        glBindRenderbufferEXT(GL_RENDERBUFFER, StencilBuffer);
-        glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, StencilBuffer);*/
-        return S_OK;
-    }
-};
-
-class AvnGlDisplay : public virtual ComSingleObject<IAvnGlDisplay, &IID_IAvnGlDisplay>
-{
-    int _sampleCount, _stencilSize;
-    void* _libgl;
-    
-public:
-    FORWARD_IUNKNOWN()
-    
-    AvnGlDisplay(int sampleCount, int stencilSize)
-    {
-        _sampleCount = sampleCount;
-        _stencilSize = stencilSize;
-        _libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", RTLD_LAZY);
-    }
-    
-    virtual HRESULT GetSampleCount(int* ret)  override
-    {
-        *ret = _sampleCount;
-        return S_OK;
-    }
-    virtual HRESULT GetStencilSize(int* ret) override
-    {
-        *ret = _stencilSize;
-        return S_OK;
-    }
-    
-    virtual HRESULT ClearContext()  override
-    {
-        [NSOpenGLContext clearCurrentContext];
-        return S_OK;
-    }
-    
-    virtual void* GetProcAddress(char* proc)  override
-    {
-        return dlsym(_libgl, proc);
-    }
-};
-
-
-class GlFeature : public virtual ComSingleObject<IAvnGlFeature, &IID_IAvnGlFeature>
-{
-    IAvnGlDisplay* _display;
-    AvnGlContext *_immediate;
-    NSOpenGLContext* _shared;
-public:
-    FORWARD_IUNKNOWN()
-    NSOpenGLPixelFormat* _format;
-    GlFeature(IAvnGlDisplay* display, AvnGlContext* immediate, NSOpenGLPixelFormat* format)
-    {
-        _display = display;
-        _immediate = immediate;
-        _format = format;
-        _shared = [[NSOpenGLContext alloc] initWithFormat:_format shareContext:_immediate->GlContext];
-    }
-    
-    NSOpenGLContext* CreateContext()
-    {
-        return _shared;
-        //return [[NSOpenGLContext alloc] initWithFormat:_format shareContext:nil];
-    }
-    
-    virtual HRESULT ObtainDisplay(IAvnGlDisplay**retOut)  override
-    {
-        *retOut = _display;
-        _display->AddRef();
-        return S_OK;
-    }
-    
-    virtual HRESULT ObtainImmediateContext(IAvnGlContext**retOut)  override
-    {
-        *retOut = _immediate;
-        _immediate->AddRef();
-        return S_OK;
-    }
-};
-
-static GlFeature* Feature;
-
-GlFeature* CreateGlFeature()
-{
-    auto format = CreateFormat();
-    if(format == nil)
-    {
-        NSLog(@"Unable to choose pixel format");
-        return NULL;
-    }
-    
-    auto immediateContext = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];
-    if(immediateContext == nil)
-    {
-        NSLog(@"Unable to create NSOpenGLContext");
-        return NULL;
-    }
-
-    int stencilBits = 0, sampleCount = 0;
-    
-    auto fmt = CGLGetPixelFormat([immediateContext CGLContextObj]);
-    CGLDescribePixelFormat(fmt, 0, kCGLPFASamples, &sampleCount);
-    CGLDescribePixelFormat(fmt, 0, kCGLPFAStencilSize, &stencilBits);
-    
-    auto offscreen = new AvnGlContext(immediateContext, true);
-    auto display = new AvnGlDisplay(sampleCount, stencilBits);
-    
-    return new GlFeature(display, offscreen, format);
-}
-
-
-static GlFeature* GetFeature()
-{
-    if(Feature == nil)
-        Feature = CreateGlFeature();
-    return Feature;
-}
-
-extern IAvnGlFeature* GetGlFeature()
-{
-    return GetFeature();
-}
-
-class AvnGlRenderingSession : public ComSingleObject<IAvnGlSurfaceRenderingSession, &IID_IAvnGlSurfaceRenderingSession>
-{
-    NSView* _view;
-    NSWindow* _window;
-    NSOpenGLContext* _context;
-public:
-    FORWARD_IUNKNOWN()
-    AvnGlRenderingSession(NSWindow*window, NSView* view, NSOpenGLContext* context)
-    {
-        _context = context;
-        _window = window;
-        _view = view;
-    }
-    
-    virtual HRESULT GetPixelSize(AvnPixelSize* ret)  override
-    {
-        auto fsize = [_view convertSizeToBacking: [_view frame].size];
-        ret->Width = (int)fsize.width;
-        ret->Height = (int)fsize.height;
-        return S_OK;
-    }
-    virtual HRESULT GetScaling(double* ret)  override
-    {
-        *ret = [_window backingScaleFactor];
-        return S_OK;
-    }
-    
-    virtual ~AvnGlRenderingSession()
-    {
-        [_context flushBuffer];
-        [NSOpenGLContext clearCurrentContext];
-        CGLUnlockContext([_context CGLContextObj]);
-        [_view unlockFocus];
-    }
-};
-
-class AvnGlRenderTarget : public ComSingleObject<IAvnGlSurfaceRenderTarget, &IID_IAvnGlSurfaceRenderTarget>
-{
-    NSView* _view;
-    NSWindow* _window;
-    NSOpenGLContext* _context;
-public:
-    FORWARD_IUNKNOWN()
-    AvnGlRenderTarget(NSWindow* window, NSView*view)
-    {
-        _window = window;
-        _view = view;
-        _context = GetFeature()->CreateContext();
-    }
-    
-    virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret)  override
-    {
-        auto f = GetFeature();
-        if(f == NULL)
-            return E_FAIL;
-        if(![_view lockFocusIfCanDraw])
-            return E_ABORT;
-        
-        auto gl = _context;
-        CGLLockContext([_context CGLContextObj]);
-        [gl setView: _view];
-        [gl update];
-        [gl makeCurrentContext];
-        *ret = new AvnGlRenderingSession(_window, _view, gl);
-        return S_OK;
-    }
-};
-
-extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view)
-{
-    return new AvnGlRenderTarget(window, view);
-}

+ 157 - 23
native/Avalonia.Native/src/OSX/main.mm

@@ -1,31 +1,129 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 //This file will contain actual IID structures
 #define COM_GUIDS_MATERIALIZE
 #include "common.h"
 
-static BOOL ShowInDock = 1;
+static NSString* s_appTitle = @"Avalonia";
 
-static void SetActivationPolicy()
-{
-    [[NSApplication sharedApplication] setActivationPolicy: (ShowInDock ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory)];
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+void SetProcessName(NSString* appTitle) {
+    s_appTitle = appTitle;
+    
+    CFStringRef process_name = (__bridge CFStringRef)appTitle;
+    
+    if (!process_name || CFStringGetLength(process_name) == 0) {
+        //NOTREACHED() << "SetProcessName given bad name.";
+        return;
+    }
+    
+    if (![NSThread isMainThread]) {
+        //NOTREACHED() << "Should only set process name from main thread.";
+        return;
+    }
+    
+    // Warning: here be dragons! This is SPI reverse-engineered from WebKit's
+    // plugin host, and could break at any time (although realistically it's only
+    // likely to break in a new major release).
+    // When 10.7 is available, check that this still works, and update this
+    // comment for 10.8.
+    
+    // Private CFType used in these LaunchServices calls.
+    typedef CFTypeRef PrivateLSASN;
+    typedef PrivateLSASN (*LSGetCurrentApplicationASNType)();
+    typedef OSStatus (*LSSetApplicationInformationItemType)(int, PrivateLSASN,
+                                                            CFStringRef,
+                                                            CFStringRef,
+                                                            CFDictionaryRef*);
+    
+    static LSGetCurrentApplicationASNType ls_get_current_application_asn_func =
+    NULL;
+    static LSSetApplicationInformationItemType
+    ls_set_application_information_item_func = NULL;
+    static CFStringRef ls_display_name_key = NULL;
+    
+    static bool did_symbol_lookup = false;
+    if (!did_symbol_lookup) {
+        did_symbol_lookup = true;
+        CFBundleRef launch_services_bundle =
+        CFBundleGetBundleWithIdentifier(CFSTR("com.apple.LaunchServices"));
+        if (!launch_services_bundle) {
+            //LOG(ERROR) << "Failed to look up LaunchServices bundle";
+            return;
+        }
+        
+        ls_get_current_application_asn_func =
+        reinterpret_cast<LSGetCurrentApplicationASNType>(
+                                                         CFBundleGetFunctionPointerForName(
+                                                                                           launch_services_bundle, CFSTR("_LSGetCurrentApplicationASN")));
+        if (!ls_get_current_application_asn_func){}
+        //LOG(ERROR) << "Could not find _LSGetCurrentApplicationASN";
+        
+        ls_set_application_information_item_func =
+        reinterpret_cast<LSSetApplicationInformationItemType>(
+                                                              CFBundleGetFunctionPointerForName(
+                                                                                                launch_services_bundle,
+                                                                                                CFSTR("_LSSetApplicationInformationItem")));
+        if (!ls_set_application_information_item_func){}
+        //LOG(ERROR) << "Could not find _LSSetApplicationInformationItem";
+        
+        CFStringRef* key_pointer = reinterpret_cast<CFStringRef*>(
+                                                                  CFBundleGetDataPointerForName(launch_services_bundle,
+                                                                                                CFSTR("_kLSDisplayNameKey")));
+        ls_display_name_key = key_pointer ? *key_pointer : NULL;
+        if (!ls_display_name_key){}
+        //LOG(ERROR) << "Could not find _kLSDisplayNameKey";
+        
+        // Internally, this call relies on the Mach ports that are started up by the
+        // Carbon Process Manager.  In debug builds this usually happens due to how
+        // the logging layers are started up; but in release, it isn't started in as
+        // much of a defined order.  So if the symbols had to be loaded, go ahead
+        // and force a call to make sure the manager has been initialized and hence
+        // the ports are opened.
+        ProcessSerialNumber psn;
+        GetCurrentProcess(&psn);
+    }
+    if (!ls_get_current_application_asn_func ||
+        !ls_set_application_information_item_func ||
+        !ls_display_name_key) {
+        return;
+    }
+    
+    PrivateLSASN asn = ls_get_current_application_asn_func();
+    // Constant used by WebKit; what exactly it means is unknown.
+    const int magic_session_constant = -2;
+    
+    ls_set_application_information_item_func(magic_session_constant, asn,
+                                             ls_display_name_key,
+                                             process_name,
+                                             NULL /* optional out param */);
 }
 
 class MacOptions : public ComSingleObject<IAvnMacOptions, &IID_IAvnMacOptions>
 {
 public:
     FORWARD_IUNKNOWN()
+    
+    virtual HRESULT SetApplicationTitle(void* utf8String) override
+    {
+        auto appTitle = [NSString stringWithUTF8String:(const char*)utf8String];
+        
+        [[NSProcessInfo processInfo] setProcessName:appTitle];
+        
+        
+        SetProcessName(appTitle);
+        
+        return S_OK;
+    }
+    
     virtual HRESULT SetShowInDock(int show)  override
     {
-        ShowInDock = show;
-        SetActivationPolicy();
+        AvnDesiredActivationPolicy = show
+            ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
         return S_OK;
     }
 };
 
-
-
 /// See "Using POSIX Threads in a Cocoa Application" section here:
 /// https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/CreatingThreads/CreatingThreads.html#//apple_ref/doc/uid/20000738-125024
 @interface ThreadingInitializer : NSObject
@@ -50,22 +148,22 @@ public:
     close(_fds[0]);
     close(_fds[1]);
 }
-
-
 @end
 
-
+static ComPtr<IAvnGCHandleDeallocatorCallback> _deallocator;
 class AvaloniaNative : public ComSingleObject<IAvaloniaNativeFactory, &IID_IAvaloniaNativeFactory>
 {
     
 public:
     FORWARD_IUNKNOWN()
-    virtual HRESULT Initialize() override
+    virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator) override
     {
+        _deallocator = deallocator;
         @autoreleasepool{
             [[ThreadingInitializer new] do];
-            return S_OK;
         }
+        InitializeAvnApp();
+        return S_OK;
     };
     
     virtual IAvnMacOptions* GetMacOptions()  override
@@ -73,20 +171,20 @@ public:
         return (IAvnMacOptions*)new MacOptions();
     }
     
-    virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnWindow** ppv)  override
+    virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv)  override
     {
         if(cb == nullptr || ppv == nullptr)
             return E_POINTER;
-        *ppv = CreateAvnWindow(cb);
+        *ppv = CreateAvnWindow(cb, gl);
         return S_OK;
     };
     
-    virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnPopup** ppv) override
+    virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) override
     {
         if(cb == nullptr || ppv == nullptr)
             return E_POINTER;
         
-        *ppv = CreateAvnPopup(cb);
+        *ppv = CreateAvnPopup(cb, gl);
         return S_OK;
     }
     
@@ -110,7 +208,13 @@ public:
 
     virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
     {
-        *ppv = ::CreateClipboard ();
+        *ppv = ::CreateClipboard (nil, nil);
+        return S_OK;
+    }
+    
+    virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
+    {
+        *ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
         return S_OK;
     }
 
@@ -120,15 +224,39 @@ public:
         return S_OK;
     }
     
-    virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) override
+    virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) override
     {
-        auto rv = ::GetGlFeature();
+        auto rv = ::GetGlDisplay();
         if(rv == NULL)
             return E_FAIL;
         rv->AddRef();
         *ppv = rv;
         return S_OK;
     }
+    
+    virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) override
+    {
+        *ppv = ::CreateAppMenu(cb);
+        return S_OK;
+    }
+    
+    virtual HRESULT CreateMenuItem (IAvnMenuItem** ppv) override
+    {
+        *ppv = ::CreateAppMenuItem();
+        return S_OK;
+    }
+    
+    virtual HRESULT CreateMenuItemSeperator (IAvnMenuItem** ppv) override
+    {
+        *ppv = ::CreateAppMenuItemSeperator();
+        return S_OK;
+    }
+    
+    virtual HRESULT SetAppMenu (IAvnMenu* appMenu) override
+    {
+        ::SetAppMenu(s_appTitle, appMenu);
+        return S_OK;
+    }
 };
 
 extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
@@ -136,6 +264,12 @@ extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()
     return new AvaloniaNative();
 };
 
+extern void FreeAvnGCHandle(void* handle)
+{
+    if(_deallocator != nil)
+        _deallocator->FreeGCHandle(handle);
+}
+
 NSSize ToNSSize (AvnSize s)
 {
     NSSize result;

+ 94 - 0
native/Avalonia.Native/src/OSX/menu.h

@@ -0,0 +1,94 @@
+//
+//  menu.h
+//  Avalonia.Native.OSX
+//
+//  Created by Dan Walmsley on 01/08/2019.
+//  Copyright © 2019 Avalonia. All rights reserved.
+//
+
+#ifndef menu_h
+#define menu_h
+
+#include "common.h"
+
+class AvnAppMenuItem;
+class AvnAppMenu;
+
+@interface AvnMenu : NSMenu
+- (id) initWithDelegate: (NSObject<NSMenuDelegate>*) del;
+- (void) setHasGlobalMenuItem: (bool) value;
+- (bool) hasGlobalMenuItem;
+@end
+
+@interface AvnMenuItem : NSMenuItem
+- (id) initWithAvnAppMenuItem: (AvnAppMenuItem*)menuItem;
+- (void)didSelectItem:(id)sender;
+@end
+
+class AvnAppMenuItem : public ComSingleObject<IAvnMenuItem, &IID_IAvnMenuItem>
+{
+private:
+    NSMenuItem* _native; // here we hold a pointer to an AvnMenuItem
+    IAvnActionCallback* _callback;
+    IAvnPredicateCallback* _predicate;
+    bool _isSeperator;
+    bool _isCheckable;
+    
+public:
+    FORWARD_IUNKNOWN()
+    
+    AvnAppMenuItem(bool isSeperator);
+    
+    NSMenuItem* GetNative();
+    
+    virtual HRESULT SetSubMenu (IAvnMenu* menu) override;
+    
+    virtual HRESULT SetTitle (void* utf8String) override;
+    
+    virtual HRESULT SetGesture (void* key, AvnInputModifiers modifiers) override;
+    
+    virtual HRESULT SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback) override;
+    
+    virtual HRESULT SetIsChecked (bool isChecked) override;
+    
+    virtual HRESULT SetToggleType (AvnMenuItemToggleType toggleType) override;
+    
+    virtual HRESULT SetIcon (void* data, size_t length) override;
+    
+    bool EvaluateItemEnabled();
+    
+    void RaiseOnClicked();
+};
+
+
+class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu>
+{
+private:
+    AvnMenu* _native;
+    ComPtr<IAvnMenuEvents> _baseEvents;
+    
+public:
+    FORWARD_IUNKNOWN()
+    
+    AvnAppMenu(IAvnMenuEvents* events);
+        
+    AvnMenu* GetNative();
+    
+    void RaiseNeedsUpdate ();
+    
+    virtual HRESULT InsertItem (int index, IAvnMenuItem* item) override;
+    
+    virtual HRESULT RemoveItem (IAvnMenuItem* item) override;
+    
+    virtual HRESULT SetTitle (void* utf8String) override;
+    
+    virtual HRESULT Clear () override;
+};
+
+
+@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
+- (id) initWithParent: (AvnAppMenu*) parent;
+@end
+
+#endif
+

+ 469 - 0
native/Avalonia.Native/src/OSX/menu.mm

@@ -0,0 +1,469 @@
+
+#include "common.h"
+#include "menu.h"
+#include "window.h"
+
+@implementation AvnMenu
+{
+    bool _isReparented;
+    NSObject<NSMenuDelegate>* _wtf;
+}
+
+- (id) initWithDelegate: (NSObject<NSMenuDelegate>*)del
+{
+    self = [super init];
+    self.delegate = del;
+    _wtf = del;
+    _isReparented = false;
+    return self;
+}
+
+- (bool)hasGlobalMenuItem
+{
+    return _isReparented;
+}
+
+- (void)setHasGlobalMenuItem:(bool)value
+{
+    _isReparented = value;
+}
+
+@end
+
+@implementation AvnMenuItem
+{
+    AvnAppMenuItem* _item;
+}
+
+- (id) initWithAvnAppMenuItem: (AvnAppMenuItem*)menuItem
+{
+    if(self != nil)
+    {
+        _item = menuItem;
+        self = [super initWithTitle:@""
+                             action:@selector(didSelectItem:)
+                      keyEquivalent:@""];
+        
+        [self setEnabled:YES];
+        
+        [self setTarget:self];
+    }
+    
+    return self;
+}
+
+- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
+{
+    if([self submenu] != nil)
+    {
+        return YES;
+    }
+    
+    return _item->EvaluateItemEnabled();
+}
+
+- (void)didSelectItem:(nullable id)sender
+{
+    _item->RaiseOnClicked();
+}
+@end
+
+AvnAppMenuItem::AvnAppMenuItem(bool isSeperator)
+{
+    _isCheckable = false;
+    _isSeperator = isSeperator;
+    
+    if(isSeperator)
+    {
+        _native = [NSMenuItem separatorItem];
+    }
+    else
+    {
+        _native = [[AvnMenuItem alloc] initWithAvnAppMenuItem: this];
+    }
+    
+    _callback = nullptr;
+}
+
+NSMenuItem* AvnAppMenuItem::GetNative()
+{
+    return _native;
+}
+
+HRESULT AvnAppMenuItem::SetSubMenu (IAvnMenu* menu)
+{
+    @autoreleasepool
+    {
+        if(menu != nullptr)
+        {
+            auto nsMenu = dynamic_cast<AvnAppMenu*>(menu)->GetNative();
+            
+            [_native setSubmenu: nsMenu];
+        }
+        else
+        {
+            [_native setSubmenu: nullptr];
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetTitle (void* utf8String)
+{
+    @autoreleasepool
+    {
+        if (utf8String != nullptr)
+        {
+            [_native setTitle:[NSString stringWithUTF8String:(const char*)utf8String]];
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetGesture (void* key, AvnInputModifiers modifiers)
+{
+    @autoreleasepool
+    {
+        NSEventModifierFlags flags = 0;
+        
+        if (modifiers & Control)
+            flags |= NSEventModifierFlagControl;
+        if (modifiers & Shift)
+            flags |= NSEventModifierFlagShift;
+        if (modifiers & Alt)
+            flags |= NSEventModifierFlagOption;
+        if (modifiers & Windows)
+            flags |= NSEventModifierFlagCommand;
+        
+        [_native setKeyEquivalent:[NSString stringWithUTF8String:(const char*)key]];
+        [_native setKeyEquivalentModifierMask:flags];
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback)
+{
+    @autoreleasepool
+    {
+        _predicate = predicate;
+        _callback = callback;
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetIsChecked (bool isChecked)
+{
+    @autoreleasepool
+    {
+        [_native setState:(isChecked && _isCheckable ? NSOnState : NSOffState)];
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType)
+{
+    @autoreleasepool
+    {
+        switch(toggleType)
+        {
+            case AvnMenuItemToggleType::None:
+                [_native setOnStateImage: [NSImage imageNamed:@"NSMenuCheckmark"]];
+                
+                _isCheckable = false;
+                break;
+                
+            case AvnMenuItemToggleType::CheckMark:
+                [_native setOnStateImage: [NSImage imageNamed:@"NSMenuCheckmark"]];
+                
+                _isCheckable = true;
+                break;
+                
+            case AvnMenuItemToggleType::Radio:
+                [_native setOnStateImage: [NSImage imageNamed:@"NSMenuItemBullet"]];
+                
+                _isCheckable = true;
+                break;
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenuItem::SetIcon(void *data, size_t length)
+{
+    @autoreleasepool
+    {
+        if(data != nullptr)
+        {
+            NSData *imageData = [NSData dataWithBytes:data length:length];
+            NSImage *image = [[NSImage alloc] initWithData:imageData];
+            
+            NSSize originalSize = [image size];
+             
+            NSSize size;
+            size.height = [[NSFont menuFontOfSize:0] pointSize] * 1.333333;
+            
+            auto scaleFactor = size.height / originalSize.height;
+            size.width = originalSize.width * scaleFactor;
+            
+            [image setSize: size];
+            [_native setImage:image];
+        }
+        else
+        {
+            [_native setImage:nullptr];
+        }
+        return S_OK;
+    }
+}
+
+bool AvnAppMenuItem::EvaluateItemEnabled()
+{
+    if(_predicate != nullptr)
+    {
+        auto result = _predicate->Evaluate ();
+        
+        return result;
+    }
+    
+    return false;
+}
+
+void AvnAppMenuItem::RaiseOnClicked()
+{
+    if(_callback != nullptr)
+    {
+        _callback->Run();
+    }
+}
+
+AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
+{
+    _baseEvents = events;
+    id del = [[AvnMenuDelegate alloc] initWithParent: this];
+    _native = [[AvnMenu alloc] initWithDelegate: del];
+}
+
+
+AvnMenu* AvnAppMenu::GetNative()
+{
+    return _native;
+}
+
+void AvnAppMenu::RaiseNeedsUpdate()
+{
+    if(_baseEvents != nullptr)
+    {
+        _baseEvents->NeedsUpdate();
+    }
+}
+
+HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
+{
+    @autoreleasepool
+    {
+        if([_native hasGlobalMenuItem])
+        {
+            index++;
+        }
+        
+        auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item);
+        
+        if(avnMenuItem != nullptr)
+        {
+            [_native insertItem: avnMenuItem->GetNative() atIndex:index];
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenu::RemoveItem (IAvnMenuItem* item)
+{
+    @autoreleasepool
+    {
+        auto avnMenuItem = dynamic_cast<AvnAppMenuItem*>(item);
+        
+        if(avnMenuItem != nullptr)
+        {
+            [_native removeItem:avnMenuItem->GetNative()];
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenu::SetTitle (void* utf8String)
+{
+    @autoreleasepool
+    {
+        if (utf8String != nullptr)
+        {
+            [_native setTitle:[NSString stringWithUTF8String:(const char*)utf8String]];
+        }
+        
+        return S_OK;
+    }
+}
+
+HRESULT AvnAppMenu::Clear()
+{
+    @autoreleasepool
+    {
+        [_native removeAllItems];
+        return S_OK;
+    }
+}
+
+@implementation AvnMenuDelegate
+{
+    ComPtr<AvnAppMenu> _parent;
+}
+- (id) initWithParent:(AvnAppMenu *)parent
+{
+    self = [super init];
+    _parent = parent;
+    return self;
+}
+- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
+{
+    if(shouldCancel)
+        return NO;
+    return YES;
+}
+
+- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
+{
+    return [menu numberOfItems];
+}
+
+- (void)menuNeedsUpdate:(NSMenu *)menu
+{
+    _parent->RaiseNeedsUpdate();
+}
+
+
+@end
+
+extern IAvnMenu* CreateAppMenu(IAvnMenuEvents* cb)
+{
+    @autoreleasepool
+    {
+        return new AvnAppMenu(cb);
+    }
+}
+
+extern IAvnMenuItem* CreateAppMenuItem()
+{
+    @autoreleasepool
+    {
+        return new AvnAppMenuItem(false);
+    }
+}
+
+extern IAvnMenuItem* CreateAppMenuItemSeperator()
+{
+    @autoreleasepool
+    {
+        return new AvnAppMenuItem(true);
+    }
+}
+
+static IAvnMenu* s_appMenu = nullptr;
+static NSMenuItem* s_appMenuItem = nullptr;
+
+extern void SetAppMenu (NSString* appName, IAvnMenu* menu)
+{
+    s_appMenu = menu;
+    
+    if(s_appMenu != nullptr)
+    {
+        auto nativeMenu = dynamic_cast<AvnAppMenu*>(s_appMenu);
+        
+        auto currentMenu = [s_appMenuItem menu];
+        
+        if (currentMenu != nullptr)
+        {
+            [currentMenu removeItem:s_appMenuItem];
+        }
+        
+        s_appMenuItem = [nativeMenu->GetNative() itemAtIndex:0];
+        
+        if (currentMenu == nullptr)
+        {
+            currentMenu = [s_appMenuItem menu];
+        }
+        
+        [[s_appMenuItem menu] removeItem:s_appMenuItem];
+        
+        [currentMenu insertItem:s_appMenuItem atIndex:0];
+        
+        if([s_appMenuItem submenu] == nullptr)
+        {
+            [s_appMenuItem setSubmenu:[NSMenu new]];
+        }
+        
+        auto appMenu  = [s_appMenuItem submenu];
+        
+        [appMenu addItem:[NSMenuItem separatorItem]];
+        
+        // Services item and menu
+        auto servicesItem = [[NSMenuItem alloc] init];
+        servicesItem.title = @"Services";
+        NSMenu *servicesMenu = [[NSMenu alloc] initWithTitle:@"Services"];
+        servicesItem.submenu = servicesMenu;
+        [NSApplication sharedApplication].servicesMenu = servicesMenu;
+        [appMenu addItem:servicesItem];
+        
+        [appMenu addItem:[NSMenuItem separatorItem]];
+        
+        // Hide Application
+        auto hideItem = [[NSMenuItem alloc] initWithTitle:[@"Hide " stringByAppendingString:appName] action:@selector(hide:) keyEquivalent:@"h"];
+        
+        [appMenu addItem:hideItem];
+        
+        // Hide Others
+        auto hideAllOthersItem = [[NSMenuItem alloc] initWithTitle:@"Hide Others"
+                                                       action:@selector(hideOtherApplications:)
+                                                keyEquivalent:@"h"];
+        
+        hideAllOthersItem.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption;
+        [appMenu addItem:hideAllOthersItem];
+        
+        // Show All
+        auto showAllItem = [[NSMenuItem alloc] initWithTitle:@"Show All"
+                                                 action:@selector(unhideAllApplications:)
+                                          keyEquivalent:@""];
+        
+        [appMenu addItem:showAllItem];
+        
+        [appMenu addItem:[NSMenuItem separatorItem]];
+        
+        // Quit Application
+        auto quitItem = [[NSMenuItem alloc] init];
+        quitItem.title = [@"Quit " stringByAppendingString:appName];
+        quitItem.keyEquivalent = @"q";
+        quitItem.target = [AvnWindow class];
+        quitItem.action = @selector(closeAll);
+        [appMenu addItem:quitItem];
+    }
+    else
+    {
+        s_appMenuItem = nullptr;
+    }
+}
+
+extern IAvnMenu* GetAppMenu ()
+{
+    return s_appMenu;
+}
+
+extern NSMenuItem* GetAppMenuItem ()
+{
+    return s_appMenuItem;
+}
+
+

+ 39 - 36
native/Avalonia.Native/src/OSX/platformthreading.mm

@@ -1,6 +1,3 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #include "common.h"
 
 class PlatformThreadingInterface;
@@ -10,12 +7,6 @@ class PlatformThreadingInterface;
 -(Signaler*) init;
 @end
 
-
-@interface ActionCallback : NSObject
-- (ActionCallback*) initWithCallback: (IAvnActionCallback*) callback;
-- (void) action;
-@end
-
 @implementation ActionCallback
 {
     ComPtr<IAvnActionCallback> _callback;
@@ -57,16 +48,38 @@ class PlatformThreadingInterface : public ComSingleObject<IAvnPlatformThreadingI
 {
 private:
     Signaler* _signaler;
+    bool _wasRunningAtLeastOnce = false;
     
     class LoopCancellation : public ComSingleObject<IAvnLoopCancellation, &IID_IAvnLoopCancellation>
     {
     public:
         FORWARD_IUNKNOWN()
-        bool Cancelled = 0;
+        
+        bool Running = false;
+        bool Cancelled = false;
+        
         virtual void Cancel() override
         {
-            Cancelled = 1;
+            Cancelled = true;
+            if(Running)
+            {
+                Running = false;
+                dispatch_async(dispatch_get_main_queue(), ^{
+                    [[NSApplication sharedApplication] stop:nil];
+                    NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
+                                                        location:NSMakePoint(0, 0)
+                                                   modifierFlags:0
+                                                       timestamp:0
+                                                    windowNumber:0
+                                                         context:nil
+                                                         subtype:0
+                                                           data1:0
+                                                           data2:0];
+                    [NSApp postEvent:event atStart:YES];
+                });
+            }
         }
+
     };
     
 public:
@@ -99,30 +112,17 @@ public:
         return new LoopCancellation();
     }
     
-    virtual void RunLoop(IAvnLoopCancellation* cancel) override
+    virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) override
     {
-        @autoreleasepool {
-            auto can = dynamic_cast<LoopCancellation*>(cancel);
-            [[NSApplication sharedApplication] activateIgnoringOtherApps:true];
-            while(true)
-            {
-                @autoreleasepool
-                {
-                    if(can != NULL && can->Cancelled)
-                        return;
-                    NSEvent* ev = [[NSApplication sharedApplication]
-                                   nextEventMatchingMask:NSEventMaskAny
-                                   untilDate: [NSDate dateWithTimeIntervalSinceNow:1]
-                                   inMode:NSDefaultRunLoopMode
-                                   dequeue:true];
-                    if(can != NULL && can->Cancelled)
-                        return;
-                    if(ev != NULL)
-                        [[NSApplication sharedApplication] sendEvent:ev];
-                }
-            }
-            NSDebugLog(@"RunLoop exited");
-        }
+        auto can = dynamic_cast<LoopCancellation*>(cancel);
+        if(can->Cancelled)
+            return S_OK;
+        if(_wasRunningAtLeastOnce)
+            return E_FAIL;
+        can->Running = true;
+        _wasRunningAtLeastOnce = true;
+        [NSApp run];
+        return S_OK;
     }
     
     virtual void Signal(int priority) override
@@ -156,11 +156,14 @@ NSArray<NSString*>* _modes;
 
 -(void) perform
 {
+    ComPtr<IAvnSignaledCallback> cb;
     @synchronized (self) {
         _signaled  = false;
-        if(_parent != NULL && _parent->SignaledCallback != NULL)
-            _parent->SignaledCallback->Signaled(0, false);
+        if(_parent != NULL)
+            cb = _parent->SignaledCallback;
     }
+    if(cb != nullptr)
+        cb->Signaled(0, false);
 }
 
 -(void) setParent:(PlatformThreadingInterface *)parent

+ 284 - 0
native/Avalonia.Native/src/OSX/rendertarget.mm

@@ -0,0 +1,284 @@
+#include "common.h"
+#include "rendertarget.h"
+#import <IOSurface/IOSurface.h>
+#import <IOSurface/IOSurfaceObjC.h>
+
+#include <OpenGL/CGLIOSurface.h>
+#include <OpenGL/OpenGL.h>
+#include <OpenGL/glext.h>
+#include <OpenGL/gl3.h>
+#include <OpenGL/gl3ext.h>
+
+@interface IOSurfaceHolder : NSObject
+@end
+
+@implementation IOSurfaceHolder
+{
+    @public IOSurfaceRef surface;
+    @public AvnPixelSize size;
+    @public float scale;
+    ComPtr<IAvnGlContext> _context;
+    GLuint _framebuffer, _texture, _renderbuffer;
+}
+
+- (IOSurfaceHolder*) initWithSize: (AvnPixelSize) size
+                        withScale: (float)scale
+                withOpenGlContext: (IAvnGlContext*) context
+{
+    long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.Width * 4);
+    long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.Height * bytesPerRow);
+    NSDictionary* options = @{
+                              (id)kIOSurfaceWidth: @(size.Width),
+                              (id)kIOSurfaceHeight:  @(size.Height),
+                              (id)kIOSurfacePixelFormat: @((uint)'BGRA'),
+                              (id)kIOSurfaceBytesPerElement: @(4),
+                              (id)kIOSurfaceBytesPerRow: @(bytesPerRow),
+                              (id)kIOSurfaceAllocSize: @(allocSize),
+                              
+                              //(id)kIOSurfaceCacheMode: @(kIOMapWriteCombineCache),
+                              (id)kIOSurfaceElementWidth: @(1),
+                              (id)kIOSurfaceElementHeight: @(1)
+                              };
+    
+    surface = IOSurfaceCreate((CFDictionaryRef)options);
+    self->scale = scale;
+    self->size = size;
+    self->_context = context;
+    return self;
+}
+
+-(HRESULT) prepareForGlRender
+{
+    if(_context == nil)
+        return E_FAIL;
+    if(CGLGetCurrentContext() != _context->GetNativeHandle())
+        return E_FAIL;
+    if(_framebuffer == 0)
+        glGenFramebuffersEXT(1, &_framebuffer);
+    
+    
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, _framebuffer);
+    if(_texture == 0)
+    {
+        glGenTextures(1, &_texture);
+    
+        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, _texture);
+        CGLError res = CGLTexImageIOSurface2D((CGLContextObj)_context->GetNativeHandle(),
+                               GL_TEXTURE_RECTANGLE_EXT, GL_RGBA8,
+                               size.Width, size.Height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
+        glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
+        
+        if(res != 0)
+        {
+            glDeleteTextures(1, &_texture);
+            _texture = 0;
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+            return E_FAIL;
+        }
+        glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_EXT, _texture, 0);
+    }
+    
+    if(_renderbuffer == 0)
+    {
+        glGenRenderbuffers(1, &_renderbuffer);
+        glBindRenderbuffer(GL_RENDERBUFFER, _renderbuffer);
+        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.Width, size.Height);
+        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _renderbuffer);
+    }
+    
+    return S_OK;
+}
+
+-(void) finishDraw
+{
+    ComPtr<IUnknown> release;
+    _context->MakeCurrent(release.getPPV());
+    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+    glFlush();
+}
+
+-(void) dealloc
+{
+    
+    if(_framebuffer != 0)
+    {
+        ComPtr<IUnknown> release;
+        _context->MakeCurrent(release.getPPV());
+        glDeleteFramebuffers(1, &_framebuffer);
+        if(_texture != 0)
+            glDeleteTextures(1, &_texture);
+        if(_renderbuffer != 0)
+            glDeleteRenderbuffers(1, &_renderbuffer);
+    }
+    IOSurfaceDecrementUseCount(surface);
+}
+@end
+
+static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* target);
+
+@implementation IOSurfaceRenderTarget
+{
+    CALayer* _layer;
+    @public IOSurfaceHolder* surface;
+    @public NSObject* lock;
+    ComPtr<IAvnGlContext> _glContext;
+}
+
+- (IOSurfaceRenderTarget*) initWithOpenGlContext: (IAvnGlContext*) context;
+{
+    self = [super init];
+    _glContext = context;
+    lock = [NSObject new];
+    surface  = nil;
+    [self resize:{1,1} withScale: 1];
+    
+    return self;
+}
+
+- (AvnPixelSize) pixelSize {
+    return {1, 1};
+}
+
+- (CALayer *)layer {
+    return _layer;
+}
+
+- (void)resize:(AvnPixelSize)size withScale: (float) scale;{
+    @synchronized (lock) {
+        if(surface == nil
+           || surface->size.Width != size.Width
+           || surface->size.Height != size.Height
+           || surface->scale != scale)
+            surface = [[IOSurfaceHolder alloc] initWithSize:size withScale:scale withOpenGlContext:_glContext.getRaw()];
+    }
+}
+
+- (void)updateLayer {
+    if ([NSThread isMainThread])
+    {
+        @synchronized (lock) {
+            if(_layer == nil)
+                return;
+            [_layer setContents: nil];
+            if(surface != nil)
+            {
+                [_layer setContentsScale: surface->scale];
+                [_layer setContents: (__bridge IOSurface*) surface->surface];
+            }
+        }
+    }
+    else
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self updateLayer];
+        });
+}
+
+- (void) setNewLayer:(CALayer *)layer {
+    _layer = layer;
+    [self updateLayer];
+}
+
+- (HRESULT)setSwFrame:(AvnFramebuffer *)fb {
+    @synchronized (lock) {
+        if(fb->PixelFormat == AvnPixelFormat::kAvnRgb565)
+            return E_INVALIDARG;
+        if(surface == nil)
+            return E_FAIL;
+        IOSurfaceRef surf = surface->surface;
+        if(IOSurfaceLock(surf, 0, nil))
+            return E_FAIL;
+        size_t w = MIN(fb->Width, IOSurfaceGetWidth(surf));
+        size_t h = MIN(fb->Height, IOSurfaceGetHeight(surf));
+        size_t wbytes = w*4;
+        size_t sstride = IOSurfaceGetBytesPerRow(surf);
+        size_t fstride = fb->Stride;
+        char*pSurface = (char*)IOSurfaceGetBaseAddress(surf);
+        char*pFb = (char*)fb->Data;
+        for(size_t y = 0; y < h; y++)
+        {
+            memcpy(pSurface + y*sstride, pFb + y*fstride, wbytes);
+        }
+        IOSurfaceUnlock(surf, 0, nil);
+        [self updateLayer];
+        return S_OK;
+    }
+}
+
+-(IAvnGlSurfaceRenderTarget*) createSurfaceRenderTarget
+{
+    return CreateGlRenderTarget(self);
+}
+
+@end
+
+class AvnGlRenderingSession : public ComSingleObject<IAvnGlSurfaceRenderingSession, &IID_IAvnGlSurfaceRenderingSession>
+{
+    ComPtr<IUnknown> _releaseContext;
+    IOSurfaceRenderTarget* _target;
+    IOSurfaceHolder* _surface;
+public:
+    FORWARD_IUNKNOWN()
+    AvnGlRenderingSession(IOSurfaceRenderTarget* target, ComPtr<IUnknown> releaseContext)
+    {
+        _target = target;
+        // This happens in a synchronized block set up by AvnRenderTarget, so we take the current surface for this
+        // particular render session
+        _surface = _target->surface;
+        _releaseContext = releaseContext;
+    }
+    
+    virtual HRESULT GetPixelSize(AvnPixelSize* ret)  override
+    {
+        if(!_surface)
+            return E_FAIL;
+        *ret = _surface->size;
+        return S_OK;
+    }
+    
+    virtual HRESULT GetScaling(double* ret)  override
+    {
+        if(!_surface)
+            return E_FAIL;
+        *ret = _surface->scale;
+        return S_OK;
+    }
+    
+    virtual ~AvnGlRenderingSession()
+    {
+        [_surface finishDraw];
+        [_target updateLayer];
+        _releaseContext = nil;
+    }
+};
+
+class AvnGlRenderTarget : public ComSingleObject<IAvnGlSurfaceRenderTarget, &IID_IAvnGlSurfaceRenderTarget>
+{
+    IOSurfaceRenderTarget* _target;
+public:
+    FORWARD_IUNKNOWN()
+    AvnGlRenderTarget(IOSurfaceRenderTarget* target)
+    {
+        _target = target;
+    }
+    
+    virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret)  override
+    {
+        ComPtr<IUnknown> releaseContext;
+        @synchronized (_target->lock) {
+            if(_target->surface == nil)
+                return E_FAIL;
+            _target->_glContext->MakeCurrent(releaseContext.getPPV());
+            HRESULT res = [_target->surface prepareForGlRender];
+            if(res)
+                return res;
+            *ret = new AvnGlRenderingSession(_target, releaseContext);
+            return S_OK;
+        }
+    }
+};
+
+
+static IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(IOSurfaceRenderTarget* target)
+{
+    return new AvnGlRenderTarget(target);
+}

+ 15 - 4
native/Avalonia.Native/src/OSX/window.h

@@ -1,25 +1,32 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
 #ifndef window_h
 #define window_h
 
 class WindowBaseImpl;
 
-@interface AvnView : NSView<NSTextInputClient>
+@interface AutoFitContentVisualEffectView : NSVisualEffectView
+@end
+
+@interface AvnView : NSView<NSTextInputClient, NSDraggingDestination>
 -(AvnView* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
 -(NSEvent* _Nonnull) lastMouseDownEvent;
 -(AvnPoint) translateLocalPoint:(AvnPoint)pt;
 -(void) setSwRenderedFrame: (AvnFramebuffer* _Nonnull) fb dispose: (IUnknown* _Nonnull) dispose;
 -(void) onClosed;
+-(AvnPixelSize) getPixelSize;
 @end
 
 @interface AvnWindow : NSWindow <NSWindowDelegate>
++(void) closeAll;
 -(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent;
 -(void) setCanBecomeKeyAndMain;
 -(void) pollModalSession: (NSModalSession _Nonnull) session;
 -(void) restoreParentWindow;
 -(bool) shouldTryToHandleEvents;
+-(void) setEnabled: (bool) enable;
+-(void) showAppMenuOnly;
+-(void) showWindowMenuWithAppMenu;
+-(void) applyMenu:(NSMenu* _Nullable)menu;
+-(double) getScaling;
 @end
 
 struct INSWindowHolder
@@ -30,6 +37,10 @@ struct INSWindowHolder
 struct IWindowStateChanged
 {
     virtual void WindowStateChanged () = 0;
+    virtual void StartStateTransition () = 0;
+    virtual void EndStateTransition () = 0;
+    virtual SystemDecorations Decorations () = 0;
+    virtual AvnWindowState WindowState () = 0;
 };
 
 #endif /* window_h */

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 513 - 231
native/Avalonia.Native/src/OSX/window.mm


+ 94 - 85
nukebuild/Build.cs

@@ -12,7 +12,9 @@ using Nuke.Common.ProjectModel;
 using Nuke.Common.Tooling;
 using Nuke.Common.Tools.DotNet;
 using Nuke.Common.Tools.MSBuild;
+using Nuke.Common.Tools.Npm;
 using Nuke.Common.Utilities;
+using Nuke.Common.Utilities.Collections;
 using static Nuke.Common.EnvironmentInfo;
 using static Nuke.Common.IO.FileSystemTasks;
 using static Nuke.Common.IO.PathConstruction;
@@ -26,11 +28,13 @@ using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
  running and debugging a particular target (optionally without deps) would be way easier
  ReSharper/Rider - https://plugins.jetbrains.com/plugin/10803-nuke-support
  VSCode - https://marketplace.visualstudio.com/items?itemName=nuke.support
- 
+
  */
 
 partial class Build : NukeBuild
 {
+    [Solution("Avalonia.sln")] readonly Solution Solution;
+
     static Lazy<string> MsBuildExe = new Lazy<string>(() =>
     {
         if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -54,7 +58,7 @@ partial class Build : NukeBuild
     protected override void OnBuildInitialized()
     {
         Parameters = new BuildParameters(this);
-        Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.", 
+        Information("Building version {0} of Avalonia ({1}) using version {2} of Nuke.",
             Parameters.Version,
             Parameters.Configuration,
             typeof(NukeBuild).Assembly.GetName().Version.ToString());
@@ -93,29 +97,24 @@ partial class Build : NukeBuild
         string projectFile,
         Configure<MSBuildSettings> configurator = null)
     {
-        return MSBuild(projectFile, c =>
-        {
+        return MSBuild(c => c
+            .SetProjectFile(projectFile)
             // This is required for VS2019 image on Azure Pipelines
-            if (Parameters.IsRunningOnWindows && Parameters.IsRunningOnAzure)
-            {
-                var javaSdk = Environment.GetEnvironmentVariable("JAVA_HOME_8_X64");
-                if (javaSdk != null)
-                    c = c.AddProperty("JavaSdkDirectory", javaSdk);
-            }
-
-            c = c.AddProperty("PackageVersion", Parameters.Version)
-                .AddProperty("iOSRoslynPathHackRequired", "true")
-                .SetToolPath(MsBuildExe.Value)
-                .SetConfiguration(Parameters.Configuration)
-                .SetVerbosity(MSBuildVerbosity.Minimal);
-            c = configurator?.Invoke(c) ?? c;
-            return c;
-        });
+            .When(Parameters.IsRunningOnWindows &&
+                  Parameters.IsRunningOnAzure, c => c
+                .AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_8_X64")))
+            .AddProperty("PackageVersion", Parameters.Version)
+            .AddProperty("iOSRoslynPathHackRequired", true)
+            .SetToolPath(MsBuildExe.Value)
+            .SetConfiguration(Parameters.Configuration)
+            .SetVerbosity(MSBuildVerbosity.Minimal)
+            .Apply(configurator));
     }
+
     Target Clean => _ => _.Executes(() =>
     {
-        DeleteDirectories(Parameters.BuildDirs);
-        EnsureCleanDirectories(Parameters.BuildDirs);
+        Parameters.BuildDirs.ForEach(DeleteDirectory);
+        Parameters.BuildDirs.ForEach(EnsureCleanDirectory);
         EnsureCleanDirectory(Parameters.ArtifactsDir);
         EnsureCleanDirectory(Parameters.NugetIntermediateRoot);
         EnsureCleanDirectory(Parameters.NugetRoot);
@@ -123,8 +122,21 @@ partial class Build : NukeBuild
         EnsureCleanDirectory(Parameters.TestResultsRoot);
     });
 
+    Target CompileHtmlPreviewer => _ => _
+        .DependsOn(Clean)
+        .Executes(() =>
+        {
+            var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
+
+            NpmTasks.NpmInstall(c => c.SetWorkingDirectory(webappDir));
+            NpmTasks.NpmRun(c => c
+                .SetWorkingDirectory(webappDir)
+                .SetCommand("dist"));
+        });
+    
     Target Compile => _ => _
         .DependsOn(Clean)
+        .DependsOn(CompileHtmlPreviewer)
         .Executes(() =>
         {
             if (Parameters.IsRunningOnWindows)
@@ -134,96 +146,84 @@ partial class Build : NukeBuild
                 );
 
             else
-                DotNetBuild(Parameters.MSBuildSolution, c => c
+                DotNetBuild(c => c
+                    .SetProjectFile(Parameters.MSBuildSolution)
                     .AddProperty("PackageVersion", Parameters.Version)
                     .SetConfiguration(Parameters.Configuration)
                 );
         });
-    
-    void RunCoreTest(string project)
+
+    void RunCoreTest(string projectName)
     {
-        if(!project.EndsWith(".csproj"))
-            project = System.IO.Path.Combine(project, System.IO.Path.GetFileName(project)+".csproj");
-        Information("Running tests from " + project);
-        XDocument xdoc;
-        using (var s = File.OpenRead(project))
-            xdoc = XDocument.Load(s);
-
-        List<string> frameworks = null;
-        var targets = xdoc.Root.Descendants("TargetFrameworks").FirstOrDefault();
-        if (targets != null)
-            frameworks = targets.Value.Split(';').Where(f => !string.IsNullOrWhiteSpace(f)).ToList();
-        else 
-            frameworks = new List<string> {xdoc.Root.Descendants("TargetFramework").First().Value};
-        
-        foreach(var fw in frameworks)
+        Information($"Running tests from {projectName}");
+        var project = Solution.GetProject(projectName).NotNull("project != null");
+
+        foreach (var fw in project.GetTargetFrameworks())
         {
             if (fw.StartsWith("net4")
-                && RuntimeInformation.IsOSPlatform(OSPlatform.Linux) 
+                && RuntimeInformation.IsOSPlatform(OSPlatform.Linux)
                 && Environment.GetEnvironmentVariable("FORCE_LINUX_TESTS") != "1")
             {
-                Information($"Skipping {fw} tests on Linux - https://github.com/mono/mono/issues/13969");
+                Information($"Skipping {projectName} ({fw}) tests on Linux - https://github.com/mono/mono/issues/13969");
                 continue;
             }
 
-            Information("Running for " + fw);
-            DotNetTest(c =>
-            {
-                c = c
-                    .SetProjectFile(project)
-                    .SetConfiguration(Parameters.Configuration)
-                    .SetFramework(fw)
-                    .EnableNoBuild()
-                    .EnableNoRestore();
-                // NOTE: I can see that we could maybe add another extension method "Switch" or "If" to make this more  convenient
-                if (Parameters.PublishTestResults)
-                    c = c.SetLogger("trx").SetResultsDirectory(Parameters.TestResultsRoot);
-                return c;
-            });
+            Information($"Running for {projectName} ({fw}) ...");
+
+            DotNetTest(c => c
+                .SetProjectFile(project)
+                .SetConfiguration(Parameters.Configuration)
+                .SetFramework(fw)
+                .EnableNoBuild()
+                .EnableNoRestore()
+                .When(Parameters.PublishTestResults, c => c
+                    .SetLogger("trx")
+                    .SetResultsDirectory(Parameters.TestResultsRoot)));
         }
     }
 
     Target RunCoreLibsTests => _ => _
-        .OnlyWhen(() => !Parameters.SkipTests)
+        .OnlyWhenStatic(() => !Parameters.SkipTests)
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.Animation.UnitTests");
-            RunCoreTest("./tests/Avalonia.Base.UnitTests");
-            RunCoreTest("./tests/Avalonia.Controls.UnitTests");
-            RunCoreTest("./tests/Avalonia.Input.UnitTests");
-            RunCoreTest("./tests/Avalonia.Interactivity.UnitTests");
-            RunCoreTest("./tests/Avalonia.Layout.UnitTests");
-            RunCoreTest("./tests/Avalonia.Markup.UnitTests");
-            RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests");
-            RunCoreTest("./tests/Avalonia.Styling.UnitTests");
-            RunCoreTest("./tests/Avalonia.Visuals.UnitTests");
-            RunCoreTest("./tests/Avalonia.Skia.UnitTests");
-            RunCoreTest("./tests/Avalonia.ReactiveUI.UnitTests");
+            RunCoreTest("Avalonia.Animation.UnitTests");
+            RunCoreTest("Avalonia.Base.UnitTests");
+            RunCoreTest("Avalonia.Controls.UnitTests");
+            RunCoreTest("Avalonia.Controls.DataGrid.UnitTests");
+            RunCoreTest("Avalonia.Input.UnitTests");
+            RunCoreTest("Avalonia.Interactivity.UnitTests");
+            RunCoreTest("Avalonia.Layout.UnitTests");
+            RunCoreTest("Avalonia.Markup.UnitTests");
+            RunCoreTest("Avalonia.Markup.Xaml.UnitTests");
+            RunCoreTest("Avalonia.Styling.UnitTests");
+            RunCoreTest("Avalonia.Visuals.UnitTests");
+            RunCoreTest("Avalonia.Skia.UnitTests");
+            RunCoreTest("Avalonia.ReactiveUI.UnitTests");
         });
 
     Target RunRenderTests => _ => _
-        .OnlyWhen(() => !Parameters.SkipTests)
+        .OnlyWhenStatic(() => !Parameters.SkipTests)
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj");
+            RunCoreTest("Avalonia.Skia.RenderTests");
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-                RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj");
+                RunCoreTest("Avalonia.Direct2D1.RenderTests");
         });
-    
+
     Target RunDesignerTests => _ => _
-        .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+        .OnlyWhenStatic(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
         .DependsOn(Compile)
         .Executes(() =>
         {
-            RunCoreTest("./tests/Avalonia.DesignerSupport.Tests");
+            RunCoreTest("Avalonia.DesignerSupport.Tests");
         });
 
     [PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit;
 
     Target RunLeakTests => _ => _
-        .OnlyWhen(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
+        .OnlyWhenStatic(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
         .DependsOn(Compile)
         .Executes(() =>
         {
@@ -234,7 +234,7 @@ partial class Build : NukeBuild
         });
 
     Target ZipFiles => _ => _
-        .After(CreateNugetPackages, Compile, RunCoreLibsTests, Package)    
+        .After(CreateNugetPackages, Compile, RunCoreLibsTests, Package)
         .Executes(() =>
         {
             var data = Parameters;
@@ -258,9 +258,10 @@ partial class Build : NukeBuild
                 MsBuildCommon(Parameters.MSBuildSolution, c => c
                     .AddTargets("Pack"));
             else
-                DotNetPack(Parameters.MSBuildSolution, c =>
-                    c.SetConfiguration(Parameters.Configuration)
-                        .AddProperty("PackageVersion", Parameters.Version));
+                DotNetPack(c => c
+                    .SetProject(Parameters.MSBuildSolution)
+                    .SetConfiguration(Parameters.Configuration)
+                    .AddProperty("PackageVersion", Parameters.Version));
         });
 
     Target CreateNugetPackages => _ => _
@@ -273,32 +274,40 @@ partial class Build : NukeBuild
                 new NumergeNukeLogger()))
                 throw new Exception("Package merge failed");
         });
-    
+
     Target RunTests => _ => _
         .DependsOn(RunCoreLibsTests)
         .DependsOn(RunRenderTests)
         .DependsOn(RunDesignerTests)
         .DependsOn(RunLeakTests);
-    
+
     Target Package => _ => _
         .DependsOn(RunTests)
         .DependsOn(CreateNugetPackages);
-    
+
     Target CiAzureLinux => _ => _
         .DependsOn(RunTests);
-    
+
     Target CiAzureOSX => _ => _
         .DependsOn(Package)
         .DependsOn(ZipFiles);
-    
+
     Target CiAzureWindows => _ => _
         .DependsOn(Package)
         .DependsOn(ZipFiles);
 
-    
+
     public static int Main() =>
         RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
             ? Execute<Build>(x => x.Package)
             : Execute<Build>(x => x.RunTests);
 
 }
+
+public static class ToolSettingsExtensions
+{
+    public static T Apply<T>(this T settings, Configure<T> configurator)
+    {
+        return configurator != null ? configurator(settings) : settings;
+    }
+}

+ 9 - 12
nukebuild/BuildParameters.cs

@@ -4,24 +4,21 @@ using System.Linq;
 using System.Runtime.InteropServices;
 using System.Xml.Linq;
 using Nuke.Common;
-using Nuke.Common.BuildServers;
-using Nuke.Common.Execution;
+using Nuke.Common.CI.AzurePipelines;
 using Nuke.Common.IO;
-using static Nuke.Common.IO.FileSystemTasks;
 using static Nuke.Common.IO.PathConstruction;
-using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
 
 public partial class Build
 {
     [Parameter("configuration")]
     public string Configuration { get; set; }
-    
+
     [Parameter("skip-tests")]
     public bool SkipTests { get; set; }
-    
+
     [Parameter("force-nuget-version")]
     public string ForceNugetVersion { get; set; }
-    
+
     public class BuildParameters
     {
         public string Configuration { get; }
@@ -79,15 +76,15 @@ public partial class Build
             IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix ||
                               Environment.OSVersion.Platform == PlatformID.MacOSX;
             IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
-            IsRunningOnAzure = Host == HostType.TeamServices ||
+            IsRunningOnAzure = Host == HostType.AzurePipelines ||
                                Environment.GetEnvironmentVariable("LOGNAME") == "vsts";
 
             if (IsRunningOnAzure)
             {
-                RepositoryName = TeamServices.Instance.RepositoryUri;
-                RepositoryBranch = TeamServices.Instance.SourceBranch;
-                IsPullRequest = TeamServices.Instance.PullRequestId.HasValue;
-                IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, TeamServices.Instance.RepositoryUri);
+                RepositoryName = AzurePipelines.Instance.RepositoryUri;
+                RepositoryBranch = AzurePipelines.Instance.SourceBranch;
+                IsPullRequest = AzurePipelines.Instance.PullRequestId.HasValue;
+                IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, AzurePipelines.Instance.RepositoryUri);
             }
             IsMainRepo =
                 StringComparer.OrdinalIgnoreCase.Equals(MainRepo,

+ 4 - 4
nukebuild/Shims.cs

@@ -19,9 +19,9 @@ public partial class Build
         Logger.Info(info, args);
     }
 
-    private void Zip(PathConstruction.AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable());
+    private void Zip(AbsolutePath target, params string[] paths) => Zip(target, paths.AsEnumerable());
 
-    private void Zip(PathConstruction.AbsolutePath target, IEnumerable<string> paths)
+    private void Zip(AbsolutePath target, IEnumerable<string> paths)
     {
         var targetPath = target.ToString();
         bool finished = false, atLeastOneFileAdded = false;
@@ -38,7 +38,7 @@ public partial class Build
                         fileStream.CopyTo(entryStream);
                     atLeastOneFileAdded = true;
                 }
-                
+
                 foreach (var path in paths)
                 {
                     if (Directory.Exists(path))
@@ -64,7 +64,7 @@ public partial class Build
 
             finished = true;
         }
-        finally 
+        finally
         {
             try
             {

+ 4 - 4
nukebuild/_build.csproj

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
     <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
     <RootNamespace></RootNamespace>
     <IsPackable>False</IsPackable>
@@ -10,7 +10,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Nuke.Common" Version="0.12.3" />
+    <PackageReference Include="Nuke.Common" Version="0.24.0" />
     <PackageReference Include="xunit.runner.console" Version="2.3.1" />
     <PackageReference Include="JetBrains.dotMemoryUnit" Version="3.0.20171219.105559" />
     <PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " />
@@ -20,11 +20,11 @@
     <NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" />
     <NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" />
     <None Remove="*.csproj.DotSettings;*.ref.*.txt" />
-    
+
     <!-- Common build related files -->
     <None Include="..\build.ps1" />
     <None Include="..\build.sh" />
-    <None Include="..\.nuke" />     
+    <None Include="..\.nuke" />
     <None Include="..\global.json" Condition="Exists('..\global.json')" />
     <None Include="..\nuget.config" Condition="Exists('..\nuget.config')" />
     <None Include="..\Jenkinsfile" Condition="Exists('..\Jenkinsfile')" />

+ 6 - 1
packages/Avalonia/AvaloniaBuildTasks.targets

@@ -2,6 +2,7 @@
   <PropertyGroup>
     <_AvaloniaUseExternalMSBuild>$(AvaloniaUseExternalMSBuild)</_AvaloniaUseExternalMSBuild>
     <_AvaloniaUseExternalMSBuild Condition="'$(_AvaloniaForceInternalMSBuild)' == 'true'">false</_AvaloniaUseExternalMSBuild>
+    <AvaloniaXamlReportImportance Condition="'$(AvaloniaXamlReportImportance)' == ''">low</AvaloniaXamlReportImportance>
   </PropertyGroup>
   
   <UsingTask TaskName="GenerateAvaloniaResourcesTask"
@@ -38,7 +39,8 @@
       Output="$(AvaloniaResourcesTemporaryFilePath)"
       Root="$(MSBuildProjectDirectory)"
       Resources="@(AvaloniaResource)"
-      EmbeddedResources="@(EmbeddedResources)"/>
+      EmbeddedResources="@(EmbeddedResources)"
+      ReportImportance="$(AvaloniaXamlReportImportance)"/>
     <Exec 
       Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"
       Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false"/>
@@ -53,6 +55,7 @@
     <PropertyGroup>
       <AvaloniaXamlReferencesTemporaryFilePath Condition="'$(AvaloniaXamlReferencesTemporaryFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/references</AvaloniaXamlReferencesTemporaryFilePath>
       <AvaloniaXamlOriginalCopyFilePath Condition="'$(AvaloniaXamlOriginalCopyFilePath)' == ''">$(IntermediateOutputPath)/Avalonia/original.dll</AvaloniaXamlOriginalCopyFilePath>
+      <AvaloniaXamlIlVerifyIl Condition="'$(AvaloniaXamlIlVerifyIl)' == ''">false</AvaloniaXamlIlVerifyIl>
     </PropertyGroup>
     <WriteLinesToFile
       Condition="'$(_AvaloniaForceInternalMSBuild)' != 'true'"
@@ -65,6 +68,8 @@
       ReferencesFilePath="$(AvaloniaXamlReferencesTemporaryFilePath)"
       OriginalCopyPath="$(AvaloniaXamlOriginalCopyFilePath)"
       ProjectDirectory="$(MSBuildProjectDirectory)"
+      VerifyIl="$(AvaloniaXamlIlVerifyIl)"
+      ReportImportance="$(AvaloniaXamlReportImportance)"
     />
     <Exec
       Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'"

+ 46 - 29
readme.md

@@ -1,69 +1,82 @@
-<img src='https://avatars2.githubusercontent.com/u/14075148?s=200&v=4' width='100' />
+[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![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://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg)
+<br />
+[![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) [![downloads](https://img.shields.io/nuget/dt/avalonia)](https://www.nuget.org/packages/Avalonia) [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) ![Size](https://img.shields.io/github/repo-size/avaloniaui/avalonia.svg) 
 
-# Avalonia
+<img alt="Avalonia" src="https://user-images.githubusercontent.com/6759207/84897744-cab6d800-b0ae-11ea-8214-e5174d71f5c8.png" width="400"/>
 
-| Gitter Chat | Build Status (Win, Linux, OSX) | Open Collective | NuGet | MyGet |
-|---|---|---|---|---|
-|  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) | [![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://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) | [![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) | [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) |
+## 📖 About AvaloniaUI 
 
-## About
+Avalonia is a cross-platform XAML-based UI framework providing a flexible styling system and supporting a wide range of Operating Systems such as Windows via .NET Framework and .NET Core, Linux via Xorg, macOS. Avalonia is ready for **General-Purpose Desktop App Development**. However, there may be some bugs and breaking changes as we continue along into this project's development. 
 
-**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.
+<img src="https://user-images.githubusercontent.com/6759207/84751662-7c79da00-afc5-11ea-8780-dda28db70b76.png" width="700" />
 
-**Avalonia** is ready for **General-Purpose Desktop App Development**. However there may be some bugs and breaking changes as we continue along into this project's development. To see the status for some of our features, please see our [Roadmap here](https://github.com/AvaloniaUI/Avalonia/issues/2239).
+> **Note:** The UI theme you see in the picture above is still work-in-progress and will be available in the upcoming Avalonia 0.10.0 release. However, you can connect to our nightly build feed and install latest pre-release versions of Avalonia NuGet packages, if you are willing to help out with the development and testing. See [Using nightly build feed](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) for more info.
 
-| Control catalog | Desktop platforms | Mobile platforms |
-|---|---|---|
-| <a href='https://youtu.be/wHcB3sGLVYg'><img width='300' src='http://avaloniaui.net/images/screen.png'></a> | <a href='https://www.youtube.com/watch?t=28&v=c_AB_XSILp0' target='_blank'><img width='300' src='http://avaloniaui.net/images/avalonia-video.png'></a> | <a href='https://www.youtube.com/watch?v=NJ9-hnmUbBM' target='_blank'><img width='300' src='https://i.ytimg.com/vi/NJ9-hnmUbBM/hqdefault.jpg'></a> |
+To see the status of some of our features, please see our [Roadmap](https://github.com/AvaloniaUI/Avalonia/issues/2239). You can also see what [breaking changes](https://github.com/AvaloniaUI/Avalonia/issues/3538) we have planned and what our [past breaking changes](https://github.com/AvaloniaUI/Avalonia/wiki/Breaking-Changes) have been. [Awesome Avalonia](https://github.com/AvaloniaCommunity/awesome-avalonia) is community-curated list of awesome Avalonia UI tools, libraries, projects and resources. Go and see what people are building with Avalonia!
 
-## Getting Started
+## 🚀 Getting Started
 
-Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (<a href="http://avaloniaui.net/docs/quickstart/images/new-project-dialog.png">screenshot</a>). Now you can write code and markup that will work on multiple platforms!
+The Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started, or you can use the .NET Core CLI. For a starer guide see our [documentation](http://avaloniaui.net/docs/quickstart/create-new-project).
 
-For those without Visual Studio, starter guide for .NET Core CLI can be found [here](http://avaloniaui.net/docs/quickstart/create-new-project#net-core).
+Avalonia is delivered via <b>NuGet</b> package manager. You can find the packages here: https://www.nuget.org/packages/Avalonia/
 
-Avalonia is delivered via <b>NuGet</b> package manager. You can find the packages here: ([stable(ish)](https://www.nuget.org/packages/Avalonia/), [nightly](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed))
-
-Use these commands in Package Manager console to install Avalonia manually:
+Use these commands in the Package Manager console to install Avalonia manually:
 ```
 Install-Package Avalonia
 Install-Package Avalonia.Desktop
 ```
 
-## Bleeding Edge Builds
+## Showcase
 
-or use nightly build feeds as described here:
-https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed
+Examples of UIs built with Avalonia
+![image](https://user-images.githubusercontent.com/4672627/84707589-5b69a880-af35-11ea-87a6-7ad57a31d314.png)
 
-## Documentation
+![image](https://user-images.githubusercontent.com/4672627/85069644-d8419000-b18a-11ea-8732-be9055bb61fd.PNG)
+
+![image](https://user-images.githubusercontent.com/4672627/85069659-dc6dad80-b18a-11ea-8375-39ef95315b5c.PNG)
+
+![image](https://user-images.githubusercontent.com/4672627/84708947-c3b98980-af37-11ea-8c9d-503334615bbf.png)
+
+## JetBrains Rider
+
+If you need to develop Avalonia app with JetBrains Rider, go and *vote* on [this issue](https://youtrack.jetbrains.com/issue/RIDER-39247) in their tracker. JetBrains won't do things without their users telling them that they want the feature, so only **YOU** can make it happen.
+
+## Bleeding Edge Builds
 
-You can take a look at the [getting started page](http://avaloniaui.net/docs/quickstart/) for an overview of how to get started but probably the best thing to do for now is to already know a little bit about WPF/Silverlight/UWP/XAML and ask questions in our [Gitter room](https://gitter.im/AvaloniaUI/Avalonia). 
+We also have a [nightly build](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed) which tracks the current state of master. Although these packages are less stable than the release on NuGet.org, you'll get all the latest features and bugfixes right away and many of our users actually prefer this feed!
 
-There's also a high-level [architecture document](http://avaloniaui.net/architecture/project-structure) that is currently a little bit out of date, and I've also started writing blog posts on Avalonia at http://grokys.github.io/.
+## Documentation
 
-Contributions for our docs are always welcome!
+Documentation can be found on our website at http://avaloniaui.net/docs/. We also have a [tutorial](http://avaloniaui.net/docs/tutorial/) over there for newcomers.
 
 ## Building and Using
 
-See the [build instructions here](http://avaloniaui.net/contributing/build).
+See the [build instructions here](Documentation/build.md).
 
 ## Contributing
 
-Please read the [contribution guidelines](http://avaloniaui.net/contributing/contributing) before submitting a pull request.
+Please read the [contribution guidelines](CONTRIBUTING.md) before submitting a pull request.
+
+## Code of Conduct
+
+This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
+For more information see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 
+
+## Licence
+
+Avalonia is licenced under the [MIT licence](licence.md).
 
-### Contributors
+## Contributors
 
 This project exists thanks to all the people who contribute. [[Contribute](http://avaloniaui.net/contributing/contributing)].
 <a href="https://github.com/AvaloniaUI/Avalonia/graphs/contributors"><img src="https://opencollective.com/Avalonia/contributors.svg?width=890&button=false" /></a>
 
-
 ### Backers
 
 Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Avalonia#backer)]
 
 <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)]
@@ -78,3 +91,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
 <a href="https://opencollective.com/Avalonia/sponsor/7/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/7/avatar.svg"></a>
 <a href="https://opencollective.com/Avalonia/sponsor/8/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/8/avatar.svg"></a>
 <a href="https://opencollective.com/Avalonia/sponsor/9/website" target="_blank"><img src="https://opencollective.com/Avalonia/sponsor/9/avatar.svg"></a> 
+
+## .NET Foundation
+
+This project is supported by the [.NET Foundation](https://dotnetfoundation.org).

+ 0 - 2
samples/BindingDemo/App.xaml.cs

@@ -1,10 +1,8 @@
 using System;
 using Avalonia;
 using Avalonia.Controls;
-using Avalonia.Logging.Serilog;
 using Avalonia.Markup.Xaml;
 using Avalonia.ReactiveUI;
-using Serilog;
 
 namespace BindingDemo
 {

+ 2 - 2
samples/BindingDemo/BindingDemo.csproj

@@ -1,15 +1,15 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
   </PropertyGroup>
   <ItemGroup>
+    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
     <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
     <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" />
   </ItemGroup>
   <Import Project="..\..\build\SampleApp.props" />
   <Import Project="..\..\build\EmbedXaml.props" />
-  <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\Rx.props" />
   <Import Project="..\..\build\ReactiveUI.props" />
   <Import Condition="'$(TargetFramework)'=='net461'" Project="..\..\build\NetFX.props" />

+ 5 - 2
samples/BindingDemo/MainWindow.xaml

@@ -24,6 +24,9 @@
             <TextBox Watermark="Two Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue}" Name="first"/>
             <TextBox Watermark="One Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneWay}"/>
             <TextBox Watermark="One Time" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneTime}"/>
+            <!-- Removed due to #2983: reinstate when that's fixed.
+              <TextBox Watermark="One Way to Source" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneWayToSource}"/>
+            -->
           </StackPanel>
           <StackPanel Margin="18" Spacing="4" Width="200">
             <TextBlock FontSize="16" Text="Collection Bindings"/>
@@ -71,11 +74,11 @@
         </StackPanel.DataTemplates>
         <StackPanel Margin="18" Spacing="4" Width="200">
           <TextBlock FontSize="16" Text="Multiple"/>
-          <ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
+          <ListBox Items="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
         </StackPanel>
         <StackPanel Margin="18" Spacing="4" Width="200">
           <TextBlock FontSize="16" Text="Multiple"/>
-          <ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
+          <ListBox Items="{Binding Items}" SelectionMode="Multiple" Selection="{Binding Selection}"/>
         </StackPanel>
         <ContentControl Content="{Binding SelectedItems[0]}">
           <ContentControl.DataTemplates>

+ 1 - 4
samples/BindingDemo/ViewModels/DataAnnotationsErrorViewModel.cs

@@ -1,7 +1,4 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations;
 
 namespace BindingDemo.ViewModels
 {

+ 1 - 4
samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs

@@ -1,7 +1,4 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using ReactiveUI;
+using ReactiveUI;
 using System;
 
 namespace BindingDemo.ViewModels

+ 1 - 4
samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs

@@ -1,7 +1,4 @@
-// Copyright (c) The Avalonia Project. All rights reserved.
-// Licensed under the MIT license. See licence.md file in the project root for full license information.
-
-using ReactiveUI;
+using ReactiveUI;
 using System;
 using System.ComponentModel;
 using System.Collections;

+ 7 - 5
samples/BindingDemo/ViewModels/MainWindowViewModel.cs

@@ -1,10 +1,12 @@
 using System;
 using System.Collections.ObjectModel;
 using System.Linq;
-using ReactiveUI;
+using System.Reactive;
 using System.Reactive.Linq;
 using System.Threading.Tasks;
 using System.Threading;
+using ReactiveUI;
+using Avalonia.Controls;
 
 namespace BindingDemo.ViewModels
 {
@@ -26,7 +28,7 @@ namespace BindingDemo.ViewModels
                     Detail = "Item " + x + " details",
                 }));
 
-            SelectedItems = new ObservableCollection<TestItem>();
+            Selection = new SelectionModel();
 
             ShuffleItems = ReactiveCommand.Create(() =>
             {
@@ -55,8 +57,8 @@ namespace BindingDemo.ViewModels
         }
 
         public ObservableCollection<TestItem> Items { get; }
-        public ObservableCollection<TestItem> SelectedItems { get; }
-        public ReactiveCommand ShuffleItems { get; }
+        public SelectionModel Selection { get; }
+        public ReactiveCommand<Unit, Unit> ShuffleItems { get; }
 
         public string BooleanString
         {
@@ -89,7 +91,7 @@ namespace BindingDemo.ViewModels
         }
 
         public IObservable<string> CurrentTimeObservable { get; }
-        public ReactiveCommand StringValueCommand { get; }
+        public ReactiveCommand<object, Unit> StringValueCommand { get; }
 
         public DataAnnotationsErrorViewModel DataAnnotationsValidation { get; } = new DataAnnotationsErrorViewModel();
         public ExceptionErrorViewModel ExceptionDataValidation { get; } = new ExceptionErrorViewModel();

+ 1 - 1
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@@ -16,7 +16,7 @@
     <AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
     <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
     <AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
-    <TargetFrameworkVersion>v8.0</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
     <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

+ 1 - 1
samples/ControlCatalog.Android/MainActivity.cs

@@ -20,7 +20,7 @@ namespace ControlCatalog.Android
         {
             if (Avalonia.Application.Current == null)           
             {
-                AppBuilder.Configure(new App())
+                AppBuilder.Configure<App>()
                     .UseAndroid()
                     .SetupWithoutStarting();
                 Content = new MainView();

+ 0 - 1
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@@ -10,6 +10,5 @@
   </ItemGroup>
 
   <Import Project="..\..\build\SampleApp.props" />
-  <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\NetFX.props" />
 </Project>

+ 0 - 2
samples/ControlCatalog.Desktop/Program.cs

@@ -2,10 +2,8 @@ using System;
 using System.Linq;
 using Avalonia;
 using Avalonia.Controls;
-using Avalonia.Logging.Serilog;
 using Avalonia.Platform;
 using Avalonia.ReactiveUI;
-using Serilog;
 
 namespace ControlCatalog
 {

+ 2 - 1
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@@ -2,12 +2,13 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp2.0</TargetFramework>
+    <TargetFramework>netcoreapp3.1</TargetFramework>
     <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
   </PropertyGroup>
 
   <ItemGroup>
     <ProjectReference Include="..\..\src\Avalonia.Headless.Vnc\Avalonia.Headless.Vnc.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
     <ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
     <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
     <ProjectReference Include="..\..\src\Avalonia.Desktop\Avalonia.Desktop.csproj" />

+ 12 - 6
samples/ControlCatalog.NetCore/Program.cs

@@ -17,10 +17,9 @@ namespace ControlCatalog.NetCore
 {
     static class Program
     {
-
+        [STAThread]
         static int Main(string[] args)
         {
-            Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
             if (args.Contains("--wait-for-attach"))
             {
                 Console.WriteLine("Attach debugger and use 'Set next statement'");
@@ -101,21 +100,27 @@ namespace ControlCatalog.NetCore
             else
                 return builder.StartWithClassicDesktopLifetime(args);
         }
-        
+
         /// <summary>
         /// This method is needed for IDE previewer infrastructure
         /// </summary>
         public static AppBuilder BuildAvaloniaApp()
             => AppBuilder.Configure<App>()
                 .UsePlatformDetect()
-                .With(new X11PlatformOptions {EnableMultiTouch = true})
+                .With(new X11PlatformOptions
+                {
+                    EnableMultiTouch = true,
+                    UseDBusMenu = true
+                })
                 .With(new Win32PlatformOptions
                 {
                     EnableMultitouch = true,
                     AllowEglInitialization = true
                 })
                 .UseSkia()
-                .UseReactiveUI();
+                .UseReactiveUI()
+                .UseManagedSystemDialogs()
+                .LogToDebug();
 
         static void SilenceConsole()
         {
@@ -124,7 +129,8 @@ namespace ControlCatalog.NetCore
                 Console.CursorVisible = false;
                 while (true)
                     Console.ReadKey(true);
-            }) {IsBackground = true}.Start();
+            })
+            { IsBackground = true }.Start();
         }
     }
 }

+ 2 - 4
samples/ControlCatalog/App.xaml

@@ -1,10 +1,8 @@
 <Application xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              x:Class="ControlCatalog.App">
-  <Application.Styles>
-      <StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
-      <StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
-      <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
+  <Application.Styles>        
+    <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
     <Style Selector="TextBlock.h1">
       <Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/>
       <Setter Property="FontWeight" Value="Medium"/>

+ 54 - 1
samples/ControlCatalog/App.xaml.cs

@@ -1,14 +1,67 @@
+using System;
 using Avalonia;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Markup.Xaml;
+using Avalonia.Markup.Xaml.Styling;
+using Avalonia.Styling;
 
 namespace ControlCatalog
 {
     public class App : Application
     {
+        public static Styles FluentDark = new Styles
+        {
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseDark.xaml?assembly=Avalonia.Themes.Default")
+            },
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Fluent.Accents.FluentDark.xaml?assembly=Avalonia.Themes.Fluent")
+            },
+        };
+
+        public static Styles FluentLight = new Styles
+        {
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default")
+            },
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Fluent.Accents.FluentLight.xaml?assembly=Avalonia.Themes.Fluent")
+            },
+        };
+
+        public static Styles DefaultLight = new Styles
+        {
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default")
+            },
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default")
+            },
+        };
+
+        public static Styles DefaultDark = new Styles
+        {
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseDark.xaml?assembly=Avalonia.Themes.Default")
+            },
+            new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
+            {
+                Source = new Uri("resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default")
+            },
+        };
+
         public override void Initialize()
         {
             AvaloniaXamlLoader.Load(this);
+
+            Styles.Insert(0, FluentDark);
         }
 
         public override void OnFrameworkInitializationCompleted()
@@ -17,7 +70,7 @@ namespace ControlCatalog
                 desktopLifetime.MainWindow = new MainWindow();
             else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
                 singleViewLifetime.MainView = new MainView();
-            
+
             base.OnFrameworkInitializationCompleted();
         }
     }

+ 4 - 2
samples/ControlCatalog/ControlCatalog.csproj

@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <TargetFramework>netstandard2.0</TargetFramework>    
+    <TargetFramework>netstandard2.0</TargetFramework>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>    
   </PropertyGroup>
   <ItemGroup>
     <Compile Update="**\*.xaml.cs">
@@ -17,14 +18,15 @@
     <EmbeddedResource Include="Assets\Fonts\SourceSansPro-BoldItalic.ttf" />
     <EmbeddedResource Include="Assets\Fonts\SourceSansPro-Italic.ttf" />
     <EmbeddedResource Include="Assets\Fonts\SourceSansPro-Regular.ttf" />
+    <EmbeddedResource Include="Pages\teapot.bin" />
   </ItemGroup>
 
   <ItemGroup>
     <ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
+    <ProjectReference Include="..\..\src\Avalonia.Diagnostics\Avalonia.Diagnostics.csproj" />
     <ProjectReference Include="..\..\src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj" />
     <ProjectReference Include="..\..\src\Avalonia.Controls.DataGrid\Avalonia.Controls.DataGrid.csproj" />
   </ItemGroup>
   
-  <Import Project="..\..\build\Serilog.props" />
   <Import Project="..\..\build\BuildTargets.targets" />
 </Project>

+ 25 - 0
samples/ControlCatalog/DecoratedWindow.xaml

@@ -3,6 +3,31 @@
         x:Class="ControlCatalog.DecoratedWindow"
         Title="Avalonia Control Gallery"
         xmlns:local="clr-namespace:ControlCatalog" HasSystemDecorations="False" Name="Window">
+        <NativeMenu.Menu>
+    <NativeMenu>
+      <NativeMenuItem Header="Decorated">
+        <NativeMenuItem.Menu>
+          <NativeMenu>
+            <NativeMenuItem Header="Open"/>
+            <NativeMenuItem Header="Recent">
+              <NativeMenuItem.Menu>
+                <NativeMenu/>
+              </NativeMenuItem.Menu>
+            </NativeMenuItem>
+            <NativeMenuItem Header="Quit Avalonia" Gesture="CMD+Q"/>
+          </NativeMenu>
+        </NativeMenuItem.Menu>
+      </NativeMenuItem>
+      <NativeMenuItem Header="Edit">
+        <NativeMenuItem.Menu>
+          <NativeMenu>
+            <NativeMenuItem Header="Copy"/>
+            <NativeMenuItem Header="Paste"/>
+          </NativeMenu>
+        </NativeMenuItem.Menu>
+      </NativeMenuItem>
+    </NativeMenu>
+  </NativeMenu.Menu>
     <Grid RowDefinitions="5,*,5" ColumnDefinitions="5,*,5">
         <DockPanel  Grid.Column="1"  Grid.Row="1" >
             <Grid Name="TitleBar" Background="LightBlue" DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto">

+ 4 - 4
samples/ControlCatalog/DecoratedWindow.xaml.cs

@@ -18,18 +18,18 @@ namespace ControlCatalog
         {
             var ctl = this.FindControl<Control>(name);
             ctl.Cursor = new Cursor(cursor);
-            ctl.PointerPressed += delegate
+            ctl.PointerPressed += (i, e) =>
             {
-                PlatformImpl?.BeginResizeDrag(edge);
+                PlatformImpl?.BeginResizeDrag(edge, e);
             };
         }
 
         private void InitializeComponent()
         {
             AvaloniaXamlLoader.Load(this);
-            this.FindControl<Control>("TitleBar").PointerPressed += delegate
+            this.FindControl<Control>("TitleBar").PointerPressed += (i, e) =>
             {
-                PlatformImpl?.BeginMoveDrag();
+                PlatformImpl?.BeginMoveDrag(e);
             };
             SetupSide("Left", StandardCursorType.LeftSide, WindowEdge.West);
             SetupSide("Right", StandardCursorType.RightSide, WindowEdge.East);

+ 40 - 12
samples/ControlCatalog/MainView.xaml

@@ -2,7 +2,7 @@
         xmlns:pages="clr-namespace:ControlCatalog.Pages"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="ControlCatalog.MainView"
-        Background="{DynamicResource ThemeBackgroundBrush}"
+        Background="Transparent"
         Foreground="{DynamicResource ThemeForegroundBrush}"
         FontSize="{DynamicResource FontSizeNormal}">
   <Grid>
@@ -24,38 +24,66 @@
       <TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
       <TabItem Header="ComboBox"><pages:ComboBoxPage/></TabItem>
       <TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
-      <!-- DataGrid is our special snowflake -->  
       <TabItem Header="DataGrid" 
                ScrollViewer.VerticalScrollBarVisibility="Disabled"
                ScrollViewer.HorizontalScrollBarVisibility="Disabled">
           <pages:DataGridPage/>
       </TabItem>
-      <TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
+      <TabItem Header="CalendarDatePicker">
+        <pages:CalendarDatePickerPage/></TabItem>
       <TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
       <TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
-      <TabItem Header="Image"><pages:ImagePage/></TabItem>
-      <TabItem Header="ItemsRepeater"><pages:ItemsRepeaterPage/></TabItem>
+      <TabItem Header="Image"
+               ScrollViewer.VerticalScrollBarVisibility="Disabled"
+               ScrollViewer.HorizontalScrollBarVisibility="Disabled">
+        <pages:ImagePage/>
+      </TabItem>
+      <TabItem Header="ItemsRepeater"
+               ScrollViewer.VerticalScrollBarVisibility="Disabled"
+               ScrollViewer.HorizontalScrollBarVisibility="Disabled">
+        <pages:ItemsRepeaterPage/>
+      </TabItem>
       <TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
       <TabItem Header="ListBox"><pages:ListBoxPage/></TabItem>
       <TabItem Header="Menu"><pages:MenuPage/></TabItem>
       <TabItem Header="Notifications"><pages:NotificationsPage/></TabItem>
-	  <TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
+	    <TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
+      <TabItem Header="OpenGL"><pages:OpenGlPage/></TabItem>
       <TabItem Header="Pointers (Touch)"><pages:PointersPage/></TabItem>
       <TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
       <TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
+      <TabItem Header="ScrollViewer"><pages:ScrollViewerPage/></TabItem>
       <TabItem Header="Slider"><pages:SliderPage/></TabItem>
       <TabItem Header="TabControl"><pages:TabControlPage/></TabItem>
       <TabItem Header="TabStrip"><pages:TabStripPage/></TabItem>
       <TabItem Header="TextBox"><pages:TextBoxPage/></TabItem>
+      <TabItem Header="TextBlock"><pages:TextBlockPage/></TabItem>
+      <TabItem Header="ToggleSwitch"><pages:ToggleSwitchPage/></TabItem>
       <TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
       <TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
       <TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
-    <TabControl.Tag>
-        <ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
-            <ComboBoxItem>Light</ComboBoxItem>
-            <ComboBoxItem>Dark</ComboBoxItem>
-        </ComboBox>
-    </TabControl.Tag>
+      <TabControl.Tag>
+        <StackPanel Width="115" Spacing="4" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="8">
+          <ComboBox x:Name="Decorations" SelectedIndex="0">
+            <ComboBoxItem>No Decorations</ComboBoxItem>
+            <ComboBoxItem>Border Only</ComboBoxItem>
+            <ComboBoxItem>Full Decorations</ComboBoxItem>
+          </ComboBox>
+          <ComboBox x:Name="Themes" SelectedIndex="0">
+            <ComboBoxItem>Fluent - Dark</ComboBoxItem>
+            <ComboBoxItem>Fluent - Light</ComboBoxItem>
+            <ComboBoxItem>Simple - Light</ComboBoxItem>
+            <ComboBoxItem>Simple - Dark</ComboBoxItem>
+          </ComboBox>
+          <ComboBox x:Name="TransparencyLevels" SelectedIndex="0">
+            <ComboBoxItem>None</ComboBoxItem>
+            <ComboBoxItem>Transparent</ComboBoxItem>
+            <ComboBoxItem>Blur</ComboBoxItem>
+            <ComboBoxItem>AcrylicBlur</ComboBoxItem>
+          </ComboBox>
+          <ComboBox Items="{Binding WindowStates}" SelectedItem="{Binding WindowState}" />
+        </StackPanel>
+      </TabControl.Tag>
     </TabControl>
   </Grid>
 </UserControl>

+ 30 - 13
samples/ControlCatalog/MainView.xaml.cs

@@ -32,30 +32,47 @@ namespace ControlCatalog
 
             }
 
-            var light = new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
-            {
-                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default")
-            };
-            var dark = new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
-            {
-                Source = new Uri("resm:Avalonia.Themes.Default.Accents.BaseDark.xaml?assembly=Avalonia.Themes.Default")
-            };
-
-            
             var themes = this.Find<ComboBox>("Themes");
             themes.SelectionChanged += (sender, e) =>
             {
                 switch (themes.SelectedIndex)
                 {
                     case 0:
-                        Styles[0] = light;
+                        Application.Current.Styles[0] = App.FluentDark;
                         break;
                     case 1:
-                        Styles[0] = dark;
+                        Application.Current.Styles[0] = App.FluentLight;
+                        break;
+                    case 2:
+                        Application.Current.Styles[0] = App.DefaultLight;
+                        break;
+                    case 3:
+                        Application.Current.Styles[0] = App.DefaultDark;
                         break;
                 }
+            };            
+
+            var decorations = this.Find<ComboBox>("Decorations");
+            decorations.SelectionChanged += (sender, e) =>
+            {
+                if (VisualRoot is Window window)
+                    window.SystemDecorations = (SystemDecorations)decorations.SelectedIndex;
+            };
+
+            var transparencyLevels = this.Find<ComboBox>("TransparencyLevels");
+            transparencyLevels.SelectionChanged += (sender, e) =>
+            {
+                if (VisualRoot is Window window)
+                    window.TransparencyLevelHint = (WindowTransparencyLevel)transparencyLevels.SelectedIndex;
             };
-            Styles.Add(light);
+        }
+
+        protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+        {
+            base.OnAttachedToVisualTree(e);
+            var decorations = this.Find<ComboBox>("Decorations");
+            if (VisualRoot is Window window)
+                decorations.SelectedIndex = (int)window.SystemDecorations;
         }
     }
 }

+ 65 - 9
samples/ControlCatalog/MainWindow.xaml

@@ -7,13 +7,69 @@
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:vm="clr-namespace:ControlCatalog.ViewModels"
         xmlns:v="clr-namespace:ControlCatalog.Views"
-        x:Class="ControlCatalog.MainWindow">
-    <Window.DataTemplates>
-        <DataTemplate DataType="vm:NotificationViewModel">
-            <v:CustomNotificationView />
-        </DataTemplate>
-    </Window.DataTemplates>
-    <Panel>
-        <local:MainView/>
-    </Panel>
+        x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}" Background="{DynamicResource SystemControlPageBackgroundAltHighBrush}">
+  <NativeMenu.Menu>
+    <NativeMenu>
+      <NativeMenuItem Header="File">
+        <NativeMenuItem.Menu>
+          <NativeMenu>
+            <NativeMenuItem Icon="/Assets/test_icon.ico" Header="Open" Clicked="OnOpenClicked" Gesture="Ctrl+O"/>
+            <NativeMenuItemSeperator/>
+            <NativeMenuItem Icon="/Assets/github_icon.png" Header="Recent">
+              <NativeMenuItem.Menu>
+                <NativeMenu/>
+              </NativeMenuItem.Menu>
+            </NativeMenuItem>
+            <NativeMenuItemSeperator/>
+            <NativeMenuItem Header="{x:Static local:MainWindow.MenuQuitHeader}"
+                            Gesture="{x:Static local:MainWindow.MenuQuitGesture}"
+                            Clicked="OnCloseClicked" />
+          </NativeMenu>
+        </NativeMenuItem.Menu>
+      </NativeMenuItem>
+      <NativeMenuItem Header="Edit">
+        <NativeMenuItem.Menu>
+          <NativeMenu>
+            <NativeMenuItem Header="Copy"/>
+            <NativeMenuItem Header="Paste"/>
+          </NativeMenu>
+        </NativeMenuItem.Menu>
+      </NativeMenuItem>
+      <NativeMenuItem Header="Options">
+        <NativeMenuItem.Menu>
+          <NativeMenu>
+           <NativeMenuItem Header="Check Me (None)" 
+                            Command="{Binding ToggleMenuItemCheckedCommand}"
+                            ToggleType="None"
+                            IsChecked="{Binding IsMenuItemChecked}"  />
+            <NativeMenuItem Header="Check Me (CheckBox)" 
+                            Command="{Binding ToggleMenuItemCheckedCommand}"
+                            ToggleType="CheckBox"
+                            IsChecked="{Binding IsMenuItemChecked}"  />
+            <NativeMenuItem Header="Check Me (Radio)" 
+                            Command="{Binding ToggleMenuItemCheckedCommand}"
+                            ToggleType="Radio"
+                            IsChecked="{Binding IsMenuItemChecked}"  />
+          </NativeMenu>
+        </NativeMenuItem.Menu>
+      </NativeMenuItem>
+    </NativeMenu>
+  </NativeMenu.Menu>
+
+ <Window.DataTemplates>
+    <DataTemplate DataType="vm:NotificationViewModel">
+      <v:CustomNotificationView />
+    </DataTemplate>
+  </Window.DataTemplates>
+  <DockPanel LastChildFill="True">
+    <Menu Name="MainMenu" DockPanel.Dock="Top">
+      <MenuItem Header="File">
+        <MenuItem Header="Exit" Command="{Binding ExitCommand}" />
+      </MenuItem>
+      <MenuItem Header="Help">
+        <MenuItem Header="About" Command="{Binding AboutCommand}" />
+      </MenuItem>
+    </Menu>
+    <local:MainView />
+  </DockPanel>
 </Window>

+ 32 - 4
samples/ControlCatalog/MainWindow.xaml.cs

@@ -1,18 +1,18 @@
+using System;
+using System.Runtime.InteropServices;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls.Notifications;
-using Avalonia.Controls.Primitives;
+using Avalonia.Input;
 using Avalonia.Markup.Xaml;
-using Avalonia.Threading;
 using ControlCatalog.ViewModels;
-using System;
-using System.Threading.Tasks;
 
 namespace ControlCatalog
 {
     public class MainWindow : Window
     {
         private WindowNotificationManager _notificationArea;
+        private NativeMenu _recentMenu;
 
         public MainWindow()
         {
@@ -28,6 +28,34 @@ namespace ControlCatalog
             };
 
             DataContext = new MainWindowViewModel(_notificationArea);
+            _recentMenu = ((NativeMenu.GetMenu(this).Items[0] as NativeMenuItem).Menu.Items[2] as NativeMenuItem).Menu;
+
+            var mainMenu = this.FindControl<Menu>("MainMenu");
+            mainMenu.AttachedToVisualTree += MenuAttached;
+        }
+
+        public static string MenuQuitHeader => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "Quit Avalonia" : "E_xit";
+
+        public static KeyGesture MenuQuitGesture => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
+            new KeyGesture(Key.Q, KeyModifiers.Meta) :
+            new KeyGesture(Key.F4, KeyModifiers.Alt);
+
+        public void MenuAttached(object sender, VisualTreeAttachmentEventArgs e)
+        {
+            if (NativeMenu.GetIsNativeMenuExported(this) && sender is Menu mainMenu)
+            {
+                mainMenu.IsVisible = false;
+            }
+        }
+
+        public void OnOpenClicked(object sender, EventArgs args)
+        {
+            _recentMenu.Items.Insert(0, new NativeMenuItem("Item " + (_recentMenu.Items.Count + 1)));
+        }
+
+        public void OnCloseClicked(object sender, EventArgs args)
+        {
+            Close();
         }
 
         private void InitializeComponent()

+ 3 - 3
samples/ControlCatalog/Models/Person.cs

@@ -21,12 +21,12 @@ namespace ControlCatalog.Models
             get => _firstName;
             set
             {
+                _firstName = value;
                 if (string.IsNullOrWhiteSpace(value))
                     SetError(nameof(FirstName), "First Name Required");
                 else
                     SetError(nameof(FirstName), null);
 
-                _firstName = value;
                 OnPropertyChanged(nameof(FirstName));
             }
 
@@ -37,12 +37,12 @@ namespace ControlCatalog.Models
             get => _lastName;
             set
             {
+                _lastName = value;
                 if (string.IsNullOrWhiteSpace(value))
                     SetError(nameof(LastName), "Last Name Required");
                 else
                     SetError(nameof(LastName), null);
 
-                _lastName = value;
                 OnPropertyChanged(nameof(LastName));
             }
         }
@@ -95,4 +95,4 @@ namespace ControlCatalog.Models
                 return null;
         }
     }
-}
+}

+ 7 - 0
samples/ControlCatalog/Pages/BorderPage.xaml

@@ -29,6 +29,13 @@
               Padding="16">
         <TextBlock>Rounded Corners</TextBlock>
       </Border>
+      <Border BorderBrush="{DynamicResource ThemeAccentBrush2}" Width="100" Height="100"
+              BorderThickness="0"
+              Background="White"
+              CornerRadius="100" ClipToBounds="True">
+        <Image Source="/Assets/maple-leaf-888807_640.jpg" Stretch="UniformToFill" />
+      </Border>
+      <TextBlock Text="Border with Clipping" HorizontalAlignment="Center" />
     </StackPanel>    
   </StackPanel>
 </UserControl>

+ 5 - 1
samples/ControlCatalog/Pages/ButtonPage.xaml

@@ -24,7 +24,11 @@
             </Style>
           </Button.Styles>          
         </Button>
-      </StackPanel>
+        <RepeatButton Name="RepeatButton">
+          <TextBlock Name="RepeatButtonTextBlock" Text="Repeat Button: 0" />
+        </RepeatButton>
+        <ToggleButton Content="Toggle Button"/>
+    </StackPanel>
 
       <StackPanel Orientation="Vertical" Spacing="8" Width="150">
         <Button BorderThickness="0">No Border</Button>

+ 20 - 0
samples/ControlCatalog/Pages/ButtonPage.xaml.cs

@@ -5,5 +5,25 @@ namespace ControlCatalog.Pages
 {
     public class ButtonPage : UserControl
     {
+        private int repeatButtonClickCount = 0;
+
+        public ButtonPage()
+        {
+            InitializeComponent();
+
+            this.FindControl<RepeatButton>("RepeatButton").Click += OnRepeatButtonClick;
+        }
+
+        private void InitializeComponent()
+        {
+            AvaloniaXamlLoader.Load(this);
+        }
+
+        public void OnRepeatButtonClick(object sender, object args)
+        {
+            repeatButtonClickCount++;
+            var textBlock = this.FindControl<TextBlock>("RepeatButtonTextBlock");
+            textBlock.Text = $"Repeat Button: {repeatButtonClickCount}";
+        }
     }
 }

+ 9 - 9
samples/ControlCatalog/Pages/DatePickerPage.xaml → samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml

@@ -1,8 +1,8 @@
 <UserControl xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-             x:Class="ControlCatalog.Pages.DatePickerPage">
+             x:Class="ControlCatalog.Pages.CalendarDatePickerPage">
   <StackPanel Orientation="Vertical" Spacing="4">
-    <TextBlock Classes="h1">DatePicker</TextBlock>
+    <TextBlock Classes="h1">CalendarDatePicker</TextBlock>
     <TextBlock Classes="h2">A control for selecting dates with a calendar drop-down</TextBlock>
         
     <StackPanel Orientation="Horizontal"
@@ -12,34 +12,34 @@
       <StackPanel Orientation="Vertical"
                   Width="200">
         <TextBlock Text="SelectedDateFormat: Short"/>
-        <DatePicker Name="DatePicker1"
+        <CalendarDatePicker Name="DatePicker1"
                     SelectedDateFormat="Short"
                     Margin="0,0,0,8"/>
 
         <TextBlock Text="SelectedDateFormat: Long"/>
-        <DatePicker Name="DatePicker2"
+        <CalendarDatePicker Name="DatePicker2"
                     SelectedDateFormat="Long"
                     Margin="0,0,0,8"/>
 
         <TextBlock Text="SelectedDateFormat: Custom"/>
-        <DatePicker Name="DatePicker3"
+        <CalendarDatePicker Name="DatePicker3"
                     SelectedDateFormat="Custom"
                     CustomDateFormatString="ddd, MMM d"
                     Margin="0,0,0,8"/>
 
         <TextBlock Text="Blackout Dates"/>
-        <DatePicker Name="DatePicker4"
+        <CalendarDatePicker Name="DatePicker4"
                     Margin="0,0,0,8"/>
 
-        <DatePicker Margin="0,0,0,8"
+        <CalendarDatePicker Margin="0,0,0,8"
                     Watermark="Watermark"/>
-        <DatePicker Margin="0,0,0,8"
+        <CalendarDatePicker Margin="0,0,0,8"
                     Name="DatePicker5"
                     Watermark="Floating Watermark"
                     UseFloatingWatermark="True"/>
                 
         <TextBlock Text="Disabled"/>
-        <DatePicker IsEnabled="False"/>
+        <CalendarDatePicker IsEnabled="False"/>
       </StackPanel>
 
     </StackPanel> 

+ 7 - 7
samples/ControlCatalog/Pages/DatePickerPage.xaml.cs → samples/ControlCatalog/Pages/CalendarDatePickerPage.xaml.cs

@@ -4,17 +4,17 @@ using System;
 
 namespace ControlCatalog.Pages
 {
-    public class DatePickerPage : UserControl
+    public class CalendarDatePickerPage : UserControl
     {
-        public DatePickerPage()
+        public CalendarDatePickerPage()
         {
             InitializeComponent();
             
-            var dp1 = this.FindControl<DatePicker>("DatePicker1");
-            var dp2 = this.FindControl<DatePicker>("DatePicker2");
-            var dp3 = this.FindControl<DatePicker>("DatePicker3");
-            var dp4 = this.FindControl<DatePicker>("DatePicker4");
-            var dp5 = this.FindControl<DatePicker>("DatePicker5");
+            var dp1 = this.FindControl<CalendarDatePicker>("DatePicker1");
+            var dp2 = this.FindControl<CalendarDatePicker>("DatePicker2");
+            var dp3 = this.FindControl<CalendarDatePicker>("DatePicker3");
+            var dp4 = this.FindControl<CalendarDatePicker>("DatePicker4");
+            var dp5 = this.FindControl<CalendarDatePicker>("DatePicker5");
 
             dp1.SelectedDate = DateTime.Today;
             dp2.SelectedDate = DateTime.Today.AddDays(10);

+ 1 - 1
samples/ControlCatalog/Pages/ComboBoxPage.xaml

@@ -6,7 +6,7 @@
     <TextBlock Classes="h2">A drop-down list.</TextBlock>
 
     <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Spacing="8">
-      <ComboBox SelectedIndex="0">
+      <ComboBox PlaceholderText="Pick an Item">
         <ComboBoxItem>Inline Items</ComboBoxItem>
         <ComboBoxItem>Inline Item 2</ComboBoxItem>
         <ComboBoxItem>Inline Item 3</ComboBoxItem>

+ 3 - 1
samples/ControlCatalog/Pages/ComboBoxPage.xaml.cs

@@ -1,5 +1,7 @@
+using System.Linq;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
+using Avalonia.Media;
 
 namespace ControlCatalog.Pages
 {
@@ -14,7 +16,7 @@ namespace ControlCatalog.Pages
         {
             AvaloniaXamlLoader.Load(this);
             var fontComboBox = this.Find<ComboBox>("fontComboBox");
-            fontComboBox.Items = Avalonia.Media.FontFamily.SystemFontFamilies;
+            fontComboBox.Items = FontManager.Current.GetInstalledFontFamilyNames().Select(x => new FontFamily(x));
             fontComboBox.SelectedIndex = 0;
         }
     }

+ 4 - 0
samples/ControlCatalog/Pages/DialogsPage.xaml

@@ -6,8 +6,12 @@
       <Button Name="OpenFile">Open File</Button>
       <Button Name="SaveFile">Save File</Button>
       <Button Name="SelectFolder">Select Folder</Button>
+      <Button Name="OpenBoth">Select Both</Button>
       <Button Name="DecoratedWindow">Decorated window</Button>
       <Button Name="DecoratedWindowDialog">Decorated window (dialog)</Button>
       <Button Name="Dialog">Dialog</Button>
+      <Button Name="DialogNoTaskbar">Dialog (No taskbar icon)</Button>
+      <Button Name="OwnedWindow">Owned window</Button>
+      <Button Name="OwnedWindowNoTaskbar">Owned window (No taskbar icon)</Button>
   </StackPanel>
 </UserControl>

+ 61 - 11
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@@ -1,5 +1,9 @@
+using System;
 using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
 using Avalonia.Controls;
+using Avalonia.Dialogs;
 using Avalonia.Markup.Xaml;
 #pragma warning disable 4014
 
@@ -34,7 +38,9 @@ namespace ControlCatalog.Pages
                 new OpenFileDialog()
                 {
                     Title = "Open file",
-                    Filters = GetFilters()
+                    Filters = GetFilters(),
+                    // Almost guaranteed to exist
+                    InitialFileName = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName
                 }.ShowAsync(GetWindow());
             };
             this.FindControl<Button>("SaveFile").Click += delegate
@@ -42,16 +48,30 @@ namespace ControlCatalog.Pages
                 new SaveFileDialog()
                 {
                     Title = "Save file",
-                    Filters = GetFilters()
+                    Filters = GetFilters(),
+                    InitialFileName = "test.txt"
                 }.ShowAsync(GetWindow());
             };
             this.FindControl<Button>("SelectFolder").Click += delegate
             {
                 new OpenFolderDialog()
                 {
-                    Title = "Select folder"
+                    Title = "Select folder",
                 }.ShowAsync(GetWindow());
             };
+            this.FindControl<Button>("OpenBoth").Click += async delegate
+            {
+                var res = await new OpenFileDialog()
+                {
+                    Title = "Select both",
+                    AllowMultiple = true
+                }.ShowManagedAsync(GetWindow(), new ManagedFileDialogOptions
+                {
+                    AllowDirectorySelection = true
+                });
+                if (res != null)
+                    Console.WriteLine("Selected: \n" + string.Join("\n", res));
+            };
             this.FindControl<Button>("DecoratedWindow").Click += delegate
             {
                 new DecoratedWindow().Show();
@@ -61,14 +81,44 @@ namespace ControlCatalog.Pages
                 new DecoratedWindow().ShowDialog(GetWindow());
             };
             this.FindControl<Button>("Dialog").Click += delegate
-                {
-                    var window = new Window();
-                    window.Height = 200;
-                    window.Width = 200;
-                    window.Content = new TextBlock { Text = "Hello world!" };
-                    window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
-                    window.ShowDialog(GetWindow());
-                };
+            {
+                var window = CreateSampleWindow();
+                window.Height = 200;
+                window.ShowDialog(GetWindow());
+            };
+            this.FindControl<Button>("DialogNoTaskbar").Click += delegate
+            {
+                var window = CreateSampleWindow();
+                window.Height = 200;
+                window.ShowInTaskbar = false;
+                window.ShowDialog(GetWindow());
+            };
+            this.FindControl<Button>("OwnedWindow").Click += delegate
+            {
+                var window = CreateSampleWindow();
+
+                window.Show(GetWindow());
+            };
+
+            this.FindControl<Button>("OwnedWindowNoTaskbar").Click += delegate
+            {
+                var window = CreateSampleWindow();
+
+                window.ShowInTaskbar = false;
+
+                window.Show(GetWindow());
+            };
+        }
+
+        private Window CreateSampleWindow()
+        {
+            var window = new Window();
+            window.Height = 200;
+            window.Width = 200;
+            window.Content = new TextBlock { Text = "Hello world!" };
+            window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
+
+            return window;
         }
 
         Window GetWindow() => (Window)this.VisualRoot;

+ 9 - 3
samples/ControlCatalog/Pages/DragAndDropPage.xaml

@@ -9,9 +9,15 @@
                 Margin="0,16,0,0"
                 HorizontalAlignment="Center"
                 Spacing="16">
-            <Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16" Name="DragMe">
-                <TextBlock Name="DragState">Drag Me</TextBlock>
-            </Border>
+            <StackPanel>
+                <Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16" Name="DragMeText">
+                  <TextBlock Name="DragStateText">Drag Me</TextBlock>
+                </Border>
+                <Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16" Name="DragMeCustom">
+                  <TextBlock Name="DragStateCustom">Drag Me (custom)</TextBlock>
+                </Border>
+            </StackPanel>
+
             <Border Background="{DynamicResource ThemeAccentBrush2}" Padding="16" 
                     DragDrop.AllowDrop="True">
                 <TextBlock Name="DropState">Drop some text or files here</TextBlock>

+ 54 - 38
samples/ControlCatalog/Pages/DragAndDropPage.xaml.cs

@@ -3,69 +3,85 @@ using Avalonia.Input;
 using Avalonia.Markup.Xaml;
 using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
 using System.Text;
 
 namespace ControlCatalog.Pages
 {
     public class DragAndDropPage : UserControl
     {
-        private TextBlock _DropState;
-        private TextBlock _DragState;
-        private Border _DragMe;
-        private int DragCount = 0;
-
+        TextBlock _DropState;
+        private const string CustomFormat = "application/xxx-avalonia-controlcatalog-custom";
         public DragAndDropPage()
         {
             this.InitializeComponent();
+            _DropState = this.Find<TextBlock>("DropState");
 
-            _DragMe.PointerPressed += DoDrag;
+            int textCount = 0;
+            SetupDnd("Text", d => d.Set(DataFormats.Text,
+                $"Text was dragged {++textCount} times"));
 
-            AddHandler(DragDrop.DropEvent, Drop);
-            AddHandler(DragDrop.DragOverEvent, DragOver);
+            SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"));
         }
 
-        private async void DoDrag(object sender, Avalonia.Input.PointerPressedEventArgs e)
+        void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects = DragDropEffects.Copy)
         {
-            DataObject dragData = new DataObject();
-            dragData.Set(DataFormats.Text, $"You have dragged text {++DragCount} times");
+            var dragMe = this.Find<Border>("DragMe" + suffix);
+            var dragState = this.Find<TextBlock>("DragState"+suffix);
 
-            var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy);
-            switch(result)
+            async void DoDrag(object sender, Avalonia.Input.PointerPressedEventArgs e)
             {
-                case DragDropEffects.Copy:
-                    _DragState.Text = "The text was copied"; break;
-                case DragDropEffects.Link:
-                    _DragState.Text = "The text was linked"; break;
-                case DragDropEffects.None:
-                    _DragState.Text = "The drag operation was canceled"; break;
+                var dragData = new DataObject();
+                factory(dragData);
+
+                var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy);
+                switch (result)
+                {
+                    case DragDropEffects.Copy:
+                        dragState.Text = "Data was copied";
+                        break;
+                    case DragDropEffects.Link:
+                        dragState.Text = "Data was linked";
+                        break;
+                    case DragDropEffects.None:
+                        dragState.Text = "The drag operation was canceled";
+                        break;
+                }
             }
-        }
 
-        private void DragOver(object sender, DragEventArgs e)
-        {
-            // Only allow Copy or Link as Drop Operations.
-            e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);
+            void DragOver(object sender, DragEventArgs e)
+            {
+                // Only allow Copy or Link as Drop Operations.
+                e.DragEffects = e.DragEffects & (DragDropEffects.Copy | DragDropEffects.Link);
 
-            // Only allow if the dragged data contains text or filenames.
-            if (!e.Data.Contains(DataFormats.Text) && !e.Data.Contains(DataFormats.FileNames))
-                e.DragEffects = DragDropEffects.None; 
-        }
+                // Only allow if the dragged data contains text or filenames.
+                if (!e.Data.Contains(DataFormats.Text)
+                    && !e.Data.Contains(DataFormats.FileNames)
+                    && !e.Data.Contains(CustomFormat))
+                    e.DragEffects = DragDropEffects.None;
+            }
 
-        private void Drop(object sender, DragEventArgs e)
-        {
-            if (e.Data.Contains(DataFormats.Text))
-                _DropState.Text = e.Data.GetText();
-            else if (e.Data.Contains(DataFormats.FileNames))
-                _DropState.Text = string.Join(Environment.NewLine, e.Data.GetFileNames());
+            void Drop(object sender, DragEventArgs e)
+            {
+                if (e.Data.Contains(DataFormats.Text))
+                    _DropState.Text = e.Data.GetText();
+                else if (e.Data.Contains(DataFormats.FileNames))
+                    _DropState.Text = string.Join(Environment.NewLine, e.Data.GetFileNames());
+                else if (e.Data.Contains(CustomFormat))
+                    _DropState.Text = "Custom: " + e.Data.Get(CustomFormat);
+            }
+
+            dragMe.PointerPressed += DoDrag;
+
+            AddHandler(DragDrop.DropEvent, Drop);
+            AddHandler(DragDrop.DragOverEvent, DragOver);
         }
 
         private void InitializeComponent()
         {
             AvaloniaXamlLoader.Load(this);
-
-            _DropState = this.Find<TextBlock>("DropState");
-            _DragState = this.Find<TextBlock>("DragState");
-            _DragMe = this.Find<Border>("DragMe");
         }
     }
 }

+ 62 - 38
samples/ControlCatalog/Pages/ImagePage.xaml

@@ -1,45 +1,69 @@
 <UserControl xmlns="https://github.com/avaloniaui"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              x:Class="ControlCatalog.Pages.ImagePage">
-  <StackPanel Orientation="Vertical" Spacing="4">
-    <TextBlock Classes="h1">Image</TextBlock>
-    <TextBlock Classes="h2">Displays an image</TextBlock>
-
-    <StackPanel Orientation="Horizontal"
-                Margin="0,16,0,0"
-                HorizontalAlignment="Center"
-                Spacing="16">
-      <StackPanel Orientation="Vertical">
-        <TextBlock>No Stretch</TextBlock>
-        <Image Source="/Assets/delicate-arch-896885_640.jpg"
-               Width="100" Height="200"
-               Stretch="None"/>
-      </StackPanel>
+  <DockPanel>
+    <StackPanel DockPanel.Dock="Top" Orientation="Vertical" Spacing="4">
+      <TextBlock Classes="h1">Image</TextBlock>
+      <TextBlock Classes="h2">Displays an image</TextBlock>
+    </StackPanel>
 
-      <StackPanel Orientation="Vertical">
-        <TextBlock>Fill</TextBlock>
-        <Image Source="/Assets/delicate-arch-896885_640.jpg"
-               Width="100" Height="200"
-               Stretch="Fill"/>
-      </StackPanel>
+    <Grid ColumnDefinitions="*,*,*" RowDefinitions="Auto,*" Margin="64">
+      
+      <DockPanel Grid.Column="0" Grid.Row="1" Margin="16">
+        <TextBlock DockPanel.Dock="Top" Classes="h3" Margin="0 8">Bitmap</TextBlock>
+        <ComboBox Name="bitmapStretch" DockPanel.Dock="Top" SelectedIndex="2" SelectionChanged="BitmapStretchChanged">
+          <ComboBoxItem>None</ComboBoxItem>
+          <ComboBoxItem>Fill</ComboBoxItem>
+          <ComboBoxItem>Uniform</ComboBoxItem>
+          <ComboBoxItem>UniformToFill</ComboBoxItem>
+        </ComboBox>
+        <Image Name="bitmapImage"
+               Source="/Assets/delicate-arch-896885_640.jpg"/>
+      </DockPanel>
 
-      <StackPanel Orientation="Vertical">
-        <TextBlock>Uniform</TextBlock>
-        <Image Source="/Assets/delicate-arch-896885_640.jpg"
-                Width="100" Height="200"
-                Stretch="Uniform"/>
-      </StackPanel>
+      <DockPanel Grid.Column="1" Grid.Row="1" Margin="16">
+        <TextBlock DockPanel.Dock="Top" Classes="h3" Margin="0 8">Crop</TextBlock>
+        <ComboBox Name="bitmapCrop" DockPanel.Dock="Top" SelectedIndex="2" SelectionChanged="BitmapCropChanged">
+          <ComboBoxItem>None</ComboBoxItem>
+          <ComboBoxItem>Center</ComboBoxItem>
+          <ComboBoxItem>TopLeft</ComboBoxItem>
+          <ComboBoxItem>TopRight</ComboBoxItem>
+          <ComboBoxItem>BottomLeft</ComboBoxItem>
+          <ComboBoxItem>BottomRight</ComboBoxItem>
+        </ComboBox>
+        <Image Name="croppedImage">
+          <Image.Source>
+            <CroppedBitmap  Source="/Assets/delicate-arch-896885_640.jpg" SourceRect="0 0 320 240"/>  
+          </Image.Source>
+        </Image>
+      </DockPanel>
 
-      <StackPanel Orientation="Vertical">
-        <TextBlock>UniformToFill</TextBlock>
-        <Image Source="/Assets/delicate-arch-896885_640.jpg"
-               Width="100" Height="200"
-               Stretch="UniformToFill"/>
-      </StackPanel>
-    </StackPanel>
-    <StackPanel Orientation="Vertical">
-      <TextBlock>Window Icon as an Image</TextBlock>
-      <Image Name="Icon" Width="100" Height="200" Stretch="None" />
-    </StackPanel>
-  </StackPanel>
+      <DockPanel Grid.Column="2" Grid.Row="1" Margin="16">
+        <TextBlock DockPanel.Dock="Top" Classes="h3" Margin="0 8">Drawing</TextBlock>
+        <ComboBox Name="drawingStretch" DockPanel.Dock="Top" SelectedIndex="2" SelectionChanged="DrawingStretchChanged">
+          <ComboBoxItem>None</ComboBoxItem>
+          <ComboBoxItem>Fill</ComboBoxItem>
+          <ComboBoxItem>Uniform</ComboBoxItem>
+          <ComboBoxItem>UniformToFill</ComboBoxItem>
+        </ComboBox>
+        <Image Name="drawingImage">
+          <Image.Source>
+            <DrawingImage>
+              <GeometryDrawing Brush="Red">
+                <PathGeometry>
+                  <PathFigure StartPoint="0,0" IsClosed="True">
+                    <QuadraticBezierSegment Point1="50,0" Point2="50,-50" />
+                    <QuadraticBezierSegment Point1="100,-50" Point2="100,0" />
+                    <LineSegment Point="50,0" />
+                    <LineSegment Point="50,50" />
+                  </PathFigure>
+                </PathGeometry>
+              </GeometryDrawing>
+            </DrawingImage>
+          </Image.Source>
+        </Image>
+      </DockPanel>
+    </Grid>
+    
+  </DockPanel>
 </UserControl>

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно