diff --git a/src/UniGetUI.Avalonia/App.axaml.cs b/src/UniGetUI.Avalonia/App.axaml.cs index 1d75b8aa7..29bb3200e 100644 --- a/src/UniGetUI.Avalonia/App.axaml.cs +++ b/src/UniGetUI.Avalonia/App.axaml.cs @@ -122,6 +122,24 @@ private static void StartMainWindow(IClassicDesktopStyleApplicationLifetime desk AvaloniaAppHost.SecondaryInstanceArgsReceived += args => HandleSecondaryInstanceArgs(mainWindow, args); + desktop.ShutdownRequested += (_, e) => + { + if (mainWindow.IsQuitting) + return; + + e.Cancel = true; + mainWindow.QuitApplication(); + }; + + if (Current?.TryGetFeature() is { } activatable) + { + activatable.Activated += (_, e) => + { + if (e.Kind == ActivationKind.Reopen) + mainWindow.ShowFromTray(); + }; + } + if (CoreData.WasDaemon) { // Start silently: hide the window on first open only. diff --git a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs index 62d59ffaf..cda71f44a 100644 --- a/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs +++ b/src/UniGetUI.Avalonia/ViewModels/MainWindowViewModel.cs @@ -324,7 +324,7 @@ public static PageType GetPreviousPage(PageType type) => public void NavigateTo(PageType newPage_t, bool toHistory = true) { if (newPage_t is PageType.About) { _ = ShowAboutDialog(); return; } - if (newPage_t is PageType.Quit) { (Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.Shutdown(); return; } + if (newPage_t is PageType.Quit) { MainWindow.Instance?.QuitApplication(); return; } if (_currentPage == newPage_t) { diff --git a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs index 8d3216da5..f643dd16e 100644 --- a/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs +++ b/src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs @@ -1,8 +1,8 @@ using System; using System.Runtime.InteropServices; +using System.Threading; using Avalonia; using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Data; using Avalonia.Input; using Avalonia.Interactivity; @@ -73,6 +73,7 @@ public partial class MainWindow : Window private bool _focusSidebarSelectionOnNextPageChange; private TrayService? _trayService; private bool _allowClose; + private int _isQuitting; public enum RuntimeNotificationLevel { @@ -136,18 +137,23 @@ protected override void OnOpened(EventArgs e) protected override void OnClosing(WindowClosingEventArgs e) { - if (!_allowClose && !Settings.Get(Settings.K.DisableSystemTray)) + if (!_allowClose && (OperatingSystem.IsMacOS() || !Settings.Get(Settings.K.DisableSystemTray))) { e.Cancel = true; Hide(); return; } + e.Cancel = true; + QuitApplication(); + } + + private void ReleaseWindowResources() + { SaveGeometryNow(); AvaloniaAutoUpdater.ReleaseLockForAutoupdate_Window = true; _trayService?.Dispose(); _trayService = null; - base.OnClosing(e); } private void Window_KeyDown(object? sender, KeyEventArgs e) @@ -1004,14 +1010,25 @@ public void ShowFromTray() Activate(); } + public bool IsQuitting => Interlocked.CompareExchange(ref _isQuitting, 0, 0) == 1; + public void QuitApplication() { + if (Interlocked.Exchange(ref _isQuitting, 1) == 1) + return; + _allowClose = true; + ReleaseWindowResources(); + + if (IsVisible) + Hide(); + _ = QuitApplicationAsync(); } private static async Task QuitApplicationAsync() { + Logger.Warn("Quitting UniGetUI"); try { await AvaloniaBootstrapper.StopIpcApiAsync().WaitAsync(TimeSpan.FromSeconds(5)); @@ -1026,9 +1043,7 @@ private static async Task QuitApplicationAsync() Logger.Error(ex); } - Dispatcher.UIThread.Post(() => - (global::Avalonia.Application.Current?.ApplicationLifetime - as IClassicDesktopStyleApplicationLifetime)?.Shutdown()); + Environment.Exit(0); } public static void ApplyProxyVariableToProcess()