Cancel window closing

Is there a way to cancel or ignore a user’s close request? I’d like to delay a window closing if the user’s project is still saving.

I know about NewWindow::closeButtonPressed and Component::userTriedToCloseWindow, but neither of these functions allows for a way to completely cancel or ignore a close request. I can’t create a while loop in these functions either, because I don’t want the UI to freeze up.

For an example, C# WPF has a way to Cancel a window closing: Window.Closing Event (System.Windows) | Microsoft Docs

It is handled in the JUCEApplication. There is a method systemRequestedQuit()

Called when the operating system is trying to close the application.

The default implementation of this method is to call quit(), but it may be overloaded to ignore the request or do some other special behaviour instead. For example, you might want to offer the user the chance to save their changes before quitting, and give them the chance to cancel.

[…]

1 Like

Not going to have any use for plugin projects, though…? The original poster didn’t clarify if this is for a standalone application or for a plugin. If it’s a plugin, there’s no way ignore the user’s request to close the plugin window since that is owned by the host.

This is for a standalone application, so @daniel’s solution works great. Thanks guys!

Just realized that JUCEApplication::systemRequestedQuit() might not work for my purposes. The window that I’m trying to cancel closing is the second window opened; meaning when the user clicks close on this window, the application itself isn’t quitting because there’s a window still open. So that function won’t be called.

Is there another method that can do what I’m trying to do? Or is it not possible as @xenakios suggested?

If your window is a juce::DocumentWindow then you get a callback as well called closeButtonPressed(). This makes sense, because only DocumentWindows have the close/maximize/minimize buttons.

In this doc there is another valuable hint:

(Note that the DocumentWindow class overrides Component::userTriedToCloseWindow() and redirects it to call this method, so any methods of closing the window that are caught by userTriedToCloseWindow() will also end up here).

that means, you could also look into that userTriedToCloseWindow() method, e.g. if you don’t use a DocumentWindow.

Hope that helps

Thanks, but as I said in my original post, closeButtonPressed() doesn’t have a way to cancel the closing of the DocumentWindow. The only way to delay closing the window is to essentially halt the UI thread while the saving task finishes, which I don’t want to do in this case because I want to show a loading screen or something.

I think I just need to go about this another way and make project saving a application-wide process, that way when systemRequestedQuit() is called I can “cancel” the application closing until the project is finished saving.

Sounds to me that the architecture could be improved by having the state separated from the window, so the state stays alive regardless if the window is open or not.

The problem you face is, if the same thread handles the saving and the closing, waiting doesn’t buy you time.

Regardless of any architectural concerns, I’m confused why closeButtonPressed() doesn’t do what you need. If you do nothing in your closeButtonPressed() method, the window shouldn’t close, so can’t you just return early if a save is in-progress to “cancel”? What does your implementation of that method look like?

For example, this class creates a window that does not close when the close button is pressed:

struct NonClosableWindow : juce::DocumentWindow
{
    NonClosableWindow()
        : juce::DocumentWindow ("NonClosableWindow", juce::Colours::grey,
                                juce::DocumentWindow::TitleBarButtons::allButtons)
    {
        setUsingNativeTitleBar (true);
        centreWithSize (800, 500);
        setVisible (true);
    }

    void closeButtonPressed() override
    {
    }
};

Oh my gosh. :man_facepalming: That totally works! I had a class that overrides that but I thought it wasn’t able to cancel the close. I guess I’m crazy. :roll_eyes:

Thank you!!!