From 22ed332c70bf492c2ef8126efd2c61aa2213125a Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 30 Aug 2016 16:26:21 -0500 Subject: [PATCH] Made UsePlatformDetect more modular and updated our platform assemblies to use this feature. Implemented feedback and fixed iOS build. --- src/Avalonia.Controls/AppBuilderBase.cs | 4 +- .../Avalonia.Controls.csproj | 1 + .../ExportWindowingSubsystemAttribute.cs | 27 ++++++++++ .../AppBuilder.cs | 54 ++++++++++++++----- .../Avalonia.DotNetFrameworkRuntime.csproj | 6 ++- .../Avalonia.SceneGraph.csproj | 1 + .../ExportRenderingSubsystemAttribute.cs | 28 ++++++++++ src/Gtk/Avalonia.Cairo/CairoPlatform.cs | 2 +- .../Avalonia.Cairo/Properties/AssemblyInfo.cs | 6 +++ src/Gtk/Avalonia.Gtk/GtkPlatform.cs | 2 +- .../Avalonia.Gtk/Properties/AssemblyInfo.cs | 7 +++ .../Properties/AssemblyInfo.cs | 4 ++ src/Skia/Avalonia.Skia/SkiaPlatform.cs | 2 +- .../Avalonia.Direct2D1/Direct2D1Platform.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++ .../Avalonia.Win32/Properties/AssemblyInfo.cs | 3 ++ src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- src/iOS/Avalonia.iOS/iOSPlatform.cs | 2 +- 18 files changed, 134 insertions(+), 23 deletions(-) create mode 100644 src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs create mode 100644 src/Avalonia.SceneGraph/Platform/ExportRenderingSubsystemAttribute.cs diff --git a/src/Avalonia.Controls/AppBuilderBase.cs b/src/Avalonia.Controls/AppBuilderBase.cs index d741e5b977..a2dedd7340 100644 --- a/src/Avalonia.Controls/AppBuilderBase.cs +++ b/src/Avalonia.Controls/AppBuilderBase.cs @@ -17,7 +17,7 @@ namespace Avalonia.Controls /// /// Gets or sets the instance. /// - public IRuntimePlatform RuntimePlatform { get; private set; } + public IRuntimePlatform RuntimePlatform { get; set; } /// /// Gets or sets a method to call the initialize the runtime platform services (e. g. AssetLoader) @@ -105,7 +105,7 @@ namespace Avalonia.Controls return Self; } - public AppBuilder AfterSetup(Action callback) + public TAppBuilder AfterSetup(Action callback) { AfterSetupCallback = (Action)Delegate.Combine(AfterSetupCallback, callback); return Self; diff --git a/src/Avalonia.Controls/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj index 1f5fd7c449..c7bfcf7ac4 100644 --- a/src/Avalonia.Controls/Avalonia.Controls.csproj +++ b/src/Avalonia.Controls/Avalonia.Controls.csproj @@ -59,6 +59,7 @@ + diff --git a/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs new file mode 100644 index 0000000000..628f73ca80 --- /dev/null +++ b/src/Avalonia.Controls/Platform/ExportWindowingSubsystemAttribute.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Platform +{ + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public class ExportWindowingSubsystemAttribute : Attribute + { + public ExportWindowingSubsystemAttribute(OperatingSystemType requiredRuntimePlatform, int priority, string name, Type initializationType, string initializationMethod) + { + Name = name; + InitializationType = initializationType; + InitializationMethod = initializationMethod; + RequiredOS = requiredRuntimePlatform; + Priority = priority; + } + + public string InitializationMethod { get; private set; } + public Type InitializationType { get; private set; } + public string Name { get; private set; } + public int Priority { get; private set; } + public OperatingSystemType RequiredOS { get; private set; } + } +} diff --git a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs index 508a23866c..157fb7acd9 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs +++ b/src/Avalonia.DotNetFrameworkRuntime/AppBuilder.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Platform; using Avalonia.Shared.PlatformSupport; +using System.IO; namespace Avalonia { @@ -23,22 +24,47 @@ namespace Avalonia public AppBuilder UsePlatformDetect() { - var platformId = (int)Environment.OSVersion.Platform; - if (platformId == 4 || platformId == 6) - { - UseRenderingSubsystem("Avalonia.Cairo"); - UseWindowingSubsystem("Avalonia.Gtk"); - WindowingSubsystemName = "Gtk"; - RenderingSubsystemName = "Cairo"; - } - else + var os = RuntimePlatform.GetRuntimeInfo().OperatingSystem; + + LoadAssembliesInDirectory(); + + var windowingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies() + from attribute in assembly.GetCustomAttributes() + where attribute.RequiredOS == os + orderby attribute.Priority ascending + select attribute).First(); + + var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies() + from attribute in assembly.GetCustomAttributes() + where attribute.RequiredOS == os + where attribute.RequiresWindowingSubsystem == null + || attribute.RequiresWindowingSubsystem == windowingSubsystemAttribute.Name + orderby attribute.Priority ascending + select attribute).First(); + + UseWindowingSubsystem(() => windowingSubsystemAttribute.InitializationType + .GetRuntimeMethod(windowingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null)); + WindowingSubsystemName = windowingSubsystemAttribute.Name; + + UseRenderingSubsystem(() => renderingSubsystemAttribute.InitializationType + .GetRuntimeMethod(renderingSubsystemAttribute.InitializationMethod, Type.EmptyTypes).Invoke(null, null)); + RenderingSubsystemName = renderingSubsystemAttribute.Name; + + return this; + } + + private void LoadAssembliesInDirectory() + { + foreach (var file in new FileInfo(Assembly.GetEntryAssembly().Location).Directory.EnumerateFiles("*.dll")) { - UseRenderingSubsystem("Avalonia.Direct2D1"); - UseWindowingSubsystem("Avalonia.Win32"); - WindowingSubsystemName = "Win32"; - RenderingSubsystemName = "Direct2D1"; + try + { + Assembly.LoadFile(file.FullName); + } + catch (Exception) + { + } } - return this; } } } diff --git a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj index 55a4578f59..b58ad3af1e 100644 --- a/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj +++ b/src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj @@ -64,6 +64,10 @@ {D2221C82-4A25-4583-9B43-D791E3F6820C} Avalonia.Controls + + {eb582467-6abb-43a1-b052-e981ba910e3a} + Avalonia.SceneGraph + {f1baa01a-f176-4c6a-b39d-5b40bb1b148f} Avalonia.Styling @@ -81,4 +85,4 @@ --> - + \ No newline at end of file diff --git a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj index 25a79307e6..1f2734b2e9 100644 --- a/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj +++ b/src/Avalonia.SceneGraph/Avalonia.SceneGraph.csproj @@ -100,6 +100,7 @@ + diff --git a/src/Avalonia.SceneGraph/Platform/ExportRenderingSubsystemAttribute.cs b/src/Avalonia.SceneGraph/Platform/ExportRenderingSubsystemAttribute.cs new file mode 100644 index 0000000000..a020bf9b1c --- /dev/null +++ b/src/Avalonia.SceneGraph/Platform/ExportRenderingSubsystemAttribute.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Avalonia.Platform +{ + [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] + public class ExportRenderingSubsystemAttribute : Attribute + { + public ExportRenderingSubsystemAttribute(OperatingSystemType requiredOS, int priority, string name, Type initializationType, string initializationMethod) + { + Name = name; + InitializationType = initializationType; + InitializationMethod = initializationMethod; + RequiredOS = requiredOS; + Priority = priority; + } + + public string InitializationMethod { get; private set; } + 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; } + } +} diff --git a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs b/src/Gtk/Avalonia.Cairo/CairoPlatform.cs index 493416d15f..c97a95a1ed 100644 --- a/src/Gtk/Avalonia.Cairo/CairoPlatform.cs +++ b/src/Gtk/Avalonia.Cairo/CairoPlatform.cs @@ -14,7 +14,7 @@ namespace Avalonia { public static T UseCairo(this T builder) where T : AppBuilderBase, new() { - builder.RenderingSubsystemInitializer = Cairo.CairoPlatform.Initialize; + builder.UseRenderingSubsystem(Cairo.CairoPlatform.Initialize); builder.RenderingSubsystemName = "Cairo"; return builder; } diff --git a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs index cdda1132bb..63457cc1a2 100644 --- a/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs +++ b/src/Gtk/Avalonia.Cairo/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using Avalonia.Cairo; +using Avalonia.Platform; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -37,3 +39,7 @@ using System.Runtime.InteropServices; // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] +[assembly: ExportRenderingSubsystem(OperatingSystemType.Linux, 1, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] +[assembly: ExportRenderingSubsystem(OperatingSystemType.OSX, 2, "Cairo", typeof(CairoPlatform), nameof(CairoPlatform.Initialize), RequiresWindowingSubsystem = "GTK")] diff --git a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs index b54b6d3e71..15c16b3c2c 100644 --- a/src/Gtk/Avalonia.Gtk/GtkPlatform.cs +++ b/src/Gtk/Avalonia.Gtk/GtkPlatform.cs @@ -16,7 +16,7 @@ namespace Avalonia { public static T UseGtk(this T builder) where T : AppBuilderBase, new() { - builder.WindowingSubsystemInitializer = Gtk.GtkPlatform.Initialize; + builder.UseWindowingSubsystem(Gtk.GtkPlatform.Initialize); builder.WindowingSubsystemName = "Gtk"; return builder; } diff --git a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs b/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs index 6c970b77f6..f0e9ab4ccb 100644 --- a/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs +++ b/src/Gtk/Avalonia.Gtk/Properties/AssemblyInfo.cs @@ -1,6 +1,8 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using Avalonia.Gtk; +using Avalonia.Platform; using System.Reflection; using System.Runtime.CompilerServices; @@ -19,3 +21,8 @@ using System.Runtime.CompilerServices; // The form "{Major}.{Minor}.*" will automatically update the build and revision, // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("1.0.*")] + +[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] +[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 1, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] +[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK", typeof(GtkPlatform), nameof(GtkPlatform.Initialize))] + diff --git a/src/Skia/Avalonia.Skia.Desktop/Properties/AssemblyInfo.cs b/src/Skia/Avalonia.Skia.Desktop/Properties/AssemblyInfo.cs index 0afee62368..69a3f34489 100644 --- a/src/Skia/Avalonia.Skia.Desktop/Properties/AssemblyInfo.cs +++ b/src/Skia/Avalonia.Skia.Desktop/Properties/AssemblyInfo.cs @@ -1,3 +1,5 @@ +using Avalonia.Platform; +using Avalonia.Skia; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -34,3 +36,5 @@ using System.Runtime.InteropServices; // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] + +[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 3, "Skia", typeof(SkiaPlatform), nameof(SkiaPlatform.Initialize))] diff --git a/src/Skia/Avalonia.Skia/SkiaPlatform.cs b/src/Skia/Avalonia.Skia/SkiaPlatform.cs index 3523af0b35..a49bb8bb13 100644 --- a/src/Skia/Avalonia.Skia/SkiaPlatform.cs +++ b/src/Skia/Avalonia.Skia/SkiaPlatform.cs @@ -10,7 +10,7 @@ namespace Avalonia { public static T UseSkia(this T builder) where T : AppBuilderBase, new() { - builder.RenderingSubsystemInitializer = Avalonia.Skia.SkiaPlatform.Initialize; + builder.UseRenderingSubsystem(Skia.SkiaPlatform.Initialize); builder.RenderingSubsystemName = "Skia"; return builder; } diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs index 8d94ebd1e9..22d4a498cc 100644 --- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs +++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs @@ -14,7 +14,7 @@ namespace Avalonia { public static T UseDirect2D1(this T builder) where T : AppBuilderBase, new() { - builder.RenderingSubsystemInitializer = Avalonia.Direct2D1.Direct2D1Platform.Initialize; + builder.UseRenderingSubsystem(Direct2D1.Direct2D1Platform.Initialize); builder.RenderingSubsystemName = "Direct2D1"; return builder; } diff --git a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs index a4556b001f..3ab086b156 100644 --- a/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs +++ b/src/Windows/Avalonia.Direct2D1/Properties/AssemblyInfo.cs @@ -2,5 +2,9 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System.Reflection; +using Avalonia.Platform; +using Avalonia.Direct2D1; [assembly: AssemblyTitle("Avalonia.Direct2D1")] +[assembly: ExportRenderingSubsystem(OperatingSystemType.WinNT, 1, "Direct2D1", typeof(Direct2D1Platform), nameof(Direct2D1Platform.Initialize))] + diff --git a/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs b/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs index cf7be620be..5b4d2cef23 100644 --- a/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs +++ b/src/Windows/Avalonia.Win32/Properties/AssemblyInfo.cs @@ -1,6 +1,9 @@ // Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using Avalonia.Platform; +using Avalonia.Win32; using System.Reflection; [assembly: AssemblyTitle("Avalonia.Win32")] +[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 1, "Win32", typeof(Win32Platform), nameof(Win32Platform.Initialize))] diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 5c6309b17a..6b5f55cb47 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -23,7 +23,7 @@ namespace Avalonia { public static T UseWin32(this T builder) where T : AppBuilderBase, new() { - builder.WindowingSubsystemInitializer = Win32.Win32Platform.Initialize; + builder.UseWindowingSubsystem(Win32.Win32Platform.Initialize); builder.WindowingSubsystemName = "Win32"; return builder; } diff --git a/src/iOS/Avalonia.iOS/iOSPlatform.cs b/src/iOS/Avalonia.iOS/iOSPlatform.cs index 6a14904b35..4a25b7d374 100644 --- a/src/iOS/Avalonia.iOS/iOSPlatform.cs +++ b/src/iOS/Avalonia.iOS/iOSPlatform.cs @@ -15,7 +15,7 @@ namespace Avalonia { public static T UseiOS(this T builder) where T : AppBuilderBase, new() { - builder.WindowingSubsystemInitializer = iOSPlatform.Initialize; + builder.UseWindowingSubsystem(iOSPlatform.Initialize); builder.WindowingSubsystemName = "iOS"; return builder; }