using System; using System.Runtime.InteropServices; using System.Security.Cryptography; 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; using Avalonia.Platform.Interop; namespace Avalonia.Native { class AvaloniaNativePlatform : IPlatformSettings, 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 public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options) { var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor(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(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; _factory.Initialize(new GCHandleDeallocator()); if (_factory.MacOptions != null) { var macOpts = AvaloniaLocator.Current.GetService(); _factory.MacOptions.SetShowInDock(macOpts?.ShowInDock != false ? 1 : 0); } AvaloniaLocator.CurrentMutable .Bind() .ToConstant(new PlatformThreadingInterface(_factory.CreatePlatformThreadingInterface())) .Bind().ToConstant(new CursorFactory(_factory.CreateCursorFactory())) .Bind().ToSingleton() .Bind().ToConstant(KeyboardDevice) .Bind().ToConstant(this) .Bind().ToConstant(this) .Bind().ToConstant(new ClipboardImpl(_factory.CreateClipboard())) .Bind().ToConstant(new RenderLoop()) .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToConstant(new SystemDialogs(_factory.CreateSystemDialogs())) .Bind().ToConstant(new PlatformHotkeyConfiguration(KeyModifiers.Meta)) .Bind().ToConstant(new MacOSMountedVolumeInfoProvider()) .Bind().ToConstant(new AvaloniaNativeDragSource(_factory)); if (_options.UseGpu) { try { AvaloniaLocator.CurrentMutable.Bind() .ToConstant(_platformGl = new AvaloniaNativePlatformOpenGlInterface(_factory.ObtainGlDisplay())); } catch (Exception) { // ignored } } } 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); } } } }