Browse Source

Made UsePlatformDetect more modular and updated our platform assemblies to use this feature.

Implemented feedback and fixed iOS build.
Jeremy Koritzinsky 9 years ago
parent
commit
22ed332c70

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

@@ -17,7 +17,7 @@ namespace Avalonia.Controls
         /// <summary>
         /// Gets or sets the <see cref="IRuntimePlatform"/> instance.
         /// </summary>
-        public IRuntimePlatform RuntimePlatform { get; private set; }
+        public IRuntimePlatform RuntimePlatform { get; set; }
 
         /// <summary>
         /// 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<TAppBuilder> callback)
+        public TAppBuilder AfterSetup(Action<TAppBuilder> callback)
         {
             AfterSetupCallback = (Action<TAppBuilder>)Delegate.Combine(AfterSetupCallback, callback);
             return Self;

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

@@ -59,6 +59,7 @@
     <Compile Include="Embedding\EmbeddableControlRoot.cs" />
     <Compile Include="Platform\IEmbeddableWindowImpl.cs" />
     <Compile Include="Platform\ExportAvaloniaModuleAttribute.cs" />
+    <Compile Include="Platform\ExportWindowingSubsystemAttribute.cs" />
     <Compile Include="WindowIcon.cs" />
     <Compile Include="IPseudoClasses.cs" />
     <Compile Include="DropDownItem.cs" />

+ 27 - 0
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; }
+    }
+}

+ 40 - 14
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<ExportWindowingSubsystemAttribute>()
+                                               where attribute.RequiredOS == os
+                                               orderby attribute.Priority ascending
+                                               select attribute).First();
+
+            var renderingSubsystemAttribute = (from assembly in RuntimePlatform.GetLoadedAssemblies()
+                                               from attribute in assembly.GetCustomAttributes<ExportRenderingSubsystemAttribute>()
+                                               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;
         }
     }
 }

+ 5 - 1
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@@ -64,6 +64,10 @@
       <Project>{D2221C82-4A25-4583-9B43-D791E3F6820C}</Project>
       <Name>Avalonia.Controls</Name>
     </ProjectReference>
+    <ProjectReference Include="..\Avalonia.SceneGraph\Avalonia.SceneGraph.csproj">
+      <Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
+      <Name>Avalonia.SceneGraph</Name>
+    </ProjectReference>
     <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj">
       <Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
       <Name>Avalonia.Styling</Name>
@@ -81,4 +85,4 @@
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
+</Project>

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

@@ -100,6 +100,7 @@
     <Compile Include="Media\FormattedText.cs" />
     <Compile Include="Media\Geometry.cs" />
     <Compile Include="Media\IDrawingContext.cs" />
+    <Compile Include="Platform\ExportRenderingSubsystemAttribute.cs" />
     <Compile Include="RenderTargetCorruptedException.cs" />
     <Compile Include="VisualTree\IVisual.cs" />
     <Compile Include="Media\Imaging\Bitmap.cs" />

+ 28 - 0
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; }
+    }
+}

+ 1 - 1
src/Gtk/Avalonia.Cairo/CairoPlatform.cs

@@ -14,7 +14,7 @@ namespace Avalonia
     {
         public static T UseCairo<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.RenderingSubsystemInitializer = Cairo.CairoPlatform.Initialize;
+            builder.UseRenderingSubsystem(Cairo.CairoPlatform.Initialize);
             builder.RenderingSubsystemName = "Cairo";
             return builder;
         }

+ 6 - 0
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")]

+ 1 - 1
src/Gtk/Avalonia.Gtk/GtkPlatform.cs

@@ -16,7 +16,7 @@ namespace Avalonia
     {
         public static T UseGtk<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.WindowingSubsystemInitializer = Gtk.GtkPlatform.Initialize;
+            builder.UseWindowingSubsystem(Gtk.GtkPlatform.Initialize);
             builder.WindowingSubsystemName = "Gtk";
             return builder;
         }

+ 7 - 0
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))]
+

+ 4 - 0
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))]

+ 1 - 1
src/Skia/Avalonia.Skia/SkiaPlatform.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     {
         public static T UseSkia<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.RenderingSubsystemInitializer = Avalonia.Skia.SkiaPlatform.Initialize;
+            builder.UseRenderingSubsystem(Skia.SkiaPlatform.Initialize);
             builder.RenderingSubsystemName = "Skia";
             return builder;
         }

+ 1 - 1
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@@ -14,7 +14,7 @@ namespace Avalonia
     {
         public static T UseDirect2D1<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.RenderingSubsystemInitializer = Avalonia.Direct2D1.Direct2D1Platform.Initialize;
+            builder.UseRenderingSubsystem(Direct2D1.Direct2D1Platform.Initialize);
             builder.RenderingSubsystemName = "Direct2D1";
             return builder;
         }

+ 4 - 0
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))]
+

+ 3 - 0
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))]

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

@@ -23,7 +23,7 @@ namespace Avalonia
     {
         public static T UseWin32<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.WindowingSubsystemInitializer = Win32.Win32Platform.Initialize;
+            builder.UseWindowingSubsystem(Win32.Win32Platform.Initialize);
             builder.WindowingSubsystemName = "Win32";
             return builder;
         }

+ 1 - 1
src/iOS/Avalonia.iOS/iOSPlatform.cs

@@ -15,7 +15,7 @@ namespace Avalonia
     {
         public static T UseiOS<T>(this T builder) where T : AppBuilderBase<T>, new()
         {
-            builder.WindowingSubsystemInitializer = iOSPlatform.Initialize;
+            builder.UseWindowingSubsystem(iOSPlatform.Initialize);
             builder.WindowingSubsystemName = "iOS";
             return builder;
         }