diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index b0692905e7..52f687ffab 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -37,5 +37,6 @@
<Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
True
+ True
True
True
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index 6a941c21ae..2b55c5bad8 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -3,6 +3,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
+using Avalonia.Platform;
using Avalonia.Styling;
using Avalonia.Themes.Simple;
using Avalonia.Themes.Fluent;
@@ -51,7 +52,7 @@ namespace ControlCatalog
singleViewLifetime.MainView = new MainView { DataContext = new MainWindowViewModel() };
}
- if (ApplicationLifetime is IActivatableApplicationLifetime activatableApplicationLifetime)
+ if (this.TryGetFeature() is {} activatableApplicationLifetime)
{
activatableApplicationLifetime.Activated += (sender, args) =>
Console.WriteLine($"App activated: {args.Kind}");
diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
index b1ce10df24..39b00590f3 100644
--- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
+++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs
@@ -3,6 +3,7 @@ using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using System.Security;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
@@ -43,7 +44,7 @@ namespace ControlCatalog.Pages
{
lastSelectedDirectory = await GetStorageProvider().TryGetWellKnownFolderAsync(folderEnum);
}
- else
+ else if (!string.IsNullOrWhiteSpace(currentFolderBox.Text))
{
if (!Uri.TryCreate(currentFolderBox.Text, UriKind.Absolute, out var folderLink))
{
@@ -52,7 +53,14 @@ namespace ControlCatalog.Pages
if (folderLink is not null)
{
- lastSelectedDirectory = await GetStorageProvider().TryGetFolderFromPathAsync(folderLink);
+ try
+ {
+ lastSelectedDirectory = await GetStorageProvider().TryGetFolderFromPathAsync(folderLink);
+ }
+ catch (SecurityException)
+ {
+
+ }
}
}
};
diff --git a/src/Android/Avalonia.Android/AndroidPlatform.cs b/src/Android/Avalonia.Android/AndroidPlatform.cs
index f3dcb3560c..4ed759c78b 100644
--- a/src/Android/Avalonia.Android/AndroidPlatform.cs
+++ b/src/Android/Avalonia.Android/AndroidPlatform.cs
@@ -5,6 +5,7 @@ using Avalonia.Controls;
using Avalonia.Android;
using Avalonia.Android.Platform;
using Avalonia.Android.Platform.Input;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.OpenGL.Egl;
@@ -81,7 +82,8 @@ namespace Avalonia.Android
.Bind().ToConstant(new AndroidThreadingInterface())
.Bind().ToSingleton()
.Bind().ToConstant(new ChoreographerTimer())
- .Bind().ToSingleton();
+ .Bind().ToSingleton()
+ .Bind().ToConstant(new AndroidActivatableLifetime());
var graphics = InitializeGraphics(Options);
if (graphics is not null)
diff --git a/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs b/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs
index cf258a5a1f..f203b6c544 100644
--- a/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs
+++ b/src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs
@@ -1,5 +1,9 @@
#nullable enable
+using Avalonia.Android.Platform;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Platform;
+
namespace Avalonia.Android
{
partial class AvaloniaMainActivity where TApp : Application, new()
@@ -36,11 +40,17 @@ namespace Avalonia.Android
{
var builder = CreateAppBuilder();
- builder.SetupWithLifetime(new SingleViewLifetime(this));
+ builder.SetupWithLifetime(new SingleViewLifetime());
s_appBuilder = builder;
}
+ if (Avalonia.Application.Current?.TryGetFeature()
+ is AndroidActivatableLifetime activatableLifetime)
+ {
+ activatableLifetime.Activity = this;
+ }
+
View = new AvaloniaView(this);
if (ViewContent != null)
{
diff --git a/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs b/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs
new file mode 100644
index 0000000000..f8cf0d946a
--- /dev/null
+++ b/src/Android/Avalonia.Android/Platform/AndroidActivatableLifetime.cs
@@ -0,0 +1,47 @@
+using System;
+using Android.App;
+using Avalonia.Controls.ApplicationLifetimes;
+
+namespace Avalonia.Android.Platform;
+
+internal class AndroidActivatableLifetime : IActivatableLifetime
+{
+ private IAvaloniaActivity _activity;
+
+ public IAvaloniaActivity Activity
+ {
+ get => _activity;
+ set
+ {
+ if (_activity is not null)
+ {
+ _activity.Activated -= ActivityOnActivated;
+ _activity.Deactivated -= ActivityOnDeactivated;
+ }
+
+ _activity = value;
+
+ if (_activity is not null)
+ {
+ _activity.Activated += ActivityOnActivated;
+ _activity.Deactivated += ActivityOnDeactivated;
+ }
+ }
+ }
+
+ public event EventHandler Activated;
+ public event EventHandler Deactivated;
+
+ public bool TryLeaveBackground() => (_activity as Activity)?.MoveTaskToBack(true) == true;
+ public bool TryEnterBackground() => false;
+
+ private void ActivityOnDeactivated(object sender, ActivatedEventArgs e)
+ {
+ Deactivated?.Invoke(this, e);
+ }
+
+ private void ActivityOnActivated(object sender, ActivatedEventArgs e)
+ {
+ Activated?.Invoke(this, e);
+ }
+}
diff --git a/src/Android/Avalonia.Android/SingleViewLifetime.cs b/src/Android/Avalonia.Android/SingleViewLifetime.cs
index 2b6b4d3359..c912d2f890 100644
--- a/src/Android/Avalonia.Android/SingleViewLifetime.cs
+++ b/src/Android/Avalonia.Android/SingleViewLifetime.cs
@@ -1,25 +1,11 @@
-using System;
-using Android.App;
-using Avalonia.Controls;
+using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.Android
{
- internal class SingleViewLifetime : ISingleViewApplicationLifetime, IActivatableApplicationLifetime
+ internal class SingleViewLifetime : ISingleViewApplicationLifetime
{
- private readonly Activity _activity;
private AvaloniaView _view;
-
- public SingleViewLifetime(Activity activity)
- {
- _activity = activity;
-
- if (activity is IAvaloniaActivity activableActivity)
- {
- activableActivity.Activated += (_, args) => Activated?.Invoke(this, args);
- activableActivity.Deactivated += (_, args) => Deactivated?.Invoke(this, args);
- }
- }
public AvaloniaView View
{
@@ -36,10 +22,5 @@ namespace Avalonia.Android
}
public Control MainView { get; set; }
- public event EventHandler Activated;
- public event EventHandler Deactivated;
-
- public bool TryLeaveBackground() => _activity.MoveTaskToBack(true);
- public bool TryEnterBackground() => false;
}
}
diff --git a/src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs b/src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs
index 1778031e5b..27c2243791 100644
--- a/src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs
+++ b/src/Avalonia.Base/Platform/IOptionalFeatureProvider.cs
@@ -1,22 +1,25 @@
using System;
using System.Diagnostics.CodeAnalysis;
+// TODO12: move to Avalonia namespace.
namespace Avalonia.Platform;
public interface IOptionalFeatureProvider
{
///
- /// Queries for an optional feature
+ /// Queries for an optional feature.
///
- /// Feature type
+ /// Feature type.
public object? TryGetFeature(Type featureType);
}
public static class OptionalFeatureProviderExtensions
{
+ ///
public static T? TryGetFeature(this IOptionalFeatureProvider provider) where T : class =>
(T?)provider.TryGetFeature(typeof(T));
+ ///
public static bool TryGetFeature(this IOptionalFeatureProvider provider, [MaybeNullWhen(false)] out T rv)
where T : class
{
diff --git a/src/Avalonia.Controls/AppBuilder.cs b/src/Avalonia.Controls/AppBuilder.cs
index 3275f35989..b77ce7ebb2 100644
--- a/src/Avalonia.Controls/AppBuilder.cs
+++ b/src/Avalonia.Controls/AppBuilder.cs
@@ -1,4 +1,5 @@
using System;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Linq;
@@ -58,6 +59,8 @@ namespace Avalonia
///
/// Gets a method to override a lifetime factory.
///
+ [Obsolete("This property has no effect", true)]
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
public Func? LifetimeOverride { get; private set; }
///
@@ -244,13 +247,6 @@ namespace Avalonia
return Self;
}
- [PrivateApi]
- public AppBuilder UseLifetimeOverride(Func func)
- {
- LifetimeOverride = func;
- return Self;
- }
-
///
/// Configures platform-specific options
///
diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs
index 46b31bff3e..6b8ddc15ea 100644
--- a/src/Avalonia.Controls/Application.cs
+++ b/src/Avalonia.Controls/Application.cs
@@ -30,7 +30,7 @@ namespace Avalonia
/// method.
/// - Tracks the lifetime of the application.
///
- public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IApplicationPlatformEvents
+ public class Application : AvaloniaObject, IDataContextProvider, IGlobalDataTemplates, IGlobalStyles, IThemeVariantHost, IApplicationPlatformEvents, IOptionalFeatureProvider
{
///
/// The application-global data templates.
@@ -62,7 +62,7 @@ namespace Avalonia
///
public event EventHandler? ResourcesChanged;
- [Obsolete("Cast ApplicationLifetime to IActivatableApplicationLifetime instead.")]
+ [Obsolete("Use Application.Current.TryGetFeature() instead.")]
public event EventHandler? UrlsOpened;
///
@@ -204,7 +204,7 @@ namespace Avalonia
/// which should always be preferred over a global one,
/// as specific top levels might have different settings set-up.
///
- public IPlatformSettings? PlatformSettings => AvaloniaLocator.Current.GetService();
+ public IPlatformSettings? PlatformSettings => this.TryGetFeature();
event Action>? IGlobalStyles.GlobalStylesAdded
{
@@ -329,7 +329,34 @@ namespace Avalonia
get => _name;
set => SetAndRaise(NameProperty, ref _name, value);
}
-
+
+ ///
+ /// Queries for an optional feature.
+ ///
+ /// Feature type.
+ ///
+ /// Features currently supported by :
+ ///
+ /// - IPlatformSettings
+ /// - IActivatableApplicationLifetime
+ ///
+ ///
+ public object? TryGetFeature(Type featureType)
+ {
+ if (featureType == typeof(IPlatformSettings))
+ {
+ return AvaloniaLocator.Current.GetService();
+ }
+
+ if (featureType == typeof(IActivatableLifetime))
+ {
+ return AvaloniaLocator.Current.GetService();
+ }
+
+ // Do not return just any service from AvaloniaLocator.
+ return null;
+ }
+
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
index 7b3de3306b..497be9d671 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
@@ -217,8 +217,7 @@ namespace Avalonia
private static ClassicDesktopStyleApplicationLifetime PrepareLifetime(AppBuilder builder, string[] args,
Action? lifetimeBuilder)
{
- var lifetime = builder.LifetimeOverride?.Invoke(typeof(ClassicDesktopStyleApplicationLifetime)) as ClassicDesktopStyleApplicationLifetime
- ?? new ClassicDesktopStyleApplicationLifetime();
+ var lifetime = new ClassicDesktopStyleApplicationLifetime();
lifetime.SubscribeGlobalEvents();
lifetime.Args = args;
diff --git a/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
index eb050e63d1..e07e8cd6a1 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
@@ -1,13 +1,20 @@
using System;
+using System.Diagnostics;
using Avalonia.Metadata;
namespace Avalonia.Controls.ApplicationLifetimes;
+[NotClientImplementable]
+[Obsolete("This interface has no effect. Instead use Application.Current.TryGetFeature().", true)]
+public interface IActivatableApplicationLifetime : IActivatableLifetime {
+
+}
+
///
/// An interface for ApplicationLifetimes where the application can be Activated and Deactivated.
///
[NotClientImplementable]
-public interface IActivatableApplicationLifetime
+public interface IActivatableLifetime
{
///
/// An event that is raised when the application is Activated for various reasons
diff --git a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs
index 212088d4cd..298ef5619a 100644
--- a/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs
+++ b/src/Avalonia.Native/AvaloniaNativeApplicationPlatform.cs
@@ -9,18 +9,18 @@ namespace Avalonia.Native
internal class AvaloniaNativeApplicationPlatform : NativeCallbackBase, IAvnApplicationEvents, IPlatformLifetimeEventsImpl
{
public event EventHandler ShutdownRequested;
-
+
void IAvnApplicationEvents.FilesOpened(IAvnStringArray urls)
{
- ((IApplicationPlatformEvents)Application.Current).RaiseUrlsOpened(urls.ToStringArray());
+ ((IApplicationPlatformEvents)Application.Current)?.RaiseUrlsOpened(urls.ToStringArray());
}
-
+
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 (Application.Current?.ApplicationLifetime is MacOSClassicDesktopStyleApplicationLifetime lifetime)
+ if (AvaloniaLocator.Current.GetService() is MacOSActivatableLifetime lifetime)
{
foreach (var url in urls.ToStringArray())
{
@@ -34,7 +34,7 @@ namespace Avalonia.Native
void IAvnApplicationEvents.OnReopen()
{
- if (Application.Current?.ApplicationLifetime is MacOSClassicDesktopStyleApplicationLifetime lifetime)
+ if (AvaloniaLocator.Current.GetService() is MacOSActivatableLifetime lifetime)
{
lifetime.RaiseActivated(ActivationKind.Reopen);
}
@@ -42,7 +42,7 @@ namespace Avalonia.Native
void IAvnApplicationEvents.OnHide()
{
- if (Application.Current?.ApplicationLifetime is MacOSClassicDesktopStyleApplicationLifetime lifetime)
+ if (AvaloniaLocator.Current.GetService() is MacOSActivatableLifetime lifetime)
{
lifetime.RaiseDeactivated(ActivationKind.Background);
}
@@ -50,7 +50,7 @@ namespace Avalonia.Native
void IAvnApplicationEvents.OnUnhide()
{
- if (Application.Current?.ApplicationLifetime is MacOSClassicDesktopStyleApplicationLifetime lifetime)
+ if (AvaloniaLocator.Current.GetService() is MacOSActivatableLifetime lifetime)
{
lifetime.RaiseActivated(ActivationKind.Background);
}
diff --git a/src/Avalonia.Native/AvaloniaNativePlatform.cs b/src/Avalonia.Native/AvaloniaNativePlatform.cs
index 85331bea6b..f218103b18 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatform.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatform.cs
@@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Compatibility;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls.Platform;
using Avalonia.Input;
using Avalonia.Input.Platform;
@@ -112,7 +113,8 @@ namespace Avalonia.Native
.Bind().ToConstant(new MacOSMountedVolumeInfoProvider())
.Bind().ToConstant(new AvaloniaNativeDragSource(_factory))
.Bind().ToConstant(applicationPlatform)
- .Bind().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands()));
+ .Bind().ToConstant(new MacOSNativeMenuCommands(_factory.CreateApplicationCommands()))
+ .Bind().ToSingleton();
var hotkeys = new PlatformHotkeyConfiguration(KeyModifiers.Meta, wholeWordTextActionModifiers: KeyModifiers.Alt);
hotkeys.MoveCursorToTheStartOfLine.Add(new KeyGesture(Key.Left, hotkeys.CommandModifiers));
diff --git a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
index 1956e214fb..d5fffbbff0 100644
--- a/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
+++ b/src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs
@@ -23,9 +23,7 @@ namespace Avalonia
platform.SetupApplicationName();
platform.SetupApplicationMenuExporter();
});
- })
- .UseLifetimeOverride(type => type == typeof(ClassicDesktopStyleApplicationLifetime)
- ? new MacOSClassicDesktopStyleApplicationLifetime() : null);
+ });
return builder;
}
diff --git a/src/Avalonia.Native/MacOSClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Native/MacOSActivatableLifetime.cs
similarity index 89%
rename from src/Avalonia.Native/MacOSClassicDesktopStyleApplicationLifetime.cs
rename to src/Avalonia.Native/MacOSActivatableLifetime.cs
index caf6e03ec8..54dfab6132 100644
--- a/src/Avalonia.Native/MacOSClassicDesktopStyleApplicationLifetime.cs
+++ b/src/Avalonia.Native/MacOSActivatableLifetime.cs
@@ -6,8 +6,7 @@ namespace Avalonia.Native;
#nullable enable
-internal class MacOSClassicDesktopStyleApplicationLifetime : ClassicDesktopStyleApplicationLifetime,
- IActivatableApplicationLifetime
+internal class MacOSActivatableLifetime : IActivatableLifetime
{
///
public event EventHandler? Activated;
diff --git a/src/Browser/Avalonia.Browser/BrowserActivatableLifetime.cs b/src/Browser/Avalonia.Browser/BrowserActivatableLifetime.cs
new file mode 100644
index 0000000000..30996d55df
--- /dev/null
+++ b/src/Browser/Avalonia.Browser/BrowserActivatableLifetime.cs
@@ -0,0 +1,36 @@
+using System;
+using Avalonia.Browser.Interop;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Threading;
+
+namespace Avalonia.Browser;
+
+internal class BrowserActivatableLifetime : IActivatableLifetime
+{
+ public BrowserActivatableLifetime()
+ {
+ bool? initiallyVisible = InputHelper.SubscribeVisibilityChange(visible =>
+ {
+ initiallyVisible = null;
+ (visible ? Activated : Deactivated)?.Invoke(this, new ActivatedEventArgs(ActivationKind.Background));
+ });
+
+ // Trigger Activated as an initial state, if web page is visible, and wasn't hidden during initialization.
+ if (initiallyVisible == true)
+ {
+ _ = Dispatcher.UIThread.InvokeAsync(() =>
+ {
+ if (initiallyVisible == true)
+ {
+ Activated?.Invoke(this, new ActivatedEventArgs(ActivationKind.Background));
+ }
+ }, DispatcherPriority.Background);
+ }
+ }
+
+ public event EventHandler? Activated;
+ public event EventHandler? Deactivated;
+
+ public bool TryLeaveBackground() => false;
+ public bool TryEnterBackground() => false;
+}
diff --git a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
index e568067b74..ba404c2600 100644
--- a/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
+++ b/src/Browser/Avalonia.Browser/BrowserSingleViewLifetime.cs
@@ -2,24 +2,12 @@
using System.Diagnostics.CodeAnalysis;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
-using System.Runtime.Versioning;
using Avalonia.Browser;
-using Avalonia.Browser.Interop;
-using Avalonia.Threading;
namespace Avalonia;
-internal class BrowserSingleViewLifetime : ISingleViewApplicationLifetime, IActivatableApplicationLifetime
+internal class BrowserSingleViewLifetime : ISingleViewApplicationLifetime
{
- public BrowserSingleViewLifetime()
- {
- bool? initiallyVisible = InputHelper.SubscribeVisibilityChange(visible =>
- {
- initiallyVisible = null;
- (visible ? Activated : Deactivated)?.Invoke(this, new ActivatedEventArgs(ActivationKind.Background));
- });
- }
-
public AvaloniaView? View;
public Control? MainView
@@ -44,10 +32,4 @@ internal class BrowserSingleViewLifetime : ISingleViewApplicationLifetime, IActi
throw new InvalidOperationException("Browser lifetime was not initialized. Make sure AppBuilder.StartBrowserApp was called.");
}
}
-
- public event EventHandler? Activated;
- public event EventHandler? Deactivated;
-
- public bool TryLeaveBackground() => false;
- public bool TryEnterBackground() => false;
}
diff --git a/src/Browser/Avalonia.Browser/WindowingPlatform.cs b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
index 2db0e2aec3..27e5537431 100644
--- a/src/Browser/Avalonia.Browser/WindowingPlatform.cs
+++ b/src/Browser/Avalonia.Browser/WindowingPlatform.cs
@@ -1,6 +1,7 @@
using System;
using Avalonia.Browser.Interop;
using Avalonia.Browser.Skia;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Platform;
@@ -43,7 +44,8 @@ internal class BrowserWindowingPlatform : IWindowingPlatform
.Bind().ToConstant(instance)
.Bind().ToConstant(new BrowserSkiaGraphics())
.Bind().ToSingleton()
- .Bind().ToSingleton();
+ .Bind().ToSingleton()
+ .Bind().ToSingleton();
if (AvaloniaLocator.Current.GetService() is { } options
&& options.RegisterAvaloniaServiceWorker)
diff --git a/src/iOS/Avalonia.iOS/ActivatableLifetime.cs b/src/iOS/Avalonia.iOS/ActivatableLifetime.cs
new file mode 100644
index 0000000000..c3e2ddedde
--- /dev/null
+++ b/src/iOS/Avalonia.iOS/ActivatableLifetime.cs
@@ -0,0 +1,18 @@
+using System;
+using Avalonia.Controls.ApplicationLifetimes;
+
+namespace Avalonia.iOS;
+
+internal class ActivatableLifetime : IActivatableLifetime
+{
+ public ActivatableLifetime(IAvaloniaAppDelegate avaloniaAppDelegate)
+ {
+ avaloniaAppDelegate.Activated += (_, args) => Activated?.Invoke(this, args);
+ avaloniaAppDelegate.Deactivated += (_, args) => Deactivated?.Invoke(this, args);
+ }
+
+ public event EventHandler? Activated;
+ public event EventHandler? Deactivated;
+ public bool TryLeaveBackground() => false;
+ public bool TryEnterBackground() => false;
+}
diff --git a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
index e4ec20bbbd..7a07fab2fe 100644
--- a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
+++ b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
@@ -42,9 +42,9 @@ namespace Avalonia.iOS
[Export("application:didFinishLaunchingWithOptions:")]
public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
- var builder = AppBuilder.Configure().UseiOS();
+ var builder = AppBuilder.Configure().UseiOS(this);
- var lifetime = new SingleViewLifetime(this);
+ var lifetime = new SingleViewLifetime();
builder.AfterSetup(_ =>
{
diff --git a/src/iOS/Avalonia.iOS/Platform.cs b/src/iOS/Avalonia.iOS/Platform.cs
index 07c212a01a..57d31f773c 100644
--- a/src/iOS/Avalonia.iOS/Platform.cs
+++ b/src/iOS/Avalonia.iOS/Platform.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input;
using Avalonia.Input.Platform;
+using Avalonia.iOS;
using Avalonia.Platform;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
@@ -39,13 +41,15 @@ namespace Avalonia
public static class IOSApplicationExtensions
{
- public static AppBuilder UseiOS(this AppBuilder builder)
+ public static AppBuilder UseiOS(this AppBuilder builder, IAvaloniaAppDelegate appDelegate)
{
return builder
.UseStandardRuntimePlatformSubsystem()
- .UseWindowingSubsystem(iOS.Platform.Register, "iOS")
+ .UseWindowingSubsystem(() => iOS.Platform.Register(appDelegate), "iOS")
.UseSkia();
}
+
+ public static AppBuilder UseiOS(this AppBuilder builder) => UseiOS(builder, null!);
}
}
@@ -58,7 +62,7 @@ namespace Avalonia.iOS
public static DisplayLinkTimer? Timer;
internal static Compositor? Compositor { get; private set; }
- public static void Register()
+ public static void Register(IAvaloniaAppDelegate? appDelegate)
{
Options = AvaloniaLocator.Current.GetService() ?? new iOSPlatformOptions();
@@ -77,6 +81,12 @@ namespace Avalonia.iOS
.Bind().ToConstant(DispatcherImpl.Instance)
.Bind().ToConstant(keyboard);
+ if (appDelegate is not null)
+ {
+ AvaloniaLocator.CurrentMutable
+ .Bind().ToConstant(new ActivatableLifetime(appDelegate));
+ }
+
Compositor = new Compositor(AvaloniaLocator.Current.GetService());
AvaloniaLocator.CurrentMutable.Bind().ToConstant(Compositor);
}
diff --git a/src/iOS/Avalonia.iOS/SingleViewLifetime.cs b/src/iOS/Avalonia.iOS/SingleViewLifetime.cs
index 9627700c7f..49b8e97769 100644
--- a/src/iOS/Avalonia.iOS/SingleViewLifetime.cs
+++ b/src/iOS/Avalonia.iOS/SingleViewLifetime.cs
@@ -4,14 +4,8 @@ using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.iOS;
-internal class SingleViewLifetime : ISingleViewApplicationLifetime, IActivatableApplicationLifetime
-{
- public SingleViewLifetime(IAvaloniaAppDelegate avaloniaAppDelegate)
- {
- avaloniaAppDelegate.Activated += (_, args) => Activated?.Invoke(this, args);
- avaloniaAppDelegate.Deactivated += (_, args) => Deactivated?.Invoke(this, args);
- }
-
+internal class SingleViewLifetime : ISingleViewApplicationLifetime
+{
public AvaloniaView? View;
public Control? MainView
@@ -19,9 +13,4 @@ internal class SingleViewLifetime : ISingleViewApplicationLifetime, IActivatable
get => View!.Content;
set => View!.Content = value;
}
-
- public event EventHandler? Activated;
- public event EventHandler? Deactivated;
- public bool TryLeaveBackground() => false;
- public bool TryEnterBackground() => false;
}