A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

179 lines
6.9 KiB

using System;
using System.Runtime.InteropServices;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.MicroCom;
using Avalonia.Native.Interop;
using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Rendering;
namespace Avalonia.Native
{
class AvaloniaNativePlatform : IPlatformSettings, ITouchPlatformSettings, IWindowingPlatform
{
private readonly IAvaloniaNativeFactory _factory;
private AvaloniaNativePlatformOptions _options;
private AvaloniaNativePlatformOpenGlInterface _platformGl;
[DllImport("libAvaloniaNative")]
static extern IntPtr CreateAvaloniaNative();
internal static readonly KeyboardDevice KeyboardDevice = new KeyboardDevice();
public Size DoubleClickSize => new Size(4, 4);
public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(500); //TODO
/// <inheritdoc cref="ITouchPlatformSettings.TouchDoubleClickSize"/>
public Size TouchDoubleClickSize => new Size(16, 16);
/// <inheritdoc cref="ITouchPlatformSettings.TouchDoubleClickTime"/>
public TimeSpan TouchDoubleClickTime => DoubleClickTime;
public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
{
var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true));
result.DoInitialize(options);
return result;
}
delegate IntPtr CreateAvaloniaNativeDelegate();
public static AvaloniaNativePlatform Initialize(AvaloniaNativePlatformOptions options)
{
if (options.AvaloniaNativeLibraryPath != null)
{
var loader = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ?
(IDynLoader)new Win32Loader() :
new UnixLoader();
var lib = loader.LoadLibrary(options.AvaloniaNativeLibraryPath);
var proc = loader.GetProcAddress(lib, "CreateAvaloniaNative", false);
var d = Marshal.GetDelegateForFunctionPointer<CreateAvaloniaNativeDelegate>(proc);
return Initialize(d(), options);
}
else
return Initialize(CreateAvaloniaNative(), options);
}
public void SetupApplicationMenuExporter()
{
var exporter = new AvaloniaNativeMenuExporter(_factory);
}
public void SetupApplicationName()
{
if (!string.IsNullOrWhiteSpace(Application.Current.Name))
{
_factory.MacOptions.SetApplicationTitle(Application.Current.Name);
}
}
private AvaloniaNativePlatform(IAvaloniaNativeFactory factory)
{
_factory = factory;
}
class GCHandleDeallocator : CallbackBase, IAvnGCHandleDeallocatorCallback
{
public void FreeGCHandle(IntPtr handle)
{
GCHandle.FromIntPtr(handle).Free();
}
}
void DoInitialize(AvaloniaNativePlatformOptions options)
{
_options = options;
var applicationPlatform = new AvaloniaNativeApplicationPlatform();
_factory.Initialize(new GCHandleDeallocator(), applicationPlatform);
if (_factory.MacOptions != null)
{
var macOpts = AvaloniaLocator.Current.GetService<MacOSPlatformOptions>();
_factory.MacOptions.SetShowInDock(macOpts?.ShowInDock != false ? 1 : 0);
}
AvaloniaLocator.CurrentMutable
.Bind<IPlatformThreadingInterface>()
.ToConstant(new PlatformThreadingInterface(_factory.CreatePlatformThreadingInterface()))
.Bind<ICursorFactory>().ToConstant(new CursorFactory(_factory.CreateCursorFactory()))
.Bind<IPlatformIconLoader>().ToSingleton<IconLoader>()
.Bind<IKeyboardDevice>().ToConstant(KeyboardDevice)
.Bind<IPlatformSettings>().ToConstant(this)
.Bind<ITouchPlatformSettings>().ToConstant(this)
.Bind<IWindowingPlatform>().ToConstant(this)
.Bind<IClipboard>().ToConstant(new ClipboardImpl(_factory.CreateClipboard()))
.Bind<IRenderLoop>().ToConstant(new RenderLoop())
.Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))
.Bind<ISystemDialogImpl>().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs()))
.Bind<PlatformHotkeyConfiguration>().ToConstant(new PlatformHotkeyConfiguration(KeyModifiers.Meta, wholeWordTextActionModifiers: KeyModifiers.Alt))
.Bind<IMountedVolumeInfoProvider>().ToConstant(new MacOSMountedVolumeInfoProvider())
.Bind<IPlatformDragSource>().ToConstant(new AvaloniaNativeDragSource(_factory))
.Bind<IPlatformLifetimeEventsImpl>().ToConstant(applicationPlatform)
.Bind<INativeApplicationCommands>().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands()));
var hotkeys = AvaloniaLocator.Current.GetService<PlatformHotkeyConfiguration>();
hotkeys.MoveCursorToTheStartOfLine.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers));
hotkeys.MoveCursorToTheStartOfLineWithSelection.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
hotkeys.MoveCursorToTheEndOfLine.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers));
hotkeys.MoveCursorToTheEndOfLineWithSelection.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers | hotkeys.SelectionModifiers));
if (_options.UseGpu)
{
try
{
AvaloniaLocator.CurrentMutable.Bind<IPlatformOpenGlInterface>()
.ToConstant(_platformGl = new AvaloniaNativePlatformOpenGlInterface(_factory.ObtainGlDisplay()));
}
catch (Exception)
{
// ignored
}
}
}
public ITrayIconImpl CreateTrayIcon()
{
return new TrayIconImpl(_factory);
}
public IWindowImpl CreateWindow()
{
return new WindowImpl(_factory, _options, _platformGl);
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
}
public class AvaloniaNativeMacOptions
{
private readonly IAvnMacOptions _opts;
private bool _showInDock;
internal AvaloniaNativeMacOptions(IAvnMacOptions opts)
{
_opts = opts;
ShowInDock = true;
}
public bool ShowInDock
{
get => _showInDock;
set
{
_showInDock = value;
_opts.SetShowInDock(value ? 1 : 0);
}
}
}
}