Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to cancel App Shutdown from Window Closing #14748

Closed
nixtar opened this issue Feb 28, 2024 · 11 comments · Fixed by #15438
Closed

Unable to cancel App Shutdown from Window Closing #14748

nixtar opened this issue Feb 28, 2024 · 11 comments · Fixed by #15438

Comments

@nixtar
Copy link

nixtar commented Feb 28, 2024

Describe the bug

I have an application that prompts the user to confirm when they try and close the apps main window.

I'm currently doing this using Avalonia.Xaml.Behaviors to wire up the Closing event to an async RelayCommand in the viewmodel.

When you close the window with the red X this works as desired.
However, on macOS when you close the app from the menu bar or from the dock this does not work.
The closing event is raised but the app closes when the first await is fired (even if e.Cancel = true; is set).

To Reproduce

  1. Create a new Avalonia Project
  2. Wire up the MainWindow Closing event to a new method in the code behind
  3. Set body of the Closing method to:
e.Cancel = true;
  1. Run the app on macOS and try closing the window directly (it shouldn't close)
  2. Close the app from the menu bar or the dock (it will close)

Expected behavior

All methods to gracefully close the app should be cancellable.

Environment

  • OS: macOS 13.6
  • Avalonia-Version: 11.0.9

Additional context

You can cancel the app shutdown from the ShutdownRequested event however the remarks for this event reads:

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 Closing event on each and allowing each window to cancel the shutdown of the application.

@nixtar nixtar added the bug label Feb 28, 2024
@THE-KONDRAT
Copy link

THE-KONDRAT commented Apr 11, 2024

I have the same issue but on windows.
I use ShutdownRequested event and set e.Cancel = true;.
When I click the red cross button main window closes, but app continues to work. How can I return main window?

I also have another problem.
When I call save project method and then I click the red cross or shutdown my app in another way I want to wait for saving finished. I think I should do this in OnShutdownRequested (handler) but the handler blocks saving process. What should I do? Maybe I should call save method in some different way?

@timunie
Copy link
Contributor

timunie commented Apr 12, 2024

@THE-KONDRAT if you want to prevent a Window from closing, why not override OnClosing in the Window or listen to the Closing-Event?

@THE-KONDRAT
Copy link

@THE-KONDRAT if you want to prevent a Window from closing, why not override OnClosing in the Window or listen to the Closing-Event?

I'm sorry but where should i override this event?
I want to control both the cross button click and manual shutdown request.
I thought i should use IClassicDesktopStyleApplicationLifetime (in my case) in app.axaml.cs.

@timunie
Copy link
Contributor

timunie commented Apr 15, 2024

In MainWindow.axaml.cs

@THE-KONDRAT
Copy link

In MainWindow.axaml.cs
Ok. That works.

And how can i wait another method inside OnClosing?

@timunie
Copy link
Contributor

timunie commented Apr 17, 2024

something like that should work

private bool _canClose;
    
protected override void OnClosing(WindowClosingEventArgs e)
{
    if (!_canClose)
    {
        // cancel closing 
        e.Cancel = true;
       
        _canClose = await DoAsyncStuff(); // async stuff should return bool here
        if (_canClose) this.Close(); // request close again if above was successful
    }
    base.OnClosing(e);
}

@THE-KONDRAT
Copy link

something like that should work

private bool _canClose;
    
protected override void OnClosing(WindowClosingEventArgs e)
{
    if (!_canClose)
    {
        // cancel closing 
        e.Cancel = true;
       
        _canClose = await DoAsyncStuff(); // async stuff should return bool here
        if (_canClose) this.Close(); // request close again if above was successful
    }
    base.OnClosing(e);
}

Thanks! This also works. Maybe someone find this usefull.

protected override async void OnClosing(WindowClosingEventArgs e)
{
    var context = Ioc.Default.GetRequiredService<ApplicationContext>();
    if (!context.CanClose)
    {
        e.Cancel = true;
        await context.WaitForAsync(nameof(context.CanClose), q => q.CanClose);
        if (context.CanClose) this.Close();
    }
    base.OnClosing(e);
}

@nixtar
Copy link
Author

nixtar commented Apr 18, 2024

Just to clarify, this is not what this issue is about.

The issue I'm having is when the app is being closed by the OS (not when clicking close on the window).

If you wire up the OnClosing the same as above, but on macOS you close the application from the menu bar or by right clicking it on the dock. The OnClosing event will fire but the app will close regardless.

@timunie
Copy link
Contributor

timunie commented Apr 18, 2024

@nixtar I'm aware of that, and this is why I didn't close it.

@maxkatz6
Copy link
Member

From how it looks, this functionality was broken for two years since #7400

@nixtar
Copy link
Author

nixtar commented Apr 30, 2024

Finally got a chance to test this with 11.1.0-beta2 and am happy to confirm it now works as expected. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants