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, 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 Size TouchDoubleClickSize => new Size(16, 16); /// public TimeSpan TouchDoubleClickTime => DoubleClickTime; 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; var applicationPlatform = new AvaloniaNativeApplicationPlatform(); _factory.Initialize(new GCHandleDeallocator(), applicationPlatform); if (_factory.MacOptions != null) { var macOpts = AvaloniaLocator.Current.GetService() ?? new MacOSPlatformOptions(); _factory.MacOptions.SetShowInDock(macOpts.ShowInDock ? 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, wholeWordTextActionModifiers: KeyModifiers.Alt)) .Bind().ToConstant(new MacOSMountedVolumeInfoProvider()) .Bind().ToConstant(new AvaloniaNativeDragSource(_factory)) .Bind().ToConstant(applicationPlatform) .Bind().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands())); var hotkeys = AvaloniaLocator.Current.GetService(); 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() .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); } } } }