Browse Source

Added ShutdownRequested to IClassicDesktopStyleApplicationLifetime.

Steven Kirk 4 years ago
parent
commit
298dd4e299

+ 8 - 2
src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs

@@ -46,6 +46,10 @@ namespace Avalonia.Controls.ApplicationLifetimes
 
         /// <inheritdoc/>
         public event EventHandler<ControlledApplicationLifetimeStartupEventArgs> Startup;
+
+        /// <inheritdoc/>
+        public event EventHandler<CancelEventArgs> ShutdownRequested;
+
         /// <inheritdoc/>
         public event EventHandler<ControlledApplicationLifetimeExitEventArgs> Exit;
 
@@ -115,7 +119,7 @@ namespace Avalonia.Controls.ApplicationLifetimes
             var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>(); 
 
             if (lifetimeEvents != null)
-                lifetimeEvents.ShutdownRequested += ShutdownRequested;
+                lifetimeEvents.ShutdownRequested += OnShutdownRequested;
 
             _cts = new CancellationTokenSource();
             MainWindow?.Show();
@@ -130,8 +134,10 @@ namespace Avalonia.Controls.ApplicationLifetimes
                 _activeLifetime = null;
         }
         
-        private void ShutdownRequested(object sender, CancelEventArgs e)
+        private void OnShutdownRequested(object sender, CancelEventArgs e)
         {
+            ShutdownRequested?.Invoke(this, e);
+
             if (e.Cancel)
                 return;
 

+ 12 - 0
src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 
 namespace Avalonia.Controls.ApplicationLifetimes
 {
@@ -34,5 +35,16 @@ namespace Avalonia.Controls.ApplicationLifetimes
         Window MainWindow { get; set; }
         
         IReadOnlyList<Window> Windows { get; }
+
+        /// <summary>
+        /// Raised by the platform when a shutdown is requested.
+        /// </summary>
+        /// <remarks>
+        /// Raised on on OSX via the Quit menu or right-clicking on the application icon and selecting Quit. This event
+        /// provides a first-chance to cancel application shutdown; if shutdown is not canceled at this point the application
+        /// will try to close each non-owned open window, invoking the <see cref="Window.Closing"/> event on each and allowing
+        /// each window to cancel the shutdown.
+        /// </remarks>
+        event EventHandler<CancelEventArgs> ShutdownRequested;
     }
 }

+ 29 - 1
tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.ComponentModel;
 using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Platform;
 using Avalonia.Threading;
@@ -209,6 +210,33 @@ namespace Avalonia.Controls.UnitTests
                 Assert.Empty(lifetime.Windows);
             }
         }
+
+        [Fact]
+        public void Should_Allow_Canceling_Shutdown_Via_ShutdownRequested_Event()
+        {
+            using (UnitTestApplication.Start(TestServices.StyledWindow))
+            using (var lifetime = new ClassicDesktopStyleApplicationLifetime())
+            {
+                var lifetimeEvents = new Mock<IPlatformLifetimeEventsImpl>();
+                AvaloniaLocator.CurrentMutable.Bind<IPlatformLifetimeEventsImpl>().ToConstant(lifetimeEvents.Object);
+                lifetime.Start(Array.Empty<string>());
+
+                var window = new Window();
+                var raised = 0;
+
+                window.Show();
+
+                lifetime.ShutdownRequested += (s, e) =>
+                {
+                    e.Cancel = true;
+                    ++raised;
+                };
+
+                lifetimeEvents.Raise(x => x.ShutdownRequested += null, new CancelEventArgs());
+
+                Assert.Equal(1, raised);
+                Assert.Equal(new[] { window }, lifetime.Windows);
+            }
+        }
     }
-    
 }