committed by
GitHub
35 changed files with 878 additions and 293 deletions
@ -1,26 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Platform |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] |
|||
public class ExportWindowingSubsystemAttribute : Attribute |
|||
{ |
|||
public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType, |
|||
string initializationMethod, Type? environmentChecker = null) |
|||
{ |
|||
Name = name; |
|||
InitializationType = initializationType; |
|||
InitializationMethod = initializationMethod; |
|||
EnvironmentChecker = environmentChecker; |
|||
RequiredOS = requiredRuntimePlatform; |
|||
Priority = priority; |
|||
} |
|||
|
|||
public string InitializationMethod { get; private set; } |
|||
public Type? EnvironmentChecker { get; } |
|||
public Type InitializationType { get; private set; } |
|||
public string Name { get; private set; } |
|||
public int Priority { get; private set; } |
|||
public OperatingSystemType RequiredOS { get; private set; } |
|||
} |
|||
} |
|||
@ -1,3 +0,0 @@ |
|||
Compat issues with assembly Avalonia.DesktopRuntime: |
|||
TypesMustExist : Type 'Avalonia.Shared.PlatformSupport.AssetLoader' does not exist in the implementation but it does exist in the contract. |
|||
Total Issues: 1 |
|||
@ -1,103 +0,0 @@ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using Avalonia.Controls; |
|||
using Avalonia.Platform; |
|||
using Avalonia.PlatformSupport; |
|||
|
|||
namespace Avalonia |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes platform-specific services for an <see cref="Application"/>.
|
|||
/// </summary>
|
|||
public sealed class AppBuilder : AppBuilderBase<AppBuilder> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="AppBuilder"/> class.
|
|||
/// </summary>
|
|||
public AppBuilder() |
|||
: base(new StandardRuntimePlatform(), |
|||
builder => StandardRuntimePlatformServices.Register(builder.ApplicationType.Assembly)) |
|||
{ |
|||
} |
|||
|
|||
bool CheckEnvironment(Type checkerType) |
|||
{ |
|||
if (checkerType == null) |
|||
return true; |
|||
try |
|||
{ |
|||
return ((IModuleEnvironmentChecker) Activator.CreateInstance(checkerType)).IsCompatible; |
|||
} |
|||
catch |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Instructs the <see cref="AppBuilder"/> to use the best settings for the platform.
|
|||
/// </summary>
|
|||
/// <returns>An <see cref="AppBuilder"/> instance.</returns>
|
|||
public AppBuilder UseSubsystemsFromStartupDirectory() |
|||
{ |
|||
var os = RuntimePlatform.GetRuntimeInfo().OperatingSystem; |
|||
|
|||
LoadAssembliesInDirectory(); |
|||
|
|||
var windowingSubsystemAttribute = (from assembly in AppDomain.CurrentDomain.GetAssemblies() |
|||
from attribute in assembly.GetCustomAttributes<ExportWindowingSubsystemAttribute>() |
|||
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker) |
|||
orderby attribute.Priority ascending |
|||
select attribute).FirstOrDefault(); |
|||
if (windowingSubsystemAttribute == null) |
|||
{ |
|||
throw new InvalidOperationException("No windowing subsystem found. Are you missing assembly references?"); |
|||
} |
|||
|
|||
var renderingSubsystemAttribute = (from assembly in AppDomain.CurrentDomain.GetAssemblies() |
|||
from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>() |
|||
where attribute.RequiredOS == os && CheckEnvironment(attribute.EnvironmentChecker) |
|||
where attribute.RequiresWindowingSubsystem == null |
|||
|| attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name |
|||
orderby attribute.Priority ascending |
|||
select attribute).FirstOrDefault(); |
|||
|
|||
if (renderingSubsystemAttribute == null) |
|||
{ |
|||
throw new InvalidOperationException("No rendering subsystem found. Are you missing assembly references?"); |
|||
} |
|||
|
|||
UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType |
|||
.GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null), |
|||
windowingSubsystemAttribute.Name); |
|||
|
|||
UseRenderingSubsystem(() => renderingSubsystemAttribute.InitializationType |
|||
.GetRuntimeMethod(renderingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null), |
|||
renderingSubsystemAttribute.Name); |
|||
|
|||
return this; |
|||
} |
|||
|
|||
private void LoadAssembliesInDirectory() |
|||
{ |
|||
var location = Assembly.GetEntryAssembly().Location; |
|||
if (string.IsNullOrWhiteSpace(location)) |
|||
return; |
|||
var dir = new FileInfo(location).Directory; |
|||
if (dir == null) |
|||
return; |
|||
foreach (var file in dir.EnumerateFiles("*.dll")) |
|||
{ |
|||
try |
|||
{ |
|||
Assembly.LoadFile(file.FullName); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFrameworks>net6.0;net461;netcoreapp2.0</TargetFrameworks> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="../Avalonia.Base/Avalonia.Base.csproj" /> |
|||
<ProjectReference Include="../Avalonia.Visuals/Avalonia.Visuals.csproj" /> |
|||
<ProjectReference Include="../Avalonia.Controls/Avalonia.Controls.csproj" /> |
|||
<ProjectReference Include="../Avalonia.PlatformSupport/Avalonia.PlatformSupport.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="System.Runtime.InteropServices.RuntimeInformation" Version="4.3.0" Condition="'$(TargetFramework)' == 'net461'" /> |
|||
</ItemGroup> |
|||
|
|||
<Import Project="..\..\build\NetCore.props" /> |
|||
<Import Project="..\..\build\NetFX.props" /> |
|||
<Import Project="..\..\build\ApiDiff.props" /> |
|||
</Project> |
|||
@ -1,4 +0,0 @@ |
|||
using Avalonia.Native; |
|||
using Avalonia.Platform; |
|||
|
|||
[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 1, "AvaloniaNative", typeof(AvaloniaNativePlatform), nameof(AvaloniaNativePlatform.Initialize))] |
|||
@ -0,0 +1,20 @@ |
|||
using Avalonia.Controls; |
|||
using Avalonia.PlatformSupport; |
|||
|
|||
namespace Avalonia |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes platform-specific services for an <see cref="Application"/>.
|
|||
/// </summary>
|
|||
public sealed class AppBuilder : AppBuilderBase<AppBuilder> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="AppBuilder"/> class.
|
|||
/// </summary>
|
|||
public AppBuilder() |
|||
: base(new StandardRuntimePlatform(), |
|||
builder => StandardRuntimePlatformServices.Register(builder.ApplicationType?.Assembly)) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Platform |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] |
|||
public class ExportRenderingSubsystemAttribute : Attribute |
|||
{ |
|||
public ExportRenderingSubsystemAttribute(OperatingSystemType requiredOS, int priority, string name, Type initializationType, string initializationMethod, |
|||
Type? environmentChecker = null) |
|||
{ |
|||
Name = name; |
|||
InitializationType = initializationType; |
|||
InitializationMethod = initializationMethod; |
|||
EnvironmentChecker = environmentChecker; |
|||
RequiredOS = requiredOS; |
|||
Priority = priority; |
|||
} |
|||
|
|||
public string InitializationMethod { get; private set; } |
|||
public Type? EnvironmentChecker { get; } |
|||
public Type InitializationType { get; private set; } |
|||
public string Name { get; private set; } |
|||
public int Priority { get; private set; } |
|||
public OperatingSystemType RequiredOS { get; private set; } |
|||
public string? RequiresWindowingSubsystem { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,116 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Text; |
|||
using XamlX.Emit; |
|||
using XamlX.IL; |
|||
using XamlX.TypeSystem; |
|||
using Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers; |
|||
using System.Reflection.Emit; |
|||
|
|||
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|||
{ |
|||
internal class XamlIlTrampolineBuilder |
|||
{ |
|||
private IXamlTypeBuilder<IXamlILEmitter> _builder; |
|||
private Dictionary<string, IXamlMethod> _trampolines = new(); |
|||
|
|||
public XamlIlTrampolineBuilder(IXamlTypeBuilder<IXamlILEmitter> builder) |
|||
{ |
|||
_builder = builder; |
|||
} |
|||
|
|||
public IXamlMethod EmitCommandExecuteTrampoline(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlMethod executeMethod) |
|||
{ |
|||
Debug.Assert(!executeMethod.IsStatic); |
|||
string methodName = $"{executeMethod.DeclaringType.GetFqn()}+{executeMethod.Name}_{executeMethod.Parameters.Count}!CommandExecuteTrampoline"; |
|||
if (_trampolines.TryGetValue(methodName, out var method)) |
|||
{ |
|||
return method; |
|||
} |
|||
var trampoline = _builder.DefineMethod( |
|||
context.Configuration.WellKnownTypes.Void, |
|||
new[] { context.Configuration.WellKnownTypes.Object, context.Configuration.WellKnownTypes.Object }, |
|||
methodName, |
|||
true, |
|||
true, |
|||
false); |
|||
var gen = trampoline.Generator; |
|||
if (executeMethod.DeclaringType.IsValueType) |
|||
{ |
|||
gen.Ldarg_0() |
|||
.Unbox(executeMethod.DeclaringType); |
|||
} |
|||
else |
|||
{ |
|||
gen.Ldarg_0() |
|||
.Castclass(executeMethod.DeclaringType); |
|||
} |
|||
if (executeMethod.Parameters.Count != 0) |
|||
{ |
|||
Debug.Assert(executeMethod.Parameters.Count == 1); |
|||
if (executeMethod.Parameters[0] != context.Configuration.WellKnownTypes.Object) |
|||
{ |
|||
var convertedValue = gen.DefineLocal(context.Configuration.WellKnownTypes.Object); |
|||
gen.Ldtype(executeMethod.Parameters[0]) |
|||
.Ldarg(1) |
|||
.EmitCall(context.Configuration.WellKnownTypes.CultureInfo.FindMethod(m => m.Name == "get_CurrentCulture")) |
|||
.Ldloca(convertedValue) |
|||
.EmitCall( |
|||
context.GetAvaloniaTypes().TypeUtilities.FindMethod(m => m.Name == "TryConvert"), |
|||
swallowResult: true) |
|||
.Ldloc(convertedValue) |
|||
.Unbox_Any(executeMethod.Parameters[0]); |
|||
} |
|||
else |
|||
{ |
|||
gen.Ldarg(1); |
|||
} |
|||
} |
|||
gen.EmitCall(executeMethod, swallowResult: true); |
|||
gen.Ret(); |
|||
|
|||
_trampolines.Add(methodName, trampoline); |
|||
return trampoline; |
|||
} |
|||
|
|||
public IXamlMethod EmitCommandCanExecuteTrampoline(XamlEmitContext<IXamlILEmitter, XamlILNodeEmitResult> context, IXamlMethod canExecuteMethod) |
|||
{ |
|||
Debug.Assert(!canExecuteMethod.IsStatic); |
|||
Debug.Assert(canExecuteMethod.Parameters.Count == 1); |
|||
Debug.Assert(canExecuteMethod.ReturnType == context.Configuration.WellKnownTypes.Boolean); |
|||
string methodName = $"{canExecuteMethod.DeclaringType.GetFqn()}+{canExecuteMethod.Name}!CommandCanExecuteTrampoline"; |
|||
if (_trampolines.TryGetValue(methodName, out var method)) |
|||
{ |
|||
return method; |
|||
} |
|||
var trampoline = _builder.DefineMethod( |
|||
context.Configuration.WellKnownTypes.Boolean, |
|||
new[] { context.Configuration.WellKnownTypes.Object, context.Configuration.WellKnownTypes.Object }, |
|||
methodName, |
|||
true, |
|||
true, |
|||
false); |
|||
if (canExecuteMethod.DeclaringType.IsValueType) |
|||
{ |
|||
trampoline.Generator |
|||
.Ldarg_0() |
|||
.Unbox(canExecuteMethod.DeclaringType); |
|||
} |
|||
else |
|||
{ |
|||
trampoline.Generator |
|||
.Ldarg_0() |
|||
.Castclass(canExecuteMethod.DeclaringType); |
|||
} |
|||
trampoline.Generator |
|||
.Ldarg(1) |
|||
.Emit(OpCodes.Tailcall) |
|||
.EmitCall(canExecuteMethod) |
|||
.Ret(); |
|||
|
|||
_trampolines.Add(methodName, trampoline); |
|||
return trampoline; |
|||
} |
|||
} |
|||
} |
|||
@ -1 +1 @@ |
|||
Subproject commit 8e20d65eb5f1efbae08e49b18f39bfdce32df7b3 |
|||
Subproject commit daaac590e078967b78045f74c38ef046d00d8582 |
|||
@ -0,0 +1,156 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel; |
|||
using System.Reflection; |
|||
using System.Text; |
|||
using System.Windows.Input; |
|||
using Avalonia.Data; |
|||
using Avalonia.Data.Core.Plugins; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings |
|||
{ |
|||
internal class CommandAccessorPlugin : IPropertyAccessorPlugin |
|||
{ |
|||
private readonly Action<object, object> _execute; |
|||
private readonly Func<object, object, bool> _canExecute; |
|||
private readonly ISet<string> _dependsOnProperties; |
|||
|
|||
public CommandAccessorPlugin(Action<object, object> execute, Func<object, object, bool> canExecute, ISet<string> dependsOnProperties) |
|||
{ |
|||
_execute = execute; |
|||
_canExecute = canExecute; |
|||
_dependsOnProperties = dependsOnProperties; |
|||
} |
|||
|
|||
public bool Match(object obj, string propertyName) |
|||
{ |
|||
throw new InvalidOperationException("The CommandAccessorPlugin does not support dynamic matching"); |
|||
} |
|||
|
|||
public IPropertyAccessor Start(WeakReference<object> reference, string propertyName) |
|||
{ |
|||
return new CommandAccessor(reference, _execute, _canExecute, _dependsOnProperties); |
|||
} |
|||
|
|||
private sealed class CommandAccessor : PropertyAccessorBase |
|||
{ |
|||
private readonly WeakReference<object> _reference; |
|||
private Command _command; |
|||
private readonly ISet<string> _dependsOnProperties; |
|||
|
|||
public CommandAccessor(WeakReference<object> reference, Action<object, object> execute, Func<object, object, bool> canExecute, ISet<string> dependsOnProperties) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(reference != null); |
|||
|
|||
_reference = reference; |
|||
_dependsOnProperties = dependsOnProperties; |
|||
_command = new Command(reference, execute, canExecute); |
|||
|
|||
} |
|||
|
|||
public override object Value => _reference.TryGetTarget(out var _) ? _command : null; |
|||
|
|||
private void RaiseCanExecuteChanged() |
|||
{ |
|||
_command.RaiseCanExecuteChanged(); |
|||
} |
|||
|
|||
private sealed class Command : ICommand |
|||
{ |
|||
private readonly WeakReference<object> _target; |
|||
private readonly Action<object, object> _execute; |
|||
private readonly Func<object, object, bool> _canExecute; |
|||
|
|||
public event EventHandler CanExecuteChanged; |
|||
|
|||
public Command(WeakReference<object> target, Action<object, object> execute, Func<object, object, bool> canExecute) |
|||
{ |
|||
_target = target; |
|||
_execute = execute; |
|||
_canExecute = canExecute; |
|||
} |
|||
|
|||
public void RaiseCanExecuteChanged() |
|||
{ |
|||
Threading.Dispatcher.UIThread.Post(() => CanExecuteChanged?.Invoke(this, EventArgs.Empty) |
|||
, Threading.DispatcherPriority.Input); |
|||
} |
|||
|
|||
public bool CanExecute(object parameter) |
|||
{ |
|||
if (_target.TryGetTarget(out var target)) |
|||
{ |
|||
if (_canExecute == null) |
|||
{ |
|||
return true; |
|||
} |
|||
return _canExecute(target, parameter); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
public void Execute(object parameter) |
|||
{ |
|||
if (_target.TryGetTarget(out var target)) |
|||
{ |
|||
_execute(target, parameter); |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override Type PropertyType => typeof(ICommand); |
|||
|
|||
public override bool SetValue(object value, BindingPriority priority) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
void OnNotifyPropertyChanged(object sender, PropertyChangedEventArgs e) |
|||
{ |
|||
if (string.IsNullOrEmpty(e.PropertyName) || _dependsOnProperties.Contains(e.PropertyName)) |
|||
{ |
|||
RaiseCanExecuteChanged(); |
|||
} |
|||
} |
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
SendCurrentValue(); |
|||
SubscribeToChanges(); |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
if (_dependsOnProperties is { Count: > 0 } && _reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc) |
|||
{ |
|||
WeakEventHandlerManager.Unsubscribe<PropertyChangedEventArgs, InpcPropertyAccessor>( |
|||
inpc, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
|
|||
private void SendCurrentValue() |
|||
{ |
|||
try |
|||
{ |
|||
var value = Value; |
|||
PublishValue(value); |
|||
} |
|||
catch { } |
|||
} |
|||
|
|||
private void SubscribeToChanges() |
|||
{ |
|||
if (_dependsOnProperties is { Count:>0 } && _reference.TryGetTarget(out var o) && o is INotifyPropertyChanged inpc) |
|||
{ |
|||
WeakEventHandlerManager.Subscribe<INotifyPropertyChanged, PropertyChangedEventArgs, InpcPropertyAccessor>( |
|||
inpc, |
|||
nameof(INotifyPropertyChanged.PropertyChanged), |
|||
OnNotifyPropertyChanged); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Reflection; |
|||
using System.Text; |
|||
using Avalonia.Data; |
|||
using Avalonia.Data.Core.Plugins; |
|||
|
|||
#nullable enable |
|||
|
|||
namespace Avalonia.Markup.Xaml.MarkupExtensions.CompiledBindings |
|||
{ |
|||
internal class MethodAccessorPlugin : IPropertyAccessorPlugin |
|||
{ |
|||
private MethodInfo _method; |
|||
private readonly Type _delegateType; |
|||
|
|||
public MethodAccessorPlugin(MethodInfo method, Type delegateType) |
|||
{ |
|||
_method = method; |
|||
_delegateType = delegateType; |
|||
} |
|||
|
|||
public bool Match(object obj, string propertyName) |
|||
{ |
|||
throw new InvalidOperationException("The MethodAccessorPlugin does not support dynamic matching"); |
|||
} |
|||
|
|||
public IPropertyAccessor Start(WeakReference<object?> reference, string propertyName) |
|||
{ |
|||
Debug.Assert(_method.Name == propertyName); |
|||
return new Accessor(reference, _method, _delegateType); |
|||
} |
|||
|
|||
private sealed class Accessor : PropertyAccessorBase |
|||
{ |
|||
public Accessor(WeakReference<object?> reference, MethodInfo method, Type delegateType) |
|||
{ |
|||
_ = reference ?? throw new ArgumentNullException(nameof(reference)); |
|||
_ = method ?? throw new ArgumentNullException(nameof(method)); |
|||
|
|||
PropertyType = delegateType; |
|||
|
|||
if (method.IsStatic) |
|||
{ |
|||
Value = method.CreateDelegate(PropertyType); |
|||
} |
|||
else if (reference.TryGetTarget(out var target)) |
|||
{ |
|||
Value = method.CreateDelegate(PropertyType, target); |
|||
} |
|||
} |
|||
|
|||
public override Type? PropertyType { get; } |
|||
|
|||
public override object? Value { get; } |
|||
|
|||
public override bool SetValue(object? value, BindingPriority priority) => false; |
|||
|
|||
protected override void SubscribeCore() |
|||
{ |
|||
try |
|||
{ |
|||
PublishValue(Value); |
|||
} |
|||
catch { } |
|||
} |
|||
|
|||
protected override void UnsubscribeCore() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,9 +1,4 @@ |
|||
using System.Runtime.CompilerServices; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Direct2D1; |
|||
|
|||
[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize), |
|||
typeof(Direct2DChecker))] |
|||
|
|||
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.RenderTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
|||
[assembly: InternalsVisibleTo("Avalonia.Direct2D1.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] |
|||
|
|||
@ -1,4 +0,0 @@ |
|||
using Avalonia.Platform; |
|||
using Avalonia.Win32; |
|||
|
|||
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 1, "Win32", typeof(Win32Platform), nameof(Win32Platform.Initialize))] |
|||
Loading…
Reference in new issue