Browse Source

Merge pull request #8035 from AvaloniaUI/fixes/nullable-avalonia-native

Fixes/nullable avalonia native
release/0.10.14
Max Katz 4 years ago
committed by GitHub
parent
commit
471aa2881c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 39
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  2. 27
      src/Avalonia.Native/WindowImpl.cs
  3. 114
      src/Avalonia.Native/WindowImplBase.cs

39
src/Avalonia.Native/AvaloniaNativePlatform.cs

@ -9,13 +9,15 @@ using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
#nullable enable
namespace Avalonia.Native namespace Avalonia.Native
{ {
class AvaloniaNativePlatform : IPlatformSettings, IWindowingPlatform class AvaloniaNativePlatform : IPlatformSettings, IWindowingPlatform
{ {
private readonly IAvaloniaNativeFactory _factory; private readonly IAvaloniaNativeFactory _factory;
private AvaloniaNativePlatformOptions _options; private AvaloniaNativePlatformOptions _options;
private AvaloniaNativePlatformOpenGlInterface _platformGl; private AvaloniaNativePlatformOpenGlInterface? _platformGl;
[DllImport("libAvaloniaNative")] [DllImport("libAvaloniaNative")]
static extern IntPtr CreateAvaloniaNative(); static extern IntPtr CreateAvaloniaNative();
@ -28,8 +30,8 @@ namespace Avalonia.Native
public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options) public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
{ {
var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true)); var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true), options);
result.DoInitialize(options); result.DoInitialize();
return result; return result;
} }
@ -62,15 +64,20 @@ namespace Avalonia.Native
public void SetupApplicationName () public void SetupApplicationName ()
{ {
if(!string.IsNullOrWhiteSpace(Application.Current.Name)) if(!string.IsNullOrWhiteSpace(Application.Current?.Name))
{
_factory.MacOptions.SetApplicationTitle(Application.Current?.Name);
}
else
{ {
_factory.MacOptions.SetApplicationTitle(Application.Current.Name); _factory.MacOptions.SetApplicationTitle("");
} }
} }
private AvaloniaNativePlatform(IAvaloniaNativeFactory factory) private AvaloniaNativePlatform(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions options)
{ {
_factory = factory; _factory = factory;
_options = options;
} }
class GCHandleDeallocator : CallbackBase, IAvnGCHandleDeallocatorCallback class GCHandleDeallocator : CallbackBase, IAvnGCHandleDeallocatorCallback
@ -81,10 +88,8 @@ namespace Avalonia.Native
} }
} }
void DoInitialize(AvaloniaNativePlatformOptions options) void DoInitialize()
{ {
_options = options;
var applicationPlatform = new AvaloniaNativeApplicationPlatform(); var applicationPlatform = new AvaloniaNativeApplicationPlatform();
_factory.Initialize(new GCHandleDeallocator(), applicationPlatform); _factory.Initialize(new GCHandleDeallocator(), applicationPlatform);
@ -114,11 +119,17 @@ namespace Avalonia.Native
.Bind<INativeApplicationCommands>().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands())); .Bind<INativeApplicationCommands>().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands()));
var hotkeys = AvaloniaLocator.Current.GetService<PlatformHotkeyConfiguration>(); 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)); if (hotkeys != null)
hotkeys.MoveCursorToTheEndOfLine.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers)); {
hotkeys.MoveCursorToTheEndOfLineWithSelection.Add(new KeyGesture(Key.Right, hotkeys.CommandModifiers | hotkeys.SelectionModifiers)); 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) if (_options.UseGpu)
{ {
try try

27
src/Avalonia.Native/WindowImpl.cs

@ -1,13 +1,12 @@
using System; using System;
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Raw; using Avalonia.Input.Raw;
using Avalonia.Native.Interop; using Avalonia.Native.Interop;
using Avalonia.OpenGL;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Platform.Interop;
#nullable enable
namespace Avalonia.Native namespace Avalonia.Native
{ {
@ -15,14 +14,14 @@ namespace Avalonia.Native
{ {
private readonly IAvaloniaNativeFactory _factory; private readonly IAvaloniaNativeFactory _factory;
private readonly AvaloniaNativePlatformOptions _opts; private readonly AvaloniaNativePlatformOptions _opts;
private readonly AvaloniaNativePlatformOpenGlInterface _glFeature; private readonly AvaloniaNativePlatformOpenGlInterface? _glFeature;
IAvnWindow _native; IAvnWindow _native;
private double _extendTitleBarHeight = -1; private double _extendTitleBarHeight = -1;
private DoubleClickHelper _doubleClickHelper; private DoubleClickHelper _doubleClickHelper;
internal WindowImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts, internal WindowImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts,
AvaloniaNativePlatformOpenGlInterface glFeature) : base(opts, glFeature) AvaloniaNativePlatformOpenGlInterface? glFeature) : base(opts, glFeature)
{ {
_factory = factory; _factory = factory;
_opts = opts; _opts = opts;
@ -82,12 +81,12 @@ namespace Avalonia.Native
_native.SetDecorations((Interop.SystemDecorations)enabled); _native.SetDecorations((Interop.SystemDecorations)enabled);
} }
public void SetTitleBarColor(Avalonia.Media.Color color) public void SetTitleBarColor(Media.Color color)
{ {
_native.SetTitleBarColor(new AvnColor { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B }); _native.SetTitleBarColor(new AvnColor { Alpha = color.A, Red = color.R, Green = color.G, Blue = color.B });
} }
public void SetTitle(string title) public void SetTitle(string? title)
{ {
_native.SetTitle(title ?? ""); _native.SetTitle(title ?? "");
} }
@ -98,9 +97,9 @@ namespace Avalonia.Native
set => _native.SetWindowState((AvnWindowState)value); set => _native.SetWindowState((AvnWindowState)value);
} }
public Action<WindowState> WindowStateChanged { get; set; } public Action<WindowState>? WindowStateChanged { get; set; }
public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; } public Action<bool>? ExtendClientAreaToDecorationsChanged { get; set; }
public Thickness ExtendedMargins { get; private set; } public Thickness ExtendedMargins { get; private set; }
@ -113,9 +112,9 @@ namespace Avalonia.Native
{ {
if(_isExtended) if(_isExtended)
{ {
if(e.Type == RawPointerEventType.LeftButtonDown) if(e.Type == RawPointerEventType.LeftButtonDown && _inputRoot is Window window)
{ {
var visual = (_inputRoot as Window).Renderer.HitTestFirst(e.Position, _inputRoot as Window, x => var visual = window.Renderer.HitTestFirst(e.Position, _inputRoot as Window, x =>
{ {
if (x is IInputElement ie && (!ie.IsHitTestVisible || !ie.IsVisible)) if (x is IInputElement ie && (!ie.IsHitTestVisible || !ie.IsVisible))
{ {
@ -203,16 +202,16 @@ namespace Avalonia.Native
// NO OP on OSX // NO OP on OSX
} }
public Func<bool> Closing { get; set; } public Func<bool>? Closing { get; set; }
public ITopLevelNativeMenuExporter NativeMenuExporter { get; } public ITopLevelNativeMenuExporter NativeMenuExporter { get; }
public void Move(PixelPoint point) => Position = point; public void Move(PixelPoint point) => Position = point;
public override IPopupImpl CreatePopup() => public override IPopupImpl? CreatePopup() =>
_opts.OverlayPopups ? null : new PopupImpl(_factory, _opts, _glFeature, this); _opts.OverlayPopups ? null : new PopupImpl(_factory, _opts, _glFeature, this);
public Action GotInputWhenDisabled { get; set; } public Action? GotInputWhenDisabled { get; set; }
public void SetParent(IWindowImpl parent) public void SetParent(IWindowImpl parent)
{ {

114
src/Avalonia.Native/WindowImplBase.cs

@ -13,11 +13,13 @@ using Avalonia.Platform;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Threading; using Avalonia.Threading;
#nullable enable
namespace Avalonia.Native namespace Avalonia.Native
{ {
internal class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle internal class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle
{ {
IAvnWindowBase _native; private readonly IAvnWindowBase _native;
public MacOSTopLevelWindowHandle(IAvnWindowBase native) public MacOSTopLevelWindowHandle(IAvnWindowBase native)
{ {
@ -28,50 +30,55 @@ namespace Avalonia.Native
public string HandleDescriptor => "NSWindow"; public string HandleDescriptor => "NSWindow";
public IntPtr NSView => _native?.ObtainNSViewHandle() ?? IntPtr.Zero; public IntPtr NSView => _native.ObtainNSViewHandle();
public IntPtr NSWindow => _native?.ObtainNSWindowHandle() ?? IntPtr.Zero; public IntPtr NSWindow => _native.ObtainNSWindowHandle();
public IntPtr GetNSViewRetained() public IntPtr GetNSViewRetained()
{ {
return _native?.ObtainNSViewHandleRetained() ?? IntPtr.Zero; return _native.ObtainNSViewHandleRetained();
} }
public IntPtr GetNSWindowRetained() public IntPtr GetNSWindowRetained()
{ {
return _native?.ObtainNSWindowHandleRetained() ?? IntPtr.Zero; return _native.ObtainNSWindowHandleRetained();
} }
} }
internal abstract class WindowBaseImpl : IWindowBaseImpl, internal abstract class WindowBaseImpl : IWindowBaseImpl,
IFramebufferPlatformSurface, ITopLevelImplWithNativeControlHost IFramebufferPlatformSurface, ITopLevelImplWithNativeControlHost
{ {
protected IInputRoot _inputRoot; protected IInputRoot? _inputRoot;
IAvnWindowBase _native; IAvnWindowBase? _native;
private object _syncRoot = new object(); private object _syncRoot = new();
private bool _deferredRendering = false; private bool _deferredRendering;
private bool _gpu = false; private bool _gpu;
private readonly MouseDevice _mouse; private readonly MouseDevice _mouse;
private readonly IKeyboardDevice _keyboard; private readonly IKeyboardDevice _keyboard;
private readonly ICursorFactory _cursorFactory; private readonly ICursorFactory _cursorFactory;
private Size _savedLogicalSize; private Size _savedLogicalSize;
private Size _lastRenderedLogicalSize;
private double _savedScaling; private double _savedScaling;
private GlPlatformSurface _glSurface; private GlPlatformSurface? _glSurface;
private NativeControlHostImpl _nativeControlHost; private NativeControlHostImpl? _nativeControlHost;
private IGlContext _glContext; private IGlContext? _glContext;
internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, AvaloniaNativePlatformOpenGlInterface glFeature) internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, AvaloniaNativePlatformOpenGlInterface? glFeature)
{ {
_gpu = opts.UseGpu && glFeature != null; _gpu = opts.UseGpu && glFeature != null;
_deferredRendering = opts.UseDeferredRendering; _deferredRendering = opts.UseDeferredRendering;
_keyboard = AvaloniaLocator.Current.GetService<IKeyboardDevice>(); var keyboardDevice = AvaloniaLocator.Current.GetService<IKeyboardDevice>();
_keyboard = keyboardDevice ?? throw new Exception("Invalid configuration, missing IKeyboardDevice");
_mouse = new MouseDevice(); _mouse = new MouseDevice();
_cursorFactory = AvaloniaLocator.Current.GetService<ICursorFactory>();
var cursorFactory = AvaloniaLocator.Current.GetService<ICursorFactory>();
_cursorFactory = cursorFactory ?? throw new Exception("Invalid configuration, missing ICursorFactory");
} }
protected void Init(IAvnWindowBase window, IAvnScreens screens, IGlContext glContext) protected void Init(IAvnWindowBase window, IAvnScreens screens, IGlContext? glContext)
{ {
_native = window; _native = window;
_glContext = glContext; _glContext = glContext;
@ -85,7 +92,7 @@ namespace Avalonia.Native
_nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost()); _nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost());
var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity) var monitor = Screen.AllScreens.OrderBy(x => x.PixelDensity)
.FirstOrDefault(m => m.Bounds.Contains(Position)); .First(m => m.Bounds.Contains(Position));
Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), PlatformResizeReason.Layout); Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), PlatformResizeReason.Layout);
} }
@ -137,19 +144,18 @@ namespace Avalonia.Native
if (_native == null) if (_native == null)
return false; return false;
cb(_native); cb(_native);
_lastRenderedLogicalSize = _savedLogicalSize;
return true; return true;
} }
}, (int)w, (int)h, new Vector(dpi, dpi)); }, (int)w, (int)h, new Vector(dpi, dpi));
} }
public Action LostFocus { get; set; } public Action? LostFocus { get; set; }
public Action<Rect> Paint { get; set; } public Action<Rect>? Paint { get; set; }
public Action<Size, PlatformResizeReason> Resized { get; set; } public Action<Size, PlatformResizeReason>? Resized { get; set; }
public Action Closed { get; set; } public Action? Closed { get; set; }
public IMouseDevice MouseDevice => _mouse; public IMouseDevice MouseDevice => _mouse;
public abstract IPopupImpl CreatePopup(); public abstract IPopupImpl? CreatePopup();
protected unsafe class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents protected unsafe class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents
{ {
@ -165,12 +171,12 @@ namespace Avalonia.Native
var n = _parent._native; var n = _parent._native;
try try
{ {
_parent?.Closed?.Invoke(); _parent.Closed?.Invoke();
} }
finally finally
{ {
_parent?.Dispose(); _parent.Dispose();
n?.Dispose(); n?.Dispose();
} }
} }
@ -188,7 +194,7 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.Resized(AvnSize* size, AvnPlatformResizeReason reason) void IAvnWindowBaseEvents.Resized(AvnSize* size, AvnPlatformResizeReason reason)
{ {
if (_parent?._native != null) if (_parent._native != null)
{ {
var s = new Size(size->Width, size->Height); var s = new Size(size->Width, size->Height);
_parent._savedLogicalSize = s; _parent._savedLogicalSize = s;
@ -240,21 +246,26 @@ namespace Avalonia.Native
{ {
var device = AvaloniaLocator.Current.GetService<IDragDropDevice>(); var device = AvaloniaLocator.Current.GetService<IDragDropDevice>();
IDataObject dataObject = null; if (device != null && _parent._inputRoot != null)
if (dataObjectHandle != IntPtr.Zero)
dataObject = GCHandle.FromIntPtr(dataObjectHandle).Target as IDataObject;
using(var clipboardDataObject = new ClipboardDataObject(clipboard))
{ {
if (dataObject == null) IDataObject? dataObject = null;
dataObject = clipboardDataObject; if (dataObjectHandle != IntPtr.Zero)
dataObject = GCHandle.FromIntPtr(dataObjectHandle).Target as IDataObject;
var args = new RawDragEvent(device, (RawDragEventType)type,
_parent._inputRoot, position.ToAvaloniaPoint(), dataObject, (DragDropEffects)effects, using (var clipboardDataObject = new ClipboardDataObject(clipboard))
(RawInputModifiers)modifiers); {
_parent.Input(args); if (dataObject == null)
return (AvnDragDropEffects)args.Effects; dataObject = clipboardDataObject;
var args = new RawDragEvent(device, (RawDragEventType)type,
_parent._inputRoot, position.ToAvaloniaPoint(), dataObject, (DragDropEffects)effects,
(RawInputModifiers)modifiers);
_parent.Input?.Invoke(args);
return (AvnDragDropEffects)args.Effects;
}
} }
return AvnDragDropEffects.None;
} }
} }
@ -263,6 +274,7 @@ namespace Avalonia.Native
_native?.Activate(); _native?.Activate();
} }
public bool RawTextInputEvent(uint timeStamp, string text) public bool RawTextInputEvent(uint timeStamp, string text)
{ {
if (_inputRoot is null) if (_inputRoot is null)
@ -409,8 +421,8 @@ namespace Avalonia.Native
public double DesktopScaling => 1; public double DesktopScaling => 1;
public Action Deactivated { get; set; } public Action? Deactivated { get; set; }
public Action Activated { get; set; } public Action? Activated { get; set; }
public void SetCursor(ICursorImpl cursor) public void SetCursor(ICursorImpl cursor)
{ {
@ -420,19 +432,21 @@ namespace Avalonia.Native
} }
var newCursor = cursor as AvaloniaNativeCursor; var newCursor = cursor as AvaloniaNativeCursor;
newCursor = newCursor ?? (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor);
_native.SetCursor(newCursor.Cursor); newCursor ??= (_cursorFactory.GetCursor(StandardCursorType.Arrow) as AvaloniaNativeCursor);
_native.SetCursor(newCursor?.Cursor);
} }
public Action<PixelPoint> PositionChanged { get; set; } public Action<PixelPoint>? PositionChanged { get; set; }
public Action<RawInputEventArgs> Input { get; set; } public Action<RawInputEventArgs>? Input { get; set; }
public Action<double> ScalingChanged { get; set; } public Action<double>? ScalingChanged { get; set; }
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; } public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
public IScreenImpl Screen { get; private set; } public IScreenImpl? Screen { get; private set; }
// TODO // TODO

Loading…
Cancel
Save