From 6258df5b63e59c758bd5e80cdd08bede4c4232aa Mon Sep 17 00:00:00 2001 From: Max Katz Date: Thu, 11 Apr 2024 18:03:03 -0700 Subject: [PATCH] Enable nullable on Avalonia.Android project (#15331) * Enable nullable on Avalonia.Android project * More specific exception --- .../Avalonia.Android/AndroidInputMethod.cs | 33 +++-- .../Avalonia.Android/AndroidPlatform.cs | 8 +- .../AndroidRuntimePlatform.cs | 4 +- .../AndroidThreadingInterface.cs | 17 +-- .../AndroidViewControlHandle.cs | 4 +- .../Avalonia.Android/Avalonia.Android.csproj | 3 +- .../Avalonia.Android/AvaloniaActivity.cs | 1 - .../AvaloniaMainActivity.App.cs | 10 +- .../Avalonia.Android/AvaloniaMainActivity.cs | 3 - src/Android/Avalonia.Android/AvaloniaView.cs | 28 ++-- .../Avalonia.Android/ChoreographerTimer.cs | 13 +- .../IActivityResultHandler.cs | 11 +- .../IAndroidNavigationService.cs | 1 - .../Avalonia.Android/IAvaloniaActivity.cs | 3 +- .../Platform/AndroidActivatableLifetime.cs | 12 +- .../Platform/AndroidInsetsManager.cs | 14 +- .../Platform/AndroidNativeControlHostImpl.cs | 4 +- .../Platform/AndroidPlatformSettings.cs | 32 +++-- .../AndroidSystemNavigationManager.cs | 4 +- .../Platform/ClipboardImpl.cs | 2 - .../Platform/PlatformSupport.cs | 1 - .../SkiaPlatform/FramebufferManager.cs | 9 +- .../InvalidationAwareSurfaceView.cs | 17 ++- .../Platform/SkiaPlatform/TopLevelImpl.cs | 124 +++++++++--------- .../Specific/Helpers/AndroidKeyInterop.cs | 4 +- .../Helpers/AndroidKeyboardEventsHelper.cs | 14 +- .../Helpers/AndroidMotionEventsHelper.cs | 15 ++- .../Platform/Storage/AndroidStorageItem.cs | 7 +- .../Storage/AndroidStorageProvider.cs | 7 +- .../Avalonia.Android/SingleViewLifetime.cs | 3 +- src/Android/Avalonia.Android/Stubs.cs | 2 +- .../Avalonia.Headless/HeadlessWindowImpl.cs | 1 - tests/Avalonia.UnitTests/TestRoot.cs | 2 - 33 files changed, 195 insertions(+), 218 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs index 1fcb74962a..3f951d6bb1 100644 --- a/src/Android/Avalonia.Android/AndroidInputMethod.cs +++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using Android.Content; using Android.Runtime; using Android.Text; @@ -13,8 +14,9 @@ namespace Avalonia.Android { public View View { get; } - public TextInputMethodClient Client { get; } + public TextInputMethodClient? Client { get; } + [MemberNotNullWhen(true, nameof(Client))] public bool IsActive { get; } public InputMethodManager IMM { get; } @@ -38,8 +40,8 @@ namespace Avalonia.Android { private readonly TView _host; private readonly InputMethodManager _imm; - private TextInputMethodClient _client; - private AvaloniaInputConnection _inputConnection; + private TextInputMethodClient? _client; + private AvaloniaInputConnection? _inputConnection; public AndroidInputMethod(TView host) { @@ -47,7 +49,8 @@ namespace Avalonia.Android throw new InvalidOperationException("Host should return true from OnCheckIsTextEditor()"); _host = host; - _imm = host.Context.GetSystemService(Context.InputMethodService).JavaCast(); + _imm = host.Context?.GetSystemService(Context.InputMethodService).JavaCast() + ?? throw new InvalidOperationException("Context.InputMethodService is expected to be not null."); _host.Focusable = true; _host.FocusableInTouchMode = true; @@ -55,9 +58,11 @@ namespace Avalonia.Android public View View => _host; + [MemberNotNullWhen(true, nameof(Client))] + [MemberNotNullWhen(true, nameof(_client))] public bool IsActive => Client != null; - public TextInputMethodClient Client => _client; + public TextInputMethodClient? Client => _client; public InputMethodManager IMM => _imm; @@ -66,7 +71,7 @@ namespace Avalonia.Android } - public void SetClient(TextInputMethodClient client) + public void SetClient(TextInputMethodClient? client) { _client = client; @@ -103,9 +108,9 @@ namespace Avalonia.Android } } - private void _client_SelectionChanged(object sender, EventArgs e) + private void _client_SelectionChanged(object? sender, EventArgs e) { - if (_inputConnection.IsInBatchEdit) + if (_inputConnection is null || _inputConnection.IsInBatchEdit) return; OnSelectionChanged(); } @@ -121,19 +126,19 @@ namespace Avalonia.Android _imm.UpdateSelection(_host, selection.Start, selection.End, selection.Start, selection.End); - _inputConnection.SetSelection(selection.Start, selection.End); + _inputConnection?.SetSelection(selection.Start, selection.End); } - private void _client_SurroundingTextChanged(object sender, EventArgs e) + private void _client_SurroundingTextChanged(object? sender, EventArgs e) { - if (_inputConnection.IsInBatchEdit) + if (_inputConnection is null || _inputConnection.IsInBatchEdit) return; OnSurroundingTextChanged(); } public void OnBatchEditedEnded() { - if (_inputConnection.IsInBatchEdit) + if (_inputConnection is null || _inputConnection.IsInBatchEdit) return; OnSurroundingTextChanged(); @@ -142,7 +147,7 @@ namespace Avalonia.Android private void OnSurroundingTextChanged() { - if(_client is null) + if(_client is null || _inputConnection is null) { return; } @@ -199,7 +204,7 @@ namespace Avalonia.Android _host.InitEditorInfo((topLevel, outAttrs) => { if (_client == null) - return null; + return null!; _inputConnection = new AvaloniaInputConnection(topLevel, this); diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs index 4ed759c78b..bf9237deec 100644 --- a/src/Android/Avalonia.Android/AndroidPlatform.cs +++ b/src/Android/Avalonia.Android/AndroidPlatform.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Avalonia.Controls; using Avalonia.Android; using Avalonia.Android.Platform; using Avalonia.Android.Platform.Input; @@ -12,7 +11,6 @@ using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Rendering.Composition; -using Avalonia.OpenGL; namespace Avalonia { @@ -66,9 +64,9 @@ namespace Avalonia.Android class AndroidPlatform { public static readonly AndroidPlatform Instance = new AndroidPlatform(); - public static AndroidPlatformOptions Options { get; private set; } + public static AndroidPlatformOptions? Options { get; private set; } - internal static Compositor Compositor { get; private set; } + internal static Compositor? Compositor { get; private set; } public static void Initialize() { @@ -95,7 +93,7 @@ namespace Avalonia.Android AvaloniaLocator.CurrentMutable.Bind().ToConstant(Compositor); } - private static IPlatformGraphics InitializeGraphics(AndroidPlatformOptions opts) + private static IPlatformGraphics? InitializeGraphics(AndroidPlatformOptions opts) { if (opts.RenderingMode is null || !opts.RenderingMode.Any()) { diff --git a/src/Android/Avalonia.Android/AndroidRuntimePlatform.cs b/src/Android/Avalonia.Android/AndroidRuntimePlatform.cs index ed3b9b6ccb..8607f6b8c1 100644 --- a/src/Android/Avalonia.Android/AndroidRuntimePlatform.cs +++ b/src/Android/Avalonia.Android/AndroidRuntimePlatform.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using Android.Content.PM; using Android.Content; using Avalonia.Platform; diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index c85d5b1343..703cc85057 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -14,11 +14,12 @@ namespace Avalonia.Android internal sealed class AndroidThreadingInterface : IPlatformThreadingInterface { private Handler _handler; - private static Thread s_uiThread; + private static Thread? s_uiThread; public AndroidThreadingInterface() { - _handler = new Handler(App.Context.MainLooper); + _handler = new Handler(App.Context.MainLooper + ?? throw new InvalidOperationException("Application.Context.MainLooper was not expected to be null.")); } public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) @@ -27,7 +28,7 @@ namespace Avalonia.Android interval = TimeSpan.FromMilliseconds(10); var stopped = false; - Timer timer = null; + Timer? timer = null; timer = new Timer(_ => { if (stopped) @@ -42,7 +43,7 @@ namespace Avalonia.Android finally { if (!stopped) - timer.Change(interval, Timeout.InfiniteTimeSpan); + timer!.Change(interval, Timeout.InfiniteTimeSpan); } }); }, @@ -70,9 +71,9 @@ namespace Avalonia.Android return s_uiThread == Thread.CurrentThread; var isOnMainThread = OperatingSystem.IsAndroidVersionAtLeast(23) - ? Looper.MainLooper.IsCurrentThread - : Looper.MainLooper.Thread.Equals(Java.Lang.Thread.CurrentThread()); - if (isOnMainThread) + ? Looper.MainLooper?.IsCurrentThread + : Looper.MainLooper?.Thread.Equals(Java.Lang.Thread.CurrentThread()); + if (isOnMainThread == true) { s_uiThread = Thread.CurrentThread; return true; @@ -81,6 +82,6 @@ namespace Avalonia.Android return false; } } - public event Action Signaled; + public event Action? Signaled; } } diff --git a/src/Android/Avalonia.Android/AndroidViewControlHandle.cs b/src/Android/Avalonia.Android/AndroidViewControlHandle.cs index e999d198c6..6d14ea787f 100644 --- a/src/Android/Avalonia.Android/AndroidViewControlHandle.cs +++ b/src/Android/Avalonia.Android/AndroidViewControlHandle.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using Android.Views; diff --git a/src/Android/Avalonia.Android/Avalonia.Android.csproj b/src/Android/Avalonia.Android/Avalonia.Android.csproj index 86862b5614..bd6eb4e903 100644 --- a/src/Android/Avalonia.Android/Avalonia.Android.csproj +++ b/src/Android/Avalonia.Android/Avalonia.Android.csproj @@ -3,7 +3,6 @@ $(AvsCurrentAndroidTargetFramework) $(AvsMinSupportedAndroidVersion) true - portable Avalonia.Android.Internal @@ -16,6 +15,8 @@ + + diff --git a/src/Android/Avalonia.Android/AvaloniaActivity.cs b/src/Android/Avalonia.Android/AvaloniaActivity.cs index 187349fbb6..b5e4270028 100644 --- a/src/Android/Avalonia.Android/AvaloniaActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaActivity.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.Versioning; diff --git a/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs b/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs index 153da8d217..c3116fe232 100644 --- a/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs +++ b/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs @@ -1,12 +1,4 @@ -#nullable enable - -using Android.OS; -using Android.Views; -using Avalonia.Android.Platform; -using Avalonia.Controls.ApplicationLifetimes; -using Avalonia.Platform; - -namespace Avalonia.Android; +namespace Avalonia.Android; public class AvaloniaMainActivity : AvaloniaMainActivity where TApp : Application, new() diff --git a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs index 48411d792f..54756a166f 100644 --- a/src/Android/Avalonia.Android/AvaloniaMainActivity.cs +++ b/src/Android/Avalonia.Android/AvaloniaMainActivity.cs @@ -1,7 +1,4 @@ -#nullable enable - using System; -using System.Diagnostics.CodeAnalysis; using Android.OS; using Avalonia.Android.Platform; using Avalonia.Controls.ApplicationLifetimes; diff --git a/src/Android/Avalonia.Android/AvaloniaView.cs b/src/Android/Avalonia.Android/AvaloniaView.cs index e9ea41ab61..f72da82010 100644 --- a/src/Android/Avalonia.Android/AvaloniaView.cs +++ b/src/Android/Avalonia.Android/AvaloniaView.cs @@ -20,7 +20,7 @@ namespace Avalonia.Android private EmbeddableControlRoot _root; private readonly ViewImpl _view; - private IDisposable _timerSubscription; + private IDisposable? _timerSubscription; public AvaloniaView(Context context) : base(context) { @@ -35,9 +35,9 @@ namespace Avalonia.Android } internal TopLevelImpl TopLevelImpl => _view; - internal TopLevel TopLevel => _root; + internal TopLevel? TopLevel => _root; - public object Content + public object? Content { get { return _root.Content; } set { _root.Content = value; } @@ -47,10 +47,10 @@ namespace Avalonia.Android { base.Dispose(disposing); _root?.Dispose(); - _root = null; + _root = null!; } - public override bool DispatchKeyEvent(KeyEvent e) + public override bool DispatchKeyEvent(KeyEvent? e) { return _view.View.DispatchKeyEvent(e); } @@ -91,7 +91,7 @@ namespace Avalonia.Android } } - protected override void OnConfigurationChanged(Configuration newConfig) + protected override void OnConfigurationChanged(Configuration? newConfig) { base.OnConfigurationChanged(newConfig); OnConfigurationChanged(); @@ -99,8 +99,12 @@ namespace Avalonia.Android private void OnConfigurationChanged() { - var settings = AvaloniaLocator.Current.GetRequiredService() as AndroidPlatformSettings; - settings?.OnViewConfigurationChanged(Context); + if (Context is { } context) + { + var settings = + AvaloniaLocator.Current.GetRequiredService() as AndroidPlatformSettings; + settings?.OnViewConfigurationChanged(context); + } } class ViewImpl : TopLevelImpl @@ -111,17 +115,11 @@ namespace Avalonia.Android View.FocusChange += ViewImpl_FocusChange; } - private void ViewImpl_FocusChange(object sender, FocusChangeEventArgs e) + private void ViewImpl_FocusChange(object? sender, FocusChangeEventArgs e) { if(!e.HasFocus) LostFocus?.Invoke(); } - - protected override void OnResized(Size size) - { - MaxClientSize = size; - base.OnResized(size); - } } } } diff --git a/src/Android/Avalonia.Android/ChoreographerTimer.cs b/src/Android/Avalonia.Android/ChoreographerTimer.cs index 3545ae8fe1..4c6d176539 100644 --- a/src/Android/Avalonia.Android/ChoreographerTimer.cs +++ b/src/Android/Avalonia.Android/ChoreographerTimer.cs @@ -14,14 +14,14 @@ namespace Avalonia.Android { internal sealed class ChoreographerTimer : Java.Lang.Object, IRenderTimer, Choreographer.IFrameCallback { - private readonly object _lock = new object(); + private readonly object _lock = new(); private readonly Thread _thread; - private readonly TaskCompletionSource _choreographer = new TaskCompletionSource(); + private readonly TaskCompletionSource _choreographer = new(); private readonly ISet _views = new HashSet(); - private Action _tick; + private Action? _tick; private int _count; public ChoreographerTimer() @@ -29,8 +29,7 @@ namespace Avalonia.Android _thread = new Thread(Loop); _thread.Start(); } - - + public bool RunsInBackground => true; public event Action Tick @@ -84,7 +83,7 @@ namespace Avalonia.Android private void Loop() { Looper.Prepare(); - _choreographer.SetResult(Choreographer.Instance); + _choreographer.SetResult(Choreographer.Instance!); Looper.Loop(); } @@ -96,7 +95,7 @@ namespace Avalonia.Android { if (_count > 0 && _views.Count > 0) { - Choreographer.Instance.PostFrameCallback(this); + Choreographer.Instance!.PostFrameCallback(this); } } } diff --git a/src/Android/Avalonia.Android/IActivityResultHandler.cs b/src/Android/Avalonia.Android/IActivityResultHandler.cs index 40a8b5cbcf..3546d3e801 100644 --- a/src/Android/Avalonia.Android/IActivityResultHandler.cs +++ b/src/Android/Avalonia.Android/IActivityResultHandler.cs @@ -3,12 +3,11 @@ using Android.App; using Android.Content; using Android.Content.PM; -namespace Avalonia.Android +namespace Avalonia.Android; + +public interface IActivityResultHandler { - public interface IActivityResultHandler - { - public Action ActivityResult { get; set; } + public Action? ActivityResult { get; set; } - public Action RequestPermissionsResult { get; set; } - } + public Action? RequestPermissionsResult { get; set; } } diff --git a/src/Android/Avalonia.Android/IAndroidNavigationService.cs b/src/Android/Avalonia.Android/IAndroidNavigationService.cs index b45ee6e78d..5fa93971d9 100644 --- a/src/Android/Avalonia.Android/IAndroidNavigationService.cs +++ b/src/Android/Avalonia.Android/IAndroidNavigationService.cs @@ -1,5 +1,4 @@ using System; -using Avalonia.Controls.ApplicationLifetimes; namespace Avalonia.Android { diff --git a/src/Android/Avalonia.Android/IAvaloniaActivity.cs b/src/Android/Avalonia.Android/IAvaloniaActivity.cs index d6239400e8..dd4fbafba8 100644 --- a/src/Android/Avalonia.Android/IAvaloniaActivity.cs +++ b/src/Android/Avalonia.Android/IAvaloniaActivity.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using Avalonia.Controls.ApplicationLifetimes; namespace Avalonia.Android; diff --git a/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs b/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs index 525c4d7f21..62f347e9bf 100644 --- a/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs +++ b/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs @@ -6,9 +6,9 @@ namespace Avalonia.Android.Platform; internal class AndroidActivatableLifetime : IActivatableLifetime { - private IAvaloniaActivity _activity; + private IAvaloniaActivity? _activity; - public IAvaloniaActivity Activity + public IAvaloniaActivity? Activity { get => _activity; set @@ -29,18 +29,18 @@ internal class AndroidActivatableLifetime : IActivatableLifetime } } - public event EventHandler Activated; - public event EventHandler Deactivated; + public event EventHandler? Activated; + public event EventHandler? Deactivated; public bool TryLeaveBackground() => false; public bool TryEnterBackground() => (_activity as Activity)?.MoveTaskToBack(true) == true; - private void ActivityOnDeactivated(object sender, ActivatedEventArgs e) + private void ActivityOnDeactivated(object? sender, ActivatedEventArgs e) { Deactivated?.Invoke(this, e); } - private void ActivityOnActivated(object sender, ActivatedEventArgs e) + private void ActivityOnActivated(object? sender, ActivatedEventArgs e) { Activated?.Invoke(this, e); } diff --git a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs index f4c3aa7596..18cad0aebf 100644 --- a/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs +++ b/src/Android/Avalonia.Android/Platform/AndroidInsetsManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Android.App; using Android.OS; using Android.Views; using Android.Views.Animations; @@ -15,7 +16,7 @@ namespace Avalonia.Android.Platform { internal sealed class AndroidInsetsManager : WindowInsetsAnimationCompat.Callback, IInsetsManager, IOnApplyWindowInsetsListener, ViewTreeObserver.IOnGlobalLayoutListener, IInputPane { - private readonly AvaloniaMainActivity _activity; + private readonly Activity _activity; private readonly TopLevelImpl _topLevel; private bool _displayEdgeToEdge; private bool? _systemUiVisibility; @@ -28,8 +29,8 @@ namespace Avalonia.Android.Platform private AndroidWindow Window => _activity.Window ?? throw new InvalidOperationException("Activity.Window must be set."); - public event EventHandler SafeAreaChanged; - public event EventHandler StateChanged; + public event EventHandler? SafeAreaChanged; + public event EventHandler? StateChanged; public InputPaneState State { @@ -73,7 +74,7 @@ namespace Avalonia.Android.Platform } } - internal AndroidInsetsManager(AvaloniaMainActivity activity, TopLevelImpl topLevel) : base(DispatchModeStop) + internal AndroidInsetsManager(Activity activity, TopLevelImpl topLevel) : base(DispatchModeStop) { _activity = activity; _topLevel = topLevel; @@ -155,7 +156,7 @@ namespace Avalonia.Android.Platform Dispatcher.UIThread.Send(_ => SafeAreaChanged?.Invoke(this, new SafeAreaChangedArgs(safeAreaPadding))); } - private void NotifyStateChanged(InputPaneState newState, Rect? startRect, Rect endRect, TimeSpan animationDuration, IEasing easing) + private void NotifyStateChanged(InputPaneState newState, Rect? startRect, Rect endRect, TimeSpan animationDuration, IEasing? easing) { Dispatcher.UIThread.Send(_ => StateChanged?.Invoke(this, new InputPaneStateEventArgs(newState, startRect, endRect, animationDuration, easing))); } @@ -300,7 +301,8 @@ namespace Avalonia.Android.Platform var duration = TimeSpan.FromMilliseconds(animation.DurationMillis); bool isOpening = State == InputPaneState.Open; - NotifyStateChanged(State, isOpening ? upperRect : lowerRect, isOpening ? lowerRect : upperRect, duration, new AnimationEasing(animation.Interpolator)); + NotifyStateChanged(State, isOpening ? upperRect : lowerRect, isOpening ? lowerRect : upperRect, duration, + animation.Interpolator is { } interpolator ? new AnimationEasing(interpolator) : null); } } diff --git a/src/Android/Avalonia.Android/Platform/AndroidNativeControlHostImpl.cs b/src/Android/Avalonia.Android/Platform/AndroidNativeControlHostImpl.cs index 4738bd86f9..7cc1e70cfd 100644 --- a/src/Android/Avalonia.Android/Platform/AndroidNativeControlHostImpl.cs +++ b/src/Android/Avalonia.Android/Platform/AndroidNativeControlHostImpl.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Diagnostics.CodeAnalysis; using Android.Views; diff --git a/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs b/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs index 0872603e7b..3963a88203 100644 --- a/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs +++ b/src/Android/Avalonia.Android/Platform/AndroidPlatformSettings.cs @@ -1,12 +1,7 @@ using System; -using Android; using Android.Content; using Android.Content.Res; -using Android.Graphics; using Android.Provider; -using Android.Views.Accessibility; -using AndroidX.Core.Content.Resources; -using Avalonia.Media; using Avalonia.Platform; using Color = Avalonia.Media.Color; @@ -60,16 +55,25 @@ internal class AndroidPlatformSettings : DefaultPlatformSettings else if (OperatingSystem.IsAndroidVersionAtLeast(23)) { // See https://developer.android.com/reference/android/R.attr - var array = context.Theme.ObtainStyledAttributes(new[] { 16843829 }); // Resource.Attribute.ColorAccent - var accent = array.GetColor(0, 0); - - _latestValues = new PlatformColorValues + var array = context.Theme?.ObtainStyledAttributes(new[] { 16843829 }); // Resource.Attribute.ColorAccent + if (array is not null) { - ThemeVariant = systemTheme, - ContrastPreference = IsHighContrast(context), - AccentColor1 = new Color(accent.A, accent.R, accent.G, accent.B) - }; - array.Recycle(); + try + { + var accent = array.GetColor(0, 0); + + _latestValues = new PlatformColorValues + { + ThemeVariant = systemTheme, + ContrastPreference = IsHighContrast(context), + AccentColor1 = new Color(accent.A, accent.R, accent.G, accent.B) + }; + } + finally + { + array.Recycle(); + } + } } else { diff --git a/src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs b/src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs index ec619fd0f3..2bf5c5c987 100644 --- a/src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs +++ b/src/Android/Avalonia.Android/Platform/AndroidSystemNavigationManager.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using Avalonia.Interactivity; using Avalonia.Platform; diff --git a/src/Android/Avalonia.Android/Platform/ClipboardImpl.cs b/src/Android/Avalonia.Android/Platform/ClipboardImpl.cs index 0f2f985e27..028134ffad 100644 --- a/src/Android/Avalonia.Android/Platform/ClipboardImpl.cs +++ b/src/Android/Avalonia.Android/Platform/ClipboardImpl.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Threading.Tasks; using Android.Content; diff --git a/src/Android/Avalonia.Android/Platform/PlatformSupport.cs b/src/Android/Avalonia.Android/Platform/PlatformSupport.cs index 9877f48664..feff497f61 100644 --- a/src/Android/Avalonia.Android/Platform/PlatformSupport.cs +++ b/src/Android/Avalonia.Android/Platform/PlatformSupport.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading.Tasks; using Android.App; -using Android.Content; using Android.Content.PM; namespace Avalonia.Android.Platform; diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs index 365c9cdb42..31dae74b1f 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/FramebufferManager.cs @@ -1,4 +1,5 @@ -using Avalonia.Controls.Platform.Surfaces; +using System; +using Avalonia.Controls.Platform.Surfaces; using Avalonia.Platform; namespace Avalonia.Android.Platform.SkiaPlatform @@ -12,8 +13,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform _topLevel = topLevel; } - public ILockedFramebuffer Lock() => new AndroidFramebuffer(_topLevel.InternalView.Holder.Surface, _topLevel.RenderScaling); - + public ILockedFramebuffer Lock() => new AndroidFramebuffer( + _topLevel.InternalView.Holder?.Surface ?? throw new InvalidOperationException("TopLevel.InternalView.Holder.Surface was not expected to be null."), + _topLevel.RenderScaling); + public IFramebufferRenderTarget CreateFramebufferRenderTarget() => new FuncFramebufferRenderTarget(Lock); } } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index 3fb78591bc..0d9206f418 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -16,14 +16,19 @@ namespace Avalonia.Android readonly object _lock = new object(); private readonly Handler _handler; - IntPtr IPlatformHandle.Handle => - AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, Holder.Surface.Handle); + IntPtr IPlatformHandle.Handle => Holder?.Surface?.Handle is { } handle ? + AndroidFramebuffer.ANativeWindow_fromSurface(JNIEnv.Handle, handle) : + default; public InvalidationAwareSurfaceView(Context context) : base(context) { + if (Holder is null) + throw new InvalidOperationException( + "SurfaceView.Holder was not expected to be null during InvalidationAwareSurfaceView initialization."); + Holder.AddCallback(this); Holder.SetFormat(global::Android.Graphics.Format.Transparent); - _handler = new Handler(context.MainLooper); + _handler = new Handler(context.MainLooper!); } public override void Invalidate() @@ -34,7 +39,7 @@ namespace Avalonia.Android return; _handler.Post(() => { - if (Holder.Surface?.IsValid != true) + if (Holder?.Surface?.IsValid != true) return; try { @@ -77,8 +82,8 @@ namespace Avalonia.Android protected abstract void Draw(); public string HandleDescriptor => "SurfaceView"; - public PixelSize Size => new PixelSize(Holder.SurfaceFrame.Width(), Holder.SurfaceFrame.Height()); + public PixelSize Size => new(Holder?.SurfaceFrame?.Width() ?? 1, Holder?.SurfaceFrame?.Height() ?? 1); - public double Scaling => Resources.DisplayMetrics.Density; + public double Scaling => Resources?.DisplayMetrics?.Density ?? 1; } } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index 04840ace22..c790d658bf 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -40,66 +40,61 @@ namespace Avalonia.Android.Platform.SkiaPlatform private readonly AndroidMotionEventsHelper _pointerHelper; private readonly AndroidInputMethod _textInputMethod; private readonly INativeControlHostImpl _nativeControlHost; - private readonly IStorageProvider _storageProvider; + private readonly IStorageProvider? _storageProvider; private readonly AndroidSystemNavigationManagerImpl _systemNavigationManager; - private readonly AndroidInsetsManager _insetsManager; + private readonly AndroidInsetsManager? _insetsManager; private readonly ClipboardImpl _clipboard; - private readonly AndroidLauncher _launcher; + private readonly AndroidLauncher? _launcher; private ViewImpl _view; private WindowTransparencyLevel _transparencyLevel; public TopLevelImpl(AvaloniaView avaloniaView, bool placeOnTop = false) { + if (avaloniaView.Context is null) + { + throw new ArgumentException("AvaloniaView.Context must not be null"); + } + _view = new ViewImpl(avaloniaView.Context, this, placeOnTop); _textInputMethod = new AndroidInputMethod(_view); _keyboardHelper = new AndroidKeyboardEventsHelper(this); _pointerHelper = new AndroidMotionEventsHelper(this); _gl = new EglGlPlatformSurface(this); _framebuffer = new FramebufferManager(this); - _clipboard = new ClipboardImpl(avaloniaView.Context?.GetSystemService(Context.ClipboardService).JavaCast()); + _clipboard = new ClipboardImpl(avaloniaView.Context.GetSystemService(Context.ClipboardService).JavaCast()); RenderScaling = _view.Scaling; - MaxClientSize = new PixelSize(_view.Resources.DisplayMetrics.WidthPixels, - _view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling); - - if (avaloniaView.Context is AvaloniaMainActivity mainActivity) + if (avaloniaView.Context is Activity mainActivity) { _insetsManager = new AndroidInsetsManager(mainActivity, this); + _storageProvider = new AndroidStorageProvider(mainActivity); + _launcher = new AndroidLauncher(mainActivity); } _nativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); - _storageProvider = new AndroidStorageProvider((Activity)avaloniaView.Context); _transparencyLevel = WindowTransparencyLevel.None; - _launcher = new AndroidLauncher((Activity)avaloniaView.Context); _systemNavigationManager = new AndroidSystemNavigationManagerImpl(avaloniaView.Context as IActivityNavigationService); Surfaces = new object[] { _gl, _framebuffer, Handle }; } - public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) => - new Point(e.GetX(pointerIndex), e.GetY(pointerIndex)) / RenderScaling; - - public IInputRoot InputRoot { get; private set; } + public IInputRoot? InputRoot { get; private set; } public virtual Size ClientSize => _view.Size.ToSize(RenderScaling); public Size? FrameSize => null; + + public Action? Closed { get; set; } - public IMouseDevice MouseDevice { get; } = new MouseDevice(); - - public Action Closed { get; set; } - - public Action Input { get; set; } - - public Size MaxClientSize { get; protected set; } + public Action? Input { get; set; } - public Action Paint { get; set; } + public Action? Paint { get; set; } - public Action Resized { get; set; } + public Action? Resized { get; set; } - public Action ScalingChanged { get; set; } + public Action? ScalingChanged { get; set; } public View View => _view; @@ -109,8 +104,9 @@ namespace Avalonia.Android.Platform.SkiaPlatform public IEnumerable Surfaces { get; } - public Compositor Compositor => AndroidPlatform.Compositor; - + public Compositor Compositor => AndroidPlatform.Compositor ?? + throw new InvalidOperationException("Android backend wasn't initialized. Make sure .UseAndroid() was executed."); + public virtual void Hide() { _view.Visibility = ViewStates.Invisible; @@ -131,7 +127,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform return PixelPoint.FromPoint(point, RenderScaling); } - public void SetCursor(ICursorImpl cursor) + public void SetCursor(ICursorImpl? cursor) { //still not implemented } @@ -157,7 +153,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform { _systemNavigationManager.Dispose(); _view.Dispose(); - _view = null; + _view = null!; } protected virtual void OnResized(Size size) @@ -205,37 +201,34 @@ namespace Avalonia.Android.Platform.SkiaPlatform else { // Android 9 did this - canvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear); + canvas.DrawColor(Color.Transparent, PorterDuff.Mode.Clear!); } base.DispatchDraw(canvas); } - protected override bool DispatchGenericPointerEvent(MotionEvent e) + protected override bool DispatchGenericPointerEvent(MotionEvent? e) { - bool callBase; - bool? result = _tl._pointerHelper.DispatchMotionEvent(e, out callBase); - bool baseResult = callBase ? base.DispatchGenericPointerEvent(e) : false; + var result = _tl._pointerHelper.DispatchMotionEvent(e, out var callBase); + var baseResult = callBase && base.DispatchGenericPointerEvent(e); - return result != null ? result.Value : baseResult; + return result ?? baseResult; } - public override bool DispatchTouchEvent(MotionEvent e) + public override bool DispatchTouchEvent(MotionEvent? e) { - bool callBase; - bool? result = _tl._pointerHelper.DispatchMotionEvent(e, out callBase); - bool baseResult = callBase ? base.DispatchTouchEvent(e) : false; + var result = _tl._pointerHelper.DispatchMotionEvent(e, out var callBase); + var baseResult = callBase && base.DispatchTouchEvent(e); - return result != null ? result.Value : baseResult; + return result ?? baseResult; } - public override bool DispatchKeyEvent(KeyEvent e) + public override bool DispatchKeyEvent(KeyEvent? e) { - bool callBase; - bool? res = _tl._keyboardHelper.DispatchKeyEvent(e, out callBase); - bool baseResult = callBase ? base.DispatchKeyEvent(e) : false; + var res = _tl._keyboardHelper.DispatchKeyEvent(e, out var callBase); + var baseResult = callBase && base.DispatchKeyEvent(e); - return res != null ? res.Value : baseResult; + return res ?? baseResult; } void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height) @@ -256,29 +249,24 @@ namespace Avalonia.Android.Platform.SkiaPlatform return true; } - private Func _initEditorInfo; + private Func? _initEditorInfo; public void InitEditorInfo(Func init) { _initEditorInfo = init; } - public sealed override IInputConnection OnCreateInputConnection(EditorInfo outAttrs) + public sealed override IInputConnection OnCreateInputConnection(EditorInfo? outAttrs) { - if (_initEditorInfo != null) - { - return _initEditorInfo(_tl, outAttrs); - } - - return null; + return _initEditorInfo?.Invoke(_tl, outAttrs!)!; } } - public IPopupImpl CreatePopup() => null; + public IPopupImpl? CreatePopup() => null; - public Action LostFocus { get; set; } - public Action TransparencyLevelChanged { get; set; } + public Action? LostFocus { get; set; } + public Action? TransparencyLevelChanged { get; set; } public WindowTransparencyLevel TransparencyLevel { @@ -374,7 +362,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.White)); } - public virtual object TryGetFeature(Type featureType) + public virtual object? TryGetFeature(Type featureType) { if (featureType == typeof(IStorageProvider)) { @@ -443,7 +431,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform { if(Input != null) { - var args = new RawTextInputEventArgs(AndroidKeyboardDevice.Instance, (ulong)DateTime.Now.Ticks, InputRoot, text); + var args = new RawTextInputEventArgs(AndroidKeyboardDevice.Instance!, (ulong)DateTime.Now.Ticks, InputRoot!, text); Input(args); } @@ -464,7 +452,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform public bool IgnoreChange { get; set; } - public override IEditable Replace(int start, int end, ICharSequence tb) + public override IEditable? Replace(int start, int end, ICharSequence? tb) { if (!IgnoreChange && start != end) { @@ -474,7 +462,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform return base.Replace(start, end, tb); } - public override IEditable Replace(int start, int end, ICharSequence tb, int tbstart, int tbend) + public override IEditable? Replace(int start, int end, ICharSequence? tb, int tbstart, int tbend) { if (!IgnoreChange && start != end) { @@ -486,7 +474,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform private void SelectSurroundingTextForDeletion(int start, int end) { - _inputConnection.InputMethod.Client.Selection = new TextSelection(start, end); + _inputConnection.InputMethod.Client!.Selection = new TextSelection(start, end); } } @@ -522,8 +510,13 @@ namespace Avalonia.Android.Platform.SkiaPlatform return base.SetComposingRegion(start, end); } - public override bool SetComposingText(ICharSequence text, int newCursorPosition) + public override bool SetComposingText(ICharSequence? text, int newCursorPosition) { + if (InputMethod.Client is null || text is null) + { + return false; + } + BeginBatchEdit(); _editable.IgnoreChange = true; @@ -570,8 +563,13 @@ namespace Avalonia.Android.Platform.SkiaPlatform return base.EndBatchEdit(); } - public override bool CommitText(ICharSequence text, int newCursorPosition) + public override bool CommitText(ICharSequence? text, int newCursorPosition) { + if (InputMethod.Client is null || text is null) + { + return false; + } + BeginBatchEdit(); _commitInProgress = true; @@ -639,7 +637,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform return base.PerformEditorAction(actionCode); } - public override ExtractedText GetExtractedText(ExtractedTextRequest request, [GeneratedEnum] GetTextFlags flags) + public override ExtractedText? GetExtractedText(ExtractedTextRequest? request, [GeneratedEnum] GetTextFlags flags) { if (request == null) return null; diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs index fc5ce3a71b..5a8e549ff2 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyInterop.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System.Collections.Generic; +using System.Collections.Generic; using Avalonia.Input; namespace Avalonia.Android.Platform.Specific.Helpers; diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs index 7e220d3f9a..a97c42577e 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs @@ -1,5 +1,3 @@ -#nullable enable - using System; using System.Runtime.Versioning; using Android.Views; @@ -22,9 +20,9 @@ namespace Avalonia.Android.Platform.Specific.Helpers HandleEvents = true; } - public bool? DispatchKeyEvent(KeyEvent e, out bool callBase) + public bool? DispatchKeyEvent(KeyEvent? e, out bool callBase) { - if (!HandleEvents) + if (!HandleEvents || e is null) { callBase = true; return null; @@ -46,8 +44,10 @@ namespace Avalonia.Android.Platform.Specific.Helpers private bool? DispatchKeyEventInternal(KeyEvent e, out bool callBase) { var unicodeTextInput = OperatingSystem.IsAndroidVersionAtLeast(29) ? null : UnicodeTextInput(e); + var inputRoot = _view.InputRoot; - if (e.Action == KeyEventActions.Multiple && unicodeTextInput == null) + if ((e.Action == KeyEventActions.Multiple && unicodeTextInput == null) + || inputRoot is null) { callBase = true; return null; @@ -60,7 +60,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers var rawKeyEvent = new RawKeyEventArgs( AndroidKeyboardDevice.Instance!, Convert.ToUInt64(e.EventTime), - _view.InputRoot, + inputRoot, e.Action == KeyEventActions.Down ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp, AndroidKeyboardDevice.ConvertKey(e.KeyCode), GetModifierKeys(e), @@ -76,7 +76,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers var rawTextEvent = new RawTextInputEventArgs( AndroidKeyboardDevice.Instance!, Convert.ToUInt64(e.EventTime), - _view.InputRoot, + inputRoot, unicodeTextInput ?? Convert.ToChar(e.UnicodeChar).ToString() ); _view.Input?.Invoke(rawTextEvent); diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs index d11054da60..183604bbea 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidMotionEventsHelper.cs @@ -8,8 +8,6 @@ using Avalonia.Collections.Pooled; using Avalonia.Input; using Avalonia.Input.Raw; -#nullable enable - namespace Avalonia.Android.Platform.Specific.Helpers { internal class AndroidMotionEventsHelper : IDisposable @@ -30,16 +28,19 @@ namespace Avalonia.Android.Platform.Specific.Helpers _view = view; } - public bool? DispatchMotionEvent(MotionEvent e, out bool callBase) + public bool? DispatchMotionEvent(MotionEvent? e, out bool callBase) { callBase = true; - if (_disposed) + if (_disposed || e is null) { return null; } var eventTime = (ulong)e.EventTime; var inputRoot = _view.InputRoot; + if (inputRoot is null) + return false; // too early to handle events. + var actionMasked = e.ActionMasked; var modifiers = GetModifiers(e.MetaState, e.ButtonState); @@ -75,7 +76,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers return s_intermediatePointsPooledList; }) }; - _view.Input(args); + _view.Input?.Invoke(args); } } else @@ -90,7 +91,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers { var delta = new Vector(e.GetAxisValue(Axis.Hscroll), e.GetAxisValue(Axis.Vscroll)); var args = new RawMouseWheelEventArgs(device, eventTime, inputRoot, point.Position, delta, RawInputModifiers.None); - _view.Input(args); + _view.Input?.Invoke(args); } else { @@ -98,7 +99,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers if (eventType >= 0) { var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)); - _view.Input(args); + _view.Input?.Invoke(args); } } } diff --git a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs index 0b51350419..0c606ee07f 100644 --- a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs +++ b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageItem.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -8,7 +6,6 @@ using System.Threading.Tasks; using Android; using Android.App; using Android.Content; -using Android.OS; using Android.Provider; using Android.Webkit; using AndroidX.DocumentFile.Provider; @@ -136,7 +133,7 @@ internal abstract class AndroidStorageItem : IStorageBookmarkItem return true; } - return await _activity.CheckPermission(Manifest.Permission.ReadExternalStorage); + return await _activity!.CheckPermission(Manifest.Permission.ReadExternalStorage); } public void Dispose() diff --git a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs index daf1111bea..64c9c3a3cb 100644 --- a/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs +++ b/src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs @@ -1,6 +1,4 @@ -#nullable enable - -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -9,7 +7,6 @@ using Android.App; using Android.Content; using Android.Provider; using Avalonia.Platform.Storage; -using Java.Lang; using AndroidUri = Android.Net.Uri; using Exception = System.Exception; using JavaFile = Java.IO.File; @@ -244,7 +241,7 @@ internal class AndroidStorageProvider : IStorageProvider return resultList; - void OnActivityResult(int requestCode, Result resultCode, Intent data) + void OnActivityResult(int requestCode, Result resultCode, Intent? data) { if (currentRequestCode != requestCode) { diff --git a/src/Android/Avalonia.Android/SingleViewLifetime.cs b/src/Android/Avalonia.Android/SingleViewLifetime.cs index f525a2773a..e71f4e0333 100644 --- a/src/Android/Avalonia.Android/SingleViewLifetime.cs +++ b/src/Android/Avalonia.Android/SingleViewLifetime.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; diff --git a/src/Android/Avalonia.Android/Stubs.cs b/src/Android/Avalonia.Android/Stubs.cs index 05638cdf88..21df905bb6 100644 --- a/src/Android/Avalonia.Android/Stubs.cs +++ b/src/Android/Avalonia.Android/Stubs.cs @@ -10,7 +10,7 @@ namespace Avalonia.Android public IWindowImpl CreateEmbeddableWindow() => throw new NotSupportedException(); - public ITrayIconImpl CreateTrayIcon() => null; + public ITrayIconImpl? CreateTrayIcon() => null; } internal class PlatformIconLoaderStub : IPlatformIconLoader diff --git a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs index 5c2e320383..815452bf30 100644 --- a/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs +++ b/src/Headless/Avalonia.Headless/HeadlessWindowImpl.cs @@ -108,7 +108,6 @@ namespace Avalonia.Headless public Action? Deactivated { get; set; } public Action? Activated { get; set; } public IPlatformHandle Handle { get; } = new PlatformHandle(IntPtr.Zero, "STUB"); - public Size MaxClientSize { get; } = new Size(1920, 1280); public void Resize(Size clientSize, WindowResizeReason reason) { if (ClientSize == clientSize) diff --git a/tests/Avalonia.UnitTests/TestRoot.cs b/tests/Avalonia.UnitTests/TestRoot.cs index ae62301d69..27ec987e7c 100644 --- a/tests/Avalonia.UnitTests/TestRoot.cs +++ b/tests/Avalonia.UnitTests/TestRoot.cs @@ -50,8 +50,6 @@ namespace Avalonia.UnitTests public Size ClientSize { get; set; } = new Size(1000, 1000); - public Size MaxClientSize { get; set; } = Size.Infinity; - public double LayoutScaling { get; set; } = 1; internal ILayoutManager LayoutManager { get; set; }