Jelajahi Sumber

Merge branch 'master' into scenegraph

 Conflicts:
	src/Gtk/Avalonia.Gtk/WindowImplBase.cs
	src/Skia/Avalonia.Skia.Android/RenderTarget.cs
	src/Skia/Avalonia.Skia.Android/SkiaRenderView.cs
	tests/Avalonia.Input.UnitTests/InputElement_HitTesting.cs
	tests/Avalonia.LeakTests/ControlTests.cs
Steven Kirk 8 tahun lalu
induk
melakukan
ff9654a7b0
100 mengubah file dengan 5641 tambahan dan 1166 penghapusan
  1. 2 0
      .gitignore
  2. 181 35
      Avalonia.sln
  3. 120 576
      build.cake
  4. 469 0
      packages.cake
  5. 143 0
      parameters.cake
  6. 4 1
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  7. 5 19
      samples/ControlCatalog.Android/MainActivity.cs
  8. 7 0
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  9. 15 12
      samples/ControlCatalog/Pages/TreeViewPage.xaml.cs
  10. 14 11
      src/Android/Avalonia.Android/AndroidPlatform.cs
  11. 9 3
      src/Android/Avalonia.Android/AndroidThreadingInterface.cs
  12. 5 4
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  13. 50 0
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  14. 59 0
      src/Android/Avalonia.Android/AvaloniaView.cs
  15. 101 0
      src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs
  16. 4 4
      src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs
  17. 0 44
      src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs
  18. 16 22
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  19. 0 60
      src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs
  20. 1 1
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs
  21. 1 1
      src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs
  22. 0 12
      src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs
  23. 8 9
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  24. 8 24
      src/Android/Avalonia.AndroidTestApplication/MainActivity.cs
  25. 2 1
      src/Android/Avalonia.AndroidTestApplication/packages.config
  26. 2 2
      src/Avalonia.Animation/Avalonia.Animation.csproj
  27. 2 2
      src/Avalonia.Base/Avalonia.Base.csproj
  28. 5 2
      src/Avalonia.Controls/Avalonia.Controls.csproj
  29. 2 1
      src/Avalonia.Controls/Expander.cs
  30. 13 0
      src/Avalonia.Controls/Platform/ITopLevelImpl.cs
  31. 0 5
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  32. 19 0
      src/Avalonia.Controls/Platform/Surfaces/IFramebufferPlatformSurface.cs
  33. 37 0
      src/Avalonia.Controls/Platform/Surfaces/ILockedFramebuffer.cs
  34. 15 0
      src/Avalonia.Controls/Platform/Surfaces/PixelFormat.cs
  35. 4 2
      src/Avalonia.Controls/TopLevel.cs
  36. 0 20
      src/Avalonia.Controls/Window.cs
  37. 2 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  38. 2 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  39. 53 0
      src/Avalonia.DotNetCoreRuntime/AppBuilder.cs
  40. 89 0
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj
  41. 5 0
      src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.v3.ncrunchproject
  42. 47 0
      src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs
  43. 41 0
      src/Avalonia.DotNetCoreRuntime/RuntimeInfo.cs
  44. 11 0
      src/Avalonia.DotNetCoreRuntime/project.json
  45. 2 2
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
  46. 6 0
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.v3.ncrunchproject
  47. 2 2
      src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
  48. 2 2
      src/Avalonia.Input/Avalonia.Input.csproj
  49. 2 2
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  50. 2 2
      src/Avalonia.Layout/Avalonia.Layout.csproj
  51. 2 2
      src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
  52. 2 2
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  53. 2 2
      src/Avalonia.Styling/Avalonia.Styling.csproj
  54. 2 2
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  55. 2 2
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  56. 5 2
      src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs
  57. 7 15
      src/Gtk/Avalonia.Cairo/CairoPlatform.cs
  58. 6 13
      src/Gtk/Avalonia.Cairo/RenderTarget.cs
  59. 5 0
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  60. 39 0
      src/Gtk/Avalonia.Gtk/FramebufferManager.cs
  61. 1 208
      src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs
  62. 224 0
      src/Gtk/Avalonia.Gtk/KeyTransform.cs
  63. 55 0
      src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs
  64. 2 2
      src/Gtk/Avalonia.Gtk/SystemDialogImpl.cs
  65. 1 1
      src/Gtk/Avalonia.Gtk/WindowImpl.cs
  66. 21 14
      src/Gtk/Avalonia.Gtk/WindowImplBase.cs
  67. 1 0
      src/Gtk/Avalonia.Gtk3/.gitignore
  68. 103 0
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  69. 5 0
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.v3.ncrunchproject
  70. 53 0
      src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs
  71. 79 0
      src/Gtk/Avalonia.Gtk3/CursorFactory.cs
  72. 32 0
      src/Gtk/Avalonia.Gtk3/FramebufferManager.cs
  73. 91 0
      src/Gtk/Avalonia.Gtk3/GdkCursor.cs
  74. 1347 0
      src/Gtk/Avalonia.Gtk3/GdkKey.cs
  75. 116 0
      src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
  76. 54 0
      src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs
  77. 20 0
      src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs
  78. 129 0
      src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs
  79. 33 0
      src/Gtk/Avalonia.Gtk3/Interop/GException.cs
  80. 62 0
      src/Gtk/Avalonia.Gtk3/Interop/GObject.cs
  81. 64 0
      src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
  82. 17 0
      src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs
  83. 571 0
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  84. 24 0
      src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs
  85. 68 0
      src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs
  86. 155 0
      src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs
  87. 50 0
      src/Gtk/Avalonia.Gtk3/Interop/Signal.cs
  88. 45 0
      src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs
  89. 20 0
      src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs
  90. 24 0
      src/Gtk/Avalonia.Gtk3/PopupImpl.cs
  91. 5 5
      src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
  92. 8 0
      src/Gtk/Avalonia.Gtk3/README.md
  93. 92 0
      src/Gtk/Avalonia.Gtk3/SystemDialogs.cs
  94. 336 0
      src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs
  95. 45 0
      src/Gtk/Avalonia.Gtk3/WindowImpl.cs
  96. 10 0
      src/Gtk/Avalonia.Gtk3/project.json
  97. 2 3
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  98. 5 1
      src/Markup/Avalonia.Markup.Xaml/packages.config
  99. 4 2
      src/Shared/PlatformSupport/AssetLoader.cs
  100. 6 3
      src/Shared/PlatformSupport/StandardRuntimePlatform.cs

+ 2 - 0
.gitignore

@@ -161,3 +161,5 @@ tools/
 .nuget
 .nuget
 artifacts/
 artifacts/
 nuget
 nuget
+Avalonia.XBuild.sln
+project.lock.json

+ 181 - 35
Avalonia.sln

@@ -99,8 +99,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop", "sr
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android", "src\Skia\Avalonia.Skia.Android\Avalonia.Skia.Android.csproj", "{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}"
 EndProject
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Android.TestApp", "src\Skia\Avalonia.Skia.Android.TestApp\Avalonia.Skia.Android.TestApp.csproj", "{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS.TestApp", "src\Skia\Avalonia.Skia.iOS.TestApp\Avalonia.Skia.iOS.TestApp.csproj", "{DA49C5F3-BE95-461C-B999-072128CCF59E}"
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.iOS", "src\Skia\Avalonia.Skia.iOS\Avalonia.Skia.iOS.csproj", "{47BE08A7-5985-410B-9FFC-2264B8EA595F}"
@@ -130,6 +128,9 @@ EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog", "samples\ControlCatalog\ControlCatalog.csproj", "{D0A739B9-3C68-4BA6-A328-41606954B6BD}"
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Desktop", "samples\ControlCatalog.Desktop\ControlCatalog.Desktop.csproj", "{2B888490-D14A-4BCA-AB4B-48676FA93C9B}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Desktop", "samples\ControlCatalog.Desktop\ControlCatalog.Desktop.csproj", "{2B888490-D14A-4BCA-AB4B-48676FA93C9B}"
+	ProjectSection(ProjectDependencies) = postProject
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {BB1F7BB5-6AD4-4776-94D9-C09D0A972658}
+	EndProjectSection
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.iOS", "samples\ControlCatalog.iOS\ControlCatalog.iOS.csproj", "{57E0455D-D565-44BB-B069-EE1AA20F8337}"
 EndProject
 EndProject
@@ -155,19 +156,35 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RenderTest", "samples\Rende
 EndProject
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
 EndProject
 EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Avalonia.Win32.Shared", "src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.shproj", "{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32.NetStandard", "src\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj", "{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.DotNetCoreRuntime", "src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj", "{7863EA94-F0FB-4386-BF8C-E5BFA761560A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Skia.Desktop.NetStandard", "src\Skia\Avalonia.Skia.Desktop.NetStandard\Avalonia.Skia.Desktop.NetStandard.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Gtk3", "src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj", "{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}"
+EndProject
 Global
 Global
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
 		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 = 4
+		src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{40759a76-d0f2-464e-8000-6ff0f5c4bd7c}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{4488ad85-1495-4809-9aa4-ddfe0a48527e}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{47be08a7-5985-410b-9ffc-2264b8ea595f}*SharedItemsImports = 4
 		tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{48840edd-24bf-495d-911e-2eb12ae75d3b}*SharedItemsImports = 13
 		tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{48840edd-24bf-495d-911e-2eb12ae75d3b}*SharedItemsImports = 13
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{4a1abb09-9047-4bd5-a4ad-a055e52c5ee0}*SharedItemsImports = 4
+		src\Shared\PlatformSupport\PlatformSupport.projitems*{7863ea94-f0fb-4386-bf8c-e5bfa761560a}*SharedItemsImports = 4
 		src\Shared\PlatformSupport\PlatformSupport.projitems*{7b92af71-6287-4693-9dcb-bd5b6e927e23}*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
+		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{7d2d3083-71dd-4cc9-8907-39a0d86fb322}*SharedItemsImports = 4
+		src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{811a76cf-1cf6-440f-963b-bbe31bd72a82}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{925dd807-b651-475f-9f7c-cbeb974ce43d}*SharedItemsImports = 4
+		src\Windows\Avalonia.Win32\Avalonia.Win32.Shared.projitems*{9defc6b7-845b-4d8f-afc0-d32bf0032b8c}*SharedItemsImports = 13
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
 		src\Shared\RenderHelpers\RenderHelpers.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
 		src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{bd43f7c0-396b-4aa1-bad9-dfde54d51298}*SharedItemsImports = 4
 		tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{d35a9f3d-8bb0-496e-bf72-444038a7debb}*SharedItemsImports = 4
 		tests\Avalonia.RenderTests\Avalonia.RenderTests.projitems*{d35a9f3d-8bb0-496e-bf72-444038a7debb}*SharedItemsImports = 4
@@ -1469,38 +1486,6 @@ Global
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|Mono.ActiveCfg = Release|Any CPU
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.ActiveCfg = Release|Any CPU
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298}.Release|x86.Build.0 = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|Mono.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Ad-Hoc|x86.Deploy.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhone.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|Mono.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Build.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.AppStore|x86.Deploy.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhone.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|Mono.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Build.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Debug|x86.Deploy.0 = Debug|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Build.0 = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Any CPU.Deploy.0 = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhone.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|Mono.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.ActiveCfg = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Build.0 = Release|Any CPU
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31}.Release|x86.Deploy.0 = Release|Any CPU
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|Any CPU.ActiveCfg = Ad-Hoc|iPhone
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
 		{DA49C5F3-BE95-461C-B999-072128CCF59E}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
@@ -2329,6 +2314,164 @@ Global
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.ActiveCfg = Release|Any CPU
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.ActiveCfg = Release|Any CPU
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Build.0 = Release|Any CPU
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Build.0 = Release|Any CPU
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Deploy.0 = Release|Any CPU
 		{29132311-1848-4FD6-AE0C-4FF841151BD3}.Release|x86.Deploy.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Mono.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|Mono.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.AppStore|x86.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|Mono.ActiveCfg = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Debug|x86.Build.0 = Debug|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Any CPU.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhone.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|Mono.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.ActiveCfg = Release|Any CPU
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C}.Release|x86.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Mono.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|Mono.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.AppStore|x86.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Mono.ActiveCfg = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|Mono.Build.0 = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Debug|x86.Build.0 = Debug|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhone.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Mono.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|Mono.Build.0 = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|x86.ActiveCfg = Release|Any CPU
+		{7863EA94-F0FB-4386-BF8C-E5BFA761560A}.Release|x86.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Mono.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|Mono.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.AppStore|x86.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Mono.ActiveCfg = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|Mono.Build.0 = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Debug|x86.Build.0 = Debug|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhone.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Mono.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|Mono.Build.0 = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|x86.ActiveCfg = Release|Any CPU
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|x86.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|x86.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Mono.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Mono.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|x86.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Mono.ActiveCfg = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Mono.Build.0 = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|x86.Build.0 = Debug|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Mono.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Mono.Build.0 = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|x86.ActiveCfg = Release|Any CPU
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 		HideSolutionNode = FALSE
@@ -2359,7 +2502,6 @@ Global
 		{2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{2F59F3D0-748D-4652-B01E-E0D954756308} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{925DD807-B651-475F-9F7C-CBEB974CE43D} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{BD43F7C0-396B-4AA1-BAD9-DFDE54D51298} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
-		{F92E55A5-ED73-4CCB-AB4B-0541B6757F31} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{DA49C5F3-BE95-461C-B999-072128CCF59E} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{47BE08A7-5985-410B-9FFC-2264B8EA595F} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
 		{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
 		{7B92AF71-6287-4693-9DCB-BD5B6E927E23} = {7CF9789C-F1D3-4D0E-90E5-F1DF67A2753F}
@@ -2382,5 +2524,9 @@ Global
 		{BD7F352C-6DC1-4740-BAF2-2D34A038728C} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
 		{BD7F352C-6DC1-4740-BAF2-2D34A038728C} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
 		{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
 		{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
 		{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
 		{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
+		{9DEFC6B7-845B-4D8F-AFC0-D32BF0032B8C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
+		{40759A76-D0F2-464E-8000-6FF0F5C4BD7C} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
+		{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
+		{BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3}
 	EndGlobalSection
 	EndGlobalSection
 EndGlobal
 EndGlobal

+ 120 - 576
build.cake

@@ -24,574 +24,118 @@ using Polly;
 using NuGet;
 using NuGet;
 
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// ARGUMENTS
+// SCRIPTS
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-var target = Argument("target", "Default");
-var platform = Argument("platform", "Any CPU");
-var configuration = Argument("configuration", "Release");
-var skipTests = HasArgument("skip-tests");
+#load "./parameters.cake"
+#load "./packages.cake"
 
 
-///////////////////////////////////////////////////////////////////////////////
-// CONFIGURATION
-///////////////////////////////////////////////////////////////////////////////
-
-var MainRepo = "AvaloniaUI/Avalonia";
-var MasterBranch = "master";
-var AssemblyInfoPath = File("./src/Shared/SharedAssemblyInfo.cs");
-var ReleasePlatform = "Any CPU";
-var ReleaseConfiguration = "Release";
-var MSBuildSolution = "./Avalonia.sln";
-var XBuildSolution = "./Avalonia.sln";
-
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
 // PARAMETERS
 // PARAMETERS
-///////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
 
 
-var isPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(platform, "Any CPU");
-var isPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(platform, "x86");
-var isPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(platform, "x64");
-var isLocalBuild = BuildSystem.IsLocalBuild;
-var isRunningOnUnix = IsRunningOnUnix();
-var isRunningOnWindows = IsRunningOnWindows();
-var isRunningOnAppVeyor = BuildSystem.AppVeyor.IsRunningOnAppVeyor;
-var isPullRequest = BuildSystem.AppVeyor.Environment.PullRequest.IsPullRequest;
-var isMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, BuildSystem.AppVeyor.Environment.Repository.Name);
-var isMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, BuildSystem.AppVeyor.Environment.Repository.Branch);
-var isTagged = BuildSystem.AppVeyor.Environment.Repository.Tag.IsTag 
-               && !string.IsNullOrWhiteSpace(BuildSystem.AppVeyor.Environment.Repository.Tag.Name);
-var isReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, platform) 
-                   && StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, configuration);
-var isMyGetRelease = !isTagged && isReleasable;
-var isNuGetRelease = isTagged && isReleasable;
+Parameters parameters = new Parameters(Context);
+Packages packages = new Packages(Context, parameters);
 
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// VERSION
+// SETUP
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-var version = ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion;
-
-if (isRunningOnAppVeyor)
+Setup(context =>
 {
 {
-    if (isTagged)
-    {
-        // Use Tag Name as version
-        version = BuildSystem.AppVeyor.Environment.Repository.Tag.Name;
-    }
-    else
+    Information("Building version {0} of Avalonia ({1}, {2}, {3}) using version {4} of Cake.", 
+        parameters.Version,
+        parameters.Platform,
+        parameters.Configuration,
+        parameters.Target,
+        typeof(ICakeContext).Assembly.GetName().Version.ToString());
+
+    if (parameters.IsRunningOnAppVeyor)
     {
     {
-        // Use AssemblyVersion with Build as version
-        version += "-build" + EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-alpha";
+        Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
+        Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
     }
     }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// DIRECTORIES
-///////////////////////////////////////////////////////////////////////////////
 
 
-var artifactsDir = (DirectoryPath)Directory("./artifacts");
-var nugetRoot = artifactsDir.Combine("nuget");
-var zipRoot = artifactsDir.Combine("zip");
-var binRoot = artifactsDir.Combine("bin");
-var testsRoot = artifactsDir.Combine("tests");
-
-var dirSuffix = configuration;
-var dirSuffixSkia = (isPlatformAnyCPU ? "x86" : platform) + "/" + configuration;
-var dirSuffixIOS = "iPhone" + "/" + configuration;
-
-var buildDirs = 
-    GetDirectories("./src/**/bin/" + dirSuffix) + 
-    GetDirectories("./src/**/obj/" + dirSuffix) + 
-    GetDirectories("./src/Markup/**/bin/" + dirSuffix) + 
-    GetDirectories("./src/Markup/**/obj/" + dirSuffix) + 
-    GetDirectories("./src/Android/**/bin/" + dirSuffix) + 
-    GetDirectories("./src/Android/**/obj/" + dirSuffix) + 
-    GetDirectories("./src/Gtk/**/bin/" + dirSuffix) + 
-    GetDirectories("./src/Gtk/**/obj/" + dirSuffix) + 
-    GetDirectories("./src/iOS/**/bin/" + dirSuffixIOS) + 
-    GetDirectories("./src/iOS/**/obj/" + dirSuffixIOS) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android/bin/" + dirSuffix) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android/obj/" + dirSuffix) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/bin/" + dirSuffix) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Android.TestApp/obj/" + dirSuffix) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.Desktop/obj/" + dirSuffixSkia) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + dirSuffixIOS) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS/obj/" + dirSuffixIOS) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/bin/" + dirSuffixIOS) + 
-    (DirectoryPath)Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/obj/" + dirSuffixIOS) + 
-    GetDirectories("./src/Windows/**/bin/" + dirSuffix) + 
-    GetDirectories("./src/Windows/**/obj/" + dirSuffix) + 
-    GetDirectories("./tests/**/bin/" + dirSuffix) + 
-    GetDirectories("./tests/**/obj/" + dirSuffix) + 
-    GetDirectories("./Samples/**/bin/" + dirSuffix) + 
-    GetDirectories("./Samples/**/obj/" + dirSuffix);
-
-var fileZipSuffix = version + ".zip";
-var zipCoreArtifacts = zipRoot.CombineWithFilePath("Avalonia-" + fileZipSuffix);
-var zipSourceControlCatalogDesktopDirs = (DirectoryPath)Directory("./samples/ControlCatalog.Desktop/bin/" + dirSuffix);
-var zipTargetControlCatalogDesktopDirs = zipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + fileZipSuffix);
+    Information("Target: " + parameters.Target);
+    Information("Platform: " + parameters.Platform);
+    Information("Configuration: " + parameters.Configuration);
+    Information("IsLocalBuild: " + parameters.IsLocalBuild);
+    Information("IsRunningOnUnix: " + parameters.IsRunningOnUnix);
+    Information("IsRunningOnWindows: " + parameters.IsRunningOnWindows);
+    Information("IsRunningOnAppVeyor: " + parameters.IsRunningOnAppVeyor);
+    Information("IsPullRequest: " + parameters.IsPullRequest);
+    Information("IsMainRepo: " + parameters.IsMainRepo);
+    Information("IsMasterBranch: " + parameters.IsMasterBranch);
+    Information("IsTagged: " + parameters.IsTagged);
+    Information("IsReleasable: " + parameters.IsReleasable);
+    Information("IsMyGetRelease: " + parameters.IsMyGetRelease);
+    Information("IsNuGetRelease: " + parameters.IsNuGetRelease);
+});
 
 
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
-// NUGET NUSPECS
+// TEARDOWN
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-Information("Getting git modules:");
-
-var ignoredSubModulesPaths = System.IO.File.ReadAllLines(".git/config").Where(m=>m.StartsWith("[submodule ")).Select(m => 
+Teardown(context =>
 {
 {
-    var path = m.Split(' ')[1].Trim("\"[] \t".ToArray());
-    Information(path);
-    return ((DirectoryPath)Directory(path)).FullPath;
-}).ToList();
-
-var normalizePath = new Func<string, string>(
-    path => path.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar).ToUpperInvariant());
-
-// Key: Package Id
-// Value is Tuple where Item1: Package Version, Item2: The packages.config file path.
-var packageVersions = new Dictionary<string, IList<Tuple<string,string>>>();
-
-System.IO.Directory.EnumerateFiles(((DirectoryPath)Directory("./src")).FullPath, "packages.config", SearchOption.AllDirectories).ToList().ForEach(fileName =>
-{
-    if (!ignoredSubModulesPaths.Any(i => normalizePath(fileName).Contains(normalizePath(i))))
-    {
-        var file = new PackageReferenceFile(fileName);
-        foreach (PackageReference packageReference in file.GetPackageReferences())
-        {
-            IList<Tuple<string, string>> versions;
-            packageVersions.TryGetValue(packageReference.Id, out versions);
-            if (versions == null)
-            {
-                versions = new List<Tuple<string, string>>();
-                packageVersions[packageReference.Id] = versions;
-            }
-            versions.Add(Tuple.Create(packageReference.Version.ToString(), fileName));
-        }
-    }
+    Information("Finished running tasks.");
 });
 });
 
 
-Information("Checking installed NuGet package dependencies versions:");
+///////////////////////////////////////////////////////////////////////////////
+// TASKS
+///////////////////////////////////////////////////////////////////////////////
 
 
-packageVersions.ToList().ForEach(package =>
+Task("Clean")
+    .Does(() =>
 {
 {
-    var packageVersion = package.Value.First().Item1;
-    bool isValidVersion = package.Value.All(x => x.Item1 == packageVersion);
-    if (!isValidVersion)
-    {
-        Information("Error: package {0} has multiple versions installed:", package.Key);
-        foreach (var v in package.Value)
-        {
-            Information("{0}, file: {1}", v.Item1, v.Item2);
-        }
-        throw new Exception("Detected multiple NuGet package version installed for different projects.");
-    }
-});
-
-Information("Setting NuGet package dependencies versions:");
-
-var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1;
-var SplatVersion = packageVersions["Splat"].FirstOrDefault().Item1;
-var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
-var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
-var SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1;
-var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
-var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
-var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
-
-Information("Package: Serilog, version: {0}", SerilogVersion);
-Information("Package: Splat, version: {0}", SplatVersion);
-Information("Package: Sprache, version: {0}", SpracheVersion);
-Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
-Information("Package: SkiaSharp, version: {0}", SkiaSharpVersion);
-Information("Package: SharpDX, version: {0}", SharpDXVersion);
-Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
-Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
-
-var SetNuGetNuspecCommonProperties = new Action<NuGetPackSettings> ((nuspec) => {
-    nuspec.Version = version;
-    nuspec.Authors = new [] { "Avalonia Team" };
-    nuspec.Owners = new [] { "stevenk" };
-    nuspec.LicenseUrl = new Uri("http://opensource.org/licenses/MIT");
-    nuspec.ProjectUrl = new Uri("https://github.com/AvaloniaUI/Avalonia/");
-    nuspec.RequireLicenseAcceptance = false;
-    nuspec.Symbols = false;
-    nuspec.NoPackageAnalysis = true;
-    nuspec.Description = "The Avalonia UI framework";
-    nuspec.Copyright = "Copyright 2015";
-    nuspec.Tags = new [] { "Avalonia" };
+    CleanDirectories(parameters.BuildDirs);
+    CleanDirectory(parameters.ArtifactsDir);
+    CleanDirectory(parameters.NugetRoot);
+    CleanDirectory(parameters.ZipRoot);
+    CleanDirectory(parameters.BinRoot);
+    CleanDirectory(parameters.TestsRoot);
 });
 });
 
 
-var coreLibraries = new string[][]
+Task("Prepare-XBuild-Solution")
+    .Does(() =>
 {
 {
-    new [] { "./src/", "Avalonia.Animation", ".dll" },
-    new [] { "./src/", "Avalonia.Animation", ".xml" },
-    new [] { "./src/", "Avalonia.Base", ".dll" },
-    new [] { "./src/", "Avalonia.Base", ".xml" },
-    new [] { "./src/", "Avalonia.Controls", ".dll" },
-    new [] { "./src/", "Avalonia.Controls", ".xml" },
-    new [] { "./src/", "Avalonia.DesignerSupport", ".dll" },
-    new [] { "./src/", "Avalonia.DesignerSupport", ".xml" },
-    new [] { "./src/", "Avalonia.Diagnostics", ".dll" },
-    new [] { "./src/", "Avalonia.Diagnostics", ".xml" },
-    new [] { "./src/", "Avalonia.Input", ".dll" },
-    new [] { "./src/", "Avalonia.Input", ".xml" },
-    new [] { "./src/", "Avalonia.Interactivity", ".dll" },
-    new [] { "./src/", "Avalonia.Interactivity", ".xml" },
-    new [] { "./src/", "Avalonia.Layout", ".dll" },
-    new [] { "./src/", "Avalonia.Layout", ".xml" },
-    new [] { "./src/", "Avalonia.Logging.Serilog", ".dll" },
-    new [] { "./src/", "Avalonia.Logging.Serilog", ".xml" },
-    new [] { "./src/", "Avalonia.Visuals", ".dll" },
-    new [] { "./src/", "Avalonia.Visuals", ".xml" },
-    new [] { "./src/", "Avalonia.Styling", ".dll" },
-    new [] { "./src/", "Avalonia.Styling", ".xml" },
-    new [] { "./src/", "Avalonia.ReactiveUI", ".dll" },
-    new [] { "./src/", "Avalonia.Themes.Default", ".dll" },
-    new [] { "./src/", "Avalonia.Themes.Default", ".xml" },
-    new [] { "./src/Markup/", "Avalonia.Markup", ".dll" },
-    new [] { "./src/Markup/", "Avalonia.Markup", ".xml" },
-    new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".dll" },
-    new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".xml" }
-};
-
-var coreLibrariesFiles = coreLibraries.Select((lib) => {
-    return (FilePath)File(lib[0] + lib[1] + "/bin/" + dirSuffix + "/" + lib[1] + lib[2]);
-}).ToList();
-
-var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
-    return new NuSpecContent { 
-        Source = file.FullPath, Target = "lib/portable-windows8+net45" 
-    };
-});
-
-var win32CoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
-    return new NuSpecContent { 
-        Source = file.FullPath, Target = "lib/net45" 
-    };
-});
-
-var net45RuntimePlatformExtensions = new [] {".xml", ".dll"};
-var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => {
-    return new NuSpecContent {
-        Source = ((FilePath)File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + dirSuffix + "/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath, 
-        Target = "lib/net45" 
+    var blacklistedProjects = new[]
+    {
+        "Avalonia.Win32.NetStandard",
+        "Avalonia.DotNetCoreRuntime",
+        "Avalonia.Skia.Desktop.NetStandard",
+        "Avalonia.Gtk3"
     };
     };
-});
+    var blacklistedGuids = System.IO.File.ReadAllLines(parameters.MSBuildSolution)
+        .Where(l=>l.StartsWith("Project") && blacklistedProjects.Any(p=>l.Contains(p)))
+        .Select(l => l.Split(',').Select(part => part.Trim()).FirstOrDefault(part => part.StartsWith("\"{")))
+        .Where(g=>g!=null)
+        .Select(l=>l.Trim(new[]{'"', '}', '{'}).ToLower()).ToArray();
 
 
-var nuspecNuGetSettingsCore = new []
-{
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Serilog", Version = SerilogVersion },
-            new NuSpecDependency() { Id = "Splat", Version = SplatVersion },
-            new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion },
-            new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion }
-        },
-        Files = coreLibrariesNuSpecContent.Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform).ToList(),
-        BasePath = Directory("./"),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.HtmlRenderer
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.HtmlRenderer",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/portable-windows8+net45" }
-        },
-        BasePath = Directory("./src/Avalonia.HtmlRenderer/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    }
-};
+    Console.WriteLine("Blacklisted guids are: " + string.Join(",", blacklistedGuids));
+    var removeUntilEndProject = false;
 
 
-var nuspecNuGetSettingsMobile = new []
-{
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Android
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Android",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Skia.Android", Version = version }
-        },
-        Files = new []
+    System.IO.File.WriteAllLines(parameters.XBuildSolution, System.IO.File.ReadAllLines(parameters.MSBuildSolution)
+        .Where(l => 
         {
         {
-            new NuSpecContent { Source = "Avalonia.Android.dll", Target = "lib/MonoAndroid10" }
-        },
-        BasePath = Directory("./src/Android/Avalonia.Android/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Skia.Android
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Skia.Android",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Skia.Android.dll", Target = "lib/MonoAndroid10" }
-        },
-        BasePath = Directory("./src/Skia/Avalonia.Skia.Android/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.iOS
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.iOS",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Skia.iOS", Version = version }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.iOS.dll", Target = "lib/Xamarin.iOS10" }
-        },
-        BasePath = Directory("./src/iOS/Avalonia.iOS/bin/" + dirSuffixIOS),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Skia.iOS
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Skia.iOS",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Skia.iOS.dll", Target = "lib/Xamarin.iOS10" }
-        },
-        BasePath = Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + dirSuffixIOS),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Mobile
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Mobile",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia.Android", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.iOS", Version = version }
-        },
-        Files = new NuSpecContent[]
-        {
-            new NuSpecContent { Source = "licence.md", Target = "" }
-        },
-        BasePath = Directory("./"),
-        OutputDirectory = nugetRoot
-    }
-};
-
-var nuspecNuGetSettingsDesktop = new []
-{
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Win32
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Win32",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Win32.dll", Target = "lib/net45" }
-        },
-        BasePath = Directory("./src/Windows/Avalonia.Win32/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Direct2D1
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Direct2D1",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "SharpDX", Version = SharpDXVersion },
-            new NuSpecDependency() { Id = "SharpDX.Direct2D1", Version = SharpDXDirect2D1Version },
-            new NuSpecDependency() { Id = "SharpDX.DXGI", Version = SharpDXDXGIVersion }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/net45" }
-        },
-        BasePath = Directory("./src/Windows/Avalonia.Direct2D1/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Gtk
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Gtk",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Gtk.dll", Target = "lib/net45" }
-        },
-        BasePath = Directory("./src/Gtk/Avalonia.Gtk/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Cairo
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Cairo",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Cairo.dll", Target = "lib/net45" }
-        },
-        BasePath = Directory("./src/Gtk/Avalonia.Cairo/bin/" + dirSuffix),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Skia.Desktop
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Skia.Desktop",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia", Version = version },
-            new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
-        },
-        Files = new []
-        {
-            new NuSpecContent { Source = "Avalonia.Skia.Desktop.dll", Target = "lib/net45" }
-        },
-        BasePath = Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + dirSuffixSkia),
-        OutputDirectory = nugetRoot
-    },
-    ///////////////////////////////////////////////////////////////////////////////
-    // Avalonia.Desktop
-    ///////////////////////////////////////////////////////////////////////////////
-    new NuGetPackSettings()
-    {
-        Id = "Avalonia.Desktop",
-        Dependencies = new []
-        {
-            new NuSpecDependency() { Id = "Avalonia.Win32", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Gtk", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Cairo", Version = version },
-            new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", Version = version }
-        },
-        Files = new NuSpecContent[]
-        {
-            new NuSpecContent { Source = "licence.md", Target = "" }
-        },
-        BasePath = Directory("./"),
-        OutputDirectory = nugetRoot
-    }
-};
-
-var nuspecNuGetSettings = new List<NuGetPackSettings>();
-
-nuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore);
-nuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop);
-nuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
-
-nuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec));
-
-var nugetPackages = nuspecNuGetSettings.Select(nuspec => {
-    return nuspec.OutputDirectory.CombineWithFilePath(string.Concat(nuspec.Id, ".", nuspec.Version, ".nupkg"));
-}).ToArray();
-
-var binFiles = nuspecNuGetSettings.SelectMany(nuspec => {
-    return nuspec.Files.Select(file => {
-        return ((DirectoryPath)nuspec.BasePath).CombineWithFilePath(file.Source);
-    });
-}).GroupBy(f => f.FullPath).Select(g => g.First());
-
-///////////////////////////////////////////////////////////////////////////////
-// INFORMATION
-///////////////////////////////////////////////////////////////////////////////
-
-Information("Building version {0} of Avalonia ({1}, {2}, {3}) using version {4} of Cake.", 
-    version,
-    platform,
-    configuration,
-    target,
-    typeof(ICakeContext).Assembly.GetName().Version.ToString());
-
-if (isRunningOnAppVeyor)
-{
-    Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
-    Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
-}
-
-Information("Target: " + target);
-Information("Platform: " + platform);
-Information("Configuration: " + configuration);
-Information("IsLocalBuild: " + isLocalBuild);
-Information("IsRunningOnUnix: " + isRunningOnUnix);
-Information("IsRunningOnWindows: " + isRunningOnWindows);
-Information("IsRunningOnAppVeyor: " + isRunningOnAppVeyor);
-Information("IsPullRequest: " + isPullRequest);
-Information("IsMainRepo: " + isMainRepo);
-Information("IsMasterBranch: " + isMasterBranch);
-Information("IsTagged: " + isTagged);
-Information("IsReleasable: " + isReleasable);
-Information("IsMyGetRelease: " + isMyGetRelease);
-Information("IsNuGetRelease: " + isNuGetRelease);
-
-///////////////////////////////////////////////////////////////////////////////
-// TASKS
-///////////////////////////////////////////////////////////////////////////////
-
-Task("Clean")
-    .Does(() =>
-{
-    CleanDirectories(buildDirs);
-    CleanDirectory(artifactsDir);
-    CleanDirectory(nugetRoot);
-    CleanDirectory(zipRoot);
-    CleanDirectory(binRoot);
-    CleanDirectory(testsRoot);
+            if(removeUntilEndProject)
+            {
+                if(l.StartsWith("EndProject"))
+                    removeUntilEndProject = false;
+                return false;
+            }
+            
+            var blacklist = blacklistedGuids.Any(g => l.ToLower().Contains(g));
+            if(blacklist && l.StartsWith("Project"))
+                removeUntilEndProject = true;
+            
+            return !blacklist;
+        }));
 });
 });
 
 
 Task("Restore-NuGet-Packages")
 Task("Restore-NuGet-Packages")
     .IsDependentOn("Clean")
     .IsDependentOn("Clean")
+    .IsDependentOn("Prepare-XBuild-Solution")
     .Does(() =>
     .Does(() =>
 {
 {
     var maxRetryCount = 5;
     var maxRetryCount = 5;
@@ -609,15 +153,15 @@ Task("Restore-NuGet-Packages")
                 toolTimeout+=0.5;
                 toolTimeout+=0.5;
             }})
             }})
         .Execute(()=> {
         .Execute(()=> {
-            if(isRunningOnWindows)
+            if(parameters.IsRunningOnWindows)
             {
             {
-                NuGetRestore(MSBuildSolution, new NuGetRestoreSettings {
+                NuGetRestore(parameters.MSBuildSolution, new NuGetRestoreSettings {
                     ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
                     ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
                 });
                 });
             }
             }
             else
             else
             {
             {
-                NuGetRestore(XBuildSolution, new NuGetRestoreSettings {
+                NuGetRestore(parameters.XBuildSolution, new NuGetRestoreSettings {
                     ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
                     ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
                 });
                 });
             }
             }
@@ -628,11 +172,11 @@ Task("Build")
     .IsDependentOn("Restore-NuGet-Packages")
     .IsDependentOn("Restore-NuGet-Packages")
     .Does(() =>
     .Does(() =>
 {
 {
-    if(isRunningOnWindows)
+    if(parameters.IsRunningOnWindows)
     {
     {
-        MSBuild(MSBuildSolution, settings => {
-            settings.SetConfiguration(configuration);
-            settings.WithProperty("Platform", "\"" + platform + "\"");
+        MSBuild(parameters.MSBuildSolution, settings => {
+            settings.SetConfiguration(parameters.Configuration);
+            settings.WithProperty("Platform", "\"" + parameters.Platform + "\"");
             settings.SetVerbosity(Verbosity.Minimal);
             settings.SetVerbosity(Verbosity.Minimal);
             settings.WithProperty("Windows", "True");
             settings.WithProperty("Windows", "True");
             settings.UseToolVersion(MSBuildToolVersion.VS2015);
             settings.UseToolVersion(MSBuildToolVersion.VS2015);
@@ -641,9 +185,9 @@ Task("Build")
     }
     }
     else
     else
     {
     {
-        XBuild(XBuildSolution, settings => {
-            settings.SetConfiguration(configuration);
-            settings.WithProperty("Platform", "\"" + platform + "\"");
+        XBuild(parameters.XBuildSolution, settings => {
+            settings.SetConfiguration(parameters.Configuration);
+            settings.WithProperty("Platform", "\"" + parameters.Platform + "\"");
             settings.SetVerbosity(Verbosity.Minimal);
             settings.SetVerbosity(Verbosity.Minimal);
         });
         });
     }
     }
@@ -651,23 +195,23 @@ Task("Build")
 
 
 Task("Run-Unit-Tests")
 Task("Run-Unit-Tests")
     .IsDependentOn("Build")
     .IsDependentOn("Build")
-    .WithCriteria(() => !skipTests)
+    .WithCriteria(() => !parameters.SkipTests)
     .Does(() =>
     .Does(() =>
 {
 {
     var unitTests = GetDirectories("./tests/Avalonia.*.UnitTests")
     var unitTests = GetDirectories("./tests/Avalonia.*.UnitTests")
         .Select(dir => System.IO.Path.GetFileName(dir.FullPath))
         .Select(dir => System.IO.Path.GetFileName(dir.FullPath))
-        .Where(name => isRunningOnWindows ? true : !(name.IndexOf("Direct2D", StringComparison.OrdinalIgnoreCase) >= 0))
-        .Select(name => MakeAbsolute(File("./tests/" + name + "/bin/" + dirSuffix + "/" + name + ".dll")))
+        .Where(name => parameters.IsRunningOnWindows ? true : !(name.IndexOf("Direct2D", StringComparison.OrdinalIgnoreCase) >= 0))
+        .Select(name => MakeAbsolute(File("./tests/" + name + "/bin/" + parameters.DirSuffix + "/" + name + ".dll")))
         .ToList();
         .ToList();
 
 
-    if (isRunningOnWindows)
+    if (parameters.IsRunningOnWindows)
     {
     {
-        var leakTests = GetFiles("./tests/Avalonia.LeakTests/bin/" + dirSuffix + "/*.LeakTests.dll");
+        var leakTests = GetFiles("./tests/Avalonia.LeakTests/bin/" + parameters.DirSuffix + "/*.LeakTests.dll");
 
 
         unitTests.AddRange(leakTests);
         unitTests.AddRange(leakTests);
     }
     }
 
 
-    var toolPath = (isPlatformAnyCPU || isPlatformX86) ? 
+    var toolPath = (parameters.IsPlatformAnyCPU || parameters.IsPlatformX86) ? 
         "./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
         "./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
         "./tools/xunit.runner.console/tools/xunit.console.exe";
         "./tools/xunit.runner.console/tools/xunit.console.exe";
 
 
@@ -678,9 +222,9 @@ Task("Run-Unit-Tests")
         ShadowCopy = false
         ShadowCopy = false
     };
     };
 
 
-    xUnitSettings.NoAppDomain = !isRunningOnWindows;
+    xUnitSettings.NoAppDomain = !parameters.IsRunningOnWindows;
 
 
-    var openCoverOutput = artifactsDir.GetFilePath(new FilePath("./coverage.xml"));
+    var openCoverOutput = parameters.ArtifactsDir.GetFilePath(new FilePath("./coverage.xml"));
     var openCoverSettings = new OpenCoverSettings()
     var openCoverSettings = new OpenCoverSettings()
         .WithFilter("+[Avalonia.*]* -[*Test*]* -[ControlCatalog*]*")
         .WithFilter("+[Avalonia.*]* -[*Test*]* -[ControlCatalog*]*")
         .WithFilter("-[Avalonia.*]OmniXaml.* -[Avalonia.*]Glass.*")
         .WithFilter("-[Avalonia.*]OmniXaml.* -[Avalonia.*]Glass.*")
@@ -690,11 +234,11 @@ Task("Run-Unit-Tests")
 
 
     foreach(var test in unitTests.Where(testFile => FileExists(testFile)))
     foreach(var test in unitTests.Where(testFile => FileExists(testFile)))
     {
     {
-        CopyDirectory(test.GetDirectory(), testsRoot);
+        CopyDirectory(test.GetDirectory(), parameters.TestsRoot);
     }
     }
 
 
     var testsInDirectoryToRun = new List<FilePath>();
     var testsInDirectoryToRun = new List<FilePath>();
-    if(isRunningOnWindows)
+    if(parameters.IsRunningOnWindows)
     {
     {
         testsInDirectoryToRun.AddRange(GetFiles("./artifacts/tests/*Tests.dll"));
         testsInDirectoryToRun.AddRange(GetFiles("./artifacts/tests/*Tests.dll"));
     }
     }
@@ -703,7 +247,7 @@ Task("Run-Unit-Tests")
         testsInDirectoryToRun.AddRange(GetFiles("./artifacts/tests/*.UnitTests.dll"));
         testsInDirectoryToRun.AddRange(GetFiles("./artifacts/tests/*.UnitTests.dll"));
     }
     }
 
 
-    if(isRunningOnWindows)
+    if(parameters.IsRunningOnWindows)
     {
     {
         OpenCover(context => {
         OpenCover(context => {
             context.XUnit2(testsInDirectoryToRun, xUnitSettings);
             context.XUnit2(testsInDirectoryToRun, xUnitSettings);
@@ -719,26 +263,26 @@ Task("Copy-Files")
     .IsDependentOn("Run-Unit-Tests")
     .IsDependentOn("Run-Unit-Tests")
     .Does(() =>
     .Does(() =>
 {
 {
-    CopyFiles(binFiles, binRoot);
+    CopyFiles(packages.BinFiles, parameters.BinRoot);
 });
 });
 
 
 Task("Zip-Files")
 Task("Zip-Files")
     .IsDependentOn("Copy-Files")
     .IsDependentOn("Copy-Files")
     .Does(() =>
     .Does(() =>
 {
 {
-    Zip(binRoot, zipCoreArtifacts);
+    Zip(parameters.BinRoot, parameters.ZipCoreArtifacts);
 
 
-    Zip(zipSourceControlCatalogDesktopDirs, 
-        zipTargetControlCatalogDesktopDirs, 
-        GetFiles(zipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + 
-        GetFiles(zipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
+    Zip(parameters.ZipSourceControlCatalogDesktopDirs, 
+        parameters.ZipTargetControlCatalogDesktopDirs, 
+        GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") + 
+        GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
 });
 });
 
 
 Task("Create-NuGet-Packages")
 Task("Create-NuGet-Packages")
     .IsDependentOn("Run-Unit-Tests")
     .IsDependentOn("Run-Unit-Tests")
     .Does(() =>
     .Does(() =>
 {
 {
-    foreach(var nuspec in nuspecNuGetSettings)
+    foreach(var nuspec in packages.NuspecNuGetSettings)
     {
     {
         NuGetPack(nuspec);
         NuGetPack(nuspec);
     }
     }
@@ -746,11 +290,11 @@ Task("Create-NuGet-Packages")
 
 
 Task("Publish-MyGet")
 Task("Publish-MyGet")
     .IsDependentOn("Create-NuGet-Packages")
     .IsDependentOn("Create-NuGet-Packages")
-    .WithCriteria(() => !isLocalBuild)
-    .WithCriteria(() => !isPullRequest)
-    .WithCriteria(() => isMainRepo)
-    .WithCriteria(() => isMasterBranch)
-    .WithCriteria(() => isMyGetRelease)
+    .WithCriteria(() => !parameters.IsLocalBuild)
+    .WithCriteria(() => !parameters.IsPullRequest)
+    .WithCriteria(() => parameters.IsMainRepo)
+    .WithCriteria(() => parameters.IsMasterBranch)
+    .WithCriteria(() => parameters.IsMyGetRelease)
     .Does(() =>
     .Does(() =>
 {
 {
     var apiKey = EnvironmentVariable("MYGET_API_KEY");
     var apiKey = EnvironmentVariable("MYGET_API_KEY");
@@ -765,7 +309,7 @@ Task("Publish-MyGet")
         throw new InvalidOperationException("Could not resolve MyGet API url.");
         throw new InvalidOperationException("Could not resolve MyGet API url.");
     }
     }
 
 
-    foreach(var nupkg in nugetPackages)
+    foreach(var nupkg in packages.NugetPackages)
     {
     {
         NuGetPush(nupkg, new NuGetPushSettings {
         NuGetPush(nupkg, new NuGetPushSettings {
             Source = apiUrl,
             Source = apiUrl,
@@ -780,11 +324,11 @@ Task("Publish-MyGet")
 
 
 Task("Publish-NuGet")
 Task("Publish-NuGet")
     .IsDependentOn("Create-NuGet-Packages")
     .IsDependentOn("Create-NuGet-Packages")
-    .WithCriteria(() => !isLocalBuild)
-    .WithCriteria(() => !isPullRequest)
-    .WithCriteria(() => isMainRepo)
-    .WithCriteria(() => isMasterBranch)
-    .WithCriteria(() => isNuGetRelease)
+    .WithCriteria(() => !parameters.IsLocalBuild)
+    .WithCriteria(() => !parameters.IsPullRequest)
+    .WithCriteria(() => parameters.IsMainRepo)
+    .WithCriteria(() => parameters.IsMasterBranch)
+    .WithCriteria(() => parameters.IsNuGetRelease)
     .Does(() =>
     .Does(() =>
 {
 {
     var apiKey = EnvironmentVariable("NUGET_API_KEY");
     var apiKey = EnvironmentVariable("NUGET_API_KEY");
@@ -799,7 +343,7 @@ Task("Publish-NuGet")
         throw new InvalidOperationException("Could not resolve NuGet API url.");
         throw new InvalidOperationException("Could not resolve NuGet API url.");
     }
     }
 
 
-    foreach(var nupkg in nugetPackages)
+    foreach(var nupkg in packages.NugetPackages)
     {
     {
         NuGetPush(nupkg, new NuGetPushSettings {
         NuGetPush(nupkg, new NuGetPushSettings {
             ApiKey = apiKey,
             ApiKey = apiKey,
@@ -834,4 +378,4 @@ Task("Travis")
 // EXECUTE
 // EXECUTE
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
-RunTarget(target);
+RunTarget(parameters.Target);

+ 469 - 0
packages.cake

@@ -0,0 +1,469 @@
+public class Packages
+{
+    public List<NuGetPackSettings> NuspecNuGetSettings { get; private set; }
+    public FilePath[] NugetPackages { get; private set; }
+    public FilePath[] BinFiles { get; private set; }
+
+    public Packages(ICakeContext context, Parameters parameters)
+    {
+        // NUGET NUSPECS
+        context.Information("Getting git modules:");
+
+        var ignoredSubModulesPaths = System.IO.File.ReadAllLines(".git/config").Where(m=>m.StartsWith("[submodule ")).Select(m => 
+        {
+            var path = m.Split(' ')[1].Trim("\"[] \t".ToArray());
+            context.Information(path);
+            return ((DirectoryPath)context.Directory(path)).FullPath;
+        }).ToList();
+
+        var normalizePath = new Func<string, string>(
+            path => path.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar).ToUpperInvariant());
+
+        // Key: Package Id
+        // Value is Tuple where Item1: Package Version, Item2: The packages.config file path.
+        var packageVersions = new Dictionary<string, IList<Tuple<string,string>>>();
+
+        System.IO.Directory.EnumerateFiles(((DirectoryPath)context.Directory("./src")).FullPath, "packages.config", SearchOption.AllDirectories).ToList().ForEach(fileName =>
+        {
+            if (!ignoredSubModulesPaths.Any(i => normalizePath(fileName).Contains(normalizePath(i))))
+            {
+                var file = new PackageReferenceFile(fileName);
+                foreach (PackageReference packageReference in file.GetPackageReferences())
+                {
+                    IList<Tuple<string, string>> versions;
+                    packageVersions.TryGetValue(packageReference.Id, out versions);
+                    if (versions == null)
+                    {
+                        versions = new List<Tuple<string, string>>();
+                        packageVersions[packageReference.Id] = versions;
+                    }
+                    versions.Add(Tuple.Create(packageReference.Version.ToString(), fileName));
+                }
+            }
+        });
+
+        context.Information("Checking installed NuGet package dependencies versions:");
+
+        packageVersions.ToList().ForEach(package =>
+        {
+            var packageVersion = package.Value.First().Item1;
+            bool isValidVersion = package.Value.All(x => x.Item1 == packageVersion);
+            if (!isValidVersion)
+            {
+                context.Information("Error: package {0} has multiple versions installed:", package.Key);
+                foreach (var v in package.Value)
+                {
+                    context.Information("{0}, file: {1}", v.Item1, v.Item2);
+                }
+                throw new Exception("Detected multiple NuGet package version installed for different projects.");
+            }
+        });
+
+        context.Information("Setting NuGet package dependencies versions:");
+
+        var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1;
+        var SplatVersion = packageVersions["Splat"].FirstOrDefault().Item1;
+        var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
+        var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
+        var SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1;
+        var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
+        var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
+        var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
+        var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
+
+        context.Information("Package: Serilog, version: {0}", SerilogVersion);
+        context.Information("Package: Splat, version: {0}", SplatVersion);
+        context.Information("Package: Sprache, version: {0}", SpracheVersion);
+        context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
+        context.Information("Package: SkiaSharp, version: {0}", SkiaSharpVersion);
+        context.Information("Package: SharpDX, version: {0}", SharpDXVersion);
+        context.Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
+        context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version);
+        context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
+
+        var SetNuGetNuspecCommonProperties = new Action<NuGetPackSettings> ((nuspec) => {
+            nuspec.Version = parameters.Version;
+            nuspec.Authors = new [] { "Avalonia Team" };
+            nuspec.Owners = new [] { "stevenk" };
+            nuspec.LicenseUrl = new Uri("http://opensource.org/licenses/MIT");
+            nuspec.ProjectUrl = new Uri("https://github.com/AvaloniaUI/Avalonia/");
+            nuspec.RequireLicenseAcceptance = false;
+            nuspec.Symbols = false;
+            nuspec.NoPackageAnalysis = true;
+            nuspec.Description = "The Avalonia UI framework";
+            nuspec.Copyright = "Copyright 2015";
+            nuspec.Tags = new [] { "Avalonia" };
+        });
+
+        var coreLibraries = new string[][]
+        {
+            new [] { "./src/", "Avalonia.Animation", ".dll" },
+            new [] { "./src/", "Avalonia.Animation", ".xml" },
+            new [] { "./src/", "Avalonia.Base", ".dll" },
+            new [] { "./src/", "Avalonia.Base", ".xml" },
+            new [] { "./src/", "Avalonia.Controls", ".dll" },
+            new [] { "./src/", "Avalonia.Controls", ".xml" },
+            new [] { "./src/", "Avalonia.DesignerSupport", ".dll" },
+            new [] { "./src/", "Avalonia.DesignerSupport", ".xml" },
+            new [] { "./src/", "Avalonia.Diagnostics", ".dll" },
+            new [] { "./src/", "Avalonia.Diagnostics", ".xml" },
+            new [] { "./src/", "Avalonia.Input", ".dll" },
+            new [] { "./src/", "Avalonia.Input", ".xml" },
+            new [] { "./src/", "Avalonia.Interactivity", ".dll" },
+            new [] { "./src/", "Avalonia.Interactivity", ".xml" },
+            new [] { "./src/", "Avalonia.Layout", ".dll" },
+            new [] { "./src/", "Avalonia.Layout", ".xml" },
+            new [] { "./src/", "Avalonia.Logging.Serilog", ".dll" },
+            new [] { "./src/", "Avalonia.Logging.Serilog", ".xml" },
+            new [] { "./src/", "Avalonia.Visuals", ".dll" },
+            new [] { "./src/", "Avalonia.Visuals", ".xml" },
+            new [] { "./src/", "Avalonia.Styling", ".dll" },
+            new [] { "./src/", "Avalonia.Styling", ".xml" },
+            new [] { "./src/", "Avalonia.ReactiveUI", ".dll" },
+            new [] { "./src/", "Avalonia.Themes.Default", ".dll" },
+            new [] { "./src/", "Avalonia.Themes.Default", ".xml" },
+            new [] { "./src/Markup/", "Avalonia.Markup", ".dll" },
+            new [] { "./src/Markup/", "Avalonia.Markup", ".xml" },
+            new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".dll" },
+            new [] { "./src/Markup/", "Avalonia.Markup.Xaml", ".xml" }
+        };
+
+        var coreLibrariesFiles = coreLibraries.Select((lib) => {
+            return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/" + lib[1] + lib[2]);
+        }).ToList();
+
+        var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
+            return new NuSpecContent { 
+                Source = file.FullPath, Target = "lib/portable-windows8+net45" 
+            };
+        });
+
+        var win32CoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
+            return new NuSpecContent { 
+                Source = file.FullPath, Target = "lib/net45" 
+            };
+        });
+
+        var netcoreappCoreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
+            return new NuSpecContent { 
+                Source = file.FullPath, Target = "lib/netcoreapp1.0" 
+            };
+        });
+
+        var net45RuntimePlatformExtensions = new [] {".xml", ".dll"};
+        var net45RuntimePlatform = net45RuntimePlatformExtensions.Select(libSuffix => {
+            return new NuSpecContent {
+                Source = ((FilePath)context.File("./src/Avalonia.DotNetFrameworkRuntime/bin/" + parameters.DirSuffix + "/Avalonia.DotNetFrameworkRuntime" + libSuffix)).FullPath, 
+                Target = "lib/net45" 
+            };
+        });
+
+        var netCoreRuntimePlatformExtensions = new [] {".xml", ".dll"};
+        var netCoreRuntimePlatform = netCoreRuntimePlatformExtensions.Select(libSuffix => {
+            return new NuSpecContent {
+                Source = ((FilePath)context.File("./src/Avalonia.DotNetCoreRuntime/bin/" + parameters.DirSuffix + "/Avalonia.DotNetCoreRuntime" + libSuffix)).FullPath, 
+                Target = "lib/netcoreapp1.0" 
+            };
+        });
+
+        var nuspecNuGetSettingsCore = new []
+        {
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Serilog", Version = SerilogVersion },
+                    new NuSpecDependency() { Id = "Splat", Version = SplatVersion },
+                    new NuSpecDependency() { Id = "Sprache", Version = SpracheVersion },
+                    new NuSpecDependency() { Id = "System.Reactive", Version = SystemReactiveVersion },
+                    new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" },
+                    //.NET Core
+                    new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" },
+                    new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" },
+                    new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = "2.0.0" },
+                    new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = "2.3.0" },
+                    new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion },
+                    new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion }
+                },
+                Files = coreLibrariesNuSpecContent
+                    .Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform)
+                    .Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
+                    .ToList(),
+                BasePath = context.Directory("./"),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.HtmlRenderer
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.HtmlRenderer",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/portable-windows8+net45" }
+                },
+                BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            }
+        };
+
+        var nuspecNuGetSettingsMobile = new []
+        {
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Android
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Android",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Skia.Android", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Android.dll", Target = "lib/MonoAndroid10" }
+                },
+                BasePath = context.Directory("./src/Android/Avalonia.Android/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Skia.Android
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Skia.Android",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Skia.Android.dll", Target = "lib/MonoAndroid10" }
+                },
+                BasePath = context.Directory("./src/Skia/Avalonia.Skia.Android/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.iOS
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.iOS",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Skia.iOS", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.iOS.dll", Target = "lib/Xamarin.iOS10" }
+                },
+                BasePath = context.Directory("./src/iOS/Avalonia.iOS/bin/" + parameters.DirSuffixIOS),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Skia.iOS
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Skia.iOS",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Skia.iOS.dll", Target = "lib/Xamarin.iOS10" }
+                },
+                BasePath = context.Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + parameters.DirSuffixIOS),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Mobile
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Mobile",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia.Android", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.iOS", Version = parameters.Version }
+                },
+                Files = new NuSpecContent[]
+                {
+                    new NuSpecContent { Source = "licence.md", Target = "" }
+                },
+                BasePath = context.Directory("./"),
+                OutputDirectory = parameters.NugetRoot
+            }
+        };
+
+        var nuspecNuGetSettingsDesktop = new []
+        {
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Win32
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Win32",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" },
+                    new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/netstandard1.1" }
+                },
+                BasePath = context.Directory("./src/Windows"),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Direct2D1
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Direct2D1",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "SharpDX", Version = SharpDXVersion },
+                    new NuSpecDependency() { Id = "SharpDX.Direct2D1", Version = SharpDXDirect2D1Version },
+                    new NuSpecDependency() { Id = "SharpDX.Direct3D11", Version = SharpDXDirect3D11Version },
+                    new NuSpecDependency() { Id = "SharpDX.DXGI", Version = SharpDXDXGIVersion }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Direct2D1.dll", Target = "lib/net45" }
+                },
+                BasePath = context.Directory("./src/Windows/Avalonia.Direct2D1/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Gtk
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Gtk",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Gtk.dll", Target = "lib/net45" }
+                },
+                BasePath = context.Directory("./src/Gtk/Avalonia.Gtk/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Gtk3
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Gtk3",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.1" }
+                },
+                BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Cairo
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Cairo",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Cairo.dll", Target = "lib/net45" }
+                },
+                BasePath = context.Directory("./src/Gtk/Avalonia.Cairo/bin/" + parameters.DirSuffix),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Skia.Desktop
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Skia.Desktop",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "SkiaSharp", Version = SkiaSharpVersion },
+                    //.NET Core
+                    new NuSpecDependency() { Id = "Avalonia", TargetFramework = "netcoreapp1.0", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "SkiaSharp", TargetFramework = "netcoreapp1.0", Version = SkiaSharpVersion },
+                    new NuSpecDependency() { Id = "NETStandard.Library", TargetFramework = "netcoreapp1.0", Version = "1.6.0" },
+                    new NuSpecDependency() { Id = "Microsoft.NETCore.Portable.Compatibility", TargetFramework = "netcoreapp1.0", Version = "1.0.1" }
+                },
+                Files = new []
+                {
+                    new NuSpecContent { Source = "Avalonia.Skia.Desktop/bin/" + parameters.DirSuffixSkia + "/Avalonia.Skia.Desktop.dll", Target = "lib/net45" },
+                    new NuSpecContent { Source = "Avalonia.Skia.Desktop.NetStandard/bin/" + parameters.DirSuffix + "/Avalonia.Skia.Desktop.dll", Target = "lib/netcoreapp1.0" }
+                },
+                BasePath = context.Directory("./src/Skia/"),
+                OutputDirectory = parameters.NugetRoot
+            },
+            ///////////////////////////////////////////////////////////////////////////////
+            // Avalonia.Desktop
+            ///////////////////////////////////////////////////////////////////////////////
+            new NuGetPackSettings()
+            {
+                Id = "Avalonia.Desktop",
+                Dependencies = new []
+                {
+                    new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Gtk", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Cairo", Version = parameters.Version },
+                    new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", Version = parameters.Version }
+                },
+                Files = new NuSpecContent[]
+                {
+                    new NuSpecContent { Source = "licence.md", Target = "" }
+                },
+                BasePath = context.Directory("./"),
+                OutputDirectory = parameters.NugetRoot
+            }
+        };
+
+        NuspecNuGetSettings = new List<NuGetPackSettings>();
+
+        NuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore);
+        NuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop);
+        NuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
+
+        NuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec));
+
+        NugetPackages = NuspecNuGetSettings.Select(nuspec => {
+            return nuspec.OutputDirectory.CombineWithFilePath(string.Concat(nuspec.Id, ".", nuspec.Version, ".nupkg"));
+        }).ToArray();
+
+        BinFiles = NuspecNuGetSettings.SelectMany(nuspec => {
+            return nuspec.Files.Select(file => {
+                return ((DirectoryPath)nuspec.BasePath).CombineWithFilePath(file.Source);
+            });
+        }).GroupBy(f => f.FullPath).Select(g => g.First()).ToArray();
+    }
+}

+ 143 - 0
parameters.cake

@@ -0,0 +1,143 @@
+public class Parameters
+{
+    public string Target { get; private set; }
+    public string Platform { get; private set; }
+    public string Configuration { get; private set; }
+    public bool SkipTests { get; private set; }
+    public string MainRepo { get; private set; }
+    public string MasterBranch { get; private set; }
+    public string AssemblyInfoPath { get; private set; }
+    public string ReleasePlatform { get; private set; }
+    public string ReleaseConfiguration { get; private set; }
+    public string MSBuildSolution { get; private set; } 
+    public string XBuildSolution { get; private set; } 
+    public bool IsPlatformAnyCPU { get; private set; }
+    public bool IsPlatformX86 { get; private set; }
+    public bool IsPlatformX64 { get; private set; }
+    public bool IsLocalBuild { get; private set; }
+    public bool IsRunningOnUnix { get; private set; }
+    public bool IsRunningOnWindows { get; private set; }
+    public bool IsRunningOnAppVeyor { get; private set; }
+    public bool IsPullRequest { get; private set; }
+    public bool IsMainRepo { get; private set; }
+    public bool IsMasterBranch { get; private set; }
+    public bool IsTagged { get; private set; }
+    public bool IsReleasable { get; private set; }
+    public bool IsMyGetRelease { get; private set; }
+    public bool IsNuGetRelease { get; private set; }
+    public string Version { get; private set; } 
+    public DirectoryPath ArtifactsDir { get; private set; }
+    public DirectoryPath NugetRoot { get; private set; }
+    public DirectoryPath ZipRoot { get; private set; }
+    public DirectoryPath BinRoot { get; private set; }
+    public DirectoryPath TestsRoot { get; private set; }
+    public string DirSuffix { get; private set; }
+    public string DirSuffixSkia { get; private set; }
+    public string DirSuffixIOS { get; private set; }
+    public DirectoryPathCollection BuildDirs { get; private set; }
+    public string FileZipSuffix { get; private set; }
+    public FilePath ZipCoreArtifacts { get; private set; }
+    public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; }
+    public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; }
+
+    public Parameters(ICakeContext context)
+    {
+        var buildSystem = context.BuildSystem();
+
+        // ARGUMENTS
+        Target = context.Argument("target", "Default");
+        Platform = context.Argument("platform", "Any CPU");
+        Configuration = context.Argument("configuration", "Release");
+        SkipTests = context.HasArgument("skip-tests");
+
+        // CONFIGURATION
+        MainRepo = "AvaloniaUI/Avalonia";
+        MasterBranch = "master";
+        AssemblyInfoPath = context.File("./src/Shared/SharedAssemblyInfo.cs");
+        ReleasePlatform = "Any CPU";
+        ReleaseConfiguration = "Release";
+        MSBuildSolution = "./Avalonia.sln";
+        XBuildSolution = "./Avalonia.XBuild.sln";
+
+        // PARAMETERS
+        IsPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(Platform, "Any CPU");
+        IsPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x86");
+        IsPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x64");
+        IsLocalBuild = buildSystem.IsLocalBuild;
+        IsRunningOnUnix = context.IsRunningOnUnix();
+        IsRunningOnWindows = context.IsRunningOnWindows();
+        IsRunningOnAppVeyor = buildSystem.AppVeyor.IsRunningOnAppVeyor;
+        IsPullRequest = buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest;
+        IsMainRepo = StringComparer.OrdinalIgnoreCase.Equals(MainRepo, buildSystem.AppVeyor.Environment.Repository.Name);
+        IsMasterBranch = StringComparer.OrdinalIgnoreCase.Equals(MasterBranch, buildSystem.AppVeyor.Environment.Repository.Branch);
+        IsTagged = buildSystem.AppVeyor.Environment.Repository.Tag.IsTag 
+                && !string.IsNullOrWhiteSpace(buildSystem.AppVeyor.Environment.Repository.Tag.Name);
+        IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, Platform) 
+                    && StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
+        IsMyGetRelease = !IsTagged && IsReleasable;
+        IsNuGetRelease = IsTagged && IsReleasable;
+
+        // VERSION
+        Version = context.Argument("force-nuget-version", context.ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion);
+
+        if (IsRunningOnAppVeyor)
+        {
+            if (IsTagged)
+            {
+                // Use Tag Name as version
+                Version = buildSystem.AppVeyor.Environment.Repository.Tag.Name;
+            }
+            else
+            {
+                // Use AssemblyVersion with Build as version
+                Version += "-build" + context.EnvironmentVariable("APPVEYOR_BUILD_NUMBER") + "-alpha";
+            }
+        }
+
+        // DIRECTORIES
+        ArtifactsDir = (DirectoryPath)context.Directory("./artifacts");
+        NugetRoot = ArtifactsDir.Combine("nuget");
+        ZipRoot = ArtifactsDir.Combine("zip");
+        BinRoot = ArtifactsDir.Combine("bin");
+        TestsRoot = ArtifactsDir.Combine("tests");
+
+        DirSuffix = Configuration;
+        DirSuffixSkia = (IsPlatformAnyCPU ? "x86" : Platform) + "/" + Configuration;
+        DirSuffixIOS = "iPhone" + "/" + Configuration;
+
+        BuildDirs = 
+            context.GetDirectories("./src/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./src/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./src/Markup/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./src/Markup/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./src/Android/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./src/Android/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./src/Gtk/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./src/Gtk/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./src/iOS/**/bin/" + DirSuffixIOS) + 
+            context.GetDirectories("./src/iOS/**/obj/" + DirSuffixIOS) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Android/bin/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Android/obj/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Android.TestApp/bin/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Android.TestApp/obj/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Desktop/bin/" + DirSuffixSkia) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Desktop/obj/" + DirSuffixSkia) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Desktop.NetStandard/bin/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.Desktop.NetStandard/obj/" + DirSuffix) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.iOS/bin/" + DirSuffixIOS) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.iOS/obj/" + DirSuffixIOS) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/bin/" + DirSuffixIOS) + 
+            (DirectoryPath)context.Directory("./src/Skia/Avalonia.Skia.iOS.TestApp/obj/" + DirSuffixIOS) + 
+            context.GetDirectories("./src/Windows/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./src/Windows/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./tests/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./tests/**/obj/" + DirSuffix) + 
+            context.GetDirectories("./Samples/**/bin/" + DirSuffix) + 
+            context.GetDirectories("./Samples/**/obj/" + DirSuffix);
+
+        FileZipSuffix = Version + ".zip";
+        ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
+        ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix);
+        ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
+    }
+}

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

@@ -32,9 +32,12 @@
     <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
     <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
     <BundleAssemblies>False</BundleAssemblies>
     <BundleAssemblies>False</BundleAssemblies>
     <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
     <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
-    <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
+    <AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
     <Debugger>Xamarin</Debugger>
     <Debugger>Xamarin</Debugger>
     <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
     <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
+    <AotAssemblies>False</AotAssemblies>
+    <EnableLLVM>False</EnableLLVM>
+    <EnableProguard>False</EnableProguard>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>

+ 5 - 19
samples/ControlCatalog.Android/MainActivity.cs

@@ -1,9 +1,8 @@
 using System;
 using System;
 using Android.App;
 using Android.App;
-
 using Android.OS;
 using Android.OS;
 using Android.Content.PM;
 using Android.Content.PM;
-using Avalonia.Android.Platform.Specific;
+using Avalonia.Android;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Controls.Templates;
 using Avalonia.Controls.Templates;
 using Avalonia.Markup.Xaml;
 using Avalonia.Markup.Xaml;
@@ -17,29 +16,16 @@ namespace ControlCatalog.Android
     [Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)]
     [Activity(Label = "ControlCatalog.Android", MainLauncher = true, Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleInstance)]
     public class MainActivity : AvaloniaActivity
     public class MainActivity : AvaloniaActivity
     {
     {
-        public MainActivity() : base(typeof (App))
-        {
-
-        }
-
         protected override void OnCreate(Bundle savedInstanceState)
         protected override void OnCreate(Bundle savedInstanceState)
         {
         {
-            base.OnCreate(savedInstanceState);
-
-            App app;
-            if (Avalonia.Application.Current != null)
-                app = (App)Avalonia.Application.Current;
-            else
+            if (Avalonia.Application.Current == null)           
             {
             {
-                app = new App();
-                AppBuilder.Configure(app)
+                AppBuilder.Configure(new App())
                     .UseAndroid()
                     .UseAndroid()
-                    .UseSkia()
                     .SetupWithoutStarting();
                     .SetupWithoutStarting();
+                Content = new MainView();
             }
             }
-
-            var mainWindow = new MainWindow();
-            app.Run(mainWindow);
+            base.OnCreate(savedInstanceState);
         }
         }
     }
     }
 }
 }

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

@@ -33,6 +33,9 @@
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
+  <PropertyGroup>
+    <StartupObject />
+  </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
     <Reference Include="Serilog, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
     <Reference Include="Serilog, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
       <HintPath>..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll</HintPath>
       <HintPath>..\..\packages\Serilog.1.5.14\lib\net45\Serilog.dll</HintPath>
@@ -72,6 +75,10 @@
       <Project>{FB05AC90-89BA-4F2F-A924-F37875FB547C}</Project>
       <Project>{FB05AC90-89BA-4F2F-A924-F37875FB547C}</Project>
       <Name>Avalonia.Cairo</Name>
       <Name>Avalonia.Cairo</Name>
     </ProjectReference>
     </ProjectReference>
+    <ProjectReference Include="..\..\src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj">
+      <Project>{bb1f7bb5-6ad4-4776-94d9-c09d0a972658}</Project>
+      <Name>Avalonia.Gtk3</Name>
+    </ProjectReference>
     <ProjectReference Include="..\..\src\Gtk\Avalonia.Gtk\Avalonia.Gtk.csproj">
     <ProjectReference Include="..\..\src\Gtk\Avalonia.Gtk\Avalonia.Gtk.csproj">
       <Project>{54F237D5-A70A-4752-9656-0C70B1A7B047}</Project>
       <Project>{54F237D5-A70A-4752-9656-0C70B1A7B047}</Project>
       <Name>Avalonia.Gtk</Name>
       <Name>Avalonia.Gtk</Name>

+ 15 - 12
samples/ControlCatalog/Pages/TreeViewPage.xaml.cs

@@ -11,7 +11,7 @@ namespace ControlCatalog.Pages
         public TreeViewPage()
         public TreeViewPage()
         {
         {
             this.InitializeComponent();
             this.InitializeComponent();
-            DataContext = CreateNodes(0);
+            DataContext = new Node().Children;
         }
         }
 
 
         private void InitializeComponent()
         private void InitializeComponent()
@@ -19,19 +19,22 @@ namespace ControlCatalog.Pages
             AvaloniaXamlLoader.Load(this);
             AvaloniaXamlLoader.Load(this);
         }
         }
 
 
-        private IList<Node> CreateNodes(int level)
+        public class Node
         {
         {
-            return Enumerable.Range(0, 10).Select(x => new Node
+            private IList<Node> _children;
+            public string Header { get; private set; }
+            public IList<Node> Children
             {
             {
-                Header = $"Item {x}",
-                Children = level < 5 ? CreateNodes(level + 1) : null,
-            }).ToList();
-        }
-
-        private class Node
-        {
-            public string Header { get; set; }
-            public IList<Node> Children { get; set; }
+                get
+                {
+                    if (_children == null)
+                    {
+                        _children = Enumerable.Range(1, 10).Select(i => new Node() {Header = $"Item {i}"})
+                            .ToArray();
+                    }
+                    return _children;
+                }
+            }
         }
         }
     }
     }
 }
 }

+ 14 - 11
src/Android/Avalonia.Android/AndroidPlatform.cs

@@ -1,5 +1,8 @@
 using System;
 using System;
 using System.IO;
 using System.IO;
+using System.Linq;
+using Android.Content;
+using Android.Views;
 using Avalonia.Android.Platform;
 using Avalonia.Android.Platform;
 using Avalonia.Android.Platform.Input;
 using Avalonia.Android.Platform.Input;
 using Avalonia.Android.Platform.SkiaPlatform;
 using Avalonia.Android.Platform.SkiaPlatform;
@@ -8,6 +11,7 @@ using Avalonia.Controls.Platform;
 using Avalonia.Input;
 using Avalonia.Input;
 using Avalonia.Input.Platform;
 using Avalonia.Input.Platform;
 using Avalonia.Platform;
 using Avalonia.Platform;
+using Avalonia.Rendering;
 using Avalonia.Shared.PlatformSupport;
 using Avalonia.Shared.PlatformSupport;
 using Avalonia.Skia;
 using Avalonia.Skia;
 
 
@@ -17,7 +21,8 @@ namespace Avalonia
     {
     {
         public static T UseAndroid<T>(this T builder) where T : AppBuilderBase<T>, new()
         public static T UseAndroid<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
         {
-            builder.UseWindowingSubsystem(Android.AndroidPlatform.Initialize, "Android");
+            builder.UseWindowingSubsystem(() => Android.AndroidPlatform.Initialize(builder.Instance), "Android");
+            builder.UseSkia();
             return builder;
             return builder;
         }
         }
     }
     }
@@ -25,7 +30,7 @@ namespace Avalonia
 
 
 namespace Avalonia.Android
 namespace Avalonia.Android
 {
 {
-    public class AndroidPlatform : IPlatformSettings, IWindowingPlatform
+    class AndroidPlatform : IPlatformSettings, IWindowingPlatform
     {
     {
         public static readonly AndroidPlatform Instance = new AndroidPlatform();
         public static readonly AndroidPlatform Instance = new AndroidPlatform();
         public Size DoubleClickSize => new Size(4, 4);
         public Size DoubleClickSize => new Size(4, 4);
@@ -40,7 +45,7 @@ namespace Avalonia.Android
             _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity;
             _scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity;
         }
         }
 
 
-        public static void Initialize()
+        public static void Initialize(Avalonia.Application app)
         {
         {
             AvaloniaLocator.CurrentMutable
             AvaloniaLocator.CurrentMutable
                 .Bind<IClipboard>().ToTransient<ClipboardImpl>()
                 .Bind<IClipboard>().ToTransient<ClipboardImpl>()
@@ -51,24 +56,22 @@ namespace Avalonia.Android
                 .Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
                 .Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
                 .Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
                 .Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
                 .Bind<IWindowingPlatform>().ToConstant(Instance)
                 .Bind<IWindowingPlatform>().ToConstant(Instance)
-                .Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>();
+                .Bind<IPlatformIconLoader>().ToSingleton<PlatformIconLoader>()
+                .Bind<IRenderLoop>().ToConstant(new DefaultRenderLoop(60))
 
 
-            SkiaPlatform.Initialize();
-        }
+                .Bind<IAssetLoader>().ToConstant(new AssetLoader(app.GetType().Assembly));
 
 
-        public void Init(Type applicationType)
-        {
-            StandardRuntimePlatformServices.Register(applicationType.Assembly);
+            SkiaPlatform.Initialize();
         }
         }
 
 
         public IWindowImpl CreateWindow()
         public IWindowImpl CreateWindow()
         {
         {
-            return new WindowImpl();
+            throw new NotSupportedException();
         }
         }
 
 
         public IEmbeddableWindowImpl CreateEmbeddableWindow()
         public IEmbeddableWindowImpl CreateEmbeddableWindow()
         {
         {
-            throw new NotImplementedException();
+            throw new NotSupportedException();
         }
         }
 
 
         public IPopupImpl CreatePopup()
         public IPopupImpl CreatePopup()

+ 9 - 3
src/Android/Avalonia.Android/AndroidThreadingInterface.cs

@@ -51,10 +51,16 @@ namespace Avalonia.Android
                     scheduled = true;
                     scheduled = true;
                     EnsureInvokeOnMainThread(() =>
                     EnsureInvokeOnMainThread(() =>
                     {
                     {
-                        tick();
-                        lock (l)
+                        try
                         {
                         {
-                            scheduled = false;
+                            tick();
+                        }
+                        finally
+                        {
+                            lock (l)
+                            {
+                                scheduled = false;
+                            }
                         }
                         }
                     });
                     });
                 }
                 }

+ 5 - 4
src/Android/Avalonia.Android/Avalonia.Android.csproj

@@ -63,16 +63,17 @@
   <ItemGroup>
   <ItemGroup>
     <Compile Include="AndroidPlatform.cs" />
     <Compile Include="AndroidPlatform.cs" />
     <Compile Include="AndroidThreadingInterface.cs" />
     <Compile Include="AndroidThreadingInterface.cs" />
+    <Compile Include="AvaloniaActivity.cs" />
+    <Compile Include="AvaloniaView.cs" />
     <Compile Include="PlatformIconLoader.cs" />
     <Compile Include="PlatformIconLoader.cs" />
     <Compile Include="Platform\ClipboardImpl.cs" />
     <Compile Include="Platform\ClipboardImpl.cs" />
     <Compile Include="CursorFactory.cs" />
     <Compile Include="CursorFactory.cs" />
     <Compile Include="Platform\Input\AndroidKeyboardDevice.cs" />
     <Compile Include="Platform\Input\AndroidKeyboardDevice.cs" />
     <Compile Include="Platform\Input\AndroidMouseDevice.cs" />
     <Compile Include="Platform\Input\AndroidMouseDevice.cs" />
-    <Compile Include="Platform\SkiaPlatform\MainWindowImpl.cs" />
-    <Compile Include="Platform\SkiaPlatform\WindowImpl.cs" />
+    <Compile Include="Platform\SkiaPlatform\AndroidFramebuffer.cs" />
+    <Compile Include="Platform\SkiaPlatform\InvalidationAwareSurfaceView.cs" />
+    <Compile Include="Platform\SkiaPlatform\TopLevelImpl.cs" />
     <Compile Include="Platform\Specific\IAndroidView.cs" />
     <Compile Include="Platform\Specific\IAndroidView.cs" />
-    <Compile Include="Platform\Specific\IAndroidActivity.cs" />
-    <Compile Include="Platform\Specific\AvaloniaActivity.cs" />
     <Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />
     <Compile Include="Platform\Specific\Helpers\AndroidTouchEventsHelper.cs" />
     <Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" />
     <Compile Include="Platform\Specific\Helpers\AndroidKeyboardEventsHelper.cs" />
     <Compile Include="Resources\Resource.Designer.cs" />
     <Compile Include="Resources\Resource.Designer.cs" />

+ 50 - 0
src/Android/Avalonia.Android/AvaloniaActivity.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Android.App;
+using Android.Content;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+
+namespace Avalonia.Android
+{
+    public abstract class AvaloniaActivity : Activity
+    {
+        AvaloniaView _view;
+        object _content;
+
+        protected override void OnCreate(Bundle savedInstanceState)
+        {
+            RequestWindowFeature(WindowFeatures.NoTitle);
+            _view = new AvaloniaView(this);
+            if(_content != null)
+                _view.Content = _content;
+            SetContentView(_view);
+            TakeKeyEvents(true);
+            base.OnCreate(savedInstanceState);
+        }
+
+        public object Content
+        {
+            get
+            {
+                return _content;
+            }
+            set
+            {
+                _content = value;
+                if (_view != null)
+                    _view.Content = value;
+            }
+        }
+
+        public override bool DispatchKeyEvent(KeyEvent e)
+        {
+            return _view.DispatchKeyEvent(e);
+        }
+    }
+}

+ 59 - 0
src/Android/Avalonia.Android/AvaloniaView.cs

@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Android.App;
+using Android.Content;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+using Avalonia.Android.Platform.SkiaPlatform;
+using Avalonia.Controls.Embedding;
+using Avalonia.Platform;
+
+namespace Avalonia.Android
+{
+    public class AvaloniaView : FrameLayout
+    {
+        private readonly EmbeddableControlRoot _root;
+        private readonly ViewImpl _view;
+
+        public AvaloniaView(Context context) : base(context)
+        {
+            _view = new ViewImpl(context);
+            AddView(_view);
+            _root = new EmbeddableControlRoot(_view);
+            _root.Prepare();
+        }
+
+        public object Content
+        {
+            get { return _root.Content; }
+            set { _root.Content = value; }
+        }
+
+        public override bool DispatchKeyEvent(KeyEvent e)
+        {
+            return _view.DispatchKeyEvent(e);
+        }
+
+        class ViewImpl : TopLevelImpl, IEmbeddableWindowImpl
+        {
+            public event Action LostFocus;
+
+            public ViewImpl(Context context) : base(context)
+            {
+                Focusable = true;
+                FocusChange += ViewImpl_FocusChange;
+            }
+
+            private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e)
+            {
+                if(!e.HasFocus)
+                    LostFocus?.Invoke();
+            }
+        }
+    }
+}

+ 101 - 0
src/Android/Avalonia.Android/Platform/SkiaPlatform/AndroidFramebuffer.cs

@@ -0,0 +1,101 @@
+using System;
+using System.Runtime.InteropServices;
+using Android.Runtime;
+using Android.Views;
+using Avalonia.Controls.Platform.Surfaces;
+
+namespace Avalonia.Android.Platform.SkiaPlatform
+{
+    class AndroidFramebuffer : ILockedFramebuffer
+    {
+        private IntPtr _window;
+
+        public AndroidFramebuffer(Surface surface)
+        {
+            _window = ANativeWindow_fromSurface(JNIEnv.Handle, surface.Handle);
+            ANativeWindow_Buffer buffer;
+            var rc = new ARect()
+            {
+                right = Width = ANativeWindow_getWidth(_window),
+                bottom = Height = ANativeWindow_getHeight(_window)
+            };
+            ANativeWindow_lock(_window, out buffer, ref rc);
+
+            Format = buffer.format == AndroidPixelFormat.WINDOW_FORMAT_RGB_565
+                ? PixelFormat.Rgb565 : PixelFormat.Rgba8888;
+
+            RowBytes = buffer.stride * (Format == PixelFormat.Rgb565 ? 2 : 4);
+            Address = buffer.bits;
+        }
+
+        public void Dispose()
+        {
+            ANativeWindow_unlockAndPost(_window);
+            ANativeWindow_release(_window);
+            _window = IntPtr.Zero;
+            Address = IntPtr.Zero;
+        }
+
+        public IntPtr Address { get; set; }
+        public int Width { get; }
+        public int Height { get; }
+        public int RowBytes { get; }
+        public Size Dpi { get; } = new Size(96, 96);
+        public PixelFormat Format { get; }
+
+        [DllImport("android")]
+        internal static extern IntPtr ANativeWindow_fromSurface(IntPtr jniEnv, IntPtr handle);
+        [DllImport("android")]
+        internal static extern int ANativeWindow_getWidth(IntPtr window);
+        [DllImport("android")]
+        internal static extern int ANativeWindow_getHeight(IntPtr window);
+        [DllImport("android")]
+        internal static extern void ANativeWindow_release(IntPtr window);
+        [DllImport("android")]
+        internal static extern void ANativeWindow_unlockAndPost(IntPtr window);
+
+        [DllImport("android")]
+        internal static extern int ANativeWindow_lock(IntPtr window, out ANativeWindow_Buffer outBuffer, ref ARect inOutDirtyBounds);
+        public enum AndroidPixelFormat
+        {
+            WINDOW_FORMAT_RGBA_8888 = 1,
+            WINDOW_FORMAT_RGBX_8888 = 2,
+            WINDOW_FORMAT_RGB_565 = 4,
+        }
+
+        internal struct ARect
+        {
+            public int left;
+            public int top;
+            public int right;
+            public int bottom;
+        }
+        
+        internal struct ANativeWindow_Buffer
+        {
+            // The number of pixels that are show horizontally.
+            public int width;
+
+            // The number of pixels that are shown vertically.
+            public int height;
+
+            // The number of *pixels* that a line in the buffer takes in
+            // memory.  This may be >= width.
+            public int stride;
+
+            // The format of the buffer.  One of WINDOW_FORMAT_*
+            public AndroidPixelFormat format;
+
+            // The actual bits.
+            public IntPtr bits;
+
+            // Do not touch.
+            uint reserved1;
+            uint reserved2;
+            uint reserved3;
+            uint reserved4;
+            uint reserved5;
+            uint reserved6;
+        }
+    }
+}

+ 4 - 4
src/Skia/Avalonia.Skia.Android/SkiaView.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs

@@ -14,16 +14,16 @@ using Android.Widget;
 using Avalonia.Media;
 using Avalonia.Media;
 using Avalonia.Platform;
 using Avalonia.Platform;
 
 
-namespace Avalonia.Skia.Android
+namespace Avalonia.Android
 {
 {
-    public abstract class SkiaView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
+    public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle
     {
     {
-        private readonly Activity _context;
+        private readonly Context _context;
         bool _invalidateQueued;
         bool _invalidateQueued;
         readonly object _lock = new object();
         readonly object _lock = new object();
         private readonly Handler _handler;
         private readonly Handler _handler;
 
 
-        public SkiaView(Activity context) : base(context)
+        public InvalidationAwareSurfaceView(Context context) : base(context)
         {
         {
             _context = context;
             _context = context;
             Holder.AddCallback(this);
             Holder.AddCallback(this);

+ 0 - 44
src/Android/Avalonia.Android/Platform/SkiaPlatform/MainWindowImpl.cs

@@ -1,44 +0,0 @@
-using Android.Views;
-using Avalonia.Android.Platform.Specific;
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Platform;
-
-namespace Avalonia.Android.Platform.SkiaPlatform
-{
-    public class MainWindowImpl :
-        WindowImpl
-        , IWindowImpl
-    {
-        public MainWindowImpl()
-        {
-        }
-
-        public new WindowState WindowState
-        {
-            get { return WindowState.Normal; }
-            set { }
-        }
-
-        protected override void Init()
-        {
-            base.Init();
-
-            HandleEvents = true;
-            _keyboardHelper.ActivateAutoShowKeybord();
-        }
-
-        void ITopLevelImpl.Show()
-        {
-            (Parent as ViewGroup)?.RemoveAllViews();
-            AvaloniaLocator.Current.GetService<IAndroidActivity>().ContentView = this;
-            //this.Visibility = ViewStates.Visible;
-        }
-
-        void ITopLevelImpl.SetInputRoot(IInputRoot inputRoot)
-        {
-            base.SetInputRoot(inputRoot);
-            _keyboardHelper.UpdateKeyboardState(inputRoot);
-        }
-    }
-}

+ 16 - 22
src/Android/Avalonia.Android/Platform/SkiaPlatform/WindowImpl.cs → src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@@ -7,31 +7,30 @@ using Avalonia.Android.Platform.Specific.Helpers;
 using Avalonia.Input;
 using Avalonia.Input;
 using Avalonia.Input.Raw;
 using Avalonia.Input.Raw;
 using Avalonia.Platform;
 using Avalonia.Platform;
-using Avalonia.Skia.Android;
 using System;
 using System;
+using System.Collections.Generic;
 using Avalonia.Controls;
 using Avalonia.Controls;
+using Avalonia.Controls.Platform.Surfaces;
 
 
 namespace Avalonia.Android.Platform.SkiaPlatform
 namespace Avalonia.Android.Platform.SkiaPlatform
 {
 {
-    public class WindowImpl : SkiaView, IAndroidView, IWindowImpl, ISurfaceHolderCallback
+    class TopLevelImpl : InvalidationAwareSurfaceView, IAndroidView, ITopLevelImpl,
+        ISurfaceHolderCallback, IFramebufferPlatformSurface
+
     {
     {
-        protected AndroidKeyboardEventsHelper<WindowImpl> _keyboardHelper;
+        protected AndroidKeyboardEventsHelper<TopLevelImpl> _keyboardHelper;
 
 
-        private AndroidTouchEventsHelper<WindowImpl> _touchHelper;
+        private AndroidTouchEventsHelper<TopLevelImpl> _touchHelper;
 
 
-        public WindowImpl(Context context) : base((Activity)context)
+        public TopLevelImpl(Context context) : base(context)
         {
         {
-            _keyboardHelper = new AndroidKeyboardEventsHelper<WindowImpl>(this);
-            _touchHelper = new AndroidTouchEventsHelper<WindowImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
+            _keyboardHelper = new AndroidKeyboardEventsHelper<TopLevelImpl>(this);
+            _touchHelper = new AndroidTouchEventsHelper<TopLevelImpl>(this, () => InputRoot, p => GetAvaloniaPointFromEvent(p));
 
 
             MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
             MaxClientSize = new Size(Resources.DisplayMetrics.WidthPixels, Resources.DisplayMetrics.HeightPixels);
             ClientSize = MaxClientSize;
             ClientSize = MaxClientSize;
-            Init();
-        }
-
-        public WindowImpl() : this(AvaloniaLocator.Current.GetService<IAndroidActivity>().Activity)
-        {
         }
         }
+        
 
 
         void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
         void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
         {
         {
@@ -45,11 +44,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
 
 
             base.SurfaceChanged(holder, format, width, height);
             base.SurfaceChanged(holder, format, width, height);
         }
         }
-
-        protected virtual void Init()
-        {
-        }
-
+        
         private bool _handleEvents;
         private bool _handleEvents;
 
 
         public bool HandleEvents
         public bool HandleEvents
@@ -95,6 +90,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
 
 
         IPlatformHandle ITopLevelImpl.Handle => this;
         IPlatformHandle ITopLevelImpl.Handle => this;
 
 
+        public IEnumerable<object> Surfaces => new object[] { this };
+
         public void Activate()
         public void Activate()
         {
         {
         }
         }
@@ -108,11 +105,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
         {
         {
         }
         }
 
 
-        public void SetCoverTaskbarWhenMaximized(bool enable)
-        {
-            //Not supported
-        }
-
         public void Invalidate(Rect rect)
         public void Invalidate(Rect rect)
         {
         {
             if (Holder?.Surface?.IsValid == true) base.Invalidate();
             if (Holder?.Surface?.IsValid == true) base.Invalidate();
@@ -193,5 +185,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
         {
         {
             // No window icons for mobile platforms
             // No window icons for mobile platforms
         }
         }
+
+        ILockedFramebuffer IFramebufferPlatformSurface.Lock()=>new AndroidFramebuffer(Holder.Surface);
     }
     }
 }
 }

+ 0 - 60
src/Android/Avalonia.Android/Platform/Specific/AvaloniaActivity.cs

@@ -1,60 +0,0 @@
-using System;
-using Android.App;
-using Android.OS;
-using Android.Views;
-using Android.Widget;
-
-namespace Avalonia.Android.Platform.Specific
-{
-    public class AvaloniaActivity : Activity, IAndroidActivity
-    {
-        private IAndroidView _contentView;
-
-        public AvaloniaActivity(Type applicationType)
-        {
-            AndroidPlatform.Instance.Init(applicationType);
-        }
-
-        public Activity Activity => this;
-
-        public IAndroidView ContentView
-        {
-            get
-            {
-                return this._contentView;
-            }
-
-            set
-            {
-                this._contentView = value;
-                var fl = new FrameLayout(this);
-                fl.AddView(this._contentView.View);
-                //this.SetContentView(value.View);
-                this.SetContentView(fl);
-            }
-        }
-
-        protected override void OnCreate(Bundle savedInstanceState)
-        {
-            AvaloniaLocator.CurrentMutable.Bind<IAndroidActivity>().ToConstant(this);
-            RequestWindowFeature(WindowFeatures.NoTitle);
-            base.OnCreate(savedInstanceState);
-        }
-
-        public override void SetContentView(View view)
-        {
-            base.SetContentView(view);
-            TakeKeyEvents(true);
-        }
-
-        public override bool DispatchKeyEvent(KeyEvent e)
-        {
-            if (_contentView != null)
-            {
-                _contentView.View.DispatchKeyEvent(e);
-            }
-
-            return base.DispatchKeyEvent(e);
-        }
-    }
-}

+ 1 - 1
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs

@@ -12,7 +12,7 @@ using System.ComponentModel;
 
 
 namespace Avalonia.Android.Platform.Specific.Helpers
 namespace Avalonia.Android.Platform.Specific.Helpers
 {
 {
-    public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
+    public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
     {
     {
         private TView _view;
         private TView _view;
         private IInputElement _lastFocusedElement;
         private IInputElement _lastFocusedElement;

+ 1 - 1
src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidTouchEventsHelper.cs

@@ -8,7 +8,7 @@ using System;
 
 
 namespace Avalonia.Android.Platform.Specific.Helpers
 namespace Avalonia.Android.Platform.Specific.Helpers
 {
 {
-    public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, IWindowImpl, IAndroidView
+    public class AndroidTouchEventsHelper<TView> : IDisposable where TView : View, ITopLevelImpl, IAndroidView
     {
     {
         private TView _view;
         private TView _view;
         public bool HandleEvents { get; set; }
         public bool HandleEvents { get; set; }

+ 0 - 12
src/Android/Avalonia.Android/Platform/Specific/IAndroidActivity.cs

@@ -1,12 +0,0 @@
-using Android.App;
-using Android.Views;
-
-namespace Avalonia.Android.Platform.Specific
-{
-    public interface IAndroidActivity
-    {
-        Activity Activity { get; }
-
-        IAndroidView ContentView { get; set; }
-    }
-}

+ 8 - 9
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@@ -20,7 +20,7 @@
     <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
     <AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
-    <DebugSymbols>true</DebugSymbols>
+    <DebugSymbols>True</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
     <OutputPath>bin\Debug\</OutputPath>
@@ -29,16 +29,16 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
     <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
     <AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
     <AndroidLinkMode>None</AndroidLinkMode>
     <AndroidLinkMode>None</AndroidLinkMode>
-    <AndroidLinkSkip />
-    <EmbedAssembliesIntoApk>False</EmbedAssembliesIntoApk>
+    <EmbedAssembliesIntoApk>True</EmbedAssembliesIntoApk>
     <BundleAssemblies>False</BundleAssemblies>
     <BundleAssemblies>False</BundleAssemblies>
     <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
     <AndroidCreatePackagePerAbi>False</AndroidCreatePackagePerAbi>
-    <AndroidSupportedAbis>armeabi,armeabi-v7a,x86</AndroidSupportedAbis>
-    <AndroidStoreUncompressedFileExtensions />
-    <MandroidI18n />
+    <AndroidSupportedAbis>armeabi;armeabi-v7a;x86</AndroidSupportedAbis>
     <Debugger>Xamarin</Debugger>
     <Debugger>Xamarin</Debugger>
     <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
     <AndroidEnableMultiDex>False</AndroidEnableMultiDex>
     <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
     <DevInstrumentationEnabled>True</DevInstrumentationEnabled>
+    <AotAssemblies>False</AotAssemblies>
+    <EnableLLVM>False</EnableLLVM>
+    <EnableProguard>False</EnableProguard>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
@@ -72,9 +72,8 @@
       <HintPath>..\..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll</HintPath>
       <HintPath>..\..\..\packages\Splat.1.6.2\lib\monoandroid\Splat.dll</HintPath>
       <Private>True</Private>
       <Private>True</Private>
     </Reference>
     </Reference>
-    <Reference Include="Sprache, Version=2.0.0.51, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\..\..\packages\Sprache.2.0.0.51\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="Sprache, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\Sprache.2.1.0\lib\netstandard1.0\Sprache.dll</HintPath>
     </Reference>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Core" />

+ 8 - 24
src/Android/Avalonia.AndroidTestApplication/MainActivity.cs

@@ -2,7 +2,7 @@ using System;
 using Android.App;
 using Android.App;
 using Android.Content.PM;
 using Android.Content.PM;
 using Android.OS;
 using Android.OS;
-using Avalonia.Android.Platform.Specific;
+using Avalonia.Android;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Controls.Templates;
 using Avalonia.Controls.Templates;
 using Avalonia.Markup.Xaml;
 using Avalonia.Markup.Xaml;
@@ -17,36 +17,24 @@ namespace Avalonia.AndroidTestApplication
         Icon = "@drawable/icon",
         Icon = "@drawable/icon",
         LaunchMode = LaunchMode.SingleInstance/*,
         LaunchMode = LaunchMode.SingleInstance/*,
         ScreenOrientation = ScreenOrientation.Landscape*/)]
         ScreenOrientation = ScreenOrientation.Landscape*/)]
-    public class MainBaseActivity : AvaloniaActivity
+    public class MainBaseActivity : Activity
     {
     {
-        public MainBaseActivity() : base(typeof (App))
-        {
-
-        }
-
         protected override void OnCreate(Bundle savedInstanceState)
         protected override void OnCreate(Bundle savedInstanceState)
         {
         {
             base.OnCreate(savedInstanceState);
             base.OnCreate(savedInstanceState);
-
-            App app;
-            if (Avalonia.Application.Current != null)
-                app = (App)Avalonia.Application.Current;
-            else
+            if (Avalonia.Application.Current == null)
             {
             {
-                app = new App();
-                AppBuilder.Configure(app)
+                AppBuilder.Configure<App>()
                     .UseAndroid()
                     .UseAndroid()
-                    .UseSkia()
                     .SetupWithoutStarting();
                     .SetupWithoutStarting();
             }
             }
-
-            app.Run();
+            SetContentView(new AvaloniaView(this) { Content = App.CreateSimpleWindow() });
         }
         }
     }
     }
 
 
     public class App : Application
     public class App : Application
     {
     {
-        public void Run()
+        public override void Initialize()
         {
         {
             Styles.Add(new DefaultTheme());
             Styles.Add(new DefaultTheme());
 
 
@@ -55,18 +43,14 @@ namespace Avalonia.AndroidTestApplication
                 new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
                 new Uri("resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"));
             Styles.Add(baseLight);
             Styles.Add(baseLight);
 
 
-            var wnd = App.CreateSimpleWindow();
-            wnd.AttachDevTools();
 
 
-            Run(wnd);
         }
         }
 
 
         // This provides a simple UI tree for testing input handling, drawing, etc
         // This provides a simple UI tree for testing input handling, drawing, etc
-        public static Window CreateSimpleWindow()
+        public static ContentControl CreateSimpleWindow()
         {
         {
-            Window window = new Window
+            ContentControl window = new ContentControl()
             {
             {
-                Title = "Avalonia Test Application",
                 Background = Brushes.Red,
                 Background = Brushes.Red,
                 Content = new StackPanel
                 Content = new StackPanel
                 {
                 {

+ 2 - 1
src/Android/Avalonia.AndroidTestApplication/packages.config

@@ -2,7 +2,7 @@
 <packages>
 <packages>
   <package id="Serilog" version="1.5.14" targetFramework="monoandroid44" />
   <package id="Serilog" version="1.5.14" targetFramework="monoandroid44" />
   <package id="Splat" version="1.6.2" targetFramework="monoandroid51" />
   <package id="Splat" version="1.6.2" targetFramework="monoandroid51" />
-  <package id="Sprache" version="2.0.0.51" targetFramework="monoandroid44" />
+  <package id="Sprache" version="2.1.0" targetFramework="monoandroid44" />
   <package id="System.Collections" version="4.0.11" targetFramework="monoandroid44" />
   <package id="System.Collections" version="4.0.11" targetFramework="monoandroid44" />
   <package id="System.Collections.Concurrent" version="4.0.12" targetFramework="monoandroid44" />
   <package id="System.Collections.Concurrent" version="4.0.12" targetFramework="monoandroid44" />
   <package id="System.ComponentModel" version="4.0.1" targetFramework="monoandroid44" />
   <package id="System.ComponentModel" version="4.0.1" targetFramework="monoandroid44" />
@@ -19,6 +19,7 @@
   <package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="monoandroid44" />
   <package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="monoandroid44" />
   <package id="System.Runtime" version="4.1.0" targetFramework="monoandroid44" />
   <package id="System.Runtime" version="4.1.0" targetFramework="monoandroid44" />
   <package id="System.Runtime.Extensions" version="4.1.0" targetFramework="monoandroid44" />
   <package id="System.Runtime.Extensions" version="4.1.0" targetFramework="monoandroid44" />
+  <package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="monoandroid44" />
   <package id="System.Threading" version="4.0.11" targetFramework="monoandroid44" />
   <package id="System.Threading" version="4.0.11" targetFramework="monoandroid44" />
   <package id="System.Threading.Tasks" version="4.0.11" targetFramework="monoandroid44" />
   <package id="System.Threading.Tasks" version="4.0.11" targetFramework="monoandroid44" />
 </packages>
 </packages>

+ 2 - 2
src/Avalonia.Animation/Avalonia.Animation.csproj

@@ -16,7 +16,7 @@
     <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
     <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -27,7 +27,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Animation.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Animation.XML</DocumentationFile>
     <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
     <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Base/Avalonia.Base.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Base.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Base.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 5 - 2
src/Avalonia.Controls/Avalonia.Controls.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Controls.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Controls.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>
@@ -57,6 +57,9 @@
     <Compile Include="HotkeyManager.cs" />
     <Compile Include="HotkeyManager.cs" />
     <Compile Include="IApplicationLifecycle.cs" />
     <Compile Include="IApplicationLifecycle.cs" />
     <Compile Include="IScrollable.cs" />
     <Compile Include="IScrollable.cs" />
+    <Compile Include="Platform\Surfaces\IFramebufferPlatformSurface.cs" />
+    <Compile Include="Platform\Surfaces\ILockedFramebuffer.cs" />
+    <Compile Include="Platform\Surfaces\PixelFormat.cs" />
     <Compile Include="PointEventArgs.cs" />
     <Compile Include="PointEventArgs.cs" />
     <Compile Include="Embedding\EmbeddableControlRoot.cs" />
     <Compile Include="Embedding\EmbeddableControlRoot.cs" />
     <Compile Include="Platform\IEmbeddableWindowImpl.cs" />
     <Compile Include="Platform\IEmbeddableWindowImpl.cs" />

+ 2 - 1
src/Avalonia.Controls/Expander.cs

@@ -31,7 +31,8 @@ namespace Avalonia.Controls
             AvaloniaProperty.RegisterDirect<Expander, bool>(
             AvaloniaProperty.RegisterDirect<Expander, bool>(
                 nameof(IsExpanded),
                 nameof(IsExpanded),
                 o => o.IsExpanded,
                 o => o.IsExpanded,
-                (o, v) => o.IsExpanded = v);
+                (o, v) => o.IsExpanded = v,
+                defaultBindingMode: Data.BindingMode.TwoWay);
 
 
         static Expander()
         static Expander()
         {
         {

+ 13 - 0
src/Avalonia.Controls/Platform/ITopLevelImpl.cs

@@ -2,6 +2,7 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 
 using System;
 using System;
+using System.Collections.Generic;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Input;
 using Avalonia.Input;
 using Avalonia.Input.Raw;
 using Avalonia.Input.Raw;
@@ -37,6 +38,18 @@ namespace Avalonia.Platform
         /// </summary>
         /// </summary>
         IPlatformHandle Handle { get; }
         IPlatformHandle Handle { get; }
 
 
+        /// <summary>
+        /// The list of native platform's surfaces that can be consumed by rendering subsystems.
+        /// </summary>
+        /// <remarks>
+        /// Rendering platform will check that list and see if it can utilize one of them to output.
+        /// It should be enough to expose a native window handle via IPlatformHandle
+        /// and add support for framebuffer (even if it's emulated one) via IFramebufferPlatformSurface.
+        /// If you have some rendering platform that's tied to your particular windowing platform,
+        /// just expose some toolkit-specific object (e. g. Func&lt;Gdk.Drawable&gt; in case of GTK#+Cairo)
+        /// </remarks>
+        IEnumerable<object> Surfaces { get; }
+
         /// <summary>
         /// <summary>
         /// Gets or sets a method called when the window is activated (receives focus).
         /// Gets or sets a method called when the window is activated (receives focus).
         /// </summary>
         /// </summary>

+ 0 - 5
src/Avalonia.Controls/Platform/IWindowImpl.cs

@@ -35,11 +35,6 @@ namespace Avalonia.Platform
         /// </summary>
         /// </summary>
         void SetSystemDecorations(bool enabled);
         void SetSystemDecorations(bool enabled);
 
 
-        /// <summary>
-        /// When system decorations are disabled sets if the maximized state covers the entire screen or just the working area.
-        /// </summary>        
-        void SetCoverTaskbarWhenMaximized(bool enable);
-
         /// <summary>
         /// <summary>
         /// Sets the icon of this window.
         /// Sets the icon of this window.
         /// </summary>
         /// </summary>

+ 19 - 0
src/Avalonia.Controls/Platform/Surfaces/IFramebufferPlatformSurface.cs

@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Controls.Platform.Surfaces
+{
+    public interface IFramebufferPlatformSurface
+    {
+        /// <summary>
+        /// Provides a framebuffer descriptor for drawing.
+        /// </summary>
+        /// <remarks>
+        /// Contents should be drawn on actual window after disposing
+        /// </remarks>
+        ILockedFramebuffer Lock();
+    }
+}

+ 37 - 0
src/Avalonia.Controls/Platform/Surfaces/ILockedFramebuffer.cs

@@ -0,0 +1,37 @@
+using System;
+
+namespace Avalonia.Controls.Platform.Surfaces
+{
+    public interface ILockedFramebuffer : IDisposable
+    {
+        /// <summary>
+        /// Address of the first pixel
+        /// </summary>
+        IntPtr Address { get; }
+
+        /// <summary>
+        /// Framebuffer width
+        /// </summary>
+        int Width { get; }
+        
+        /// <summary>
+        /// Framebuffer height
+        /// </summary>
+        int Height { get; }
+        
+        /// <summary>
+        /// Number of bytes per row
+        /// </summary>
+        int RowBytes { get; }
+        
+        /// <summary>
+        /// DPI of underling screen
+        /// </summary>
+        Size Dpi { get; }
+        
+        /// <summary>
+        /// Pixel format
+        /// </summary>
+        PixelFormat Format { get; }
+    }
+}

+ 15 - 0
src/Avalonia.Controls/Platform/Surfaces/PixelFormat.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Controls.Platform.Surfaces
+{
+    public enum PixelFormat
+    {
+        Rgb565,
+        Rgba8888,
+        Bgra8888
+    }
+}

+ 4 - 2
src/Avalonia.Controls/TopLevel.cs

@@ -185,7 +185,7 @@ namespace Avalonia.Controls
         /// <summary>
         /// <summary>
         /// Gets the renderer for the window.
         /// Gets the renderer for the window.
         /// </summary>
         /// </summary>
-        public IRenderer Renderer { get; }
+        public IRenderer Renderer { get; private set; }
 
 
         /// <summary>
         /// <summary>
         /// Gets the access key handler for the window.
         /// Gets the access key handler for the window.
@@ -241,7 +241,7 @@ namespace Avalonia.Controls
         /// <inheritdoc/>
         /// <inheritdoc/>
         IRenderTarget IRenderRoot.CreateRenderTarget(IVisualBrushRenderer visualBrushRenderer)
         IRenderTarget IRenderRoot.CreateRenderTarget(IVisualBrushRenderer visualBrushRenderer)
         {
         {
-            return _renderInterface.CreateRenderTarget(PlatformImpl.Handle);
+            return _renderInterface.CreateRenderTarget(PlatformImpl.Surfaces);
         }
         }
 
 
         /// <inheritdoc/>
         /// <inheritdoc/>
@@ -386,6 +386,8 @@ namespace Avalonia.Controls
         {
         {
             IsVisible = false;
             IsVisible = false;
             Closed?.Invoke(this, EventArgs.Empty);
             Closed?.Invoke(this, EventArgs.Empty);
+            Renderer?.Dispose();
+            Renderer = null;
             _applicationLifecycle.OnExit -= OnApplicationExiting;
             _applicationLifecycle.OnExit -= OnApplicationExiting;
         }
         }
 
 

+ 0 - 20
src/Avalonia.Controls/Window.cs

@@ -64,13 +64,6 @@ namespace Avalonia.Controls
         public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
         public static readonly StyledProperty<bool> HasSystemDecorationsProperty =
             AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
             AvaloniaProperty.Register<Window, bool>(nameof(HasSystemDecorations), true);
 
 
-        /// <summary>
-        /// Sets if the window should cover the taskbar when maximized. Only applies to Windows 
-        /// with HasSystemDecorations = false.
-        /// </summary>
-        public static readonly StyledProperty<bool> CoverTaskbarOnMaximizeProperty =
-            AvaloniaProperty.Register<Window, bool>(nameof(CoverTaskbarOnMaximize), true);
-
         /// <summary>
         /// <summary>
         /// Defines the <see cref="Title"/> property.
         /// Defines the <see cref="Title"/> property.
         /// </summary>
         /// </summary>
@@ -97,9 +90,6 @@ namespace Avalonia.Controls
             HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
             HasSystemDecorationsProperty.Changed.AddClassHandler<Window>(
                 (s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
                 (s, e) => s.PlatformImpl.SetSystemDecorations((bool) e.NewValue));
 
 
-            CoverTaskbarOnMaximizeProperty.Changed.AddClassHandler<Window>(
-                (s, e) => s.PlatformImpl.SetCoverTaskbarWhenMaximized((bool)e.NewValue));
-
             IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
             IconProperty.Changed.AddClassHandler<Window>((s, e) => s.PlatformImpl.SetIcon(((WindowIcon)e.NewValue).PlatformImpl));
         }
         }
 
 
@@ -168,16 +158,6 @@ namespace Avalonia.Controls
             set { SetValue(HasSystemDecorationsProperty, value); }
             set { SetValue(HasSystemDecorationsProperty, value); }
         }
         }
 
 
-        /// <summary>
-        /// Sets if the window should cover the taskbar when maximized. Only applies to Windows 
-        /// with HasSystemDecorations = false.
-        /// </summary>
-        public bool CoverTaskbarOnMaximize
-        {
-            get { return GetValue(CoverTaskbarOnMaximizeProperty); }
-            set { SetValue(CoverTaskbarOnMaximizeProperty, value); }
-        }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the minimized/maximized state of the window.
         /// Gets or sets the minimized/maximized state of the window.
         /// </summary>
         /// </summary>

+ 2 - 2
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.DesignerSupport.xml</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.DesignerSupport.xml</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Diagnostics.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Diagnostics.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 53 - 0
src/Avalonia.DotNetCoreRuntime/AppBuilder.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Platform;
+using Avalonia.Shared.PlatformSupport;
+
+namespace Avalonia
+{
+    public sealed class AppBuilder : AppBuilderBase<AppBuilder>
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AppBuilder"/> class.
+        /// </summary>
+        public AppBuilder()
+            : base(new StandardRuntimePlatform(), () => StandardRuntimePlatformServices.Register())
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AppBuilder"/> class.
+        /// </summary>
+        /// <param name="app">The <see cref="Application"/> instance.</param>
+        public AppBuilder(Application app) : this()
+        {
+            Instance = app;
+        }
+
+        /// <summary>
+        /// Instructs the <see cref="AppBuilder"/> to use the best settings for the platform.
+        /// </summary>
+        /// <returns>An <see cref="AppBuilder"/> instance.</returns>
+        public AppBuilder UsePlatformDetect()
+        {
+            //We don't have the ability to load every assembly right now, so we are
+            //stuck with manual configuration  here
+            //Helpers are extracted to separate methods to take the advantage of the fact
+            //that CLR doesn't try to load dependencies before referencing method is jitted
+            if (RuntimePlatform.GetRuntimeInfo().OperatingSystem == OperatingSystemType.WinNT)
+                LoadWin32();
+            else
+                LoadGtk3();
+            this.UseSkia();
+
+            return this;
+        }
+
+        void LoadWin32() => this.UseWin32();
+        void LoadGtk3() => this.UseGtk3();
+    }
+}

+ 89 - 0
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.csproj

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{7863EA94-F0FB-4386-BF8C-E5BFA761560A}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Avalonia.DotNetCoreRuntime</RootNamespace>
+    <AssemblyName>Avalonia.DotNetCoreRuntime</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;NETSTANDARD</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;NETSTANDARD</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Avalonia.DotNetCoreRuntime.XML</DocumentationFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .NET Framework is automatically included -->
+    <None Include="project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Shared\SharedAssemblyInfo.cs">
+      <Link>SharedAssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="AppBuilder.cs" />
+    <Compile Include="NetCoreRuntimePlatform.cs" />
+    <Compile Include="RuntimeInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj">
+      <Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
+      <Name>Avalonia.Base</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj">
+      <Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
+      <Name>Avalonia.Controls</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj">
+      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
+      <Name>Avalonia.Visuals</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj">
+      <Project>{bb1f7bb5-6ad4-4776-94d9-c09d0a972658}</Project>
+      <Name>Avalonia.Gtk3</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Skia\Avalonia.Skia.Desktop.NetStandard\Avalonia.Skia.Desktop.NetStandard.csproj">
+      <Project>{7d2d3083-71dd-4cc9-8907-39a0d86fb322}</Project>
+      <Name>Avalonia.Skia.Desktop.NetStandard</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Windows\Avalonia.Win32.NetStandard\Avalonia.Win32.NetStandard.csproj">
+      <Project>{40759a76-d0f2-464e-8000-6ff0f5c4bd7c}</Project>
+      <Name>Avalonia.Win32.NetStandard</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+  <Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 5 - 0
src/Avalonia.DotNetCoreRuntime/Avalonia.DotNetCoreRuntime.v3.ncrunchproject

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

+ 47 - 0
src/Avalonia.DotNetCoreRuntime/NetCoreRuntimePlatform.cs

@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Shared.PlatformSupport
+{
+    internal partial class StandardRuntimePlatform
+    {
+        private static readonly Lazy<Assembly[]> Assemblies = new Lazy<Assembly[]>(LoadAssemblies);
+        public Assembly[] GetLoadedAssemblies() => Assemblies.Value;
+
+        static Assembly[] LoadAssemblies()
+        {
+
+            var rv = new List<Assembly>();
+            var entry = Assembly.GetEntryAssembly();
+            rv.Add(entry);
+            var queue = new Queue<AssemblyName>(entry.GetReferencedAssemblies());
+            var aset = new HashSet<string>(queue.Select(r => r.ToString()));
+
+            while (queue.Count > 0)
+            {
+                Assembly asm;
+                try
+                {
+                    asm = Assembly.Load(queue.Dequeue());
+                }
+                catch (Exception e)
+                {
+                    Debug.Write(e.ToString());
+                    continue;
+                }
+                rv.Add(asm);
+                foreach (var r in asm.GetReferencedAssemblies())
+                {
+                    if (aset.Add(r.ToString()))
+                        queue.Enqueue(r);
+                }
+            }
+            return rv.Distinct().ToArray();
+        }
+    }
+}

+ 41 - 0
src/Avalonia.DotNetCoreRuntime/RuntimeInfo.cs

@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+
+namespace Avalonia.Shared.PlatformSupport
+{
+    internal partial class StandardRuntimePlatform
+    {
+        private static readonly Lazy<RuntimePlatformInfo> Info = new Lazy<RuntimePlatformInfo>(() =>
+        {
+            OperatingSystemType os;
+            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+                os = OperatingSystemType.OSX;
+            else if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+                os = OperatingSystemType.Linux;
+            else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+                os = OperatingSystemType.WinNT;
+            else
+                throw new Exception("Unknown OS platform " + RuntimeInformation.OSDescription);
+
+            return new RuntimePlatformInfo
+            {
+                IsCoreClr = true,
+                IsDesktop = true,
+                IsDotNetFramework = false,
+                IsMono = false,
+                IsMobile = false,
+                IsUnix = os != OperatingSystemType.WinNT,
+                OperatingSystem = os,
+            };
+        });
+
+
+        public RuntimePlatformInfo GetRuntimeInfo() => Info.Value;
+    }
+}

+ 11 - 0
src/Avalonia.DotNetCoreRuntime/project.json

@@ -0,0 +1,11 @@
+{
+  "supports": {},
+  "dependencies": {
+    "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+    "NETStandard.Library": "1.6.0",
+    "System.Threading.ThreadPool": "4.3.0"
+  },
+  "frameworks": {
+    "netstandard1.5": {}
+  }
+}

+ 2 - 2
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@@ -13,7 +13,7 @@
     <FileAlignment>512</FileAlignment>
     <FileAlignment>512</FileAlignment>
     <TargetFrameworkProfile />
     <TargetFrameworkProfile />
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -23,7 +23,7 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Debug\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.DotNetFrameworkRuntime.xml</DocumentationFile>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 6 - 0
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.v3.ncrunchproject

@@ -0,0 +1,6 @@
+<ProjectConfiguration>
+  <Settings>
+    <IgnoreThisComponentCompletely>False</IgnoreThisComponentCompletely>
+    <PreviouslyBuiltSuccessfully>True</PreviouslyBuiltSuccessfully>
+  </Settings>
+</ProjectConfiguration>

+ 2 - 2
src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -27,7 +27,7 @@
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Input/Avalonia.Input.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Input.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Input.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Interactivity.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Interactivity.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Layout/Avalonia.Layout.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Layout.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Layout.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj

@@ -16,7 +16,7 @@
     <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
     <TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -26,7 +26,7 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Debug\Avalonia.Logging.Serilog.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Logging.Serilog.XML</DocumentationFile>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@@ -16,7 +16,7 @@
     <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
     <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -25,7 +25,7 @@
     <ErrorReport>prompt</ErrorReport>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Styling/Avalonia.Styling.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Styling.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Styling.XML</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -28,7 +28,7 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Debug\Avalonia.Themes.Default.XML</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Themes.Default.XML</DocumentationFile>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 2 - 2
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@@ -18,7 +18,7 @@
     <NuGetPackageImportStamp>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
     <DebugSymbols>true</DebugSymbols>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
     <DebugType>full</DebugType>
     <Optimize>false</Optimize>
     <Optimize>false</Optimize>
@@ -29,7 +29,7 @@
     <DocumentationFile>bin\Debug\Avalonia.Visuals.xml</DocumentationFile>
     <DocumentationFile>bin\Debug\Avalonia.Visuals.xml</DocumentationFile>
     <NoWarn>CS1591</NoWarn>
     <NoWarn>CS1591</NoWarn>
   </PropertyGroup>
   </PropertyGroup>
-  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
     <DebugType>pdbonly</DebugType>
     <DebugType>pdbonly</DebugType>
     <Optimize>true</Optimize>
     <Optimize>true</Optimize>
     <OutputPath>bin\Release\</OutputPath>
     <OutputPath>bin\Release\</OutputPath>

+ 5 - 2
src/Avalonia.Visuals/Platform/IPlatformRenderInterface.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // 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.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 
+using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using Avalonia.Media;
 using Avalonia.Media;
 
 
@@ -42,9 +43,11 @@ namespace Avalonia.Platform
         /// <summary>
         /// <summary>
         /// Creates a renderer.
         /// Creates a renderer.
         /// </summary>
         /// </summary>
-        /// <param name="handle">The platform handle for the renderer.</param>
+        /// <param name="surfaces">
+        /// The list of native platform surfaces that can be used for output.
+        /// </param>
         /// <returns>An <see cref="IRenderTarget"/>.</returns>
         /// <returns>An <see cref="IRenderTarget"/>.</returns>
-        IRenderTarget CreateRenderTarget(IPlatformHandle handle);
+        IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces);
 
 
         /// <summary>
         /// <summary>
         /// Creates a render target bitmap implementation.
         /// Creates a render target bitmap implementation.

+ 7 - 15
src/Gtk/Avalonia.Cairo/CairoPlatform.cs

@@ -2,6 +2,8 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 
 using System;
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using Avalonia.Cairo.Media;
 using Avalonia.Cairo.Media;
 using Avalonia.Cairo.Media.Imaging;
 using Avalonia.Cairo.Media.Imaging;
 using Avalonia.Media;
 using Avalonia.Media;
@@ -51,24 +53,14 @@ namespace Avalonia.Cairo
             return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight, constraint);
             return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight, constraint);
         }
         }
 
 
-        public IRenderTarget CreateRenderTarget(IPlatformHandle handle)
+        public IRenderTarget CreateRenderTarget(IEnumerable<object> surfaces)
         {
         {
-            var window = handle as Gtk.Window;
-            if (window != null)
-            {
-                window.DoubleBuffered = true;
-                return new RenderTarget(window);
-            }
-            var area = handle as Gtk.DrawingArea;
-            if (area != null)
-            {
-                area.DoubleBuffered = true;
-                return new RenderTarget(area);
-            }
+            var accessor = surfaces?.OfType<Func<Gdk.Drawable>>().FirstOrDefault();
+            if(accessor!=null)
+                return new RenderTarget(accessor);
 
 
             throw new NotSupportedException(string.Format(
             throw new NotSupportedException(string.Format(
-                "Don't know how to create a Cairo renderer from a '{0}' handle which isn't Gtk.Window or Gtk.DrawingArea",
-                handle.HandleDescriptor));
+                "Don't know how to create a Cairo renderer from any of the provided surfaces."));
         }
         }
 
 
         public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height, double dpiX, double dpiY)
         public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height, double dpiX, double dpiY)

+ 6 - 13
src/Gtk/Avalonia.Cairo/RenderTarget.cs

@@ -20,8 +20,8 @@ namespace Avalonia.Cairo
     public class RenderTarget : IRenderTarget
     public class RenderTarget : IRenderTarget
     {
     {
         private readonly Surface _surface;
         private readonly Surface _surface;
-        private readonly Gtk.Window _window;
-        private readonly Gtk.DrawingArea _area;
+        private readonly Func<Gdk.Drawable> _drawableAccessor;
+
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="RenderTarget"/> class.
         /// Initializes a new instance of the <see cref="RenderTarget"/> class.
@@ -29,9 +29,9 @@ namespace Avalonia.Cairo
         /// <param name="window">The window.</param>
         /// <param name="window">The window.</param>
         /// <param name="width">The width of the window.</param>
         /// <param name="width">The width of the window.</param>
         /// <param name="height">The height of the window.</param>
         /// <param name="height">The height of the window.</param>
-        public RenderTarget(Gtk.Window window)
+        public RenderTarget(Func<Gdk.Drawable> drawable)
         {
         {
-            _window = window;
+            _drawableAccessor = drawable;
         }
         }
 
 
         public RenderTarget(ImageSurface surface)
         public RenderTarget(ImageSurface surface)
@@ -39,11 +39,6 @@ namespace Avalonia.Cairo
             _surface = surface;
             _surface = surface;
         }
         }
 
 
-        public RenderTarget(DrawingArea area)
-        {
-            _area = area;
-        }
-
         /// <summary>
         /// <summary>
         /// Creates a cairo surface that targets a platform-specific resource.
         /// Creates a cairo surface that targets a platform-specific resource.
         /// </summary>
         /// </summary>
@@ -51,12 +46,10 @@ namespace Avalonia.Cairo
         /// <returns>A surface wrapped in an <see cref="Avalonia.Media.DrawingContext"/>.</returns>
         /// <returns>A surface wrapped in an <see cref="Avalonia.Media.DrawingContext"/>.</returns>
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         {
         {
-            if (_window != null)
-                return new Media.DrawingContext(_window.GdkWindow);
+            if (_drawableAccessor != null)
+                return new Media.DrawingContext(_drawableAccessor());
             if (_surface != null)
             if (_surface != null)
                 return new Media.DrawingContext(_surface);
                 return new Media.DrawingContext(_surface);
-            if (_area != null)
-                return new Media.DrawingContext(_area.GdkWindow);
             throw new InvalidOperationException("Unspecified render target");
             throw new InvalidOperationException("Unspecified render target");
         }
         }
 
 

+ 5 - 0
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@@ -30,6 +30,8 @@
     <ConsolePause>false</ConsolePause>
     <ConsolePause>false</ConsolePause>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
+    <Reference Include="Mono.Cairo, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System" />
     <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <Reference Include="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <Reference Include="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
@@ -48,7 +50,10 @@
     <Compile Include="ClipboardImpl.cs" />
     <Compile Include="ClipboardImpl.cs" />
     <Compile Include="EmbeddableImpl.cs" />
     <Compile Include="EmbeddableImpl.cs" />
     <Compile Include="Embedding\GtkAvaloniaControlHost.cs" />
     <Compile Include="Embedding\GtkAvaloniaControlHost.cs" />
+    <Compile Include="FramebufferManager.cs" />
     <Compile Include="IconImpl.cs" />
     <Compile Include="IconImpl.cs" />
+    <Compile Include="KeyTransform.cs" />
+    <Compile Include="SurfaceFramebuffer.cs" />
     <Compile Include="SystemDialogImpl.cs" />
     <Compile Include="SystemDialogImpl.cs" />
     <Compile Include="CursorFactory.cs" />
     <Compile Include="CursorFactory.cs" />
     <Compile Include="GtkExtensions.cs" />
     <Compile Include="GtkExtensions.cs" />

+ 39 - 0
src/Gtk/Avalonia.Gtk/FramebufferManager.cs

@@ -0,0 +1,39 @@
+using System;
+using Avalonia.Controls.Platform.Surfaces;
+
+namespace Avalonia.Gtk
+{
+    class FramebufferManager : IFramebufferPlatformSurface, IDisposable
+    {
+        private readonly WindowImplBase _window;
+        private SurfaceFramebuffer _fb;
+
+        public FramebufferManager(WindowImplBase window)
+        {
+            _window = window;
+        }
+
+        public void Dispose()
+        {
+            _fb?.Deallocate();
+        }
+
+        public ILockedFramebuffer Lock()
+        {
+            if(_window.CurrentDrawable == null)
+                throw new InvalidOperationException("Window is not in drawing state");
+
+            var drawable = _window.CurrentDrawable;
+            var width = (int) _window.ClientSize.Width;
+            var height = (int) _window.ClientSize.Height;
+            if (_fb == null || _fb.Width != width ||
+                _fb.Height != height)
+            {
+                _fb?.Deallocate();
+                _fb = new SurfaceFramebuffer(width, height);
+            }
+            _fb.SetDrawable(drawable);
+            return _fb;
+        }
+    }
+}

+ 1 - 208
src/Gtk/Avalonia.Gtk/Input/GtkKeyboardDevice.cs

@@ -8,218 +8,11 @@ using System.Reflection;
 using System.Text;
 using System.Text;
 using Avalonia.Input;
 using Avalonia.Input;
 
 
+
 namespace Avalonia.Gtk
 namespace Avalonia.Gtk
 {
 {
     public class GtkKeyboardDevice : KeyboardDevice
     public class GtkKeyboardDevice : KeyboardDevice
     {
     {
-        private static readonly Dictionary<Gdk.Key, Key> KeyDic = new Dictionary<Gdk.Key, Key>
-        {
-            { Gdk.Key.Cancel, Key.Cancel },
-            { Gdk.Key.BackSpace, Key.Back },
-            { Gdk.Key.Tab, Key.Tab },
-            { Gdk.Key.Linefeed, Key.LineFeed },
-            { Gdk.Key.Clear, Key.Clear },
-            { Gdk.Key.Return, Key.Return },
-            { Gdk.Key.Pause, Key.Pause },
-            //{ Gdk.Key.?, Key.CapsLock }
-            //{ Gdk.Key.?, Key.HangulMode }
-            //{ Gdk.Key.?, Key.JunjaMode }
-            //{ Gdk.Key.?, Key.FinalMode }
-            //{ Gdk.Key.?, Key.KanjiMode }
-            { Gdk.Key.Escape, Key.Escape },
-            //{ Gdk.Key.?, Key.ImeConvert }
-            //{ Gdk.Key.?, Key.ImeNonConvert }
-            //{ Gdk.Key.?, Key.ImeAccept }
-            //{ Gdk.Key.?, Key.ImeModeChange }
-            { Gdk.Key.space, Key.Space },
-            { Gdk.Key.Prior, Key.Prior },
-            //{ Gdk.Key.?, Key.PageDown }
-            { Gdk.Key.End, Key.End },
-            { Gdk.Key.Home, Key.Home },
-            { Gdk.Key.Left, Key.Left },
-            { Gdk.Key.Up, Key.Up },
-            { Gdk.Key.Right, Key.Right },
-            { Gdk.Key.Down, Key.Down },
-            { Gdk.Key.Select, Key.Select },
-            { Gdk.Key.Print, Key.Print },
-            { Gdk.Key.Execute, Key.Execute },
-            //{ Gdk.Key.?, Key.Snapshot }
-            { Gdk.Key.Insert, Key.Insert },
-            { Gdk.Key.Delete, Key.Delete },
-            { Gdk.Key.Help, Key.Help },
-            //{ Gdk.Key.?, Key.D0 }
-            //{ Gdk.Key.?, Key.D1 }
-            //{ Gdk.Key.?, Key.D2 }
-            //{ Gdk.Key.?, Key.D3 }
-            //{ Gdk.Key.?, Key.D4 }
-            //{ Gdk.Key.?, Key.D5 }
-            //{ Gdk.Key.?, Key.D6 }
-            //{ Gdk.Key.?, Key.D7 }
-            //{ Gdk.Key.?, Key.D8 }
-            //{ Gdk.Key.?, Key.D9 }
-            { Gdk.Key.A, Key.A },
-            { Gdk.Key.B, Key.B },
-            { Gdk.Key.C, Key.C },
-            { Gdk.Key.D, Key.D },
-            { Gdk.Key.E, Key.E },
-            { Gdk.Key.F, Key.F },
-            { Gdk.Key.G, Key.G },
-            { Gdk.Key.H, Key.H },
-            { Gdk.Key.I, Key.I },
-            { Gdk.Key.J, Key.J },
-            { Gdk.Key.K, Key.K },
-            { Gdk.Key.L, Key.L },
-            { Gdk.Key.M, Key.M },
-            { Gdk.Key.N, Key.N },
-            { Gdk.Key.O, Key.O },
-            { Gdk.Key.P, Key.P },
-            { Gdk.Key.Q, Key.Q },
-            { Gdk.Key.R, Key.R },
-            { Gdk.Key.S, Key.S },
-            { Gdk.Key.T, Key.T },
-            { Gdk.Key.U, Key.U },
-            { Gdk.Key.V, Key.V },
-            { Gdk.Key.W, Key.W },
-            { Gdk.Key.X, Key.X },
-            { Gdk.Key.Y, Key.Y },
-            { Gdk.Key.Z, Key.Z },
-            { Gdk.Key.a, Key.A },
-            { Gdk.Key.b, Key.B },
-            { Gdk.Key.c, Key.C },
-            { Gdk.Key.d, Key.D },
-            { Gdk.Key.e, Key.E },
-            { Gdk.Key.f, Key.F },
-            { Gdk.Key.g, Key.G },
-            { Gdk.Key.h, Key.H },
-            { Gdk.Key.i, Key.I },
-            { Gdk.Key.j, Key.J },
-            { Gdk.Key.k, Key.K },
-            { Gdk.Key.l, Key.L },
-            { Gdk.Key.m, Key.M },
-            { Gdk.Key.n, Key.N },
-            { Gdk.Key.o, Key.O },
-            { Gdk.Key.p, Key.P },
-            { Gdk.Key.q, Key.Q },
-            { Gdk.Key.r, Key.R },
-            { Gdk.Key.s, Key.S },
-            { Gdk.Key.t, Key.T },
-            { Gdk.Key.u, Key.U },
-            { Gdk.Key.v, Key.V },
-            { Gdk.Key.w, Key.W },
-            { Gdk.Key.x, Key.X },
-            { Gdk.Key.y, Key.Y },
-            { Gdk.Key.z, Key.Z },
-            //{ Gdk.Key.?, Key.LWin }
-            //{ Gdk.Key.?, Key.RWin }
-            //{ Gdk.Key.?, Key.Apps }
-            //{ Gdk.Key.?, Key.Sleep }
-            //{ Gdk.Key.?, Key.NumPad0 }
-            //{ Gdk.Key.?, Key.NumPad1 }
-            //{ Gdk.Key.?, Key.NumPad2 }
-            //{ Gdk.Key.?, Key.NumPad3 }
-            //{ Gdk.Key.?, Key.NumPad4 }
-            //{ Gdk.Key.?, Key.NumPad5 }
-            //{ Gdk.Key.?, Key.NumPad6 }
-            //{ Gdk.Key.?, Key.NumPad7 }
-            //{ Gdk.Key.?, Key.NumPad8 }
-            //{ Gdk.Key.?, Key.NumPad9 }
-            { Gdk.Key.multiply, Key.Multiply },
-            //{ Gdk.Key.?, Key.Add }
-            //{ Gdk.Key.?, Key.Separator }
-            //{ Gdk.Key.?, Key.Subtract }
-            //{ Gdk.Key.?, Key.Decimal }
-            //{ Gdk.Key.?, Key.Divide }
-            { Gdk.Key.F1, Key.F1 },
-            { Gdk.Key.F2, Key.F2 },
-            { Gdk.Key.F3, Key.F3 },
-            { Gdk.Key.F4, Key.F4 },
-            { Gdk.Key.F5, Key.F5 },
-            { Gdk.Key.F6, Key.F6 },
-            { Gdk.Key.F7, Key.F7 },
-            { Gdk.Key.F8, Key.F8 },
-            { Gdk.Key.F9, Key.F9 },
-            { Gdk.Key.F10, Key.F10 },
-            { Gdk.Key.F11, Key.F11 },
-            { Gdk.Key.F12, Key.F12 },
-            { Gdk.Key.L3, Key.F13 },
-            { Gdk.Key.F14, Key.F14 },
-            { Gdk.Key.L5, Key.F15 },
-            { Gdk.Key.F16, Key.F16 },
-            { Gdk.Key.F17, Key.F17 },
-            { Gdk.Key.L8, Key.F18 },
-            { Gdk.Key.L9, Key.F19 },
-            { Gdk.Key.L10, Key.F20 },
-            { Gdk.Key.R1, Key.F21 },
-            { Gdk.Key.R2, Key.F22 },
-            { Gdk.Key.F23, Key.F23 },
-            { Gdk.Key.R4, Key.F24 },
-            //{ Gdk.Key.?, Key.NumLock }
-            //{ Gdk.Key.?, Key.Scroll }
-            //{ Gdk.Key.?, Key.LeftShift }
-            //{ Gdk.Key.?, Key.RightShift }
-            //{ Gdk.Key.?, Key.LeftCtrl }
-            //{ Gdk.Key.?, Key.RightCtrl }
-            //{ Gdk.Key.?, Key.LeftAlt }
-            //{ Gdk.Key.?, Key.RightAlt }
-            //{ Gdk.Key.?, Key.BrowserBack }
-            //{ Gdk.Key.?, Key.BrowserForward }
-            //{ Gdk.Key.?, Key.BrowserRefresh }
-            //{ Gdk.Key.?, Key.BrowserStop }
-            //{ Gdk.Key.?, Key.BrowserSearch }
-            //{ Gdk.Key.?, Key.BrowserFavorites }
-            //{ Gdk.Key.?, Key.BrowserHome }
-            //{ Gdk.Key.?, Key.VolumeMute }
-            //{ Gdk.Key.?, Key.VolumeDown }
-            //{ Gdk.Key.?, Key.VolumeUp }
-            //{ Gdk.Key.?, Key.MediaNextTrack }
-            //{ Gdk.Key.?, Key.MediaPreviousTrack }
-            //{ Gdk.Key.?, Key.MediaStop }
-            //{ Gdk.Key.?, Key.MediaPlayPause }
-            //{ Gdk.Key.?, Key.LaunchMail }
-            //{ Gdk.Key.?, Key.SelectMedia }
-            //{ Gdk.Key.?, Key.LaunchApplication1 }
-            //{ Gdk.Key.?, Key.LaunchApplication2 }
-            //{ Gdk.Key.?, Key.OemSemicolon }
-            //{ Gdk.Key.?, Key.OemPlus }
-            //{ Gdk.Key.?, Key.OemComma }
-            //{ Gdk.Key.?, Key.OemMinus }
-            //{ Gdk.Key.?, Key.OemPeriod }
-            //{ Gdk.Key.?, Key.Oem2 }
-            //{ Gdk.Key.?, Key.OemTilde }
-            //{ Gdk.Key.?, Key.AbntC1 }
-            //{ Gdk.Key.?, Key.AbntC2 }
-            //{ Gdk.Key.?, Key.Oem4 }
-            //{ Gdk.Key.?, Key.OemPipe }
-            //{ Gdk.Key.?, Key.OemCloseBrackets }
-            //{ Gdk.Key.?, Key.Oem7 }
-            //{ Gdk.Key.?, Key.Oem8 }
-            //{ Gdk.Key.?, Key.Oem102 }
-            //{ Gdk.Key.?, Key.ImeProcessed }
-            //{ Gdk.Key.?, Key.System }
-            //{ Gdk.Key.?, Key.OemAttn }
-            //{ Gdk.Key.?, Key.OemFinish }
-            //{ Gdk.Key.?, Key.DbeHiragana }
-            //{ Gdk.Key.?, Key.OemAuto }
-            //{ Gdk.Key.?, Key.DbeDbcsChar }
-            //{ Gdk.Key.?, Key.OemBackTab }
-            //{ Gdk.Key.?, Key.Attn }
-            //{ Gdk.Key.?, Key.DbeEnterWordRegisterMode }
-            //{ Gdk.Key.?, Key.DbeEnterImeConfigureMode }
-            //{ Gdk.Key.?, Key.EraseEof }
-            //{ Gdk.Key.?, Key.Play }
-            //{ Gdk.Key.?, Key.Zoom }
-            //{ Gdk.Key.?, Key.NoName }
-            //{ Gdk.Key.?, Key.DbeEnterDialogConversionMode }
-            //{ Gdk.Key.?, Key.OemClear }
-            //{ Gdk.Key.?, Key.DeadCharProcessed }
-        };
-
         public new static GtkKeyboardDevice Instance { get; } = new GtkKeyboardDevice();
         public new static GtkKeyboardDevice Instance { get; } = new GtkKeyboardDevice();
-
-        public static Key ConvertKey(Gdk.Key key)
-        {
-            Key result;
-            return KeyDic.TryGetValue(key, out result) ? result : Key.None;
-        }
     }
     }
 }
 }

+ 224 - 0
src/Gtk/Avalonia.Gtk/KeyTransform.cs

@@ -0,0 +1,224 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Input;
+#if GTK3_PINVOKE
+using Avalonia.Gtk3;
+#else
+using GdkKey = Gdk.Key;
+#endif
+namespace Avalonia.Gtk.Common
+{
+    static class KeyTransform
+    {
+        private static readonly Dictionary<GdkKey, Key> KeyDic = new Dictionary<GdkKey, Key>
+        {
+            { GdkKey.Cancel, Key.Cancel },
+            { GdkKey.BackSpace, Key.Back },
+            { GdkKey.Tab, Key.Tab },
+            { GdkKey.Linefeed, Key.LineFeed },
+            { GdkKey.Clear, Key.Clear },
+            { GdkKey.Return, Key.Return },
+            { GdkKey.Pause, Key.Pause },
+            //{ GdkKey.?, Key.CapsLock }
+            //{ GdkKey.?, Key.HangulMode }
+            //{ GdkKey.?, Key.JunjaMode }
+            //{ GdkKey.?, Key.FinalMode }
+            //{ GdkKey.?, Key.KanjiMode }
+            { GdkKey.Escape, Key.Escape },
+            //{ GdkKey.?, Key.ImeConvert }
+            //{ GdkKey.?, Key.ImeNonConvert }
+            //{ GdkKey.?, Key.ImeAccept }
+            //{ GdkKey.?, Key.ImeModeChange }
+            { GdkKey.space, Key.Space },
+            { GdkKey.Prior, Key.Prior },
+            //{ GdkKey.?, Key.PageDown }
+            { GdkKey.End, Key.End },
+            { GdkKey.Home, Key.Home },
+            { GdkKey.Left, Key.Left },
+            { GdkKey.Up, Key.Up },
+            { GdkKey.Right, Key.Right },
+            { GdkKey.Down, Key.Down },
+            { GdkKey.Select, Key.Select },
+            { GdkKey.Print, Key.Print },
+            { GdkKey.Execute, Key.Execute },
+            //{ GdkKey.?, Key.Snapshot }
+            { GdkKey.Insert, Key.Insert },
+            { GdkKey.Delete, Key.Delete },
+            { GdkKey.Help, Key.Help },
+            //{ GdkKey.?, Key.D0 }
+            //{ GdkKey.?, Key.D1 }
+            //{ GdkKey.?, Key.D2 }
+            //{ GdkKey.?, Key.D3 }
+            //{ GdkKey.?, Key.D4 }
+            //{ GdkKey.?, Key.D5 }
+            //{ GdkKey.?, Key.D6 }
+            //{ GdkKey.?, Key.D7 }
+            //{ GdkKey.?, Key.D8 }
+            //{ GdkKey.?, Key.D9 }
+            { GdkKey.A, Key.A },
+            { GdkKey.B, Key.B },
+            { GdkKey.C, Key.C },
+            { GdkKey.D, Key.D },
+            { GdkKey.E, Key.E },
+            { GdkKey.F, Key.F },
+            { GdkKey.G, Key.G },
+            { GdkKey.H, Key.H },
+            { GdkKey.I, Key.I },
+            { GdkKey.J, Key.J },
+            { GdkKey.K, Key.K },
+            { GdkKey.L, Key.L },
+            { GdkKey.M, Key.M },
+            { GdkKey.N, Key.N },
+            { GdkKey.O, Key.O },
+            { GdkKey.P, Key.P },
+            { GdkKey.Q, Key.Q },
+            { GdkKey.R, Key.R },
+            { GdkKey.S, Key.S },
+            { GdkKey.T, Key.T },
+            { GdkKey.U, Key.U },
+            { GdkKey.V, Key.V },
+            { GdkKey.W, Key.W },
+            { GdkKey.X, Key.X },
+            { GdkKey.Y, Key.Y },
+            { GdkKey.Z, Key.Z },
+            { GdkKey.a, Key.A },
+            { GdkKey.b, Key.B },
+            { GdkKey.c, Key.C },
+            { GdkKey.d, Key.D },
+            { GdkKey.e, Key.E },
+            { GdkKey.f, Key.F },
+            { GdkKey.g, Key.G },
+            { GdkKey.h, Key.H },
+            { GdkKey.i, Key.I },
+            { GdkKey.j, Key.J },
+            { GdkKey.k, Key.K },
+            { GdkKey.l, Key.L },
+            { GdkKey.m, Key.M },
+            { GdkKey.n, Key.N },
+            { GdkKey.o, Key.O },
+            { GdkKey.p, Key.P },
+            { GdkKey.q, Key.Q },
+            { GdkKey.r, Key.R },
+            { GdkKey.s, Key.S },
+            { GdkKey.t, Key.T },
+            { GdkKey.u, Key.U },
+            { GdkKey.v, Key.V },
+            { GdkKey.w, Key.W },
+            { GdkKey.x, Key.X },
+            { GdkKey.y, Key.Y },
+            { GdkKey.z, Key.Z },
+            //{ GdkKey.?, Key.LWin }
+            //{ GdkKey.?, Key.RWin }
+            //{ GdkKey.?, Key.Apps }
+            //{ GdkKey.?, Key.Sleep }
+            //{ GdkKey.?, Key.NumPad0 }
+            //{ GdkKey.?, Key.NumPad1 }
+            //{ GdkKey.?, Key.NumPad2 }
+            //{ GdkKey.?, Key.NumPad3 }
+            //{ GdkKey.?, Key.NumPad4 }
+            //{ GdkKey.?, Key.NumPad5 }
+            //{ GdkKey.?, Key.NumPad6 }
+            //{ GdkKey.?, Key.NumPad7 }
+            //{ GdkKey.?, Key.NumPad8 }
+            //{ GdkKey.?, Key.NumPad9 }
+            { GdkKey.multiply, Key.Multiply },
+            //{ GdkKey.?, Key.Add }
+            //{ GdkKey.?, Key.Separator }
+            //{ GdkKey.?, Key.Subtract }
+            //{ GdkKey.?, Key.Decimal }
+            //{ GdkKey.?, Key.Divide }
+            { GdkKey.F1, Key.F1 },
+            { GdkKey.F2, Key.F2 },
+            { GdkKey.F3, Key.F3 },
+            { GdkKey.F4, Key.F4 },
+            { GdkKey.F5, Key.F5 },
+            { GdkKey.F6, Key.F6 },
+            { GdkKey.F7, Key.F7 },
+            { GdkKey.F8, Key.F8 },
+            { GdkKey.F9, Key.F9 },
+            { GdkKey.F10, Key.F10 },
+            { GdkKey.F11, Key.F11 },
+            { GdkKey.F12, Key.F12 },
+            { GdkKey.L3, Key.F13 },
+            { GdkKey.F14, Key.F14 },
+            { GdkKey.L5, Key.F15 },
+            { GdkKey.F16, Key.F16 },
+            { GdkKey.F17, Key.F17 },
+            { GdkKey.L8, Key.F18 },
+            { GdkKey.L9, Key.F19 },
+            { GdkKey.L10, Key.F20 },
+            { GdkKey.R1, Key.F21 },
+            { GdkKey.R2, Key.F22 },
+            { GdkKey.F23, Key.F23 },
+            { GdkKey.R4, Key.F24 },
+            //{ GdkKey.?, Key.NumLock }
+            //{ GdkKey.?, Key.Scroll }
+            //{ GdkKey.?, Key.LeftShift }
+            //{ GdkKey.?, Key.RightShift }
+            //{ GdkKey.?, Key.LeftCtrl }
+            //{ GdkKey.?, Key.RightCtrl }
+            //{ GdkKey.?, Key.LeftAlt }
+            //{ GdkKey.?, Key.RightAlt }
+            //{ GdkKey.?, Key.BrowserBack }
+            //{ GdkKey.?, Key.BrowserForward }
+            //{ GdkKey.?, Key.BrowserRefresh }
+            //{ GdkKey.?, Key.BrowserStop }
+            //{ GdkKey.?, Key.BrowserSearch }
+            //{ GdkKey.?, Key.BrowserFavorites }
+            //{ GdkKey.?, Key.BrowserHome }
+            //{ GdkKey.?, Key.VolumeMute }
+            //{ GdkKey.?, Key.VolumeDown }
+            //{ GdkKey.?, Key.VolumeUp }
+            //{ GdkKey.?, Key.MediaNextTrack }
+            //{ GdkKey.?, Key.MediaPreviousTrack }
+            //{ GdkKey.?, Key.MediaStop }
+            //{ GdkKey.?, Key.MediaPlayPause }
+            //{ GdkKey.?, Key.LaunchMail }
+            //{ GdkKey.?, Key.SelectMedia }
+            //{ GdkKey.?, Key.LaunchApplication1 }
+            //{ GdkKey.?, Key.LaunchApplication2 }
+            //{ GdkKey.?, Key.OemSemicolon }
+            //{ GdkKey.?, Key.OemPlus }
+            //{ GdkKey.?, Key.OemComma }
+            //{ GdkKey.?, Key.OemMinus }
+            //{ GdkKey.?, Key.OemPeriod }
+            //{ GdkKey.?, Key.Oem2 }
+            //{ GdkKey.?, Key.OemTilde }
+            //{ GdkKey.?, Key.AbntC1 }
+            //{ GdkKey.?, Key.AbntC2 }
+            //{ GdkKey.?, Key.Oem4 }
+            //{ GdkKey.?, Key.OemPipe }
+            //{ GdkKey.?, Key.OemCloseBrackets }
+            //{ GdkKey.?, Key.Oem7 }
+            //{ GdkKey.?, Key.Oem8 }
+            //{ GdkKey.?, Key.Oem102 }
+            //{ GdkKey.?, Key.ImeProcessed }
+            //{ GdkKey.?, Key.System }
+            //{ GdkKey.?, Key.OemAttn }
+            //{ GdkKey.?, Key.OemFinish }
+            //{ GdkKey.?, Key.DbeHiragana }
+            //{ GdkKey.?, Key.OemAuto }
+            //{ GdkKey.?, Key.DbeDbcsChar }
+            //{ GdkKey.?, Key.OemBackTab }
+            //{ GdkKey.?, Key.Attn }
+            //{ GdkKey.?, Key.DbeEnterWordRegisterMode }
+            //{ GdkKey.?, Key.DbeEnterImeConfigureMode }
+            //{ GdkKey.?, Key.EraseEof }
+            //{ GdkKey.?, Key.Play }
+            //{ GdkKey.?, Key.Zoom }
+            //{ GdkKey.?, Key.NoName }
+            //{ GdkKey.?, Key.DbeEnterDialogConversionMode }
+            //{ GdkKey.?, Key.OemClear }
+            //{ GdkKey.?, Key.DeadCharProcessed }
+        };
+
+        public static Key ConvertKey(GdkKey key)
+        {
+            Key result;
+            return KeyDic.TryGetValue(key, out result) ? result : Key.None;
+        }
+    }
+}

+ 55 - 0
src/Gtk/Avalonia.Gtk/SurfaceFramebuffer.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls.Platform.Surfaces;
+using Avalonia.Platform;
+using Cairo;
+using Gdk;
+
+namespace Avalonia.Gtk
+{
+    class SurfaceFramebuffer : ILockedFramebuffer
+    {
+        private Drawable _drawable;
+        private ImageSurface _surface;
+
+        public SurfaceFramebuffer(int width, int height)
+        {
+            _surface = new ImageSurface(Cairo.Format.RGB24, width, height);
+        }
+
+        public void SetDrawable(Drawable drawable)
+        {
+            _drawable = drawable;
+            _surface.Flush();
+        }
+
+        public void Deallocate()
+        {
+            _surface.Dispose();
+            _surface = null;
+        }
+
+        public void Dispose()
+        {
+            using (var ctx = CairoHelper.Create(_drawable))
+            {
+                _surface.MarkDirty();
+                ctx.SetSourceSurface(_surface, 0, 0);
+                ctx.Paint();
+            }
+            _drawable = null;
+        }
+
+        public IntPtr Address => _surface.DataPtr;
+        public int Width => _surface.Width;
+        public int Height => _surface.Height;
+        public int RowBytes => _surface.Stride;
+        //TODO: Proper DPI detect
+        public Size Dpi => new Size(96, 96);
+        public PixelFormat Format => PixelFormat.Bgra8888;
+    }
+}
+

+ 2 - 2
src/Gtk/Avalonia.Gtk/SystemDialogImpl.cs

@@ -15,7 +15,7 @@ namespace Avalonia.Gtk
         public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
         public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
         {
         {
             var tcs = new TaskCompletionSource<string[]>();
             var tcs = new TaskCompletionSource<string[]>();
-            var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((WindowImplBase)parent).Widget.Toplevel as Window, 
+            var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((WindowImplBase)parent)?.Widget.Toplevel as Window, 
                 dialog is OpenFileDialog
                 dialog is OpenFileDialog
                     ? FileChooserAction.Open
                     ? FileChooserAction.Open
                     : FileChooserAction.Save,
                     : FileChooserAction.Save,
@@ -57,7 +57,7 @@ namespace Avalonia.Gtk
         public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
         public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
         {
         {
             var tcs = new TaskCompletionSource<string>();
             var tcs = new TaskCompletionSource<string>();
-            var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((WindowImplBase)parent).Widget.Toplevel as Window, 
+            var dlg = new global::Gtk.FileChooserDialog(dialog.Title, ((WindowImplBase)parent)?.Widget.Toplevel as Window, 
                 FileChooserAction.SelectFolder,
                 FileChooserAction.SelectFolder,
                 "Cancel", ResponseType.Cancel,
                 "Cancel", ResponseType.Cancel,
                 "Select Folder", ResponseType.Accept)
                 "Select Folder", ResponseType.Accept)

+ 1 - 1
src/Gtk/Avalonia.Gtk/WindowImpl.cs

@@ -10,7 +10,7 @@ namespace Avalonia.Gtk
     {
     {
         private Gtk.Window _window;
         private Gtk.Window _window;
         private Gtk.Window Window => _window ?? (_window = (Gtk.Window) Widget);
         private Gtk.Window Window => _window ?? (_window = (Gtk.Window) Widget);
-		
+        
         public WindowImpl(Gtk.WindowType type) : base(new PlatformHandleAwareWindow(type))
         public WindowImpl(Gtk.WindowType type) : base(new PlatformHandleAwareWindow(type))
         {
         {
             Init();
             Init();

+ 21 - 14
src/Gtk/Avalonia.Gtk/WindowImplBase.cs

@@ -2,16 +2,14 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 
 using System;
 using System;
-using System.Reactive.Disposables;
-using System.Runtime.InteropServices;
-using Gdk;
-using Avalonia.Controls;
+using System.Collections.Generic;
+using Avalonia.Input;
 using Avalonia.Input.Raw;
 using Avalonia.Input.Raw;
 using Avalonia.Platform;
 using Avalonia.Platform;
-using Avalonia.Input;
-using Avalonia.Threading;
+using Gdk;
 using Action = System.Action;
 using Action = System.Action;
 using WindowEdge = Avalonia.Controls.WindowEdge;
 using WindowEdge = Avalonia.Controls.WindowEdge;
+using GLib;
 
 
 namespace Avalonia.Gtk
 namespace Avalonia.Gtk
 {
 {
@@ -21,8 +19,7 @@ namespace Avalonia.Gtk
     {
     {
         private IInputRoot _inputRoot;
         private IInputRoot _inputRoot;
         protected Gtk.Widget _window;
         protected Gtk.Widget _window;
-        public Gtk.Widget Widget => _window;
-
+        private FramebufferManager _framebuffer;
 
 
         private Gtk.IMContext _imContext;
         private Gtk.IMContext _imContext;
 
 
@@ -33,6 +30,7 @@ namespace Avalonia.Gtk
         protected WindowImplBase(Gtk.Widget window)
         protected WindowImplBase(Gtk.Widget window)
         {
         {
             _window = window;
             _window = window;
+            _framebuffer = new FramebufferManager(this);
             Init();
             Init();
         }
         }
 
 
@@ -54,10 +52,13 @@ namespace Avalonia.Gtk
             _window.KeyReleaseEvent += OnKeyReleaseEvent;
             _window.KeyReleaseEvent += OnKeyReleaseEvent;
             _window.ExposeEvent += OnExposeEvent;
             _window.ExposeEvent += OnExposeEvent;
             _window.MotionNotifyEvent += OnMotionNotifyEvent;
             _window.MotionNotifyEvent += OnMotionNotifyEvent;
+
             
             
         }
         }
 
 
         public IPlatformHandle Handle { get; private set; }
         public IPlatformHandle Handle { get; private set; }
+        public Gtk.Widget Widget => _window;
+        public Gdk.Drawable CurrentDrawable { get; private set; }
 
 
         void OnRealized (object sender, EventArgs eventArgs)
         void OnRealized (object sender, EventArgs eventArgs)
         {
         {
@@ -128,6 +129,13 @@ namespace Avalonia.Gtk
 
 
         public Action<double> ScalingChanged { get; set; }
         public Action<double> ScalingChanged { get; set; }
 
 
+        public IEnumerable<object> Surfaces => new object[]
+        {
+            Handle,
+            new Func<Gdk.Drawable>(() => CurrentDrawable),
+            _framebuffer
+        };
+
         public IPopupImpl CreatePopup()
         public IPopupImpl CreatePopup()
         {
         {
             return new PopupImpl();
             return new PopupImpl();
@@ -261,10 +269,11 @@ namespace Avalonia.Gtk
                 GtkKeyboardDevice.Instance,
                 GtkKeyboardDevice.Instance,
                 evnt.Time,
                 evnt.Time,
                 evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
                 evnt.Type == EventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
-                GtkKeyboardDevice.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
+                Common.KeyTransform.ConvertKey(evnt.Key), GetModifierKeys(evnt.State));
             Input(e);
             Input(e);
         }
         }
 
 
+		[ConnectBefore]
         void OnKeyPressEvent(object o, Gtk.KeyPressEventArgs args)
         void OnKeyPressEvent(object o, Gtk.KeyPressEventArgs args)
         {
         {
             args.RetVal = true;
             args.RetVal = true;
@@ -284,7 +293,9 @@ namespace Avalonia.Gtk
 
 
         void OnExposeEvent(object o, Gtk.ExposeEventArgs args)
         void OnExposeEvent(object o, Gtk.ExposeEventArgs args)
         {
         {
+            CurrentDrawable = args.Event.Window;
             Paint(args.Event.Area.ToAvalonia());
             Paint(args.Event.Area.ToAvalonia());
+            CurrentDrawable = null;
             args.RetVal = true;
             args.RetVal = true;
         }
         }
 
 
@@ -305,13 +316,9 @@ namespace Avalonia.Gtk
             args.RetVal = true;
             args.RetVal = true;
         }
         }
 
 
-        public void SetCoverTaskbarWhenMaximized(bool enable)
-        {
-            // No action neccesary on Gtk.
-        }
-
         public void Dispose()
         public void Dispose()
         {
         {
+            _framebuffer.Dispose();
             _window.Hide();
             _window.Hide();
             _window.Dispose();
             _window.Dispose();
             _window = null;
             _window = null;

+ 1 - 0
src/Gtk/Avalonia.Gtk3/.gitignore

@@ -0,0 +1 @@
+project.lock.json

+ 103 - 0
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Avalonia.Gtk3</RootNamespace>
+    <AssemblyName>Avalonia.Gtk3</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <TargetFrameworkVersion>v5.0</TargetFrameworkVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;GTK3_PINVOKE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;GTK3_PINVOKE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .NET Framework is automatically included -->
+    <None Include="project.json" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Avalonia.Gtk\KeyTransform.cs">
+      <Link>KeyTransform.cs</Link>
+    </Compile>
+    <Compile Include="Interop\CairoSurface.cs" />
+    <Compile Include="ClipboardImpl.cs" />
+    <Compile Include="CursorFactory.cs" />
+    <Compile Include="FramebufferManager.cs" />
+    <Compile Include="GdkCursor.cs" />
+    <Compile Include="GdkKey.cs" />
+    <Compile Include="Gtk3Platform.cs" />
+    <Compile Include="Interop\GException.cs" />
+    <Compile Include="Interop\GObject.cs" />
+    <Compile Include="Interop\ICustomGtk3NativeLibraryResolver.cs" />
+    <Compile Include="Interop\DynLoader.cs" />
+    <Compile Include="Interop\GlibTimeout.cs" />
+    <Compile Include="Interop\Native.cs" />
+    <Compile Include="Interop\NativeException.cs" />
+    <Compile Include="Interop\Pixbuf.cs" />
+    <Compile Include="Interop\Resolver.cs" />
+    <Compile Include="Interop\Signal.cs" />
+    <Compile Include="ImageSurfaceFramebuffer.cs" />
+    <Compile Include="PlatformIconLoader.cs" />
+    <Compile Include="PopupImpl.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="SystemDialogs.cs" />
+    <Compile Include="TopLevelImpl.cs" />
+    <Compile Include="Interop\Utf8Buffer.cs" />
+    <Compile Include="WindowImpl.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj">
+      <Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
+      <Name>Avalonia.Base</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.Controls\Avalonia.Controls.csproj">
+      <Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project>
+      <Name>Avalonia.Controls</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.Input\Avalonia.Input.csproj">
+      <Project>{62024B2D-53EB-4638-B26B-85EEAA54866E}</Project>
+      <Name>Avalonia.Input</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.Interactivity\Avalonia.Interactivity.csproj">
+      <Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
+      <Name>Avalonia.Interactivity</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\Avalonia.Visuals\Avalonia.Visuals.csproj">
+      <Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project>
+      <Name>Avalonia.SceneGraph</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 5 - 0
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.v3.ncrunchproject

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

+ 53 - 0
src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs

@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input.Platform;
+
+namespace Avalonia.Gtk3
+{
+    class ClipboardImpl : IClipboard
+    {
+
+        IntPtr GetClipboard() => Native.GtkClipboardGetForDisplay(Native.GdkGetDefaultDisplay(), IntPtr.Zero);
+
+        static void OnText(IntPtr clipboard, IntPtr utf8string, IntPtr userdata)
+        {
+            var handle = GCHandle.FromIntPtr(userdata);
+
+            ((TaskCompletionSource<string>) handle.Target)
+                .TrySetResult(Utf8Buffer.StringFromPtr(utf8string));
+            handle.Free();
+        }
+
+        private static readonly Native.D.GtkClipboardTextReceivedFunc OnTextDelegate = OnText;
+
+        static ClipboardImpl()
+        {
+            GCHandle.Alloc(OnTextDelegate);
+        }
+
+        public Task<string> GetTextAsync()
+        {
+            var tcs = new TaskCompletionSource<string>();
+            Native.GtkClipboardRequestText(GetClipboard(), OnTextDelegate, GCHandle.ToIntPtr(GCHandle.Alloc(tcs)));
+            return tcs.Task;
+        }
+
+        public Task SetTextAsync(string text)
+        {
+            using (var buf = new Utf8Buffer(text))
+                Native.GtkClipboardSetText(GetClipboard(), buf, buf.ByteLen);
+            return Task.FromResult(0);
+        }
+
+        public Task ClearAsync()
+        {
+            Native.GtkClipboardRequestClear(GetClipboard());
+            return Task.FromResult(0);
+        }
+    }
+}

+ 79 - 0
src/Gtk/Avalonia.Gtk3/CursorFactory.cs

@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Platform;
+using CursorType = Avalonia.Gtk3.GdkCursorType;
+namespace Avalonia.Gtk3
+{
+    class CursorFactory :  IStandardCursorFactory
+    {
+        private static readonly Dictionary<StandardCursorType, object> CursorTypeMapping = new Dictionary
+    <StandardCursorType, object>
+        {
+            {StandardCursorType.AppStarting, CursorType.Watch},
+            {StandardCursorType.Arrow, CursorType.LeftPtr},
+            {StandardCursorType.Cross, CursorType.Cross},
+            {StandardCursorType.Hand, CursorType.Hand1},
+            {StandardCursorType.Ibeam, CursorType.Xterm},
+            {StandardCursorType.No, "gtk-cancel"},
+            {StandardCursorType.SizeAll, CursorType.Sizing},
+            //{ StandardCursorType.SizeNorthEastSouthWest, 32643 },
+            {StandardCursorType.SizeNorthSouth, CursorType.SbVDoubleArrow},
+            //{ StandardCursorType.SizeNorthWestSouthEast, 32642 },
+            {StandardCursorType.SizeWestEast, CursorType.SbHDoubleArrow},
+            {StandardCursorType.UpArrow, CursorType.BasedArrowUp},
+            {StandardCursorType.Wait, CursorType.Watch},
+            {StandardCursorType.Help, "gtk-help"},
+            {StandardCursorType.TopSide, CursorType.TopSide},
+            {StandardCursorType.BottomSize, CursorType.BottomSide},
+            {StandardCursorType.LeftSide, CursorType.LeftSide},
+            {StandardCursorType.RightSide, CursorType.RightSide},
+            {StandardCursorType.TopLeftCorner, CursorType.TopLeftCorner},
+            {StandardCursorType.TopRightCorner, CursorType.TopRightCorner},
+            {StandardCursorType.BottomLeftCorner, CursorType.BottomLeftCorner},
+            {StandardCursorType.BottomRightCorner, CursorType.BottomRightCorner}
+        };
+
+        private static readonly Dictionary<StandardCursorType, IPlatformHandle> Cache =
+            new Dictionary<StandardCursorType, IPlatformHandle>();
+
+        private IntPtr GetCursor(object desc)
+        {
+            IntPtr rv;
+            var name = desc as string;
+            if (name != null)
+            {
+                var theme = Native.GtkIconThemeGetDefault();
+                IntPtr icon, error;
+                using (var u = new Utf8Buffer(name))
+                    icon = Native.GtkIconThemeLoadIcon(theme, u, 32, 0, out error);
+                rv = icon == IntPtr.Zero
+                    ? Native.GdkCursorNew(GdkCursorType.XCursor)
+                    : Native.GdkCursorNewFromPixbuf(Native.GdkGetDefaultDisplay(), icon, 0, 0);
+            }
+            else
+            {
+                rv = Native.GdkCursorNew((CursorType)desc);
+            }
+
+            
+            return rv;
+        }
+
+        public IPlatformHandle GetCursor(StandardCursorType cursorType)
+        {
+            IPlatformHandle rv;
+            if (!Cache.TryGetValue(cursorType, out rv))
+            {
+                Cache[cursorType] =
+                    rv =
+                        new PlatformHandle(
+                            GetCursor(CursorTypeMapping[cursorType]),
+                            "GTKCURSOR");
+            }
+
+            return rv;
+        }
+    }
+}

+ 32 - 0
src/Gtk/Avalonia.Gtk3/FramebufferManager.cs

@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls.Platform.Surfaces;
+
+namespace Avalonia.Gtk3
+{
+    class FramebufferManager : IFramebufferPlatformSurface, IDisposable
+    {
+        private readonly TopLevelImpl _window;
+        public FramebufferManager(TopLevelImpl window)
+        {
+            _window = window;
+        }
+
+        public void Dispose()
+        {
+            //
+        }
+
+        public ILockedFramebuffer Lock()
+        {
+            if(_window.CurrentCairoContext == IntPtr.Zero)
+                throw new InvalidOperationException("Window is not in drawing state");
+            var width = (int) _window.ClientSize.Width;
+            var height = (int) _window.ClientSize.Height;
+            return new ImageSurfaceFramebuffer(_window.CurrentCairoContext, width, height);
+        }
+    }
+}

+ 91 - 0
src/Gtk/Avalonia.Gtk3/GdkCursor.cs

@@ -0,0 +1,91 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3
+{
+    enum GdkCursorType
+    {
+        CursorIsPixmap = -1,
+        XCursor = 0,
+        Arrow = 2,
+        BasedArrowDown = 4,
+        BasedArrowUp = 6,
+        Boat = 8,
+        Bogosity = 10,
+        BottomLeftCorner = 12,
+        BottomRightCorner = 14,
+        BottomSide = 16,
+        BottomTee = 18,
+        BoxSpiral = 20,
+        CenterPtr = 22,
+        Circle = 24,
+        Clock = 26,
+        CoffeeMug = 28,
+        Cross = 30,
+        CrossReverse = 32,
+        Crosshair = 34,
+        DiamondCross = 36,
+        Dot = 38,
+        Dotbox = 40,
+        DoubleArrow = 42,
+        DraftLarge = 44,
+        DraftSmall = 46,
+        DrapedBox = 48,
+        Exchange = 50,
+        Fleur = 52,
+        Gobbler = 54,
+        Gumby = 56,
+        Hand1 = 58,
+        Hand2 = 60,
+        Heart = 62,
+        Icon = 64,
+        IronCross = 66,
+        LeftPtr = 68,
+        LeftSide = 70,
+        LeftTee = 72,
+        Leftbutton = 74,
+        LlAngle = 76,
+        LrAngle = 78,
+        Man = 80,
+        Middlebutton = 82,
+        Mouse = 84,
+        Pencil = 86,
+        Pirate = 88,
+        Plus = 90,
+        QuestionArrow = 92,
+        RightPtr = 94,
+        RightSide = 96,
+        RightTee = 98,
+        Rightbutton = 100,
+        RtlLogo = 102,
+        Sailboat = 104,
+        SbDownArrow = 106,
+        SbHDoubleArrow = 108,
+        SbLeftArrow = 110,
+        SbRightArrow = 112,
+        SbUpArrow = 114,
+        SbVDoubleArrow = 116,
+        Shuttle = 118,
+        Sizing = 120,
+        Spider = 122,
+        Spraycan = 124,
+        Star = 126,
+        Target = 128,
+        Tcross = 130,
+        TopLeftArrow = 132,
+        TopLeftCorner = 134,
+        TopRightCorner = 136,
+        TopSide = 138,
+        TopTee = 140,
+        Trek = 142,
+        UlAngle = 144,
+        Umbrella = 146,
+        UrAngle = 148,
+        Watch = 150,
+        Xterm = 152,
+        LastCursor = 153,
+    }
+}

+ 1347 - 0
src/Gtk/Avalonia.Gtk3/GdkKey.cs

@@ -0,0 +1,1347 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3
+{
+    enum GdkKey
+    {
+        space = 32,
+        exclam = 33,
+        quotedbl = 34,
+        numbersign = 35,
+        dollar = 36,
+        percent = 37,
+        ampersand = 38,
+        apostrophe = 39,
+        quoteright = 39,
+        parenleft = 40,
+        parenright = 41,
+        asterisk = 42,
+        plus = 43,
+        comma = 44,
+        minus = 45,
+        period = 46,
+        slash = 47,
+        Key_0 = 48,
+        Key_1 = 49,
+        Key_2 = 50,
+        Key_3 = 51,
+        Key_4 = 52,
+        Key_5 = 53,
+        Key_6 = 54,
+        Key_7 = 55,
+        Key_8 = 56,
+        Key_9 = 57,
+        colon = 58,
+        semicolon = 59,
+        less = 60,
+        equal = 61,
+        greater = 62,
+        question = 63,
+        at = 64,
+        A = 65,
+        B = 66,
+        C = 67,
+        D = 68,
+        E = 69,
+        F = 70,
+        G = 71,
+        H = 72,
+        I = 73,
+        J = 74,
+        K = 75,
+        L = 76,
+        M = 77,
+        N = 78,
+        O = 79,
+        P = 80,
+        Q = 81,
+        R = 82,
+        S = 83,
+        T = 84,
+        U = 85,
+        V = 86,
+        W = 87,
+        X = 88,
+        Y = 89,
+        Z = 90,
+        bracketleft = 91,
+        backslash = 92,
+        bracketright = 93,
+        asciicircum = 94,
+        underscore = 95,
+        grave = 96,
+        quoteleft = 96,
+        a = 97,
+        b = 98,
+        c = 99,
+        d = 100,
+        e = 101,
+        f = 102,
+        g = 103,
+        h = 104,
+        i = 105,
+        j = 106,
+        k = 107,
+        l = 108,
+        m = 109,
+        n = 110,
+        o = 111,
+        p = 112,
+        q = 113,
+        r = 114,
+        s = 115,
+        t = 116,
+        u = 117,
+        v = 118,
+        w = 119,
+        x = 120,
+        y = 121,
+        z = 122,
+        braceleft = 123,
+        bar = 124,
+        braceright = 125,
+        asciitilde = 126,
+        nobreakspace = 160,
+        exclamdown = 161,
+        cent = 162,
+        sterling = 163,
+        currency = 164,
+        yen = 165,
+        brokenbar = 166,
+        section = 167,
+        diaeresis = 168,
+        copyright = 169,
+        ordfeminine = 170,
+        guillemotleft = 171,
+        notsign = 172,
+        hyphen = 173,
+        registered = 174,
+        macron = 175,
+        degree = 176,
+        plusminus = 177,
+        twosuperior = 178,
+        threesuperior = 179,
+        acute = 180,
+        mu = 181,
+        paragraph = 182,
+        periodcentered = 183,
+        cedilla = 184,
+        onesuperior = 185,
+        masculine = 186,
+        guillemotright = 187,
+        onequarter = 188,
+        onehalf = 189,
+        threequarters = 190,
+        questiondown = 191,
+        Agrave = 192,
+        Aacute = 193,
+        Acircumflex = 194,
+        Atilde = 195,
+        Adiaeresis = 196,
+        Aring = 197,
+        AE = 198,
+        Ccedilla = 199,
+        Egrave = 200,
+        Eacute = 201,
+        Ecircumflex = 202,
+        Ediaeresis = 203,
+        Igrave = 204,
+        Iacute = 205,
+        Icircumflex = 206,
+        Idiaeresis = 207,
+        ETH = 208,
+        Eth = 208,
+        Ntilde = 209,
+        Ograve = 210,
+        Oacute = 211,
+        Ocircumflex = 212,
+        Otilde = 213,
+        Odiaeresis = 214,
+        multiply = 215,
+        Ooblique = 216,
+        Ugrave = 217,
+        Uacute = 218,
+        Ucircumflex = 219,
+        Udiaeresis = 220,
+        Yacute = 221,
+        THORN = 222,
+        Thorn = 222,
+        ssharp = 223,
+        agrave = 224,
+        aacute = 225,
+        acircumflex = 226,
+        atilde = 227,
+        adiaeresis = 228,
+        aring = 229,
+        ae = 230,
+        ccedilla = 231,
+        egrave = 232,
+        eacute = 233,
+        ecircumflex = 234,
+        ediaeresis = 235,
+        igrave = 236,
+        iacute = 237,
+        icircumflex = 238,
+        idiaeresis = 239,
+        eth = 240,
+        ntilde = 241,
+        ograve = 242,
+        oacute = 243,
+        ocircumflex = 244,
+        otilde = 245,
+        odiaeresis = 246,
+        division = 247,
+        oslash = 248,
+        ugrave = 249,
+        uacute = 250,
+        ucircumflex = 251,
+        udiaeresis = 252,
+        yacute = 253,
+        thorn = 254,
+        ydiaeresis = 255,
+        Aogonek = 417,
+        breve = 418,
+        Lstroke = 419,
+        Lcaron = 421,
+        Sacute = 422,
+        Scaron = 425,
+        Scedilla = 426,
+        Tcaron = 427,
+        Zacute = 428,
+        Zcaron = 430,
+        Zabovedot = 431,
+        aogonek = 433,
+        ogonek = 434,
+        lstroke = 435,
+        lcaron = 437,
+        sacute = 438,
+        caron = 439,
+        scaron = 441,
+        scedilla = 442,
+        tcaron = 443,
+        zacute = 444,
+        doubleacute = 445,
+        zcaron = 446,
+        zabovedot = 447,
+        Racute = 448,
+        Abreve = 451,
+        Lacute = 453,
+        Cacute = 454,
+        Ccaron = 456,
+        Eogonek = 458,
+        Ecaron = 460,
+        Dcaron = 463,
+        Dstroke = 464,
+        Nacute = 465,
+        Ncaron = 466,
+        Odoubleacute = 469,
+        Rcaron = 472,
+        Uring = 473,
+        Udoubleacute = 475,
+        Tcedilla = 478,
+        racute = 480,
+        abreve = 483,
+        lacute = 485,
+        cacute = 486,
+        ccaron = 488,
+        eogonek = 490,
+        ecaron = 492,
+        dcaron = 495,
+        dstroke = 496,
+        nacute = 497,
+        ncaron = 498,
+        odoubleacute = 501,
+        rcaron = 504,
+        uring = 505,
+        udoubleacute = 507,
+        tcedilla = 510,
+        abovedot = 511,
+        Hstroke = 673,
+        Hcircumflex = 678,
+        Iabovedot = 681,
+        Gbreve = 683,
+        Jcircumflex = 684,
+        hstroke = 689,
+        hcircumflex = 694,
+        idotless = 697,
+        gbreve = 699,
+        jcircumflex = 700,
+        Cabovedot = 709,
+        Ccircumflex = 710,
+        Gabovedot = 725,
+        Gcircumflex = 728,
+        Ubreve = 733,
+        Scircumflex = 734,
+        cabovedot = 741,
+        ccircumflex = 742,
+        gabovedot = 757,
+        gcircumflex = 760,
+        ubreve = 765,
+        scircumflex = 766,
+        kappa = 930,
+        kra = 930,
+        Rcedilla = 931,
+        Itilde = 933,
+        Lcedilla = 934,
+        Emacron = 938,
+        Gcedilla = 939,
+        Tslash = 940,
+        rcedilla = 947,
+        itilde = 949,
+        lcedilla = 950,
+        emacron = 954,
+        gcedilla = 955,
+        tslash = 956,
+        ENG = 957,
+        eng = 959,
+        Amacron = 960,
+        Iogonek = 967,
+        Eabovedot = 972,
+        Imacron = 975,
+        Ncedilla = 977,
+        Omacron = 978,
+        Kcedilla = 979,
+        Uogonek = 985,
+        Utilde = 989,
+        Umacron = 990,
+        amacron = 992,
+        iogonek = 999,
+        eabovedot = 1004,
+        imacron = 1007,
+        ncedilla = 1009,
+        omacron = 1010,
+        kcedilla = 1011,
+        uogonek = 1017,
+        utilde = 1021,
+        umacron = 1022,
+        overline = 1150,
+        kana_fullstop = 1185,
+        kana_openingbracket = 1186,
+        kana_closingbracket = 1187,
+        kana_comma = 1188,
+        kana_conjunctive = 1189,
+        kana_middledot = 1189,
+        kana_WO = 1190,
+        kana_a = 1191,
+        kana_i = 1192,
+        kana_u = 1193,
+        kana_e = 1194,
+        kana_o = 1195,
+        kana_ya = 1196,
+        kana_yu = 1197,
+        kana_yo = 1198,
+        kana_tsu = 1199,
+        kana_tu = 1199,
+        prolongedsound = 1200,
+        kana_A = 1201,
+        kana_I = 1202,
+        kana_U = 1203,
+        kana_E = 1204,
+        kana_O = 1205,
+        kana_KA = 1206,
+        kana_KI = 1207,
+        kana_KU = 1208,
+        kana_KE = 1209,
+        kana_KO = 1210,
+        kana_SA = 1211,
+        kana_SHI = 1212,
+        kana_SU = 1213,
+        kana_SE = 1214,
+        kana_SO = 1215,
+        kana_TA = 1216,
+        kana_CHI = 1217,
+        kana_TI = 1217,
+        kana_TSU = 1218,
+        kana_TU = 1218,
+        kana_TE = 1219,
+        kana_TO = 1220,
+        kana_NA = 1221,
+        kana_NI = 1222,
+        kana_NU = 1223,
+        kana_NE = 1224,
+        kana_NO = 1225,
+        kana_HA = 1226,
+        kana_HI = 1227,
+        kana_FU = 1228,
+        kana_HU = 1228,
+        kana_HE = 1229,
+        kana_HO = 1230,
+        kana_MA = 1231,
+        kana_MI = 1232,
+        kana_MU = 1233,
+        kana_ME = 1234,
+        kana_MO = 1235,
+        kana_YA = 1236,
+        kana_YU = 1237,
+        kana_YO = 1238,
+        kana_RA = 1239,
+        kana_RI = 1240,
+        kana_RU = 1241,
+        kana_RE = 1242,
+        kana_RO = 1243,
+        kana_WA = 1244,
+        kana_N = 1245,
+        voicedsound = 1246,
+        semivoicedsound = 1247,
+        Arabic_comma = 1452,
+        Arabic_semicolon = 1467,
+        Arabic_question_mark = 1471,
+        Arabic_hamza = 1473,
+        Arabic_maddaonalef = 1474,
+        Arabic_hamzaonalef = 1475,
+        Arabic_hamzaonwaw = 1476,
+        Arabic_hamzaunderalef = 1477,
+        Arabic_hamzaonyeh = 1478,
+        Arabic_alef = 1479,
+        Arabic_beh = 1480,
+        Arabic_tehmarbuta = 1481,
+        Arabic_teh = 1482,
+        Arabic_theh = 1483,
+        Arabic_jeem = 1484,
+        Arabic_hah = 1485,
+        Arabic_khah = 1486,
+        Arabic_dal = 1487,
+        Arabic_thal = 1488,
+        Arabic_ra = 1489,
+        Arabic_zain = 1490,
+        Arabic_seen = 1491,
+        Arabic_sheen = 1492,
+        Arabic_sad = 1493,
+        Arabic_dad = 1494,
+        Arabic_tah = 1495,
+        Arabic_zah = 1496,
+        Arabic_ain = 1497,
+        Arabic_ghain = 1498,
+        Arabic_tatweel = 1504,
+        Arabic_feh = 1505,
+        Arabic_qaf = 1506,
+        Arabic_kaf = 1507,
+        Arabic_lam = 1508,
+        Arabic_meem = 1509,
+        Arabic_noon = 1510,
+        Arabic_ha = 1511,
+        Arabic_heh = 1511,
+        Arabic_waw = 1512,
+        Arabic_alefmaksura = 1513,
+        Arabic_yeh = 1514,
+        Arabic_fathatan = 1515,
+        Arabic_dammatan = 1516,
+        Arabic_kasratan = 1517,
+        Arabic_fatha = 1518,
+        Arabic_damma = 1519,
+        Arabic_kasra = 1520,
+        Arabic_shadda = 1521,
+        Arabic_sukun = 1522,
+        Serbian_dje = 1697,
+        Macedonia_gje = 1698,
+        Cyrillic_io = 1699,
+        Ukrainian_ie = 1700,
+        Ukranian_je = 1700,
+        Macedonia_dse = 1701,
+        Ukrainian_i = 1702,
+        Ukranian_i = 1702,
+        Ukrainian_yi = 1703,
+        Ukranian_yi = 1703,
+        Cyrillic_je = 1704,
+        Serbian_je = 1704,
+        Cyrillic_lje = 1705,
+        Serbian_lje = 1705,
+        Cyrillic_nje = 1706,
+        Serbian_nje = 1706,
+        Serbian_tshe = 1707,
+        Macedonia_kje = 1708,
+        Byelorussian_shortu = 1710,
+        Cyrillic_dzhe = 1711,
+        Serbian_dze = 1711,
+        numerosign = 1712,
+        Serbian_DJE = 1713,
+        Macedonia_GJE = 1714,
+        Cyrillic_IO = 1715,
+        Ukrainian_IE = 1716,
+        Ukranian_JE = 1716,
+        Macedonia_DSE = 1717,
+        Ukrainian_I = 1718,
+        Ukranian_I = 1718,
+        Ukrainian_YI = 1719,
+        Ukranian_YI = 1719,
+        Cyrillic_JE = 1720,
+        Serbian_JE = 1720,
+        Cyrillic_LJE = 1721,
+        Serbian_LJE = 1721,
+        Cyrillic_NJE = 1722,
+        Serbian_NJE = 1722,
+        Serbian_TSHE = 1723,
+        Macedonia_KJE = 1724,
+        Byelorussian_SHORTU = 1726,
+        Cyrillic_DZHE = 1727,
+        Serbian_DZE = 1727,
+        Cyrillic_yu = 1728,
+        Cyrillic_a = 1729,
+        Cyrillic_be = 1730,
+        Cyrillic_tse = 1731,
+        Cyrillic_de = 1732,
+        Cyrillic_ie = 1733,
+        Cyrillic_ef = 1734,
+        Cyrillic_ghe = 1735,
+        Cyrillic_ha = 1736,
+        Cyrillic_i = 1737,
+        Cyrillic_shorti = 1738,
+        Cyrillic_ka = 1739,
+        Cyrillic_el = 1740,
+        Cyrillic_em = 1741,
+        Cyrillic_en = 1742,
+        Cyrillic_o = 1743,
+        Cyrillic_pe = 1744,
+        Cyrillic_ya = 1745,
+        Cyrillic_er = 1746,
+        Cyrillic_es = 1747,
+        Cyrillic_te = 1748,
+        Cyrillic_u = 1749,
+        Cyrillic_zhe = 1750,
+        Cyrillic_ve = 1751,
+        Cyrillic_softsign = 1752,
+        Cyrillic_yeru = 1753,
+        Cyrillic_ze = 1754,
+        Cyrillic_sha = 1755,
+        Cyrillic_e = 1756,
+        Cyrillic_shcha = 1757,
+        Cyrillic_che = 1758,
+        Cyrillic_hardsign = 1759,
+        Cyrillic_YU = 1760,
+        Cyrillic_A = 1761,
+        Cyrillic_BE = 1762,
+        Cyrillic_TSE = 1763,
+        Cyrillic_DE = 1764,
+        Cyrillic_IE = 1765,
+        Cyrillic_EF = 1766,
+        Cyrillic_GHE = 1767,
+        Cyrillic_HA = 1768,
+        Cyrillic_I = 1769,
+        Cyrillic_SHORTI = 1770,
+        Cyrillic_KA = 1771,
+        Cyrillic_EL = 1772,
+        Cyrillic_EM = 1773,
+        Cyrillic_EN = 1774,
+        Cyrillic_O = 1775,
+        Cyrillic_PE = 1776,
+        Cyrillic_YA = 1777,
+        Cyrillic_ER = 1778,
+        Cyrillic_ES = 1779,
+        Cyrillic_TE = 1780,
+        Cyrillic_U = 1781,
+        Cyrillic_ZHE = 1782,
+        Cyrillic_VE = 1783,
+        Cyrillic_SOFTSIGN = 1784,
+        Cyrillic_YERU = 1785,
+        Cyrillic_ZE = 1786,
+        Cyrillic_SHA = 1787,
+        Cyrillic_E = 1788,
+        Cyrillic_SHCHA = 1789,
+        Cyrillic_CHE = 1790,
+        Cyrillic_HARDSIGN = 1791,
+        Greek_ALPHAaccent = 1953,
+        Greek_EPSILONaccent = 1954,
+        Greek_ETAaccent = 1955,
+        Greek_IOTAaccent = 1956,
+        Greek_IOTAdiaeresis = 1957,
+        Greek_OMICRONaccent = 1959,
+        Greek_UPSILONaccent = 1960,
+        Greek_UPSILONdieresis = 1961,
+        Greek_OMEGAaccent = 1963,
+        Greek_accentdieresis = 1966,
+        Greek_horizbar = 1967,
+        Greek_alphaaccent = 1969,
+        Greek_epsilonaccent = 1970,
+        Greek_etaaccent = 1971,
+        Greek_iotaaccent = 1972,
+        Greek_iotadieresis = 1973,
+        Greek_iotaaccentdieresis = 1974,
+        Greek_omicronaccent = 1975,
+        Greek_upsilonaccent = 1976,
+        Greek_upsilondieresis = 1977,
+        Greek_upsilonaccentdieresis = 1978,
+        Greek_omegaaccent = 1979,
+        Greek_ALPHA = 1985,
+        Greek_BETA = 1986,
+        Greek_GAMMA = 1987,
+        Greek_DELTA = 1988,
+        Greek_EPSILON = 1989,
+        Greek_ZETA = 1990,
+        Greek_ETA = 1991,
+        Greek_THETA = 1992,
+        Greek_IOTA = 1993,
+        Greek_KAPPA = 1994,
+        Greek_LAMBDA = 1995,
+        Greek_LAMDA = 1995,
+        Greek_MU = 1996,
+        Greek_NU = 1997,
+        Greek_XI = 1998,
+        Greek_OMICRON = 1999,
+        Greek_PI = 2000,
+        Greek_RHO = 2001,
+        Greek_SIGMA = 2002,
+        Greek_TAU = 2004,
+        Greek_UPSILON = 2005,
+        Greek_PHI = 2006,
+        Greek_CHI = 2007,
+        Greek_PSI = 2008,
+        Greek_OMEGA = 2009,
+        Greek_alpha = 2017,
+        Greek_beta = 2018,
+        Greek_gamma = 2019,
+        Greek_delta = 2020,
+        Greek_epsilon = 2021,
+        Greek_zeta = 2022,
+        Greek_eta = 2023,
+        Greek_theta = 2024,
+        Greek_iota = 2025,
+        Greek_kappa = 2026,
+        Greek_lambda = 2027,
+        Greek_lamda = 2027,
+        Greek_mu = 2028,
+        Greek_nu = 2029,
+        Greek_xi = 2030,
+        Greek_omicron = 2031,
+        Greek_pi = 2032,
+        Greek_rho = 2033,
+        Greek_sigma = 2034,
+        Greek_finalsmallsigma = 2035,
+        Greek_tau = 2036,
+        Greek_upsilon = 2037,
+        Greek_phi = 2038,
+        Greek_chi = 2039,
+        Greek_psi = 2040,
+        Greek_omega = 2041,
+        leftradical = 2209,
+        topleftradical = 2210,
+        horizconnector = 2211,
+        topintegral = 2212,
+        botintegral = 2213,
+        vertconnector = 2214,
+        topleftsqbracket = 2215,
+        botleftsqbracket = 2216,
+        toprightsqbracket = 2217,
+        botrightsqbracket = 2218,
+        topleftparens = 2219,
+        botleftparens = 2220,
+        toprightparens = 2221,
+        botrightparens = 2222,
+        leftmiddlecurlybrace = 2223,
+        rightmiddlecurlybrace = 2224,
+        topleftsummation = 2225,
+        botleftsummation = 2226,
+        topvertsummationconnector = 2227,
+        botvertsummationconnector = 2228,
+        toprightsummation = 2229,
+        botrightsummation = 2230,
+        rightmiddlesummation = 2231,
+        lessthanequal = 2236,
+        notequal = 2237,
+        greaterthanequal = 2238,
+        integral = 2239,
+        therefore = 2240,
+        variation = 2241,
+        infinity = 2242,
+        nabla = 2245,
+        approximate = 2248,
+        similarequal = 2249,
+        ifonlyif = 2253,
+        implies = 2254,
+        identical = 2255,
+        radical = 2262,
+        includedin = 2266,
+        includes = 2267,
+        intersection = 2268,
+        union = 2269,
+        logicaland = 2270,
+        logicalor = 2271,
+        partialderivative = 2287,
+        function = 2294,
+        leftarrow = 2299,
+        uparrow = 2300,
+        rightarrow = 2301,
+        downarrow = 2302,
+        blank = 2527,
+        soliddiamond = 2528,
+        checkerboard = 2529,
+        ht = 2530,
+        ff = 2531,
+        cr = 2532,
+        lf = 2533,
+        nl = 2536,
+        vt = 2537,
+        lowrightcorner = 2538,
+        uprightcorner = 2539,
+        upleftcorner = 2540,
+        lowleftcorner = 2541,
+        crossinglines = 2542,
+        horizlinescan1 = 2543,
+        horizlinescan3 = 2544,
+        horizlinescan5 = 2545,
+        horizlinescan7 = 2546,
+        horizlinescan9 = 2547,
+        leftt = 2548,
+        rightt = 2549,
+        bott = 2550,
+        topt = 2551,
+        vertbar = 2552,
+        emspace = 2721,
+        enspace = 2722,
+        em3space = 2723,
+        em4space = 2724,
+        digitspace = 2725,
+        punctspace = 2726,
+        thinspace = 2727,
+        hairspace = 2728,
+        emdash = 2729,
+        endash = 2730,
+        signifblank = 2732,
+        ellipsis = 2734,
+        doubbaselinedot = 2735,
+        onethird = 2736,
+        twothirds = 2737,
+        onefifth = 2738,
+        twofifths = 2739,
+        threefifths = 2740,
+        fourfifths = 2741,
+        onesixth = 2742,
+        fivesixths = 2743,
+        careof = 2744,
+        figdash = 2747,
+        leftanglebracket = 2748,
+        decimalpoint = 2749,
+        rightanglebracket = 2750,
+        marker = 2751,
+        oneeighth = 2755,
+        threeeighths = 2756,
+        fiveeighths = 2757,
+        seveneighths = 2758,
+        trademark = 2761,
+        signaturemark = 2762,
+        trademarkincircle = 2763,
+        leftopentriangle = 2764,
+        rightopentriangle = 2765,
+        emopencircle = 2766,
+        emopenrectangle = 2767,
+        leftsinglequotemark = 2768,
+        rightsinglequotemark = 2769,
+        leftdoublequotemark = 2770,
+        rightdoublequotemark = 2771,
+        prescription = 2772,
+        minutes = 2774,
+        seconds = 2775,
+        latincross = 2777,
+        hexagram = 2778,
+        filledrectbullet = 2779,
+        filledlefttribullet = 2780,
+        filledrighttribullet = 2781,
+        emfilledcircle = 2782,
+        emfilledrect = 2783,
+        enopencircbullet = 2784,
+        enopensquarebullet = 2785,
+        openrectbullet = 2786,
+        opentribulletup = 2787,
+        opentribulletdown = 2788,
+        openstar = 2789,
+        enfilledcircbullet = 2790,
+        enfilledsqbullet = 2791,
+        filledtribulletup = 2792,
+        filledtribulletdown = 2793,
+        leftpointer = 2794,
+        rightpointer = 2795,
+        club = 2796,
+        diamond = 2797,
+        heart = 2798,
+        maltesecross = 2800,
+        dagger = 2801,
+        doubledagger = 2802,
+        checkmark = 2803,
+        ballotcross = 2804,
+        musicalsharp = 2805,
+        musicalflat = 2806,
+        malesymbol = 2807,
+        femalesymbol = 2808,
+        telephone = 2809,
+        telephonerecorder = 2810,
+        phonographcopyright = 2811,
+        caret = 2812,
+        singlelowquotemark = 2813,
+        doublelowquotemark = 2814,
+        cursor = 2815,
+        leftcaret = 2979,
+        rightcaret = 2982,
+        downcaret = 2984,
+        upcaret = 2985,
+        overbar = 3008,
+        downtack = 3010,
+        upshoe = 3011,
+        downstile = 3012,
+        underbar = 3014,
+        jot = 3018,
+        quad = 3020,
+        uptack = 3022,
+        circle = 3023,
+        upstile = 3027,
+        downshoe = 3030,
+        rightshoe = 3032,
+        leftshoe = 3034,
+        lefttack = 3036,
+        righttack = 3068,
+        hebrew_doublelowline = 3295,
+        hebrew_aleph = 3296,
+        hebrew_bet = 3297,
+        hebrew_beth = 3297,
+        hebrew_gimel = 3298,
+        hebrew_gimmel = 3298,
+        hebrew_dalet = 3299,
+        hebrew_daleth = 3299,
+        hebrew_he = 3300,
+        hebrew_waw = 3301,
+        hebrew_zain = 3302,
+        hebrew_zayin = 3302,
+        hebrew_chet = 3303,
+        hebrew_het = 3303,
+        hebrew_tet = 3304,
+        hebrew_teth = 3304,
+        hebrew_yod = 3305,
+        hebrew_finalkaph = 3306,
+        hebrew_kaph = 3307,
+        hebrew_lamed = 3308,
+        hebrew_finalmem = 3309,
+        hebrew_mem = 3310,
+        hebrew_finalnun = 3311,
+        hebrew_nun = 3312,
+        hebrew_samech = 3313,
+        hebrew_samekh = 3313,
+        hebrew_ayin = 3314,
+        hebrew_finalpe = 3315,
+        hebrew_pe = 3316,
+        hebrew_finalzade = 3317,
+        hebrew_finalzadi = 3317,
+        hebrew_zade = 3318,
+        hebrew_zadi = 3318,
+        hebrew_kuf = 3319,
+        hebrew_qoph = 3319,
+        hebrew_resh = 3320,
+        hebrew_shin = 3321,
+        hebrew_taf = 3322,
+        hebrew_taw = 3322,
+        Thai_kokai = 3489,
+        Thai_khokhai = 3490,
+        Thai_khokhuat = 3491,
+        Thai_khokhwai = 3492,
+        Thai_khokhon = 3493,
+        Thai_khorakhang = 3494,
+        Thai_ngongu = 3495,
+        Thai_chochan = 3496,
+        Thai_choching = 3497,
+        Thai_chochang = 3498,
+        Thai_soso = 3499,
+        Thai_chochoe = 3500,
+        Thai_yoying = 3501,
+        Thai_dochada = 3502,
+        Thai_topatak = 3503,
+        Thai_thothan = 3504,
+        Thai_thonangmontho = 3505,
+        Thai_thophuthao = 3506,
+        Thai_nonen = 3507,
+        Thai_dodek = 3508,
+        Thai_totao = 3509,
+        Thai_thothung = 3510,
+        Thai_thothahan = 3511,
+        Thai_thothong = 3512,
+        Thai_nonu = 3513,
+        Thai_bobaimai = 3514,
+        Thai_popla = 3515,
+        Thai_phophung = 3516,
+        Thai_fofa = 3517,
+        Thai_phophan = 3518,
+        Thai_fofan = 3519,
+        Thai_phosamphao = 3520,
+        Thai_moma = 3521,
+        Thai_yoyak = 3522,
+        Thai_rorua = 3523,
+        Thai_ru = 3524,
+        Thai_loling = 3525,
+        Thai_lu = 3526,
+        Thai_wowaen = 3527,
+        Thai_sosala = 3528,
+        Thai_sorusi = 3529,
+        Thai_sosua = 3530,
+        Thai_hohip = 3531,
+        Thai_lochula = 3532,
+        Thai_oang = 3533,
+        Thai_honokhuk = 3534,
+        Thai_paiyannoi = 3535,
+        Thai_saraa = 3536,
+        Thai_maihanakat = 3537,
+        Thai_saraaa = 3538,
+        Thai_saraam = 3539,
+        Thai_sarai = 3540,
+        Thai_saraii = 3541,
+        Thai_saraue = 3542,
+        Thai_sarauee = 3543,
+        Thai_sarau = 3544,
+        Thai_sarauu = 3545,
+        Thai_phinthu = 3546,
+        Thai_maihanakat_maitho = 3550,
+        Thai_baht = 3551,
+        Thai_sarae = 3552,
+        Thai_saraae = 3553,
+        Thai_sarao = 3554,
+        Thai_saraaimaimuan = 3555,
+        Thai_saraaimaimalai = 3556,
+        Thai_lakkhangyao = 3557,
+        Thai_maiyamok = 3558,
+        Thai_maitaikhu = 3559,
+        Thai_maiek = 3560,
+        Thai_maitho = 3561,
+        Thai_maitri = 3562,
+        Thai_maichattawa = 3563,
+        Thai_thanthakhat = 3564,
+        Thai_nikhahit = 3565,
+        Thai_leksun = 3568,
+        Thai_leknung = 3569,
+        Thai_leksong = 3570,
+        Thai_leksam = 3571,
+        Thai_leksi = 3572,
+        Thai_lekha = 3573,
+        Thai_lekhok = 3574,
+        Thai_lekchet = 3575,
+        Thai_lekpaet = 3576,
+        Thai_lekkao = 3577,
+        Hangul_Kiyeog = 3745,
+        Hangul_SsangKiyeog = 3746,
+        Hangul_KiyeogSios = 3747,
+        Hangul_Nieun = 3748,
+        Hangul_NieunJieuj = 3749,
+        Hangul_NieunHieuh = 3750,
+        Hangul_Dikeud = 3751,
+        Hangul_SsangDikeud = 3752,
+        Hangul_Rieul = 3753,
+        Hangul_RieulKiyeog = 3754,
+        Hangul_RieulMieum = 3755,
+        Hangul_RieulPieub = 3756,
+        Hangul_RieulSios = 3757,
+        Hangul_RieulTieut = 3758,
+        Hangul_RieulPhieuf = 3759,
+        Hangul_RieulHieuh = 3760,
+        Hangul_Mieum = 3761,
+        Hangul_Pieub = 3762,
+        Hangul_SsangPieub = 3763,
+        Hangul_PieubSios = 3764,
+        Hangul_Sios = 3765,
+        Hangul_SsangSios = 3766,
+        Hangul_Ieung = 3767,
+        Hangul_Jieuj = 3768,
+        Hangul_SsangJieuj = 3769,
+        Hangul_Cieuc = 3770,
+        Hangul_Khieuq = 3771,
+        Hangul_Tieut = 3772,
+        Hangul_Phieuf = 3773,
+        Hangul_Hieuh = 3774,
+        Hangul_A = 3775,
+        Hangul_AE = 3776,
+        Hangul_YA = 3777,
+        Hangul_YAE = 3778,
+        Hangul_EO = 3779,
+        Hangul_E = 3780,
+        Hangul_YEO = 3781,
+        Hangul_YE = 3782,
+        Hangul_O = 3783,
+        Hangul_WA = 3784,
+        Hangul_WAE = 3785,
+        Hangul_OE = 3786,
+        Hangul_YO = 3787,
+        Hangul_U = 3788,
+        Hangul_WEO = 3789,
+        Hangul_WE = 3790,
+        Hangul_WI = 3791,
+        Hangul_YU = 3792,
+        Hangul_EU = 3793,
+        Hangul_YI = 3794,
+        Hangul_I = 3795,
+        Hangul_J_Kiyeog = 3796,
+        Hangul_J_SsangKiyeog = 3797,
+        Hangul_J_KiyeogSios = 3798,
+        Hangul_J_Nieun = 3799,
+        Hangul_J_NieunJieuj = 3800,
+        Hangul_J_NieunHieuh = 3801,
+        Hangul_J_Dikeud = 3802,
+        Hangul_J_Rieul = 3803,
+        Hangul_J_RieulKiyeog = 3804,
+        Hangul_J_RieulMieum = 3805,
+        Hangul_J_RieulPieub = 3806,
+        Hangul_J_RieulSios = 3807,
+        Hangul_J_RieulTieut = 3808,
+        Hangul_J_RieulPhieuf = 3809,
+        Hangul_J_RieulHieuh = 3810,
+        Hangul_J_Mieum = 3811,
+        Hangul_J_Pieub = 3812,
+        Hangul_J_PieubSios = 3813,
+        Hangul_J_Sios = 3814,
+        Hangul_J_SsangSios = 3815,
+        Hangul_J_Ieung = 3816,
+        Hangul_J_Jieuj = 3817,
+        Hangul_J_Cieuc = 3818,
+        Hangul_J_Khieuq = 3819,
+        Hangul_J_Tieut = 3820,
+        Hangul_J_Phieuf = 3821,
+        Hangul_J_Hieuh = 3822,
+        Hangul_RieulYeorinHieuh = 3823,
+        Hangul_SunkyeongeumMieum = 3824,
+        Hangul_SunkyeongeumPieub = 3825,
+        Hangul_PanSios = 3826,
+        Hangul_KkogjiDalrinIeung = 3827,
+        Hangul_SunkyeongeumPhieuf = 3828,
+        Hangul_YeorinHieuh = 3829,
+        Hangul_AraeA = 3830,
+        Hangul_AraeAE = 3831,
+        Hangul_J_PanSios = 3832,
+        Hangul_J_KkogjiDalrinIeung = 3833,
+        Hangul_J_YeorinHieuh = 3834,
+        Korean_Won = 3839,
+        OE = 5052,
+        oe = 5053,
+        Ydiaeresis = 5054,
+        EcuSign = 8352,
+        ColonSign = 8353,
+        CruzeiroSign = 8354,
+        FFrancSign = 8355,
+        LiraSign = 8356,
+        MillSign = 8357,
+        NairaSign = 8358,
+        PesetaSign = 8359,
+        RupeeSign = 8360,
+        WonSign = 8361,
+        NewSheqelSign = 8362,
+        DongSign = 8363,
+        EuroSign = 8364,
+        Key_3270_Duplicate = 64769,
+        Key_3270_FieldMark = 64770,
+        Key_3270_Right2 = 64771,
+        Key_3270_Left2 = 64772,
+        Key_3270_BackTab = 64773,
+        Key_3270_EraseEOF = 64774,
+        Key_3270_EraseInput = 64775,
+        Key_3270_Reset = 64776,
+        Key_3270_Quit = 64777,
+        Key_3270_PA1 = 64778,
+        Key_3270_PA2 = 64779,
+        Key_3270_PA3 = 64780,
+        Key_3270_Test = 64781,
+        Key_3270_Attn = 64782,
+        Key_3270_CursorBlink = 64783,
+        Key_3270_AltCursor = 64784,
+        Key_3270_KeyClick = 64785,
+        Key_3270_Jump = 64786,
+        Key_3270_Ident = 64787,
+        Key_3270_Rule = 64788,
+        Key_3270_Copy = 64789,
+        Key_3270_Play = 64790,
+        Key_3270_Setup = 64791,
+        Key_3270_Record = 64792,
+        Key_3270_ChangeScreen = 64793,
+        Key_3270_DeleteWord = 64794,
+        Key_3270_ExSelect = 64795,
+        Key_3270_CursorSelect = 64796,
+        Key_3270_PrintScreen = 64797,
+        Key_3270_Enter = 64798,
+        ISO_Lock = 65025,
+        ISO_Level2_Latch = 65026,
+        ISO_Level3_Shift = 65027,
+        ISO_Level3_Latch = 65028,
+        ISO_Level3_Lock = 65029,
+        ISO_Group_Latch = 65030,
+        ISO_Group_Lock = 65031,
+        ISO_Next_Group = 65032,
+        ISO_Next_Group_Lock = 65033,
+        ISO_Prev_Group = 65034,
+        ISO_Prev_Group_Lock = 65035,
+        ISO_First_Group = 65036,
+        ISO_First_Group_Lock = 65037,
+        ISO_Last_Group = 65038,
+        ISO_Last_Group_Lock = 65039,
+        ISO_Left_Tab = 65056,
+        ISO_Move_Line_Up = 65057,
+        ISO_Move_Line_Down = 65058,
+        ISO_Partial_Line_Up = 65059,
+        ISO_Partial_Line_Down = 65060,
+        ISO_Partial_Space_Left = 65061,
+        ISO_Partial_Space_Right = 65062,
+        ISO_Set_Margin_Left = 65063,
+        ISO_Set_Margin_Right = 65064,
+        ISO_Release_Margin_Left = 65065,
+        ISO_Release_Margin_Right = 65066,
+        ISO_Release_Both_Margins = 65067,
+        ISO_Fast_Cursor_Left = 65068,
+        ISO_Fast_Cursor_Right = 65069,
+        ISO_Fast_Cursor_Up = 65070,
+        ISO_Fast_Cursor_Down = 65071,
+        ISO_Continuous_Underline = 65072,
+        ISO_Discontinuous_Underline = 65073,
+        ISO_Emphasize = 65074,
+        ISO_Center_Object = 65075,
+        ISO_Enter = 65076,
+        dead_grave = 65104,
+        dead_acute = 65105,
+        dead_circumflex = 65106,
+        dead_tilde = 65107,
+        dead_macron = 65108,
+        dead_breve = 65109,
+        dead_abovedot = 65110,
+        dead_diaeresis = 65111,
+        dead_abovering = 65112,
+        dead_doubleacute = 65113,
+        dead_caron = 65114,
+        dead_cedilla = 65115,
+        dead_ogonek = 65116,
+        dead_iota = 65117,
+        dead_voiced_sound = 65118,
+        dead_semivoiced_sound = 65119,
+        dead_belowdot = 65120,
+        AccessX_Enable = 65136,
+        AccessX_Feedback_Enable = 65137,
+        RepeatKeys_Enable = 65138,
+        SlowKeys_Enable = 65139,
+        BounceKeys_Enable = 65140,
+        StickyKeys_Enable = 65141,
+        MouseKeys_Enable = 65142,
+        MouseKeys_Accel_Enable = 65143,
+        Overlay1_Enable = 65144,
+        Overlay2_Enable = 65145,
+        AudibleBell_Enable = 65146,
+        First_Virtual_Screen = 65232,
+        Prev_Virtual_Screen = 65233,
+        Next_Virtual_Screen = 65234,
+        Last_Virtual_Screen = 65236,
+        Terminate_Server = 65237,
+        Pointer_Left = 65248,
+        Pointer_Right = 65249,
+        Pointer_Up = 65250,
+        Pointer_Down = 65251,
+        Pointer_UpLeft = 65252,
+        Pointer_UpRight = 65253,
+        Pointer_DownLeft = 65254,
+        Pointer_DownRight = 65255,
+        Pointer_Button_Dflt = 65256,
+        Pointer_Button1 = 65257,
+        Pointer_Button2 = 65258,
+        Pointer_Button3 = 65259,
+        Pointer_Button4 = 65260,
+        Pointer_Button5 = 65261,
+        Pointer_DblClick_Dflt = 65262,
+        Pointer_DblClick1 = 65263,
+        Pointer_DblClick2 = 65264,
+        Pointer_DblClick3 = 65265,
+        Pointer_DblClick4 = 65266,
+        Pointer_DblClick5 = 65267,
+        Pointer_Drag_Dflt = 65268,
+        Pointer_Drag1 = 65269,
+        Pointer_Drag2 = 65270,
+        Pointer_Drag3 = 65271,
+        Pointer_Drag4 = 65272,
+        Pointer_EnableKeys = 65273,
+        Pointer_Accelerate = 65274,
+        Pointer_DfltBtnNext = 65275,
+        Pointer_DfltBtnPrev = 65276,
+        Pointer_Drag5 = 65277,
+        BackSpace = 65288,
+        Tab = 65289,
+        Linefeed = 65290,
+        Clear = 65291,
+        Return = 65293,
+        Pause = 65299,
+        Scroll_Lock = 65300,
+        Sys_Req = 65301,
+        Escape = 65307,
+        Multi_key = 65312,
+        Kanji = 65313,
+        Muhenkan = 65314,
+        Henkan = 65315,
+        Henkan_Mode = 65315,
+        Romaji = 65316,
+        Hiragana = 65317,
+        Katakana = 65318,
+        Hiragana_Katakana = 65319,
+        Zenkaku = 65320,
+        Hankaku = 65321,
+        Zenkaku_Hankaku = 65322,
+        Touroku = 65323,
+        Massyo = 65324,
+        Kana_Lock = 65325,
+        Kana_Shift = 65326,
+        Eisu_Shift = 65327,
+        Eisu_toggle = 65328,
+        Hangul = 65329,
+        Hangul_Start = 65330,
+        Hangul_End = 65331,
+        Hangul_Hanja = 65332,
+        Hangul_Jamo = 65333,
+        Hangul_Romaja = 65334,
+        Codeinput = 65335,
+        Hangul_Codeinput = 65335,
+        Kanji_Bangou = 65335,
+        Hangul_Jeonja = 65336,
+        Hangul_Banja = 65337,
+        Hangul_PreHanja = 65338,
+        Hangul_PostHanja = 65339,
+        Hangul_SingleCandidate = 65340,
+        SingleCandidate = 65340,
+        Hangul_MultipleCandidate = 65341,
+        MultipleCandidate = 65341,
+        Zen_Koho = 65341,
+        Hangul_PreviousCandidate = 65342,
+        Mae_Koho = 65342,
+        PreviousCandidate = 65342,
+        Hangul_Special = 65343,
+        Home = 65360,
+        Left = 65361,
+        Up = 65362,
+        Right = 65363,
+        Down = 65364,
+        Page_Up = 65365,
+        Prior = 65365,
+        Next = 65366,
+        Page_Down = 65366,
+        End = 65367,
+        Begin = 65368,
+        Select = 65376,
+        Print = 65377,
+        Execute = 65378,
+        Insert = 65379,
+        Undo = 65381,
+        Redo = 65382,
+        Menu = 65383,
+        Find = 65384,
+        Cancel = 65385,
+        Help = 65386,
+        Break = 65387,
+        Arabic_switch = 65406,
+        Greek_switch = 65406,
+        Hangul_switch = 65406,
+        Hebrew_switch = 65406,
+        ISO_Group_Shift = 65406,
+        Mode_switch = 65406,
+        kana_switch = 65406,
+        script_switch = 65406,
+        Num_Lock = 65407,
+        KP_Space = 65408,
+        KP_Tab = 65417,
+        KP_Enter = 65421,
+        KP_F1 = 65425,
+        KP_F2 = 65426,
+        KP_F3 = 65427,
+        KP_F4 = 65428,
+        KP_Home = 65429,
+        KP_Left = 65430,
+        KP_Up = 65431,
+        KP_Right = 65432,
+        KP_Down = 65433,
+        KP_Page_Up = 65434,
+        KP_Prior = 65434,
+        KP_Next = 65435,
+        KP_Page_Down = 65435,
+        KP_End = 65436,
+        KP_Begin = 65437,
+        KP_Insert = 65438,
+        KP_Delete = 65439,
+        KP_Multiply = 65450,
+        KP_Add = 65451,
+        KP_Separator = 65452,
+        KP_Subtract = 65453,
+        KP_Decimal = 65454,
+        KP_Divide = 65455,
+        KP_0 = 65456,
+        KP_1 = 65457,
+        KP_2 = 65458,
+        KP_3 = 65459,
+        KP_4 = 65460,
+        KP_5 = 65461,
+        KP_6 = 65462,
+        KP_7 = 65463,
+        KP_8 = 65464,
+        KP_9 = 65465,
+        KP_Equal = 65469,
+        F1 = 65470,
+        F2 = 65471,
+        F3 = 65472,
+        F4 = 65473,
+        F5 = 65474,
+        F6 = 65475,
+        F7 = 65476,
+        F8 = 65477,
+        F9 = 65478,
+        F10 = 65479,
+        F11 = 65480,
+        L1 = 65480,
+        F12 = 65481,
+        L2 = 65481,
+        F13 = 65482,
+        L3 = 65482,
+        F14 = 65483,
+        L4 = 65483,
+        F15 = 65484,
+        L5 = 65484,
+        F16 = 65485,
+        L6 = 65485,
+        F17 = 65486,
+        L7 = 65486,
+        F18 = 65487,
+        L8 = 65487,
+        F19 = 65488,
+        L9 = 65488,
+        F20 = 65489,
+        L10 = 65489,
+        F21 = 65490,
+        R1 = 65490,
+        F22 = 65491,
+        R2 = 65491,
+        F23 = 65492,
+        R3 = 65492,
+        F24 = 65493,
+        R4 = 65493,
+        F25 = 65494,
+        R5 = 65494,
+        F26 = 65495,
+        R6 = 65495,
+        F27 = 65496,
+        R7 = 65496,
+        F28 = 65497,
+        R8 = 65497,
+        F29 = 65498,
+        R9 = 65498,
+        F30 = 65499,
+        R10 = 65499,
+        F31 = 65500,
+        R11 = 65500,
+        F32 = 65501,
+        R12 = 65501,
+        F33 = 65502,
+        R13 = 65502,
+        F34 = 65503,
+        R14 = 65503,
+        F35 = 65504,
+        R15 = 65504,
+        Shift_L = 65505,
+        Shift_R = 65506,
+        Control_L = 65507,
+        Control_R = 65508,
+        Caps_Lock = 65509,
+        Shift_Lock = 65510,
+        Meta_L = 65511,
+        Meta_R = 65512,
+        Alt_L = 65513,
+        Alt_R = 65514,
+        Super_L = 65515,
+        Super_R = 65516,
+        Hyper_L = 65517,
+        Hyper_R = 65518,
+        Delete = 65535,
+        VoidSymbol = 16777215,
+    }
+}

+ 116 - 0
src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs

@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Input.Platform;
+using Avalonia.Platform;
+using Avalonia.Rendering;
+using Avalonia.Gtk3;
+
+namespace Avalonia.Gtk3
+{
+    public class Gtk3Platform : IWindowingPlatform, IPlatformSettings, IPlatformThreadingInterface
+    {
+        internal static readonly Gtk3Platform Instance = new Gtk3Platform();
+        internal static readonly MouseDevice Mouse = new MouseDevice();
+        internal static readonly KeyboardDevice Keyboard = new KeyboardDevice();
+        internal static IntPtr App { get; set; }
+        public static void Initialize()
+        {
+            Resolver.Resolve();
+            Native.GtkInit(0, IntPtr.Zero);
+            using (var utf = new Utf8Buffer("avalonia.app." + Guid.NewGuid()))
+                App = Native.GtkApplicationNew(utf, 0);
+            //Mark current thread as UI thread
+            s_tlsMarker = true;
+
+            AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatform>().ToConstant(Instance)
+                .Bind<IClipboard>().ToSingleton<ClipboardImpl>()
+                .Bind<IStandardCursorFactory>().ToConstant(new CursorFactory())
+                .Bind<IKeyboardDevice>().ToConstant(Keyboard)
+                .Bind<IMouseDevice>().ToConstant(Mouse)
+                .Bind<IPlatformSettings>().ToConstant(Instance)
+                .Bind<IPlatformThreadingInterface>().ToConstant(Instance)
+                .Bind<ISystemDialogImpl>().ToSingleton<SystemDialog>()
+                .Bind<IRenderLoop>().ToConstant(new DefaultRenderLoop(60))
+                .Bind<IPlatformIconLoader>().ToConstant(new PlatformIconLoader());
+
+        }
+
+        public IWindowImpl CreateWindow() => new WindowImpl();
+
+        public IEmbeddableWindowImpl CreateEmbeddableWindow()
+        {
+            throw new NotImplementedException();
+        }
+
+        public IPopupImpl CreatePopup() => new PopupImpl();
+
+        
+
+        public Size DoubleClickSize => new Size(4, 4);
+
+        public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(100); //STUB
+        public double RenderScalingFactor { get; } = 1;
+        public double LayoutScalingFactor { get; } = 1;
+
+        public void RunLoop(CancellationToken cancellationToken)
+        {
+            while (!cancellationToken.IsCancellationRequested)
+                Native.GtkMainIteration();
+        }
+
+        public IDisposable StartTimer(TimeSpan interval, Action tick)
+        {
+            return GlibTimeout.StarTimer((uint) interval.TotalMilliseconds, tick);
+        }
+
+        private bool _signaled = false;
+        object _lock = new object();
+
+        public void Signal()
+        {
+            lock(_lock)
+                if (!_signaled)
+                {
+                    _signaled = true;
+                    GlibTimeout.Add(0, () =>
+                    {
+                        lock (_lock)
+                        {
+                            _signaled = false;
+                        }
+                        Signaled?.Invoke();
+                        return false;
+                    });
+                }
+        }
+        public event Action Signaled;
+
+
+        [ThreadStatic]
+        private static bool s_tlsMarker;
+
+        public bool CurrentThreadIsLoopThread => s_tlsMarker;
+
+    }
+}
+
+namespace Avalonia
+{
+    public static class Gtk3AppBuilderExtensions
+    {
+        public static T UseGtk3<T>(this AppBuilderBase<T> builder, ICustomGtk3NativeLibraryResolver resolver = null) 
+            where T : AppBuilderBase<T>, new()
+        {
+            Resolver.Custom = resolver;
+            return builder.UseWindowingSubsystem(Gtk3Platform.Initialize, "GTK3");
+        }
+    }
+}

+ 54 - 0
src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs

@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls.Platform.Surfaces;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+
+namespace Avalonia.Gtk3
+{
+    class ImageSurfaceFramebuffer : ILockedFramebuffer
+    {
+        private IntPtr _context;
+        private CairoSurface _surface;
+
+        public ImageSurfaceFramebuffer(IntPtr context, int width, int height)
+        {
+            _context = context;
+            _surface = Native.CairoImageSurfaceCreate(1, width, height);
+            Width = width;
+            Height = height;
+            Address = Native.CairoImageSurfaceGetData(_surface);
+            RowBytes = Native.CairoImageSurfaceGetStride(_surface);
+            Native.CairoSurfaceFlush(_surface);
+        }
+        
+        public void Dispose()
+        {
+            if(_context == IntPtr.Zero || _surface == null)
+                return;
+            Native.CairoSurfaceMarkDirty(_surface);
+            Native.CairoSetSourceSurface(_context, _surface, 0, 0);
+            Native.CairoPaint(_context);
+            _context = IntPtr.Zero;
+            _surface.Dispose();
+            _surface = null;
+        }
+
+        public IntPtr Address { get; }
+        public int Width  { get; }
+        public int Height { get; }
+        public int RowBytes { get; }
+
+        //TODO: Proper DPI detect
+        public Size Dpi => new Size(96, 96);
+
+        public PixelFormat Format => PixelFormat.Bgra8888;
+    }
+}
+
+
+

+ 20 - 0
src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Gtk3.Interop
+{
+    class CairoSurface : SafeHandle
+    {
+        public CairoSurface() : base(IntPtr.Zero, true)
+        {
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            Native.CairoSurfaceDestroy(handle);
+            return true;
+        }
+
+        public override bool IsInvalid => handle == IntPtr.Zero;
+    }
+}

+ 129 - 0
src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs

@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+/*
+ * Source code imported from https://github.com/kekekeks/evhttp-sharp
+ * Source is provided under MIT license for Avalonia project and derived works
+ */
+
+
+namespace Avalonia.Gtk3.Interop
+{
+    internal interface IDynLoader
+    {
+        IntPtr LoadLibrary(string dll);
+        IntPtr GetProcAddress(IntPtr dll, string proc);
+
+    }
+
+    class UnixLoader : IDynLoader
+    {
+        // ReSharper disable InconsistentNaming
+        static class LinuxImports
+        {
+            [DllImport("libdl.so.2")]
+            private static extern IntPtr dlopen(string path, int flags);
+
+            [DllImport("libdl.so.2")]
+            private static extern IntPtr dlsym(IntPtr handle, string symbol);
+
+            [DllImport("libdl.so.2")]
+            private static extern IntPtr dlerror();
+
+            public static void Init()
+            {
+                DlOpen = dlopen;
+                DlSym = dlsym;
+                DlError = dlerror;
+            }
+        }
+        static class OsXImports
+        {
+            
+            
+            [DllImport("/usr/lib/libSystem.dylib")]
+            private static extern IntPtr dlopen(string path, int flags);
+
+            [DllImport("/usr/lib/libSystem.dylib")]
+            private static extern IntPtr dlsym(IntPtr handle, string symbol);
+
+            [DllImport("/usr/lib/libSystem.dylib")]
+            private static extern IntPtr dlerror();
+
+            public static void Init()
+            {
+                DlOpen = dlopen;
+                DlSym = dlsym;
+                DlError = dlerror;
+            }
+            
+        }
+        
+
+        [DllImport("libc")]
+        static extern int uname(IntPtr buf);
+
+        static UnixLoader()
+        {
+            var buffer = Marshal.AllocHGlobal(0x1000);
+            uname(buffer);
+            var unixName = Marshal.PtrToStringAnsi(buffer);
+            Marshal.FreeHGlobal(buffer);
+            if(unixName == "Darwin")
+                OsXImports.Init();
+            else
+                LinuxImports.Init();
+        }
+
+        private static Func<string, int, IntPtr> DlOpen;
+        private static Func<IntPtr, string, IntPtr> DlSym;
+        private static Func<IntPtr> DlError;
+        // ReSharper restore InconsistentNaming
+
+        static string DlErrorString() => Marshal.PtrToStringAnsi(DlError());
+
+        public IntPtr LoadLibrary(string dll)
+        {
+            var handle = DlOpen(dll, 1);
+            if (handle == IntPtr.Zero)
+                throw new NativeException(DlErrorString());
+            return handle;
+        }
+
+        public IntPtr GetProcAddress(IntPtr dll, string proc)
+        {
+            var ptr = DlSym(dll, proc);
+            if (ptr == IntPtr.Zero)
+                throw new NativeException(DlErrorString());
+            return ptr;
+        }
+    }
+
+    internal class Win32Loader : IDynLoader
+    {
+        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
+        private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
+
+        [DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
+        private static extern IntPtr LoadLibrary(string lpszLib);
+
+        IntPtr IDynLoader.LoadLibrary(string dll)
+        {
+            var handle = LoadLibrary(dll);
+            if (handle != IntPtr.Zero)
+                return handle;
+            var err = Marshal.GetLastWin32Error();
+
+            throw new NativeException("Error loading " + dll + " error " + err);
+        }
+
+        IntPtr IDynLoader.GetProcAddress(IntPtr dll, string proc)
+        {
+            var ptr = GetProcAddress(dll, proc);
+            if (ptr == IntPtr.Zero)
+                throw new NativeException("Error " + Marshal.GetLastWin32Error());
+            return ptr;
+        }
+    }
+}

+ 33 - 0
src/Gtk/Avalonia.Gtk3/Interop/GException.cs

@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+    public class GException : Exception
+    {
+        [StructLayout(LayoutKind.Sequential)]
+        struct GError
+        {
+            UInt32 domain;
+            int code;
+            public IntPtr message;
+        };
+
+        static unsafe string GetError(IntPtr error)
+        {
+            if (error == IntPtr.Zero)
+                return "Unknown error";
+            return Utf8Buffer.StringFromPtr(((GError*) error)->message);
+        }
+
+        public GException(IntPtr error) : base(GetError(error))
+        {
+            
+        }
+
+    }
+}

+ 62 - 0
src/Gtk/Avalonia.Gtk3/Interop/GObject.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+    class GObject : SafeHandle
+    {
+        public GObject() : base(IntPtr.Zero, true)
+        {
+        }
+
+        public GObject(IntPtr handle, bool owned = true) : base(IntPtr.Zero, owned)
+        {
+            this.handle = handle;
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            if (handle != IntPtr.Zero)
+                Native.GObjectUnref(handle);
+            handle = IntPtr.Zero;
+            return true;
+        }
+
+        public override bool IsInvalid => handle == IntPtr.Zero;
+    }
+
+    class GInputStream : GObject
+    {
+        
+    }
+
+    class GtkWidget : GObject
+    {
+        
+    }
+
+    class GtkWindow : GtkWidget
+    {
+        
+    }
+
+    class GtkImContext : GObject
+    {
+        
+    }
+
+    class GtkDialog : GtkWindow
+    {
+        
+    }
+
+    class GtkFileChooser : GtkDialog
+    {
+        
+    }
+}
+

+ 64 - 0
src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+    static class GlibTimeout
+    {
+        static bool Handler(IntPtr data)
+        {
+            var handle = GCHandle.FromIntPtr(data);
+            var cb = (Func<bool>) handle.Target;
+            if (!cb())
+            {
+                handle.Free();
+                return false;
+            }
+            return true;
+        }
+
+        private static readonly GCHandle PinnedHandle;
+        private static readonly Native.D.timeout_callback PinnedHandler;
+        static GlibTimeout()
+        {
+            PinnedHandler = Handler;
+            
+        }
+
+
+        public static void Add(uint interval, Func<bool> callback)
+        {
+            var handle = GCHandle.Alloc(callback);
+            Native.GTimeoutAdd(interval, PinnedHandler, GCHandle.ToIntPtr(handle));
+        }
+
+        class Timer : IDisposable
+        {
+            public bool Stopped;
+            public void Dispose()
+            {
+
+                Stopped = true;
+            }
+        }
+
+        public static IDisposable StarTimer(uint interval, Action tick)
+        {
+            var timer = new Timer ();
+            GlibTimeout.Add(interval,
+                () =>
+                {
+                    if (timer.Stopped)
+                        return false;
+                    tick();
+                    return !timer.Stopped;
+                });
+
+            return timer;
+        }
+    }
+}

+ 17 - 0
src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+
+namespace Avalonia.Gtk3
+{
+    public interface ICustomGtk3NativeLibraryResolver
+    {
+        string GetName(GtkDll dll);
+        string BasePath { get; }
+        bool TrySystemFirst { get; }
+        string Lookup(GtkDll dll);
+    }
+}

+ 571 - 0
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@@ -0,0 +1,571 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using gint8 = System.Byte;
+using gint16 = System.Int16;
+using gint32 = System.Int32;
+using gint = System.Int32;
+using guint16 = System.UInt16;
+using guint32 = System.UInt32;
+using guint = System.UInt32;
+using gdouble = System.Double;
+
+namespace Avalonia.Gtk3.Interop
+{
+    static class Native
+    {
+        public static class D
+        {
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_application_new(Utf8Buffer appId, int flags);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_main_iteration();
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate GtkWindow gtk_window_new(GtkWindowType windowType);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_init(int argc, IntPtr argv);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_present(GtkWindow gtkWindow);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_widget_hide(GtkWidget gtkWidget);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_set_icon(GtkWindow window, Pixbuf pixbuf);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_set_modal(GtkWindow window, bool modal);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)] //No manual import
+            public delegate IntPtr gdk_get_native_handle(IntPtr gdkWindow);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_widget_get_window(GtkWidget gtkWidget);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_widget_get_screen(GtkWidget gtkWidget);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_widget_set_double_buffered(GtkWidget gtkWidget, bool value);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_widget_set_events(GtkWidget gtkWidget, uint flags);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate int gdk_screen_get_height(IntPtr screen);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate int gdk_screen_get_width(IntPtr screen);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_display_get_default();
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate int gdk_window_get_origin(IntPtr gdkWindow, out int x, out int y);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gdk_window_resize(IntPtr gtkWindow, int width, int height);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_widget_realize(GtkWidget gtkWidget);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_set_title(GtkWindow gtkWindow, Utf8Buffer title);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_set_decorated(GtkWindow gtkWindow, bool decorated);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_get_size(GtkWindow gtkWindow, out int width, out int height);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_resize(GtkWindow gtkWindow, int width, int height);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_widget_set_size_request(GtkWidget widget, int width, int height);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_set_default_size(GtkWindow gtkWindow, int width, int height);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_get_position(GtkWindow gtkWindow, out int x, out int y);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_window_move(GtkWindow gtkWindow, int x, int y);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate GtkFileChooser gtk_file_chooser_dialog_new(Utf8Buffer title, GtkWindow parent, GtkFileChooserAction action, IntPtr ignore);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public unsafe delegate GSList* gtk_file_chooser_get_filenames(GtkFileChooser chooser);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_file_chooser_set_select_multiple(GtkFileChooser chooser, bool allow);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_file_chooser_set_filename(GtkFileChooser chooser, Utf8Buffer file);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_dialog_add_button(GtkDialog raw, Utf8Buffer button_text, GtkResponseType response_id);
+
+
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate CairoSurface cairo_image_surface_create(int format, int width, int height);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate IntPtr cairo_image_surface_get_data(CairoSurface surface);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate int cairo_image_surface_get_stride(CairoSurface surface);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate void cairo_surface_mark_dirty(CairoSurface surface);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate void cairo_surface_flush(CairoSurface surface);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate void cairo_surface_destroy(IntPtr surface);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate void cairo_set_source_surface(IntPtr cr, CairoSurface surface, double x, double y);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
+            public delegate void cairo_paint(IntPtr context);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_widget_queue_draw_area(GtkWidget widget, int x, int y, int width, int height);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate GtkImContext gtk_im_multicontext_new();
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_im_context_set_client_window(GtkImContext context, IntPtr window);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate bool gtk_im_context_filter_keypress(GtkImContext context, IntPtr ev);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_widget_activate(GtkWidget widget);
+            
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_screen_get_root_window(IntPtr screen);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_cursor_new(GdkCursorType type);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_window_get_pointer(IntPtr raw, out int x, out int y, out int mask);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gtk_window_set_geometry_hints(GtkWindow window, IntPtr geometry_widget, ref GdkGeometry geometry, GdkWindowHints geom_mask);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gdk_window_invalidate_rect(IntPtr window, ref GdkRectangle rect, bool invalidate_children);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gdk_window_begin_move_drag(IntPtr window, gint button, gint root_x, gint root_y, guint32 timestamp);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate void gdk_event_request_motions(IntPtr ev);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_clipboard_get_for_display(IntPtr display, IntPtr atom);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_clipboard_request_text(IntPtr clipboard, GtkClipboardTextReceivedFunc callback, IntPtr user_data);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_clipboard_set_text(IntPtr clipboard, Utf8Buffer text, int len);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate void gtk_clipboard_clear(IntPtr clipboard);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+            public delegate IntPtr gdk_pixbuf_new_from_file(Utf8Buffer filename, out IntPtr error);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_icon_theme_get_default();
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
+            public delegate IntPtr gtk_icon_theme_load_icon(IntPtr icon_theme, Utf8Buffer icon_name, gint size, int flags,out IntPtr error);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_cursor_new_from_pixbuf(IntPtr disp, IntPtr pixbuf, int x, int y);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
+            public delegate IntPtr gdk_window_set_cursor(IntPtr window, IntPtr cursor);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+            public delegate IntPtr gdk_pixbuf_new_from_stream(GInputStream stream, IntPtr cancel, out IntPtr error);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
+            public delegate bool gdk_pixbuf_save_to_bufferv(Pixbuf pixbuf, out IntPtr buffer, out IntPtr buffer_size,
+                            Utf8Buffer type, IntPtr option_keys, IntPtr option_values, out IntPtr error);
+
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+            public delegate void g_object_unref(IntPtr instance);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+            public delegate void g_object_ref(GObject instance);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+            public delegate ulong g_signal_connect_object(GObject instance, Utf8Buffer signal, IntPtr handler, IntPtr userData, int flags);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
+            public delegate ulong g_signal_handler_disconnect(GObject instance, ulong connectionId);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+            public delegate ulong g_timeout_add(uint interval, timeout_callback callback, IntPtr data);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+            public delegate ulong g_free(IntPtr data);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
+            public unsafe delegate void g_slist_free(GSList* data);
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gio)]
+            public delegate GInputStream g_memory_input_stream_new_from_data(IntPtr ptr, IntPtr len, IntPtr destroyCallback);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool signal_widget_draw(IntPtr gtkWidget, IntPtr cairoContext, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool signal_generic(IntPtr gtkWidget, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool signal_dialog_response(IntPtr gtkWidget, GtkResponseType response, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool signal_onevent(IntPtr gtkWidget, IntPtr ev, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool signal_commit(IntPtr gtkWidget, IntPtr utf8string, IntPtr userData);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate bool timeout_callback(IntPtr data);
+
+            [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+            public delegate void GtkClipboardTextReceivedFunc(IntPtr clipboard, IntPtr utf8string, IntPtr userdata);
+        }
+
+
+        public static D.gtk_window_set_decorated GtkWindowSetDecorated;
+        public static D.gtk_window_set_title GtkWindowSetTitle;
+        public static D.gtk_application_new GtkApplicationNew;
+        public static D.gtk_main_iteration GtkMainIteration;
+        public static D.gtk_window_new GtkWindowNew;
+        public static D.gtk_window_set_icon GtkWindowSetIcon;
+        public static D.gtk_window_set_modal GtkWindowSetModal;
+        public static D.gtk_init GtkInit;
+        public static D.gtk_window_present GtkWindowPresent;
+        public static D.gtk_widget_hide GtkWidgetHide;
+        public static D.gdk_get_native_handle GetNativeGdkWindowHandle;
+        public static D.gtk_widget_get_window GtkWidgetGetWindow;
+        public static D.gtk_widget_get_screen GtkWidgetGetScreen;
+        public static D.gtk_widget_realize GtkWidgetRealize;
+        public static D.gtk_window_get_size GtkWindowGetSize;
+        public static D.gtk_window_resize GtkWindowResize;
+        public static D.gdk_window_resize GdkWindowResize;
+        public static D.gtk_widget_set_size_request GtkWindowSetSizeRequest;
+        public static D.gtk_window_set_default_size GtkWindowSetDefaultSize;
+        public static D.gtk_window_get_position GtkWindowGetPosition;
+        public static D.gtk_window_move GtkWindowMove;
+        public static D.gtk_file_chooser_dialog_new GtkFileChooserDialogNew;
+        public static D.gtk_file_chooser_set_select_multiple GtkFileChooserSetSelectMultiple;
+        public static D.gtk_file_chooser_set_filename GtkFileChooserSetFilename;
+        public static D.gtk_file_chooser_get_filenames GtkFileChooserGetFilenames;
+        public static D.gtk_dialog_add_button GtkDialogAddButton;
+        public static D.g_object_unref GObjectUnref;
+        public static D.g_object_ref GObjectRef;
+        public static D.g_signal_connect_object GSignalConnectObject;
+        public static D.g_signal_handler_disconnect GSignalHandlerDisconnect;
+        public static D.g_timeout_add GTimeoutAdd;
+        public static D.g_free GFree;
+        public static D.g_slist_free GSlistFree;
+        public static D.g_memory_input_stream_new_from_data GMemoryInputStreamNewFromData;
+        public static D.gtk_widget_set_double_buffered GtkWidgetSetDoubleBuffered;
+        public static D.gtk_widget_set_events GtkWidgetSetEvents;
+        public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect;
+        public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
+        public static D.gtk_widget_activate GtkWidgetActivate;
+        public static D.gtk_clipboard_get_for_display GtkClipboardGetForDisplay;
+        public static D.gtk_clipboard_request_text GtkClipboardRequestText;
+        public static D.gtk_clipboard_set_text GtkClipboardSetText;
+        public static D.gtk_clipboard_clear GtkClipboardRequestClear;
+
+
+        public static D.gtk_im_multicontext_new GtkImMulticontextNew;
+        public static D.gtk_im_context_filter_keypress GtkImContextFilterKeypress;
+        public static D.gtk_im_context_set_client_window GtkImContextSetClientWindow;
+
+        public static D.gdk_screen_get_height GdkScreenGetHeight;
+        public static D.gdk_display_get_default GdkGetDefaultDisplay;
+        public static D.gdk_screen_get_width GdkScreenGetWidth;
+        public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
+        public static D.gdk_cursor_new GdkCursorNew;
+        public static D.gdk_window_get_origin GdkWindowGetOrigin;
+        public static D.gdk_window_get_pointer GdkWindowGetPointer;
+        public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
+        public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
+        public static D.gdk_event_request_motions GdkEventRequestMotions;
+
+        public static D.gdk_pixbuf_new_from_file GdkPixbufNewFromFile;
+        public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault;
+        public static D.gtk_icon_theme_load_icon GtkIconThemeLoadIcon;
+        public static D.gdk_cursor_new_from_pixbuf GdkCursorNewFromPixbuf;
+        public static D.gdk_window_set_cursor GdkWindowSetCursor;
+        public static D.gdk_pixbuf_new_from_stream GdkPixbufNewFromStream;
+        public static D.gdk_pixbuf_save_to_bufferv GdkPixbufSaveToBufferv;
+
+        public static D.cairo_image_surface_create CairoImageSurfaceCreate;
+        public static D.cairo_image_surface_get_data CairoImageSurfaceGetData;
+        public static D.cairo_image_surface_get_stride CairoImageSurfaceGetStride;
+        public static D.cairo_surface_mark_dirty CairoSurfaceMarkDirty;
+        public static D.cairo_surface_flush CairoSurfaceFlush;
+        public static D.cairo_surface_destroy CairoSurfaceDestroy;
+        public static D.cairo_set_source_surface CairoSetSourceSurface;
+        public static D.cairo_paint CairoPaint;
+    }
+
+    public enum GtkWindowType
+    {
+        TopLevel,
+        Popup
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    public struct GdkRectangle
+    {
+        public int X, Y, Width, Height;
+
+        public static GdkRectangle FromRect(Rect rect)
+        {
+            return new GdkRectangle
+            {
+                X = (int) rect.X,
+                Y = (int) rect.Y,
+                Width = (int) rect.Width,
+                Height = (int) rect.Height
+            };
+        }
+    }
+
+    enum GdkEventType
+    {
+        Nothing = -1,
+        Delete = 0,
+        Destroy = 1,
+        Expose = 2,
+        MotionNotify = 3,
+        ButtonPress = 4,
+        TwoButtonPress = 5,
+        ThreeButtonPress = 6,
+        ButtonRelease = 7,
+        KeyPress = 8,
+        KeyRelease = 9,
+        EnterNotify = 10,
+        LeaveNotify = 11,
+        FocusChange = 12,
+        Configure = 13,
+        Map = 14,
+        Unmap = 15,
+        PropertyNotify = 16,
+        SelectionClear = 17,
+        SelectionRequest = 18,
+        SelectionNotify = 19,
+        ProximityIn = 20,
+        ProximityOut = 21,
+        DragEnter = 22,
+        DragLeave = 23,
+        DragMotion = 24,
+        DragStatus = 25,
+        DropStart = 26,
+        DropFinished = 27,
+        ClientEvent = 28,
+        VisibilityNotify = 29,
+        NoExpose = 30,
+        Scroll = 31,
+        WindowState = 32,
+        Setting = 33,
+        OwnerChange = 34,
+        GrabBroken = 35,
+    }
+
+    enum GdkModifierType
+    {
+        ShiftMask = 1,
+        LockMask = 2,
+        ControlMask = 4,
+        Mod1Mask = 8,
+        Mod2Mask = 16,
+        Mod3Mask = 32,
+        Mod4Mask = 64,
+        Mod5Mask = 128,
+        Button1Mask = 256,
+        Button2Mask = 512,
+        Button3Mask = 1024,
+        Button4Mask = 2048,
+        Button5Mask = 4096,
+        SuperMask = 67108864,
+        HyperMask = 134217728,
+        MetaMask = 268435456,
+        ReleaseMask = 1073741824,
+        ModifierMask = ReleaseMask | Button5Mask | Button4Mask | Button3Mask | Button2Mask | Button1Mask | Mod5Mask | Mod4Mask | Mod3Mask | Mod2Mask | Mod1Mask | ControlMask | LockMask | ShiftMask,
+        None = 0,
+    }
+
+    enum GdkScrollDirection
+    {
+        Up,
+        Down,
+        Left,
+        Right,
+        Smooth
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GdkEventButton
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        public gint8 send_event;
+        public guint32 time;
+        public gdouble x;
+        public gdouble y;
+        public gdouble* axes;
+        public GdkModifierType state;
+        public guint button;
+        public IntPtr device;
+        public gdouble x_root, y_root;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GdkEventMotion
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        public gint8 send_event;
+        public guint32 time;
+        public gdouble x;
+        public gdouble y;
+        public gdouble* axes;
+        public GdkModifierType state;
+        public gint16 is_hint;
+        public IntPtr device;
+        public gdouble x_root, y_root;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe  struct GdkEventScroll
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        public gint8 send_event;
+        public guint32 time;
+        public gdouble x;
+        public gdouble y;
+        public GdkModifierType state;
+        public GdkScrollDirection direction;
+        public IntPtr device;
+        public gdouble x_root, y_root;
+        public gdouble delta_x;
+        public gdouble delta_y;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GdkEventWindowState
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        gint8 send_event;
+        public GdkWindowState changed_mask;
+        public GdkWindowState new_window_state;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GdkEventKey
+    {
+        public GdkEventType type;
+        public IntPtr window;
+        public gint8 send_event;
+        public guint32 time;
+        public guint state;
+        public guint keyval;
+        public gint length;
+        public IntPtr pstring;
+        public guint16 hardware_keycode;
+        public byte group;
+        public guint is_modifier;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct GSList
+    {
+        public IntPtr Data;
+        public GSList* Next;
+    }
+
+    [Flags]
+    public enum GdkWindowState
+    {
+        Withdrawn = 1,
+        Iconified = 2,
+        Maximized = 4,
+        Sticky = 8,
+        Fullscreen = 16,
+        Above = 32,
+        Below = 64,
+        Focused = 128,
+        Ttiled = 256
+    }
+
+    public enum GtkResponseType
+    {
+        Help = -11,
+        Apply = -10,
+        No = -9,
+        Yes = -8,
+        Close = -7,
+        Cancel = -6,
+        Ok = -5,
+        DeleteEvent = -4,
+        Accept = -3,
+        Reject = -2,
+        None = -1,
+    }
+
+    public enum GtkFileChooserAction
+    {
+        Open,
+        Save,
+        SelectFolder,
+        CreateFolder,
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct GdkGeometry
+    {
+        gint min_width;
+        gint min_height;
+        gint max_width;
+        gint max_height;
+        gint base_width;
+        gint base_height;
+        gint width_inc;
+        gint height_inc;
+        gdouble min_aspect;
+        gdouble max_aspect;
+        gint win_gravity;
+    }
+
+    enum GdkWindowHints
+    {
+        GDK_HINT_POS = 1 << 0,
+        GDK_HINT_MIN_SIZE = 1 << 1,
+        GDK_HINT_MAX_SIZE = 1 << 2,
+        GDK_HINT_BASE_SIZE = 1 << 3,
+        GDK_HINT_ASPECT = 1 << 4,
+        GDK_HINT_RESIZE_INC = 1 << 5,
+        GDK_HINT_WIN_GRAVITY = 1 << 6,
+        GDK_HINT_USER_POS = 1 << 7,
+        GDK_HINT_USER_SIZE = 1 << 8
+    }
+}

+ 24 - 0
src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+    public class NativeException : Exception
+    {
+        public NativeException()
+        {
+        }
+
+        public NativeException(string message) : base(message)
+        {
+        }
+
+        public NativeException(string message, Exception inner) : base(message, inner)
+        {
+        }
+        
+    }
+}

+ 68 - 0
src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3.Interop
+{
+    internal class Pixbuf : GObject, IWindowIconImpl
+    {
+        Pixbuf(IntPtr handle) : base(handle)
+        {
+            
+        }
+
+        public static Pixbuf NewFromFile(string filename)
+        {
+            using (var ub = new Utf8Buffer(filename))
+            {
+                IntPtr err;
+                var rv = Native.GdkPixbufNewFromFile(ub, out err);
+                if(rv != IntPtr.Zero)
+                    return new Pixbuf(rv);
+                throw new GException(err);
+            }
+        }
+
+        public static unsafe Pixbuf NewFromBytes(byte[] data)
+        {
+            fixed (void* bytes = data)
+            {
+                using (var stream = Native.GMemoryInputStreamNewFromData(new IntPtr(bytes), new IntPtr(data.Length), IntPtr.Zero))
+                {
+                    IntPtr err;
+                    var rv = Native.GdkPixbufNewFromStream(stream, IntPtr.Zero, out err);
+                    if (rv != IntPtr.Zero)
+                        return new Pixbuf(rv);
+                    throw new GException(err);
+                }
+            }
+        }
+
+        public static Pixbuf NewFromStream(Stream s)
+        {
+            if (s is MemoryStream)
+                return NewFromBytes(((MemoryStream) s).ToArray());
+            var ms = new MemoryStream();
+            s.CopyTo(ms);
+            return NewFromBytes(ms.ToArray());
+        }
+
+        public void Save(Stream outputStream)
+        {
+            IntPtr buffer, bufferLen, error;
+            using (var png = new Utf8Buffer("png"))
+                if (!Native.GdkPixbufSaveToBufferv(this, out buffer, out bufferLen, png,
+                    IntPtr.Zero, IntPtr.Zero, out error))
+                    throw new GException(error);
+            var data = new byte[bufferLen.ToInt32()];
+            Marshal.Copy(buffer, data, 0, bufferLen.ToInt32());
+            Native.GFree(buffer);
+            outputStream.Write(data, 0, data.Length);
+        }
+    }
+}

+ 155 - 0
src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs

@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3.Interop
+{
+    internal class GtkImportAttribute : Attribute
+    {
+        public GtkDll Dll { get; set; }
+        public string Name { get; set; }
+        public bool Optional { get; set; }
+
+        public GtkImportAttribute(GtkDll dll, string name = null, bool optional = false)
+        {
+            Dll = dll;
+            Name = name;
+            Optional = optional;
+        }
+    }
+
+    public enum GtkDll
+    {
+        Gdk,
+        Gtk,
+        Glib,
+        Gio,
+        Gobject,
+        Cairo,
+        GdkPixBuf
+    }
+
+    static class Resolver
+    {
+        private static Lazy<OperatingSystemType> Platform =
+            new Lazy<OperatingSystemType>(
+                () => AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetRuntimeInfo().OperatingSystem);
+
+        public static ICustomGtk3NativeLibraryResolver Custom { get; set; }
+
+
+        static string FormatName(string name, int version = 0)
+        {
+            if (Platform.Value == OperatingSystemType.WinNT)
+                return "lib" + name + "-" + version + ".dll";
+            if (Platform.Value == OperatingSystemType.Linux)
+                return "lib" + name + ".so" + "." + version;
+            if (Platform.Value == OperatingSystemType.OSX)
+                return "lib" + name + "." + version + ".dylib";
+            throw new Exception("Unknown platform, use custom name resolver");
+        }
+
+        
+
+        static string GetDllName(GtkDll dll)
+        {
+            var name = Custom?.GetName(dll);
+            if (name != null)
+                return name;
+
+            switch (dll)
+            {
+                case GtkDll.Cairo:
+                    return FormatName("cairo", 2);
+                case GtkDll.Gdk:
+                    return FormatName("gdk-3");
+                case GtkDll.Glib:
+                    return FormatName("glib-2.0");
+                case GtkDll.Gio:
+                    return FormatName("gio-2.0");
+                case GtkDll.Gtk:
+                    return FormatName("gtk-3");
+                case GtkDll.Gobject:
+                    return FormatName("gobject-2.0");
+                case GtkDll.GdkPixBuf:
+                    return FormatName("gdk_pixbuf-2.0");
+                default:
+                    throw new ArgumentException("Unknown lib: " + dll);
+            }
+        }
+
+        static IntPtr LoadDll(IDynLoader  loader, GtkDll dll)
+        {
+            
+            var exceptions = new List<Exception>();
+
+            var name = GetDllName(dll);
+            if (Custom?.TrySystemFirst != false)
+            {
+                try
+                {
+                    return loader.LoadLibrary(name);
+                }
+                catch (Exception e)
+                {
+                    exceptions.Add(e);
+                }
+            }
+            var path = Custom?.Lookup(dll);
+            if (path == null && Custom?.BasePath != null)
+                path = Path.Combine(Custom.BasePath, name);
+
+            try
+            {
+                return loader.LoadLibrary(path);
+            }
+            catch (Exception e)
+            {
+                exceptions.Add(e);
+            }
+            throw new AggregateException("Unable to load " + dll, exceptions);
+        }
+
+        public static void Resolve(string basePath = null)
+        {
+            var loader = Platform.Value == OperatingSystemType.WinNT ? (IDynLoader)new Win32Loader() : new UnixLoader();
+
+            var dlls = Enum.GetValues(typeof(GtkDll)).Cast<GtkDll>().ToDictionary(x => x, x => LoadDll(loader, x));
+            
+            foreach (var fieldInfo in typeof(Native).GetTypeInfo().DeclaredFields)
+            {
+                var import = fieldInfo.FieldType.GetTypeInfo().GetCustomAttributes(typeof(GtkImportAttribute), true).Cast<GtkImportAttribute>().FirstOrDefault();
+                if(import == null)
+                    continue;
+                IntPtr lib = dlls[import.Dll];
+                
+                var funcPtr = loader.GetProcAddress(lib, import.Name ?? fieldInfo.FieldType.Name);
+                fieldInfo.SetValue(null, Marshal.GetDelegateForFunctionPointer(funcPtr, fieldInfo.FieldType));
+            }
+
+            var nativeHandleNames = new[] { "gdk_win32_window_get_handle", "gdk_x11_window_get_xid", "gdk_quartz_window_get_nswindow" };
+            foreach (var name in nativeHandleNames)
+            {
+                try
+                {
+                    Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle)Marshal
+                        .GetDelegateForFunctionPointer(loader.GetProcAddress(dlls[GtkDll.Gdk], name), typeof(Native.D.gdk_get_native_handle));
+                    break;
+                }
+                catch { }
+            }
+            if (Native.GetNativeGdkWindowHandle == null)
+                throw new Exception($"Unable to locate any of [{string.Join(", ", nativeHandleNames)}] in libgdk");
+
+        }
+
+
+    }
+}
+

+ 50 - 0
src/Gtk/Avalonia.Gtk3/Interop/Signal.cs

@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Avalonia.Gtk3.Interop
+{
+    class Signal
+    {
+        class ConnectedSignal : IDisposable
+        {
+            private readonly GObject _instance;
+            private GCHandle _handle;
+            private readonly ulong _id;
+
+            public ConnectedSignal(GObject instance, GCHandle handle, ulong id)
+            {
+                _instance = instance;
+                Native.GObjectRef(instance);
+                _handle = handle;
+                _id = id;
+            }
+
+            public void Dispose()
+            {
+                if (_handle.IsAllocated)
+                {
+                    Native.GObjectUnref(_instance.DangerousGetHandle());
+                    Native.GSignalHandlerDisconnect(_instance, _id);
+                    _handle.Free();
+                }
+            }
+        }
+
+        public static IDisposable Connect<T>(GObject obj, string name, T handler) 
+        {
+            var handle = GCHandle.Alloc(handler);
+            var ptr = Marshal.GetFunctionPointerForDelegate((Delegate)(object)handler);
+            using (var utf = new Utf8Buffer(name))
+            {
+                var id = Native.GSignalConnectObject(obj, utf, ptr, IntPtr.Zero, 0);
+                if (id == 0)
+                    throw new ArgumentException("Unable to connect to signal " + name);
+                return new ConnectedSignal(obj, handle, id);
+            }
+        }
+    }
+}

+ 45 - 0
src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace Avalonia.Gtk3.Interop
+{
+    class Utf8Buffer : SafeHandle
+    {
+        private GCHandle _gchandle;
+        private byte[] _data;
+            
+        public Utf8Buffer(string s) : base(IntPtr.Zero, true)
+        {
+            _data = Encoding.UTF8.GetBytes(s);
+            _gchandle = GCHandle.Alloc(_data, GCHandleType.Pinned);
+            handle = _gchandle.AddrOfPinnedObject();
+        }
+
+        public int ByteLen => _data.Length;
+
+        protected override bool ReleaseHandle()
+        {
+            if (handle != IntPtr.Zero)
+            {
+                handle = IntPtr.Zero;
+                _data = null;
+                _gchandle.Free();
+            }
+            return true;
+        }
+
+        public override bool IsInvalid => handle == IntPtr.Zero;
+
+        public static unsafe string StringFromPtr(IntPtr s)
+        {
+            var pstr = (byte*)s;
+            int len;
+            for (len = 0; pstr[len] != 0; len++) ;
+            var bytes = new byte[len];
+            Marshal.Copy(s, bytes, 0, len);
+
+            return Encoding.UTF8.GetString(bytes, 0, len);
+        }
+    }
+}

+ 20 - 0
src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs

@@ -0,0 +1,20 @@
+using System.IO;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+    class PlatformIconLoader : IPlatformIconLoader
+    {
+        public IWindowIconImpl LoadIcon(string fileName) => Pixbuf.NewFromFile(fileName);
+
+        public IWindowIconImpl LoadIcon(Stream stream) => Pixbuf.NewFromStream(stream);
+
+        public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
+        {
+            var ms = new MemoryStream();
+            bitmap.Save(ms);
+            return Pixbuf.NewFromBytes(ms.ToArray());
+        }
+    }
+}

+ 24 - 0
src/Gtk/Avalonia.Gtk3/PopupImpl.cs

@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+    class PopupImpl : TopLevelImpl, IPopupImpl
+    {
+        static GtkWindow CreateWindow()
+        {
+            var window = Native.GtkWindowNew(GtkWindowType.Popup);
+            return window;
+        }
+
+        public PopupImpl() : base(CreateWindow())
+        {
+        }
+    }
+}

+ 5 - 5
src/Skia/Avalonia.Skia.Android.TestApp/Properties/AssemblyInfo.cs → src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs

@@ -1,20 +1,20 @@
+using System.Resources;
 using System.Reflection;
 using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices;
-using Android.App;
 
 
 // General Information about an assembly is controlled through the following 
 // General Information about an assembly is controlled through the following 
 // set of attributes. Change these attribute values to modify the information
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
 // associated with an assembly.
-[assembly: AssemblyTitle("Avalonia.Skia.Android.TestApp")]
+[assembly: AssemblyTitle("Avalonia.Gtk3")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("Avalonia.Skia.Android.TestApp")]
-[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyProduct("Avalonia.Gtk3")]
+[assembly: AssemblyCopyright("Copyright ©  2016")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 [assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
+[assembly: NeutralResourcesLanguage("en")]
 
 
 // Version information for an assembly consists of the following four values:
 // Version information for an assembly consists of the following four values:
 //
 //

+ 8 - 0
src/Gtk/Avalonia.Gtk3/README.md

@@ -0,0 +1,8 @@
+P/Invoke based GTK3 backend
+===========================
+
+Code is EXPERIMENTAL at this point. It also needs Direct2D/Skia for rendering.
+
+Windows GTK3 binaries aren't included in the repo, you need to download them from https://sourceforge.net/projects/gtk3win/
+
+On Linux it should work out of the box with system-provided GTK3. On OSX you should be able to wire GTK3 using DYLD_LIBRARY_PATH environment variable.

+ 92 - 0
src/Gtk/Avalonia.Gtk3/SystemDialogs.cs

@@ -0,0 +1,92 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Controls;
+using Avalonia.Controls.Platform;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input.Platform;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+    class SystemDialog : ISystemDialogImpl
+    {
+
+        unsafe static Task<string[]> ShowDialog(string title, GtkWindow parent, GtkFileChooserAction action,
+            bool multiselect, string initialFileName)
+        {
+            GtkFileChooser dlg;
+            using (var name = title != null ? new Utf8Buffer(title) : null)
+                dlg = Native.GtkFileChooserDialogNew(name, parent, action, IntPtr.Zero);
+            if (multiselect)
+                Native.GtkFileChooserSetSelectMultiple(dlg, true);
+
+            Native.GtkWindowSetModal(dlg, true);
+            var tcs = new TaskCompletionSource<string[]>();
+            List<IDisposable> disposables = null;
+            Action dispose = () =>
+            {
+                foreach (var d in disposables)
+                    d.Dispose();
+                disposables.Clear();
+            };
+            disposables = new List<IDisposable>
+            {
+                Signal.Connect<Native.D.signal_generic>(dlg, "close", delegate
+                {
+                    tcs.TrySetResult(null);
+                    dispose();
+                    return false;
+                }),
+                Signal.Connect<Native.D.signal_dialog_response>(dlg, "response", (_, resp, __)=>
+                {
+                    string[] result = null;
+                    if (resp == GtkResponseType.Accept)
+                    {
+                        var rlst = new List<string>();
+                        var gs = Native.GtkFileChooserGetFilenames(dlg);
+                        var cgs = gs;
+                        while (cgs != null)
+                        {
+                            if (cgs->Data != IntPtr.Zero)
+                                rlst.Add(Utf8Buffer.StringFromPtr(cgs->Data));
+                            cgs = cgs->Next;
+                        }
+                        Native.GSlistFree(gs);
+                        result = rlst.ToArray();
+                    }
+                    Native.GtkWidgetHide(dlg);
+                    dispose();
+                    tcs.TrySetResult(result);
+                    return false;
+                }),
+                dlg
+            };
+            using (var open = new Utf8Buffer("Open"))
+                Native.GtkDialogAddButton(dlg, open, GtkResponseType.Accept);
+            using (var open = new Utf8Buffer("Cancel"))
+                Native.GtkDialogAddButton(dlg, open, GtkResponseType.Cancel);
+            if(initialFileName!=null)
+                using (var fn = new Utf8Buffer(initialFileName))
+                    Native.GtkFileChooserSetFilename(dlg, fn);
+            Native.GtkWindowPresent(dlg);
+            return tcs.Task;
+        }
+
+        public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
+        {
+            return ShowDialog(dialog.Title, ((TopLevelImpl) parent)?.GtkWidget,
+                dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
+                (dialog as OpenFileDialog)?.AllowMultiple ?? false, dialog.InitialFileName);
+        }
+
+        public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
+        {
+            var res = await ShowDialog(dialog.Title, ((TopLevelImpl) parent)?.GtkWidget,
+                GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory);
+            return res?.FirstOrDefault();
+        }
+    }
+}

+ 336 - 0
src/Gtk/Avalonia.Gtk3/TopLevelImpl.cs

@@ -0,0 +1,336 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using Avalonia.Controls;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+    abstract class TopLevelImpl : ITopLevelImpl, IPlatformHandle
+    {
+        public readonly GtkWindow GtkWidget;
+        private IInputRoot _inputRoot;
+        private readonly GtkImContext _imContext;
+        private readonly FramebufferManager _framebuffer;
+        protected readonly List<IDisposable> Disposables = new List<IDisposable>();
+        private Size _lastSize;
+        private Point _lastPosition;
+        private uint _lastKbdEvent;
+        private uint _lastSmoothScrollEvent;
+
+        public TopLevelImpl(GtkWindow gtkWidget)
+        {
+            
+            GtkWidget = gtkWidget;
+            Disposables.Add(gtkWidget);
+            _framebuffer = new FramebufferManager(this);
+            _imContext = Native.GtkImMulticontextNew();
+            Disposables.Add(_imContext);
+            Native.GtkWidgetSetEvents(gtkWidget, 0xFFFFFE);
+            Disposables.Add(Signal.Connect<Native.D.signal_commit>(_imContext, "commit", OnCommit));
+            Connect<Native.D.signal_widget_draw>("draw", OnDraw);
+            Connect<Native.D.signal_generic>("realize", OnRealized);
+            ConnectEvent("configure-event", OnConfigured);
+            ConnectEvent("button-press-event", OnButton);
+            ConnectEvent("button-release-event", OnButton);
+            ConnectEvent("motion-notify-event", OnMotion);
+            ConnectEvent("scroll-event", OnScroll);
+            ConnectEvent("window-state-event", OnStateChanged);
+            ConnectEvent("key-press-event", OnKeyEvent);
+            ConnectEvent("key-release-event", OnKeyEvent);
+            Connect<Native.D.signal_generic>("destroy", OnDestroy);
+            Native.GtkWidgetRealize(gtkWidget);
+            _lastSize = ClientSize;
+        }
+
+        private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata)
+        {
+            var size = ClientSize;
+            if (_lastSize != size)
+            {
+                Resized?.Invoke(size);
+                _lastSize = size;
+            }
+            var pos = Position;
+            if (_lastPosition != pos)
+            {
+                PositionChanged?.Invoke(pos);
+                _lastPosition = pos;
+            }
+
+            return false;
+        }
+
+        private bool OnRealized(IntPtr gtkwidget, IntPtr userdata)
+        {
+            Native.GtkImContextSetClientWindow(_imContext, Native.GtkWidgetGetWindow(GtkWidget));
+            return false;
+        }
+
+        private bool OnDestroy(IntPtr gtkwidget, IntPtr userdata)
+        {
+            Dispose();
+            return false;
+        }
+
+        private static InputModifiers GetModifierKeys(GdkModifierType state)
+        {
+            var rv = InputModifiers.None;
+            if (state.HasFlag(GdkModifierType.ControlMask))
+                rv |= InputModifiers.Control;
+            if (state.HasFlag(GdkModifierType.ShiftMask))
+                rv |= InputModifiers.Shift;
+            if (state.HasFlag(GdkModifierType.Mod1Mask))
+                rv |= InputModifiers.Control;
+            if (state.HasFlag(GdkModifierType.Button1Mask))
+                rv |= InputModifiers.LeftMouseButton;
+            if (state.HasFlag(GdkModifierType.Button2Mask))
+                rv |= InputModifiers.RightMouseButton;
+            if (state.HasFlag(GdkModifierType.Button3Mask))
+                rv |= InputModifiers.MiddleMouseButton;
+            return rv;
+        }
+
+        private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
+        {
+            var evnt = (GdkEventButton*)ev;
+            var e = new RawMouseEventArgs(
+                Gtk3Platform.Mouse,
+                evnt->time,
+                _inputRoot,
+                evnt->type == GdkEventType.ButtonRelease
+                    ? evnt->button == 1
+                        ? RawMouseEventType.LeftButtonUp
+                        : evnt->button == 3 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp
+                    : evnt->button == 1
+                        ? RawMouseEventType.LeftButtonDown
+                        : evnt->button == 3 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown,
+                new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state));
+            Input?.Invoke(e);
+            return true;
+        }
+
+        protected virtual unsafe bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
+        {
+            var ev = (GdkEventWindowState*) pev;
+            if (ev->changed_mask.HasFlag(GdkWindowState.Focused))
+            {
+                if(ev->new_window_state.HasFlag(GdkWindowState.Focused))
+                    Activated?.Invoke();
+                else
+                    Deactivated?.Invoke();
+            }
+            return true;
+        }
+
+        private unsafe bool OnMotion(IntPtr w, IntPtr ev, IntPtr userdata)
+        {
+            var evnt = (GdkEventMotion*)ev;
+            var position = new Point(evnt->x, evnt->y);
+            Native.GdkEventRequestMotions(ev);
+            var e = new RawMouseEventArgs(
+                Gtk3Platform.Mouse,
+                evnt->time,
+                _inputRoot,
+                RawMouseEventType.Move,
+                position, GetModifierKeys(evnt->state));
+            Input(e);
+            
+            return true;
+        }
+        private unsafe bool OnScroll(IntPtr w, IntPtr ev, IntPtr userdata)
+        {
+            var evnt = (GdkEventScroll*)ev;
+
+            //Ignore duplicates
+            if (evnt->time - _lastSmoothScrollEvent < 10 && evnt->direction != GdkScrollDirection.Smooth)
+                return true;
+
+            var delta = new Vector();
+            const double step = (double) 1;
+            if (evnt->direction == GdkScrollDirection.Down)
+                delta = new Vector(0, -step);
+            else if (evnt->direction == GdkScrollDirection.Up)
+                delta = new Vector(0, step);
+            else if (evnt->direction == GdkScrollDirection.Right)
+                delta = new Vector(-step, 0);
+            else if (evnt->direction == GdkScrollDirection.Left)
+                delta = new Vector(step, 0);
+            else if (evnt->direction == GdkScrollDirection.Smooth)
+            {
+                delta = new Vector(-evnt->delta_x, -evnt->delta_y);
+                _lastSmoothScrollEvent = evnt->time;
+            }
+            var e = new RawMouseWheelEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot,
+                new Point(evnt->x, evnt->y), delta, GetModifierKeys(evnt->state));
+            Input(e);
+            return true;
+        }
+
+        private unsafe bool OnKeyEvent(IntPtr w, IntPtr pev, IntPtr userData)
+        {
+            var evnt = (GdkEventKey*) pev;
+            _lastKbdEvent = evnt->time;
+            if (Native.GtkImContextFilterKeypress(_imContext, pev))
+                return true;
+            var e = new RawKeyEventArgs(
+                Gtk3Platform.Keyboard,
+                evnt->time,
+                evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
+                Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state));
+            Input(e);
+            return true;
+        }
+
+        private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
+        {
+            Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
+            return true;
+        }
+
+        void ConnectEvent(string name, Native.D.signal_onevent handler) 
+            => Disposables.Add(Signal.Connect<Native.D.signal_onevent>(GtkWidget, name, handler));
+        void Connect<T>(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
+
+        internal IntPtr CurrentCairoContext { get; private set; }
+
+        private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata)
+        {
+            CurrentCairoContext = cairocontext;
+            Paint?.Invoke(new Rect(ClientSize));
+            CurrentCairoContext = IntPtr.Zero;
+            return true;
+        }
+
+        public void Dispose()
+        {
+            //We are calling it here, since signal handler will be detached
+            if (!GtkWidget.IsClosed)
+                Closed?.Invoke();
+            foreach(var d in Disposables.AsEnumerable().Reverse())
+                d.Dispose();
+            Disposables.Clear();
+        }
+
+        public Size MaxClientSize
+        {
+            get
+            {
+                var s = Native.GtkWidgetGetScreen(GtkWidget);
+                return new Size(Native.GdkScreenGetWidth(s), Native.GdkScreenGetHeight(s));
+            }
+        }
+
+
+        public double Scaling => 1; //TODO: Implement scaling
+        public IPlatformHandle Handle => this;
+
+        string IPlatformHandle.HandleDescriptor => "HWND";
+
+        public Action Activated { get; set; }
+        public Action Closed { get; set; }
+        public Action Deactivated { get; set; }
+        public Action<RawInputEventArgs> Input { get; set; }
+        public Action<Rect> Paint { get; set; }
+        public Action<Size> Resized { get; set; }
+        public Action<double> ScalingChanged { get; set; } //TODO
+        public Action<Point> PositionChanged { get; set; }
+
+        public void Activate() => Native.GtkWidgetActivate(GtkWidget);
+
+        public void Invalidate(Rect rect)
+        {
+            if(GtkWidget.IsClosed)
+                return;
+            Native.GtkWidgetQueueDrawArea(GtkWidget, (int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
+        }
+
+        public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
+
+        public Point PointToClient(Point point)
+        {
+            int x, y;
+            Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+
+            return new Point(point.X - x, point.Y - y);
+        }
+
+        public Point PointToScreen(Point point)
+        {
+            int x, y;
+            Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
+            return new Point(point.X + x, point.Y + y);
+        }
+
+        public void SetCursor(IPlatformHandle cursor)
+        {
+            if (GtkWidget.IsClosed)
+                return;
+            Native.GdkWindowSetCursor(Native.GtkWidgetGetWindow(GtkWidget), cursor?.Handle ??  IntPtr.Zero);
+        }
+
+        public void Show() => Native.GtkWindowPresent(GtkWidget);
+
+        public void Hide() => Native.GtkWidgetHide(GtkWidget);
+
+        void GetGlobalPointer(out int x, out int y)
+        {
+            int mask;
+            Native.GdkWindowGetPointer(Native.GdkScreenGetRootWindow(Native.GtkWidgetGetScreen(GtkWidget)),
+                out x, out y, out mask);
+        }
+
+        public void BeginMoveDrag()
+        {
+            int x, y;
+            GetGlobalPointer(out x, out y);
+            Native.GdkWindowBeginMoveDrag(Native.GtkWidgetGetWindow(GtkWidget), 1, x, y, 0);
+        }
+
+        public void BeginResizeDrag(WindowEdge edge)
+        {
+            int x, y;
+            GetGlobalPointer(out x, out y);
+            Native.GdkWindowBeginResizeDrag(Native.GtkWidgetGetWindow(GtkWidget), edge, 1, x, y, 0);
+        }
+
+
+        public Size ClientSize
+        {
+            get
+            {
+                if (GtkWidget.IsClosed)
+                    return new Size();
+                int w, h;
+                Native.GtkWindowGetSize(GtkWidget, out w, out h);
+                return new Size(w, h);
+            }
+            set
+            {
+                if (GtkWidget.IsClosed)
+                    return;
+                Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height);
+            }
+        }
+
+        public Point Position
+        {
+            get
+            {
+                int x, y;
+                Native.GtkWindowGetPosition(GtkWidget, out x, out y);
+                return new Point(x, y);
+            }
+            set { Native.GtkWindowMove(GtkWidget, (int)value.X, (int)value.Y); }
+        }
+
+        IntPtr IPlatformHandle.Handle => Native.GetNativeGdkWindowHandle(Native.GtkWidgetGetWindow(GtkWidget));
+        public IEnumerable<object> Surfaces => new object[] {Handle, _framebuffer};
+    }
+}

+ 45 - 0
src/Gtk/Avalonia.Gtk3/WindowImpl.cs

@@ -0,0 +1,45 @@
+using System;
+using Avalonia.Controls;
+using Avalonia.Gtk3.Interop;
+using Avalonia.Platform;
+
+namespace Avalonia.Gtk3
+{
+    class WindowImpl : TopLevelImpl, IWindowImpl
+    {
+        public WindowState WindowState { get; set; } //STUB
+        public void SetTitle(string title)
+        {
+            using (var t = new Utf8Buffer(title))
+                Native.GtkWindowSetTitle(GtkWidget, t);
+        }
+
+        class EmptyDisposable : IDisposable
+        {
+            public void Dispose()
+            {
+                
+            }
+        }
+
+        public IDisposable ShowDialog()
+        {
+            Native.GtkWindowSetModal(GtkWidget, true);
+            Show();
+            return new EmptyDisposable();
+        }
+
+        public void SetSystemDecorations(bool enabled) => Native.GtkWindowSetDecorated(GtkWidget, enabled);
+
+        public void SetIcon(IWindowIconImpl icon) => Native.GtkWindowSetIcon(GtkWidget, (Pixbuf) icon);
+
+        public WindowImpl() : base(Native.GtkWindowNew(GtkWindowType.TopLevel))
+        {
+        }
+
+        public void SetCoverTaskbarWhenMaximized(bool enable)
+        {
+            //Why do we even have that?
+        }
+    }
+}

+ 10 - 0
src/Gtk/Avalonia.Gtk3/project.json

@@ -0,0 +1,10 @@
+{
+  "supports": {},
+  "dependencies": {
+    "Microsoft.NETCore.Portable.Compatibility": "1.0.1",
+    "NETStandard.Library": "1.6.0"
+  },
+  "frameworks": {
+    "netstandard1.1": {}
+  }
+}

+ 2 - 3
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@@ -322,9 +322,8 @@
     </ProjectReference>
     </ProjectReference>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
-    <Reference Include="Sprache, Version=2.0.0.51, Culture=neutral, processorArchitecture=MSIL">
-      <HintPath>..\..\..\packages\Sprache.2.0.0.51\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid+Xamarin.iOS10+MonoTouch\Sprache.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="Sprache, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\Sprache.2.1.0\lib\netstandard1.0\Sprache.dll</HintPath>
     </Reference>
     </Reference>
     <Reference Include="System.Reactive.Core, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
     <Reference Include="System.Reactive.Core, Version=3.0.0.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL">
       <HintPath>..\..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll</HintPath>
       <HintPath>..\..\..\packages\System.Reactive.Core.3.0.0\lib\netstandard1.1\System.Reactive.Core.dll</HintPath>

+ 5 - 1
src/Markup/Avalonia.Markup.Xaml/packages.config

@@ -1,9 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
 <packages>
-  <package id="Sprache" version="2.0.0.51" targetFramework="portable45-net45+win8" />
+  <package id="Sprache" version="2.1.0" targetFramework="portable45-net45+win8" />
+  <package id="System.Globalization" version="4.0.11" targetFramework="portable45-net45+win8" />
+  <package id="System.Linq" version="4.1.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Core" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Core" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Interfaces" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Interfaces" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Linq" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.Linq" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.PlatformServices" version="3.0.0" targetFramework="portable45-net45+win8" />
   <package id="System.Reactive.PlatformServices" version="3.0.0" targetFramework="portable45-net45+win8" />
+  <package id="System.Runtime" version="4.1.0" targetFramework="portable45-net45+win8" />
+  <package id="System.Text.RegularExpressions" version="4.1.0" targetFramework="portable45-net45+win8" />
 </packages>
 </packages>

+ 4 - 2
src/Shared/PlatformSupport/AssetLoader.cs

@@ -138,7 +138,7 @@ namespace Avalonia.Shared.PlatformSupport
             AssemblyDescriptor rv;
             AssemblyDescriptor rv;
             if (!AssemblyNameCache.TryGetValue(name, out rv))
             if (!AssemblyNameCache.TryGetValue(name, out rv))
             {
             {
-                var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
+                var loadedAssemblies = AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetLoadedAssemblies();
                 var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name);
                 var match = loadedAssemblies.FirstOrDefault(a => a.GetName().Name == name);
                 if (match != null)
                 if (match != null)
                 {
                 {
@@ -148,7 +148,9 @@ namespace Avalonia.Shared.PlatformSupport
                 {
                 {
                     // iOS does not support loading assemblies dynamically!
                     // iOS does not support loading assemblies dynamically!
                     //
                     //
-#if !__IOS__
+#if NETSTANDARD
+                    AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(new AssemblyName(name)));
+#elif !__IOS__
                     AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
                     AssemblyNameCache[name] = rv = new AssemblyDescriptor(Assembly.Load(name));
 #endif
 #endif
                 }
                 }

+ 6 - 3
src/Shared/PlatformSupport/StandardRuntimePlatform.cs

@@ -2,7 +2,6 @@
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
 
 using System;
 using System;
-using System.Reactive.Disposables;
 using System.Reflection;
 using System.Reflection;
 using System.Resources;
 using System.Resources;
 using System.Threading;
 using System.Threading;
@@ -12,12 +11,16 @@ namespace Avalonia.Shared.PlatformSupport
 {
 {
     internal partial class StandardRuntimePlatform : IRuntimePlatform
     internal partial class StandardRuntimePlatform : IRuntimePlatform
     {
     {
+
+#if NETSTANDARD
+        public void PostThreadPoolItem(Action cb) => ThreadPool.QueueUserWorkItem(_ => cb(), null);
+#else
         public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
         public Assembly[] GetLoadedAssemblies() => AppDomain.CurrentDomain.GetAssemblies();
         public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
         public void PostThreadPoolItem(Action cb) => ThreadPool.UnsafeQueueUserWorkItem(_ => cb(), null);
+#endif
         public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
         public IDisposable StartSystemTimer(TimeSpan interval, Action tick)
         {
         {
-            var timer = new Timer(_ => tick(), null, interval, interval);
-            return Disposable.Create(() => timer.Dispose());
+            return new Timer(_ => tick(), null, interval, interval);
         }
         }
 
 
 
 

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini