Przeglądaj źródła

Merge branch 'master' into master

Steven Kirk 5 lat temu
rodzic
commit
224c11d817
87 zmienionych plików z 2920 dodań i 1353 usunięć
  1. 1 1
      NuGet.Config
  2. 1 1
      build/ApiDiff.props
  3. 4 4
      build/MicroCom.targets
  4. 1 1
      build/Rx.props
  5. 9 9
      nukebuild/Build.cs
  6. 1 1
      nukebuild/_build.csproj
  7. 1 0
      samples/Sandbox/MainWindow.axaml.cs
  8. 34 0
      src/Avalonia.Base/Data/Core/TypeCastNode.cs
  9. 4 1
      src/Avalonia.Base/Utilities/MathUtilities.cs
  10. 4 1
      src/Avalonia.Base/Utilities/StringTokenizer.cs
  11. 24 0
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  12. 3 1
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  13. 17 15
      src/Avalonia.Controls/ComboBox.cs
  14. 6 3
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  15. 15 13
      src/Avalonia.Controls/Templates/DataTemplateExtensions.cs
  16. 1 1
      src/Avalonia.MicroCom/MicroComProxyBase.cs
  17. 26 2
      src/Avalonia.MicroCom/MicroComRuntime.cs
  18. 8 0
      src/Avalonia.OpenGL/Egl/EglContext.cs
  19. 28 20
      src/Avalonia.Styling/StyledElement.cs
  20. 8 1
      src/Avalonia.Visuals/CornerRadius.cs
  21. 4 1
      src/Avalonia.Visuals/Matrix.cs
  22. 8 1
      src/Avalonia.Visuals/Point.cs
  23. 64 15
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  24. 7 0
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  25. 6 3
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs
  26. 8 1
      src/Avalonia.Visuals/Size.cs
  27. 8 1
      src/Avalonia.Visuals/Thickness.cs
  28. 8 1
      src/Avalonia.Visuals/Vector.cs
  29. 17 20
      src/Avalonia.Visuals/Visual.cs
  30. 9 1
      src/Avalonia.X11/X11Window.cs
  31. 1 0
      src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj
  32. 39 0
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs
  33. 54 0
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs
  34. 99 14
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs
  35. 37 0
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs
  36. 29 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs
  37. 1 1
      src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
  38. 1 0
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  39. 2 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs
  40. 51 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs
  41. 18 0
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/StrongTypeCastNode.cs
  42. 85 6
      src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
  43. 19 0
      src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs
  44. 7 5
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  45. 2 1
      src/Skia/Avalonia.Skia/PlatformRenderInterface.cs
  46. 4 1
      src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs
  47. 1 0
      src/Windows/Avalonia.Win32/.gitignore
  48. 3 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  49. 0 18
      src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs
  50. 0 171
      src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs
  51. 0 96
      src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs
  52. 0 91
      src/Windows/Avalonia.Win32/Composition/D2DEffects.cs
  53. 0 45
      src/Windows/Avalonia.Win32/Composition/EffectBase.cs
  54. 0 18
      src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs
  55. 0 57
      src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs
  56. 0 8
      src/Windows/Avalonia.Win32/Composition/IBlurHost.cs
  57. 0 152
      src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs
  58. 0 14
      src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs
  59. 0 69
      src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs
  60. 0 139
      src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs
  61. 0 24
      src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs
  62. 0 217
      src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs
  63. 0 35
      src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs
  64. 12 0
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  65. 2 1
      src/Windows/Avalonia.Win32/PopupImpl.cs
  66. 3 7
      src/Windows/Avalonia.Win32/Win32GlManager.cs
  67. 130 0
      src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs
  68. 99 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
  69. 238 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
  70. 135 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
  71. 118 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
  72. 7 0
      src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs
  73. 140 0
      src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
  74. 18 0
      src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs
  75. 38 0
      src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
  76. 89 0
      src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs
  77. 718 0
      src/Windows/Avalonia.Win32/WinRT/winrt.idl
  78. 15 6
      src/Windows/Avalonia.Win32/WindowImpl.cs
  79. 4 3
      src/tools/MicroComGenerator/AstParser.cs
  80. 36 11
      src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
  81. 5 4
      src/tools/MicroComGenerator/CSharpGen.Utils.cs
  82. 26 4
      src/tools/MicroComGenerator/CSharpGen.cs
  83. 1 1
      tests/Avalonia.Benchmarks/NullRenderingPlatform.cs
  84. 1 0
      tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs
  85. 1 1
      tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs
  86. 48 0
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs
  87. 248 10
      tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

+ 1 - 1
NuGet.Config

@@ -4,6 +4,6 @@
   <packageSources>
     <clear />
     <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
-      <add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
+    <add key="dotnet-eng" value="https://nuget.avaloniaui.net/repository/avalonia-devdeps/index.json" protocolVersion="3" />
   </packageSources>
 </configuration>

+ 1 - 1
build/ApiDiff.props

@@ -1,6 +1,6 @@
 <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
-    <ApiContractPackageVersion>0.10.0-preview3</ApiContractPackageVersion>
+    <ApiContractPackageVersion>0.10.0-preview6</ApiContractPackageVersion>
     <NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName>
     <NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName>
   </PropertyGroup>

+ 4 - 4
build/MicroCom.targets

@@ -2,7 +2,7 @@
 
   <!-- Ensure that code generator is actually built -->
   <ItemGroup>
-    <ProjectReference Include="..\tools\MicroComGenerator\MicroComGenerator.csproj">
+    <ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\tools\MicroComGenerator\MicroComGenerator.csproj">
       <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
       <ExcludeAssets>all</ExcludeAssets>
       <SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
@@ -12,10 +12,10 @@
   <Target Name="GenerateAvaloniaNativeComInterop"
           BeforeTargets="CoreCompile"
           DependsOnTargets="ResolveReferences"
-          Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"
+          Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/**/*.cs"
           Outputs="%(AvnComIdl.OutputFile)">
     <Message Importance="high" Text="Generating file %(AvnComIdl.OutputFile) from @(AvnComIdl)" />
-    <Exec Command="dotnet ../tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i @(AvnComIdl) --cs %(AvnComIdl.OutputFile)" LogStandardErrorAsError="true" />
+    <Exec Command="dotnet $(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i @(AvnComIdl) --cs %(AvnComIdl.OutputFile)" LogStandardErrorAsError="true" />
     <ItemGroup>
       <!-- Remove and re-add generated file, this is needed for the clean build -->
       <Compile Remove="%(AvnComIdl.OutputFile)"/>
@@ -24,7 +24,7 @@
   </Target>
   <ItemGroup>
     <UpToDateCheckInput Include="@(AvnComIdl)"/>
-    <UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"/>
+    <UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../src/tools/MicroComGenerator/**/*.cs"/>
   </ItemGroup>
   <PropertyGroup>
     <_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>

+ 1 - 1
build/Rx.props

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

+ 9 - 9
nukebuild/Build.cs

@@ -107,7 +107,7 @@ partial class Build : NukeBuild
                 .AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_8_X64")))
             .AddProperty("PackageVersion", Parameters.Version)
             .AddProperty("iOSRoslynPathHackRequired", true)
-            .SetToolPath(MsBuildExe.Value)
+            .SetProcessToolPath(MsBuildExe.Value)
             .SetConfiguration(Parameters.Configuration)
             .SetVerbosity(MSBuildVerbosity.Minimal)
             .Apply(configurator));
@@ -132,10 +132,10 @@ partial class Build : NukeBuild
             var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
 
             NpmTasks.NpmInstall(c => c
-                .SetWorkingDirectory(webappDir)
-                .SetArgumentConfigurator(a => a.Add("--silent")));
+                .SetProcessWorkingDirectory(webappDir)
+                .SetProcessArgumentConfigurator(a => a.Add("--silent")));
             NpmTasks.NpmRun(c => c
-                .SetWorkingDirectory(webappDir)
+                .SetProcessWorkingDirectory(webappDir)
                 .SetCommand("dist"));
         });
 
@@ -157,7 +157,7 @@ partial class Build : NukeBuild
         {
             if (Parameters.IsRunningOnWindows)
                 MsBuildCommon(Parameters.MSBuildSolution, c => c
-                    .SetArgumentConfigurator(a => a.Add("/r"))
+                    .SetProcessArgumentConfigurator(a => a.Add("/r"))
                     .AddTargets("Build")
                 );
 
@@ -194,7 +194,7 @@ partial class Build : NukeBuild
         var eventsProject = Path.Combine(eventsDirectory, "Avalonia.ReactiveUI.Events.csproj");
         if (Parameters.IsRunningOnWindows)
             MsBuildCommon(eventsProject, c => c
-                .SetArgumentConfigurator(a => a.Add("/r"))
+                .SetProcessArgumentConfigurator(a => a.Add("/r"))
                 .AddTargets("Build")
             );
         else
@@ -242,10 +242,10 @@ partial class Build : NukeBuild
             var webappTestDir = RootDirectory / "tests" / "Avalonia.DesignerSupport.Tests" / "Remote" / "HtmlTransport" / "webapp";
 
             NpmTasks.NpmInstall(c => c
-                .SetWorkingDirectory(webappTestDir)
-                .SetArgumentConfigurator(a => a.Add("--silent")));
+                .SetProcessWorkingDirectory(webappTestDir)
+                .SetProcessArgumentConfigurator(a => a.Add("--silent")));
             NpmTasks.NpmRun(c => c
-                .SetWorkingDirectory(webappTestDir)
+                .SetProcessWorkingDirectory(webappTestDir)
                 .SetCommand("test"));
         });
 

+ 1 - 1
nukebuild/_build.csproj

@@ -10,7 +10,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Nuke.Common" Version="0.24.0" />
+    <PackageReference Include="Nuke.Common" Version="5.0.0" />
     <PackageReference Include="xunit.runner.console" Version="2.3.1" />
     <PackageReference Include="JetBrains.dotMemoryUnit" Version="3.0.20171219.105559" />
     <PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " />

+ 1 - 0
samples/Sandbox/MainWindow.axaml.cs

@@ -1,6 +1,7 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
+using Avalonia.Win32.WinRT.Composition;
 
 namespace Sandbox
 {

+ 34 - 0
src/Avalonia.Base/Data/Core/TypeCastNode.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Avalonia.Data.Core
+{
+    public class TypeCastNode : ExpressionNode
+    {
+        public override string Description => $"as {TargetType.FullName}";
+
+        public Type TargetType { get; }
+
+        public TypeCastNode(Type type)
+        {
+            TargetType = type;
+        }
+
+        protected virtual object Cast(object value)
+        {
+            return TargetType.IsInstanceOfType(value) ? value : null;
+        }
+
+        protected override void StartListeningCore(WeakReference<object> reference)
+        {
+            if (reference.TryGetTarget(out object target))
+            {
+                target = Cast(target);
+                reference = target == null ? NullReference : new WeakReference<object>(target);
+            }
+
+            base.StartListeningCore(reference);
+        }
+    }
+}

+ 4 - 1
src/Avalonia.Base/Utilities/MathUtilities.cs

@@ -5,7 +5,10 @@ namespace Avalonia.Utilities
     /// <summary>
     /// Provides math utilities not provided in System.Math.
     /// </summary>
-    public static class MathUtilities
+#if !BUILDTASK
+    public
+#endif
+    static class MathUtilities
     {
         // smallest such that 1.0+DoubleEpsilon != 1.0
         internal static readonly double DoubleEpsilon = 2.2204460492503131e-016;

+ 4 - 1
src/Avalonia.Base/Utilities/StringTokenizer.cs

@@ -4,7 +4,10 @@ using static System.Char;
 
 namespace Avalonia.Utilities
 {
-    public struct StringTokenizer : IDisposable
+#if !BUILDTASK
+    public
+#endif
+    struct StringTokenizer : IDisposable
     {
         private const char DefaultSeparatorChar = ',';
 

+ 24 - 0
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@@ -45,6 +45,12 @@
       <Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs">
         <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
       </Compile>
+      <Compile Include="../Avalonia.Base/Utilities/StringTokenizer.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Base/Utilities/MathUtilities.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
       <Compile Include="..\Markup\Avalonia.Markup\Markup\Parsers\ArgumentListParser.cs">
         <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
       </Compile>
@@ -57,6 +63,24 @@
       <Compile Include="../Avalonia.Base/Utilities/StyleClassParser.cs">
         <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
       </Compile>
+      <Compile Include="../Avalonia.Visuals/Thickness.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Visuals/Size.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Visuals/Vector.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Visuals/Point.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Visuals/Matrix.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
+      <Compile Include="../Avalonia.Visuals/CornerRadius.cs">
+        <Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
+      </Compile>
       <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" />
       <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
       <PackageReference Include="Mono.Cecil" Version="0.11.2" />

+ 3 - 1
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@@ -46,7 +46,9 @@ namespace Avalonia.Build.Tasks
             string output, bool verifyIl, MessageImportance logImportance, string strongNameKey, bool patchCom,
             bool skipXamlCompilation)
         {
-            var typeSystem = new CecilTypeSystem(references.Concat(new[] { input }), input);
+            var typeSystem = new CecilTypeSystem(references
+                .Where(r => !r.ToLowerInvariant().EndsWith("avalonia.build.tasks.dll"))
+                .Concat(new[] { input }), input);
             
             var asm = typeSystem.TargetAssemblyDefinition;
 

+ 17 - 15
src/Avalonia.Controls/ComboBox.cs

@@ -173,11 +173,10 @@ namespace Avalonia.Controls
                 ComboBoxItem.ContentTemplateProperty);
         }
 
-        /// <inheritdoc/>
-        protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
+        protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
         {
-            base.OnAttachedToLogicalTree(e);
-            this.UpdateSelectionBoxItem(this.SelectedItem);
+            base.OnAttachedToVisualTree(e);
+            this.UpdateSelectionBoxItem(SelectedItem);
         }
 
         /// <inheritdoc/>
@@ -373,19 +372,22 @@ namespace Avalonia.Controls
 
             if (control != null)
             {
-                control.Measure(Size.Infinity);
-
-                SelectionBoxItem = new Rectangle
+                if (VisualRoot is object)
                 {
-                    Width = control.DesiredSize.Width,
-                    Height = control.DesiredSize.Height,
-                    Fill = new VisualBrush
+                    control.Measure(Size.Infinity);
+
+                    SelectionBoxItem = new Rectangle
                     {
-                        Visual = control,
-                        Stretch = Stretch.None,
-                        AlignmentX = AlignmentX.Left,
-                    }
-                };
+                        Width = control.DesiredSize.Width,
+                        Height = control.DesiredSize.Height,
+                        Fill = new VisualBrush
+                        {
+                            Visual = control,
+                            Stretch = Stretch.None,
+                            AlignmentX = AlignmentX.Left,
+                        }
+                    };
+                }
             }
             else
             {

+ 6 - 3
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@@ -354,11 +354,14 @@ namespace Avalonia.Controls.Primitives
         {
             control.SetValue(TemplatedParentProperty, this);
 
-            foreach (var child in control.LogicalChildren)
+            var children = control.LogicalChildren;
+            var count = children.Count;
+
+            for (var i = 0; i < count; i++)
             {
-                if (child is IControl c)
+                if (children[i] is IControl child)
                 {
-                    ApplyTemplatedParent(c);
+                    ApplyTemplatedParent(child);
                 }
             }
         }

+ 15 - 13
src/Avalonia.Controls/Templates/DataTemplateExtensions.cs

@@ -1,6 +1,7 @@
-using System.Linq;
 using Avalonia.LogicalTree;
 
+#nullable enable
+
 namespace Avalonia.Controls.Templates
 {
     /// <summary>
@@ -18,21 +19,23 @@ namespace Avalonia.Controls.Templates
         /// tree are searched.
         /// </param>
         /// <returns>The data template or null if no matching data template was found.</returns>
-        public static IDataTemplate FindDataTemplate(
+        public static IDataTemplate? FindDataTemplate(
             this IControl control,
             object data,
-            IDataTemplate primary = null)
+            IDataTemplate? primary = null)
         {
             if (primary?.Match(data) == true)
             {
                 return primary;
             }
 
-            foreach (var i in control.GetSelfAndLogicalAncestors().OfType<IDataTemplateHost>())
+            var currentTemplateHost = control as ILogical;
+
+            while (currentTemplateHost != null)
             {
-                if (i.IsDataTemplatesInitialized)
+                if (currentTemplateHost is IDataTemplateHost hostCandidate && hostCandidate.IsDataTemplatesInitialized)
                 {
-                    foreach (IDataTemplate dt in i.DataTemplates)
+                    foreach (IDataTemplate dt in hostCandidate.DataTemplates)
                     {
                         if (dt.Match(data))
                         {
@@ -40,20 +43,19 @@ namespace Avalonia.Controls.Templates
                         }
                     }
                 }
+
+                currentTemplateHost = currentTemplateHost.LogicalParent;
             }
 
             IGlobalDataTemplates global = AvaloniaLocator.Current.GetService<IGlobalDataTemplates>();
 
-            if (global != null)
+            if (global != null && global.IsDataTemplatesInitialized)
             {
-                if (global.IsDataTemplatesInitialized)
+                foreach (IDataTemplate dt in global.DataTemplates)
                 {
-                    foreach (IDataTemplate dt in global.DataTemplates)
+                    if (dt.Match(data))
                     {
-                        if (dt.Match(data))
-                        {
-                            return dt;
-                        }
+                        return dt;
                     }
                 }
             }

+ 1 - 1
src/Avalonia.MicroCom/MicroComProxyBase.cs

@@ -56,7 +56,7 @@ namespace Avalonia.MicroCom
         {
             var guid = MicroComRuntime.GetGuidFor(typeof(T));
             var rv = QueryInterface(guid, out var ppv);
-            if (rv != 0)
+            if (rv == 0)
                 return (T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true);
             throw new COMException("QueryInterface failed", rv);
         }

+ 26 - 2
src/Avalonia.MicroCom/MicroComRuntime.cs

@@ -38,13 +38,20 @@ namespace Avalonia.MicroCom
         public static T CreateProxyFor<T>(IntPtr pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
         
         public static object CreateProxyFor(Type type, IntPtr pObject, bool ownsHandle) => _factories[type](pObject, ownsHandle);
-        
+
+        public static IntPtr GetNativeIntPtr<T>(this T obj, bool owned = false) where T : IUnknown
+            => new IntPtr(GetNativePointer(obj, owned));
         public static void* GetNativePointer<T>(T obj, bool owned = false) where T : IUnknown
         {
             if (obj == null)
                 return null;
             if (obj is MicroComProxyBase proxy)
+            {
+                if(owned)
+                    proxy.AddRef();
                 return (void*)proxy.NativePointer;
+            }
+
             if (obj is IMicroComShadowContainer container)
             {
                 container.Shadow ??= new MicroComShadow(container);
@@ -89,10 +96,27 @@ namespace Avalonia.MicroCom
 
         }
 
-        public static T CloneReference<T>(T iface) where T : IUnknown
+        public static T CloneReference<T>(this T iface) where T : IUnknown
         {
+            var proxy = (MicroComProxyBase)(object)iface;
             var ownedPointer = GetNativePointer(iface, true);
             return CreateProxyFor<T>(ownedPointer, true);
         }
+
+        public static T QueryInterface<T>(this IUnknown unknown) where T : IUnknown
+        {
+            var proxy = (MicroComProxyBase)unknown;
+            return proxy.QueryInterface<T>();
+        }
+
+        public static void UnsafeAddRef(this IUnknown unknown)
+        {
+            ((MicroComProxyBase)unknown).AddRef();
+        }
+        
+        public static void UnsafeRelease(this IUnknown unknown)
+        {
+            ((MicroComProxyBase)unknown).Release();
+        }
     }
 }

+ 8 - 0
src/Avalonia.OpenGL/Egl/EglContext.cs

@@ -93,6 +93,14 @@ namespace Avalonia.OpenGL.Egl
             return MakeCurrent();
         }
 
+        public IDisposable EnsureLocked()
+        {
+            if (IsCurrent)
+                return Disposable.Empty;
+            Monitor.Enter(_lock);
+            return Disposable.Create(() => Monitor.Exit(_lock));
+        }
+
         public bool IsSharedWith(IGlContext context)
         {
             var c = (EglContext)context;

+ 28 - 20
src/Avalonia.Styling/StyledElement.cs

@@ -1,8 +1,8 @@
 using System;
+using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Specialized;
 using System.ComponentModel;
-using System.Linq;
 using Avalonia.Animation;
 using Avalonia.Collections;
 using Avalonia.Controls;
@@ -479,16 +479,16 @@ namespace Avalonia
             switch (e.Action)
             {
                 case NotifyCollectionChangedAction.Add:
-                    SetLogicalParent(e.NewItems.Cast<ILogical>());
+                    SetLogicalParent(e.NewItems);
                     break;
 
                 case NotifyCollectionChangedAction.Remove:
-                    ClearLogicalParent(e.OldItems.Cast<ILogical>());
+                    ClearLogicalParent(e.OldItems);
                     break;
 
                 case NotifyCollectionChangedAction.Replace:
-                    ClearLogicalParent(e.OldItems.Cast<ILogical>());
-                    SetLogicalParent(e.NewItems.Cast<ILogical>());
+                    ClearLogicalParent(e.OldItems);
+                    SetLogicalParent(e.NewItems);
                     break;
 
                 case NotifyCollectionChangedAction.Reset:
@@ -702,13 +702,32 @@ namespace Avalonia
             OnDataContextChanged(EventArgs.Empty);
         }
 
-        private void SetLogicalParent(IEnumerable<ILogical> children)
+        private void SetLogicalParent(IList children)
         {
-            foreach (var i in children)
+            var count = children.Count;
+
+            for (var i = 0; i < count; i++)
+            {
+                var logical = (ILogical) children[i];
+                
+                if (logical.LogicalParent is null)
+                {
+                    ((ISetLogicalParent)logical).SetParent(this);
+                }
+            }
+        }
+
+        private void ClearLogicalParent(IList children)
+        {
+            var count = children.Count;
+
+            for (var i = 0; i < count; i++)
             {
-                if (i.LogicalParent == null)
+                var logical = (ILogical) children[i];
+                
+                if (logical.LogicalParent == this)
                 {
-                    ((ISetLogicalParent)i).SetParent(this);
+                    ((ISetLogicalParent)logical).SetParent(null);
                 }
             }
         }
@@ -784,17 +803,6 @@ namespace Avalonia
             }
         }
 
-        private void ClearLogicalParent(IEnumerable<ILogical> children)
-        {
-            foreach (var i in children)
-            {
-                if (i.LogicalParent == this)
-                {
-                    ((ISetLogicalParent)i).SetParent(null);
-                }
-            }
-        }
-
         private void NotifyResourcesChanged(
             ResourcesChangedEventArgs? e = null,
             bool propagate = true)

+ 8 - 1
src/Avalonia.Visuals/CornerRadius.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Globalization;
+#if !BUILDTASK
 using Avalonia.Animation.Animators;
+#endif
 using Avalonia.Utilities;
 
 namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
     /// <summary>
     /// Represents the radii of a rectangle's corners.
     /// </summary>
-    public readonly struct CornerRadius : IEquatable<CornerRadius>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct CornerRadius : IEquatable<CornerRadius>
     {
         static CornerRadius()
         {
+#if !BUILDTASK
             Animation.Animation.RegisterAnimator<CornerRadiusAnimator>(prop => typeof(CornerRadius).IsAssignableFrom(prop.PropertyType));
+#endif
         }
 
         public CornerRadius(double uniformRadius)

+ 4 - 1
src/Avalonia.Visuals/Matrix.cs

@@ -7,7 +7,10 @@ namespace Avalonia
     /// <summary>
     /// A 2x3 matrix.
     /// </summary>
-    public readonly struct Matrix : IEquatable<Matrix>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct Matrix : IEquatable<Matrix>
     {
         private readonly double _m11;
         private readonly double _m12;

+ 8 - 1
src/Avalonia.Visuals/Point.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Globalization;
+#if !BUILDTASK
 using Avalonia.Animation.Animators;
+#endif
 using Avalonia.Utilities;
 
 namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
     /// <summary>
     /// Defines a point.
     /// </summary>
-    public readonly struct Point : IEquatable<Point>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct Point : IEquatable<Point>
     {
         static Point()
         {
+#if !BUILDTASK
             Animation.Animation.RegisterAnimator<PointAnimator>(prop => typeof(Point).IsAssignableFrom(prop.PropertyType));
+#endif
         }
 
         /// <summary>

+ 64 - 15
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -99,6 +99,11 @@ namespace Avalonia.Rendering
         /// </summary>
         public string DebugFramesPath { get; set; }
 
+        /// <summary>
+        /// Forces the renderer to only draw frames on the render thread. Makes Paint to wait until frame is rendered
+        /// </summary>
+        public bool RenderOnlyOnRenderThread { get; set; }
+
         /// <inheritdoc/>
         public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
 
@@ -180,11 +185,44 @@ namespace Avalonia.Rendering
         /// <inheritdoc/>
         public void Paint(Rect rect)
         {
-            var t = (IRenderLoopTask)this;
-            if(t.NeedsUpdate)
-                UpdateScene();
-            if(_scene?.Item != null)
-                Render(true);
+            if (RenderOnlyOnRenderThread)
+            {
+                // Renderer is stopped and doesn't tick on the render thread
+                // This indicates a bug somewhere in our code
+                // (currently happens when a window gets minimized with Show desktop on Windows 10)
+                if(!_running)
+                    return;
+                
+                while (true)
+                {
+                    Scene scene;
+                    bool? updated;
+                    lock (_sceneLock)
+                    {
+                        updated = UpdateScene();
+                        scene = _scene?.Item;
+                    }
+                    
+                    // Renderer is in invalid state, skip drawing
+                    if(updated == null)
+                        return;
+
+                    // Wait for the scene to be rendered or disposed
+                    scene?.Rendered.Wait();
+                    
+                    // That was an up-to-date scene, we can return immediately
+                    if (updated == true)
+                        return;
+                }
+            }
+            else
+            {
+                var t = (IRenderLoopTask)this;
+                if (t.NeedsUpdate)
+                    UpdateScene();
+                if (_scene?.Item != null)
+                    Render(true);
+            }
         }
 
         /// <inheritdoc/>
@@ -270,13 +308,20 @@ namespace Avalonia.Rendering
                         {
                             if (scene?.Item != null)
                             {
-                                var overlay = DrawDirtyRects || DrawFps;
-                                if (DrawDirtyRects)
-                                    _dirtyRectsDisplay.Tick();
-                                if (overlay)
-                                    RenderOverlay(scene.Item, ref context);
-                                if (updated || forceComposite || overlay)
-                                    RenderComposite(scene.Item, ref context);
+                                try
+                                {
+                                    var overlay = DrawDirtyRects || DrawFps;
+                                    if (DrawDirtyRects)
+                                        _dirtyRectsDisplay.Tick();
+                                    if (overlay)
+                                        RenderOverlay(scene.Item, ref context);
+                                    if (updated || forceComposite || overlay)
+                                        RenderComposite(scene.Item, ref context);
+                                }
+                                finally
+                                {
+                                    scene.Item.MarkAsRendered();
+                                }
                             }
                         }
                     }
@@ -559,15 +604,15 @@ namespace Avalonia.Rendering
                 UpdateScene();
         }
         
-        private void UpdateScene()
+        private bool? UpdateScene()
         {
             Dispatcher.UIThread.VerifyAccess();
             lock (_sceneLock)
             {
                 if (_disposed)
-                    return;
+                    return null;
                 if (_scene?.Item.Generation > _lastSceneId)
-                    return;
+                    return false;
             }
             if (_root.IsVisible)
             {
@@ -619,6 +664,8 @@ namespace Avalonia.Rendering
 
                     SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
                 }
+
+                return true;
             }
             else
             {
@@ -628,6 +675,8 @@ namespace Avalonia.Rendering
                     _scene = null;
                     oldScene?.Dispose();
                 }
+
+                return null;
             }
         }
 

+ 7 - 0
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@@ -2,6 +2,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
+using System.Threading.Tasks;
 using Avalonia.Collections.Pooled;
 using Avalonia.VisualTree;
 
@@ -13,6 +14,7 @@ namespace Avalonia.Rendering.SceneGraph
     public class Scene : IDisposable
     {
         private readonly Dictionary<IVisual, IVisualNode> _index;
+        private readonly TaskCompletionSource<bool> _rendered = new TaskCompletionSource<bool>();
 
         /// <summary>
         /// Initializes a new instance of the <see cref="Scene"/> class.
@@ -41,6 +43,8 @@ namespace Avalonia.Rendering.SceneGraph
             root.LayerRoot = root.Visual;
         }
 
+        public Task Rendered => _rendered.Task;
+
         /// <summary>
         /// Gets a value identifying the scene's generation. This is incremented each time the scene is cloned.
         /// </summary>
@@ -97,6 +101,7 @@ namespace Avalonia.Rendering.SceneGraph
 
         public void Dispose()
         {
+            _rendered.TrySetResult(false);
             foreach (var node in _index.Values)
             {
                 node.Dispose();
@@ -340,5 +345,7 @@ namespace Avalonia.Rendering.SceneGraph
                 }
             }
         }
+
+        public void MarkAsRendered() => _rendered.TrySetResult(true);
     }
 }

+ 6 - 3
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@@ -24,7 +24,8 @@ namespace Avalonia.Rendering.SceneGraph
             using (var impl = new DeferredDrawingContextImpl(this, scene.Layers))
             using (var context = new DrawingContext(impl))
             {
-                Update(context, scene, (VisualNode)scene.Root, scene.Root.Visual.Bounds, true);
+                var clip = new Rect(scene.Root.Visual.Bounds.Size);
+                Update(context, scene, (VisualNode)scene.Root, clip, true);
             }
         }
 
@@ -77,7 +78,7 @@ namespace Avalonia.Rendering.SceneGraph
                         using (var impl = new DeferredDrawingContextImpl(this, scene.Layers))
                         using (var context = new DrawingContext(impl))
                         {
-                            var clip = scene.Root.Visual.Bounds;
+                            var clip = new Rect(scene.Root.Visual.Bounds.Size);
 
                             if (node.Parent != null)
                             {
@@ -174,7 +175,9 @@ namespace Avalonia.Rendering.SceneGraph
 
             if (visual.IsVisible)
             {
-                var m = Matrix.CreateTranslation(visual.Bounds.Position);
+                var m = node != scene.Root ? 
+                    Matrix.CreateTranslation(visual.Bounds.Position) :
+                    Matrix.Identity;
 
                 var renderTransform = Matrix.Identity;
 

+ 8 - 1
src/Avalonia.Visuals/Size.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Globalization;
+#if !BUILDTASK
 using Avalonia.Animation.Animators;
+#endif
 using Avalonia.Utilities;
 
 namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
     /// <summary>
     /// Defines a size.
     /// </summary>
-    public readonly struct Size : IEquatable<Size>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct Size : IEquatable<Size>
     {
         static Size()
         {
+#if !BUILDTASK
             Animation.Animation.RegisterAnimator<SizeAnimator>(prop => typeof(Size).IsAssignableFrom(prop.PropertyType));
+#endif
         }
 
         /// <summary>

+ 8 - 1
src/Avalonia.Visuals/Thickness.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Globalization;
+#if !BUILDTASK
 using Avalonia.Animation.Animators;
+#endif
 using Avalonia.Utilities;
 
 namespace Avalonia
@@ -8,11 +10,16 @@ namespace Avalonia
     /// <summary>
     /// Describes the thickness of a frame around a rectangle.
     /// </summary>
-    public readonly struct Thickness : IEquatable<Thickness>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct Thickness : IEquatable<Thickness>
     {
         static Thickness()
         {
+#if !BUILDTASK
             Animation.Animation.RegisterAnimator<ThicknessAnimator>(prop => typeof(Thickness).IsAssignableFrom(prop.PropertyType));
+#endif
         }
 
         /// <summary>

+ 8 - 1
src/Avalonia.Visuals/Vector.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Globalization;
+#if !BUILDTASK
 using Avalonia.Animation.Animators;
+#endif
 using Avalonia.Utilities;
 
 #nullable enable
@@ -10,11 +12,16 @@ namespace Avalonia
     /// <summary>
     /// Defines a vector.
     /// </summary>
-    public readonly struct Vector : IEquatable<Vector>
+#if !BUILDTASK
+    public
+#endif
+    readonly struct Vector : IEquatable<Vector>
     {
         static Vector()
         {
+#if !BUILDTASK
             Animation.Animation.RegisterAnimator<VectorAnimator>(prop => typeof(Vector).IsAssignableFrom(prop.PropertyType));
+#endif
         }
 
         /// <summary>

+ 17 - 20
src/Avalonia.Visuals/Visual.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Collections;
 using System.Collections.Specialized;
 using Avalonia.Collections;
 using Avalonia.Data;
@@ -619,34 +620,30 @@ namespace Avalonia
             switch (e.Action)
             {
                 case NotifyCollectionChangedAction.Add:
-                    foreach (Visual v in e.NewItems)
-                    {
-                        v.SetVisualParent(this);
-                    }
-
+                    SetVisualParent(e.NewItems, this);
                     break;
 
                 case NotifyCollectionChangedAction.Remove:
-                    foreach (Visual v in e.OldItems)
-                    {
-                        v.SetVisualParent(null);
-                    }
-
+                    SetVisualParent(e.OldItems, null);
                     break;
 
                 case NotifyCollectionChangedAction.Replace:
-                    foreach (Visual v in e.OldItems)
-                    {
-                        v.SetVisualParent(null);
-                    }
-
-                    foreach (Visual v in e.NewItems)
-                    {
-                        v.SetVisualParent(this);
-                    }
-
+                    SetVisualParent(e.OldItems, null);
+                    SetVisualParent(e.NewItems, this);
                     break;
             }
         }
+        
+        private static void SetVisualParent(IList children, Visual parent)
+        {
+            var count = children.Count;
+
+            for (var i = 0; i < count; i++)
+            {
+                var visual = (Visual) children[i];
+                
+                visual.SetVisualParent(parent);
+            }
+        }
     }
 }

+ 9 - 1
src/Avalonia.X11/X11Window.cs

@@ -189,6 +189,11 @@ namespace Avalonia.X11
             if (platform.Options.UseDBusMenu)
                 NativeMenuExporter = DBusMenuExporter.TryCreate(_handle);
             NativeControlHost = new X11NativeControlHost(_platform, this);
+            DispatcherTimer.Run(() =>
+            {
+                Paint?.Invoke(default);
+                return _handle != IntPtr.Zero;
+            }, TimeSpan.FromMilliseconds(100));
         }
 
         class SurfaceInfo  : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
@@ -338,7 +343,10 @@ namespace Avalonia.X11
                 return customRendererFactory.Create(root, loop);
             
             return _platform.Options.UseDeferredRendering ?
-                new DeferredRenderer(root, loop) :
+                new DeferredRenderer(root, loop)
+                {
+                    RenderOnlyOnRenderThread = true
+                } :
                 (IRenderer)new X11ImmediateRendererProxy(root, loop);
         }
 

+ 1 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/Avalonia.Markup.Xaml.Loader.csproj

@@ -4,6 +4,7 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <IsPackable>true</IsPackable>
     <PackageId>Avalonia.Markup.Xaml.Loader</PackageId>
+    <DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants>
   </PropertyGroup>
   <Import Project="IncludeXamlIlSre.props" />
   <ItemGroup>

+ 39 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlFontFamilyAstNode.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+    class AvaloniaXamlIlFontFamilyAstNode: XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+    {
+        private readonly AvaloniaXamlIlWellKnownTypes _types;
+        private readonly string _text;
+
+        public IXamlAstTypeReference Type { get; }
+        
+        public AvaloniaXamlIlFontFamilyAstNode(AvaloniaXamlIlWellKnownTypes types,
+            string text,
+            IXamlLineInfo lineInfo) : base(lineInfo)
+        {
+            _types = types;
+            _text = text;
+            Type = new XamlAstClrTypeReference(lineInfo, types.FontFamily, false);
+        }
+        
+        public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
+        {
+            codeGen
+                .Ldloc(context.ContextLocal)
+                .Castclass(context.Configuration.TypeMappings.UriContextProvider)
+                .EmitCall(context.Configuration.TypeMappings.UriContextProvider.FindMethod(
+                    "get_BaseUri", _types.Uri, false))
+                .Ldstr(_text)
+                .Newobj(_types.FontFamilyConstructorUriName);
+            return XamlILNodeEmitResult.Type(0, _types.FontFamily);
+        }
+    }
+}

+ 54 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AstNodes/AvaloniaXamlIlVectorLikeConstantAstNode.cs

@@ -0,0 +1,54 @@
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
+using XamlX;
+using XamlX.Ast;
+using XamlX.Emit;
+using XamlX.IL;
+using XamlX.TypeSystem;
+
+namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes
+{
+    class AvaloniaXamlIlVectorLikeConstantAstNode : XamlAstNode, IXamlAstValueNode, IXamlAstILEmitableNode
+    {
+        private readonly IXamlConstructor _constructor;
+        private readonly double[] _values;
+
+        public AvaloniaXamlIlVectorLikeConstantAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, IXamlType type, IXamlConstructor constructor, double[] values) : base(lineInfo)
+        {
+            var parameters = constructor.Parameters;
+
+            if (parameters.Count != values.Length)
+            {
+                throw new XamlTypeSystemException($"Constructor that takes {values.Length} parameters is expected, got {parameters.Count} instead.");
+            }
+
+            var elementType = types.XamlIlTypes.Double;
+
+            foreach (var parameter in parameters)
+            {
+                if (parameter != elementType)
+                {
+                    throw new XamlTypeSystemException($"Expected parameter of type {elementType}, got {parameter} instead.");
+                }
+            }
+            
+            _constructor = constructor;
+            _values = values;
+            
+            Type = new XamlAstClrTypeReference(lineInfo, type, false);
+        }
+        
+        public IXamlAstTypeReference Type { get; }
+        
+        public XamlILNodeEmitResult Emit(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
+        {
+            foreach (var value in _values)
+            {
+                codeGen.Ldc_R8(value);
+            }
+            
+            codeGen.Newobj(_constructor);
+            
+            return XamlILNodeEmitResult.Type(0, Type.GetClrType());
+        }
+    }
+}

+ 99 - 14
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs

@@ -1,6 +1,8 @@
+using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
+using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.AstNodes;
 using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers;
 using XamlX;
 using XamlX.Ast;
@@ -166,17 +168,101 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
         public static bool CustomValueConverter(AstTransformationContext context,
             IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result)
         {
-            if (type.FullName == "System.TimeSpan" 
-                && node is XamlAstTextNode tn
-                && !tn.Text.Contains(":"))
-            {
-                var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture);
-                result = new XamlStaticOrTargetedReturnMethodCallNode(tn,
-                    type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double),
-                    new[]
-                    {
-                        new XamlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds)
-                    });
+            if (!(node is XamlAstTextNode textNode))
+            {
+                result = null;
+                return false;
+            }
+
+            var text = textNode.Text;
+            
+            var types = context.GetAvaloniaTypes();
+
+            if (type.FullName == "System.TimeSpan")
+            {
+                var tsText = text.Trim();
+
+                if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan))
+                {
+                    // // shorthand seconds format (ie. "0.25")
+                    if (!tsText.Contains(":") && double.TryParse(tsText,
+                        NumberStyles.Float | NumberStyles.AllowThousands,
+                        CultureInfo.InvariantCulture, out var seconds))
+                        timeSpan = TimeSpan.FromSeconds(seconds);
+                    else
+                        throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node);
+                }
+
+
+                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
+                    type.FindMethod("FromTicks", type, false, types.Long),
+                    new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) });
+                return true;
+            }
+
+            if (type.Equals(types.FontFamily))
+            {
+                result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node);
+                return true;
+            }
+            
+            if (type.Equals(types.Thickness))
+            {
+                var thickness = Thickness.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor,
+                    new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom });
+                
+                return true;
+            }
+
+            if (type.Equals(types.Point))
+            {
+                var point = Point.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
+                    new[] { point.X, point.Y });
+                
+                return true;
+            }
+            
+            if (type.Equals(types.Vector))
+            {
+                var vector = Vector.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
+                    new[] { vector.X, vector.Y });
+                
+                return true;
+            }
+            
+            if (type.Equals(types.Size))
+            {
+                var size = Size.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
+                    new[] { size.Width, size.Height });
+                
+                return true;
+            }
+            
+            if (type.Equals(types.Matrix))
+            {
+                var matrix = Matrix.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor,
+                    new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 });
+                
+                return true;
+            }
+            
+            if (type.Equals(types.CornerRadius))
+            {
+                var cornerRadius = CornerRadius.Parse(text);
+
+                result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor,
+                    new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft });
+                
                 return true;
             }
 
@@ -185,9 +271,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
                 var scope = context.ParentNodes().OfType<AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault();
                 if (scope == null)
                     throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node);
-                if (!(node is XamlAstTextNode text))
-                    throw new XamlX.XamlLoadException("Property should be a text node", node);
-                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text.Text, scope.TargetType, text);
+
+                result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node );
                 return true;
             }
 

+ 37 - 0
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXamlIlWellKnownTypes.cs

@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+using System.Linq;
 using XamlX.Emit;
 using XamlX.IL;
 using XamlX.Transform;
@@ -47,6 +49,22 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
         public IXamlType ReflectionBindingExtension { get; }
 
         public IXamlType RelativeSource { get; }
+        public IXamlType Long { get; }
+        public IXamlType Uri { get; }
+        public IXamlType FontFamily { get; }
+        public IXamlConstructor FontFamilyConstructorUriName { get; }
+        public IXamlType Thickness { get; }
+        public IXamlConstructor ThicknessFullConstructor { get; }
+        public IXamlType Point { get; }
+        public IXamlConstructor PointFullConstructor { get; }
+        public IXamlType Vector { get; }
+        public IXamlConstructor VectorFullConstructor { get; }
+        public IXamlType Size { get; }
+        public IXamlConstructor SizeFullConstructor { get; }
+        public IXamlType Matrix { get; }
+        public IXamlConstructor MatrixFullConstructor { get; }
+        public IXamlType CornerRadius { get; }
+        public IXamlConstructor CornerRadiusFullConstructor { get; }
 
         public AvaloniaXamlIlWellKnownTypes(TransformerConfiguration cfg)
         {
@@ -104,6 +122,25 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
             ItemsRepeater = cfg.TypeSystem.GetType("Avalonia.Controls.ItemsRepeater");
             ReflectionBindingExtension = cfg.TypeSystem.GetType("Avalonia.Markup.Xaml.MarkupExtensions.ReflectionBindingExtension");
             RelativeSource = cfg.TypeSystem.GetType("Avalonia.Data.RelativeSource");
+            Long = cfg.TypeSystem.GetType("System.Int64");
+            Uri = cfg.TypeSystem.GetType("System.Uri");
+            FontFamily = cfg.TypeSystem.GetType("Avalonia.Media.FontFamily");
+            FontFamilyConstructorUriName = FontFamily.GetConstructor(new List<IXamlType> { Uri, XamlIlTypes.String });
+
+            (IXamlType, IXamlConstructor) GetNumericTypeInfo(string name, IXamlType componentType, int componentCount)
+            {
+                var type = cfg.TypeSystem.GetType(name);
+                var ctor = type.GetConstructor(Enumerable.Range(0, componentCount).Select(_ => componentType).ToList());
+
+                return (type, ctor);
+            }
+
+            (Thickness, ThicknessFullConstructor) = GetNumericTypeInfo("Avalonia.Thickness", XamlIlTypes.Double, 4);
+            (Point, PointFullConstructor) = GetNumericTypeInfo("Avalonia.Point", XamlIlTypes.Double, 2);
+            (Vector, VectorFullConstructor) = GetNumericTypeInfo("Avalonia.Vector", XamlIlTypes.Double, 2);
+            (Size, SizeFullConstructor) = GetNumericTypeInfo("Avalonia.Size", XamlIlTypes.Double, 2);
+            (Matrix, MatrixFullConstructor) = GetNumericTypeInfo("Avalonia.Matrix", XamlIlTypes.Double, 6);
+            (CornerRadius, CornerRadiusFullConstructor) = GetNumericTypeInfo("Avalonia.CornerRadius", XamlIlTypes.Double, 4);
         }
     }
 

+ 29 - 3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/XamlIlBindingPathHelper.cs

@@ -203,6 +203,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
                                 .ParentNodes()
                                 .OfType<XamlAstConstructableObjectNode>()
                                 .Where(x => styledElementType.IsAssignableFrom(x.Type.GetClrType()))
+                                .Skip(1)
                                 .ElementAtOrDefault(ancestor.Level)
                                 ?.Type.GetClrType();
 
@@ -242,6 +243,16 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
                     case RawSourceBindingExpressionNode rawSource:
                         nodes.Add(new RawSourcePathElementNode(rawSource.RawSource));
                         break;
+                    case BindingExpressionGrammar.TypeCastNode typeCastNode:
+                        var castType = GetType(typeCastNode.Namespace, typeCastNode.TypeName);
+
+                        if (castType is null)
+                        {
+                            throw new XamlX.XamlParseException($"Unable to resolve cast to type {typeCastNode.Namespace}:{typeCastNode.TypeName} based on XAML tree.", lineInfo);
+                        }
+
+                        nodes.Add(new TypeCastPathElementNode(castType));
+                        break;
                 }
             }
 
@@ -422,7 +433,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
             {
                 codeGen.Ldtype(Type)
                     .Ldc_I4(_level)
-                    .EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "FindAncestor"));
+                    .EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "Ancestor"));
             }
         }
 
@@ -608,10 +619,10 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
             private readonly IXamlAstValueNode _rawSource;
 
             public RawSourcePathElementNode(IXamlAstValueNode rawSource)
-                :base(rawSource)
+                : base(rawSource)
             {
                 _rawSource = rawSource;
-                
+
             }
 
             public IXamlType Type => _rawSource.Type.GetClrType();
@@ -625,6 +636,21 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
             }
         }
 
+        class TypeCastPathElementNode : IXamlIlBindingPathElementNode
+        {
+            public TypeCastPathElementNode(IXamlType ancestorType)
+            {
+                Type = ancestorType;
+            }
+
+            public IXamlType Type { get; }
+
+            public void Emit(XamlIlEmitContext context, IXamlILEmitter codeGen)
+            {
+                codeGen.EmitCall(context.GetAvaloniaTypes().CompiledBindingPathBuilder.FindMethod(m => m.Name == "TypeCast").MakeGenericMethod(new[] { Type }));
+            }
+        }
+
         class XamlIlBindingPathNode : XamlAstNode, IXamlIlBindingPathNode, IXamlAstEmitableNode<IXamlILEmitter, XamlILNodeEmitResult>
         {
             private readonly List<IXamlIlBindingPathElementNode> _transformElements;

+ 1 - 1
src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github

@@ -1 +1 @@
-Subproject commit 5420df861ce6f2be5ead9efa078fe7242ce88f18
+Subproject commit ea80a607c5e9d8f000160dbbb48c27ed4cfafbc9

+ 1 - 0
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@@ -23,6 +23,7 @@
         <Compile Include="MarkupExtensions\CompiledBindings\ObservableStreamPlugin.cs" />
         <Compile Include="MarkupExtensions\CompiledBindings\PropertyInfoAccessorFactory.cs" />
         <Compile Include="MarkupExtensions\CompiledBindings\PropertyInfoAccessorPlugin.cs" />
+        <Compile Include="MarkupExtensions\CompiledBindings\StrongTypeCastNode.cs" />
         <Compile Include="MarkupExtensions\CompiledBindings\TaskStreamPlugin.cs" />
         <Compile Include="MarkupExtensions\DynamicResourceExtension.cs" />
         <Compile Include="MarkupExtensions\ResolveByNameExtension.cs" />

+ 2 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindingExtension.cs

@@ -26,6 +26,8 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions
             {
                 Path = Path,
                 Converter = Converter,
+                ConverterParameter = ConverterParameter,
+                TargetNullValue = TargetNullValue,
                 FallbackValue = FallbackValue,
                 Mode = Mode,
                 Priority = Priority,

+ 51 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/CompiledBindingPath.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using Avalonia.Controls;
 using Avalonia.Data.Core;
 using Avalonia.Data.Core.Plugins;
@@ -53,6 +54,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
                     case IStronglyTypedStreamElement stream:
                         node = new StreamNode(stream.CreatePlugin());
                         break;
+                    case ITypeCastElement typeCast:
+                        node = new StrongTypeCastNode(typeCast.Type, typeCast.Cast);
+                        break;
                     default:
                         throw new InvalidOperationException($"Unknown binding path element type {element.GetType().FullName}");
                 }
@@ -66,6 +70,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
         internal SourceMode SourceMode => _elements.Count > 0 && _elements[0] is IControlSourceBindingPathElement ? SourceMode.Control : SourceMode.Data;
 
         internal object RawSource { get; }
+
+        public override string ToString()
+            => string.Concat(_elements.Select(e => e.ToString()));
     }
 
     public class CompiledBindingPathBuilder
@@ -126,6 +133,12 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
             return this;
         }
 
+        public CompiledBindingPathBuilder TypeCast<T>()
+        {
+            _elements.Add(new TypeCastPathElement<T>());
+            return this;
+        }
+
         public CompiledBindingPathBuilder SetRawSource(object rawSource)
         {
             _rawSource = rawSource;
@@ -157,6 +170,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
         public IPropertyInfo Property { get; }
 
         public Func<WeakReference<object>, IPropertyInfo, IPropertyAccessor> AccessorFactory { get; }
+
+        public override string ToString()
+            => $".{Property.Name}";
     }
 
     internal interface IStronglyTypedStreamElement : ICompiledBindingPathElement
@@ -164,6 +180,13 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
         IStreamPlugin CreatePlugin();
     }
 
+    internal interface ITypeCastElement : ICompiledBindingPathElement
+    {
+        Type Type { get; }
+
+        Func<object, object> Cast { get; }
+    }
+
     internal class TaskStreamPathElement<T> : IStronglyTypedStreamElement
     {
         public static readonly TaskStreamPathElement<T> Instance = new TaskStreamPathElement<T>();
@@ -181,6 +204,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
     internal class SelfPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
     {
         public static readonly SelfPathElement Instance = new SelfPathElement();
+
+        public override string ToString()
+            => "$self";
     }
 
     internal class AncestorPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
@@ -193,6 +219,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
 
         public Type AncestorType { get; }
         public int Level { get; }
+
+        public override string ToString()
+           => $"$parent[{AncestorType?.Name},{Level}]";
     }
 
     internal class VisualAncestorPathElement : ICompiledBindingPathElement, IControlSourceBindingPathElement
@@ -217,6 +246,9 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
 
         public INameScope NameScope { get; }
         public string Name { get; }
+
+        public override string ToString()
+            => $"#{Name}";
     }
 
     internal class ArrayElementPathElement : ICompiledBindingPathElement
@@ -229,5 +261,24 @@ namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
 
         public int[] Indices { get; }
         public Type ElementType { get; }
+        public override string ToString()
+            => $"[{string.Join(",", Indices)}]";
+    }
+
+    internal class TypeCastPathElement<T> : ITypeCastElement
+    {
+        private static object TryCast(object obj)
+        {
+            if (obj is T result)
+                return result;
+            return null;
+        }
+
+        public Type Type => typeof(T);
+
+        public Func<object, object> Cast => TryCast;
+
+        public override string ToString()
+            => $"({Type.FullName})";
     }
 }

+ 18 - 0
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/CompiledBindings/StrongTypeCastNode.cs

@@ -0,0 +1,18 @@
+using System;
+using Avalonia.Data.Core;
+
+namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings
+{
+    public class StrongTypeCastNode : TypeCastNode
+    {
+        private Func<object, object> _cast;
+
+        public StrongTypeCastNode(Type type, Func<object, object> cast) : base(type)
+        {
+            _cast = cast;
+        }
+
+        protected override object Cast(object value)
+            => _cast(value);
+    }
+}

+ 85 - 6
src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs

@@ -16,7 +16,7 @@ namespace Avalonia.Markup.Parsers
 
     internal static class BindingExpressionGrammar
     {
-        public static (IList<INode> Nodes, SourceMode Mode) Parse(ref CharacterReader r)
+        public static (List<INode> Nodes, SourceMode Mode) Parse(ref CharacterReader r)
         {
             var nodes = new List<INode>();
             var state = State.Start;
@@ -46,6 +46,10 @@ namespace Avalonia.Markup.Parsers
                         state = ParseIndexer(ref r, nodes);
                         break;
 
+                    case State.TypeCast:
+                        state = ParseTypeCast(ref r, nodes);
+                        break;
+
                     case State.ElementName:
                         state = ParseElementName(ref r, nodes);
                         mode = SourceMode.Control;
@@ -84,6 +88,11 @@ namespace Avalonia.Markup.Parsers
             }
             else if (ParseOpenBrace(ref r))
             {
+                if (PeekOpenBrace(ref r))
+                {
+                    return State.TypeCast;
+                }
+
                 return State.AttachedProperty;
             }
             else if (PeekOpenBracket(ref r))
@@ -124,6 +133,10 @@ namespace Avalonia.Markup.Parsers
             {
                 return State.Indexer;
             }
+            else if (ParseOpenBrace(ref r))
+            {
+                return State.TypeCast;
+            }
 
             return State.End;
         }
@@ -132,6 +145,11 @@ namespace Avalonia.Markup.Parsers
         {
             if (ParseOpenBrace(ref r))
             {
+                if (PeekOpenBrace(ref r))
+                {
+                    return State.TypeCast;
+                }
+
                 return State.AttachedProperty;
             }
             else
@@ -152,6 +170,12 @@ namespace Avalonia.Markup.Parsers
         {
             var (ns, owner) = ParseTypeName(ref r);
 
+            if(!r.End && r.TakeIf(')'))
+            {
+                nodes.Add(new TypeCastNode() { Namespace = ns, TypeName = owner });
+                return State.AfterMember;
+            }
+
             if (r.End || !r.TakeIf('.'))
             {
                 throw new ExpressionParseException(r.Position, "Invalid attached property name.");
@@ -159,6 +183,11 @@ namespace Avalonia.Markup.Parsers
 
             var name = r.ParseIdentifier();
 
+            if (name.Length == 0)
+            {
+                throw new ExpressionParseException(r.Position, "Attached Property name expected after '.'.");
+            }
+
             if (r.End || !r.TakeIf(')'))
             {
                 throw new ExpressionParseException(r.Position, "Expected ')'.");
@@ -186,6 +215,39 @@ namespace Avalonia.Markup.Parsers
             return State.AfterMember;
         }
 
+        private static State ParseTypeCast(ref CharacterReader r, List<INode> nodes)
+        {
+            bool parseMemberBeforeAddCast = ParseOpenBrace(ref r);
+
+            var (ns, typeName) = ParseTypeName(ref r);
+
+            var result = State.AfterMember;
+
+            if (parseMemberBeforeAddCast)
+            {
+                if (!ParseCloseBrace(ref r))
+                {
+                    throw new ExpressionParseException(r.Position, "Expected ')'.");
+                }
+
+                result = ParseBeforeMember(ref r, nodes);
+
+                if(r.Peek == '[')
+                {
+                    result = ParseIndexer(ref r, nodes);
+                }
+            }
+
+            nodes.Add(new TypeCastNode { Namespace = ns, TypeName = typeName });
+
+            if (r.End || !r.TakeIf(')'))
+            {
+                throw new ExpressionParseException(r.Position, "Expected ')'.");
+            }
+
+            return result;
+        }
+
         private static State ParseElementName(ref CharacterReader r, List<INode> nodes)
         {
             var name = r.ParseIdentifier();
@@ -288,11 +350,21 @@ namespace Avalonia.Markup.Parsers
             return !r.End && r.TakeIf('(');
         }
 
+        private static bool ParseCloseBrace(ref CharacterReader r)
+        {
+            return !r.End && r.TakeIf(')');
+        }
+
         private static bool PeekOpenBracket(ref CharacterReader r)
         {
             return !r.End && r.Peek == '[';
         }
 
+        private static bool PeekOpenBrace(ref CharacterReader r)
+        {
+            return !r.End && r.Peek == '(';
+        }
+
         private static bool ParseStreamOperator(ref CharacterReader r)
         {
             return !r.End && r.TakeIf('^');
@@ -322,6 +394,7 @@ namespace Avalonia.Markup.Parsers
             BeforeMember,
             AttachedProperty,
             Indexer,
+            TypeCast,
             End,
         }
 
@@ -343,9 +416,9 @@ namespace Avalonia.Markup.Parsers
             }
         }
 
-        public interface INode {}
+        public interface INode { }
 
-        public interface ITransformNode {}
+        public interface ITransformNode { }
 
         public class EmptyExpressionNode : INode { }
 
@@ -366,11 +439,11 @@ namespace Avalonia.Markup.Parsers
             public IList<string> Arguments { get; set; }
         }
 
-        public class NotNode : INode, ITransformNode {}
+        public class NotNode : INode, ITransformNode { }
 
-        public class StreamNode : INode {}
+        public class StreamNode : INode { }
 
-        public class SelfNode : INode {}
+        public class SelfNode : INode { }
 
         public class NameNode : INode
         {
@@ -383,5 +456,11 @@ namespace Avalonia.Markup.Parsers
             public string TypeName { get; set; }
             public int Level { get; set; }
         }
+
+        public class TypeCastNode : INode
+        {
+            public string Namespace { get; set; }
+            public string TypeName { get; set; }
+        }
     }
 }

+ 19 - 0
src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs

@@ -59,6 +59,9 @@ namespace Avalonia.Markup.Parsers
                     case BindingExpressionGrammar.NameNode elementName:
                         nextNode = new ElementNameNode(_nameScope, elementName.Name);
                         break;
+                    case BindingExpressionGrammar.TypeCastNode typeCast:
+                        nextNode = ParseTypeCastNode(typeCast);
+                        break;
                 }
                 if (rootNode is null)
                 {
@@ -92,6 +95,22 @@ namespace Avalonia.Markup.Parsers
             return new FindAncestorNode(ancestorType, ancestorLevel);
         }
 
+        private TypeCastNode ParseTypeCastNode(BindingExpressionGrammar.TypeCastNode node)
+        {
+            Type castType = null;
+            if (!(node.Namespace is null) && !(node.TypeName is null))
+            {
+                if (_typeResolver == null)
+                {
+                    throw new InvalidOperationException("Cannot parse a binding path with a typed Cast without a type resolver. Maybe you can use a LINQ Expression binding path instead?");
+                }
+
+                castType = _typeResolver(node.Namespace, node.TypeName);
+            }
+
+            return new TypeCastNode(castType);
+        }
+
         private AvaloniaPropertyAccessorNode ParseAttachedProperty(BindingExpressionGrammar.AttachedPropertyNameNode node)
         {
             if (_typeResolver == null)

+ 7 - 5
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -434,7 +434,7 @@ namespace Avalonia.Skia
         /// <inheritdoc />
         public IDrawingContextLayerImpl CreateLayer(Size size)
         {
-            return CreateRenderTarget( size);
+            return CreateRenderTarget(size, true);
         }
 
         /// <inheritdoc />
@@ -673,7 +673,7 @@ namespace Avalonia.Skia
         private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
         {
             var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize);
-            var intermediate = CreateRenderTarget(calc.IntermediateSize);
+            var intermediate = CreateRenderTarget(calc.IntermediateSize, false);
 
             paintWrapper.AddDisposable(intermediate);
 
@@ -748,7 +748,7 @@ namespace Avalonia.Skia
 
             if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
             {
-                var intermediate = CreateRenderTarget(intermediateSize);
+                var intermediate = CreateRenderTarget(intermediateSize, false);
 
                 using (var ctx = intermediate.CreateDrawingContext(visualBrushRenderer))
                 {
@@ -978,9 +978,10 @@ namespace Avalonia.Skia
         /// Create new render target compatible with this drawing context.
         /// </summary>
         /// <param name="size">The size of the render target in DIPs.</param>
+        /// <param name="isLayer">Whether the render target is being created for a layer.</param>
         /// <param name="format">Pixel format.</param>
         /// <returns></returns>
-        private SurfaceRenderTarget CreateRenderTarget(Size size, PixelFormat? format = null)
+        private SurfaceRenderTarget CreateRenderTarget(Size size, bool isLayer, PixelFormat? format = null)
         {
             var pixelSize = PixelSize.FromSizeWithDpi(size, _dpi);
             var createInfo = new SurfaceRenderTarget.CreateInfo
@@ -992,7 +993,8 @@ namespace Avalonia.Skia
                 DisableTextLcdRendering = !_canTextUseLcdRendering,
                 GrContext = _grContext,
                 Gpu = _gpu,
-                Session = _session
+                Session = _session,
+                DisableManualFbo = !isLayer,
             };
 
             return new SurfaceRenderTarget(createInfo);

+ 2 - 1
src/Skia/Avalonia.Skia/PlatformRenderInterface.cs

@@ -124,7 +124,8 @@ namespace Avalonia.Skia
                 Width = size.Width,
                 Height = size.Height,
                 Dpi = dpi,
-                DisableTextLcdRendering = false
+                DisableTextLcdRendering = false,
+                DisableManualFbo = true,
             };
 
             return new SurfaceRenderTarget(createInfo);

+ 4 - 1
src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs

@@ -51,7 +51,8 @@ namespace Avalonia.Skia
             _grContext = createInfo.GrContext;
             _gpu = createInfo.Gpu;
 
-            _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.Session);
+            if (!createInfo.DisableManualFbo)
+                _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.Session);
             if (_surface == null)
                 _surface = new SkiaSurfaceWrapper(CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height,
                     createInfo.Format));
@@ -220,6 +221,8 @@ namespace Avalonia.Skia
             public ISkiaGpu Gpu;
 
             public ISkiaGpuRenderSession Session;
+
+            public bool DisableManualFbo;
         }
     }
 }

+ 1 - 0
src/Windows/Avalonia.Win32/.gitignore

@@ -0,0 +1 @@
+*.Generated.cs

+ 3 - 1
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@@ -5,9 +5,11 @@
     <PackageId>Avalonia.Win32</PackageId>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
     <ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
     <PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" />
-    <PackageReference Include="Microsoft.Windows.SDK.NET" Version="10.0.18362.3-preview" />
+    <AvnComIdl Include="WinRT\winrt.idl" OutputFile="WinRT\WinRT.Generated.cs" />
   </ItemGroup>
+  <Import Project="../../../build/MicroCom.targets" />
   <Import Project="$(MSBuildThisFileDirectory)\..\..\..\build\System.Drawing.Common.props" />    
 </Project>

+ 0 - 18
src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs

@@ -1,18 +0,0 @@
-namespace Avalonia.Win32
-{
-    internal class CompositionBlurHost : IBlurHost
-    {
-        Windows.UI.Composition.Visual _blurVisual;
-
-        public CompositionBlurHost(Windows.UI.Composition.Visual blurVisual)
-        {
-            _blurVisual = blurVisual;
-        }
-
-        public void SetBlur(bool enabled)
-        {
-            _blurVisual.IsVisible = enabled;
-        }
-    }
-}
-

+ 0 - 171
src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs

@@ -1,171 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using Avalonia.Logging;
-using Avalonia.OpenGL;
-using Avalonia.OpenGL.Angle;
-using Avalonia.OpenGL.Egl;
-using Windows.UI.Composition;
-using Windows.UI.Composition.Interop;
-using WinRT;
-
-namespace Avalonia.Win32
-{
-    internal class CompositionConnector
-    {
-        private Compositor _compositor;
-        private Windows.System.DispatcherQueueController _dispatcherQueueController;
-        private CompositionGraphicsDevice _graphicsDevice;
-
-        internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
-        {
-            DQTAT_COM_NONE = 0,
-            DQTAT_COM_ASTA = 1,
-            DQTAT_COM_STA = 2
-        };
-
-        internal enum DISPATCHERQUEUE_THREAD_TYPE
-        {
-            DQTYPE_THREAD_DEDICATED = 1,
-            DQTYPE_THREAD_CURRENT = 2,
-        };
-
-        [StructLayout(LayoutKind.Sequential)]
-        internal struct DispatcherQueueOptions
-        {
-            public int dwSize;
-
-            [MarshalAs(UnmanagedType.I4)]
-            public DISPATCHERQUEUE_THREAD_TYPE threadType;
-
-            [MarshalAs(UnmanagedType.I4)]
-            public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
-        };
-
-        [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)]
-        internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController);
-
-        public static CompositionConnector TryCreate(EglPlatformOpenGlInterface egl)
-        {
-            const int majorRequired = 10;
-            const int buildRequired = 16299;
-
-            var majorInstalled = Win32Platform.WindowsVersion.Major;
-            var buildInstalled = Win32Platform.WindowsVersion.Build;
-            
-            if (majorInstalled >= majorRequired &&
-                buildInstalled >= buildRequired)
-            {
-                try
-                {
-                    return new CompositionConnector(egl);
-                }
-                catch (Exception e)
-                {
-                    Logger.TryGet(LogEventLevel.Error, "WinUIComposition")?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
-
-                    return null;
-                }
-            }
-
-            var osVersionNotice = $"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed.";
-
-            Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
-                $"Unable to initialize WinUI compositor: {osVersionNotice}");
-
-            return null;
-        }
-        
-        public CompositionConnector(EglPlatformOpenGlInterface egl)
-        {
-            EnsureDispatcherQueue();
-
-            if (_dispatcherQueueController != null)
-                _compositor = new Compositor();
-
-            var interop = _compositor.As<ICompositorInterop>();
-
-            var display = egl.Display as AngleWin32EglDisplay;
-
-            _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice());
-        }
-
-        public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual, out IBlurHost blurHost)
-        {
-            var target = CreateDesktopWindowTarget(hwnd);
-
-            var surface = _graphicsDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0),
-                Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized,
-                Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied);
-
-            var surfaceInterop = surface.As<ICompositionDrawingSurfaceInterop>();
-
-            var brush = _compositor.CreateSurfaceBrush(surface);
-            var visual = _compositor.CreateSpriteVisual();
-
-            visual.Brush = brush;
-            visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1);
-
-            var container = _compositor.CreateContainerVisual();
-
-            target.Root = container;
-
-            var blur = CreateBlur();
-
-            blurHost = new CompositionBlurHost(blur);
-
-            container.Children.InsertAtTop(blur);
-
-            container.Children.InsertAtTop(visual);
-
-            visual.CompositeMode = CompositionCompositeMode.SourceOver;
-
-            surfaceVisual = container;
-
-            return surfaceInterop;
-        }
-
-        private SpriteVisual CreateBlur()
-        {
-            var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter("backdrop"));
-
-            var backDropBrush = _compositor.CreateBackdropBrush();
-
-            var saturateEffect = new SaturationEffect(blurEffect);
-            var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect);
-            var satBrush = satEffectFactory.CreateBrush();
-            
-            satBrush.SetSourceParameter("backdrop", backDropBrush);
-
-            var visual = _compositor.CreateSpriteVisual();
-            visual.IsVisible = false;
-
-            visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f);
-            visual.Brush = satBrush;
-
-            return visual;
-        }
-
-        private CompositionTarget CreateDesktopWindowTarget(IntPtr window)
-        {
-            var interop = _compositor.As<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>();
-
-            interop.CreateDesktopWindowTarget(window, false, out var windowTarget);
-            return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget);
-        }
-
-        private void EnsureDispatcherQueue()
-        {
-            if (_dispatcherQueueController == null)
-            {
-                DispatcherQueueOptions options = new DispatcherQueueOptions();
-                options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE;
-                options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT;
-                options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
-
-                CreateDispatcherQueueController(options, out var queue);
-                _dispatcherQueueController = Windows.System.DispatcherQueueController.FromAbi(queue);
-            }
-        }
-    }
-}
-

+ 0 - 96
src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs

@@ -1,96 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using Avalonia.OpenGL;
-using Avalonia.OpenGL.Angle;
-using Avalonia.OpenGL.Egl;
-using Avalonia.OpenGL.Surfaces;
-using Windows.UI.Composition.Interop;
-
-namespace Avalonia.Win32
-{
-    internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase
-    {
-        private EglPlatformOpenGlInterface _egl;
-        private readonly IEglWindowGlPlatformSurfaceInfo _info;
-        private ICompositionDrawingSurfaceInterop _surfaceInterop;
-        private Windows.UI.Composition.Visual _surface;
-
-        public CompositionEglGlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info) : base()
-        {
-            _egl = egl;
-            _info = info;
-        }
-
-        public IBlurHost AttachToCompositionTree(CompositionConnector connector, IntPtr hwnd)
-        {
-            using (_egl.PrimaryContext.MakeCurrent())
-            {
-                _surfaceInterop = connector.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost);
-                return blurHost;
-            }
-        }
-
-        public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
-        {
-            return new CompositionRenderTarget(_egl, _surface, _surfaceInterop, _info);
-        }
-
-        class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase
-        {
-            private readonly EglPlatformOpenGlInterface _egl;
-            private readonly IEglWindowGlPlatformSurfaceInfo _info;
-            private PixelSize _currentSize;
-            private readonly ICompositionDrawingSurfaceInterop _surfaceInterop;
-            private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
-            private Windows.UI.Composition.Visual _compositionVisual;
-
-            public CompositionRenderTarget(EglPlatformOpenGlInterface egl,
-                Windows.UI.Composition.Visual compositionVisual,
-                ICompositionDrawingSurfaceInterop interopSurface,
-                IEglWindowGlPlatformSurfaceInfo info)
-                : base(egl)
-            {
-                _egl = egl;
-                _surfaceInterop = interopSurface;
-                _info = info;
-                _currentSize = info.Size;
-                _compositionVisual = compositionVisual;
-
-                using (_egl.PrimaryContext.MakeCurrent())
-                {
-                    _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height });
-                }
-
-                _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height);
-            }
-
-            public override IGlPlatformSurfaceRenderingSession BeginDraw()
-            {
-                IntPtr texture;
-                EglSurface surface;
-
-                using (_egl.PrimaryEglContext.EnsureCurrent())
-                {
-                    if (_info.Size != _currentSize)
-                    {
-                        _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height });
-                        _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height);
-                        _currentSize = _info.Size;
-                    }
-
-                    var offset = new POINT();
-
-                    _surfaceInterop.BeginDraw(
-                        IntPtr.Zero,
-                        ref s_Iid,
-                        out texture, ref offset);
-
-                    surface = (_egl.Display as AngleWin32EglDisplay).WrapDirect3D11Texture(_egl, texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height);
-                }
-
-                return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true);
-            }
-        }
-    }
-}
-

+ 0 - 91
src/Windows/Avalonia.Win32/Composition/D2DEffects.cs

@@ -1,91 +0,0 @@
-using System;
-
-
-namespace Avalonia.Win32
-{
-    class D2DEffects
-    {
-        public static readonly Guid CLSID_D2D12DAffineTransform = new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C);
-
-        public static readonly Guid CLSID_D2D13DPerspectiveTransform = new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB);
-
-        public static readonly Guid CLSID_D2D13DTransform = new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A);
-
-        public static readonly Guid CLSID_D2D1ArithmeticComposite = new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87);
-
-        public static readonly Guid CLSID_D2D1Atlas = new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08);
-
-        public static readonly Guid CLSID_D2D1BitmapSource = new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D);
-
-        public static readonly Guid CLSID_D2D1Blend = new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D);
-
-        public static readonly Guid CLSID_D2D1Border = new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27);
-
-        public static readonly Guid CLSID_D2D1Brightness = new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87);
-
-        public static readonly Guid CLSID_D2D1ColorManagement = new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37);
-
-        public static readonly Guid CLSID_D2D1ColorMatrix = new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11);
-
-        public static readonly Guid CLSID_D2D1Composite = new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D);
-
-        public static readonly Guid CLSID_D2D1ConvolveMatrix = new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E);
-
-        public static readonly Guid CLSID_D2D1Crop = new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B);
-
-        public static readonly Guid CLSID_D2D1DirectionalBlur = new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB);
-
-        public static readonly Guid CLSID_D2D1DiscreteTransfer = new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C);
-
-        public static readonly Guid CLSID_D2D1DisplacementMap = new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90);
-
-        public static readonly Guid CLSID_D2D1DistantDiffuse = new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54);
-
-        public static readonly Guid CLSID_D2D1DistantSpecular = new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA);
-
-        public static readonly Guid CLSID_D2D1DpiCompensation = new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28);
-
-        public static readonly Guid CLSID_D2D1Flood = new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2);
-
-        public static readonly Guid CLSID_D2D1GammaTransfer = new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42);
-
-        public static readonly Guid CLSID_D2D1GaussianBlur = new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5);
-
-        public static readonly Guid CLSID_D2D1Scale = new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7);
-
-        public static readonly Guid CLSID_D2D1Histogram = new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8);
-
-        public static readonly Guid CLSID_D2D1HueRotation = new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6);
-
-        public static readonly Guid CLSID_D2D1LinearTransfer = new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06);
-
-        public static readonly Guid CLSID_D2D1LuminanceToAlpha = new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE);
-
-        public static readonly Guid CLSID_D2D1Morphology = new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02);
-
-        public static readonly Guid CLSID_D2D1OpacityMetadata = new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E);
-
-        public static readonly Guid CLSID_D2D1PointDiffuse = new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20);
-
-        public static readonly Guid CLSID_D2D1PointSpecular = new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22);
-
-        public static readonly Guid CLSID_D2D1Premultiply = new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2);
-
-        public static readonly Guid CLSID_D2D1Saturation = new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7);
-
-        public static readonly Guid CLSID_D2D1Shadow = new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B);
-
-        public static readonly Guid CLSID_D2D1SpotDiffuse = new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93);
-
-        public static readonly Guid CLSID_D2D1SpotSpecular = new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1);
-
-        public static readonly Guid CLSID_D2D1TableTransfer = new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4);
-
-        public static readonly Guid CLSID_D2D1Tile = new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F);
-
-        public static readonly Guid CLSID_D2D1Turbulence = new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9);
-
-        public static readonly Guid CLSID_D2D1UnPremultiply = new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7);
-    }
-}
-

+ 0 - 45
src/Windows/Avalonia.Win32/Composition/EffectBase.cs

@@ -1,45 +0,0 @@
-using System;
-using Windows.Graphics.Effects;
-using Windows.Graphics.Effects.Interop;
-
-
-namespace Avalonia.Win32
-{
-    abstract class EffectBase : IGraphicsEffect,  IGraphicsEffectSource, global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop
-    {
-        private IGraphicsEffectSource[] _sources;
-
-        public EffectBase(params IGraphicsEffectSource[] sources)
-        {
-            _sources = sources;
-        }
-
-        private IGraphicsEffectSource _source;
-
-        public virtual string Name { get; set; }
-
-        public abstract Guid EffectId { get; }
-
-        public abstract uint PropertyCount { get; }
-
-        public uint SourceCount => (uint)_sources.Length;
-
-        public IGraphicsEffectSource GetSource(uint index)
-        {
-            if(index < _sources.Length)
-            {
-                return _sources[index];
-            }
-
-            return null;
-        }
-
-        public uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping)
-        {
-            throw new NotImplementedException();
-        }
-
-        public abstract object GetProperty(uint index);
-    }
-}
-

+ 0 - 18
src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs

@@ -1,18 +0,0 @@
-namespace Windows.Graphics.Effects.Interop
-{
-    public enum GRAPHICS_EFFECT_PROPERTY_MAPPING
-    {
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3,
-        GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4
-    };
-}
-

+ 0 - 57
src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs

@@ -1,57 +0,0 @@
-using System;
-using Windows.Graphics.Effects;
-
-namespace Avalonia.Win32
-{
-    class GaussianBlurEffect : EffectBase
-    {
-        public GaussianBlurEffect(IGraphicsEffectSource source) : base(source)
-        {
-        }
-
-        enum D2D1_GAUSSIANBLUR_OPTIMIZATION
-        {
-            D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED,
-            D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED,
-            D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY,
-            D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD
-        };
-
-        enum D2D1_BORDER_MODE
-        {
-            D2D1_BORDER_MODE_SOFT,
-            D2D1_BORDER_MODE_HARD,
-            D2D1_BORDER_MODE_FORCE_DWORD
-        };
-
-        enum D2D1GaussianBlurProp
-        {
-            D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION,
-            D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION,
-            D2D1_GAUSSIANBLUR_PROP_BORDER_MODE,
-            D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD
-        };
-
-        public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur;
-
-        public override uint PropertyCount => 3;
-
-        public override object GetProperty(uint index)
-        {
-            switch ((D2D1GaussianBlurProp)index)
-            {
-                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION:
-                    return 30.0f;
-
-                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION:
-                    return (uint)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED;
-
-                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE:
-                    return (uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD;
-            }
-
-            return null;
-        }
-    }
-}
-

+ 0 - 8
src/Windows/Avalonia.Win32/Composition/IBlurHost.cs

@@ -1,8 +0,0 @@
-namespace Avalonia.Win32
-{
-    internal interface IBlurHost
-    {
-        void SetBlur(bool enabled);
-    }
-}
-

+ 0 - 152
src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs

@@ -1,152 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using WinRT;
-
-namespace Windows.UI.Composition.Interop
-{
-    public struct POINT
-    {
-        public int X;
-        public int Y;
-    }
-
-    public struct RECT
-    {
-        public int left;
-        public int top;
-        public int right;
-        public int bottom;
-
-        public int Width => right - left;
-        public int Height => bottom - top;
-    }
-
-    [WindowsRuntimeType]
-    [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
-    public interface ICompositionDrawingSurfaceInterop
-    {
-        void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point);
-
-        void EndDraw();
-
-        void Resize(POINT sizePixels);
-
-        void ResumeDraw();
-
-        void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY);
-
-        void SuspendDraw();
-    }
-}
-
-namespace ABI.Windows.UI.Composition.Interop
-{
-    using global::System;
-    using global::System.Runtime.InteropServices;
-    using global::Windows.UI.Composition;
-    using global::Windows.UI.Composition.Interop;
-
-    [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
-    internal class ICompositionDrawingSurfaceInterop : global::Windows.UI.Composition.Interop.ICompositionDrawingSurfaceInterop
-
-    {
-        [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
-        public unsafe struct Vftbl
-        {
-            public delegate int _BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset);
-            public delegate int _EndDraw(IntPtr ThisPtr);
-            public delegate int _Resize(IntPtr ThisPtr, POINT sizePixels);
-            public delegate int _ResumeDraw(IntPtr ThisPtr);
-            public delegate int _Scroll(IntPtr ThisPtr, RECT scrollRect, RECT clipRect, int offsetX, int offsetY);
-            public delegate int _SuspendDraw(IntPtr ThisPtr);
-
-            internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
-            public _BeginDraw BeginDraw;
-            public _EndDraw EndDraw;
-            public _Resize Resize;
-            public _ResumeDraw ResumeDraw;
-            public _Scroll Scroll;
-            public _SuspendDraw SuspendDraw;
-
-            public static readonly Vftbl AbiToProjectionVftable;
-            public static readonly IntPtr AbiToProjectionVftablePtr;
-
-            static Vftbl()
-            {
-                AbiToProjectionVftable = new Vftbl
-                {
-                    IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
-
-                    BeginDraw = Do_Abi_BeginDraw,
-                    EndDraw = Do_Abi_EndDraw,
-                    Resize = Do_Abi_Resize
-
-
-                };
-                AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
-                Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
-            }
-
-            private static int Do_Abi_BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset)
-            {
-                updateObject = IntPtr.Zero;
-                return 0;
-            }
-
-            private static int Do_Abi_EndDraw(IntPtr ThisPtr)
-            {
-                return 0;
-            }
-
-            private static int Do_Abi_Resize(IntPtr ThisPtr, POINT sizePixels)
-            {
-                return 0;
-            }
-        }
-        internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
-
-        public static implicit operator ICompositionDrawingSurfaceInterop(IObjectReference obj) => (obj != null) ? new ICompositionDrawingSurfaceInterop(obj) : null;
-        protected readonly ObjectReference<Vftbl> _obj;
-        public IObjectReference ObjRef { get => _obj; }
-        public IntPtr ThisPtr => _obj.ThisPtr;
-        public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
-        public A As<A>() => _obj.AsType<A>();
-
-        public ICompositionDrawingSurfaceInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
-        internal ICompositionDrawingSurfaceInterop(ObjectReference<Vftbl> obj)
-        {
-            _obj = obj;
-        }
-
-        public void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point)
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, updateRect, ref iid, out updateObject, ref point));
-        }
-
-        public void EndDraw()
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.EndDraw(ThisPtr));
-        }
-
-        public void Resize(POINT sizePixels)
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.Resize(ThisPtr, sizePixels));
-        }
-
-        public void ResumeDraw()
-        {
-            throw new NotImplementedException();
-        }
-
-        public void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY)
-        {
-            throw new NotImplementedException();
-        }
-
-        public void SuspendDraw()
-        {
-            throw new NotImplementedException();
-        }        
-    }
-}
-

+ 0 - 14
src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs

@@ -1,14 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using WinRT;
-
-namespace Windows.UI.Composition.Desktop
-{
-    [WindowsRuntimeType]
-    [Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
-    public interface ICompositorDesktopInterop
-    {
-        void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test);
-    }
-}
-

+ 0 - 69
src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs

@@ -1,69 +0,0 @@
-using WinRT;
-
-namespace ABI.Windows.UI.Composition.Desktop
-{
-    using global::System;
-    using global::System.Runtime.InteropServices;
-
-    [Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
-    internal class ICompositorDesktopInterop : global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop
-
-    {
-        [Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
-        public struct Vftbl
-        {
-            public delegate int _CreateDesktopWindowTarget(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget);
-
-            internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
-            public _CreateDesktopWindowTarget CreateDesktopWindowTarget;
-
-
-            public static readonly Vftbl AbiToProjectionVftable;
-            public static readonly IntPtr AbiToProjectionVftablePtr;
-
-            static Vftbl()
-            {
-                AbiToProjectionVftable = new Vftbl
-                {
-                    IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
-                    CreateDesktopWindowTarget = Do_Abi_Create_Desktop_Window_Target
-                };
-                AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
-                Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
-            }
-
-            private static int Do_Abi_Create_Desktop_Window_Target(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget)
-            {
-                try
-                {
-                    ComWrappersSupport.FindObject<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>(thisPtr).CreateDesktopWindowTarget(hwndTarget, isTopMost != 0, out desktopWindowTarget);
-                    return 0;
-                }
-                catch (Exception ex)
-                {
-                    desktopWindowTarget = IntPtr.Zero;
-                    return Marshal.GetHRForException(ex);
-                }
-            }
-        }
-        internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
-
-        public static implicit operator ICompositorDesktopInterop(IObjectReference obj) => (obj != null) ? new ICompositorDesktopInterop(obj) : null;
-        protected readonly ObjectReference<Vftbl> _obj;
-        public IObjectReference ObjRef { get => _obj; }
-        public IntPtr ThisPtr => _obj.ThisPtr;
-        public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
-        public A As<A>() => _obj.AsType<A>();
-        public ICompositorDesktopInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
-        internal ICompositorDesktopInterop(ObjectReference<Vftbl> obj)
-        {
-            _obj = obj;
-        }
-
-        public void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test)
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateDesktopWindowTarget(ThisPtr, hwndTarget, isTopmost ? (byte)1 : (byte)0, out test));
-        }
-    }
-}
-

+ 0 - 139
src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs

@@ -1,139 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using WinRT;
-
-namespace Windows.UI.Composition.Interop
-{
-    [WindowsRuntimeType]
-    [Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]    
-    public interface ICompositorInterop
-    {
-        ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain);
-
-        ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain);
-
-        CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice);
-    }
-}
-
-namespace ABI.Windows.UI.Composition.Interop
-{
-    using global::System;
-    using global::System.Runtime.InteropServices;
-    using global::Windows.UI.Composition;
-
-    [Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]
-    internal class ICompositorInterop : global::Windows.UI.Composition.Interop.ICompositorInterop
-
-    {
-        [Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]
-        public struct Vftbl
-        {
-            public delegate int _CreateCompositionSurfaceForHandle(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result);
-            public delegate int _CreateCompositionSurfaceForSwapChain(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result);
-            public delegate int _CreateGraphicsDevice(IntPtr ThisPtr, IntPtr renderingDevice, out IntPtr result);
-
-            internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
-            public _CreateCompositionSurfaceForHandle CreateCompositionSurfaceForHandle;
-            public _CreateCompositionSurfaceForSwapChain CreateCompositionSurfaceForSwapChain;
-            public _CreateGraphicsDevice CreateGraphicsDevice;
-
-
-            public static readonly Vftbl AbiToProjectionVftable;
-            public static readonly IntPtr AbiToProjectionVftablePtr;
-
-            static Vftbl()
-            {
-                AbiToProjectionVftable = new Vftbl
-                {
-                    IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
-
-                    CreateCompositionSurfaceForHandle = Do_Abi_Create_Composition_Surface_For_Handle,
-                    CreateCompositionSurfaceForSwapChain = Do_Abi_Create_Composition_Surface_For_SwapChain,
-                    CreateGraphicsDevice= Do_Abi_Create_Graphics_Device
-                };
-                AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
-                Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
-            }
-
-            private static int Do_Abi_Create_Composition_Surface_For_Handle(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface)
-            {
-                try
-                {
-                    surface = IntPtr.Zero;
-                    //surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForHandle(swapChain);
-                    return 0;
-                }
-                catch (Exception ex)
-                {
-                    surface = IntPtr.Zero;
-                    return Marshal.GetHRForException(ex);
-                }
-            }
-
-            private static int Do_Abi_Create_Composition_Surface_For_SwapChain(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface)
-            {
-                try
-                {
-                    surface = IntPtr.Zero;
-                    //surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForSwapChain(swapChain);
-                    return 0;
-                }
-                catch (Exception ex)
-                {
-                    surface = IntPtr.Zero;                    
-                    return Marshal.GetHRForException(ex);
-                }
-            }
-
-            private static int Do_Abi_Create_Graphics_Device(IntPtr thisPtr, IntPtr renderingDevice, out IntPtr graphicsDevice)
-            {
-                try
-                {
-                    graphicsDevice = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateGraphicsDevice(renderingDevice).ThisPtr;
-                    return 0;
-                }
-                catch (Exception ex)
-                {
-                    graphicsDevice = IntPtr.Zero;
-                    return Marshal.GetHRForException(ex);
-                }
-            }
-        }
-        internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
-
-        public static implicit operator ICompositorInterop(IObjectReference obj) => (obj != null) ? new ICompositorInterop(obj) : null;
-        protected readonly ObjectReference<Vftbl> _obj;
-        public IObjectReference ObjRef { get => _obj; }
-        public IntPtr ThisPtr => _obj.ThisPtr;
-        public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
-        public A As<A>() => _obj.AsType<A>();
-        public ICompositorInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
-        internal ICompositorInterop(ObjectReference<Vftbl> obj)
-        {
-            _obj = obj;
-        }
-
-        public ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain)
-        {            
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForHandle(ThisPtr, swapChain, out var compositionSurface));
-            
-            return null;
-        }
-
-        public ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain)
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForSwapChain(ThisPtr, swapChain, out var compositionSurface));
-
-            return null;            
-        }
-
-        public CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice)
-        {
-            Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateGraphicsDevice(ThisPtr, renderingDevice, out var graphicsDevice));
-
-            return CompositionGraphicsDevice.FromAbi(graphicsDevice);
-        }
-    }
-}
-

+ 0 - 24
src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs

@@ -1,24 +0,0 @@
-using System;
-using System.Runtime.InteropServices;
-using WinRT;
-
-namespace Windows.Graphics.Effects.Interop
-{
-    [WindowsRuntimeType]
-    [Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
-    public interface IGraphicsEffectD2D1Interop
-    {
-        Guid EffectId { get; }
-
-        uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping);
-
-        object GetProperty(uint index);
-
-        uint PropertyCount { get; }
-
-        IGraphicsEffectSource GetSource(uint index);
-
-        uint SourceCount { get; }
-    }
-}
-

+ 0 - 217
src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs

@@ -1,217 +0,0 @@
-using WinRT;
-
-namespace ABI.Windows.Graphics.Effects.Interop
-{
-    using global::System;
-    using global::System.Runtime.InteropServices;
-
-    [Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
-    internal class IGraphicsEffectD2D1Interop : global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop
-
-    {
-        [Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
-        public struct Vftbl
-        {
-            public delegate int _GetEffectId(IntPtr thisPtr, out Guid guid);
-            public delegate int _GetNamedPropertyMapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping);
-            public delegate int _GetProperty(IntPtr thisPtr, uint index, out IntPtr value);
-            public unsafe delegate int _GetPropertyCount(IntPtr thisPtr, uint* count);
-            public delegate int _GetSource(IntPtr thisPtr, uint index, out IntPtr source);
-            public delegate int _GetSourceCount(IntPtr thisPtr, out uint count);
-
-            internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
-            public _GetEffectId GetEffectId;
-            public _GetNamedPropertyMapping GetNamedPropertyMapping;
-            public _GetPropertyCount GetPropertyCount;
-            public _GetProperty GetProperty;
-            public _GetSource GetSource;
-            public _GetSourceCount GetSourceCount;
-
-            public static readonly Vftbl AbiToProjectionVftable;
-            public static readonly IntPtr AbiToProjectionVftablePtr;
-
-            unsafe static Vftbl()
-            {
-                AbiToProjectionVftable = new Vftbl
-                {
-                    IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
-                    GetEffectId = Do_Abi_Get_Effect_Id,
-                    GetNamedPropertyMapping = Do_Abi_Get_Property_Mapping,
-                    GetPropertyCount = Do_Abi_Get_Property_Count,
-                    GetProperty = Do_Abi_Get_Property,
-                    GetSource = Do_Abi_Get_Source,
-                    GetSourceCount = Do_Abi_Get_Source_Count
-
-                };
-                AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
-                Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
-            }
-
-            private static int Do_Abi_Get_Effect_Id(IntPtr thisPtr, out Guid guid)
-            {
-                guid = default;
-
-                try
-                {
-                    guid = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).EffectId;
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-
-            private static int Do_Abi_Get_Property_Mapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping)
-            {
-                try
-                {
-                    ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetNamedPropertyMapping(MarshalString.FromAbi(name), out var mappingResult);
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-
-            private static int Do_Abi_Get_Property(IntPtr thisPtr, uint index, out IntPtr value)
-            {
-                value = default;
-
-                try
-                {
-                    value = MarshalInspectable.CreateMarshaler(
-                        ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetProperty(index))
-                        .As(Guid.Parse("4BD682DD-7554-40E9-9A9B-82654EDE7E62"))
-                        .GetRef();
-
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-
-            unsafe private static int Do_Abi_Get_Property_Count(IntPtr thisPtr, uint* count)
-            {
-
-                try
-                {
-                    var res = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).PropertyCount;
-
-                    if (count != null)
-                    {
-                        *count = res;
-                    }
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-
-            private static int Do_Abi_Get_Source(IntPtr thisPtr, uint index, out IntPtr value)
-            {
-                value = default;
-
-                try
-                {                    
-                    var source = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetSource(index);
-
-                    value = MarshalInterface<global::Windows.Graphics.Effects.IGraphicsEffectSource>.FromManaged(source);
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-
-            private static int Do_Abi_Get_Source_Count(IntPtr thisPtr, out uint count)
-            {
-                count = default;
-
-                try
-                {
-                    count = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).SourceCount;
-                }
-                catch (Exception ex)
-                {
-                    return Marshal.GetHRForException(ex);
-                }
-
-                return 0;
-            }
-        }
-        internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
-
-        public static implicit operator IGraphicsEffectD2D1Interop(IObjectReference obj) => (obj != null) ? new IGraphicsEffectD2D1Interop(obj) : null;
-        protected readonly ObjectReference<Vftbl> _obj;
-        public IObjectReference ObjRef { get => _obj; }
-        public IntPtr ThisPtr => _obj.ThisPtr;
-
-        public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
-        public A As<A>() => _obj.AsType<A>();
-        public IGraphicsEffectD2D1Interop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
-        internal IGraphicsEffectD2D1Interop(ObjectReference<Vftbl> obj)
-        {
-            _obj = obj;
-        }
-
-        public Guid EffectId
-        {
-            get
-            {
-                Marshal.ThrowExceptionForHR(_obj.Vftbl.GetEffectId(ThisPtr, out Guid guid));
-                return guid;
-            }
-        }
-
-        public uint PropertyCount
-        {
-            get
-            {
-                unsafe
-                {
-                    uint count = default;
-                    Marshal.ThrowExceptionForHR(_obj.Vftbl.GetPropertyCount(ThisPtr, &count));
-                    return count;
-                }
-            }
-        }
-
-        public uint SourceCount
-        {
-            get
-            {
-                Marshal.ThrowExceptionForHR(_obj.Vftbl.GetSourceCount(ThisPtr, out uint count));
-                return count;
-            }
-        }
-
-        public uint GetNamedPropertyMapping(string name, out global::Windows.Graphics.Effects.Interop.GRAPHICS_EFFECT_PROPERTY_MAPPING mapping)
-        {
-            throw new NotImplementedException();
-        }
-
-        public object GetProperty(uint index)
-        {
-            // Marshal.ThrowExceptionForHR(_obj.Vftbl.GetProperty(ThisPtr, index, out IntPtr value));
-            throw new NotImplementedException();
-        }
-
-        public global::Windows.Graphics.Effects.IGraphicsEffectSource GetSource(uint index)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
-

+ 0 - 35
src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs

@@ -1,35 +0,0 @@
-using System;
-using Windows.Graphics.Effects;
-
-
-namespace Avalonia.Win32
-{
-    class SaturationEffect : EffectBase
-    {
-        public SaturationEffect(IGraphicsEffectSource source) : base(source)
-        {
-        }
-
-        enum D2D1_SATURATION_PROP
-        {
-            D2D1_SATURATION_PROP_SATURATION,
-            D2D1_SATURATION_PROP_FORCE_DWORD
-        };
-
-        public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation;
-
-        public override uint PropertyCount => 1;
-
-        public override object GetProperty(uint index)
-        {
-            switch ((D2D1_SATURATION_PROP)index)
-            {
-                case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION:
-                    return 2.0f;
-            }
-
-            return null;
-        }
-    }
-}
-

+ 12 - 0
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@@ -1225,6 +1225,9 @@ namespace Avalonia.Win32.Interop
 
         [DllImport("kernel32.dll", SetLastError = true)]
         public static extern IntPtr LoadLibrary(string fileName);
+        
+        [DllImport("kernel32.dll", SetLastError = true)]
+        public static extern IntPtr LoadLibraryEx(string fileName, IntPtr hFile, int flags);
 
         [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
         public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
@@ -1382,6 +1385,9 @@ namespace Avalonia.Win32.Interop
         [DllImport("dwmapi.dll")]
         public static extern int DwmIsCompositionEnabled(out bool enabled);
 
+        [DllImport("dwmapi.dll")]
+        public static extern void DwmFlush();
+        
         [DllImport("dwmapi.dll")]
         public static extern bool DwmDefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref IntPtr plResult);
         
@@ -1613,6 +1619,12 @@ namespace Avalonia.Win32.Interop
             public int X;
             public int Y;
         }
+        
+        public struct SIZE
+        {
+            public int X;
+            public int Y;
+        }
 
         public struct RECT
         {

+ 2 - 1
src/Windows/Avalonia.Win32/PopupImpl.cs

@@ -69,7 +69,8 @@ namespace Avalonia.Win32
         {
             UnmanagedMethods.WindowStyles style =
                 UnmanagedMethods.WindowStyles.WS_POPUP |
-                UnmanagedMethods.WindowStyles.WS_CLIPSIBLINGS;
+                UnmanagedMethods.WindowStyles.WS_CLIPSIBLINGS |
+                UnmanagedMethods.WindowStyles.WS_CLIPCHILDREN;
 
             UnmanagedMethods.WindowStyles exStyle =
                 UnmanagedMethods.WindowStyles.WS_EX_TOOLWINDOW |

+ 3 - 7
src/Windows/Avalonia.Win32/Win32GlManager.cs

@@ -3,6 +3,7 @@ using Avalonia.OpenGL;
 using Avalonia.OpenGL.Angle;
 using Avalonia.OpenGL.Egl;
 using Avalonia.Win32.OpenGl;
+using Avalonia.Win32.WinRT.Composition;
 
 namespace Avalonia.Win32
 {
@@ -24,13 +25,8 @@ namespace Avalonia.Win32
                     var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay());
 
                     if (egl is { } &&
-                        opts?.UseWindowsUIComposition == true)
-                    {
-                        var compositionConnector = CompositionConnector.TryCreate(egl);
-
-                        if (compositionConnector != null)
-                            AvaloniaLocator.CurrentMutable.BindToSelf(compositionConnector);
-                    }
+                        opts?.UseWindowsUIComposition == true) 
+                        WinUICompositorConnection.TryCreateAndRegister(egl);
 
                     return egl;
                 }

+ 130 - 0
src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs

@@ -0,0 +1,130 @@
+using System;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+    class D2DEffects
+    {
+        public static readonly Guid CLSID_D2D12DAffineTransform =
+            new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C);
+
+        public static readonly Guid CLSID_D2D13DPerspectiveTransform =
+            new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB);
+
+        public static readonly Guid CLSID_D2D13DTransform =
+            new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A);
+
+        public static readonly Guid CLSID_D2D1ArithmeticComposite =
+            new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87);
+
+        public static readonly Guid CLSID_D2D1Atlas =
+            new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08);
+
+        public static readonly Guid CLSID_D2D1BitmapSource =
+            new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D);
+
+        public static readonly Guid CLSID_D2D1Blend =
+            new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D);
+
+        public static readonly Guid CLSID_D2D1Border =
+            new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27);
+
+        public static readonly Guid CLSID_D2D1Brightness =
+            new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87);
+
+        public static readonly Guid CLSID_D2D1ColorManagement =
+            new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37);
+
+        public static readonly Guid CLSID_D2D1ColorMatrix =
+            new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11);
+
+        public static readonly Guid CLSID_D2D1Composite =
+            new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D);
+
+        public static readonly Guid CLSID_D2D1ConvolveMatrix =
+            new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E);
+
+        public static readonly Guid CLSID_D2D1Crop =
+            new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B);
+
+        public static readonly Guid CLSID_D2D1DirectionalBlur =
+            new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB);
+
+        public static readonly Guid CLSID_D2D1DiscreteTransfer =
+            new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C);
+
+        public static readonly Guid CLSID_D2D1DisplacementMap =
+            new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90);
+
+        public static readonly Guid CLSID_D2D1DistantDiffuse =
+            new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54);
+
+        public static readonly Guid CLSID_D2D1DistantSpecular =
+            new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA);
+
+        public static readonly Guid CLSID_D2D1DpiCompensation =
+            new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28);
+
+        public static readonly Guid CLSID_D2D1Flood =
+            new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2);
+
+        public static readonly Guid CLSID_D2D1GammaTransfer =
+            new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42);
+
+        public static readonly Guid CLSID_D2D1GaussianBlur =
+            new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5);
+
+        public static readonly Guid CLSID_D2D1Scale =
+            new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7);
+
+        public static readonly Guid CLSID_D2D1Histogram =
+            new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8);
+
+        public static readonly Guid CLSID_D2D1HueRotation =
+            new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6);
+
+        public static readonly Guid CLSID_D2D1LinearTransfer =
+            new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06);
+
+        public static readonly Guid CLSID_D2D1LuminanceToAlpha =
+            new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE);
+
+        public static readonly Guid CLSID_D2D1Morphology =
+            new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02);
+
+        public static readonly Guid CLSID_D2D1OpacityMetadata =
+            new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E);
+
+        public static readonly Guid CLSID_D2D1PointDiffuse =
+            new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20);
+
+        public static readonly Guid CLSID_D2D1PointSpecular =
+            new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22);
+
+        public static readonly Guid CLSID_D2D1Premultiply =
+            new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2);
+
+        public static readonly Guid CLSID_D2D1Saturation =
+            new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7);
+
+        public static readonly Guid CLSID_D2D1Shadow =
+            new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B);
+
+        public static readonly Guid CLSID_D2D1SpotDiffuse =
+            new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93);
+
+        public static readonly Guid CLSID_D2D1SpotSpecular =
+            new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1);
+
+        public static readonly Guid CLSID_D2D1TableTransfer =
+            new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4);
+
+        public static readonly Guid CLSID_D2D1Tile =
+            new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F);
+
+        public static readonly Guid CLSID_D2D1Turbulence =
+            new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9);
+
+        public static readonly Guid CLSID_D2D1UnPremultiply =
+            new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7);
+    }
+}

+ 99 - 0
src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs

@@ -0,0 +1,99 @@
+using System;
+using System.Numerics;
+using System.Reactive.Disposables;
+using System.Threading;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Egl;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+    public class WinUICompositedWindow : IDisposable
+    {
+        private EglContext _syncContext;
+        private readonly object _pumpLock;
+        private readonly IVisual _blurVisual;
+        private ICompositionTarget _compositionTarget;
+        private IVisual _contentVisual;
+        private ICompositionDrawingSurfaceInterop _surfaceInterop;
+        private PixelSize _size;
+
+        private static Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
+        private ICompositor _compositor;
+
+
+        internal WinUICompositedWindow(EglContext syncContext,
+            ICompositor compositor,
+            object pumpLock,
+            ICompositionTarget compositionTarget,
+            ICompositionDrawingSurfaceInterop surfaceInterop,
+            IVisual contentVisual, IVisual blurVisual)
+        {
+            _compositor = compositor.CloneReference();
+            _syncContext = syncContext;
+            _pumpLock = pumpLock;
+            _blurVisual = blurVisual.CloneReference();
+            _compositionTarget = compositionTarget.CloneReference();
+            _contentVisual = contentVisual.CloneReference();
+            _surfaceInterop = surfaceInterop.CloneReference();
+        }
+
+
+        public void ResizeIfNeeded(PixelSize size)
+        {
+            using (_syncContext.EnsureLocked())
+            {
+                if (_size != size)
+                {
+                    _surfaceInterop.Resize(new UnmanagedMethods.POINT { X = size.Width, Y = size.Height });
+                    _contentVisual.SetSize(new Vector2(size.Width, size.Height));
+                    _size = size;
+                }
+            }
+        }
+
+        public unsafe IUnknown BeginDrawToTexture(out PixelPoint offset)
+        {
+            if (!_syncContext.IsCurrent)
+                throw new InvalidOperationException();
+            
+            var iid = IID_ID3D11Texture2D;
+            void* pTexture;
+            var off = _surfaceInterop.BeginDraw(null, &iid, &pTexture);
+            offset = new PixelPoint(off.X, off.Y);
+            return MicroComRuntime.CreateProxyFor<IUnknown>(pTexture, true);
+        }
+
+        public void EndDraw()
+        {
+            if (!_syncContext.IsCurrent)
+                throw new InvalidOperationException();
+            _surfaceInterop.EndDraw();
+        }
+
+        public void SetBlur(bool enable)
+        {
+            using (_syncContext.EnsureLocked())
+                _blurVisual.SetIsVisible(enable ? 1 : 0);
+        }
+
+        public IDisposable BeginTransaction()
+        {
+            Monitor.Enter(_pumpLock);
+            return Disposable.Create(() => Monitor.Exit(_pumpLock));
+        }
+        
+        public void Dispose()
+        {
+            if (_syncContext == null)
+            {
+                _compositor.Dispose();
+                _blurVisual.Dispose();
+                _contentVisual.Dispose();
+                _surfaceInterop.Dispose();
+                _compositionTarget.Dispose();
+            }
+        }
+    }
+}

+ 238 - 0
src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs

@@ -0,0 +1,238 @@
+using System;
+using System.Diagnostics;
+using System.Numerics;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Avalonia.Logging;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL;
+using Avalonia.OpenGL.Angle;
+using Avalonia.OpenGL.Egl;
+using Avalonia.Rendering;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+    class WinUICompositorConnection : IRenderTimer
+    {
+        private readonly EglContext _syncContext;
+        private IntPtr _queue;
+        private ICompositor _compositor;
+        private ICompositor2 _compositor2;
+        private ICompositor5 _compositor5;
+        private ICompositorInterop _compositorInterop;
+        private AngleWin32EglDisplay _angle;
+        private ICompositionGraphicsDevice _device;
+        private EglPlatformOpenGlInterface _gl;
+        private ICompositorDesktopInterop _compositorDesktopInterop;
+        private ICompositionBrush _blurBrush;
+        private object _pumpLock = new object();
+
+        public WinUICompositorConnection(EglPlatformOpenGlInterface gl, object pumpLock)
+        {
+            _gl = gl;
+            _pumpLock = pumpLock;
+            _syncContext = _gl.PrimaryEglContext;
+            _angle = (AngleWin32EglDisplay)_gl.Display;
+            _compositor = NativeWinRTMethods.CreateInstance<ICompositor>("Windows.UI.Composition.Compositor");
+            _compositor2 = _compositor.QueryInterface<ICompositor2>();
+            _compositor5 = _compositor.QueryInterface<ICompositor5>();
+            _compositorInterop = _compositor.QueryInterface<ICompositorInterop>();
+            _compositorDesktopInterop = _compositor.QueryInterface<ICompositorDesktopInterop>();
+            using var device = MicroComRuntime.CreateProxyFor<IUnknown>(_angle.GetDirect3DDevice(), true);
+            
+            _device = _compositorInterop.CreateGraphicsDevice(device);
+            _blurBrush = CreateBlurBrush();
+            
+        }
+
+        public EglPlatformOpenGlInterface Egl => _gl;
+
+        static bool TryCreateAndRegisterCore(EglPlatformOpenGlInterface angle)
+        {
+            var tcs = new TaskCompletionSource<bool>();
+            var pumpLock = new object();
+            var th = new Thread(() =>
+            {
+                WinUICompositorConnection connect;
+                try
+                {
+                    NativeWinRTMethods.CreateDispatcherQueueController(new NativeWinRTMethods.DispatcherQueueOptions
+                    {
+                        apartmentType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE,
+                        dwSize = Marshal.SizeOf<NativeWinRTMethods.DispatcherQueueOptions>(),
+                        threadType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT
+                    });
+                    connect = new WinUICompositorConnection(angle, pumpLock);
+                    AvaloniaLocator.CurrentMutable.BindToSelf(connect);
+                    AvaloniaLocator.CurrentMutable.Bind<IRenderTimer>().ToConstant(connect);
+                    tcs.SetResult(true);
+                    
+                }
+                catch (Exception e)
+                {
+                    tcs.SetException(e);
+                    return;
+                }
+                connect.RunLoop();
+            })
+            {
+                IsBackground = true
+            };
+            th.SetApartmentState(ApartmentState.STA);
+            th.Start();
+            return tcs.Task.Result;
+        }
+
+        class RunLoopHandler : IAsyncActionCompletedHandler, IMicroComShadowContainer
+        {
+            private readonly WinUICompositorConnection _parent;
+            private Stopwatch _st = Stopwatch.StartNew();
+
+            public RunLoopHandler(WinUICompositorConnection parent)
+            {
+                _parent = parent;
+            }
+            public void Dispose()
+            {
+                
+            }
+
+            public void Invoke(IAsyncAction asyncInfo, AsyncStatus asyncStatus)
+            {
+                _parent.Tick?.Invoke(_st.Elapsed);
+                using var act = _parent._compositor5.RequestCommitAsync();
+                act.SetCompleted(this);
+            }
+
+            public MicroComShadow Shadow { get; set; }
+            public void OnReferencedFromNative()
+            {
+            }
+
+            public void OnUnreferencedFromNative()
+            {
+            }
+        }
+        
+        private void RunLoop()
+        {
+            {
+                var st = Stopwatch.StartNew();
+                using (var act = _compositor5.RequestCommitAsync()) 
+                    act.SetCompleted(new RunLoopHandler(this));
+                while (true)
+                {
+                    UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0);
+                    lock (_pumpLock)
+                        UnmanagedMethods.DispatchMessage(ref msg);
+                }
+            }
+        }
+
+        public static void TryCreateAndRegister(EglPlatformOpenGlInterface angle)
+        {
+            const int majorRequired = 10;
+            const int buildRequired = 16299;
+
+            var majorInstalled = Win32Platform.WindowsVersion.Major;
+            var buildInstalled = Win32Platform.WindowsVersion.Build;
+
+            if (majorInstalled >= majorRequired &&
+                buildInstalled >= buildRequired)
+            {
+                try
+                {
+                    TryCreateAndRegisterCore(angle);
+                }
+                catch (Exception e)
+                {
+                    Logger.TryGet(LogEventLevel.Error, "WinUIComposition")
+                        ?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
+
+                }
+            }
+
+            var osVersionNotice =
+                $"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed.";
+
+            Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
+                $"Unable to initialize WinUI compositor: {osVersionNotice}");
+        }
+
+
+        public WinUICompositedWindow CreateWindow(IntPtr hWnd)
+        {
+            using var sc = _syncContext.EnsureLocked();
+            using var desktopTarget = _compositorDesktopInterop.CreateDesktopWindowTarget(hWnd, 0);
+            using var target = desktopTarget.QueryInterface<ICompositionTarget>();
+            
+            using var drawingSurface = _device.CreateDrawingSurface(new UnmanagedMethods.SIZE(), DirectXPixelFormat.B8G8R8A8UIntNormalized,
+                DirectXAlphaMode.Premultiplied);
+            using var surface = drawingSurface.QueryInterface<ICompositionSurface>();
+            using var surfaceInterop = drawingSurface.QueryInterface<ICompositionDrawingSurfaceInterop>();
+            
+            using var surfaceBrush = _compositor.CreateSurfaceBrushWithSurface(surface);
+            using var brush = surfaceBrush.QueryInterface<ICompositionBrush>();
+
+            using var spriteVisual = _compositor.CreateSpriteVisual();
+            spriteVisual.SetBrush(brush);
+            using var visual = spriteVisual.QueryInterface<IVisual>();
+            using var visual2 = spriteVisual.QueryInterface<IVisual2>();
+            using var container = _compositor.CreateContainerVisual();
+            using var containerVisual = container.QueryInterface<IVisual>();
+            using var containerVisual2 = container.QueryInterface<IVisual2>();
+            containerVisual2.SetRelativeSizeAdjustment(new Vector2(1, 1));
+            using var containerChildren = container.Children;
+            
+            target.SetRoot(containerVisual);
+
+            using var blur = CreateBlurVisual(); 
+            
+            containerChildren.InsertAtTop(blur);
+            containerChildren.InsertAtTop(visual);
+            
+            return new WinUICompositedWindow(_syncContext, _compositor, _pumpLock, target, surfaceInterop, visual, blur);
+        }
+
+
+        private unsafe ICompositionBrush CreateBlurBrush()
+        {
+            using var backDropParameterFactory = NativeWinRTMethods.CreateActivationFactory<ICompositionEffectSourceParameterFactory>(
+                "Windows.UI.Composition.CompositionEffectSourceParameter");
+            using var backdropString = new HStringInterop("backdrop");
+            using var backDropParameter =
+                backDropParameterFactory.Create(backdropString.Handle);
+            using var backDropParameterAsSource = backDropParameter.QueryInterface<IGraphicsEffectSource>();
+            var blurEffect = new WinUIGaussianBlurEffect(backDropParameterAsSource);
+            using var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect);
+            using var backdrop = _compositor2.CreateBackdropBrush();
+            using var backdropBrush = backdrop.QueryInterface<ICompositionBrush>();
+            
+            
+            var saturateEffect = new SaturationEffect(blurEffect);
+            using var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect);
+            using var sat = satEffectFactory.CreateBrush();
+            sat.SetSourceParameter(backdropString.Handle, backdropBrush);
+            return sat.QueryInterface<ICompositionBrush>();
+        }
+        
+        private unsafe IVisual CreateBlurVisual()
+        {
+            using var spriteVisual = _compositor.CreateSpriteVisual();
+            using var visual = spriteVisual.QueryInterface<IVisual>();
+            using var visual2 = spriteVisual.QueryInterface<IVisual2>();
+           
+            
+            spriteVisual.SetBrush(_blurBrush);
+            visual.SetIsVisible(0);
+            visual2.SetRelativeSizeAdjustment(new Vector2(1.0f, 1.0f));
+
+            return visual.CloneReference();
+        }
+
+
+        public event Action<TimeSpan> Tick;
+    }
+}

+ 135 - 0
src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs

@@ -0,0 +1,135 @@
+using System;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+    abstract class WinUIEffectBase : WinRTInspectable, IGraphicsEffect,  IGraphicsEffectSource, IGraphicsEffectD2D1Interop
+    {
+        private IGraphicsEffectSource[] _sources;
+
+        public WinUIEffectBase(params IGraphicsEffectSource[] _sources)
+        {
+            this._sources = _sources.Select(e =>
+            {
+                if (e is WinUIEffectBase)
+                    return e;
+                return e.CloneReference();
+            }).ToArray();
+        }
+
+        public IntPtr Name => IntPtr.Zero;
+
+        public void SetName(IntPtr name)
+        {
+            
+        }
+
+        public abstract Guid EffectId { get; }
+        public unsafe void GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping) =>
+            throw new COMException("Not supported", unchecked((int)0x80004001));
+
+        public abstract uint PropertyCount { get; }
+        public abstract IPropertyValue GetProperty(uint index);
+
+        public IGraphicsEffectSource GetSource(uint index)
+        {
+            if (_sources == null || index> _sources.Length)
+                throw new COMException("Invalid index", unchecked((int)0x80070057));
+            return _sources[index];
+        }
+
+        public uint SourceCount => (uint)(_sources?.Length ?? 0);
+
+        public override void OnUnreferencedFromNative()
+        {
+            if (_sources == null)
+                return;
+            
+            /*foreach(var s in _sources)
+                s.Dispose();*/
+            _sources = null;
+        }
+    }
+    
+    class WinUIGaussianBlurEffect : WinUIEffectBase
+    {
+        public WinUIGaussianBlurEffect(IGraphicsEffectSource source) : base(source)
+        {
+        }
+
+        enum D2D1_GAUSSIANBLUR_OPTIMIZATION
+        {
+            D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED,
+            D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED,
+            D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY,
+            D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD
+        };
+
+        enum D2D1_BORDER_MODE
+        {
+            D2D1_BORDER_MODE_SOFT,
+            D2D1_BORDER_MODE_HARD,
+            D2D1_BORDER_MODE_FORCE_DWORD
+        };
+
+        enum D2D1GaussianBlurProp
+        {
+            D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION,
+            D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION,
+            D2D1_GAUSSIANBLUR_PROP_BORDER_MODE,
+            D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD
+        };
+
+        public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur;
+
+        public override uint PropertyCount => 3;
+
+        public override IPropertyValue GetProperty(uint index)
+        {
+            switch ((D2D1GaussianBlurProp)index)
+            {
+                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION:
+                    return new WinRTPropertyValue(30.0f);
+
+                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION:
+                    return new WinRTPropertyValue((uint)D2D1_GAUSSIANBLUR_OPTIMIZATION
+                        .D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED);
+
+                case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE:
+                    return new WinRTPropertyValue((uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD);
+            }
+
+            return null;
+        }
+    }
+    
+    class SaturationEffect : WinUIEffectBase
+    {
+        public SaturationEffect(IGraphicsEffectSource source) : base(source)
+        {
+        }
+
+        enum D2D1_SATURATION_PROP
+        {
+            D2D1_SATURATION_PROP_SATURATION,
+            D2D1_SATURATION_PROP_FORCE_DWORD
+        };
+
+        public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation;
+
+        public override uint PropertyCount => 1;
+
+        public override IPropertyValue GetProperty(uint index)
+        {
+            switch ((D2D1_SATURATION_PROP)index)
+            {
+                case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION:
+                    return new WinRTPropertyValue(2.0f);
+            }
+
+            return null;
+        }
+    }
+}

+ 118 - 0
src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs

@@ -0,0 +1,118 @@
+using System;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+using Avalonia.OpenGL.Angle;
+using Avalonia.OpenGL.Egl;
+using Avalonia.OpenGL.Surfaces;
+using Avalonia.Utilities;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT.Composition
+{
+    internal class WinUiCompositedWindowSurface : EglGlPlatformSurfaceBase, IBlurHost, IDisposable
+    {
+        private readonly WinUICompositorConnection _connection;
+        private EglPlatformOpenGlInterface _egl;
+        private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info;
+        private IRef<WinUICompositedWindow> _window;
+        private bool _enableBlur;
+
+        public WinUiCompositedWindowSurface(WinUICompositorConnection connection, IEglWindowGlPlatformSurfaceInfo info) : base()
+        {
+            _connection = connection;
+            _egl = connection.Egl;
+            _info = info;
+        }
+
+        public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
+        {
+            using (_egl.PrimaryContext.EnsureCurrent())
+            {
+                if (_window?.Item == null)
+                {
+                    _window = RefCountable.Create(_connection.CreateWindow(_info.Handle));
+                    _window.Item.SetBlur(_enableBlur);
+                }
+
+                return new CompositionRenderTarget(_egl, _window, _info);
+            }
+        }
+
+        class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase
+        {
+            private readonly EglPlatformOpenGlInterface _egl;
+            private readonly IRef<WinUICompositedWindow> _window;
+            private readonly IEglWindowGlPlatformSurfaceInfo _info;
+
+            public CompositionRenderTarget(EglPlatformOpenGlInterface egl,
+                IRef<WinUICompositedWindow> window,
+                IEglWindowGlPlatformSurfaceInfo info)
+                : base(egl)
+            {
+                _egl = egl;
+                _window = window.Clone();
+                _info = info;
+                _window.Item.ResizeIfNeeded(_info.Size);
+            }
+
+            public override IGlPlatformSurfaceRenderingSession BeginDraw()
+            {
+                var contextLock = _egl.PrimaryEglContext.EnsureCurrent();
+                IUnknown texture = null;
+                EglSurface surface = null;
+                IDisposable transaction = null;
+                var success = false;
+                try
+                {
+                    if (_window?.Item == null)
+                        throw new ObjectDisposedException(GetType().FullName);
+                    
+                    var size = _info.Size;
+                    transaction = _window.Item.BeginTransaction();
+                    _window.Item.ResizeIfNeeded(size);
+                    texture = _window.Item.BeginDrawToTexture(out var offset);
+
+                    surface = ((AngleWin32EglDisplay) _egl.Display).WrapDirect3D11Texture(_egl,
+                        texture.GetNativeIntPtr(),
+                        offset.X, offset.Y, size.Width, size.Height);
+
+                    var res = base.BeginDraw(surface, _info, () =>
+                    {
+                        surface?.Dispose();
+                        texture?.Dispose();
+                        _window.Item.EndDraw();
+                        transaction?.Dispose();
+                        contextLock?.Dispose();
+                    }, true);
+                    success = true;
+                    return res;
+                }
+                finally
+                {
+                    if (!success)
+                    {
+                        surface?.Dispose();
+                        texture?.Dispose();
+                        transaction?.Dispose();
+                        contextLock.Dispose();
+                    }
+                }
+            }
+        }
+
+        public void SetBlur(bool enable)
+        {
+            _enableBlur = enable;
+            _window?.Item?.SetBlur(enable);
+        }
+
+        public void Dispose()
+        {
+            using (_egl.PrimaryEglContext.EnsureLocked())
+            {
+                _window?.Dispose();
+                _window = null;
+            }
+        }
+    }
+}

+ 7 - 0
src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs

@@ -0,0 +1,7 @@
+namespace Avalonia.Win32.WinRT
+{
+    public interface IBlurHost
+    {
+        void SetBlur(bool enable);
+    }
+}

+ 140 - 0
src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs

@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+using System.Threading;
+using Avalonia.MicroCom;
+using Avalonia.Win32.Interop;
+
+namespace Avalonia.Win32.WinRT
+{
+    internal static class NativeWinRTMethods
+    {
+        [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall,
+            PreserveSig = false)]
+        internal static extern unsafe IntPtr WindowsCreateString(
+            [MarshalAs(UnmanagedType.LPWStr)] string sourceString,
+            int length);
+
+        internal static IntPtr WindowsCreateString(string sourceString) 
+            => WindowsCreateString(sourceString, sourceString.Length);
+
+        [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", 
+            CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
+        internal static extern unsafe IntPtr WindowsDeleteString(IntPtr hString);
+        
+        [DllImport("Windows.UI.Composition", EntryPoint = "DllGetActivationFactory",
+            CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
+        private extern static IntPtr GetWindowsUICompositionActivationFactory(
+            IntPtr activatableClassId);
+
+        internal static IActivationFactory GetWindowsUICompositionActivationFactory(string className)
+        {//"Windows.UI.Composition.Compositor"
+            var s = WindowsCreateString(className);
+            var factory = GetWindowsUICompositionActivationFactory(s);
+            return MicroComRuntime.CreateProxyFor<IActivationFactory>(factory, true);
+        }
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        delegate int GetActivationFactoryDelegate(IntPtr classId, out IntPtr ppv);
+        
+        internal static T CreateInstance<T>(string fullName) where T : IUnknown
+        {
+            var s = WindowsCreateString(fullName);
+            EnsureRoInitialized();
+            var pUnk = RoActivateInstance(s);
+            using var unk = MicroComRuntime.CreateProxyFor<IUnknown>(pUnk, true);
+            WindowsDeleteString(s);
+            return MicroComRuntime.QueryInterface<T>(unk);
+        }
+        
+        internal static TFactory CreateActivationFactory<TFactory>(string fullName) where TFactory : IUnknown
+        {
+            var s = WindowsCreateString(fullName);
+            EnsureRoInitialized();
+            var guid = MicroComRuntime.GetGuidFor(typeof(TFactory));
+            var pUnk = RoGetActivationFactory(s, ref guid);
+            using var unk = MicroComRuntime.CreateProxyFor<IUnknown>(pUnk, true);
+            WindowsDeleteString(s);
+            return MicroComRuntime.QueryInterface<TFactory>(unk);
+        }
+        
+        internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
+        {
+            DQTAT_COM_NONE = 0,
+            DQTAT_COM_ASTA = 1,
+            DQTAT_COM_STA = 2
+        };
+
+        internal enum DISPATCHERQUEUE_THREAD_TYPE
+        {
+            DQTYPE_THREAD_DEDICATED = 1,
+            DQTYPE_THREAD_CURRENT = 2,
+        };
+
+        [StructLayout(LayoutKind.Sequential)]
+        internal struct DispatcherQueueOptions
+        {
+            public int dwSize;
+
+            [MarshalAs(UnmanagedType.I4)]
+            public DISPATCHERQUEUE_THREAD_TYPE threadType;
+
+            [MarshalAs(UnmanagedType.I4)]
+            public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
+        };
+
+        [DllImport("coremessaging.dll", PreserveSig = false)]
+        internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options);
+
+        internal enum RO_INIT_TYPE
+        {
+            RO_INIT_SINGLETHREADED = 0, // Single-threaded application
+            RO_INIT_MULTITHREADED = 1, // COM calls objects on any thread.
+        }
+
+        [DllImport("combase.dll", PreserveSig = false)]
+        private static extern void RoInitialize(RO_INIT_TYPE initType);
+
+        [DllImport("combase.dll", PreserveSig = false)]
+        private static extern IntPtr RoActivateInstance(IntPtr activatableClassId);
+
+        [DllImport("combase.dll", PreserveSig = false)]
+        private static extern IntPtr RoGetActivationFactory(IntPtr activatableClassId, ref Guid iid);
+        
+        private static bool _initialized;
+        private static void EnsureRoInitialized()
+        {
+            if (_initialized)
+                return;
+            RoInitialize(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA ?
+                RO_INIT_TYPE.RO_INIT_SINGLETHREADED :
+                RO_INIT_TYPE.RO_INIT_MULTITHREADED);
+            _initialized = true;
+        }
+    }
+
+    class HStringInterop : IDisposable
+    {
+        private IntPtr _s;
+
+        public HStringInterop(string s)
+        {
+            _s = s == null ? IntPtr.Zero : NativeWinRTMethods.WindowsCreateString(s);
+        }
+
+        public IntPtr Handle => _s;
+
+        public void Dispose()
+        {
+            if (_s != IntPtr.Zero)
+            {
+                NativeWinRTMethods.WindowsDeleteString(_s);
+                _s = IntPtr.Zero;
+            }
+        }
+    }
+}

+ 18 - 0
src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs

@@ -0,0 +1,18 @@
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Win32.WinRT
+{
+    [StructLayout(LayoutKind.Sequential, Pack = 1)]
+    public struct WinRTColor
+    {
+        public byte A;
+        public byte R;
+        public byte G;
+        public byte B;
+
+        public static WinRTColor FromArgb(byte a, byte r, byte g, byte b) => new WinRTColor()
+        {
+            A = a, R = r, G = g, B = b
+        };
+    }
+}

+ 38 - 0
src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Avalonia.MicroCom;
+
+namespace Avalonia.Win32.WinRT
+{
+    class WinRTInspectable : IInspectable, IMicroComShadowContainer
+    {
+        public virtual void Dispose()
+        {
+            
+        }
+
+        public unsafe void GetIids(ulong* iidCount, Guid** iids)
+        {
+            var interfaces = GetType().GetInterfaces().Where(typeof(IUnknown).IsAssignableFrom)
+                .Select(MicroComRuntime.GetGuidFor).ToArray();
+            var mem = (Guid*)Marshal.AllocCoTaskMem(Unsafe.SizeOf<Guid>() * interfaces.Length);
+            for (var c = 0; c < interfaces.Length; c++)
+                mem[c] = interfaces[c];
+            *iids = mem;
+            *iidCount = (ulong) interfaces.Length;
+        }
+
+        public IntPtr RuntimeClassName => NativeWinRTMethods.WindowsCreateString(GetType().FullName);
+        public TrustLevel TrustLevel => TrustLevel.BaseTrust;
+        public MicroComShadow Shadow { get; set; }
+        public virtual void OnReferencedFromNative()
+        {
+        }
+
+        public virtual void OnUnreferencedFromNative()
+        {
+        }
+    }
+}

+ 89 - 0
src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs

@@ -0,0 +1,89 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Avalonia.Win32.WinRT
+{
+    class WinRTPropertyValue : WinRTInspectable, IPropertyValue 
+    {
+        public WinRTPropertyValue(float f)
+        {
+            Type = PropertyType.Single;
+            Single = f;
+        }
+
+        public WinRTPropertyValue(uint u)
+        {
+            UInt32 = u;
+            Type = PropertyType.UInt32;
+        }
+        
+        public PropertyType Type { get; }
+        public int IsNumericScalar { get; }
+        public byte UInt8 { get; }
+        public short Int16 { get; }
+        public ushort UInt16 { get; }
+        public int Int32 { get; }
+        public uint UInt32 { get; }
+        public long Int64 { get; }
+        public ulong UInt64 { get; }
+        public float Single { get; }
+        public double Double { get; }
+        public char Char16 { get; }
+        public int Boolean { get; }
+        public IntPtr String { get; }
+        public Guid Guid { get; }
+
+        private static COMException NotImplemented => new COMException("Not supported", unchecked((int)0x80004001));
+        
+        public unsafe void GetDateTime(void* value) => throw NotImplemented;
+
+        public unsafe void GetTimeSpan(void* value) => throw NotImplemented;
+
+        public unsafe void GetPoint(void* value) => throw NotImplemented;
+
+        public unsafe void GetSize(void* value) => throw NotImplemented;
+
+        public unsafe void GetRect(void* value) => throw NotImplemented;
+
+        public unsafe byte* GetUInt8Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe short* GetInt16Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe ushort* GetUInt16Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe int* GetInt32Array(uint* __valueSize)
+        {
+            throw NotImplemented;
+        }
+
+        public unsafe uint* GetUInt32Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe long* GetInt64Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe ulong* GetUInt64Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe float* GetSingleArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe double* GetDoubleArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe char* GetChar16Array(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe int* GetBooleanArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe IntPtr* GetStringArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void** GetInspectableArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe Guid* GetGuidArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void* GetDateTimeArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void* GetTimeSpanArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void* GetPointArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void* GetSizeArray(uint* __valueSize) => throw NotImplemented;
+
+        public unsafe void* GetRectArray(uint* __valueSize) => throw NotImplemented;
+    }
+}

+ 718 - 0
src/Windows/Avalonia.Win32/WinRT/winrt.idl

@@ -0,0 +1,718 @@
+@clr-namespace Avalonia.Win32.WinRT
+@clr-access internal
+@clr-map FLOAT float
+@clr-map HSTRING IntPtr
+@clr-map Vector2 System.Numerics.Vector2
+@clr-map Vector3 System.Numerics.Vector3
+@clr-map Quaternion System.Numerics.Quaternion
+@clr-map Matrix4x4 System.Numerics.Matrix4x4
+@clr-map RECT Avalonia.Win32.Interop.UnmanagedMethods.RECT
+@clr-map SIZE Avalonia.Win32.Interop.UnmanagedMethods.SIZE
+@clr-map POINT Avalonia.Win32.Interop.UnmanagedMethods.POINT
+@clr-map HWND IntPtr
+@clr-map BOOL int
+@clr-map DWORD int
+@clr-map boolean int
+@clr-map BYTE byte
+@clr-map INT16 short
+@clr-map INT32 int
+@clr-map INT64 long
+@clr-map UINT16 ushort
+@clr-map UINT32 uint
+@clr-map UINT64 ulong
+@clr-map DOUBLE double
+@clr-map GUID System.Guid
+@clr-map WCHAR System.Char
+@clr-map Color Avalonia.Win32.WinRT.WinRTColor
+
+enum TrustLevel
+{
+    BaseTrust,
+    PartialTrust,
+    FullTrust
+}
+
+enum DirectXAlphaMode
+{
+ Unspecified,
+ Premultiplied,
+ Straight,
+ Ignore
+}
+
+enum DirectXPixelFormat
+{
+    Unknown = 0,
+    R32G32B32A32Typeless = 1,
+    R32G32B32A32Float = 2,
+    R32G32B32A32UInt = 3,
+    R32G32B32A32Int = 4,
+    R32G32B32Typeless = 5,
+    R32G32B32Float = 6,
+    R32G32B32UInt = 7,
+    R32G32B32Int = 8,
+    R16G16B16A16Typeless = 9,
+    R16G16B16A16Float = 10, 
+    R16G16B16A16UIntNormalized = 11, 
+    R16G16B16A16UInt = 12, 
+    R16G16B16A16IntNormalized = 13, 
+    R16G16B16A16Int = 14, 
+    R32G32Typeless = 15, 
+    R32G32Float = 16, 
+    R32G32UInt = 17, 
+    R32G32Int = 18, 
+    R32G8X24Typeless = 19, 
+    D32FloatS8X24UInt = 20, 
+    R32FloatX8X24Typeless = 21, 
+    X32TypelessG8X24UInt = 22, 
+    R10G10B10A2Typeless = 23, 
+    R10G10B10A2UIntNormalized = 24, 
+    R10G10B10A2UInt = 25, 
+    R11G11B10Float = 26, 
+    R8G8B8A8Typeless = 27, 
+    R8G8B8A8UIntNormalized = 28, 
+    R8G8B8A8UIntNormalizedSrgb = 29, 
+    R8G8B8A8UInt = 30, 
+    R8G8B8A8IntNormalized = 31, 
+    R8G8B8A8Int = 32, 
+    R16G16Typeless = 33, 
+    R16G16Float = 34, 
+    R16G16UIntNormalized = 35, 
+    R16G16UInt = 36, 
+    R16G16IntNormalized = 37, 
+    R16G16Int = 38, 
+    R32Typeless = 39, 
+    D32Float = 40, 
+    R32Float = 41, 
+    R32UInt = 42, 
+    R32Int = 43, 
+    R24G8Typeless = 44, 
+    D24UIntNormalizedS8UInt = 45, 
+    R24UIntNormalizedX8Typeless = 46, 
+    X24TypelessG8UInt = 47, 
+    R8G8Typeless = 48, 
+    R8G8UIntNormalized = 49, 
+    R8G8UInt = 50, 
+    R8G8IntNormalized = 51, 
+    R8G8Int = 52, 
+    R16Typeless = 53, 
+    R16Float = 54, 
+    D16UIntNormalized = 55, 
+    R16UIntNormalized = 56, 
+    R16UInt = 57, 
+    R16IntNormalized = 58, 
+    R16Int = 59, 
+    R8Typeless = 60, 
+    R8UIntNormalized = 61, 
+    R8UInt = 62, 
+    R8IntNormalized = 63, 
+    R8Int = 64, 
+    A8UIntNormalized = 65, 
+    R1UIntNormalized = 66, 
+    R9G9B9E5SharedExponent = 67, 
+    R8G8B8G8UIntNormalized = 68, 
+    G8R8G8B8UIntNormalized = 69, 
+    BC1Typeless = 70, 
+    BC1UIntNormalized = 71, 
+    BC1UIntNormalizedSrgb = 72, 
+    BC2Typeless = 73, 
+    BC2UIntNormalized = 74, 
+    BC2UIntNormalizedSrgb = 75, 
+    BC3Typeless = 76, 
+    BC3UIntNormalized = 77, 
+    BC3UIntNormalizedSrgb = 78, 
+    BC4Typeless = 79, 
+    BC4UIntNormalized = 80, 
+    BC4IntNormalized = 81, 
+    BC5Typeless = 82, 
+    BC5UIntNormalized = 83, 
+    BC5IntNormalized = 84, 
+    B5G6R5UIntNormalized = 85, 
+    B5G5R5A1UIntNormalized = 86, 
+    B8G8R8A8UIntNormalized = 87, 
+    B8G8R8X8UIntNormalized = 88, 
+    R10G10B10XRBiasA2UIntNormalized = 89, 
+    B8G8R8A8Typeless = 90, 
+    B8G8R8A8UIntNormalizedSrgb = 91, 
+    B8G8R8X8Typeless = 92, 
+    B8G8R8X8UIntNormalizedSrgb = 93, 
+    BC6HTypeless = 94, 
+    BC6H16UnsignedFloat = 95, 
+    BC6H16Float = 96, 
+    BC7Typeless = 97, 
+    BC7UIntNormalized = 98, 
+    BC7UIntNormalizedSrgb = 99, 
+    Ayuv = 100, 
+    Y410 = 101, 
+    Y416 = 102, 
+    NV12 = 103, 
+    P010 = 104, 
+    P016 = 105, 
+    Opaque420 = 106, 
+    Yuy2 = 107, 
+    Y210 = 108, 
+    Y216 = 109, 
+    NV11 = 110, 
+    AI44 = 111, 
+    IA44 = 112, 
+    P8 = 113, 
+    A8P8 = 114, 
+    B4G4R4A4UIntNormalized = 115, 
+    P208 = 130, 
+    V208 = 131, 
+    V408 = 132, 
+}
+
+[uuid(AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90)]
+interface IInspectable : IUnknown
+{
+    HRESULT GetIids(ulong * iidCount, Guid ** iids);
+    HRESULT GetRuntimeClassName( [out] IntPtr* className);
+    HRESULT GetTrustLevel([out] TrustLevel * trustLevel);
+}
+
+enum PropertyType
+{
+    Empty            = 0,
+    UInt8            = 1,
+    Int16            = 2,
+    UInt16           = 3,
+    Int32            = 4,
+    UInt32           = 5,
+    Int64            = 6,
+    UInt64           = 7,
+    Single           = 8,
+    Double           = 9,
+    Char16           = 10,
+    Boolean          = 11,
+    String           = 12,
+    Inspectable      = 13,
+    DateTime         = 14,
+    TimeSpan         = 15,
+    Guid             = 16,
+    Point            = 17,
+    Size             = 18,
+    Rect             = 19,
+    OtherType        = 20,
+    UInt8Array       = 1025,
+    Int16Array       = 1026,
+    UInt16Array      = 1027,
+    Int32Array       = 1028,
+    UInt32Array      = 1029,
+    Int64Array       = 1030,
+    UInt64Array      = 1031,
+    SingleArray      = 1032,
+    DoubleArray      = 1033,
+    Char16Array      = 1034,
+    BooleanArray     = 1035,
+    StringArray      = 1036,
+    InspectableArray = 1037,
+    DateTimeArray    = 1038,
+    TimeSpanArray    = 1039,
+    GuidArray        = 1040,
+    PointArray       = 1041,
+    SizeArray        = 1042,
+    RectArray        = 1043,
+    OtherTypeArray   = 1044
+}
+
+[uuid(4BD682DD-7554-40E9-9A9B-82654EDE7E62)]
+interface IPropertyValue : IInspectable
+{
+    [propget] HRESULT Type([out] [retval] PropertyType* value);
+    [propget] HRESULT IsNumericScalar([out] [retval] boolean* value);
+    HRESULT GetUInt8([out] [retval] BYTE* value);
+    HRESULT GetInt16([out] [retval] INT16* value);
+    HRESULT GetUInt16([out] [retval] UINT16* value);
+    HRESULT GetInt32([out] [retval] INT32* value);
+    HRESULT GetUInt32([out] [retval] UINT32* value);
+    HRESULT GetInt64([out] [retval] INT64* value);
+    HRESULT GetUInt64([out] [retval] UINT64* value);
+    HRESULT GetSingle([out] [retval] FLOAT* value);
+    HRESULT GetDouble([out] [retval] DOUBLE* value);
+    HRESULT GetChar16([out] [retval] WCHAR* value);
+    HRESULT GetBoolean([out] [retval] boolean* value);
+    HRESULT GetString([out] [retval] HSTRING* value);
+    HRESULT GetGuid([out] [retval] GUID* value);
+    HRESULT GetDateTime( void* value);
+    HRESULT GetTimeSpan(void* value);
+    HRESULT GetPoint(void* value);
+    HRESULT GetSize(void* value);
+    HRESULT GetRect(void* value);
+    HRESULT GetUInt8Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] BYTE** value);
+    HRESULT GetInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT16** value);
+    HRESULT GetUInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT16** value);
+    HRESULT GetInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT32** value);
+    HRESULT GetUInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT32** value);
+    HRESULT GetInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT64** value);
+    HRESULT GetUInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT64** value);
+    HRESULT GetSingleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] FLOAT** value);
+    HRESULT GetDoubleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] DOUBLE** value);
+    HRESULT GetChar16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] WCHAR** value);
+    HRESULT GetBooleanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] boolean** value);
+    HRESULT GetStringArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] HSTRING** value);
+    HRESULT GetInspectableArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void*** value);
+    HRESULT GetGuidArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] GUID** value);
+    HRESULT GetDateTimeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+    HRESULT GetTimeSpanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+    HRESULT GetPointArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+    HRESULT GetSizeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+    HRESULT GetRectArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
+}
+
+enum AsyncStatus {
+  Started = 0,
+  Completed, 
+  Canceled, 
+  Error,
+}
+
+[uuid(A4ED5C81-76C9-40BD-8BE6-B1D90FB20AE7)]
+interface IAsyncActionCompletedHandler : IUnknown
+{
+    HRESULT Invoke([in] IAsyncAction* asyncInfo, [in] AsyncStatus asyncStatus);
+}
+
+[uuid(5A648006-843A-4DA9-865B-9D26E5DFAD7B)]
+interface IAsyncAction : IInspectable
+{
+    HRESULT SetCompleted([in] IAsyncActionCompletedHandler* handler);
+    HRESULT GetCompleted([out] [retval] IAsyncActionCompletedHandler** ppv);
+    HRESULT GetResults();
+}
+
+[uuid(603E88E4-A338-4FFE-A457-A5CFB9CEB899)]
+interface IDispatcherQueue : IInspectable
+{
+    //TODO
+}
+
+[uuid(22F34E66-50DB-4E36-A98D-61C01B384D20)]
+interface IDispatcherQueueController : IInspectable
+{
+    [propget] HRESULT DispatcherQueue([out] [retval] IDispatcherQueue** value);
+    HRESULT ShutdownQueueAsync([out] [retval] IAsyncAction** operation);
+}
+
+[uuid(00000035-0000-0000-C000-000000000046)]
+interface IActivationFactory : IInspectable
+{
+    HRESULT ActivateInstance([out, retval] IntPtr* instance);
+}
+
+[flags]
+enum CompositionBatchTypes
+{
+    None              = 0x0,
+    Animation         = 0x1,
+    Effect            = 0x2,
+    InfiniteAnimation = 0x4,
+    AllAnimations     = 0x5
+}
+
+[uuid(B403CA50-7F8C-4E83-985F-CC45060036D8)]
+interface ICompositor : IInspectable
+{
+    HRESULT CreateColorKeyFrameAnimation([out] [retval] void** result);
+    [overload("CreateColorBrush")] HRESULT CreateColorBrush([out] [retval]void** result);
+    [overload("CreateColorBrush")] HRESULT CreateColorBrushWithColor([in] Color* color, [out] [retval] ICompositionColorBrush** result);
+    HRESULT CreateContainerVisual([out] [retval] IContainerVisual** result);
+    HRESULT CreateCubicBezierEasingFunction([in] Vector2 controlPoint1, [in] Vector2 controlPoint2, [out] [retval] void** result);
+    [overload("CreateEffectFactory")] HRESULT CreateEffectFactory([in] IGraphicsEffect* graphicsEffect, [out] [retval] ICompositionEffectFactory** result);
+    [overload("CreateEffectFactory")] HRESULT CreateEffectFactoryWithProperties([in] void* graphicsEffect, [in] void* animatableProperties, [out] [retval] void** result);
+    [overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimation([out] [retval] void** result);
+    [overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimationWithExpression([in] HSTRING expression, [out] [retval] void** result);
+    [overload("CreateInsetClip")] HRESULT CreateInsetClip([out] [retval] void** result);
+    [overload("CreateInsetClip")] HRESULT CreateInsetClipWithInsets([in] FLOAT leftInset, [in] FLOAT topInset, [in] FLOAT rightInset, [in] FLOAT bottomInset, [out] [retval] void** result);
+    HRESULT CreateLinearEasingFunction([out] [retval] void** result);
+    HRESULT CreatePropertySet([out] [retval] void** result);
+    HRESULT CreateQuaternionKeyFrameAnimation([out] [retval] void** result);
+    HRESULT CreateScalarKeyFrameAnimation([out] [retval] void** result);
+    HRESULT CreateScopedBatch([in] CompositionBatchTypes batchType, [out] [retval] ICompositionScopedBatch** result);
+    HRESULT CreateSpriteVisual([out] [retval] ISpriteVisual** result);
+    HRESULT CreateSurfaceBrush([out] [retval] ICompositionSurfaceBrush** result);
+    HRESULT CreateSurfaceBrushWithSurface([in] ICompositionSurface* surface, 
+        [out] [retval] ICompositionSurfaceBrush** result);
+    HRESULT CreateTargetForCurrentView([out] [retval] void** result);
+    HRESULT CreateVector2KeyFrameAnimation([out] [retval] void** result);
+    HRESULT CreateVector3KeyFrameAnimation([out] [retval] void** result);
+    HRESULT CreateVector4KeyFrameAnimation([out] [retval] void** result);
+    HRESULT GetCommitBatch([in]  CompositionBatchTypes batchType, [out] [retval] void** result);
+}
+
+[uuid(735081DC-5E24-45DA-A38F-E32CC349A9A0)]
+interface ICompositor2 : IInspectable
+{
+    HRESULT CreateAmbientLight([out] [retval] void** result);
+    HRESULT CreateAnimationGroup([out] [retval] void** result);
+    HRESULT CreateBackdropBrush([out] [retval] ICompositionBackdropBrush** result);
+    HRESULT CreateDistantLight([out] [retval] void** result);
+    HRESULT CreateDropShadow([out] [retval] void** result);
+    HRESULT CreateImplicitAnimationCollection([out] [retval] void** result);
+    HRESULT CreateLayerVisual([out] [retval] void** result);
+    HRESULT CreateMaskBrush([out] [retval] void** result);
+    HRESULT CreateNineGridBrush([out] [retval] void** result);
+    HRESULT CreatePointLight([out] [retval] void** result);
+    HRESULT CreateSpotLight([out] [retval] void** result);
+    [overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunction([out] [retval] void** result);
+    [overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunctionWithStepCount([in] INT32 stepCount, [out] [retval] void** result);
+}
+
+[uuid(08E05581-1AD1-4F97-9757-402D76E4233B)]
+interface ISpriteVisual : IInspectable
+{
+    [propget] HRESULT GetBrush([out] [retval] ICompositionBrush** value);
+    [propput] HRESULT SetBrush([in] ICompositionBrush* value);
+}
+
+[uuid(FD04E6E3-FE0C-4C3C-AB19-A07601A576EE)]
+interface ICompositionDrawingSurfaceInterop : IUnknown
+{
+    HRESULT BeginDraw(RECT* updateRect, Guid* iid, void** updateObject, [out, retval]POINT* updateOffset);
+    HRESULT EndDraw();
+    HRESULT Resize(POINT sizePixels);
+    HRESULT Scroll(RECT * scrollRect, RECT * clipRect, int offsetX, int offsetY);
+    HRESULT ResumeDraw();
+    HRESULT SuspendDraw();
+};
+
+[uuid(A116FF71-F8BF-4C8A-9C98-70779A32A9C8)]
+interface ICompositionGraphicsDeviceInterop : IUnknown
+{
+    HRESULT GetRenderingDevice([out] IUnknown ** value);
+    HRESULT SetRenderingDevice([out] IUnknown * value);
+};
+
+[uuid(25297D5C-3AD4-4C9C-B5CF-E36A38512330)]
+interface ICompositorInterop : IUnknown
+{
+    HRESULT CreateCompositionSurfaceForHandle(IntPtr swapChain, [out] ICompositionSurface ** res);
+    HRESULT CreateCompositionSurfaceForSwapChain(IUnknown* swapChain, [out] ICompositionSurface ** result);
+    HRESULT CreateGraphicsDevice(IUnknown * renderingDevice, [out] ICompositionGraphicsDevice ** result);
+};
+
+[uuid(26f496a0-7f38-45fb-88f7-faaabe67dd59)]
+interface ISwapChainInterop : IUnknown
+{
+    HRESULT SetSwapChain(IUnknown * swapChain);
+};
+
+/*
+[uuid(2C9DB356-E70D-4642-8298-BC4AA5B4865C)]
+interface ICompositionCapabilitiesInteropFactory : IInspectable
+{
+    HRESULT GetForWindow(IntPtr hwnd, [out] ICompositionCapabilities ** result);
+}*/
+
+[uuid(29E691FA-4567-4DCA-B319-D0F207EB6807)]
+interface ICompositorDesktopInterop : IUnknown
+{
+    HRESULT CreateDesktopWindowTarget(HWND hwndTarget, BOOL isTopmost, [out] IDesktopWindowTarget ** result);
+    HRESULT EnsureOnThread(DWORD threadId);
+};
+
+
+[uuid(35DBF59E-E3F9-45B0-81E7-FE75F4145DC9)]
+interface IDesktopWindowTargetInterop : IUnknown
+{
+    HRESULT GetHWnd([out] IntPtr* value);
+};
+
+[uuid(37642806-F421-4FD0-9F82-23AE7C776182)]
+interface IDesktopWindowContentBridgeInterop : IUnknown
+{
+    HRESULT Initialize(ICompositor* compositor, HWND parentHwnd);
+    HRESULT GetHWnd([out] IntPtr* value);
+
+    HRESULT GetAppliedScaleFactor([out] float* value);
+};
+
+[uuid(FB22C6E1-80A2-4667-9936-DBEAF6EEFE95)]
+interface ICompositionGraphicsDevice : IInspectable
+{
+    HRESULT CreateDrawingSurface([in] SIZE sizePixels, [in] DirectXPixelFormat pixelFormat,
+        [in] DirectXAlphaMode alphaMode, [out] [retval] ICompositionDrawingSurface** result);
+    HRESULT AddRenderingDeviceReplaced(void* handler, void* token);
+    HRESULT RemoveRenderingDeviceReplaced([in] int token);
+}
+
+[uuid(1527540D-42C7-47A6-A408-668F79A90DFB)]
+interface ICompositionSurface : IInspectable
+{
+}
+
+[uuid(6329D6CA-3366-490E-9DB3-25312929AC51)]
+interface IDesktopWindowTarget : IInspectable
+{
+    [propget] HRESULT IsTopmost([out] [retval] int* value);
+}
+
+
+[uuid(A166C300-FAD0-4D11-9E67-E433162FF49E)]
+interface ICompositionDrawingSurface : IInspectable
+{
+    [propget] HRESULT GetAlphaMode([out] [retval] DirectXAlphaMode* value);
+    [propget] HRESULT GetPixelFormat([out] [retval] DirectXPixelFormat* value);
+    [propget] HRESULT GetSize([out] [retval] POINT* value);
+}
+
+enum CompositionBitmapInterpolationMode
+{
+    NearestNeighbor,
+    Linear,
+    MagLinearMinLinearMipLinear,
+    MagLinearMinLinearMipNearest,
+    MagLinearMinNearestMipLinear,
+    MagLinearMinNearestMipNearest,
+    MagNearestMinLinearMipLinear,
+    MagNearestMinLinearMipNearest,
+    MagNearestMinNearestMipLinear,
+    MagNearestMinNearestMipNearest,
+}
+
+enum CompositionStretch
+{
+    None,
+    Fill,
+    Uniform,
+    UniformToFill,
+}
+
+[uuid(AD016D79-1E4C-4C0D-9C29-83338C87C162)]
+interface ICompositionSurfaceBrush : IInspectable
+{
+    [propget] HRESULT BitmapInterpolationMode([out] [retval] CompositionBitmapInterpolationMode* value);
+    [propput] HRESULT BitmapInterpolationMode([in] CompositionBitmapInterpolationMode value);
+    [propget] HRESULT HorizontalAlignmentRatio([out] [retval] FLOAT* value);
+    [propput] HRESULT HorizontalAlignmentRatio([in] FLOAT value);
+    [propget] HRESULT Stretch([out] [retval] CompositionStretch* value);
+    [propput] HRESULT Stretch([in] CompositionStretch value);
+    [propget] HRESULT Surface([out] [retval] ICompositionSurface** value);
+    [propput] HRESULT Surface([in] ICompositionSurface* value);
+    [propget] HRESULT VerticalAlignmentRatio([out] [retval] FLOAT* value);
+    [propput] HRESULT VerticalAlignmentRatio([in] FLOAT value);
+}
+
+[uuid(AB0D7608-30C0-40E9-B568-B60A6BD1FB46)]
+interface ICompositionBrush : IInspectable
+{
+}
+
+enum CompositionBackfaceVisibility
+{
+    Inherit,
+    Visible,
+    Hidden
+}
+
+enum CompositionBorderMode
+{
+    Inherit,
+    Soft,
+    Hard
+}
+
+enum CompositionCompositeMode
+{
+    Inherit,
+    SourceOver,
+    DestinationInvert,
+    MinBlend,
+}
+
+[uuid(117E202D-A859-4C89-873B-C2AA566788E3)]
+interface IVisual : IInspectable
+{
+    [propget] HRESULT AnchorPoint([out] [retval] Vector2* value);
+    [propput] HRESULT AnchorPoint([in] Vector2 value);
+    [propget] HRESULT BackfaceVisibility([out] [retval] CompositionBackfaceVisibility* value);
+    [propput] HRESULT BackfaceVisibility([in] CompositionBackfaceVisibility value);
+    [propget] HRESULT BorderMode([out] [retval] CompositionBorderMode* value);
+    [propput] HRESULT BorderMode([in] CompositionBorderMode value);
+    [propget] HRESULT CenterPoint([out] [retval] Vector3* value);
+    [propput] HRESULT CenterPoint([in] Vector3 value);
+    [propget] HRESULT Clip([out] [retval]void** value);
+    [propput] HRESULT Clip([in] void* value);
+    [propget] HRESULT CompositeMode([out] [retval] CompositionCompositeMode* value);
+    [propput] HRESULT CompositeMode([in] CompositionCompositeMode value);
+    [propget] HRESULT IsVisible([out] [retval] boolean* value);
+    [propput] HRESULT IsVisible([in] boolean value);
+    [propget] HRESULT Offset([out] [retval] Vector3* value);
+    [propput] HRESULT Offset([in] Vector3 value);
+    [propget] HRESULT Opacity([out] [retval] FLOAT* value);
+    [propput] HRESULT Opacity([in] FLOAT value);
+    [propget] HRESULT Orientation([out] [retval] Quaternion* value);
+    [propput] HRESULT Orientation([in] Quaternion value);
+    [propget] HRESULT Parent([out] [retval] IContainerVisual** value);
+    [propget] HRESULT RotationAngle([out] [retval] FLOAT* value);
+    [propput] HRESULT RotationAngle([in] FLOAT value);
+    [propget] HRESULT RotationAngleInDegrees([out] [retval] FLOAT* value);
+    [propput] HRESULT RotationAngleInDegrees([in] FLOAT value);
+    [propget] HRESULT RotationAxis([out] [retval] Vector3* value);
+    [propput] HRESULT RotationAxis([in] Vector3 value);
+    [propget] HRESULT Scale([out] [retval] Vector3* value);
+    [propput] HRESULT Scale([in] Vector3 value);
+    [propget] HRESULT Size([out] [retval] Vector2* value);
+    [propput] HRESULT Size([in] Vector2 value);
+    [propget] HRESULT TransformMatrix([out] [retval] Matrix4x4* value);
+    [propput] HRESULT TransformMatrix([in] Matrix4x4 value);
+}
+
+[uuid(3052B611-56C3-4C3E-8BF3-F6E1AD473F06)]
+interface IVisual2 : IInspectable
+{
+    [propget] HRESULT ParentForTransform([out] [retval] IVisual** value);
+    [propput] HRESULT ParentForTransform([in] IVisual* value);
+    [propget] HRESULT RelativeOffsetAdjustment([out] [retval] Vector3* value);
+    [propput] HRESULT RelativeOffsetAdjustment([in] Vector3 value);
+    [propget] HRESULT RelativeSizeAdjustment([out] [retval] Vector2* value);
+    [propput] HRESULT RelativeSizeAdjustment([in] Vector2 value);
+}
+
+[uuid(02F6BC74-ED20-4773-AFE6-D49B4A93DB32)]
+interface IContainerVisual : IInspectable
+{
+    [propget] HRESULT GetChildren([out] [retval] IVisualCollection** value);
+}
+
+[uuid(8B745505-FD3E-4A98-84A8-E949468C6BCB)]
+interface IVisualCollection : IInspectable
+{
+    [propget] HRESULT GetCount([out] [retval] INT32* value);
+    HRESULT InsertAbove([in] IVisual* newChild, [in] IVisual* sibling);
+    HRESULT InsertAtBottom([in] IVisual* newChild);
+    HRESULT InsertAtTop([in] IVisual* newChild);
+    HRESULT InsertBelow([in] IVisual* newChild, [in] IVisual* sibling);
+    HRESULT Remove([in] IVisual* child);
+    HRESULT RemoveAll();
+}
+
+[uuid(A1BEA8BA-D726-4663-8129-6B5E7927FFA6)]
+interface ICompositionTarget : IInspectable
+{
+    [propget] HRESULT Root([out] [retval] IVisual** value);
+    [propput] HRESULT Root([in] IVisual* value);
+}
+
+
+[uuid(CB51C0CE-8FE6-4636-B202-861FAA07D8F3)]
+interface IGraphicsEffect : IInspectable
+{
+    [propget] HRESULT Name([out] [retval] HSTRING* name);
+    [propput] HRESULT Name([in] HSTRING name);
+}
+
+[uuid(2D8F9DDC-4339-4EB9-9216-F9DEB75658A2)]
+interface IGraphicsEffectSource : IInspectable
+{
+}
+
+enum GRAPHICS_EFFECT_PROPERTY_MAPPING
+{
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3,
+    GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4
+}
+
+[uuid(2FC57384-A068-44D7-A331-30982FCF7177)]
+interface IGraphicsEffectD2D1Interop : IUnknown
+{
+    HRESULT GetEffectId([out] Guid* id);
+    HRESULT GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping);
+    HRESULT GetPropertyCount([out] uint* count);
+    HRESULT GetProperty(uint index, [out]IPropertyValue** value);
+    HRESULT GetSource(uint index, [out, retval] IGraphicsEffectSource** source);
+    HRESULT GetSourceCount([retval]uint *count);
+};
+
+[uuid(858AB13A-3292-4E4E-B3BB-2B6C6544A6EE)]
+interface ICompositionEffectSourceParameter : IInspectable
+{
+    [propget] HRESULT Name([out] [retval] HSTRING* value);
+}
+
+[uuid(B3D9F276-ABA3-4724-ACF3-D0397464DB1C)]
+interface ICompositionEffectSourceParameterFactory : IInspectable
+{
+    HRESULT Create([in] HSTRING name, [out] [retval] ICompositionEffectSourceParameter** instance);
+}
+
+enum CompositionEffectFactoryLoadStatus
+{
+    Success          = 0,
+    EffectTooComplex = 1,
+    Pending          = 2,
+    Other            = -1
+}
+
+[uuid(BE5624AF-BA7E-4510-9850-41C0B4FF74DF)]
+interface ICompositionEffectFactory : IInspectable
+{
+    HRESULT CreateBrush([out] [retval] ICompositionEffectBrush** result);
+    [propget] HRESULT ExtendedError([out] [retval] int* value);
+    [propget] HRESULT LoadStatus([out] [retval] CompositionEffectFactoryLoadStatus* value);
+}
+
+[uuid(BF7F795E-83CC-44BF-A447-3E3C071789EC)]
+interface ICompositionEffectBrush : IInspectable
+{
+    HRESULT GetSourceParameter([in] HSTRING name, [out] [retval] ICompositionBrush** result);
+    HRESULT SetSourceParameter([in] HSTRING name, [in] ICompositionBrush* source);
+}
+
+[uuid(C5ACAE58-3898-499E-8D7F-224E91286A5D)]
+interface ICompositionBackdropBrush : IInspectable
+{
+}
+
+[uuid(2B264C5E-BF35-4831-8642-CF70C20FFF2F)]
+interface ICompositionColorBrush : IInspectable
+{
+    [propget] HRESULT Color([out] [retval] Color* value);
+    [propput] HRESULT Color([in] Color value);
+}
+
+[uuid(0D00DAD0-FB07-46FD-8C72-6280D1A3D1DD)]
+interface ICompositionScopedBatch : IInspectable
+{
+    [propget] HRESULT IsActive([out] [retval] boolean* value);
+    [propget] HRESULT IsEnded([out] [retval] boolean* value);
+    HRESULT End();
+    HRESULT Resume();
+    HRESULT Suspend();
+    [eventadd] HRESULT AddCompleted([in] void* handler, [out] [retval] int* token);
+    [eventremove] HRESULT RemoveCompleted([in] int token);
+}
+
+[uuid(48EA31AD-7FCD-4076-A79C-90CC4B852C9B)]
+interface ICompositor5 : IInspectable
+{
+    [propget] HRESULT GetComment([out] [retval] HSTRING* value);
+    [propput] HRESULT SetComment([in] HSTRING value);
+    [propget] HRESULT GetGlobalPlaybackRate([out] [retval] FLOAT* value);
+    [propput] HRESULT SetGlobalPlaybackRate([in] FLOAT value);
+    HRESULT CreateBounceScalarAnimation([out] [retval] void** result);
+    HRESULT CreateBounceVector2Animation([out] [retval] void** result);
+    HRESULT CreateBounceVector3Animation([out] [retval] void** result);
+    HRESULT CreateContainerShape([out] [retval] void** result);
+    HRESULT CreateEllipseGeometry([out] [retval] void** result);
+    HRESULT CreateLineGeometry([out] [retval] void** result);
+    [overload("CreatePathGeometry")] HRESULT CreatePathGeometry([out] [retval] void** result);
+    [overload("CreatePathGeometry")] HRESULT CreatePathGeometryWithPath([in] void* path, [out] [retval] void** result);
+    HRESULT CreatePathKeyFrameAnimation([out] [retval] void** result);
+    HRESULT CreateRectangleGeometry([out] [retval] void** result);
+    HRESULT CreateRoundedRectangleGeometry([out] [retval] void** result);
+    HRESULT CreateShapeVisual([out] [retval] void** result);
+    [overload("CreateSpriteShape")] HRESULT CreateSpriteShape([out] [retval] void** result);
+    [overload("CreateSpriteShape")] HRESULT CreateSpriteShapeWithGeometry([in] void* geometry, [out] [retval] void** result);
+    HRESULT CreateViewBox([out] [retval] void** result);
+    HRESULT RequestCommitAsync([out] [retval] IAsyncAction** operation);
+}

+ 15 - 6
src/Windows/Avalonia.Win32/WindowImpl.cs

@@ -15,6 +15,8 @@ using Avalonia.Rendering;
 using Avalonia.Win32.Input;
 using Avalonia.Win32.Interop;
 using Avalonia.Win32.OpenGl;
+using Avalonia.Win32.WinRT;
+using Avalonia.Win32.WinRT.Composition;
 using static Avalonia.Win32.Interop.UnmanagedMethods;
 
 namespace Avalonia.Win32
@@ -107,7 +109,7 @@ namespace Avalonia.Win32
 
             var glPlatform = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
 
-            var compositionConnector = AvaloniaLocator.Current.GetService<CompositionConnector>();
+            var compositionConnector = AvaloniaLocator.Current.GetService<WinUICompositorConnection>();
 
             _isUsingComposition = compositionConnector is { } &&
                 glPlatform is EglPlatformOpenGlInterface egl &&
@@ -121,8 +123,8 @@ namespace Avalonia.Win32
             {
                 if (_isUsingComposition)
                 {
-                    var cgl = new CompositionEglGlPlatformSurface(glPlatform as EglPlatformOpenGlInterface, this);
-                    _blurHost = cgl.AttachToCompositionTree(compositionConnector, _hwnd);
+                    var cgl = new WinUiCompositedWindowSurface(compositionConnector, this);
+                    _blurHost = cgl;
 
                     _gl = cgl;
 
@@ -452,9 +454,14 @@ namespace Avalonia.Win32
             if (customRendererFactory != null)
                 return customRendererFactory.Create(root, loop);
 
-            return Win32Platform.UseDeferredRendering ?
-                (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock) :
-                new ImmediateRenderer(root);
+            return Win32Platform.UseDeferredRendering 
+                ?  _isUsingComposition 
+                    ? new DeferredRenderer(root, loop)
+                    {
+                        RenderOnlyOnRenderThread = true
+                    } 
+                    : (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock)
+                : new ImmediateRenderer(root);
         }
 
         public void Resize(Size value)
@@ -489,6 +496,8 @@ namespace Avalonia.Win32
 
         public void Dispose()
         {
+            (_gl as IDisposable)?.Dispose();
+
             if (_dropTarget != null)
             {
                 OleContext.Current?.UnregisterDragDrop(Handle);

+ 4 - 3
src/tools/MicroComGenerator/AstParser.cs

@@ -13,7 +13,8 @@ namespace MicroComGenerator
             while (!parser.Eof)
             {
                 var attrs = ParseLocalAttributes(ref parser);
-
+                if (parser.TryConsume(";"))
+                    continue;
                 if (parser.TryParseKeyword("enum"))
                     idl.Enums.Add(ParseEnum(attrs, ref parser));
                 else if (parser.TryParseKeyword("struct"))
@@ -64,7 +65,7 @@ namespace MicroComGenerator
         static AstAttributes ParseLocalAttributes(ref TokenParser parser)
         {
             var rv = new AstAttributes();
-            if (parser.TryConsume("["))
+            while (parser.TryConsume("["))
             {
                 while (!parser.TryConsume("]") && !parser.Eof)
                 {
@@ -78,7 +79,7 @@ namespace MicroComGenerator
                     if (parser.TryConsume(']'))
                     {
                         rv.Add(new AstAttributeNode(ident, null));
-                        return rv;
+                        break;
                     }
                     // No value, next attribute
                     else if (parser.TryConsume(','))

+ 36 - 11
src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs

@@ -21,7 +21,7 @@ namespace MicroComGenerator
         {
             public string Name;
             public string NativeType;
-
+            public AstAttributes Attributes { get; set; }
             public virtual StatementSyntax CreateFixed(StatementSyntax inner) => inner;
 
             public virtual void PreMarshal(List<StatementSyntax> body)
@@ -161,6 +161,13 @@ namespace MicroComGenerator
             return type;
         }
 
+        Arg ConvertArg(AstInterfaceMemberArgumentNode node)
+        {
+            var arg = ConvertArg(node.Name, node.Type);
+            arg.Attributes = node.Attributes.Clone();
+            return arg;
+        }
+        
         Arg ConvertArg(string name, AstTypeNode type)
         {
             type = new AstTypeNode { Name = ConvertNativeType(type.Name), PointerLevel = type.PointerLevel };
@@ -190,12 +197,19 @@ namespace MicroComGenerator
             List<StatementSyntax> vtblCtor, int num)
         {
             // Prepare method information
-            var args = member.Select(a => ConvertArg(a.Name, a.Type)).ToList();
+            if (member.Name == "GetRenderingDevice")
+                Console.WriteLine();
+            var args = member.Select(ConvertArg).ToList();
             var returnArg = ConvertArg("__result", member.ReturnType);
             bool isHresult = member.ReturnType.Name == "HRESULT";
             bool isHresultLastArgumentReturn = isHresult
                                                && args.Count > 0
-                                               && (args.Last().Name == "ppv" || args.Last().Name == "retOut" || args.Last().Name == "ret")
+                                               && (args.Last().Name == "ppv" 
+                                                   || args.Last().Name == "retOut" 
+                                                   || args.Last().Name == "ret"
+                                                   || args.Last().Attributes.HasAttribute("out")
+                                                   || args.Last().Attributes.HasAttribute("retval")
+                                                   )
                                                && ((member.Last().Type.PointerLevel > 0
                                                     && !IsInterface(member.Last().Type))
                                                    || member.Last().Type.PointerLevel == 2);
@@ -334,16 +348,27 @@ namespace MicroComGenerator
             BlockSyntax backBodyBlock = Block().AddStatements(backPreMarshal.ToArray()).AddStatements(backCallStatement);
 
 
+            var exceptions = new List<CatchClauseSyntax>()
+            {
+                CatchClause(
+                    CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
+                    Block(
+                        ParseStatement(
+                            "Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
+                        isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
+                        : isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
+                    ))
+            };
+            
+            if (isHresult)
+                exceptions.Insert(0, CatchClause(
+                    CatchDeclaration(ParseTypeName("System.Runtime.InteropServices.COMException"),
+                        Identifier("__com_exception__")),
+                    null, Block(ParseStatement("return __com_exception__.ErrorCode;"))));
+
             backBodyBlock = Block(
                 TryStatement(
-                        SingletonList(CatchClause(
-                            CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
-                            Block(
-                                ParseStatement(
-                                    "Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
-                                isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
-                                : isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
-                            ))))
+                        List(exceptions))
                     .WithBlock(Block(backBodyBlock))
             );
             if (isHresult)

+ 5 - 4
src/tools/MicroComGenerator/CSharpGen.Utils.cs

@@ -68,10 +68,11 @@ namespace MicroComGenerator
 
         bool IsPropertyRewriteCandidate(MethodDeclarationSyntax method)
         {
-            if(method.Identifier.Text.Contains("GetScaling"))
-                Console.WriteLine();
-            return (method.Identifier.Text.StartsWith("Get") &&
-                    method.ParameterList.Parameters.Count == 0);
+
+            return
+                method.ReturnType.ToFullString() != "void"
+                && method.Identifier.Text.StartsWith("Get")
+                && method.ParameterList.Parameters.Count == 0;
         }
 
         TypeDeclarationSyntax RewriteMethodsToProperties<T>(T decl) where T : TypeDeclarationSyntax

+ 26 - 4
src/tools/MicroComGenerator/CSharpGen.cs

@@ -22,7 +22,11 @@ namespace MicroComGenerator
         public CSharpGen(AstIdlNode idl)
         {
             _idl = idl.Clone();
-            new AstRewriter().VisitAst(_idl);
+            new AstRewriter(_idl.Attributes.Where(a => a.Name == "clr-map")
+                .Select(x => x.Value.Trim().Split(' '))
+                .ToDictionary(x => x[0], x => x[1])
+            ).VisitAst(_idl);
+            
             _extraUsings = _idl.Attributes.Where(u => u.Name == "clr-using").Select(u => u.Value).ToList();
             _namespace = _idl.GetAttribute("clr-namespace");
             var visibilityString = _idl.GetAttribute("clr-access");
@@ -37,6 +41,13 @@ namespace MicroComGenerator
 
         class AstRewriter : AstVisitor
         {
+            private readonly Dictionary<string, string> _typeMap = new Dictionary<string, string>();
+
+            public AstRewriter(Dictionary<string, string> typeMap)
+            {
+                _typeMap = typeMap;
+            }
+
             void ConvertIntPtr(AstTypeNode type)
             {
                 if (type.Name == "void" && type.PointerLevel > 0)
@@ -60,6 +71,9 @@ namespace MicroComGenerator
                     type.PointerLevel++;
                     type.IsLink = false;
                 }
+
+                if (_typeMap.TryGetValue(type.Name, out var mapped))
+                    type.Name = mapped;
                 
                 base.VisitType(type);
             }
@@ -80,6 +94,10 @@ namespace MicroComGenerator
             {
                 if (member.HasAttribute("intptr"))
                     ConvertIntPtr(member.ReturnType);
+                if (member.HasAttribute("propget") && !member.Name.StartsWith("Get"))
+                    member.Name = "Get" + member.Name;
+                if (member.HasAttribute("propput") && !member.Name.StartsWith("Set"))
+                    member.Name = "Set" + member.Name;
                 base.VisitInterfaceMember(member);
             }
         }
@@ -103,7 +121,8 @@ namespace MicroComGenerator
         NamespaceDeclarationSyntax GenerateEnums(NamespaceDeclarationSyntax ns)
         {
             return ns.AddMembers(_idl.Enums.Select(e =>
-                EnumDeclaration(e.Name)
+            {
+                var dec =  EnumDeclaration(e.Name)
                     .WithModifiers(TokenList(Token(_visibility)))
                     .WithMembers(SeparatedList(e.Select(m =>
                     {
@@ -111,8 +130,11 @@ namespace MicroComGenerator
                         if (m.Value != null)
                             return member.WithEqualsValue(EqualsValueClause(ParseExpression(m.Value)));
                         return member;
-                    })))
-            ).ToArray());
+                    })));
+                if (e.HasAttribute("flags"))
+                    dec = dec.AddAttribute("System.Flags");
+                return dec;
+            }).ToArray());
         }
         
         NamespaceDeclarationSyntax GenerateStructs(NamespaceDeclarationSyntax ns)

+ 1 - 1
tests/Avalonia.Benchmarks/NullRenderingPlatform.cs

@@ -28,7 +28,7 @@ namespace Avalonia.Benchmarks
 
         public IGeometryImpl CreateRectangleGeometry(Rect rect)
         {
-            throw new NotImplementedException();
+            return new MockStreamGeometryImpl();
         }
 
         public IStreamGeometryImpl CreateStreamGeometry()

+ 1 - 0
tests/Avalonia.Controls.UnitTests/ComboBoxTests.cs

@@ -40,6 +40,7 @@ namespace Avalonia.Controls.UnitTests
                 Items = items,
                 SelectedIndex = 0,
             };
+            var root = new TestRoot(target);
 
             var rectangle = target.GetValue(ComboBox.SelectionBoxItemProperty) as Rectangle;
             Assert.NotNull(rectangle);

+ 1 - 1
tests/Avalonia.Markup.UnitTests/Parsers/ExpressionObserverBuilderTests_AttachedProperty.cs

@@ -129,7 +129,7 @@ namespace Avalonia.Markup.UnitTests.Parsers
         {
             var data = new Class1();
 
-            Assert.Throws<ExpressionParseException>(() => ExpressionObserverBuilder.Build(data, "(Owner)", typeResolver: _typeResolver));
+            Assert.Throws<ExpressionParseException>(() => ExpressionObserverBuilder.Build(data, "(Owner.)", typeResolver: _typeResolver));
         }
 
         [Fact]

+ 48 - 0
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/BindingExtensionTests.cs

@@ -84,6 +84,54 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
             }
         }
 
+        [Fact]
+        public void SupportCastToTypeInExpression()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
+        >
+    <ContentControl Content='{Binding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = new TestDataContext
+                {
+                    StringProperty = "foobar"
+                };
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(dataContext.StringProperty, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
+        >
+    <ContentControl Content='{Binding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = "foo";
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(null, contentControl.Content);
+            }
+        }
         private class FooBar
         {
             public object Foo { get; } = null;

+ 248 - 10
tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs

@@ -1,11 +1,13 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
+using System.Globalization;
 using System.Reactive.Subjects;
 using System.Text;
 using System.Threading.Tasks;
 using Avalonia.Controls;
 using Avalonia.Controls.Presenters;
+using Avalonia.Data.Converters;
 using Avalonia.Data.Core;
 using Avalonia.Markup.Data;
 using Avalonia.UnitTests;
@@ -372,7 +374,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
     </Window.DataTemplates>
     <ContentControl Name='target' Content='{CompiledBinding}' />
 </Window>";
-                Assert.Throws<XamlTransformException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+                ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
             }
         }
 
@@ -390,7 +392,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
         <TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
     </ContentControl>
 </Window>";
-                Assert.Throws<XamlTransformException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+                ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
             }
         }
 
@@ -447,7 +449,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
         </ItemsControl.DataTemplates>
     </ItemsControl>
 </Window>";
-                Assert.Throws<XamlTransformException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+                ThrowsXamlTransformException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
             }
         }
 
@@ -597,7 +599,49 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
         x:CompileBindings='true'>
     <TextBlock Text='{Binding InvalidPath}' Name='textBlock' />
 </Window>";
-                Assert.Throws<XamlX.XamlParseException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+                ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+            }
+        }
+
+        [Fact]
+        public void SupportParentInPath()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
+        Title='foo'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.Title}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                Assert.Equal("foo", contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportConverterWithParameter()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
+        x:DataType='local:TestDataContext' x:CompileBindings='True'>
+    <TextBlock Name='textBlock' Text='{Binding StringProperty, Converter={x:Static local:AppendConverter.Instance}, ConverterParameter=Bar}'/>
+</Window>";
+
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var textBlock = window.FindControl<TextBlock>("textBlock");
+
+                window.DataContext = new TestDataContext() { StringProperty = "Foo" };
+
+                Assert.Equal("Foo+Bar", textBlock.Text);
             }
         }
 
@@ -613,26 +657,218 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
         x:DataType='local:TestDataContext'
         x:CompileBindings='notabool'>
 </Window>";
-                Assert.Throws<XamlX.XamlParseException>(() => AvaloniaRuntimeXamlLoader.Load(xaml));
+                ThrowsXamlParseException(() => AvaloniaRuntimeXamlLoader.Load(xaml));
             }
         }
-    }
 
+        [Fact]
+        public void SupportCastToTypeInExpression()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = new TestDataContext();
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(dataContext, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpression_DifferentTypeEvaluatesToNull()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = "foo";
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(null, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpressionWithProperty()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = new TestDataContext
+                {
+                    StringProperty = "foobar"
+                };
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(dataContext.StringProperty, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpressionWithProperty1()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.DataContext(local:TestDataContext).StringProperty}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = new TestDataContext
+                {
+                    StringProperty = "foobar"
+                };
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(dataContext.StringProperty, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpressionWithPropertyIndexer()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding ((local:TestData)ObjectsArrayProperty[0]).StringProperty}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var data = new TestData()
+                {
+                    StringProperty = "Foo"
+                };
+                var dataContext = new TestDataContext
+                {
+                    ObjectsArrayProperty = new object[] { data }
+                };
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(data.StringProperty, contentControl.Content);
+            }
+        }
+
+        [Fact]
+        public void SupportCastToTypeInExpressionWithProperty_DifferentTypeEvaluatesToNull()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            {
+                var xaml = @"
+<Window xmlns='https://github.com/avaloniaui'
+        xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
+        xmlns:local='using:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions'
+        x:DataType='local:TestDataContext'>
+    <ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
+</Window>";
+                var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
+                var contentControl = window.FindControl<ContentControl>("contentControl");
+
+                var dataContext = new TestDataContext
+                {
+                    StringProperty = "foobar"
+                };
+
+                window.DataContext = dataContext;
+
+                Assert.Equal(dataContext.StringProperty, contentControl.Content);
+
+                window.DataContext = "foo";
+
+                Assert.Equal(null, contentControl.Content);
+            }
+        }
+
+        void Throws(string type, Action cb)
+        {
+            try
+            {
+                cb();
+            }
+            catch (Exception e) when (e.GetType().Name == type)
+            {
+                return;
+            }
+
+            throw new Exception("Expected " + type);
+        }
+
+        void ThrowsXamlParseException(Action cb) => Throws("XamlParseException", cb);
+        void ThrowsXamlTransformException(Action cb) => Throws("XamlTransformException", cb);
+    }
+    
     public interface INonIntegerIndexer
     {
-        string this[string key] {get; set;}
+        string this[string key] { get; set; }
     }
 
     public interface INonIntegerIndexerDerived : INonIntegerIndexer
-    {}
+    { }
 
     public interface IHasProperty
     {
-        string StringProperty {get; set; }
+        string StringProperty { get; set; }
     }
 
     public interface IHasPropertyDerived : IHasProperty
-    {}
+    { }
+
+    public class AppendConverter : IValueConverter
+    {
+        public static IValueConverter Instance { get; } = new AppendConverter();
+
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+            => string.Format("{0}+{1}", value, parameter);
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+            => throw new NotImplementedException();
+
+    }
+
+    public class TestData
+    {
+        public string StringProperty { get; set; }
+    }
 
     public class TestDataContext : IHasPropertyDerived
     {
@@ -646,6 +882,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
 
         public string[] ArrayProperty { get; set; }
 
+        public object[] ObjectsArrayProperty { get; set; }
+
         public List<string> ListProperty { get; set; } = new List<string>();
 
         public NonIntegerIndexer NonIntegerIndexerProperty { get; set; } = new NonIntegerIndexer();