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.Rendering;
#nullable enable
namespace Avalonia.Native
{
class AvaloniaNativePlatform : IPlatformSettings, IWindowingPlatform
{
private readonly IAvaloniaNativeFactory _factory;
private AvaloniaNativePlatformOptions _options;
private AvaloniaNativePlatformOpenGlInterface _platformGl;
private AvaloniaNativePlatformOpenGlInterface? _platformGl;
[DllImport("libAvaloniaNative")]
static extern IntPtr CreateAvaloniaNative();
@ -28,8 +30,8 @@ namespace Avalonia.Native
public static AvaloniaNativePlatform Initialize(IntPtr factory, AvaloniaNativePlatformOptions options)
{
var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true));
result.DoInitialize(options);
var result = new AvaloniaNativePlatform(MicroComRuntime.CreateProxyFor<IAvaloniaNativeFactory>(factory, true), options);
result.DoInitialize();
return result;
}
@ -62,15 +64,20 @@ namespace Avalonia.Native
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;
_options = options;
}
class GCHandleDeallocator : CallbackBase, IAvnGCHandleDeallocatorCallback
@ -81,10 +88,8 @@ namespace Avalonia.Native
}
}
void DoInitialize(AvaloniaNativePlatformOptions options)
void DoInitialize()
{
_options = options;
var applicationPlatform = new AvaloniaNativeApplicationPlatform();
_factory.Initialize(new GCHandleDeallocator(), applicationPlatform);
@ -114,11 +119,17 @@ namespace Avalonia.Native
.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 (hotkeys != null)
{
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

27
src/Avalonia.Native/WindowImpl.cs

@ -1,13 +1,12 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Native.Interop;
using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
#nullable enable
namespace Avalonia.Native
{
@ -15,14 +14,14 @@ namespace Avalonia.Native
{
private readonly IAvaloniaNativeFactory _factory;
private readonly AvaloniaNativePlatformOptions _opts;
private readonly AvaloniaNativePlatformOpenGlInterface _glFeature;
private readonly AvaloniaNativePlatformOpenGlInterface? _glFeature;
IAvnWindow _native;
private double _extendTitleBarHeight = -1;
private DoubleClickHelper _doubleClickHelper;
internal WindowImpl(IAvaloniaNativeFactory factory, AvaloniaNativePlatformOptions opts,
AvaloniaNativePlatformOpenGlInterface glFeature) : base(opts, glFeature)
AvaloniaNativePlatformOpenGlInterface? glFeature) : base(opts, glFeature)
{
_factory = factory;
_opts = opts;
@ -82,12 +81,12 @@ namespace Avalonia.Native
_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 });
}
public void SetTitle(string title)
public void SetTitle(string? title)
{
_native.SetTitle(title ?? "");
}
@ -98,9 +97,9 @@ namespace Avalonia.Native
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; }
@ -113,9 +112,9 @@ namespace Avalonia.Native
{
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))
{
@ -203,16 +202,16 @@ namespace Avalonia.Native
// NO OP on OSX
}
public Func<bool> Closing { get; set; }
public Func<bool>? Closing { get; set; }
public ITopLevelNativeMenuExporter NativeMenuExporter { get; }
public void Move(PixelPoint point) => Position = point;
public override IPopupImpl CreatePopup() =>
public override IPopupImpl? CreatePopup() =>
_opts.OverlayPopups ? null : new PopupImpl(_factory, _opts, _glFeature, this);
public Action GotInputWhenDisabled { get; set; }
public Action? GotInputWhenDisabled { get; set; }
public void SetParent(IWindowImpl parent)
{

114
src/Avalonia.Native/WindowImplBase.cs

@ -13,11 +13,13 @@ using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Threading;
#nullable enable
namespace Avalonia.Native
{
internal class MacOSTopLevelWindowHandle : IPlatformHandle, IMacOSTopLevelPlatformHandle
{
IAvnWindowBase _native;
private readonly IAvnWindowBase _native;
public MacOSTopLevelWindowHandle(IAvnWindowBase native)
{
@ -28,50 +30,55 @@ namespace Avalonia.Native
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()
{
return _native?.ObtainNSViewHandleRetained() ?? IntPtr.Zero;
return _native.ObtainNSViewHandleRetained();
}
public IntPtr GetNSWindowRetained()
{
return _native?.ObtainNSWindowHandleRetained() ?? IntPtr.Zero;
return _native.ObtainNSWindowHandleRetained();
}
}
internal abstract class WindowBaseImpl : IWindowBaseImpl,
IFramebufferPlatformSurface, ITopLevelImplWithNativeControlHost
{
protected IInputRoot _inputRoot;
IAvnWindowBase _native;
private object _syncRoot = new object();
private bool _deferredRendering = false;
private bool _gpu = false;
protected IInputRoot? _inputRoot;
IAvnWindowBase? _native;
private object _syncRoot = new();
private bool _deferredRendering;
private bool _gpu;
private readonly MouseDevice _mouse;
private readonly IKeyboardDevice _keyboard;
private readonly ICursorFactory _cursorFactory;
private Size _savedLogicalSize;
private Size _lastRenderedLogicalSize;
private double _savedScaling;
private GlPlatformSurface _glSurface;
private NativeControlHostImpl _nativeControlHost;
private IGlContext _glContext;
private GlPlatformSurface? _glSurface;
private NativeControlHostImpl? _nativeControlHost;
private IGlContext? _glContext;
internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, AvaloniaNativePlatformOpenGlInterface glFeature)
internal WindowBaseImpl(AvaloniaNativePlatformOptions opts, AvaloniaNativePlatformOpenGlInterface? glFeature)
{
_gpu = opts.UseGpu && glFeature != null;
_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();
_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;
_glContext = glContext;
@ -85,7 +92,7 @@ namespace Avalonia.Native
_nativeControlHost = new NativeControlHostImpl(_native.CreateNativeControlHost());
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);
}
@ -137,19 +144,18 @@ namespace Avalonia.Native
if (_native == null)
return false;
cb(_native);
_lastRenderedLogicalSize = _savedLogicalSize;
return true;
}
}, (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<Size, PlatformResizeReason> Resized { get; set; }
public Action Closed { get; set; }
public Action<Rect>? Paint { get; set; }
public Action<Size, PlatformResizeReason>? Resized { get; set; }
public Action? Closed { get; set; }
public IMouseDevice MouseDevice => _mouse;
public abstract IPopupImpl CreatePopup();
public abstract IPopupImpl? CreatePopup();
protected unsafe class WindowBaseEvents : CallbackBase, IAvnWindowBaseEvents
{
@ -165,12 +171,12 @@ namespace Avalonia.Native
var n = _parent._native;
try
{
_parent?.Closed?.Invoke();
_parent.Closed?.Invoke();
}
finally
{
_parent?.Dispose();
_parent.Dispose();
n?.Dispose();
}
}
@ -188,7 +194,7 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.Resized(AvnSize* size, AvnPlatformResizeReason reason)
{
if (_parent?._native != null)
if (_parent._native != null)
{
var s = new Size(size->Width, size->Height);
_parent._savedLogicalSize = s;
@ -240,21 +246,26 @@ namespace Avalonia.Native
{
var device = AvaloniaLocator.Current.GetService<IDragDropDevice>();
IDataObject dataObject = null;
if (dataObjectHandle != IntPtr.Zero)
dataObject = GCHandle.FromIntPtr(dataObjectHandle).Target as IDataObject;
using(var clipboardDataObject = new ClipboardDataObject(clipboard))
if (device != null && _parent._inputRoot != null)
{
if (dataObject == null)
dataObject = clipboardDataObject;
var args = new RawDragEvent(device, (RawDragEventType)type,
_parent._inputRoot, position.ToAvaloniaPoint(), dataObject, (DragDropEffects)effects,
(RawInputModifiers)modifiers);
_parent.Input(args);
return (AvnDragDropEffects)args.Effects;
IDataObject? dataObject = null;
if (dataObjectHandle != IntPtr.Zero)
dataObject = GCHandle.FromIntPtr(dataObjectHandle).Target as IDataObject;
using (var clipboardDataObject = new ClipboardDataObject(clipboard))
{
if (dataObject == null)
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();
}
public bool RawTextInputEvent(uint timeStamp, string text)
{
if (_inputRoot is null)
@ -409,8 +421,8 @@ namespace Avalonia.Native
public double DesktopScaling => 1;
public Action Deactivated { get; set; }
public Action Activated { get; set; }
public Action? Deactivated { get; set; }
public Action? Activated { get; set; }
public void SetCursor(ICursorImpl cursor)
{
@ -420,19 +432,21 @@ namespace Avalonia.Native
}
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

Loading…
Cancel
Save