diff --git a/src/Avalonia.Native/Avalonia.Native.csproj b/src/Avalonia.Native/Avalonia.Native.csproj index 123ac83c65..2eb67fe5dd 100644 --- a/src/Avalonia.Native/Avalonia.Native.csproj +++ b/src/Avalonia.Native/Avalonia.Native.csproj @@ -27,4 +27,5 @@ + diff --git a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs index ea64f0d93b..68e0c5dce6 100644 --- a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs @@ -12,11 +12,11 @@ namespace Avalonia.Native { internal class AvaloniaNativeApplicationPlatform : NativeCallbackBase, IAvnApplicationEvents, IPlatformLifetimeEventsImpl { - public event EventHandler ShutdownRequested; + public event EventHandler? ShutdownRequested; void IAvnApplicationEvents.FilesOpened(IAvnStringArray urls) { - ((IApplicationPlatformEvents)Application.Current)?.RaiseUrlsOpened(urls.ToStringArray()); + ((IApplicationPlatformEvents?)Application.Current)?.RaiseUrlsOpened(urls.ToStringArray()); if (AvaloniaLocator.Current.GetService() is ActivatableLifetimeBase lifetime && AvaloniaLocator.Current.GetService() is StorageProviderApi storageApi) @@ -42,7 +42,7 @@ namespace Avalonia.Native void IAvnApplicationEvents.UrlsOpened(IAvnStringArray urls) { // Raise the urls opened event to be compatible with legacy behavior. - ((IApplicationPlatformEvents)Application.Current)?.RaiseUrlsOpened(urls.ToStringArray()); + ((IApplicationPlatformEvents?)Application.Current)?.RaiseUrlsOpened(urls.ToStringArray()); if (AvaloniaLocator.Current.GetService() is ActivatableLifetimeBase lifetime && AvaloniaLocator.Current.GetService() is StorageProviderApi storageApi) diff --git a/src/Avalonia.Native/AvaloniaNativeDragSource.cs b/src/Avalonia.Native/AvaloniaNativeDragSource.cs index 3bccdeac73..3c9397f8cc 100644 --- a/src/Avalonia.Native/AvaloniaNativeDragSource.cs +++ b/src/Avalonia.Native/AvaloniaNativeDragSource.cs @@ -19,7 +19,7 @@ namespace Avalonia.Native class DndCallback : NativeCallbackBase, IAvnDndResultCallback { - private TaskCompletionSource _tcs; + private TaskCompletionSource? _tcs; public DndCallback(TaskCompletionSource tcs) { diff --git a/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs b/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs index ae5abf2655..2a6a1f16c7 100644 --- a/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs +++ b/src/Avalonia.Native/AvaloniaNativeGlPlatformGraphics.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Avalonia.OpenGL; using Avalonia.Native.Interop; @@ -90,12 +91,12 @@ namespace Avalonia.Native class GlContext : IGlContext { private readonly GlDisplay _display; - private readonly GlContext _sharedWith; + private readonly GlContext? _sharedWith; private readonly GpuHandleWrapFeature _handleWrapFeature; private readonly GlExternalObjectsFeature _externalObjects; - public IAvnGlContext Context { get; private set; } + public IAvnGlContext? Context { get; private set; } - public GlContext(GlDisplay display, GlContext sharedWith, IAvnGlContext context, GlVersion version) + public GlContext(GlDisplay display, GlContext? sharedWith, IAvnGlContext context, GlVersion version) { _display = display; _sharedWith = sharedWith; @@ -109,14 +110,25 @@ namespace Avalonia.Native public GlInterface GlInterface => _display.GlInterface; public int SampleCount => _display.SampleCount; public int StencilSize => _display.StencilSize; - public IDisposable MakeCurrent() + + [MemberNotNull(nameof(Context))] + public void ThrowIfLost() { if (IsLost) throw new PlatformGraphicsContextLostException(); + } + + [MemberNotNull(nameof(Context))] + public IDisposable MakeCurrent() + { + ThrowIfLost(); return Context.MakeCurrent(); } + [MemberNotNullWhen(false, nameof(Context))] public bool IsLost => Context == null; + + [MemberNotNull(nameof(Context))] public IDisposable EnsureCurrent() => MakeCurrent(); public bool IsSharedWith(IGlContext context) @@ -130,16 +142,16 @@ namespace Avalonia.Native public bool CanCreateSharedContext => true; - public IGlContext CreateSharedContext(IEnumerable preferredVersions = null) => + public IGlContext CreateSharedContext(IEnumerable? preferredVersions = null) => _display.CreateSharedContext(_sharedWith ?? this); public void Dispose() { - Context.Dispose(); + Context?.Dispose(); Context = null; } - public object TryGetFeature(Type featureType) + public object? TryGetFeature(Type featureType) { if (featureType == typeof(IExternalObjectsHandleWrapRenderInterfaceContextFeature)) return _handleWrapFeature; @@ -152,7 +164,7 @@ namespace Avalonia.Native class GlPlatformSurfaceRenderTarget : IGlPlatformSurfaceRenderTarget { - private IAvnGlSurfaceRenderTarget _target; + private IAvnGlSurfaceRenderTarget? _target; private readonly IGlContext _context; public GlPlatformSurfaceRenderTarget(IAvnGlSurfaceRenderTarget target, IGlContext context) @@ -163,6 +175,7 @@ namespace Avalonia.Native public IGlPlatformSurfaceRenderingSession BeginDraw() { + ObjectDisposedException.ThrowIf(_target is null, this); return new GlPlatformSurfaceRenderingSession(_context, _target.BeginDrawing()); } @@ -175,7 +188,7 @@ namespace Avalonia.Native class GlPlatformSurfaceRenderingSession : IGlPlatformSurfaceRenderingSession { - private IAvnGlSurfaceRenderingSession _session; + private IAvnGlSurfaceRenderingSession? _session; public GlPlatformSurfaceRenderingSession(IGlContext context, IAvnGlSurfaceRenderingSession session) { @@ -185,17 +198,25 @@ namespace Avalonia.Native public IGlContext Context { get; } + private IAvnGlSurfaceRenderingSession Session + { + get + { + ObjectDisposedException.ThrowIf(_session is null, this); + return _session; + } + } + public PixelSize Size { get { - var s = _session.PixelSize; + var s = Session.PixelSize; return new PixelSize(s.Width, s.Height); } } - public double Scaling => _session.Scaling; - + public double Scaling => Session.Scaling; public bool IsYFlipped => true; @@ -230,9 +251,12 @@ namespace Avalonia.Native public unsafe GlExternalObjectsFeature(GlContext context, GlDisplay display) { + context.ThrowIfLost(); + _context = context; _display = display; ulong registryId = 0; + if (context.Context.GetIOKitRegistryId(®istryId) != 0) { // We are reversing bytes to match MoltenVK (LUID is a Vulkan term after all) @@ -306,8 +330,8 @@ namespace Avalonia.Native CompositionGpuImportedImageSynchronizationCapabilities.TimelineSemaphores; } - public byte[] DeviceLuid { get; } - public byte[] DeviceUuid { get; } + public byte[]? DeviceLuid { get; } + public byte[]? DeviceUuid { get; } } class MtlEventSemaphore(IAvnMTLSharedEvent inner) : IGlExternalSemaphore diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index 241528a9ac..75251ee0a1 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs @@ -15,10 +15,10 @@ namespace Avalonia.Native private readonly IAvaloniaNativeFactory _factory; private bool _resetQueued = true; private bool _exported; - private readonly IAvnWindow _nativeWindow; - private NativeMenu _menu; - private __MicroComIAvnMenuProxy _nativeMenu; - private readonly IAvnTrayIcon _trayIcon; + private readonly IAvnWindow? _nativeWindow; + private NativeMenu? _menu; + private __MicroComIAvnMenuProxy? _nativeMenu; + private readonly IAvnTrayIcon? _trayIcon; private readonly IAvnApplicationCommands _applicationCommands; public AvaloniaNativeMenuExporter(IAvnWindow nativeWindow, IAvaloniaNativeFactory factory) @@ -51,7 +51,7 @@ namespace Avalonia.Native public event EventHandler OnIsNativeMenuExportedChanged { add { } remove { } } - public void SetNativeMenu(NativeMenu menu) + public void SetNativeMenu(NativeMenu? menu) { _menu = menu ?? new NativeMenu(); DoLayoutReset(true); @@ -152,7 +152,7 @@ namespace Avalonia.Native private void DoLayoutReset() => DoLayoutReset(false); - private void DoLayoutReset(bool forceUpdate = false) + private void DoLayoutReset(bool forceUpdate) { var macOpts = AvaloniaLocator.Current.GetService() ?? new MacOSPlatformOptions(); @@ -169,12 +169,15 @@ namespace Avalonia.Native { if (_trayIcon is null) { - var appMenu = NativeMenu.GetMenu(Application.Current); + var app = Application.Current; + var appMenu = app is null ? null : NativeMenu.GetMenu(app); if (appMenu == null) { appMenu = CreateDefaultAppMenu(); - NativeMenu.SetMenu(Application.Current, appMenu); + + if (app is not null) + NativeMenu.SetMenu(app, appMenu); } SetMenu(appMenu); diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs index 99edfd9d29..4ad0814283 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatform.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs @@ -12,7 +12,6 @@ using Avalonia.Rendering; using Avalonia.Rendering.Composition; using Avalonia.Threading; using MicroCom.Runtime; -#nullable enable namespace Avalonia.Native { @@ -199,7 +198,7 @@ namespace Avalonia.Native public IWindowImpl CreateWindow() { - return new WindowImpl(_factory, _options); + return new WindowImpl(_factory, _options ?? new AvaloniaNativePlatformOptions()); } public IWindowImpl CreateEmbeddableWindow() diff --git a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs index f8974865a7..40985a56e3 100644 --- a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs +++ b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs @@ -79,7 +79,7 @@ namespace Avalonia /// This property should be used in case you want to build Avalonia OSX native part by yourself /// and make your Avalonia app run with it. The default value is null. /// - public string AvaloniaNativeLibraryPath { get; set; } + public string? AvaloniaNativeLibraryPath { get; set; } /// /// If you distribute your app in App Store - it should be with sandbox enabled. diff --git a/src/Avalonia.Native/AvaloniaNativeRenderTimer.cs b/src/Avalonia.Native/AvaloniaNativeRenderTimer.cs index e8c32f62f4..625de5d6bc 100644 --- a/src/Avalonia.Native/AvaloniaNativeRenderTimer.cs +++ b/src/Avalonia.Native/AvaloniaNativeRenderTimer.cs @@ -1,9 +1,7 @@ using System; using System.Diagnostics; -using System.Runtime.InteropServices; using Avalonia.Native.Interop; using Avalonia.Rendering; -#nullable enable namespace Avalonia.Native; diff --git a/src/Avalonia.Native/AvaloniaNativeTextInputMethod.cs b/src/Avalonia.Native/AvaloniaNativeTextInputMethod.cs index a3abccd2b4..3df0a0ef4a 100644 --- a/src/Avalonia.Native/AvaloniaNativeTextInputMethod.cs +++ b/src/Avalonia.Native/AvaloniaNativeTextInputMethod.cs @@ -1,10 +1,7 @@ using System; using Avalonia.Input.TextInput; -using Avalonia.Media.TextFormatting; using Avalonia.Native.Interop; -#nullable enable - namespace Avalonia.Native { internal class AvaloniaNativeTextInputMethod : ITextInputMethodImpl, IDisposable diff --git a/src/Avalonia.Native/AvnAutomationPeer.cs b/src/Avalonia.Native/AvnAutomationPeer.cs index c666ffc695..e178febd42 100644 --- a/src/Avalonia.Native/AvnAutomationPeer.cs +++ b/src/Avalonia.Native/AvnAutomationPeer.cs @@ -6,12 +6,9 @@ using System.Runtime.CompilerServices; using Avalonia.Automation; using Avalonia.Automation.Peers; using Avalonia.Automation.Provider; -using Avalonia.Controls; using Avalonia.Controls.Automation.Peers; using Avalonia.Native.Interop; -#nullable enable - namespace Avalonia.Native { internal class AvnAutomationPeer : NativeCallbackBase, IAvnAutomationPeer @@ -36,10 +33,10 @@ namespace Avalonia.Native public IAvnString? AutomationId => _inner.GetAutomationId().ToAvnString(); public AvnRect BoundingRectangle => _inner.GetBoundingRectangle().ToAvnRect(); public IAvnAutomationPeerArray Children => new AvnAutomationPeerArray(_inner.GetChildren()); - public IAvnString ClassName => _inner.GetClassName().ToAvnString(); + public IAvnString? ClassName => _inner.GetClassName().ToAvnString(); public IAvnAutomationPeer? LabeledBy => Wrap(_inner.GetLabeledBy()); - public IAvnString Name => _inner.GetName().ToAvnString(); - public IAvnString HelpText => _inner.GetHelpText().ToAvnString(); + public IAvnString? Name => _inner.GetName().ToAvnString(); + public IAvnString? HelpText => _inner.GetHelpText().ToAvnString(); public AvnLandmarkType LandmarkType => (AvnLandmarkType?)_inner.GetLandmarkType() ?? AvnLandmarkType.LandmarkNone; public int HeadingLevel => _inner.GetHeadingLevel(); public IAvnAutomationPeer? Parent => Wrap(_inner.GetParent()); @@ -173,7 +170,7 @@ namespace Avalonia.Native public void ToggleProvider_Toggle() => ToggleProvider.Toggle(); public int IsValueProvider() => IsProvider(); - public IAvnString ValueProvider_GetValue() => ValueProvider.Value.ToAvnString(); + public IAvnString? ValueProvider_GetValue() => ValueProvider.Value.ToAvnString(); public void ValueProvider_SetValue(string value) => ValueProvider.SetValue(value); [return: NotNullIfNotNull("peer")] diff --git a/src/Avalonia.Native/AvnString.cs b/src/Avalonia.Native/AvnString.cs index b0cb9a3a86..3ff484117e 100644 --- a/src/Avalonia.Native/AvnString.cs +++ b/src/Avalonia.Native/AvnString.cs @@ -8,7 +8,7 @@ namespace Avalonia.Native.Interop { partial interface IAvnString { - public string String { get; } + public string? String { get; } public byte[] Bytes { get; } } @@ -73,7 +73,7 @@ namespace Avalonia.Native.Interop _items = items.Select(s => s.ToAvnString()).ToArray(); } - public string[] ToStringArray() => _items.Select(n => n.String).ToArray(); + public string[] ToStringArray() => _items.Select(n => n.String ?? string.Empty).ToArray(); public uint Count => (uint)_items.Length; public IAvnString Get(uint index) => _items[(int)index]; @@ -91,10 +91,10 @@ namespace Avalonia.Native.Interop.Impl { unsafe partial class __MicroComIAvnStringProxy { - private string _managed; - private byte[] _bytes; + private string? _managed; + private byte[]? _bytes; - public string String + public string? String { get { @@ -124,7 +124,7 @@ namespace Avalonia.Native.Interop.Impl } } - public override string ToString() => String; + public override string? ToString() => String; } partial class __MicroComIAvnStringArrayProxy @@ -134,7 +134,7 @@ namespace Avalonia.Native.Interop.Impl var arr = new string[Count]; for(uint c = 0; c IntPtr.Zero; public string HandleDescriptor => ""; @@ -20,7 +20,7 @@ namespace Avalonia.Native public void Dispose() { - Cursor.Dispose(); + Cursor?.Dispose(); Cursor = null; } } diff --git a/src/Avalonia.Native/DataTransferItemToAvnClipboardDataItemWrapper.cs b/src/Avalonia.Native/DataTransferItemToAvnClipboardDataItemWrapper.cs index 7c64e1a987..e9be474598 100644 --- a/src/Avalonia.Native/DataTransferItemToAvnClipboardDataItemWrapper.cs +++ b/src/Avalonia.Native/DataTransferItemToAvnClipboardDataItemWrapper.cs @@ -1,12 +1,9 @@ -#nullable enable - using System; using System.IO; using System.Linq; using Avalonia.Input; using Avalonia.Logging; using Avalonia.Native.Interop; -using Avalonia.Utilities; namespace Avalonia.Native; diff --git a/src/Avalonia.Native/DataTransferToAvnClipboardDataSourceWrapper.cs b/src/Avalonia.Native/DataTransferToAvnClipboardDataSourceWrapper.cs index 3cec91b829..19301d05ad 100644 --- a/src/Avalonia.Native/DataTransferToAvnClipboardDataSourceWrapper.cs +++ b/src/Avalonia.Native/DataTransferToAvnClipboardDataSourceWrapper.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Linq; using Avalonia.Input; diff --git a/src/Avalonia.Native/DispatcherImpl.cs b/src/Avalonia.Native/DispatcherImpl.cs index 16ec0f7ba6..fa80c2ffc7 100644 --- a/src/Avalonia.Native/DispatcherImpl.cs +++ b/src/Avalonia.Native/DispatcherImpl.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/Avalonia.Native/GpuHandleWrapFeature.cs b/src/Avalonia.Native/GpuHandleWrapFeature.cs index b490e6c9c1..feb394f460 100644 --- a/src/Avalonia.Native/GpuHandleWrapFeature.cs +++ b/src/Avalonia.Native/GpuHandleWrapFeature.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using Avalonia.Native.Interop; using Avalonia.Platform; diff --git a/src/Avalonia.Native/Helpers.cs b/src/Avalonia.Native/Helpers.cs index 6270cd30a0..60a45c2cbd 100644 --- a/src/Avalonia.Native/Helpers.cs +++ b/src/Avalonia.Native/Helpers.cs @@ -1,4 +1,5 @@ -using Avalonia.Native.Interop; +using System.Diagnostics.CodeAnalysis; +using Avalonia.Native.Interop; namespace Avalonia.Native { @@ -34,7 +35,8 @@ namespace Avalonia.Native return new AvnSize { Height = size.Height, Width = size.Width }; } - public static IAvnString ToAvnString(this string s) + [return: NotNullIfNotNull(nameof(s))] + public static IAvnString? ToAvnString(this string? s) { return s != null ? new AvnString(s) : null; } diff --git a/src/Avalonia.Native/IAvnMenu.cs b/src/Avalonia.Native/IAvnMenu.cs index dc0176a8ad..b526d91924 100644 --- a/src/Avalonia.Native/IAvnMenu.cs +++ b/src/Avalonia.Native/IAvnMenu.cs @@ -10,7 +10,7 @@ namespace Avalonia.Native.Interop { class MenuEvents : NativeCallbackBase, IAvnMenuEvents { - private IAvnMenu _parent; + private IAvnMenu? _parent; public void Initialise(IAvnMenu parent) { @@ -49,7 +49,7 @@ namespace Avalonia.Native.Interop.Impl private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>(); private Dictionary _menuItemLookup = new Dictionary(); - private void UpdateTitle(string title) + private void UpdateTitle(string? title) { if (OperatingSystemEx.IsMacOS()) { @@ -136,7 +136,7 @@ namespace Avalonia.Native.Interop.Impl return nativeItem; } - internal void Initialize(AvaloniaNativeMenuExporter exporter, NativeMenu managedMenu, string title) + internal void Initialize(AvaloniaNativeMenuExporter exporter, NativeMenu managedMenu, string? title) { _exporter = exporter; ManagedMenu = managedMenu; @@ -166,7 +166,7 @@ namespace Avalonia.Native.Interop.Impl for (int i = 0; i < menu.Items.Count; i++) { - __MicroComIAvnMenuItemProxy nativeItem; + __MicroComIAvnMenuItemProxy? nativeItem; if (i >= _menuItems.Count) { @@ -197,7 +197,7 @@ namespace Avalonia.Native.Interop.Impl } } - private void OnMenuItemsChanged(object sender, NotifyCollectionChangedEventArgs e) + private void OnMenuItemsChanged(object? sender, NotifyCollectionChangedEventArgs e) { _exporter.QueueReset(); } diff --git a/src/Avalonia.Native/IAvnMenuItem.cs b/src/Avalonia.Native/IAvnMenuItem.cs index 275a088821..fd851122f2 100644 --- a/src/Avalonia.Native/IAvnMenuItem.cs +++ b/src/Avalonia.Native/IAvnMenuItem.cs @@ -18,13 +18,13 @@ namespace Avalonia.Native.Interop.Impl { partial class __MicroComIAvnMenuItemProxy { - private __MicroComIAvnMenuProxy _subMenu; + private __MicroComIAvnMenuProxy? _subMenu; private CompositeDisposable _propertyDisposables = new CompositeDisposable(); - private IDisposable _currentActionDisposable; + private IDisposable? _currentActionDisposable; public NativeMenuItemBase ManagedMenuItem { get; set; } - private void UpdateTitle(string title) + private void UpdateTitle(string? title) { if (OperatingSystemEx.IsMacOS()) { @@ -38,7 +38,7 @@ namespace Avalonia.Native.Interop.Impl SetTitle(title); } - private void UpdateToolTip(string toolTip) => SetToolTip(toolTip ?? ""); + private void UpdateToolTip(string? toolTip) => SetToolTip(toolTip ?? ""); private void UpdateIsVisible(bool isVisible) => SetIsVisible(isVisible.AsComBool()); private void UpdateIsChecked(bool isChecked) => SetIsChecked(isChecked.AsComBool()); @@ -48,7 +48,7 @@ namespace Avalonia.Native.Interop.Impl SetToggleType((AvnMenuItemToggleType)toggleType); } - private unsafe void UpdateIcon (IBitmap icon) + private unsafe void UpdateIcon (IBitmap? icon) { if(icon is null) { @@ -70,20 +70,20 @@ namespace Avalonia.Native.Interop.Impl } } - private void UpdateGesture(Input.KeyGesture gesture) + private void UpdateGesture(Input.KeyGesture? gesture) { var modifiers = gesture == null ? AvnInputModifiers.AvnInputModifiersNone : (AvnInputModifiers)gesture.KeyModifiers; var key = gesture == null ? AvnKey.AvnKeyNone : (AvnKey)gesture.Key; SetGesture(key, modifiers); } - private void UpdateAction(NativeMenuItem item) + private void UpdateAction(NativeMenuItem? item) { _currentActionDisposable?.Dispose(); var action = new PredicateCallback(() => { - if (item.Command != null || item.HasClickHandlers) + if (item is not null && (item.Command is not null || item.HasClickHandlers)) { return item.IsEnabled; } @@ -160,7 +160,7 @@ namespace Avalonia.Native.Interop.Impl _subMenu = null; } - _propertyDisposables?.Dispose(); + _propertyDisposables.Dispose(); _currentActionDisposable?.Dispose(); } diff --git a/src/Avalonia.Native/IconLoader.cs b/src/Avalonia.Native/IconLoader.cs index 04779a43aa..dbc6379bd8 100644 --- a/src/Avalonia.Native/IconLoader.cs +++ b/src/Avalonia.Native/IconLoader.cs @@ -27,13 +27,13 @@ namespace Avalonia.Native public IWindowIconImpl LoadIcon(string fileName) { return new IconStub( - AvaloniaLocator.Current.GetService().LoadBitmap(fileName)); + AvaloniaLocator.Current.GetRequiredService().LoadBitmap(fileName)); } public IWindowIconImpl LoadIcon(Stream stream) { return new IconStub( - AvaloniaLocator.Current.GetService().LoadBitmap(stream)); + AvaloniaLocator.Current.GetRequiredService().LoadBitmap(stream)); } public IWindowIconImpl LoadIcon(IBitmapImpl bitmap) diff --git a/src/Avalonia.Native/MacOSActivatableLifetime.cs b/src/Avalonia.Native/MacOSActivatableLifetime.cs index c96e43f724..f3db4a032f 100644 --- a/src/Avalonia.Native/MacOSActivatableLifetime.cs +++ b/src/Avalonia.Native/MacOSActivatableLifetime.cs @@ -1,11 +1,8 @@ -using System; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.Platform; namespace Avalonia.Native; -#nullable enable - internal class MacOSActivatableLifetime : ActivatableLifetimeBase { public override bool TryLeaveBackground() diff --git a/src/Avalonia.Native/Metal.cs b/src/Avalonia.Native/Metal.cs index 6c5f6331a8..3137ce1b6b 100644 --- a/src/Avalonia.Native/Metal.cs +++ b/src/Avalonia.Native/Metal.cs @@ -28,26 +28,34 @@ class MetalPlatformGraphics : IPlatformGraphics class MetalDevice : IMetalDevice { - public IAvnMetalDevice Native { get; private set; } - private DisposableLock _syncRoot = new(); + private readonly DisposableLock _syncRoot = new(); private readonly GpuHandleWrapFeature _handleWrapFeature; private readonly MetalExternalObjectsFeature _externalObjectsFeature; - + private IAvnMetalDevice? _native; public MetalDevice(IAvaloniaNativeFactory factory, IAvnMetalDevice native) { - Native = native; + _native = native; _handleWrapFeature = new GpuHandleWrapFeature(factory); _externalObjectsFeature = new MetalExternalObjectsFeature(native); } + public IAvnMetalDevice Native + { + get + { + ObjectDisposedException.ThrowIf(_native is null, this); + return _native; + } + } + public void Dispose() { - Native?.Dispose(); - Native = null; + _native?.Dispose(); + _native = null; } - public object TryGetFeature(Type featureType) + public object? TryGetFeature(Type featureType) { if (featureType == typeof(IExternalObjectsHandleWrapRenderInterfaceContextFeature)) return _handleWrapFeature; @@ -105,7 +113,7 @@ internal class MetalExternalObjectsFeature : IMetalExternalObjectsFeature public IReadOnlyList SupportedSemaphoreTypes { get; } = [KnownPlatformGraphicsExternalSemaphoreHandleTypes.MetalSharedEvent]; - public byte[] DeviceLuid { get; } + public byte[]? DeviceLuid { get; } public CompositionGpuImportedImageSynchronizationCapabilities GetSynchronizationCapabilities(string imageHandleType) => @@ -166,13 +174,22 @@ internal class MetalExternalObjectsFeature : IMetalExternalObjectsFeature internal class MetalRenderTarget : IMetalPlatformSurfaceRenderTarget { - private IAvnMetalRenderTarget _native; + private IAvnMetalRenderTarget? _native; public MetalRenderTarget(IAvnMetalRenderTarget native) { _native = native; } + private IAvnMetalRenderTarget Native + { + get + { + ObjectDisposedException.ThrowIf(_native is null, this); + return _native; + } + } + public void Dispose() { _native?.Dispose(); @@ -181,36 +198,47 @@ internal class MetalRenderTarget : IMetalPlatformSurfaceRenderTarget public IMetalPlatformSurfaceRenderingSession BeginRendering() { - var session = _native.BeginDrawing(); + var session = Native.BeginDrawing(); return new MetalDrawingSession(session); } } internal class MetalDrawingSession : IMetalPlatformSurfaceRenderingSession { - private IAvnMetalRenderingSession _session; + private IAvnMetalRenderingSession? _session; public MetalDrawingSession(IAvnMetalRenderingSession session) { _session = session; } + public IAvnMetalRenderingSession Session + { + get + { + ObjectDisposedException.ThrowIf(_session is null, this); + return _session; + } + } + public void Dispose() { _session?.Dispose(); _session = null; } - public IntPtr Texture => _session.Texture; + public IntPtr Texture => Session.Texture; + public PixelSize Size { get { - var size = _session.PixelSize; + var size = Session.PixelSize; return new(size.Width, size.Height); } } - public double Scaling => _session.Scaling; + public double Scaling => Session.Scaling; + public bool IsYFlipped => false; } diff --git a/src/Avalonia.Native/NativeControlHostImpl.cs b/src/Avalonia.Native/NativeControlHostImpl.cs index 8a3488d95e..134eb2bb70 100644 --- a/src/Avalonia.Native/NativeControlHostImpl.cs +++ b/src/Avalonia.Native/NativeControlHostImpl.cs @@ -10,13 +10,22 @@ namespace Avalonia.Native { class NativeControlHostImpl : IDisposable, INativeControlHostImpl { - private IAvnNativeControlHost _host; + private IAvnNativeControlHost? _host; public NativeControlHostImpl(IAvnNativeControlHost host) { _host = host; } + private IAvnNativeControlHost Host + { + get + { + ObjectDisposedException.ThrowIf(_host is null, this); + return _host; + } + } + public void Dispose() { _host?.Dispose(); @@ -25,7 +34,7 @@ namespace Avalonia.Native class DestroyableNSView : INativeControlHostDestroyableControlHandle { - private IAvnNativeControlHost _impl; + private IAvnNativeControlHost? _impl; private IntPtr _nsView; public DestroyableNSView(IAvnNativeControlHost impl) @@ -49,12 +58,12 @@ namespace Avalonia.Native } public INativeControlHostDestroyableControlHandle CreateDefaultChild(IPlatformHandle parent) - => new DestroyableNSView(_host); + => new DestroyableNSView(Host); public INativeControlHostControlTopLevelAttachment CreateNewAttachment( Func create) { - var a = new Attachment(_host.CreateAttachment()); + var a = new Attachment(Host.CreateAttachment()); try { var child = create(a.GetParentHandle()); @@ -71,7 +80,7 @@ namespace Avalonia.Native public INativeControlHostControlTopLevelAttachment CreateNewAttachment(IPlatformHandle handle) { - var a = new Attachment(_host.CreateAttachment()); + var a = new Attachment(Host.CreateAttachment()); a.InitWithChild(handle); a.AttachedTo = this; return a; @@ -81,14 +90,25 @@ namespace Avalonia.Native class Attachment : INativeControlHostControlTopLevelAttachment { - private IAvnNativeControlHostTopLevelAttachment _native; - private NativeControlHostImpl _attachedTo; - public IPlatformHandle GetParentHandle() => new PlatformHandle(_native.ParentHandle, "NSView"); + private IAvnNativeControlHostTopLevelAttachment? _native; + private NativeControlHostImpl? _attachedTo; + public Attachment(IAvnNativeControlHostTopLevelAttachment native) { _native = native; } - + + private IAvnNativeControlHostTopLevelAttachment Native + { + get + { + ObjectDisposedException.ThrowIf(_native is null, this); + return _native; + } + } + + public IPlatformHandle GetParentHandle() => new PlatformHandle(Native.ParentHandle, "NSView"); + public void Dispose() { if (_native != null) @@ -99,16 +119,13 @@ namespace Avalonia.Native } } - public INativeControlHostImpl AttachedTo + public INativeControlHostImpl? AttachedTo { get => _attachedTo; set { - var host = (NativeControlHostImpl)value; - if(host == null) - _native.AttachTo(null); - else - _native.AttachTo(host._host); + var host = (NativeControlHostImpl?)value; + Native.AttachTo(host?._host); _attachedTo = host; } } @@ -117,7 +134,7 @@ namespace Avalonia.Native public void HideWithSize(Size size) { - _native.HideWithSize(Math.Max(1, (float)size.Width), Math.Max(1, (float)size.Height)); + Native.HideWithSize(Math.Max(1, (float)size.Width), Math.Max(1, (float)size.Height)); } public void ShowInBounds(Rect bounds) @@ -126,11 +143,11 @@ namespace Avalonia.Native throw new InvalidOperationException("Native control isn't attached to a toplevel"); bounds = new Rect(bounds.X, bounds.Y, Math.Max(1, bounds.Width), Math.Max(1, bounds.Height)); - _native.ShowInBounds((float) bounds.X, (float) bounds.Y, (float) bounds.Width, (float) bounds.Height); + Native.ShowInBounds((float) bounds.X, (float) bounds.Y, (float) bounds.Width, (float) bounds.Height); } public void InitWithChild(IPlatformHandle handle) - => _native.InitializeWithChildHandle(handle.Handle); + => Native.InitializeWithChildHandle(handle.Handle); } } } diff --git a/src/Avalonia.Native/NativeOwned.cs b/src/Avalonia.Native/NativeOwned.cs index b89a422fa9..2bc6891343 100644 --- a/src/Avalonia.Native/NativeOwned.cs +++ b/src/Avalonia.Native/NativeOwned.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Runtime.ExceptionServices; using Avalonia.Threading; diff --git a/src/Avalonia.Native/NativePlatformSettings.cs b/src/Avalonia.Native/NativePlatformSettings.cs index 42d05d831c..5e3ee0cfc2 100644 --- a/src/Avalonia.Native/NativePlatformSettings.cs +++ b/src/Avalonia.Native/NativePlatformSettings.cs @@ -8,7 +8,7 @@ namespace Avalonia.Native; internal class NativePlatformSettings : DefaultPlatformSettings { private readonly IAvnPlatformSettings _platformSettings; - private PlatformColorValues _lastColorValues; + private PlatformColorValues? _lastColorValues; public NativePlatformSettings(IAvnPlatformSettings platformSettings) { diff --git a/src/Avalonia.Native/ScreenImpl.cs b/src/Avalonia.Native/ScreenImpl.cs index 65fa19dab5..1f9815733b 100644 --- a/src/Avalonia.Native/ScreenImpl.cs +++ b/src/Avalonia.Native/ScreenImpl.cs @@ -4,8 +4,6 @@ using Avalonia.Native.Interop; using Avalonia.Platform; using MicroCom.Runtime; -#nullable enable - namespace Avalonia.Native { internal sealed class AvnScreen(uint displayId) diff --git a/src/Avalonia.Native/StorageItem.cs b/src/Avalonia.Native/StorageItem.cs index efa0404a34..268fe2965d 100644 --- a/src/Avalonia.Native/StorageItem.cs +++ b/src/Avalonia.Native/StorageItem.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; diff --git a/src/Avalonia.Native/StorageProviderApi.cs b/src/Avalonia.Native/StorageProviderApi.cs index 8c737336b2..819623c0da 100644 --- a/src/Avalonia.Native/StorageProviderApi.cs +++ b/src/Avalonia.Native/StorageProviderApi.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.IO; diff --git a/src/Avalonia.Native/StorageProviderImpl.cs b/src/Avalonia.Native/StorageProviderImpl.cs index e6e1fd7257..d3062715c8 100644 --- a/src/Avalonia.Native/StorageProviderImpl.cs +++ b/src/Avalonia.Native/StorageProviderImpl.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; using Avalonia.Platform.Storage; diff --git a/src/Avalonia.Native/TopLevelImpl.cs b/src/Avalonia.Native/TopLevelImpl.cs index 05cbb15765..d45e50d5c6 100644 --- a/src/Avalonia.Native/TopLevelImpl.cs +++ b/src/Avalonia.Native/TopLevelImpl.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -311,7 +309,7 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface Native.SetCursor(newCursor?.Cursor); } - public virtual IPopupImpl CreatePopup() + public virtual IPopupImpl? CreatePopup() { return new PopupImpl(Factory, this); } @@ -554,6 +552,8 @@ internal class TopLevelImpl : ITopLevelImpl, IFramebufferPlatformSurface public ILockedFramebuffer Lock() { + ObjectDisposedException.ThrowIf(_target is null, this); + var w = _parent._savedLogicalSize.Width * _parent._savedScaling; var h = _parent._savedLogicalSize.Height * _parent._savedScaling; var dpi = _parent._savedScaling * 96; diff --git a/src/Avalonia.Native/TrayIconImpl.cs b/src/Avalonia.Native/TrayIconImpl.cs index 4c9bed0e7c..6e08131c92 100644 --- a/src/Avalonia.Native/TrayIconImpl.cs +++ b/src/Avalonia.Native/TrayIconImpl.cs @@ -4,8 +4,6 @@ using Avalonia.Controls.Platform; using Avalonia.Native.Interop; using Avalonia.Platform; -#nullable enable - namespace Avalonia.Native { internal class TrayIconImpl : ITrayIconWithIsTemplateImpl diff --git a/src/Avalonia.Native/WindowImpl.cs b/src/Avalonia.Native/WindowImpl.cs index 08aaae669f..2f35231b4f 100644 --- a/src/Avalonia.Native/WindowImpl.cs +++ b/src/Avalonia.Native/WindowImpl.cs @@ -13,7 +13,7 @@ namespace Avalonia.Native internal class WindowImpl : WindowBaseImpl, IWindowImpl { private readonly AvaloniaNativePlatformOptions _opts; - IAvnWindow _native; + private readonly IAvnWindow _native; private double _extendTitleBarHeight = -1; private DoubleClickHelper _doubleClickHelper; private readonly ITopLevelNativeMenuExporter _nativeMenuExporter; @@ -99,7 +99,7 @@ namespace Avalonia.Native _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 ?? ""); } @@ -110,9 +110,9 @@ namespace Avalonia.Native set => _native.SetWindowState((AvnWindowState)value); } - public Action WindowStateChanged { get; set; } + public Action? WindowStateChanged { get; set; } - public Action ExtendClientAreaToDecorationsChanged { get; set; } + public Action? ExtendClientAreaToDecorationsChanged { get; set; } public Thickness ExtendedMargins { get; private set; } @@ -226,23 +226,23 @@ namespace Avalonia.Native // NO OP On OSX } - public void SetIcon(IWindowIconImpl icon) + public void SetIcon(IWindowIconImpl? icon) { // NO OP on OSX } - public Func Closing { get; set; } + public Func? Closing { get; set; } public void Move(PixelPoint point) => Position = point; - public override IPopupImpl CreatePopup() => + public override IPopupImpl? CreatePopup() => _opts.OverlayPopups ? null : new PopupImpl(Factory, this); - public Action GotInputWhenDisabled { get; set; } + public Action? GotInputWhenDisabled { get; set; } - public void SetParent(IWindowImpl parent) + public void SetParent(IWindowImpl? parent) { - _native.SetParent(((WindowImpl)parent)?.Native); + _native.SetParent(((WindowImpl?)parent)?.Native); } public void SetEnabled(bool enable) @@ -257,7 +257,7 @@ namespace Avalonia.Native mouse.PlatformCaptureLost(); } - public override object TryGetFeature(Type featureType) + public override object? TryGetFeature(Type featureType) { if(featureType == typeof(ITextInputMethodImpl)) { diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index 8aaea611ab..852317a793 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Linq; using Avalonia.Controls; @@ -57,7 +55,7 @@ namespace Avalonia.Native .OrderBy(x => x.Scaling) .First(m => m.Bounds.Contains(Position)); - Resize(new Size(monitor!.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), WindowResizeReason.Layout); + Resize(new Size(monitor.WorkingArea.Width * 0.75d, monitor.WorkingArea.Height * 0.7d), WindowResizeReason.Layout); } public void Activate()