Browse Source

Merge remote-tracking branch 'origin/master' into feature/onplatform-xaml-compiler-support

Dan Walmsley 3 years ago
parent
commit
288cfed37e
43 changed files with 211 additions and 618 deletions
  1. 4 2
      .editorconfig
  2. 18 31
      src/Avalonia.Base/Media/Color.cs
  3. 12 18
      src/Avalonia.Base/Media/HslColor.cs
  4. 12 18
      src/Avalonia.Base/Media/HsvColor.cs
  5. 49 0
      src/Avalonia.Base/Utilities/SpanHelpers.cs
  6. 72 0
      src/Avalonia.Build.Tasks/SpanCompat.cs
  7. 2 2
      src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs
  8. 2 2
      src/Avalonia.Controls/AppBuilderBase.cs
  9. 1 1
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  10. 1 1
      src/Avalonia.Controls/DefinitionBase.cs
  11. 1 1
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/SimpleWebSocketHttpServer.cs
  12. 1 0
      src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
  13. 3 1
      src/Avalonia.MicroCom/CallbackBase.cs
  14. 0 9
      src/Avalonia.MicroCom/IMicroComExceptionCallback.cs
  15. 0 9
      src/Avalonia.MicroCom/IMicroComShadowContainer.cs
  16. 0 8
      src/Avalonia.MicroCom/IUnknown.cs
  17. 0 17
      src/Avalonia.MicroCom/LocalInterop.cs
  18. 0 110
      src/Avalonia.MicroCom/MicroComProxyBase.cs
  19. 0 143
      src/Avalonia.MicroCom/MicroComRuntime.cs
  20. 0 177
      src/Avalonia.MicroCom/MicroComShadow.cs
  21. 0 47
      src/Avalonia.MicroCom/MicroComVtblBase.cs
  22. 0 1
      src/Avalonia.Native/Avalonia.Native.csproj
  23. 1 0
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  24. 1 0
      src/Avalonia.Native/CallbackBase.cs
  25. 1 0
      src/Avalonia.Native/NativeControlHostImpl.cs
  26. 1 1
      src/Avalonia.X11/X11Structs.cs
  27. 9 9
      src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
  28. 0 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  29. 4 3
      src/Windows/Avalonia.Win32/ClipboardImpl.cs
  30. 3 2
      src/Windows/Avalonia.Win32/DragSource.cs
  31. 1 0
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  32. 2 1
      src/Windows/Avalonia.Win32/OleContext.cs
  33. 1 1
      src/Windows/Avalonia.Win32/OleDataObject.cs
  34. 1 0
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  35. 1 0
      src/Windows/Avalonia.Win32/Win32StorageProvider.cs
  36. 1 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
  37. 1 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
  38. 1 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
  39. 1 0
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
  40. 1 0
      src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
  41. 1 0
      src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
  42. 1 1
      tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs
  43. 0 1
      tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj

+ 4 - 2
.editorconfig

@@ -139,10 +139,12 @@ dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomme
 
 # CA1802: Use literals where appropriate
 dotnet_diagnostic.CA1802.severity = warning
-# CA1825: Avoid zero-length array allocations
-dotnet_diagnostic.CA1825.severity = warning
+# CA1820: Test for empty strings using string length
+dotnet_diagnostic.CA1820.severity = warning
 # CA1821: Remove empty finalizers
 dotnet_diagnostic.CA1821.severity = warning
+# CA1825: Avoid zero-length array allocations
+dotnet_diagnostic.CA1825.severity = warning
 #CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
 dotnet_diagnostic.CA1847.severity = warning
 

+ 18 - 31
src/Avalonia.Base/Media/Color.cs

@@ -9,6 +9,7 @@ using System;
 using System.Globalization;
 #if !BUILDTASK
 using Avalonia.Animation.Animators;
+using static Avalonia.Utilities.SpanHelpers;
 #endif
 
 namespace Avalonia.Media
@@ -295,9 +296,7 @@ namespace Avalonia.Media
                     return false;
                 }
 
-                // TODO: (netstandard 2.1) Can use allocation free parsing.
-                if (!uint.TryParse(input.ToString(), NumberStyles.HexNumber, CultureInfo.InvariantCulture,
-                    out var parsed))
+                if (!input.TryParseUInt(NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var parsed))
                 {
                     return false;
                 }
@@ -382,9 +381,9 @@ namespace Avalonia.Media
 
             if (components.Length == 3) // RGB
             {
-                if (InternalTryParseByte(components[0], out byte red) &&
-                    InternalTryParseByte(components[1], out byte green) &&
-                    InternalTryParseByte(components[2], out byte blue))
+                if (InternalTryParseByte(components[0].AsSpan(), out byte red) &&
+                    InternalTryParseByte(components[1].AsSpan(), out byte green) &&
+                    InternalTryParseByte(components[2].AsSpan(), out byte blue))
                 {
                     color = new Color(0xFF, red, green, blue);
                     return true;
@@ -392,10 +391,10 @@ namespace Avalonia.Media
             }
             else if (components.Length == 4) // RGBA
             {
-                if (InternalTryParseByte(components[0], out byte red) &&
-                    InternalTryParseByte(components[1], out byte green) &&
-                    InternalTryParseByte(components[2], out byte blue) &&
-                    InternalTryParseDouble(components[3], out double alpha))
+                if (InternalTryParseByte(components[0].AsSpan(), out byte red) &&
+                    InternalTryParseByte(components[1].AsSpan(), out byte green) &&
+                    InternalTryParseByte(components[2].AsSpan(), out byte blue) &&
+                    InternalTryParseDouble(components[3].AsSpan(), out double alpha))
                 {
                     color = new Color((byte)Math.Round(alpha * 255.0), red, green, blue);
                     return true;
@@ -403,17 +402,14 @@ namespace Avalonia.Media
             }
 
             // Local function to specially parse a byte value with an optional percentage sign
-            bool InternalTryParseByte(string inString, out byte outByte)
+            bool InternalTryParseByte(ReadOnlySpan<char> inString, out byte outByte)
             {
                 // The percent sign, if it exists, must be at the end of the number
-                int percentIndex = inString.IndexOf("%", StringComparison.Ordinal);
+                int percentIndex = inString.IndexOf("%".AsSpan(), StringComparison.Ordinal);
 
                 if (percentIndex >= 0)
                 {
-                    var result = double.TryParse(
-                        inString.Substring(0, percentIndex),
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
+                    var result = inString.Slice(0, percentIndex).TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
                         out double percentage);
 
                     outByte = (byte)Math.Round((percentage / 100.0) * 255.0);
@@ -421,37 +417,28 @@ namespace Avalonia.Media
                 }
                 else
                 {
-                    return byte.TryParse(
-                        inString,
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
+                    return inString.TryParseByte(NumberStyles.Number, CultureInfo.InvariantCulture,
                         out outByte);
                 }
             }
 
             // Local function to specially parse a double value with an optional percentage sign
-            bool InternalTryParseDouble(string inString, out double outDouble)
+            bool InternalTryParseDouble(ReadOnlySpan<char> inString, out double outDouble)
             {
                 // The percent sign, if it exists, must be at the end of the number
-                int percentIndex = inString.IndexOf("%", StringComparison.Ordinal);
+                int percentIndex = inString.IndexOf("%".AsSpan(), StringComparison.Ordinal);
 
                 if (percentIndex >= 0)
                 {
-                    var result = double.TryParse(
-                        inString.Substring(0, percentIndex),
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
-                        out double percentage);
+                    var result = inString.Slice(0, percentIndex).TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
+                         out double percentage);
 
                     outDouble = percentage / 100.0;
                     return result;
                 }
                 else
                 {
-                    return double.TryParse(
-                        inString,
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
+                    return inString.TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
                         out outDouble);
                 }
             }

+ 12 - 18
src/Avalonia.Base/Media/HslColor.cs

@@ -302,9 +302,9 @@ namespace Avalonia.Media
 
             if (components.Length == 3) // HSL
             {
-                if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
-                    TryInternalParse(components[1], out double saturation) &&
-                    TryInternalParse(components[2], out double lightness))
+                if (components[0].AsSpan().TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
+                    TryInternalParse(components[1].AsSpan(), out double saturation) &&
+                    TryInternalParse(components[2].AsSpan(), out double lightness))
                 {
                     hslColor = new HslColor(1.0, hue, saturation, lightness);
                     return true;
@@ -312,10 +312,10 @@ namespace Avalonia.Media
             }
             else if (components.Length == 4) // HSLA
             {
-                if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
-                    TryInternalParse(components[1], out double saturation) &&
-                    TryInternalParse(components[2], out double lightness) &&
-                    TryInternalParse(components[3], out double alpha))
+                if (components[0].AsSpan().TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
+                    TryInternalParse(components[1].AsSpan(), out double saturation) &&
+                    TryInternalParse(components[2].AsSpan(), out double lightness) &&
+                    TryInternalParse(components[3].AsSpan(), out double alpha))
                 {
                     hslColor = new HslColor(alpha, hue, saturation, lightness);
                     return true;
@@ -323,28 +323,22 @@ namespace Avalonia.Media
             }
 
             // Local function to specially parse a double value with an optional percentage sign
-            bool TryInternalParse(string inString, out double outDouble)
+            bool TryInternalParse(ReadOnlySpan<char> inString, out double outDouble)
             {
                 // The percent sign, if it exists, must be at the end of the number
-                int percentIndex = inString.IndexOf("%", StringComparison.Ordinal);
+                int percentIndex = inString.IndexOf("%".AsSpan(), StringComparison.Ordinal);
 
                 if (percentIndex >= 0)
                 {
-                    var result = double.TryParse(
-                        inString.Substring(0, percentIndex),
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
-                        out double percentage);
+                    var result = inString.Slice(0, percentIndex).TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
+                         out double percentage);
 
                     outDouble = percentage / 100.0;
                     return result;
                 }
                 else
                 {
-                    return double.TryParse(
-                        inString,
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
+                    return inString.TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
                         out outDouble);
                 }
             }

+ 12 - 18
src/Avalonia.Base/Media/HsvColor.cs

@@ -302,9 +302,9 @@ namespace Avalonia.Media
 
             if (components.Length == 3) // HSV
             {
-                if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
-                    TryInternalParse(components[1], out double saturation) &&
-                    TryInternalParse(components[2], out double value))
+                if (components[0].AsSpan().TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
+                    TryInternalParse(components[1].AsSpan(), out double saturation) &&
+                    TryInternalParse(components[2].AsSpan(), out double value))
                 {
                     hsvColor = new HsvColor(1.0, hue, saturation, value);
                     return true;
@@ -312,10 +312,10 @@ namespace Avalonia.Media
             }
             else if (components.Length == 4) // HSVA
             {
-                if (double.TryParse(components[0], NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
-                    TryInternalParse(components[1], out double saturation) &&
-                    TryInternalParse(components[2], out double value) &&
-                    TryInternalParse(components[3], out double alpha))
+                if (components[0].AsSpan().TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture, out double hue) &&
+                    TryInternalParse(components[1].AsSpan(), out double saturation) &&
+                    TryInternalParse(components[2].AsSpan(), out double value) &&
+                    TryInternalParse(components[3].AsSpan(), out double alpha))
                 {
                     hsvColor = new HsvColor(alpha, hue, saturation, value);
                     return true;
@@ -323,28 +323,22 @@ namespace Avalonia.Media
             }
 
             // Local function to specially parse a double value with an optional percentage sign
-            bool TryInternalParse(string inString, out double outDouble)
+            bool TryInternalParse(ReadOnlySpan<char> inString, out double outDouble)
             {
                 // The percent sign, if it exists, must be at the end of the number
-                int percentIndex = inString.IndexOf("%", StringComparison.Ordinal);
+                int percentIndex = inString.IndexOf("%".AsSpan(), StringComparison.Ordinal);
 
                 if (percentIndex >= 0)
                 {
-                    var result = double.TryParse(
-                        inString.Substring(0, percentIndex),
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
-                        out double percentage);
+                    var result = inString.Slice(0, percentIndex).TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
+                         out double percentage);
 
                     outDouble = percentage / 100.0;
                     return result;
                 }
                 else
                 {
-                    return double.TryParse(
-                        inString,
-                        NumberStyles.Number,
-                        CultureInfo.InvariantCulture,
+                    return inString.TryParseDouble(NumberStyles.Number, CultureInfo.InvariantCulture,
                         out outDouble);
                 }
             }

+ 49 - 0
src/Avalonia.Base/Utilities/SpanHelpers.cs

@@ -0,0 +1,49 @@
+using System;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace Avalonia.Utilities
+{
+    public static class SpanHelpers
+    {
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryParseUInt(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out uint value)
+        {
+#if NETSTANDARD2_0
+            return uint.TryParse(span.ToString(), style, provider, out value);
+#else
+            return uint.TryParse(span, style, provider, out value);
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryParseInt(this ReadOnlySpan<char> span, out int value)
+        {
+#if NETSTANDARD2_0
+            return int.TryParse(span.ToString(), out value);
+#else
+            return int.TryParse(span, out value);
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryParseDouble(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out double value)
+        {
+#if NETSTANDARD2_0
+            return double.TryParse(span.ToString(), style, provider, out value);
+#else
+            return double.TryParse(span, style, provider, out value);
+#endif
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static bool TryParseByte(this ReadOnlySpan<char> span, NumberStyles style, IFormatProvider provider, out byte value)
+        {
+#if NETSTANDARD2_0
+            return byte.TryParse(span.ToString(), style, provider, out value);
+#else
+            return byte.TryParse(span, style, provider, out value);
+#endif
+        }
+    }
+}

+ 72 - 0
src/Avalonia.Build.Tasks/SpanCompat.cs

@@ -1,4 +1,7 @@
 #if !NETCOREAPP3_1_OR_GREATER
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
 namespace System
 {
     // This is a hack to enable our span code to work inside MSBuild task without referencing System.Memory
@@ -9,6 +12,8 @@ namespace System
         private int _length;
         public int Length => _length;
 
+        public static implicit operator ReadOnlySpan<T>(string s) => new ReadOnlySpan<T>(s);
+
         public ReadOnlySpan(string s) : this(s, 0, s.Length)
         {
             
@@ -63,8 +68,75 @@ namespace System
             return Slice(start);
         }
 
+        public ReadOnlySpan<char> TrimEnd()
+        {
+            int end = Length - 1;
+            for (; end >= 0; end--)
+            {
+                if (!char.IsWhiteSpace(this[end]))
+                {
+                    break;
+                }
+            }
+            return Slice(0, end + 1);
+        }
+
+        public ReadOnlySpan<char> Trim()
+        {
+            return TrimStart().TrimEnd();
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryParseUInt(NumberStyles style, IFormatProvider provider, out uint value)
+        {
+            return uint.TryParse(ToString(), style, provider, out value);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryParseInt(out int value)
+        {
+            return int.TryParse(ToString(), out value);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryParseDouble(NumberStyles style, IFormatProvider provider, out double value)
+        {
+            return double.TryParse(ToString(), style, provider, out value);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryParseByte(NumberStyles style, IFormatProvider provider, out byte value)
+        {
+            return byte.TryParse(ToString(), style, provider, out value);
+        }
+
         public override string ToString() => _length == 0 ? string.Empty : _s.Substring(_start, _length);
 
+        internal int IndexOf(ReadOnlySpan<char> v, StringComparison ordinal, int start = 0)
+        {
+            if(Length == 0 || v.IsEmpty)
+            {
+                return -1;
+            }
+
+            for (var c = start; c < _length; c++)
+            {
+                if (this[c] == v[0])
+                {
+                    for(var i = 0; i < v.Length; i++)
+                    {
+                        if (this[c + i] != v[i])
+                        {
+                            break;
+                        }
+                    } 
+                    return c;
+                }
+            }
+
+            return -1;
+        }
+
         public static implicit operator ReadOnlySpan<T>(char[] arr) => new ReadOnlySpan<T>(new string(arr));
     }
 

+ 2 - 2
src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs

@@ -28,8 +28,8 @@ namespace Avalonia.Controls
         {
             if (targetType != null && targetType.IsNullableType())
             {
-                String strValue = value as String;
-                if (strValue == String.Empty)
+                var strValue = value as string;
+                if (string.IsNullOrEmpty(strValue))
                 {
                     return null;
                 }

+ 2 - 2
src/Avalonia.Controls/AppBuilderBase.cs

@@ -210,9 +210,9 @@ namespace Avalonia.Controls
         {
             var moduleInitializers = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                      from attribute in assembly.GetCustomAttributes<ExportAvaloniaModuleAttribute>()
-                                     where attribute.ForWindowingSubsystem == ""
+                                     where string.IsNullOrEmpty(attribute.ForWindowingSubsystem)
                                       || attribute.ForWindowingSubsystem == WindowingSubsystemName
-                                     where attribute.ForRenderingSubsystem == ""
+                                     where string.IsNullOrEmpty(attribute.ForRenderingSubsystem)
                                       || attribute.ForRenderingSubsystem == RenderingSubsystemName
                                      group attribute by attribute.Name into exports
                                      select (from export in exports

+ 1 - 1
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@@ -99,7 +99,7 @@ namespace Avalonia.Controls
             get => _clockIdentifier;
             set
             {
-                if (!(string.IsNullOrEmpty(value) || value == "" || value == "12HourClock" || value == "24HourClock"))
+                if (!(string.IsNullOrEmpty(value) || value == "12HourClock" || value == "24HourClock"))
                     throw new ArgumentException("Invalid ClockIdentifier");
                 SetAndRaise(ClockIdentifierProperty, ref _clockIdentifier, value);
                 SetGrid();

+ 1 - 1
src/Avalonia.Controls/DefinitionBase.cs

@@ -366,7 +366,7 @@ namespace Avalonia.Controls
 
             string id = (string)value;
 
-            if (id != string.Empty)
+            if (!string.IsNullOrEmpty(id))
             {
                 int i = -1;
                 while (++i < id.Length)

+ 1 - 1
src/Avalonia.DesignerSupport/Remote/HtmlTransport/SimpleWebSocketHttpServer.cs

@@ -72,7 +72,7 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport
                 while (true)
                 {
                     line = await ReadLineAsync();
-                    if (line == "")
+                    if (string.IsNullOrEmpty(line))
                         break;
                     sp = line.Split(new[] {':'}, 2);
                     headers[sp[0]] = sp[1].TrimStart();

+ 1 - 0
src/Avalonia.MicroCom/Avalonia.MicroCom.csproj

@@ -4,6 +4,7 @@
       <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
+    <PackageReference Include="MicroCom.Runtime" Version="0.10.5" />
     <ProjectReference Include="..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj">
       <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
       <ExcludeAssets>all</ExcludeAssets>

+ 3 - 1
src/Avalonia.MicroCom/CallbackBase.cs

@@ -1,4 +1,6 @@
-namespace Avalonia.MicroCom
+using MicroCom.Runtime;
+
+namespace Avalonia.MicroCom
 {
     public abstract class CallbackBase : IUnknown, IMicroComShadowContainer
     {

+ 0 - 9
src/Avalonia.MicroCom/IMicroComExceptionCallback.cs

@@ -1,9 +0,0 @@
-using System;
-
-namespace Avalonia.MicroCom
-{
-    public interface IMicroComExceptionCallback
-    {
-        void RaiseException(Exception e);
-    }
-}

+ 0 - 9
src/Avalonia.MicroCom/IMicroComShadowContainer.cs

@@ -1,9 +0,0 @@
-namespace Avalonia.MicroCom
-{
-    public interface IMicroComShadowContainer
-    {
-        MicroComShadow Shadow { get; set; }
-        void OnReferencedFromNative();
-        void OnUnreferencedFromNative();
-    }
-}

+ 0 - 8
src/Avalonia.MicroCom/IUnknown.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace Avalonia.MicroCom
-{
-    public interface IUnknown : IDisposable
-    {
-    }
-}

+ 0 - 17
src/Avalonia.MicroCom/LocalInterop.cs

@@ -1,17 +0,0 @@
-using System;
-
-namespace Avalonia.MicroCom
-{
-    unsafe class LocalInterop
-    {
-        public static unsafe void CalliStdCallvoid(void* thisObject, void* methodPtr)
-        {
-            throw null;
-        }
-        
-        public static unsafe int CalliStdCallint(void* thisObject, Guid* guid, IntPtr* ppv,  void* methodPtr)
-        {
-            throw null;
-        }
-    }
-}

+ 0 - 110
src/Avalonia.MicroCom/MicroComProxyBase.cs

@@ -1,110 +0,0 @@
-using System;
-using System.Runtime.ConstrainedExecution;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-namespace Avalonia.MicroCom
-{
-    public unsafe class MicroComProxyBase : CriticalFinalizerObject, IUnknown
-    {
-        private IntPtr _nativePointer;
-        private bool _ownsHandle;
-        private SynchronizationContext _synchronizationContext;
-
-        public IntPtr NativePointer
-        {
-            get
-            {
-                if (_nativePointer == IntPtr.Zero)
-                    throw new ObjectDisposedException(this.GetType().FullName);
-                return _nativePointer;
-            }
-        }
-
-        public void*** PPV => (void***)NativePointer;
-
-        public MicroComProxyBase(IntPtr nativePointer, bool ownsHandle)
-        {
-            _nativePointer = nativePointer;
-            _ownsHandle = ownsHandle;
-            _synchronizationContext = SynchronizationContext.Current;
-            if(!_ownsHandle)
-                GC.SuppressFinalize(this);
-        }
-
-        protected virtual int VTableSize => 3;
-        
-        public void AddRef()
-        {
-            LocalInterop.CalliStdCallvoid(PPV, (*PPV)[1]);
-        }
-
-        public void Release()
-        {
-            LocalInterop.CalliStdCallvoid(PPV, (*PPV)[2]);
-        }
-
-        public int QueryInterface(Guid guid, out IntPtr ppv)
-        {
-            IntPtr r = default;
-            var rv = LocalInterop.CalliStdCallint(PPV, &guid, &r, (*PPV)[0]);
-            ppv = r;
-            return rv;
-        }
-
-        public T QueryInterface<T>() where T : IUnknown
-        {
-            var guid = MicroComRuntime.GetGuidFor(typeof(T));
-            var rv = QueryInterface(guid, out var ppv);
-            if (rv == 0)
-                return (T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true);
-            throw new COMException("QueryInterface failed", rv);
-        }
-
-        public bool IsDisposed => _nativePointer == IntPtr.Zero;
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if(_nativePointer == IntPtr.Zero)
-                return;
-            if (_ownsHandle)
-            {
-                Release();
-                _ownsHandle = false;
-            }
-            _nativePointer = IntPtr.Zero;
-            GC.SuppressFinalize(this);
-        }
-        
-        public void Dispose() => Dispose(true);
-
-        public bool OwnsHandle => _ownsHandle;
-        
-        public void EnsureOwned()
-        {
-            if (!_ownsHandle)
-            {
-                GC.ReRegisterForFinalize(true);
-                AddRef();
-                _ownsHandle = true;
-            }
-        }
-
-        private static readonly SendOrPostCallback _disposeDelegate = DisposeOnContext;
-
-        private static void DisposeOnContext(object state)
-        {
-            (state as MicroComProxyBase)?.Dispose(false);
-        }
-
-        ~MicroComProxyBase()
-        {
-            if(!_ownsHandle)
-                return;
-            if (_synchronizationContext == null)
-                Dispose();
-            else
-                _synchronizationContext.Post(_disposeDelegate, this);
-        }
-    }
-}

+ 0 - 143
src/Avalonia.MicroCom/MicroComRuntime.cs

@@ -1,143 +0,0 @@
-using System;
-using System.Collections.Concurrent;
-using System.Runtime.InteropServices;
-
-namespace Avalonia.MicroCom
-{
-    public static unsafe class MicroComRuntime
-    {
-        private static ConcurrentDictionary<Type, IntPtr> _vtables = new ConcurrentDictionary<Type, IntPtr>();
-
-        private static ConcurrentDictionary<Type, Func<IntPtr, bool, object>> _factories =
-            new ConcurrentDictionary<Type, Func<IntPtr, bool, object>>();
-        private static ConcurrentDictionary<Type, Guid> _guids = new ConcurrentDictionary<Type, Guid>();
-        private static ConcurrentDictionary<Guid, Type> _guidsToTypes = new ConcurrentDictionary<Guid, Type>();
-
-        internal static readonly Guid ManagedObjectInterfaceGuid = Guid.Parse("cd7687c0-a9c2-4563-b08e-a399df50c633");
-        
-        static MicroComRuntime()
-        {
-            Register(typeof(IUnknown), new Guid("00000000-0000-0000-C000-000000000046"),
-                (ppv, owns) => new MicroComProxyBase(ppv, owns));
-            RegisterVTable(typeof(IUnknown), MicroComVtblBase.Vtable);
-        }
-
-        public static void RegisterVTable(Type t, IntPtr vtable)
-        {
-            _vtables[t] = vtable;
-        }
-        
-        public static void Register(Type t, Guid guid, Func<IntPtr, bool, object> proxyFactory)
-        {
-            _factories[t] = proxyFactory;
-            _guids[t] = guid;
-            _guidsToTypes[guid] = t;
-        }
-
-        public static Guid GetGuidFor(Type type) => _guids[type];
-
-        public static T CreateProxyFor<T>(void* pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), new IntPtr(pObject), ownsHandle);
-        public static T CreateProxyFor<T>(IntPtr pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
-
-        public static T CreateProxyOrNullFor<T>(void* pObject, bool ownsHandle) where T : class =>
-            pObject == null ? null : (T)CreateProxyFor(typeof(T), new IntPtr(pObject), ownsHandle);
-        
-        public static T CreateProxyOrNullFor<T>(IntPtr pObject, bool ownsHandle) where T : class =>
-            pObject == IntPtr.Zero ? null : (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);
-                void* ptr = null;
-                var res = container.Shadow.GetOrCreateNativePointer(typeof(T), &ptr);
-                if (res != 0)
-                    throw new COMException(
-                        "Unable to create native callable wrapper for type " + typeof(T) + " for instance of type " +
-                        obj.GetType(),
-                        res);
-                if (owned)
-                    container.Shadow.AddRef((Ccw*)ptr);
-                return ptr;
-            }
-            throw new ArgumentException("Unable to get a native pointer for " + obj);
-        }
-
-        public static object GetObjectFromCcw(IntPtr ccw)
-        {
-            var ptr = (Ccw*)ccw;
-            var shadow = (MicroComShadow)GCHandle.FromIntPtr(ptr->GcShadowHandle).Target;
-            return shadow.Target;
-        }
-
-        public static bool IsComWrapper(IUnknown obj) => obj is MicroComProxyBase;
-
-        public static object TryUnwrapManagedObject(IUnknown obj)
-        {
-            if (obj is not MicroComProxyBase proxy)
-                return null;
-            if (proxy.QueryInterface(ManagedObjectInterfaceGuid, out _) != 0)
-                return null;
-            // Successful QueryInterface always increments ref counter
-            proxy.Release();
-            return GetObjectFromCcw(proxy.NativePointer);
-        }
-
-        public static bool TryGetTypeForGuid(Guid guid, out Type t) => _guidsToTypes.TryGetValue(guid, out t);
-
-        public static bool GetVtableFor(Type type, out IntPtr ptr) => _vtables.TryGetValue(type, out ptr);
-
-        public static void UnhandledException(object target, Exception e)
-        {
-            if (target is IMicroComExceptionCallback cb)
-            {
-                try
-                {
-                    cb.RaiseException(e);
-                }
-                catch
-                {
-                    // We've tried
-                }
-            }
-
-        }
-
-        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();
-        }
-    }
-}

+ 0 - 177
src/Avalonia.MicroCom/MicroComShadow.cs

@@ -1,177 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-namespace Avalonia.MicroCom
-{
-    public unsafe class MicroComShadow : IDisposable
-    {
-        private readonly object _lock = new object();
-        private readonly Dictionary<Type, IntPtr> _shadows = new Dictionary<Type, IntPtr>();
-        private readonly Dictionary<IntPtr, Type> _backShadows = new Dictionary<IntPtr, Type>();
-        private GCHandle? _handle;
-        private volatile int _refCount;
-        internal IMicroComShadowContainer Target { get; }
-        internal MicroComShadow(IMicroComShadowContainer target)
-        {
-            Target = target;
-            Target.Shadow = this;
-        }
-        
-        internal int QueryInterface(Ccw* ccw, Guid* guid, void** ppv)
-        {
-            if (MicroComRuntime.TryGetTypeForGuid(*guid, out var type))
-                return QueryInterface(type, ppv);
-            else if (*guid == MicroComRuntime.ManagedObjectInterfaceGuid)
-            {
-                ccw->RefCount++;
-                *ppv = ccw;
-                return 0;
-            }
-            else
-                return unchecked((int)0x80004002u);
-        }
-
-        internal int QueryInterface(Type type, void** ppv)
-        {
-            if (!type.IsInstanceOfType(Target))
-                return unchecked((int)0x80004002u);
-
-            var rv = GetOrCreateNativePointer(type, ppv);
-            if (rv == 0)
-                AddRef((Ccw*)*ppv);
-            return rv;
-        }
-
-        internal int GetOrCreateNativePointer(Type type, void** ppv)
-        {
-            if (!MicroComRuntime.GetVtableFor(type, out var vtable))
-                return unchecked((int)0x80004002u);
-            lock (_lock)
-            {
-
-                if (_shadows.TryGetValue(type, out var shadow))
-                {
-                    var targetCcw = (Ccw*)shadow;
-                    AddRef(targetCcw);
-                    *ppv = targetCcw;
-                    return 0;
-                }
-                else
-                {
-                    var intPtr = Marshal.AllocHGlobal(Marshal.SizeOf<Ccw>());
-                    var targetCcw = (Ccw*)intPtr;
-                    *targetCcw = default;
-                    targetCcw->RefCount = 0;
-                    targetCcw->VTable = vtable;
-                    if (_handle == null)
-                        _handle = GCHandle.Alloc(this);
-                    targetCcw->GcShadowHandle = GCHandle.ToIntPtr(_handle.Value);
-                    _shadows[type] = intPtr;
-                    _backShadows[intPtr] = type;
-                    *ppv = targetCcw;
-
-                    return 0;
-                }
-            }
-        }
-
-        internal int AddRef(Ccw* ccw)
-        {
-            if (Interlocked.Increment(ref _refCount) == 1)
-            {
-                try
-                {
-                    Target.OnReferencedFromNative();
-                }
-                catch (Exception e)
-                {
-                    MicroComRuntime.UnhandledException(Target, e);
-                }
-            }
-            
-            return Interlocked.Increment(ref ccw->RefCount);
-        }
-
-        internal int Release(Ccw* ccw)
-        {
-            Interlocked.Decrement(ref _refCount);
-            var cnt = Interlocked.Decrement(ref ccw->RefCount);
-            if (cnt == 0)
-                return FreeCcw(ccw);
-
-            return cnt;
-        }
-
-        int FreeCcw(Ccw* ccw)
-        {
-            lock (_lock)
-            {
-                // Shadow got resurrected by a call to QueryInterface from another thread
-                if (ccw->RefCount != 0)
-                    return ccw->RefCount;
-                    
-                var intPtr = new IntPtr(ccw);
-                var type = _backShadows[intPtr];
-                _backShadows.Remove(intPtr);
-                _shadows.Remove(type);
-                Marshal.FreeHGlobal(intPtr);
-                if (_shadows.Count == 0)
-                {
-                    _handle?.Free();
-                    _handle = null;
-                    try
-                    {
-                        Target.OnUnreferencedFromNative();
-                    }
-                    catch(Exception e)
-                    {
-                        MicroComRuntime.UnhandledException(Target, e);
-                    }
-                }
-            }
-
-            return 0;
-        }
-
-        /*
-         Needs to be called to support the following scenario:
-         1) Object created
-         2) Object passed to native code, shadow is created, CCW is created
-         3) Native side has never called AddRef
-         
-         In that case the GC handle to the shadow object is still alive
-         */
-        
-        public void Dispose()
-        {
-            lock (_lock)
-            {
-                List<IntPtr> toRemove = null;
-                foreach (var kv in _backShadows)
-                {
-                    var ccw = (Ccw*)kv.Key;
-                    if (ccw->RefCount == 0)
-                    {
-                        toRemove ??= new List<IntPtr>();
-                        toRemove.Add(kv.Key);
-                    }
-                }
-
-                if(toRemove != null)
-                    foreach (var intPtr in toRemove)
-                        FreeCcw((Ccw*)intPtr);
-            }
-        }
-    }
-    
-    [StructLayout(LayoutKind.Sequential)]
-    struct Ccw
-    {
-        public IntPtr VTable;
-        public IntPtr GcShadowHandle;
-        public volatile int RefCount;
-        public MicroComShadow GetShadow() => (MicroComShadow)GCHandle.FromIntPtr(GcShadowHandle).Target;
-    }
-}

+ 0 - 47
src/Avalonia.MicroCom/MicroComVtblBase.cs

@@ -1,47 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-
-namespace Avalonia.MicroCom
-{
-    public unsafe class MicroComVtblBase
-    {
-        private List<IntPtr> _methods = new List<IntPtr>();
-        [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
-        private delegate int AddRefDelegate(Ccw* ccw);
-
-        [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]
-        private delegate int QueryInterfaceDelegate(Ccw* ccw, Guid* guid, void** ppv);
-
-        public static IntPtr Vtable { get; } = new MicroComVtblBase().CreateVTable();
-        public MicroComVtblBase()
-        {
-            AddMethod((QueryInterfaceDelegate)QueryInterface);
-            AddMethod((AddRefDelegate)AddRef);
-            AddMethod((AddRefDelegate)Release);
-        }
-
-        protected void AddMethod(void* f)
-        {
-            _methods.Add(new IntPtr(f));
-        }
-
-        protected void AddMethod(Delegate d)
-        {
-            GCHandle.Alloc(d);
-            _methods.Add(Marshal.GetFunctionPointerForDelegate(d));
-        }
-
-        protected unsafe IntPtr CreateVTable()
-        {
-            var ptr = (IntPtr*)Marshal.AllocHGlobal((IntPtr.Size + 1) * _methods.Count);
-            for (var c = 0; c < _methods.Count; c++)
-                ptr[c] = _methods[c];
-            return new IntPtr(ptr);
-        }
-
-        static int QueryInterface(Ccw* ccw, Guid* guid, void** ppv) => ccw->GetShadow().QueryInterface(ccw, guid, ppv);
-        static int AddRef(Ccw* ccw) => ccw->GetShadow().AddRef(ccw);
-        static int Release(Ccw* ccw) => ccw->GetShadow().Release(ccw);
-    }
-}

+ 0 - 1
src/Avalonia.Native/Avalonia.Native.csproj

@@ -6,7 +6,6 @@
     <IsPackable Condition="'$([MSBuild]::IsOSPlatform(OSX))' == 'True'">true</IsPackable>
     <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-    <MicroComGeneratorRuntimeNamespace>Avalonia.MicroCom</MicroComGeneratorRuntimeNamespace>
   </PropertyGroup>
 
   <ItemGroup Condition="'$(PackAvaloniaNative)' == 'true'">

+ 1 - 0
src/Avalonia.Native/AvaloniaNativePlatform.cs

@@ -10,6 +10,7 @@ using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Rendering.Composition;
 using JetBrains.Annotations;
+using MicroCom.Runtime;
 
 namespace Avalonia.Native
 {

+ 1 - 0
src/Avalonia.Native/CallbackBase.cs

@@ -2,6 +2,7 @@
 using System.Runtime.ExceptionServices;
 using Avalonia.MicroCom;
 using Avalonia.Platform;
+using MicroCom.Runtime;
 
 namespace Avalonia.Native
 {

+ 1 - 0
src/Avalonia.Native/NativeControlHostImpl.cs

@@ -4,6 +4,7 @@ using Avalonia.MicroCom;
 using Avalonia.Native.Interop;
 using Avalonia.Platform;
 using Avalonia.VisualTree;
+using MicroCom.Runtime;
 
 namespace Avalonia.Native
 {

+ 1 - 1
src/Avalonia.X11/X11Structs.cs

@@ -661,7 +661,7 @@ namespace Avalonia.X11 {
 			Type type = ev.GetType ();
 			FieldInfo [] fields = type.GetFields (System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Instance);
 			for (int i = 0; i < fields.Length; i++) {
-				if (result != string.Empty) {
+				if (!string.IsNullOrEmpty(result)) {
 					result += ", ";
 				}
 				object value = fields [i].GetValue (ev);

+ 9 - 9
src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs

@@ -376,28 +376,28 @@ namespace Avalonia.Markup.Parsers
 
             if (r.Peek == 'o')
             {
-                var constArg = r.TakeUntil(')').ToString().Trim();
-                if (constArg.Equals("odd", StringComparison.Ordinal))
+                var constArg = r.TakeUntil(')').Trim();
+                if (constArg.SequenceEqual("odd".AsSpan()))
                 {
                     step = 2;
                     offset = 1;
                 }
                 else
                 {
-                    throw new ExpressionParseException(r.Position, $"Expected nth-child(odd). Actual '{constArg}'.");
+                    throw new ExpressionParseException(r.Position, $"Expected nth-child(odd). Actual '{constArg.ToString()}'.");
                 }
             }
             else if (r.Peek == 'e')
             {
-                var constArg = r.TakeUntil(')').ToString().Trim();
-                if (constArg.Equals("even", StringComparison.Ordinal))
+                var constArg = r.TakeUntil(')').Trim();
+                if (constArg.SequenceEqual("even".AsSpan()))
                 {
                     step = 2;
                     offset = 0;
                 }
                 else
                 {
-                    throw new ExpressionParseException(r.Position, $"Expected nth-child(even). Actual '{constArg}'.");
+                    throw new ExpressionParseException(r.Position, $"Expected nth-child(even). Actual '{constArg.ToString()}'.");
                 }
             }
             else
@@ -405,7 +405,7 @@ namespace Avalonia.Markup.Parsers
                 r.SkipWhitespace();
 
                 var stepOrOffset = 0;
-                var stepOrOffsetStr = r.TakeWhile(c => char.IsDigit(c) || c == '-' || c == '+').ToString();
+                var stepOrOffsetStr = r.TakeWhile(c => char.IsDigit(c) || c == '-' || c == '+');
                 if (stepOrOffsetStr.Length == 0
                     || (stepOrOffsetStr.Length == 1
                     && stepOrOffsetStr[0] == '+'))
@@ -417,7 +417,7 @@ namespace Avalonia.Markup.Parsers
                 {
                     stepOrOffset = -1;
                 }
-                else if (!int.TryParse(stepOrOffsetStr.ToString(), out stepOrOffset))
+                else if (!stepOrOffsetStr.TryParseInt(out stepOrOffset))
                 {
                     throw new ExpressionParseException(r.Position, "Couldn't parse nth-child step or offset value. Integer was expected.");
                 }
@@ -462,7 +462,7 @@ namespace Avalonia.Markup.Parsers
                         r.SkipWhitespace();
 
                         if (sign != 0
-                            && !int.TryParse(r.TakeUntil(')').ToString(), out offset))
+                            && !r.TakeUntil(')').TryParseInt(out offset))
                         {
                             throw new ExpressionParseException(r.Position, "Couldn't parse nth-child offset value. Integer was expected.");
                         }

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

@@ -3,7 +3,6 @@
     <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <PackageId>Avalonia.Win32</PackageId>
-    <MicroComGeneratorRuntimeNamespace>Avalonia.MicroCom</MicroComGeneratorRuntimeNamespace>
   </PropertyGroup>
   <ItemGroup>
     <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />

+ 4 - 3
src/Windows/Avalonia.Win32/ClipboardImpl.cs

@@ -7,6 +7,7 @@ using Avalonia.Input;
 using Avalonia.Input.Platform;
 using Avalonia.Threading;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32
 {
@@ -83,7 +84,7 @@ namespace Avalonia.Win32
 
             while (true)
             {
-                var ptr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(wrapper);
+                var ptr = wrapper.GetNativeIntPtr<Win32Com.IDataObject>();
                 var hr = UnmanagedMethods.OleSetClipboard(ptr);
 
                 if (hr == 0)
@@ -107,7 +108,7 @@ namespace Avalonia.Win32
 
                 if (hr == 0)
                 {
-                    using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
+                    using var proxy = MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
                     using var wrapper = new OleDataObject(proxy);
                     var formats = wrapper.GetDataFormats().ToArray();
                     return formats;
@@ -131,7 +132,7 @@ namespace Avalonia.Win32
 
                 if (hr == 0)
                 {
-                    using var proxy = MicroCom.MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
+                    using var proxy = MicroComRuntime.CreateProxyFor<Win32Com.IDataObject>(dataObject, true);
                     using var wrapper = new OleDataObject(proxy);
                     var rv = wrapper.Get(format);
                     return rv;

+ 3 - 2
src/Windows/Avalonia.Win32/DragSource.cs

@@ -3,6 +3,7 @@ using Avalonia.Input;
 using Avalonia.Input.Platform;
 using Avalonia.Threading;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32
 {
@@ -19,8 +20,8 @@ namespace Avalonia.Win32
             using var src = new OleDragSource();
             var allowed = OleDropTarget.ConvertDropEffect(allowedEffects);
             
-            var objPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(dataObject);
-            var srcPtr = MicroCom.MicroComRuntime.GetNativeIntPtr<Win32Com.IDropSource>(src);
+            var objPtr = MicroComRuntime.GetNativeIntPtr<Win32Com.IDataObject>(dataObject);
+            var srcPtr = MicroComRuntime.GetNativeIntPtr<Win32Com.IDropSource>(src);
 
             UnmanagedMethods.DoDragDrop(objPtr, srcPtr, (int)allowed, out var finalEffect);
             

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

@@ -7,6 +7,7 @@ using System.Runtime.InteropServices.ComTypes;
 using System.Text;
 
 using Avalonia.MicroCom;
+using MicroCom.Runtime;
 using Avalonia.Win32.Win32Com;
 
 // ReSharper disable InconsistentNaming

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

@@ -5,6 +5,7 @@ using Avalonia.Platform;
 using Avalonia.Threading;
 using Avalonia.Win32.Interop;
 using Avalonia.Win32.Win32Com;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32
 {
@@ -47,7 +48,7 @@ namespace Avalonia.Win32
                 return false;
             }
 
-            var trgPtr = MicroCom.MicroComRuntime.GetNativeIntPtr(target);
+            var trgPtr = target.GetNativeIntPtr();
             return UnmanagedMethods.RegisterDragDrop(hwnd.Handle, trgPtr) == UnmanagedMethods.HRESULT.S_OK;
         }
 

+ 1 - 1
src/Windows/Avalonia.Win32/OleDataObject.cs

@@ -10,7 +10,7 @@ using Avalonia.Input;
 using Avalonia.MicroCom;
 using Avalonia.Utilities;
 using Avalonia.Win32.Interop;
-
+using MicroCom.Runtime;
 using IDataObject = Avalonia.Input.IDataObject;
 
 namespace Avalonia.Win32

+ 1 - 0
src/Windows/Avalonia.Win32/OleDropTarget.cs

@@ -5,6 +5,7 @@ using Avalonia.Input.Raw;
 using Avalonia.MicroCom;
 using Avalonia.Platform;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 using DropEffect = Avalonia.Win32.Win32Com.DropEffect;
 
 namespace Avalonia.Win32

+ 1 - 0
src/Windows/Avalonia.Win32/Win32StorageProvider.cs

@@ -12,6 +12,7 @@ using Avalonia.Platform.Storage;
 using Avalonia.Platform.Storage.FileIO;
 using Avalonia.Win32.Interop;
 using Avalonia.Win32.Win32Com;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32
 {

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

@@ -6,6 +6,7 @@ using Avalonia.MicroCom;
 using Avalonia.OpenGL;
 using Avalonia.OpenGL.Egl;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT.Composition
 {

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

@@ -12,6 +12,7 @@ using Avalonia.OpenGL.Angle;
 using Avalonia.OpenGL.Egl;
 using Avalonia.Rendering;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT.Composition
 {

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

@@ -2,6 +2,7 @@
 using System.Linq;
 using System.Runtime.InteropServices;
 using Avalonia.MicroCom;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT.Composition
 {

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

@@ -6,6 +6,7 @@ using Avalonia.OpenGL.Egl;
 using Avalonia.OpenGL.Surfaces;
 using Avalonia.Utilities;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT.Composition
 {

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

@@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
 using System.Threading;
 using Avalonia.MicroCom;
 using Avalonia.Win32.Interop;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT
 {

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

@@ -3,6 +3,7 @@ using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using Avalonia.MicroCom;
+using MicroCom.Runtime;
 
 namespace Avalonia.Win32.WinRT
 {

+ 1 - 1
tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs

@@ -80,7 +80,7 @@ namespace Avalonia.Visuals.UnitTests.Media.TextFormatting
                             var remaining = remainingChars.Where(x => x != "" && x != "×").Select(x => Convert.ToInt32(x, 16)).ToArray();
 
                             codepoints.AddRange(remaining);
-                        }                     
+                        }
 
                         var data = new GraphemeBreakData
                         {

+ 0 - 1
tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj

@@ -1,6 +1,5 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
-    <OutputType>Exe</OutputType>
     <TargetFramework>net6.0</TargetFramework>
     <OutputType>Exe</OutputType>
     <IsPackable>false</IsPackable>