Browse Source

Remove Uncompilable code guarded by platform defines (#20861)

* remove uncompilable code guarded by platform defines

* Remove OperatingSystemEx

* remove NativeLibraryEx

* remove unused classes

* fix unused usings
pull/20892/head
Emmanuel Hansen 2 weeks ago
committed by GitHub
parent
commit
7bdf54ee35
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 14
      samples/ControlCatalog/Pages/DialogsPage.xaml.cs
  2. 8
      src/Avalonia.Base/Avalonia.Base.csproj
  3. 32
      src/Avalonia.Base/Compatibility/CollectionCompatibilityExtensions.cs
  4. 122
      src/Avalonia.Base/Compatibility/NativeLibrary.cs
  5. 32
      src/Avalonia.Base/Compatibility/OperatingSystem.cs
  6. 43
      src/Avalonia.Base/Compatibility/StringSyntaxAttribute.cs
  7. 2
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs
  8. 2
      src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs
  9. 2
      src/Avalonia.Base/Data/Core/Parsers/ExpressionNodeFactory.cs
  10. 4
      src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs
  11. 4
      src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs
  12. 14
      src/Avalonia.Base/Input/DataFormat.cs
  13. 4
      src/Avalonia.Base/Input/KeyGesture.cs
  14. 5
      src/Avalonia.Base/Layout/LayoutHelper.cs
  15. 4
      src/Avalonia.Base/Media/Fonts/FamilyNameCollection.cs
  16. 2
      src/Avalonia.Base/Media/GlyphRun.cs
  17. 15
      src/Avalonia.Base/Media/TextFormatting/FormattingBufferHelper.cs
  18. 6
      src/Avalonia.Base/Media/Typeface.cs
  19. 13
      src/Avalonia.Base/Platform/Internal/UnmanagedBlob.cs
  20. 12
      src/Avalonia.Base/Platform/StandardRuntimePlatform.cs
  21. 3
      src/Avalonia.Base/Platform/StandardRuntimePlatformServices.cs
  22. 11
      src/Avalonia.Base/Platform/Storage/FileIO/BclLauncher.cs
  23. 7
      src/Avalonia.Base/Platform/Storage/FileIO/BclStorageProvider.cs
  24. 8
      src/Avalonia.Base/Platform/Storage/FileIO/SecurityScopedStream.cs
  25. 12
      src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs
  26. 4
      src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs
  27. 5
      src/Avalonia.Base/Rendering/Composition/Server/FrameTimeGraph.cs
  28. 5
      src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs
  29. 3
      src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
  30. 156
      src/Avalonia.Base/Threading/CulturePreservingExecutionContext.cs
  31. 8
      src/Avalonia.Base/Threading/DispatcherOperation.cs
  32. 7
      src/Avalonia.Base/Threading/NonPumpingSyncContext.cs
  33. 4
      src/Avalonia.Base/Utilities/ArrayBuilder.cs
  34. 10
      src/Avalonia.Base/Utilities/AvaloniaPropertyDictionary.cs
  35. 34
      src/Avalonia.Base/Utilities/EnumHelper.cs
  36. 43
      src/Avalonia.Base/Utilities/Polyfills.cs
  37. 20
      src/Avalonia.Base/Utilities/RefCountingSmallDictionary.cs
  38. 3
      src/Avalonia.Base/Utilities/SmallDictionary.cs
  39. 4
      src/Avalonia.Base/Utilities/StringSplitter.cs
  40. 7
      src/Avalonia.Controls.ColorPicker/Helpers/ColorHelper.cs
  41. 4
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
  42. 5
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs
  43. 8
      src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs
  44. 2
      src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs
  45. 6
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  46. 4
      src/Avalonia.Native/IAvnMenu.cs
  47. 6
      src/Avalonia.Native/IAvnMenuItem.cs
  48. 11
      src/Avalonia.OpenGL/Egl/EglInterface.cs
  49. 4
      src/Avalonia.OpenGL/OpenGlException.cs
  50. 2
      src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs
  51. 5
      src/Avalonia.X11/X11Window.cs
  52. 4
      src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs
  53. 16
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs
  54. 2
      src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs
  55. 11
      src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs
  56. 4
      src/Markup/Avalonia.Markup/Data/Binding.cs
  57. 2
      src/Shared/ModuleInitializer.cs
  58. 3
      src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs
  59. 6
      src/Skia/Avalonia.Skia/SKRoundRectCache.cs
  60. 14
      src/Windows/Avalonia.Win32.Automation/AutomationNode.cs
  61. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IDockProvider.cs
  62. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IExpandCollapseProvider.cs
  63. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IGridItemProvider.cs
  64. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IGridProvider.cs
  65. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IInvokeProvider.cs
  66. 8
      src/Windows/Avalonia.Win32.Automation/Interop/IMultipleViewProvider.cs
  67. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IRangeValueProvider.cs
  68. 9
      src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderAdviseEvents.cs
  69. 9
      src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderFragment.cs
  70. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderFragmentRoot.cs
  71. 7
      src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderSimple.cs
  72. 15
      src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderSimple2.cs
  73. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IScrollItemProvider.cs
  74. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IScrollProvider.cs
  75. 5
      src/Windows/Avalonia.Win32.Automation/Interop/ISelectionItemProvider.cs
  76. 7
      src/Windows/Avalonia.Win32.Automation/Interop/ISelectionProvider.cs
  77. 6
      src/Windows/Avalonia.Win32.Automation/Interop/ISynchronizedInputProvider.cs
  78. 9
      src/Windows/Avalonia.Win32.Automation/Interop/ITableItemProvider.cs
  79. 10
      src/Windows/Avalonia.Win32.Automation/Interop/ITableProvider.cs
  80. 9
      src/Windows/Avalonia.Win32.Automation/Interop/ITextProvider.cs
  81. 13
      src/Windows/Avalonia.Win32.Automation/Interop/ITextRangeProvider.cs
  82. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IToggleProvider.cs
  83. 5
      src/Windows/Avalonia.Win32.Automation/Interop/ITransformProvider.cs
  84. 5
      src/Windows/Avalonia.Win32.Automation/Interop/IValueProvider.cs
  85. 6
      src/Windows/Avalonia.Win32.Automation/Interop/IWindowProvider.cs
  86. 27
      src/Windows/Avalonia.Win32.Automation/Interop/UiaCoreProviderApi.cs
  87. 25
      src/Windows/Avalonia.Win32.Automation/Interop/UiaCoreTypesApi.cs
  88. 4
      src/Windows/Avalonia.Win32.Automation/InteropAutomationNode.cs
  89. 2
      src/Windows/Avalonia.Win32.Automation/Marshalling/ComVariant.cs
  90. 4
      src/Windows/Avalonia.Win32.Automation/Marshalling/ComVariantMarshaller.cs
  91. 4
      src/Windows/Avalonia.Win32.Automation/Marshalling/SafeArrayMarshaller.cs
  92. 3
      src/Windows/Avalonia.Win32.Automation/Marshalling/SafeArrayRef.cs
  93. 8
      src/Windows/Avalonia.Win32.Automation/RootAutomationNode.cs
  94. 4
      src/Windows/Avalonia.Win32/OleDataObjectHelper.cs
  95. 17
      src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs
  96. 1
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
  97. 4
      src/tools/Avalonia.Designer.HostApp/TinyJson.cs

14
samples/ControlCatalog/Pages/DialogsPage.xaml.cs

@ -228,13 +228,8 @@ namespace ControlCatalog.Pages
try
{
// Sync disposal of StreamWriter is not supported on WASM
#if NET6_0_OR_GREATER
await using var stream = await file.OpenWriteAsync();
await using var writer = new System.IO.StreamWriter(stream);
#else
using var stream = await file.OpenWriteAsync();
using var writer = new System.IO.StreamWriter(stream);
#endif
await writer.WriteLineAsync(openedFileContent.Text);
SetFolder(await file.GetParentAsync());
@ -265,13 +260,8 @@ namespace ControlCatalog.Pages
if (result.File is { } file)
{
// Sync disposal of StreamWriter is not supported on WASM
#if NET6_0_OR_GREATER
await using var stream = await file.OpenWriteAsync();
await using var writer = new System.IO.StreamWriter(stream);
#else
using var stream = await file.OpenWriteAsync();
using var writer = new System.IO.StreamWriter(stream);
#endif
if (result.SelectedFileType == FilePickerFileTypes.Xml)
{
await writer.WriteLineAsync("<sample>Test</sample>");
@ -431,11 +421,7 @@ namespace ControlCatalog.Pages
internal static async Task<string> ReadTextFromFile(IStorageFile file, int length)
{
#if NET6_0_OR_GREATER
await using var stream = await file.OpenReadAsync();
#else
using var stream = await file.OpenReadAsync();
#endif
using var reader = new System.IO.StreamReader(stream);
// 4GB file test, shouldn't load more than 10000 chars into a memory.

8
src/Avalonia.Base/Avalonia.Base.csproj

@ -16,11 +16,7 @@
<Import Project="..\..\build\DevAnalyzers.props" />
<Import Project="..\..\build\SourceGenerators.props" />
<ItemGroup>
<Compile Include="..\Shared\CallerArgumentExpressionAttribute.cs" Link="Compatibility\CallerArgumentExpressionAttribute.cs" />
<Compile Include="..\Shared\IsExternalInit.cs" Link="Compatibility\IsExternalInit.cs" />
<Compile Include="..\Shared\ModuleInitializer.cs" Link="Compatibility\ModuleInitializer.cs" />
<Compile Include="..\Shared\StringCompatibilityExtensions.cs" Link="Compatibility\StringCompatibilityExtensions.cs" />
<Compile Include="..\Shared\StreamCompatibilityExtensions.cs" Link="Compatibility\StreamCompatibilityExtensions.cs" />
</ItemGroup>
<ItemGroup Condition="!$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
@ -65,8 +61,6 @@
</ItemGroup>
<ItemGroup Label="Build dependency">
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj"
ReferenceOutputAssembly="false"
PrivateAssets="all" />
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj" ReferenceOutputAssembly="false" PrivateAssets="all" />
</ItemGroup>
</Project>

32
src/Avalonia.Base/Compatibility/CollectionCompatibilityExtensions.cs

@ -1,32 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace System;
#if !NET6_0_OR_GREATER
internal static class CollectionCompatibilityExtensions
{
public static bool Remove<TKey, TValue>(
this Dictionary<TKey, TValue> o,
TKey key,
[MaybeNullWhen(false)] out TValue value)
where TKey : notnull
{
if (o.TryGetValue(key, out value))
return o.Remove(key);
return false;
}
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> o, TKey key, TValue value)
where TKey : notnull
{
if (!o.ContainsKey(key))
{
o.Add(key, value);
return true;
}
return false;
}
}
#endif

122
src/Avalonia.Base/Compatibility/NativeLibrary.cs

@ -1,122 +0,0 @@
using System;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
using Avalonia.Platform.Interop;
namespace Avalonia.Compatibility
{
internal class NativeLibraryEx
{
#if NET6_0_OR_GREATER
public static IntPtr Load(string dll, Assembly assembly) => NativeLibrary.Load(dll, assembly, null);
public static IntPtr Load(string dll) => NativeLibrary.Load(dll);
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) =>
NativeLibrary.TryGetExport(handle, name, out address);
#else
public static IntPtr Load(string dll, Assembly assembly) => Load(dll);
public static IntPtr Load(string dll)
{
var handle = DlOpen!(dll);
if (handle != IntPtr.Zero)
return handle;
throw new InvalidOperationException("Unable to load " + dll, DlError!());
}
public static bool TryGetExport(IntPtr handle, string name, out IntPtr address)
{
try
{
address = DlSym!(handle, name);
return address != default;
}
catch (Exception)
{
address = default;
return false;
}
}
static NativeLibraryEx()
{
if (OperatingSystemEx.IsWindows())
{
Win32Imports.Init();
}
else if (OperatingSystemEx.IsLinux() || OperatingSystemEx.IsMacOS())
{
var buffer = Marshal.AllocHGlobal(0x1000);
uname(buffer);
var unixName = Marshal.PtrToStringAnsi(buffer);
Marshal.FreeHGlobal(buffer);
if (unixName == "Darwin")
OsXImports.Init();
else
LinuxImports.Init();
}
}
private static Func<string, IntPtr>? DlOpen;
private static Func<IntPtr, string, IntPtr>? DlSym;
private static Func<Exception?>? DlError;
[DllImport("libc")]
static extern int uname(IntPtr buf);
static class Win32Imports
{
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr LoadLibrary(string lpszLib);
public static void Init()
{
DlOpen = LoadLibrary;
DlSym = GetProcAddress;
DlError = () => new Win32Exception(Marshal.GetLastWin32Error());
}
}
static class LinuxImports
{
[DllImport("libdl.so.2")]
private static extern IntPtr dlopen(string path, int flags);
[DllImport("libdl.so.2")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);
[DllImport("libdl.so.2")]
private static extern IntPtr dlerror();
public static void Init()
{
DlOpen = s => dlopen(s, 1);
DlSym = dlsym;
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror()));
}
}
static class OsXImports
{
[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlopen(string path, int flags);
[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlsym(IntPtr handle, string symbol);
[DllImport("/usr/lib/libSystem.dylib")]
private static extern IntPtr dlerror();
public static void Init()
{
DlOpen = s => dlopen(s, 1);
DlSym = dlsym;
DlError = () => new InvalidOperationException(Marshal.PtrToStringAnsi(dlerror()));
}
}
#endif
}
}

32
src/Avalonia.Base/Compatibility/OperatingSystem.cs

@ -1,32 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Avalonia.Compatibility
{
internal sealed class OperatingSystemEx
{
#if NET6_0_OR_GREATER
public static bool IsWindows() => OperatingSystem.IsWindows();
public static bool IsMacOS() => OperatingSystem.IsMacOS();
public static bool IsMacCatalyst() => OperatingSystem.IsMacCatalyst();
public static bool IsLinux() => OperatingSystem.IsLinux();
public static bool IsFreeBSD() => OperatingSystem.IsFreeBSD();
public static bool IsAndroid() => OperatingSystem.IsAndroid();
public static bool IsIOS() => OperatingSystem.IsIOS();
public static bool IsTvOS() => OperatingSystem.IsTvOS();
public static bool IsBrowser() => OperatingSystem.IsBrowser();
public static bool IsOSPlatform(string platform) => OperatingSystem.IsOSPlatform(platform);
#else
public static bool IsWindows() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
public static bool IsMacOS() => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsLinux() => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
public static bool IsFreeBSD() => false;
public static bool IsAndroid() => false;
public static bool IsIOS() => false;
public static bool IsMacCatalyst() => false;
public static bool IsTvOS() => false;
public static bool IsBrowser() => false;
public static bool IsOSPlatform(string platform) => RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform));
#endif
}
}

43
src/Avalonia.Base/Compatibility/StringSyntaxAttribute.cs

@ -1,43 +0,0 @@
#pragma warning disable MA0048 // File name must match type name
// https://github.com/dotnet/runtime/blob/v8.0.4/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// ReSharper disable once CheckNamespace
namespace System.Diagnostics.CodeAnalysis
{
#if !NET7_0_OR_GREATER
/// <summary>Specifies the syntax used in a string.</summary>
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
internal sealed class StringSyntaxAttribute : Attribute
{
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
/// <param name="syntax">The syntax identifier.</param>
public StringSyntaxAttribute(string syntax)
{
Syntax = syntax;
Arguments = Array.Empty<object?>();
}
/// <summary>Initializes the <see cref="StringSyntaxAttribute"/> with the identifier of the syntax used.</summary>
/// <param name="syntax">The syntax identifier.</param>
/// <param name="arguments">Optional arguments associated with the specific syntax employed.</param>
public StringSyntaxAttribute(string syntax, params object?[] arguments)
{
Syntax = syntax;
Arguments = arguments;
}
/// <summary>Gets the identifier of the syntax used.</summary>
public string Syntax { get; }
/// <summary>Optional arguments associated with the specific syntax employed.</summary>
public object?[] Arguments { get; }
/// <summary>The syntax identifier for strings containing XML.</summary>
public const string Xml = nameof(Xml);
}
#endif
}

2
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/DynamicPluginStreamNode.cs

@ -7,9 +7,7 @@ using Avalonia.Reactive;
namespace Avalonia.Data.Core.ExpressionNodes.Reflection;
[RequiresUnreferencedCode(TrimmingMessages.ExpressionNodeRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal sealed class DynamicPluginStreamNode : ExpressionNode
{
private IDisposable? _subscription;

2
src/Avalonia.Base/Data/Core/ExpressionNodes/Reflection/ExpressionTreeIndexerNode.cs

@ -16,9 +16,7 @@ internal sealed class ExpressionTreeIndexerNode : CollectionNodeBase, ISettableN
private readonly Delegate _getDelegate;
private readonly Delegate _firstArgumentDelegate;
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
public ExpressionTreeIndexerNode(IndexExpression expression)
{
var valueParameter = Expression.Parameter(expression.Type);

2
src/Avalonia.Base/Data/Core/Parsers/ExpressionNodeFactory.cs

@ -15,9 +15,7 @@ namespace Avalonia.Data.Core.Parsers
internal static class ExpressionNodeFactory
{
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
public static List<ExpressionNode>? CreateFromAst(
List<BindingExpressionGrammar.INode> astNodes,
Func<string?, string, Type?>? typeResolver,

4
src/Avalonia.Base/Data/Core/Plugins/BindingPlugins.cs

@ -32,11 +32,7 @@ namespace Avalonia.Data.Core.Plugins
{
// When building with AOT, don't create ReflectionMethodAccessorPlugin instance.
// This branch can be eliminated in compile time with AOT.
#if NET6_0_OR_GREATER
if (System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported)
#else
if (true)
#endif
{
s_propertyAccessors.Insert(1, new ReflectionMethodAccessorPlugin());
}

4
src/Avalonia.Base/Data/Core/Plugins/ReflectionMethodAccessorPlugin.cs

@ -7,9 +7,7 @@ using System.Reflection;
namespace Avalonia.Data.Core.Plugins
{
[RequiresUnreferencedCode(TrimmingMessages.PropertyAccessorsRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
internal class ReflectionMethodAccessorPlugin : IPropertyAccessorPlugin
{
private readonly Dictionary<(Type, string), MethodInfo?> _methodLookup =
@ -84,9 +82,7 @@ namespace Avalonia.Data.Core.Plugins
return found;
}
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ExpressionNodeRequiresDynamicCodeMessage)]
#endif
private sealed class Accessor : PropertyAccessorBase
{
public Accessor(WeakReference<object?> reference, MethodInfo method)

14
src/Avalonia.Base/Input/DataFormat.cs

@ -213,19 +213,7 @@ public abstract class DataFormat : IEquatable<DataFormat>
return true;
static bool IsValidChar(char c)
=> IsAsciiLetterOrDigit(c) || c == '.' || c == '-';
static bool IsAsciiLetterOrDigit(char c)
{
#if NET8_0_OR_GREATER
return char.IsAsciiLetterOrDigit(c);
#else
return c is
(>= '0' and <= '9') or
(>= 'A' and <= 'Z') or
(>= 'a' and <= 'z');
#endif
}
=> char.IsAsciiLetterOrDigit(c) || c == '.' || c == '-';
}
/// <inheritdoc />

4
src/Avalonia.Base/Input/KeyGesture.cs

@ -167,7 +167,7 @@ namespace Avalonia.Input
if (s_keySynonyms.TryGetValue(keyStr.ToLower(CultureInfo.InvariantCulture), out key))
return true;
if (EnumHelper.TryParse(keyStr, true, out key))
if (Enum.TryParse(keyStr, true, out key))
return true;
return false;
@ -187,7 +187,7 @@ namespace Avalonia.Input
return KeyModifiers.Meta;
}
return EnumHelper.Parse<KeyModifiers>(modifier.ToString(), true);
return Enum.Parse<KeyModifiers>(modifier.ToString(), true);
}
private static Key ResolveNumPadOperationKey(Key key)

5
src/Avalonia.Base/Layout/LayoutHelper.cs

@ -263,12 +263,7 @@ namespace Avalonia.Layout
// point precision error (e.g. 79.333333333333343) then when it's multiplied by
// `dpiScale` and rounded up, it will be rounded up to a value one greater than it
// should be.
#if NET6_0_OR_GREATER
return Math.Round(value, 8, MidpointRounding.ToZero);
#else
// MidpointRounding.ToZero isn't available in netstandard2.0.
return Math.Truncate(value * 1e8) / 1e8;
#endif
}
}
}

4
src/Avalonia.Base/Media/Fonts/FamilyNameCollection.cs

@ -43,11 +43,7 @@ namespace Avalonia.Media.Fonts
}
private static string[] SplitNames(string names)
#if NET6_0_OR_GREATER
=> names.Split(',', StringSplitOptions.TrimEntries);
#else
=> Array.ConvertAll(names.Split(','), p => p.Trim());
#endif
/// <summary>
/// Gets the primary family name.

2
src/Avalonia.Base/Media/GlyphRun.cs

@ -126,12 +126,10 @@ namespace Avalonia.Media
return array.AsSpan();
}
#if NET6_0_OR_GREATER
if (list is List<ushort> concreteList)
{
return CollectionsMarshal.AsSpan(concreteList);
}
#endif
array = new ushort[count];
for (var i = 0; i < count; ++i)

15
src/Avalonia.Base/Media/TextFormatting/FormattingBufferHelper.cs

@ -52,11 +52,7 @@ namespace Avalonia.Media.TextFormatting
// dictionary is in fact larger than that: it has entries and buckets, but let's only count our data here
if (IsBufferTooLarge<KeyValuePair<TKey, TValue>>(approximateCapacity))
{
#if NET6_0_OR_GREATER
dictionary.TrimExcess();
#else
dictionary = new Dictionary<TKey, TValue>();
#endif
}
}
@ -67,18 +63,7 @@ namespace Avalonia.Media.TextFormatting
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static uint RoundUpToPowerOf2(uint value)
{
#if NET6_0_OR_GREATER
return BitOperations.RoundUpToPowerOf2(value);
#else
// Based on https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
--value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return value + 1;
#endif
}
}
}

6
src/Avalonia.Base/Media/Typeface.cs

@ -174,17 +174,17 @@ namespace Avalonia.Media
// Try match with font style, weight or stretch and update accordingly.
var match = false;
if (EnumHelper.TryParse<FontStyle>(token, true, out var newStyle))
if (Enum.TryParse<FontStyle>(token, true, out var newStyle))
{
style = newStyle;
match = true;
}
else if (EnumHelper.TryParse<FontWeight>(token, true, out var newWeight))
else if (Enum.TryParse<FontWeight>(token, true, out var newWeight))
{
weight = newWeight;
match = true;
}
else if (EnumHelper.TryParse<FontStretch>(token, true, out var newStretch))
else if (Enum.TryParse<FontStretch>(token, true, out var newStretch))
{
stretch = newStretch;
match = true;

13
src/Avalonia.Base/Platform/Internal/UnmanagedBlob.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Compatibility;
namespace Avalonia.Platform.Internal;
@ -117,7 +116,7 @@ internal class UnmanagedBlob : IDisposable
// Could be replaced with https://github.com/dotnet/runtime/issues/40892 when it will be available.
private IntPtr Alloc(int size)
{
if (!OperatingSystemEx.IsLinux())
if (!OperatingSystem.IsLinux())
{
return Marshal.AllocHGlobal(size);
}
@ -126,12 +125,8 @@ internal class UnmanagedBlob : IDisposable
var rv = mmap(IntPtr.Zero, new IntPtr(size), 3, 0x22, -1, IntPtr.Zero);
if (rv.ToInt64() == -1 || (ulong)rv.ToInt64() == 0xffffffff)
{
#if NET6_0_OR_GREATER
var errno = Marshal.GetLastSystemError();
throw new Exception("Unable to allocate memory: " + errno);
#else
throw new Exception("Unable to allocate memory");
#endif
}
return rv;
}
@ -139,7 +134,7 @@ internal class UnmanagedBlob : IDisposable
private void Free(IntPtr ptr, int len)
{
if (!OperatingSystemEx.IsLinux())
if (!OperatingSystem.IsLinux())
{
Marshal.FreeHGlobal(ptr);
}
@ -147,12 +142,8 @@ internal class UnmanagedBlob : IDisposable
{
if (munmap(ptr, new IntPtr(len)) == -1)
{
#if NET6_0_OR_GREATER
var errno = Marshal.GetLastSystemError();
throw new Exception("Unable to free memory: " + errno);
#else
throw new Exception("Unable to free memory");
#endif
}
}
}

12
src/Avalonia.Base/Platform/StandardRuntimePlatform.cs

@ -1,4 +1,4 @@
using Avalonia.Compatibility;
using System;
using Avalonia.Metadata;
namespace Avalonia.Platform
@ -8,11 +8,11 @@ namespace Avalonia.Platform
{
public virtual RuntimePlatformInfo GetRuntimeInfo() => new()
{
IsDesktop = OperatingSystemEx.IsWindows()
|| OperatingSystemEx.IsMacOS() || OperatingSystemEx.IsMacCatalyst()
|| OperatingSystemEx.IsLinux() || OperatingSystemEx.IsFreeBSD(),
IsMobile = OperatingSystemEx.IsAndroid() || (OperatingSystemEx.IsIOS() && !OperatingSystemEx.IsMacCatalyst()),
IsTV = OperatingSystemEx.IsTvOS()
IsDesktop = OperatingSystem.IsWindows()
|| OperatingSystem.IsMacOS() || OperatingSystem.IsMacCatalyst()
|| OperatingSystem.IsLinux() || OperatingSystem.IsFreeBSD(),
IsMobile = OperatingSystem.IsAndroid() || (OperatingSystem.IsIOS() && !OperatingSystem.IsMacCatalyst()),
IsTV = OperatingSystem.IsTvOS()
};
}
}

3
src/Avalonia.Base/Platform/StandardRuntimePlatformServices.cs

@ -1,7 +1,4 @@
using System.Reflection;
using Avalonia.Compatibility;
using Avalonia.Platform.Internal;
using Avalonia.Platform.Interop;
namespace Avalonia.Platform;

11
src/Avalonia.Base/Platform/Storage/FileIO/BclLauncher.cs

@ -2,7 +2,6 @@
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Avalonia.Compatibility;
namespace Avalonia.Platform.Storage.FileIO;
@ -39,7 +38,7 @@ internal class BclLauncher : ILauncher
private static bool Exec(string urlOrFile)
{
if (OperatingSystemEx.IsLinux())
if (OperatingSystem.IsLinux())
{
// If no associated application/json MimeType is found xdg-open opens return error
// but it tries to open it anyway using the console editor (nano, vim, other..)
@ -47,17 +46,17 @@ internal class BclLauncher : ILauncher
ShellExecRaw($"xdg-open \\\"{args}\\\"", waitForExit: false);
return true;
}
else if (OperatingSystemEx.IsWindows() || OperatingSystemEx.IsMacOS())
else if (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS())
{
var info = new ProcessStartInfo
{
FileName = OperatingSystemEx.IsWindows() ? urlOrFile : "open",
FileName = OperatingSystem.IsWindows() ? urlOrFile : "open",
CreateNoWindow = true,
UseShellExecute = OperatingSystemEx.IsWindows()
UseShellExecute = OperatingSystem.IsWindows()
};
// Using the argument list avoids having to escape spaces and other special
// characters that are part of valid macos file and folder paths.
if (OperatingSystemEx.IsMacOS())
if (OperatingSystem.IsMacOS())
info.ArgumentList.Add(urlOrFile);
using var process = Process.Start(info);
return true;

7
src/Avalonia.Base/Platform/Storage/FileIO/BclStorageProvider.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Compatibility;
using Avalonia.Logging;
namespace Avalonia.Platform.Storage.FileIO;
@ -107,13 +106,13 @@ internal abstract class BclStorageProvider : IStorageProvider
// Normally we want to avoid platform specific code in the Avalonia.Base assembly.
protected static string? GetDownloadsWellKnownFolder()
{
if (OperatingSystemEx.IsWindows())
if (OperatingSystem.IsWindows())
{
return Environment.OSVersion.Version.Major < 6 ? null :
TryGetWindowsKnownFolder(s_folderDownloads);
}
if (OperatingSystemEx.IsLinux())
if (OperatingSystem.IsLinux())
{
var envDir = Environment.GetEnvironmentVariable("XDG_DOWNLOAD_DIR");
if (envDir != null && Directory.Exists(envDir))
@ -122,7 +121,7 @@ internal abstract class BclStorageProvider : IStorageProvider
}
}
if (OperatingSystemEx.IsLinux() || OperatingSystemEx.IsMacOS())
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
return "~/Downloads";
}

8
src/Avalonia.Base/Platform/Storage/FileIO/SecurityScopedStream.cs

@ -40,12 +40,10 @@ internal sealed class SecurityScopedStream(FileStream _stream, IDisposable _secu
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
_stream.ReadAsync(buffer, offset, count, cancellationToken);
#if NET6_0_OR_GREATER
public override int Read(Span<byte> buffer) => _stream.Read(buffer);
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) =>
_stream.ReadAsync(buffer, cancellationToken);
#endif
public override void Write(byte[] buffer, int offset, int count) =>
_stream.Write(buffer, offset, count);
@ -53,12 +51,10 @@ internal sealed class SecurityScopedStream(FileStream _stream, IDisposable _secu
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) =>
_stream.WriteAsync(buffer, offset, count, cancellationToken);
#if NET6_0_OR_GREATER
public override void Write(ReadOnlySpan<byte> buffer) => _stream.Write(buffer);
public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) =>
_stream.WriteAsync(buffer, cancellationToken);
#endif
public override void WriteByte(byte value) => _stream.WriteByte(value);
@ -68,9 +64,7 @@ internal sealed class SecurityScopedStream(FileStream _stream, IDisposable _secu
public override void SetLength(long value) =>
_stream.SetLength(value);
#if NET6_0_OR_GREATER
public override void CopyTo(Stream destination, int bufferSize) => _stream.CopyTo(destination, bufferSize);
#endif
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) =>
_stream.CopyToAsync(destination, bufferSize, cancellationToken);
@ -100,7 +94,6 @@ internal sealed class SecurityScopedStream(FileStream _stream, IDisposable _secu
}
}
#if NET6_0_OR_GREATER
public override async ValueTask DisposeAsync()
{
try
@ -112,5 +105,4 @@ internal sealed class SecurityScopedStream(FileStream _stream, IDisposable _secu
_securityScope.Dispose();
}
}
#endif
}

12
src/Avalonia.Base/Platform/Storage/FileIO/StorageBookmarkHelper.cs

@ -58,11 +58,7 @@ internal static class StorageBookmarkHelper
nativeBookmarkBytes.CopyTo(arraySpan.Slice(HeaderLength));
// We must use span overload because ArrayPool might return way too big array.
#if NET6_0_OR_GREATER
return Convert.ToBase64String(arraySpan);
#else
return Convert.ToBase64String(arraySpan.ToArray(), Base64FormattingOptions.None);
#endif
}
finally
{
@ -89,7 +85,7 @@ internal static class StorageBookmarkHelper
}
Span<byte> decodedBookmark;
#if NET6_0_OR_GREATER
// Each base64 character represents 6 bits, but to be safe,
var arrayPool = ArrayPool<byte>.Shared.Rent(HeaderLength + base64bookmark.Length * 6);
if (Convert.TryFromBase64Chars(base64bookmark, arrayPool, out int bytesWritten))
@ -101,9 +97,7 @@ internal static class StorageBookmarkHelper
nativeBookmark = null;
return DecodeResult.InvalidFormat;
}
#else
decodedBookmark = Convert.FromBase64String(base64bookmark).AsSpan();
#endif
try
{
if (decodedBookmark.Length < HeaderLength
@ -126,9 +120,7 @@ internal static class StorageBookmarkHelper
}
finally
{
#if NET6_0_OR_GREATER
ArrayPool<byte>.Shared.Return(arrayPool);
#endif
}
}

4
src/Avalonia.Base/Rendering/Composition/Server/FpsCounter.cs

@ -42,11 +42,7 @@ internal class FpsCounter
_lastFpsUpdate = now;
}
#if NET6_0_OR_GREATER
var fpsLine = string.Create(CultureInfo.InvariantCulture, $"Frame #{_totalFrames:00000000} FPS: {_fps:000} {aux}");
#else
var fpsLine = FormattableString.Invariant($"Frame #{_totalFrames:00000000} FPS: {_fps:000} {aux}");
#endif
var size = _textRenderer.MeasureAsciiText(fpsLine.AsSpan());

5
src/Avalonia.Base/Rendering/Composition/Server/FrameTimeGraph.cs

@ -104,14 +104,9 @@ internal sealed class FrameTimeGraph
var brush = value <= _defaultMaxY ? Brushes.Black : Brushes.Red;
#if NET6_0_OR_GREATER
Span<char> buffer = stackalloc char[24];
buffer.TryWrite(CultureInfo.InvariantCulture, $"{label}: {value,5:F2}ms", out var charsWritten);
_textRenderer.DrawAsciiText(context, buffer.Slice(0, charsWritten), brush);
#else
var text = FormattableString.Invariant($"{label}: {value,5:F2}ms");
_textRenderer.DrawAsciiText(context, text.AsSpan(), brush);
#endif
}
private IStreamGeometryImpl BuildGraphGeometry(double maxY)

5
src/Avalonia.Base/Rendering/Composition/Transport/BatchStream.cs

@ -33,11 +33,8 @@ static unsafe class UnalignedMemoryHelper
{
public static T ReadUnaligned<T>(byte* src) where T : unmanaged
{
#if NET6_0_OR_GREATER
Unsafe.SkipInit<T>(out var rv);
#else
T rv;
#endif
UnalignedMemcpy((byte*)&rv, src, Unsafe.SizeOf<T>());
return rv;
}

3
src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs

@ -74,9 +74,6 @@ namespace Avalonia.Threading
_dispatcher.Send(d, state, Priority);
}
#if !NET6_0_OR_GREATER
[PrePrepareMethod]
#endif
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
{
if (

156
src/Avalonia.Base/Threading/CulturePreservingExecutionContext.cs

@ -1,156 +0,0 @@
#if NET6_0_OR_GREATER
// In .NET Core, the security context and call context are not supported, however,
// the impersonation context and culture would typically flow with the execution context.
// See: https://learn.microsoft.com/en-us/dotnet/api/system.threading.executioncontext
//
// So we can safely use ExecutionContext without worrying about culture flowing issues.
#else
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Threading;
namespace Avalonia.Threading;
/// <summary>
/// An ExecutionContext that preserves culture information across async operations.
/// This is a modernized version that removes legacy compatibility switches and
/// includes nullable reference type annotations.
/// </summary>
internal sealed class CulturePreservingExecutionContext
{
private readonly ExecutionContext _context;
private CultureAndContext? _cultureAndContext;
private CulturePreservingExecutionContext(ExecutionContext context)
{
_context = context;
}
/// <summary>
/// Captures the current ExecutionContext and culture information.
/// </summary>
/// <returns>A new CulturePreservingExecutionContext instance, or null if no context needs to be captured.</returns>
public static CulturePreservingExecutionContext? Capture()
{
// ExecutionContext.SuppressFlow had been called.
// We expect ExecutionContext.Capture() to return null, so match that behavior and return null.
if (ExecutionContext.IsFlowSuppressed())
{
return null;
}
var context = ExecutionContext.Capture();
if (context == null)
return null;
return new CulturePreservingExecutionContext(context);
}
/// <summary>
/// Runs the specified callback in the captured execution context while preserving culture information.
/// This method is used for .NET Framework and earlier .NET versions.
/// </summary>
/// <param name="executionContext">The execution context to run in.</param>
/// <param name="callback">The callback to execute.</param>
/// <param name="state">The state to pass to the callback.</param>
public static void Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, object? state)
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (callback == null)
return;
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
if (executionContext == null)
ThrowNullContext();
// Save culture information - we will need this to restore just before
// the callback is actually invoked from CallbackWrapper.
executionContext._cultureAndContext = CultureAndContext.Initialize(callback, state);
try
{
ExecutionContext.Run(
executionContext._context,
s_callbackWrapperDelegate,
executionContext._cultureAndContext);
}
finally
{
// Restore culture information - it might have been modified during callback execution.
executionContext._cultureAndContext.RestoreCultureInfos();
}
}
[DoesNotReturn]
private static void ThrowNullContext()
{
throw new InvalidOperationException("ExecutionContext cannot be null.");
}
private static readonly ContextCallback s_callbackWrapperDelegate = CallbackWrapper;
/// <summary>
/// Executes the callback and saves culture values immediately afterwards.
/// </summary>
/// <param name="obj">Contains the actual callback and state.</param>
private static void CallbackWrapper(object? obj)
{
var cultureAndContext = (CultureAndContext)obj!;
// Restore culture information saved during Run()
cultureAndContext.RestoreCultureInfos();
try
{
// Execute the actual callback
cultureAndContext.Callback(cultureAndContext.State);
}
finally
{
// Save any culture changes that might have occurred during callback execution
cultureAndContext.CaptureCultureInfos();
}
}
/// <summary>
/// Helper class to manage culture information across execution contexts.
/// </summary>
private sealed class CultureAndContext
{
public ContextCallback Callback { get; }
public object? State { get; }
private CultureInfo? _culture;
private CultureInfo? _uiCulture;
private CultureAndContext(ContextCallback callback, object? state)
{
Callback = callback;
State = state;
CaptureCultureInfos();
}
public static CultureAndContext Initialize(ContextCallback callback, object? state)
{
return new CultureAndContext(callback, state);
}
public void CaptureCultureInfos()
{
_culture = Thread.CurrentThread.CurrentCulture;
_uiCulture = Thread.CurrentThread.CurrentUICulture;
}
public void RestoreCultureInfos()
{
if (_culture != null)
Thread.CurrentThread.CurrentCulture = _culture;
if (_uiCulture != null)
Thread.CurrentThread.CurrentUICulture = _uiCulture;
}
}
}
#endif

8
src/Avalonia.Base/Threading/DispatcherOperation.cs

@ -5,11 +5,7 @@ using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
#if NET6_0_OR_GREATER
using ExecutionContext = System.Threading.ExecutionContext;
#else
using ExecutionContext = Avalonia.Threading.CulturePreservingExecutionContext;
#endif
namespace Avalonia.Threading;
@ -277,12 +273,8 @@ public class DispatcherOperation
{
if (_executionContext is { } executionContext)
{
#if NET6_0_OR_GREATER
ExecutionContext.Restore(executionContext);
InvokeCore();
#else
ExecutionContext.Run(executionContext, static s => ((DispatcherOperation)s!).InvokeCore(), this);
#endif
}
else
{

7
src/Avalonia.Base/Threading/NonPumpingSyncContext.cs

@ -22,11 +22,7 @@ namespace Avalonia.Threading
{
if (_inner is null)
{
#if NET6_0_OR_GREATER
ThreadPool.QueueUserWorkItem(static x => x.d(x.state), (d, state), false);
#else
ThreadPool.QueueUserWorkItem(_ => d(state));
#endif
}
else
{
@ -46,9 +42,6 @@ namespace Avalonia.Threading
}
}
#if !NET6_0_OR_GREATER
[PrePrepareMethod]
#endif
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) =>
_impl.Wait(waitHandles, waitAll, millisecondsTimeout);

4
src/Avalonia.Base/Utilities/ArrayBuilder.cs

@ -136,7 +136,6 @@ namespace Avalonia.Utilities
/// </summary>
public void Clear()
{
#if NET6_0_OR_GREATER
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
ClearArray();
@ -145,9 +144,6 @@ namespace Avalonia.Utilities
{
_size = 0;
}
#else
ClearArray();
#endif
}
private void ClearArray()

10
src/Avalonia.Base/Utilities/AvaloniaPropertyDictionary.cs

@ -244,12 +244,8 @@ namespace Avalonia.Utilities
// hi and lo are never negative: there's no overflow using unsigned math
var i = (int)(((uint)hi + (uint)lo) >> 1);
#if NET6_0_OR_GREATER
// nuint cast to force zero extend instead of sign extend
ref var entry = ref Unsafe.Add(ref entry0, (nuint)i);
#else
ref var entry = ref Unsafe.Add(ref entry0, i);
#endif
var entryId = entry.Id;
if (entryId == propertyId)
@ -288,12 +284,8 @@ namespace Avalonia.Utilities
// hi and lo are never negative: there's no overflow using unsigned math
var i = (int)(((uint)hi + (uint)lo) >> 1);
#if NET6_0_OR_GREATER
// nuint cast to force zero extend instead of sign extend
ref var entry = ref Unsafe.Add(ref entry0, (nuint)i);
#else
ref var entry = ref Unsafe.Add(ref entry0, i);
#endif
var entryId = entry.Id;
if (entryId == propertyId)
@ -360,7 +352,7 @@ namespace Avalonia.Utilities
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ref Entry UnsafeGetEntryRef(int index)
{
#if NET6_0_OR_GREATER && !DEBUG
#if !DEBUG
// This type is performance critical: in release mode, skip any bound check the JIT compiler couldn't elide.
// The index parameter should always be correct when calling this method: no unchecked user input should get here.
return ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_entries!), (uint)index);

34
src/Avalonia.Base/Utilities/EnumHelper.cs

@ -1,34 +0,0 @@
using System;
namespace Avalonia.Utilities
{
internal class EnumHelper
{
#if NET6_0_OR_GREATER
public static T Parse<T>(ReadOnlySpan<char> key, bool ignoreCase) where T : struct
{
return Enum.Parse<T>(key, ignoreCase);
}
public static bool TryParse<T>(ReadOnlySpan<char> key, bool ignoreCase, out T result) where T : struct
{
return Enum.TryParse(key, ignoreCase, out result);
}
#else
public static T Parse<T>(string key, bool ignoreCase) where T : struct
{
return (T)Enum.Parse(typeof(T), key, ignoreCase);
}
public static bool TryParse<T>(string key, bool ignoreCase, out T result) where T : struct
{
return Enum.TryParse(key, ignoreCase, out result);
}
public static bool TryParse<T>(ReadOnlySpan<char> key, bool ignoreCase, out T result) where T : struct
{
return Enum.TryParse(key.ToString(), ignoreCase, out result);
}
#endif
}
}

43
src/Avalonia.Base/Utilities/Polyfills.cs

@ -1,43 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
internal static class Polyfills
{
#if !NET6_0_OR_GREATER
public static bool TryDequeue<T>(this Queue<T> queue, [MaybeNullWhen(false)]out T item)
{
if (queue.Count == 0)
{
item = default;
return false;
}
item = queue.Dequeue();
return true;
}
#endif
}
#if !NET7_0_OR_GREATER
namespace System.Diagnostics.CodeAnalysis
{
[System.AttributeUsage(
System.AttributeTargets.Method | System.AttributeTargets.Parameter | System.AttributeTargets.Property,
AllowMultiple = false, Inherited = false)]
internal sealed class UnscopedRefAttribute : Attribute
{
}
struct S
{
int _field;
// Okay: `field` has the ref-safe-to-escape of `this` which is *calling method* because
// it is a `ref`
[UnscopedRef] ref int Prop1 => ref _field;
}
}
#endif

20
src/Avalonia.Base/Utilities/RefCountingSmallDictionary.cs

@ -10,20 +10,13 @@ internal struct RefCountingSmallDictionary<TKey> : IEnumerable<KeyValuePair<TKey
public bool Add(TKey key)
{
#if NET6_0_OR_GREATER
ref var cnt = ref _counts.GetValueRefOrAddDefault(key, out bool exists);
cnt++;
#else
var exists = _counts.TryGetValue(key, out var cnt);
cnt++;
_counts[key] = cnt;
#endif
return !exists;
}
public bool Remove(TKey key)
{
#if NET6_0_OR_GREATER
ref var cnt = ref _counts.GetValueRefOrNullRef(key);
cnt--;
if (cnt == 0)
@ -31,17 +24,6 @@ internal struct RefCountingSmallDictionary<TKey> : IEnumerable<KeyValuePair<TKey
_counts.Remove(key);
return true;
}
#else
var cnt = _counts[key];
cnt--;
if (cnt == 0)
{
_counts.Remove(key);
return true;
}
_counts[key] = cnt;
#endif
return false;
}
@ -51,4 +33,4 @@ internal struct RefCountingSmallDictionary<TKey> : IEnumerable<KeyValuePair<TKey
IEnumerator<KeyValuePair<TKey, int>> IEnumerable<KeyValuePair<TKey, int>>.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

3
src/Avalonia.Base/Utilities/SmallDictionary.cs

@ -177,7 +177,6 @@ internal struct InlineDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey,
return false;
}
#if NET6_0_OR_GREATER
[UnscopedRef]
public ref TValue GetValueRefOrNullRef(TKey key)
{
@ -263,8 +262,6 @@ internal struct InlineDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey,
return ref arr[1].Value!;
}
#endif
public bool TryGetAndRemoveValue(TKey key, [MaybeNullWhen(false)]out TValue value)
{

4
src/Avalonia.Base/Utilities/StringSplitter.cs

@ -87,11 +87,7 @@ internal static class StringSplitter
for (int i = 0; i < ranges.Count; i++)
{
var r = ranges[i];
#if NET6_0_OR_GREATER
result[i] = new string(span.Slice(r.start, r.length));
#else
result[i] = span.Slice(r.start, r.length).ToString();
#endif
}
return result;

7
src/Avalonia.Controls.ColorPicker/Helpers/ColorHelper.cs

@ -15,12 +15,7 @@ namespace Avalonia.Controls.Primitives
private static readonly Dictionary<KnownColor, string> _cachedKnownColorNames = new Dictionary<KnownColor, string>();
private static readonly object _displayNameCacheMutex = new object();
private static readonly object _knownColorCacheMutex = new object();
private static readonly KnownColor[] _knownColors =
#if NET6_0_OR_GREATER
Enum.GetValues<KnownColor>();
#else
(KnownColor[])Enum.GetValues(typeof(KnownColor));
#endif
private static readonly KnownColor[] _knownColors = Enum.GetValues<KnownColor>();
/// <summary>
/// Gets the relative (perceptual) luminance/brightness of the given color.

4
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -181,11 +181,7 @@ namespace Avalonia.Controls
{
if (run.Length > 0)
{
#if NET6_0_OR_GREATER
builder.Append(run.Text.Span);
#else
builder.Append(run.Text.Span.ToArray());
#endif
}
}

5
src/Avalonia.DesignerSupport/Remote/HtmlTransport/HtmlTransport.cs

@ -10,7 +10,6 @@ using System.Threading;
using System.Threading.Tasks;
using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Viewport;
using Avalonia.Utilities;
using InputProtocol = Avalonia.Remote.Protocol.Input;
namespace Avalonia.DesignerSupport.Remote.HtmlTransport
@ -354,13 +353,13 @@ namespace Avalonia.DesignerSupport.Remote.HtmlTransport
? null
: modifiersText
.Split(',')
.Select(x => EnumHelper.Parse<InputProtocol.InputModifiers>(x, true))
.Select(x => Enum.Parse<InputProtocol.InputModifiers>(x, true))
.ToArray();
private static InputProtocol.MouseButton ParseMouseButton(string buttonText) =>
string.IsNullOrWhiteSpace(buttonText)
? InputProtocol.MouseButton.None
: EnumHelper.Parse<InputProtocol.MouseButton>(buttonText, true);
: Enum.Parse<InputProtocol.MouseButton>(buttonText, true);
private static double ParseDouble(string text) =>
double.Parse(text, NumberStyles.Float, CultureInfo.InvariantCulture);

8
src/Avalonia.Desktop/AppBuilderDesktopExtensions.cs

@ -1,4 +1,4 @@
using Avalonia.Compatibility;
using System;
using Avalonia.Logging;
namespace Avalonia
@ -17,17 +17,17 @@ namespace Avalonia
// Additionally, by having a hard reference to each assembly,
// we verify that the assemblies are in the final .deps.json file
// so .NET Core knows where to load the assemblies from.
if (OperatingSystemEx.IsWindows())
if (OperatingSystem.IsWindows())
{
LoadWin32(builder);
LoadSkia(builder);
}
else if (OperatingSystemEx.IsMacOS())
else if (OperatingSystem.IsMacOS())
{
LoadAvaloniaNative(builder);
LoadSkia(builder);
}
else if (OperatingSystemEx.IsLinux())
else if (OperatingSystem.IsLinux())
{
LoadX11(builder);
LoadSkia(builder);

2
src/Avalonia.Dialogs/ManagedFileDialogExtensions.cs

@ -6,9 +6,7 @@ using Avalonia.Platform.Storage;
namespace Avalonia.Dialogs
{
#if NET6_0_OR_GREATER
[SupportedOSPlatform("windows"), SupportedOSPlatform("macos"), SupportedOSPlatform("linux")]
#endif
public static class ManagedFileDialogExtensions
{
internal class ManagedStorageProviderFactory : IStorageProviderFactory

6
src/Avalonia.Native/AvaloniaNativePlatform.cs

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Platform;
using Avalonia.Input;
@ -47,8 +45,8 @@ namespace Avalonia.Native
{
if (options.AvaloniaNativeLibraryPath != null)
{
var lib = NativeLibraryEx.Load(options.AvaloniaNativeLibraryPath);
if (!NativeLibraryEx.TryGetExport(lib, "CreateAvaloniaNative", out var proc))
var lib = NativeLibrary.Load(options.AvaloniaNativeLibraryPath);
if (!NativeLibrary.TryGetExport(lib, "CreateAvaloniaNative", out var proc))
{
throw new InvalidOperationException(
"Unable to get \"CreateAvaloniaNative\" export from AvaloniaNativeLibrary library");

4
src/Avalonia.Native/IAvnMenu.cs

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Compatibility;
using Avalonia.Reactive;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
@ -51,7 +49,7 @@ namespace Avalonia.Native.Interop.Impl
private void UpdateTitle(string? title)
{
if (OperatingSystemEx.IsMacOS())
if (OperatingSystem.IsMacOS())
{
// macOS does not process access key markers, so remove them.
title = AccessText.RemoveAccessKeyMarker(title);

6
src/Avalonia.Native/IAvnMenuItem.cs

@ -1,11 +1,9 @@
using System;
using System.IO;
using Avalonia.Compatibility;
using Avalonia.Reactive;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Interop;
using Avalonia.Reactive;
namespace Avalonia.Native.Interop
{
@ -26,7 +24,7 @@ namespace Avalonia.Native.Interop.Impl
private void UpdateTitle(string? title)
{
if (OperatingSystemEx.IsMacOS())
if (OperatingSystem.IsMacOS())
{
// macOS does not process access key markers, so remove them.
title = AccessText.RemoveAccessKeyMarker(title);

11
src/Avalonia.OpenGL/Egl/EglInterface.cs

@ -1,8 +1,5 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using Avalonia.SourceGenerator;
namespace Avalonia.OpenGL.Egl
@ -25,9 +22,9 @@ namespace Avalonia.OpenGL.Egl
static Func<string, IntPtr> Load()
{
if(OperatingSystemEx.IsLinux())
if(OperatingSystem.IsLinux())
return Load("libEGL.so.1");
if (OperatingSystemEx.IsAndroid())
if (OperatingSystem.IsAndroid())
return Load("libEGL.so");
throw new PlatformNotSupportedException();
@ -35,8 +32,8 @@ namespace Avalonia.OpenGL.Egl
static Func<string, IntPtr> Load(string library)
{
var lib = NativeLibraryEx.Load(library);
return (s) => NativeLibraryEx.TryGetExport(lib, s, out var address) ? address : default;
var lib = NativeLibrary.Load(library);
return (s) => NativeLibrary.TryGetExport(lib, s, out var address) ? address : default;
}
// ReSharper disable UnassignedGetOnlyAutoProperty

4
src/Avalonia.OpenGL/OpenGlException.cs

@ -37,11 +37,7 @@ namespace Avalonia.OpenGL
{
try
{
#if NET6_0_OR_GREATER
var errorName = Enum.GetName(errorCode);
#else
var errorName = Enum.GetName(typeof(T), errorCode);
#endif
return new OpenGlException(
$"{funcName} failed with error {errorName} (0x{errorCode.ToString("X")})", intErrorCode);
}

2
src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs

@ -130,9 +130,7 @@ internal sealed class ColorPaletteResourcesCollection : ResourceProvider, IDicti
}
bool IDictionary<ThemeVariant, ColorPaletteResources>.TryGetValue(ThemeVariant key,
#if NET6_0_OR_GREATER
[MaybeNullWhen(false)]
#endif
out ColorPaletteResources value)
{
return _inner.TryGetValue(key, out value);

5
src/Avalonia.X11/X11Window.cs

@ -395,12 +395,7 @@ namespace Avalonia.X11
private static int GetProcessId()
{
#if NET6_0_OR_GREATER
var pid = Environment.ProcessId;
#else
using var currentProcess = Process.GetCurrentProcess();
var pid = currentProcess.Id;
#endif
return pid;
}

4
src/Linux/Avalonia.LinuxFramebuffer/Input/EvDev/EvDevDevice.cs

@ -18,11 +18,7 @@ namespace Avalonia.LinuxFramebuffer.Input.EvDev
Fd = fd;
_dev = dev;
Name = Marshal.PtrToStringAnsi(NativeUnsafeMethods.libevdev_get_name(_dev));
#if NET6_0_OR_GREATER
foreach (EvType type in Enum.GetValues<EvType>())
#else
foreach (EvType type in Enum.GetValues(typeof(EvType)))
#endif
{
if (NativeUnsafeMethods.libevdev_has_event_type(dev, type) != 0)
EventTypes.Add(type);

16
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/OnPlatformExtension.cs

@ -1,4 +1,4 @@
using Avalonia.Compatibility;
using System;
using Avalonia.Metadata;
namespace Avalonia.Markup.Xaml.MarkupExtensions;
@ -76,13 +76,13 @@ public abstract class OnPlatformExtensionBase<TReturn, TOn> : IAddChild<TOn>
// IsOSPlatform might work better with trimming in the future, so it should be re-visited after .NET 8/9.
return option switch
{
"WINDOWS" => OperatingSystemEx.IsWindows(),
"OSX" => OperatingSystemEx.IsMacOS(),
"LINUX" => OperatingSystemEx.IsLinux(),
"ANDROID" => OperatingSystemEx.IsAndroid(),
"IOS" => OperatingSystemEx.IsIOS(),
"BROWSER" => OperatingSystemEx.IsBrowser(),
_ => OperatingSystemEx.IsOSPlatform(option)
"WINDOWS" => OperatingSystem.IsWindows(),
"OSX" => OperatingSystem.IsMacOS(),
"LINUX" => OperatingSystem.IsLinux(),
"ANDROID" => OperatingSystem.IsAndroid(),
"IOS" => OperatingSystem.IsIOS(),
"BROWSER" => OperatingSystem.IsBrowser(),
_ => OperatingSystem.IsOSPlatform(option)
};
}
}

2
src/Markup/Avalonia.Markup.Xaml/MarkupExtensions/ReflectionBindingExtension.cs

@ -6,9 +6,7 @@ using Avalonia.Data;
namespace Avalonia.Markup.Xaml.MarkupExtensions
{
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
public sealed class ReflectionBindingExtension : ReflectionBinding
{
/// <summary>

11
src/Markup/Avalonia.Markup.Xaml/XamlIl/Runtime/XamlIlRuntimeHelpers.cs

@ -129,22 +129,11 @@ namespace Avalonia.Markup.Xaml.XamlIl.Runtime
return false;
}
#if NET6_0_OR_GREATER
if (!CollectionsMarshal.AsSpan(resourceNodes).SequenceEqual(lastResourceNodes))
{
cachedResourceNodes = null;
return false;
}
#else
for (var i = 0; i < lastResourceNodes.Length; ++i)
{
if (lastResourceNodes[i] != resourceNodes[i])
{
cachedResourceNodes = null;
return false;
}
}
#endif
cachedResourceNodes = lastResourceNodes;
return true;

4
src/Markup/Avalonia.Markup/Data/Binding.cs

@ -8,9 +8,7 @@ namespace Avalonia.Data;
/// for new code.
/// </summary>
[RequiresUnreferencedCode(TrimmingMessages.ReflectionBindingRequiresUnreferencedCodeMessage)]
#if NET8_0_OR_GREATER
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
#endif
[RequiresDynamicCode(TrimmingMessages.ReflectionBindingRequiresDynamicCodeMessage)]
public class Binding : ReflectionBinding
{
public Binding() { }

2
src/Shared/ModuleInitializer.cs

@ -2,7 +2,7 @@ namespace System.Runtime.CompilerServices
{
#if NETSTANDARD2_0
[AttributeUsage(AttributeTargets.Method)]
internal sealed class ModuleInitializerAttribute : Attribute
internal sealed class ModuleInitializerhAttribute : Attribute
{
}

3
src/Skia/Avalonia.Skia/Helpers/PixelFormatHelper.cs

@ -1,5 +1,4 @@
using Avalonia.Compatibility;
using Avalonia.Platform;
using Avalonia.Platform;
using SkiaSharp;
namespace Avalonia.Skia.Helpers

6
src/Skia/Avalonia.Skia/SKRoundRectCache.cs

@ -91,13 +91,7 @@ namespace Avalonia.Skia
base.Clear();
// Clear out the cache of SKPoint arrays.
#if NET6_0_OR_GREATER
_radiiCache.Clear();
#else
while (_radiiCache.TryTake(out var item))
{
}
#endif
}
}
}

14
src/Windows/Avalonia.Win32.Automation/AutomationNode.cs

@ -18,15 +18,8 @@ using UIA = Avalonia.Win32.Automation.Interop;
namespace Avalonia.Win32.Automation
{
#if NET8_0_OR_GREATER
[GeneratedComClass]
internal partial class AutomationNode :
#else
#if NET6_0_OR_GREATER
[RequiresUnreferencedCode("Requires .NET COM interop")]
#endif
internal partial class AutomationNode : MarshalByRefObject,
#endif
IRawElementProviderSimple,
IRawElementProviderSimple2,
IRawElementProviderFragment,
@ -202,9 +195,7 @@ namespace Avalonia.Win32.Automation
public void SetFocus() => InvokeSync(() => Peer.SetFocus());
#if NET6_0_OR_GREATER
[return: NotNullIfNotNull(nameof(peer))]
#endif
public static AutomationNode? GetOrCreate(AutomationPeer? peer)
{
return peer is null ? null : s_nodes.GetValue(peer, Create);
@ -434,12 +425,7 @@ namespace Avalonia.Win32.Automation
private static int GetProcessId()
{
#if NET6_0_OR_GREATER
return Environment.ProcessId;
#else
using var proccess = Process.GetCurrentProcess();
return proccess.Id;
#endif
}
}
}

5
src/Windows/Avalonia.Win32.Automation/Interop/IDockProvider.cs

@ -14,12 +14,7 @@ internal enum DockPosition
None
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("159bc72c-4ad3-485e-9637-d7052edf0146")]
internal partial interface IDockProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IExpandCollapseProvider.cs

@ -4,12 +4,7 @@ using Avalonia.Automation;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("d847d3a5-cab0-4a98-8c32-ecb45c59ad24")]
internal partial interface IExpandCollapseProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IGridItemProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("d02541f1-fb81-4d64-ae32-f520f8a6dbd1")]
internal partial interface IGridItemProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IGridProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("b17d6187-0907-464b-a168-0ef17a1572b1")]
internal partial interface IGridProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IInvokeProvider.cs

@ -7,12 +7,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("54fcb24b-e18e-47a2-b4d3-eccbe77599a2")]
internal partial interface IInvokeProvider
{

8
src/Windows/Avalonia.Win32.Automation/Interop/IMultipleViewProvider.cs

@ -5,12 +5,8 @@ using Avalonia.Win32.Automation.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("6278cab1-b556-4a1a-b4e0-418acc523201")]
internal partial interface IMultipleViewProvider
{
@ -18,8 +14,6 @@ internal partial interface IMultipleViewProvider
string GetViewName(int viewId);
void SetCurrentView(int viewId);
int GetCurrentView();
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<int>))]
#endif
int[] GetSupportedViews();
}

5
src/Windows/Avalonia.Win32.Automation/Interop/IRangeValueProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("36dc7aef-33e6-4691-afe1-2be7274b3d33")]
internal partial interface IRangeValueProvider
{

9
src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderAdviseEvents.cs

@ -5,24 +5,15 @@ using Avalonia.Win32.Automation.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("a407b27b-0f6d-4427-9292-473c7bf93258")]
internal partial interface IRawElementProviderAdviseEvents
{
void AdviseEventAdded(int eventId,
#if NET8_0_OR_GREATER
[MarshalUsing(typeof(SafeArrayMarshaller<int>))]
#endif
int[] properties);
void AdviseEventRemoved(int eventId,
#if NET8_0_OR_GREATER
[MarshalUsing(typeof(SafeArrayMarshaller<int>))]
#endif
int[] properties);
}

9
src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderFragment.cs

@ -15,24 +15,15 @@ internal enum NavigateDirection
LastChild,
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("f7063da8-8359-439c-9297-bbc5299a7d87")]
internal partial interface IRawElementProviderFragment
{
IRawElementProviderFragment? Navigate(NavigateDirection direction);
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<int>))]
#endif
int[]? GetRuntimeId();
Rect GetBoundingRectangle();
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[]? GetEmbeddedFragmentRoots();
void SetFocus();
IRawElementProviderFragmentRoot? GetFragmentRoot();

5
src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderFragmentRoot.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("620ce2a5-ab8f-40a9-86cb-de3c75599b58")]
internal partial interface IRawElementProviderFragmentRoot
{

7
src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderSimple.cs

@ -307,21 +307,14 @@ internal enum UiaLiveSetting
Assertive,
};
#if NET8_0_OR_GREATER
[GeneratedComInterface]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("d6dd68d1-86fd-4332-8666-9abedea2d24c")]
internal partial interface IRawElementProviderSimple
{
ProviderOptions GetProviderOptions();
[return: MarshalAs(UnmanagedType.Interface)]
object? GetPatternProvider(int patternId);
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(ComVariantMarshaller))]
#endif
object? GetPropertyValue(int propertyId);
IRawElementProviderSimple? GetHostRawElementProvider();
}

15
src/Windows/Avalonia.Win32.Automation/Interop/IRawElementProviderSimple2.cs

@ -3,24 +3,9 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("a0a839a9-8da1-4a82-806a-8e0d44e79f56")]
internal partial interface IRawElementProviderSimple2 : IRawElementProviderSimple
{
#if !NET8_0_OR_GREATER
// Hack for the legacy COM interop
// See https://learn.microsoft.com/en-us/dotnet/standard/native-interop/comwrappers-source-generation#derived-interfaces
new ProviderOptions GetProviderOptions();
[return: MarshalAs(UnmanagedType.Interface)]
new object? GetPatternProvider(int patternId);
[return: MarshalAs(UnmanagedType.Struct)]
new object? GetPropertyValue(int propertyId);
new IRawElementProviderSimple? GetHostRawElementProvider();
#endif
void ShowContextMenu();
}

5
src/Windows/Avalonia.Win32.Automation/Interop/IScrollItemProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("2360c714-4bf1-4b26-ba65-9b21316127eb")]
internal partial interface IScrollItemProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IScrollProvider.cs

@ -4,12 +4,7 @@ using Avalonia.Automation.Provider;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("b38b8077-1fc3-42a5-8cae-d40c2215055a")]
internal partial interface IScrollProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/ISelectionItemProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("2acad808-b2d4-452d-a407-91ff1ad167b2")]
internal partial interface ISelectionItemProvider
{

7
src/Windows/Avalonia.Win32.Automation/Interop/ISelectionProvider.cs

@ -5,18 +5,11 @@ using Avalonia.Win32.Automation.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("fb8b03af-3bdf-48d4-bd36-1a65793be168")]
internal partial interface ISelectionProvider
{
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetSelection();
[return: MarshalAs(UnmanagedType.Bool)]

6
src/Windows/Avalonia.Win32.Automation/Interop/ISynchronizedInputProvider.cs

@ -13,12 +13,8 @@ internal enum SynchronizedInputType
MouseRightButtonUp = 0x10,
MouseRightButtonDown = 0x20
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("29db1a06-02ce-4cf7-9b42-565d4fab20ee")]
internal partial interface ISynchronizedInputProvider
{

9
src/Windows/Avalonia.Win32.Automation/Interop/ITableItemProvider.cs

@ -5,21 +5,12 @@ using Avalonia.Win32.Automation.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("b9734fa6-771f-4d78-9c90-2517999349cd")]
internal partial interface ITableItemProvider
{
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetRowHeaderItems();
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetColumnHeaderItems();
}

10
src/Windows/Avalonia.Win32.Automation/Interop/ITableProvider.cs

@ -12,22 +12,14 @@ internal enum RowOrColumnMajor
ColumnMajor,
Indeterminate,
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("9c860395-97b3-490a-b52a-858cc22af166")]
internal partial interface ITableProvider
{
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetRowHeaders();
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetColumnHeaders();
RowOrColumnMajor GetRowOrColumnMajor();
}

9
src/Windows/Avalonia.Win32.Automation/Interop/ITextProvider.cs

@ -15,22 +15,13 @@ internal enum SupportedTextSelection
Multiple,
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("3589c92c-63f3-4367-99bb-ada653b77cf2")]
internal partial interface ITextProvider
{
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<ITextRangeProvider>))]
#endif
ITextRangeProvider[] GetSelection();
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<ITextRangeProvider>))]
#endif
ITextRangeProvider[] GetVisibleRanges();
ITextRangeProvider RangeFromChild(IRawElementProviderSimple childElement);

13
src/Windows/Avalonia.Win32.Automation/Interop/ITextRangeProvider.cs

@ -22,12 +22,7 @@ internal enum TextUnit
Document = 6,
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("5347ad7b-c355-46f8-aff5-909033582f63")]
internal partial interface ITextRangeProvider
{
@ -42,22 +37,16 @@ internal partial interface ITextRangeProvider
void ExpandToEnclosingUnit(TextUnit unit);
ITextRangeProvider FindAttribute(int attribute,
#if NET8_0_OR_GREATER
[MarshalUsing(typeof(ComVariantMarshaller))]
#endif
object value, [MarshalAs(UnmanagedType.Bool)] bool backward);
ITextRangeProvider FindText(
[MarshalAs(UnmanagedType.BStr)] string text,
[MarshalAs(UnmanagedType.Bool)] bool backward,
[MarshalAs(UnmanagedType.Bool)] bool ignoreCase);
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(ComVariantMarshaller))]
#endif
object GetAttributeValue(int attribute);
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<double>))]
#endif
double[] GetBoundingRectangles();
IRawElementProviderSimple GetEnclosingElement();
[return: MarshalAs(UnmanagedType.BStr)]
@ -72,8 +61,6 @@ internal partial interface ITextRangeProvider
void AddToSelection();
void RemoveFromSelection();
void ScrollIntoView([MarshalAs(UnmanagedType.Bool)] bool alignToTop);
#if NET8_0_OR_GREATER
[return: MarshalUsing(typeof(SafeArrayMarshaller<IRawElementProviderSimple>))]
#endif
IRawElementProviderSimple[] GetChildren();
}

5
src/Windows/Avalonia.Win32.Automation/Interop/IToggleProvider.cs

@ -4,12 +4,7 @@ using Avalonia.Automation.Provider;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("56d00bd0-c4f4-433c-a836-1a52a57e0892")]
internal partial interface IToggleProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/ITransformProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("6829ddc4-4f91-4ffa-b86f-bd3e2987cb4c")]
internal partial interface ITransformProvider
{

5
src/Windows/Avalonia.Win32.Automation/Interop/IValueProvider.cs

@ -3,12 +3,7 @@ using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Interop;
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("c7935180-6fb3-4201-b174-7df73adbf64a")]
internal partial interface IValueProvider
{

6
src/Windows/Avalonia.Win32.Automation/Interop/IWindowProvider.cs

@ -20,12 +20,8 @@ internal enum WindowInteractionState
BlockedByModalWindow,
NotResponding
}
#if NET8_0_OR_GREATER
[GeneratedComInterface(Options = ComInterfaceOptions.ManagedObjectWrapper)]
#else
[ComImport()]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
#endif
[Guid("987df77b-db06-4d77-8f8a-86a9c3bb90b9")]
internal partial interface IWindowProvider
{

27
src/Windows/Avalonia.Win32.Automation/Interop/UiaCoreProviderApi.cs

@ -66,7 +66,6 @@ namespace Avalonia.Win32.Automation.Interop
{
public const int UIA_E_ELEMENTNOTENABLED = unchecked((int)0x80040200);
#if NET7_0_OR_GREATER
[LibraryImport("UIAutomationCore.dll", StringMarshalling = StringMarshalling.Utf8)]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool UiaClientsAreListening();
@ -88,31 +87,5 @@ namespace Avalonia.Win32.Automation.Interop
[LibraryImport("UIAutomationCore.dll", StringMarshalling = StringMarshalling.Utf8)]
public static partial int UiaDisconnectProvider(IRawElementProviderSimple? provider);
#else
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern bool UiaClientsAreListening();
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr UiaReturnRawElementProvider(IntPtr hwnd, IntPtr wParam, IntPtr lParam,
IRawElementProviderSimple? el);
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern int UiaHostProviderFromHwnd(IntPtr hwnd,
[MarshalAs(UnmanagedType.Interface)] out IRawElementProviderSimple provider);
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern int UiaRaiseAutomationEvent(IRawElementProviderSimple? provider, int id);
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern int UiaRaiseAutomationPropertyChangedEvent(IRawElementProviderSimple? provider, int id,
object? oldValue, object? newValue);
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern int UiaRaiseStructureChangedEvent(IRawElementProviderSimple? provider,
StructureChangeType structureChangeType, int[]? runtimeId, int runtimeIdLen);
[DllImport("UIAutomationCore.dll", CharSet = CharSet.Unicode)]
public static extern int UiaDisconnectProvider(IRawElementProviderSimple? provider);
#endif
}
}

25
src/Windows/Avalonia.Win32.Automation/Interop/UiaCoreTypesApi.cs

@ -24,37 +24,12 @@ namespace Avalonia.Win32.Automation.Interop
internal const int UIA_E_NOCLICKABLEPOINT = unchecked((int)0x80040202);
internal const int UIA_E_PROXYASSEMBLYNOTLOADED = unchecked((int)0x80040203);
internal static bool IsNetComInteropAvailable
{
get
{
#if NET8_0_OR_GREATER
return true;
#else
#if NET6_0_OR_GREATER
if (!System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported)
{
return false;
}
#endif
var comConfig =
AppContext.GetData("System.Runtime.InteropServices.BuiltInComInterop.IsSupported") as string;
return comConfig == null || bool.Parse(comConfig);
#endif
}
}
internal static int UiaLookupId(AutomationIdType type, ref Guid guid)
{
return RawUiaLookupId(type, ref guid);
}
#if NET7_0_OR_GREATER
[LibraryImport("UIAutomationCore.dll", EntryPoint = "UiaLookupId", StringMarshalling = StringMarshalling.Utf8)]
private static partial int RawUiaLookupId(AutomationIdType type, ref Guid guid);
#else
[DllImport("UIAutomationCore.dll", EntryPoint = "UiaLookupId", CharSet = CharSet.Unicode)]
private static extern int RawUiaLookupId(AutomationIdType type, ref Guid guid);
#endif
}
}

4
src/Windows/Avalonia.Win32.Automation/InteropAutomationNode.cs

@ -10,11 +10,7 @@ namespace Avalonia.Win32.Automation;
/// <summary>
/// An automation node which serves as the root of an embedded native control automation tree.
/// </summary>
#if NET8_0_OR_GREATER
[GeneratedComClass]
#elif NET6_0_OR_GREATER
[RequiresUnreferencedCode("Requires .NET COM interop")]
#endif
internal partial class InteropAutomationNode : AutomationNode, IRawElementProviderFragmentRoot
{
private readonly IntPtr _handle;

2
src/Windows/Avalonia.Win32.Automation/Marshalling/ComVariant.cs

@ -8,7 +8,6 @@ using System.Runtime.InteropServices;
namespace Avalonia.Win32.Automation.Marshalling;
#if NET7_0_OR_GREATER
// Oversimplified ComVariant implementation based on https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/ComVariant.cs
// Available
[StructLayout(LayoutKind.Explicit)]
@ -306,4 +305,3 @@ internal struct ComVariant : IDisposable
private set => _typeUnion._vt = (ushort)value;
}
}
#endif

4
src/Windows/Avalonia.Win32.Automation/Marshalling/ComVariantMarshaller.cs

@ -1,5 +1,4 @@
#if NET7_0_OR_GREATER
global using ComVariantMarshaller = Avalonia.Win32.Automation.Marshalling.ComVariantMarshaller;
global using ComVariantMarshaller = Avalonia.Win32.Automation.Marshalling.ComVariantMarshaller;
using System.Runtime.InteropServices.Marshalling;
namespace Avalonia.Win32.Automation.Marshalling;
@ -13,4 +12,3 @@ internal static class ComVariantMarshaller
public static void Free(ComVariant unmanaged) => unmanaged.Dispose();
}
#endif

4
src/Windows/Avalonia.Win32.Automation/Marshalling/SafeArrayMarshaller.cs

@ -1,5 +1,4 @@
#if NET7_0_OR_GREATER
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices.Marshalling;
@ -18,4 +17,3 @@ internal static class SafeArrayMarshaller<T> where T : notnull
public static void Free(SafeArrayRef unmanaged) => unmanaged.Destroy();
}
#endif

3
src/Windows/Avalonia.Win32.Automation/Marshalling/SafeArrayRef.cs

@ -8,13 +8,11 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Avalonia.Controls.Documents;
// ReSharper disable InconsistentNaming
namespace Avalonia.Win32.Automation.Marshalling;
#pragma warning disable CS0649 // Field is never assigned to, and will always have its default value
#if NET7_0_OR_GREATER
internal unsafe partial struct SafeArrayRef
{
private SAFEARRAY* _ptr;
@ -340,4 +338,3 @@ internal unsafe partial struct SafeArrayRef
}
}
}
#endif

8
src/Windows/Avalonia.Win32.Automation/RootAutomationNode.cs

@ -1,5 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using Avalonia.Automation.Peers;
@ -9,15 +8,8 @@ using Avalonia.Win32.Automation.Interop;
namespace Avalonia.Win32.Automation
{
#if NET8_0_OR_GREATER
[GeneratedComClass]
internal partial class RootAutomationNode : AutomationNode, IRawElementProviderFragmentRoot
#else
#if NET6_0_OR_GREATER
[RequiresUnreferencedCode("Requires .NET COM interop")]
#endif
internal partial class RootAutomationNode : AutomationNode, IRawElementProviderFragmentRoot
#endif
{
public RootAutomationNode(AutomationPeer peer)
: base(peer)

4
src/Windows/Avalonia.Win32/OleDataObjectHelper.cs

@ -674,11 +674,7 @@ internal static class OleDataObjectHelper
{
var data = StringBuilderCache.GetStringAndRelease(buffer);
var destSpan = new Span<byte>((void*)ptr, requiredSize);
#if NET8_0_OR_GREATER
MemoryMarshal.Write(destSpan, in dropFiles);
#else
MemoryMarshal.Write(destSpan, ref dropFiles);
#endif
fixed (char* sourcePtr = data)
{

17
src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs

@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Avalonia.Automation.Peers;
using Avalonia.Controls;
@ -155,10 +153,7 @@ namespace Avalonia.Win32
// The first and foremost thing to do - notify the TopLevel
Closed?.Invoke();
if (UiaCoreTypesApi.IsNetComInteropAvailable)
{
UiaCoreProviderApi.UiaReturnRawElementProvider(_hwnd, IntPtr.Zero, IntPtr.Zero, null);
}
UiaCoreProviderApi.UiaReturnRawElementProvider(_hwnd, IntPtr.Zero, IntPtr.Zero, null);
// We need to release IMM context and state to avoid leaks.
if (Imm32InputMethod.Current.Hwnd == _hwnd)
@ -224,7 +219,7 @@ namespace Avalonia.Win32
}
var requestIcon = (Icons)wParam;
var requestDpi = (uint) lParam;
var requestDpi = (uint)lParam;
if (requestDpi == 0)
{
@ -937,7 +932,7 @@ namespace Avalonia.Win32
return IntPtr.Zero;
}
case WindowsMessage.WM_GETOBJECT:
if ((long)lParam == uiaRootObjectId && UiaCoreTypesApi.IsNetComInteropAvailable && _owner?.FocusRoot is Control control)
if ((long)lParam == uiaRootObjectId && _owner?.FocusRoot is Control control)
{
var peer = ControlAutomationPeer.CreatePeerForElement(control);
var node = AutomationNode.GetOrCreate(peer);
@ -946,7 +941,7 @@ namespace Avalonia.Win32
break;
case WindowsMessage.WM_WINDOWPOSCHANGED:
var winPos = Marshal.PtrToStructure<WINDOWPOS>(lParam);
if((winPos.flags & (uint)SetWindowPosFlags.SWP_SHOWWINDOW) != 0)
if ((winPos.flags & (uint)SetWindowPosFlags.SWP_SHOWWINDOW) != 0)
{
OnShowHideMessage(true);
}
@ -973,7 +968,7 @@ namespace Avalonia.Win32
if (message == WindowsMessage.WM_KEYDOWN)
{
if(e is RawKeyEventArgs args && args.Key == Key.ImeProcessed)
if (e is RawKeyEventArgs args && args.Key == Key.ImeProcessed)
{
_ignoreWmChar = true;
}
@ -1118,7 +1113,7 @@ namespace Avalonia.Win32
var x = mp.x > 32767 ? mp.x - 65536 : mp.x;
var y = mp.y > 32767 ? mp.y - 65536 : mp.y;
if(mp.time <= prevMovePoint.time || mp.time >= movePoint.time)
if (mp.time <= prevMovePoint.time || mp.time >= movePoint.time)
continue;
s_sortedPoints.Add(new InternalPoint

1
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -14,7 +14,6 @@
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerExtensions\**\*.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\AvaloniaXamlIlRuntimeCompiler.cs" />
<Compile Include="..\..\..\src\Markup\Avalonia.Markup.Xaml.Loader\CompilerDynamicDependencies.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\NullableAttributes.cs" Link="Compatibility\NullableAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Compatibility\TrimmingAttributes.cs" Link="Compatibility\TrimmingAttributes.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Data\Core\Parsers\ArgumentListParser.cs" Link="Parsers\ArgumentListParser.cs" />
<Compile Include="..\..\..\src\Avalonia.Base\Data\Core\Parsers\BindingExpressionGrammar.cs" Link="Parsers\BindingExpressionGrammar.cs" />

4
src/tools/Avalonia.Designer.HostApp/TinyJson.cs

@ -344,11 +344,7 @@ namespace TinyJson
static object ParseObject(Type type, string json)
{
#if NET6_0_OR_GREATER
object instance = RuntimeHelpers.GetUninitializedObject(type);
#else
object instance = FormatterServices.GetUninitializedObject(type);
#endif
//The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON
List<string> elems = Split(json);

Loading…
Cancel
Save