Browse Source

Merge branch 'master' into fixes/8869-show-windowstate

grokys/experiment/appium-2
Steven Kirk 3 years ago
committed by GitHub
parent
commit
78be07a2f8
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .editorconfig
  2. 1
      .github/FUNDING.yml
  3. 2
      src/Avalonia.Base/Input/DragDrop.cs
  4. 8
      src/Avalonia.Base/Input/DragDropDevice.cs
  5. 49
      src/Avalonia.Base/Media/Color.cs
  6. 30
      src/Avalonia.Base/Media/HslColor.cs
  7. 30
      src/Avalonia.Base/Media/HsvColor.cs
  8. 49
      src/Avalonia.Base/Utilities/SpanHelpers.cs
  9. 72
      src/Avalonia.Build.Tasks/SpanCompat.cs
  10. 4
      src/Avalonia.Controls.DataGrid/DataGridValueConverter.cs
  11. 4
      src/Avalonia.Controls/AppBuilderBase.cs
  12. 2
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  13. 2
      src/Avalonia.Controls/DefinitionBase.cs
  14. 2
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/SimpleWebSocketHttpServer.cs
  15. 3
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  16. 1
      src/Avalonia.MicroCom/Avalonia.MicroCom.csproj
  17. 4
      src/Avalonia.MicroCom/CallbackBase.cs
  18. 9
      src/Avalonia.MicroCom/IMicroComExceptionCallback.cs
  19. 9
      src/Avalonia.MicroCom/IMicroComShadowContainer.cs
  20. 8
      src/Avalonia.MicroCom/IUnknown.cs
  21. 17
      src/Avalonia.MicroCom/LocalInterop.cs
  22. 110
      src/Avalonia.MicroCom/MicroComProxyBase.cs
  23. 143
      src/Avalonia.MicroCom/MicroComRuntime.cs
  24. 177
      src/Avalonia.MicroCom/MicroComShadow.cs
  25. 47
      src/Avalonia.MicroCom/MicroComVtblBase.cs
  26. 1
      src/Avalonia.Native/Avalonia.Native.csproj
  27. 1
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  28. 1
      src/Avalonia.Native/CallbackBase.cs
  29. 1
      src/Avalonia.Native/NativeControlHostImpl.cs
  30. 2
      src/Avalonia.X11/X11Structs.cs
  31. 18
      src/Markup/Avalonia.Markup/Markup/Parsers/SelectorGrammar.cs
  32. 2
      src/Web/Avalonia.Web/AvaloniaView.cs
  33. 2
      src/Web/Avalonia.Web/webapp/build.js
  34. 1
      src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts
  35. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  36. 7
      src/Windows/Avalonia.Win32/ClipboardImpl.cs
  37. 5
      src/Windows/Avalonia.Win32/DragSource.cs
  38. 1
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  39. 3
      src/Windows/Avalonia.Win32/OleContext.cs
  40. 2
      src/Windows/Avalonia.Win32/OleDataObject.cs
  41. 1
      src/Windows/Avalonia.Win32/OleDropTarget.cs
  42. 1
      src/Windows/Avalonia.Win32/Win32StorageProvider.cs
  43. 1
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
  44. 1
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
  45. 1
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
  46. 1
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
  47. 1
      src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
  48. 1
      src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
  49. 2
      tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs
  50. 1
      tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
  51. 6
      tests/Directory.Build.props

6
.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

1
.github/FUNDING.yml

@ -1 +1,2 @@
github: avaloniaui
open_collective: avalonia

2
src/Avalonia.Base/Input/DragDrop.cs

@ -13,7 +13,7 @@ namespace Avalonia.Input
/// <summary>
/// Event which is raised, when a drag-and-drop operation leaves the element.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> DragLeaveEvent = RoutedEvent.Register<RoutedEventArgs>("DragLeave", RoutingStrategies.Bubble, typeof(DragDrop));
public static readonly RoutedEvent<DragEventArgs> DragLeaveEvent = RoutedEvent.Register<DragEventArgs>("DragLeave", RoutingStrategies.Bubble, typeof(DragDrop));
/// <summary>
/// Event which is raised, when a drag-and-drop operation is updated while over the element.
/// </summary>

8
src/Avalonia.Base/Input/DragDropDevice.cs

@ -54,7 +54,7 @@ namespace Avalonia.Input
try
{
if (_lastTarget != null)
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));
RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragLeaveEvent, effects, data, modifiers);
return RaiseDragEvent(target, inputRoot, point, DragDrop.DragEnterEvent, effects, data, modifiers);
}
finally
@ -63,13 +63,13 @@ namespace Avalonia.Input
}
}
private void DragLeave(IInputElement inputRoot)
private void DragLeave(IInputRoot inputRoot, Point point, IDataObject data, DragDropEffects effects, KeyModifiers modifiers)
{
if (_lastTarget == null)
return;
try
{
_lastTarget.RaiseEvent(new RoutedEventArgs(DragDrop.DragLeaveEvent));
RaiseDragEvent(_lastTarget, inputRoot, point, DragDrop.DragLeaveEvent, effects, data, modifiers);
}
finally
{
@ -106,7 +106,7 @@ namespace Avalonia.Input
e.Effects = DragOver(e.Root, e.Location, e.Data, e.Effects, e.KeyModifiers);
break;
case RawDragEventType.DragLeave:
DragLeave(e.Root);
DragLeave(e.Root, e.Location, e.Data, e.Effects, e.KeyModifiers);
break;
case RawDragEventType.Drop:
e.Effects = Drop(e.Root, e.Location, e.Data, e.Effects, e.KeyModifiers);

49
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);
}
}

30
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);
}
}

30
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
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
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));
}

4
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;
}

4
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

2
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();

2
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)

2
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();

3
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -19,7 +19,8 @@
<ProjectReference Include="..\Avalonia.Themes.Simple\Avalonia.Themes.Simple.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.4.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.8.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.8.0" />
</ItemGroup>
<Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\Rx.props" />

1
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>

4
src/Avalonia.MicroCom/CallbackBase.cs

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

9
src/Avalonia.MicroCom/IMicroComExceptionCallback.cs

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

9
src/Avalonia.MicroCom/IMicroComShadowContainer.cs

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

8
src/Avalonia.MicroCom/IUnknown.cs

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

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;
}
}
}

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);
}
}
}

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();
}
}
}

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;
}
}

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);
}
}

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
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
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
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
{

2
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);

18
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.");
}

2
src/Web/Avalonia.Web/AvaloniaView.cs

@ -136,6 +136,8 @@ namespace Avalonia.Web
DomHelper.ObserveSize(host, null, OnSizeChanged);
CanvasHelper.RequestAnimationFrame(_canvas, true);
InputHelper.FocusElement(_containerElement);
}
private static RawPointerPoint ExtractRawPointerFromJSArgs(JSObject args)

2
src/Web/Avalonia.Web/webapp/build.js

@ -5,7 +5,7 @@ require("esbuild").build({
],
outdir: "../wwwroot",
bundle: true,
minify: false,
minify: true,
format: "esm",
target: "es2016",
platform: "browser",

1
src/Web/Avalonia.Web/webapp/modules/avalonia/dom.ts

@ -11,6 +11,7 @@ export class AvaloniaDOM {
host.tabIndex = 0;
host.oncontextmenu = function () { return false; };
host.style.overflow = "hidden";
host.style.touchAction = "none";
// Rendering target canvas
const canvas = document.createElement("canvas");

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" />

7
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;

5
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
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

3
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;
}

2
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
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
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
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
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
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
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
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
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
{

2
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
{

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>

6
tests/Directory.Build.props

@ -0,0 +1,6 @@
<Project>
<Import Project="..\Directory.Build.props" />
<PropertyGroup>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
</PropertyGroup>
</Project>
Loading…
Cancel
Save