Browse Source

Merge branch 'master' of https://github.com/AvaloniaUI/Avalonia into tab-navigation-fix

pull/1366/head
sdoroff 9 years ago
parent
commit
d9622effe5
  1. 1
      samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj
  2. 55
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  3. 12
      src/Avalonia.Remote.Protocol/DesignMessages.cs
  4. 2
      src/Avalonia.Remote.Protocol/TcpTransportBase.cs
  5. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems
  6. 1
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  7. 90
      src/Windows/Avalonia.Win32/EmbeddedWindowImpl.cs
  8. 43
      src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs
  9. 4
      src/Windows/Avalonia.Win32/Win32Platform.cs
  10. 35
      src/tools/Avalonia.Designer.HostApp.NetFX/Program.cs

1
samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj

@ -6,6 +6,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
<ProjectReference Include="..\..\src\Avalonia.DotNetCoreRuntime\Avalonia.DotNetCoreRuntime.csproj" />
<ProjectReference Include="..\..\src\Linux\Avalonia.LinuxFramebuffer\Avalonia.LinuxFramebuffer.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />

55
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<T> : IAppInitializer where T : AppBuilderBase<T>, new()
{
public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj)
public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport,
CommandLineArgs args, object obj)
{
var builder = (AppBuilderBase<T>) 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)
{

12
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; }
}
}

2
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);
}
}
}

1
src/Windows/Avalonia.Win32/Avalonia.Win32.Shared.projitems

@ -11,6 +11,7 @@
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)ClipboardImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CursorFactory.cs" />
<Compile Include="$(MSBuildThisFileDirectory)EmbeddedWindowImpl.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FramebufferManager.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\KeyInterop.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input\WindowsKeyboardDevice.cs" />

1
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -53,7 +53,6 @@
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<Compile Include="Embedding\EmbeddedWindowImpl.cs" />
<Compile Include="Embedding\WinFormsAvaloniaControlHost.cs">
<SubType>Component</SubType>
</Compile>

90
src/Windows/Avalonia.Win32/EmbeddedWindowImpl.cs

@ -0,0 +1,90 @@
// 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 System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
{
class EmbeddedWindowImpl : WindowImpl, IEmbeddableWindowImpl
{
private static IntPtr DefaultParentWindow = CreateParentWindow();
private static UnmanagedMethods.WndProc _wndProcDelegate;
protected override IntPtr CreateWindowOverride(ushort atom)
{
var hWnd = UnmanagedMethods.CreateWindowEx(
0,
atom,
null,
(int)UnmanagedMethods.WindowStyles.WS_CHILD,
0,
0,
640,
480,
DefaultParentWindow,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
return hWnd;
}
protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS)
LostFocus?.Invoke();
return base.WndProc(hWnd, msg, wParam, lParam);
}
public event Action LostFocus;
private static IntPtr CreateParentWindow()
{
_wndProcDelegate = new UnmanagedMethods.WndProc(ParentWndProc);
var wndClassEx = new UnmanagedMethods.WNDCLASSEX
{
cbSize = Marshal.SizeOf<UnmanagedMethods.WNDCLASSEX>(),
hInstance = UnmanagedMethods.GetModuleHandle(null),
lpfnWndProc = _wndProcDelegate,
lpszClassName = "AvaloniaEmbeddedWindow-" + Guid.NewGuid(),
};
var atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx);
if (atom == 0)
{
throw new Win32Exception();
}
var hwnd = UnmanagedMethods.CreateWindowEx(
0,
atom,
null,
(int)UnmanagedMethods.WindowStyles.WS_OVERLAPPEDWINDOW,
UnmanagedMethods.CW_USEDEFAULT,
UnmanagedMethods.CW_USEDEFAULT,
UnmanagedMethods.CW_USEDEFAULT,
UnmanagedMethods.CW_USEDEFAULT,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
if (hwnd == IntPtr.Zero)
{
throw new Win32Exception();
}
return hwnd;
}
private static IntPtr ParentWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
}
}
}

43
src/Windows/Avalonia.Win32/Embedding/EmbeddedWindowImpl.cs

@ -1,43 +0,0 @@
// 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 System;
using Avalonia.Platform;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32
{
class EmbeddedWindowImpl : WindowImpl, IEmbeddableWindowImpl
{
private static readonly System.Windows.Forms.UserControl WinFormsControl = new System.Windows.Forms.UserControl();
public static IntPtr DefaultParentWindow = WinFormsControl.Handle;
protected override IntPtr CreateWindowOverride(ushort atom)
{
var hWnd = UnmanagedMethods.CreateWindowEx(
0,
atom,
null,
(int)UnmanagedMethods.WindowStyles.WS_CHILD,
0,
0,
640,
480,
DefaultParentWindow,
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero);
return hWnd;
}
protected override IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if(msg == (uint)UnmanagedMethods.WindowsMessage.WM_KILLFOCUS)
LostFocus?.Invoke();
return base.WndProc(hWnd, msg, wParam, lParam);
}
public event Action LostFocus;
}
}

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

@ -196,13 +196,9 @@ namespace Avalonia.Win32
public IEmbeddableWindowImpl CreateEmbeddableWindow()
{
#if NETSTANDARD
throw new NotSupportedException();
#else
var embedded = new EmbeddedWindowImpl();
embedded.Show();
return embedded;
#endif
}
public IPopupImpl CreatePopup()

35
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;
}
}
}

Loading…
Cancel
Save