From 13171c4be3856d467fd997ad0b3b9a1a930ebe6f Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Mon, 12 Feb 2018 21:46:30 +0300 Subject: [PATCH] Implemented `--session-id` and `--method win32` for previewer --- .../ControlCatalog.NetCore.csproj | 1 + .../Remote/RemoteDesignerEntryPoint.cs | 55 +++++++++++++++---- .../DesignMessages.cs | 12 +++- .../TcpTransportBase.cs | 2 +- .../Program.cs | 35 +++++++++++- 5 files changed, 90 insertions(+), 15 deletions(-) diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index b308c59789..ec841db5b2 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -6,6 +6,7 @@ + diff --git a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs index 51cf1d4dde..c4febff434 100644 --- a/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs +++ b/src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Net; using System.Reflection; using Avalonia.Controls; @@ -22,6 +23,15 @@ namespace Avalonia.DesignerSupport.Remote { public string AppPath { get; set; } public Uri Transport { get; set; } + public string Method { get; set; } = Methods.AvaloniaRemote; + public string SessionId { get; set; } = Guid.NewGuid().ToString(); + } + + static class Methods + { + public const string AvaloniaRemote = "avalonia-remote"; + public const string Win32 = "win32"; + } static Exception Die(string error) @@ -35,11 +45,13 @@ namespace Avalonia.DesignerSupport.Remote return new Exception("APPEXIT"); } + static void Log(string message) => Console.WriteLine(message); + static Exception PrintUsage() { - Console.Error.WriteLine("Usage: --transport transport_spec app"); + Console.Error.WriteLine("Usage: --transport transport_spec --session-id sid --method method app"); Console.Error.WriteLine(); - Console.Error.WriteLine("Example: --transport tcp-bson://127.0.0.1:30243/ MyApp.exe"); + Console.Error.WriteLine("Example: --transport tcp-bson://127.0.0.1:30243/ --session-id 123 --method avalonia-remote MyApp.exe"); Console.Error.Flush(); return Die(null); } @@ -59,6 +71,10 @@ namespace Avalonia.DesignerSupport.Remote } else if (arg == "--transport") next = a => rv.Transport = new Uri(a, UriKind.Absolute); + else if (arg == "--method") + next = a => rv.Method = a; + else if (arg == "--session-id") + next = a => rv.SessionId = a; else if (rv.AppPath == null) rv.AppPath = arg; else @@ -84,18 +100,22 @@ namespace Avalonia.DesignerSupport.Remote PrintUsage(); return null; } - + interface IAppInitializer { - Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj); + Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, CommandLineArgs args, object obj); } class AppInitializer : IAppInitializer where T : AppBuilderBase, new() { - public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj) + public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, + CommandLineArgs args, object obj) { var builder = (AppBuilderBase) obj; - builder.UseWindowingSubsystem(() => PreviewerWindowingPlatform.Initialize(transport)); + if (args.Method == Methods.AvaloniaRemote) + builder.UseWindowingSubsystem(() => PreviewerWindowingPlatform.Initialize(transport)); + if (args.Method == Methods.Win32) + builder.UseWindowingSubsystem("Avalonia.Win32"); builder.SetupWithoutStarting(); return builder.Instance; } @@ -120,13 +140,16 @@ namespace Avalonia.DesignerSupport.Remote BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (builderMethod == null) throw Die($"{entryPoint.DeclaringType.FullName} doesn't have a method named {BuilderMethodName}"); - + Log($"Obtaining AppBuilder instance from {builderMethod.DeclaringType.FullName}.{builderMethod.Name}"); var appBuilder = builderMethod.Invoke(null, null); + Log($"Initializing application in design mode"); var initializer =(IAppInitializer)Activator.CreateInstance(typeof(AppInitializer<>).MakeGenericType(appBuilder.GetType())); - var app = initializer.GetConfiguredApp(transport, appBuilder); + var app = initializer.GetConfiguredApp(transport, args, appBuilder); s_transport = transport; transport.OnMessage += OnTransportMessage; transport.OnException += (t, e) => Die(e.ToString()); + Log("Sending StartDesignerSessionMessage"); + transport.Send(new StartDesignerSessionMessage {SessionId = args.SessionId}); app.Run(new NeverClose()); } @@ -139,7 +162,8 @@ namespace Avalonia.DesignerSupport.Remote s_viewportAllocatedMessage }; } - + + private static Window s_currentWindow; private static void OnTransportMessage(IAvaloniaRemoteTransportConnection transport, object obj) => Dispatcher.UIThread.Post(() => { if (obj is ClientSupportedPixelFormatsMessage formats) @@ -156,8 +180,17 @@ namespace Avalonia.DesignerSupport.Remote { try { - DesignWindowLoader.LoadDesignerWindow(xaml.Xaml, xaml.AssemblyPath); - s_transport.Send(new UpdateXamlResultMessage()); + s_currentWindow?.Close(); + } + catch + { + //Ignore + } + s_currentWindow = null; + try + { + s_currentWindow = DesignWindowLoader.LoadDesignerWindow(xaml.Xaml, xaml.AssemblyPath); + s_transport.Send(new UpdateXamlResultMessage(){Handle = s_currentWindow.PlatformImpl?.Handle?.Handle.ToString()}); } catch (Exception e) { diff --git a/src/Avalonia.Remote.Protocol/DesignMessages.cs b/src/Avalonia.Remote.Protocol/DesignMessages.cs index d6e898f320..f3683da21c 100644 --- a/src/Avalonia.Remote.Protocol/DesignMessages.cs +++ b/src/Avalonia.Remote.Protocol/DesignMessages.cs @@ -1,4 +1,6 @@ -namespace Avalonia.Remote.Protocol.Designer +using System; + +namespace Avalonia.Remote.Protocol.Designer { [AvaloniaRemoteMessageGuid("9AEC9A2E-6315-4066-B4BA-E9A9EFD0F8CC")] public class UpdateXamlMessage @@ -11,7 +13,13 @@ public class UpdateXamlResultMessage { public string Error { get; set; } + public string Handle { get; set; } + } + + [AvaloniaRemoteMessageGuid("854887CF-2694-4EB6-B499-7461B6FB96C7")] + public class StartDesignerSessionMessage + { + public string SessionId { get; set; } } - } \ No newline at end of file diff --git a/src/Avalonia.Remote.Protocol/TcpTransportBase.cs b/src/Avalonia.Remote.Protocol/TcpTransportBase.cs index af62f2da59..3d2bd09485 100644 --- a/src/Avalonia.Remote.Protocol/TcpTransportBase.cs +++ b/src/Avalonia.Remote.Protocol/TcpTransportBase.cs @@ -72,7 +72,7 @@ namespace Avalonia.Remote.Protocol { var c = new TcpClient(); await c.ConnectAsync(address, port); - return CreateTransport(_resolver, c.GetStream(), c.Dispose); + return CreateTransport(_resolver, c.GetStream(), ((IDisposable)c).Dispose); } } } \ No newline at end of file diff --git a/src/tools/Avalonia.Designer.HostApp.NetFX/Program.cs b/src/tools/Avalonia.Designer.HostApp.NetFX/Program.cs index d3f80dd621..bef53bb685 100644 --- a/src/tools/Avalonia.Designer.HostApp.NetFX/Program.cs +++ b/src/tools/Avalonia.Designer.HostApp.NetFX/Program.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading.Tasks; @@ -8,7 +11,37 @@ namespace Avalonia.Designer.HostApp.NetFX { class Program { + private static string s_appDir; public static void Main(string[] args) - => Avalonia.DesignerSupport.Remote.RemoteDesignerEntryPoint.Main(args); + { + s_appDir = Directory.GetCurrentDirectory(); + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; + foreach (var dll in Directory.GetFiles(s_appDir, "*.dll")) + { + try + { + Console.WriteLine("Loading " + dll); + Assembly.LoadFile(dll); + } + catch + { + + } + } + Exec(args); + } + + static void Exec(string[] args) + { + Avalonia.DesignerSupport.Remote.RemoteDesignerEntryPoint.Main(args); + } + + private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + string assemblyPath = Path.Combine(s_appDir, new AssemblyName(args.Name).Name + ".dll"); + if (File.Exists(assemblyPath) == false) return null; + Assembly assembly = Assembly.LoadFrom(assemblyPath); + return assembly; + } } }