Blocking Cmd-Q on OS X & Ctrl-Q on Windows

Hey, folks.

I am trying to replicate the following functionality that happens on OS X, on windows:

when you quit (cmd-q) a multi-window app such as Projucer, all of the windows close. OS X remembers which windows were open when you rerun the app and opens all of them.

when you quit (ctrl-q) a multi-window app such as Projucer on Windows, Windows closes the focused window only. it does not close all of the app windows.

one of the ways I’m going about trying to make this work for my own project, is to block that Cmd-Q from doing the default thing of quitting the app.

I’ve been trying to get the ApplicationCommandManager to respond to quit messages on OS X to no avail.

I added the StandardApplicationCommandIDs::quit to the KeyMappingsDemo:

    void getAllCommands (Array<CommandID>& commands) override
    {
        Array<CommandID> ids { KeyPressCommandIDs::buttonMoveUp, KeyPressCommandIDs::buttonMoveRight,
                               KeyPressCommandIDs::buttonMoveDown, KeyPressCommandIDs::buttonMoveLeft,
                               KeyPressCommandIDs::nextButtonColour, KeyPressCommandIDs::previousButtonColour,
                               KeyPressCommandIDs::nextBackgroundColour, KeyPressCommandIDs::previousBackgroundColour,
                            StandardApplicationCommandIDs::quit // <<<<<<<<
        };

        commands.addArray (ids);
    }
    void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result) override
    {
        switch (commandID)
        {
            case StandardApplicationCommandIDs::quit: // <<<<<<<
            {
                result.setInfo ("quit", "quit", "Button", 0);
                result.addDefaultKeypress('q', ModifierKeys::commandModifier);
                break;
            }
            case KeyPressCommandIDs::buttonMoveUp:
                result.setInfo ("Move up", "Move the button up", "Button", 0);
                result.addDefaultKeypress (KeyPress::upKey, 0);
                break;
    bool perform (const InvocationInfo& info) override
    {
        switch (info.commandID)
        {
            case StandardApplicationCommandIDs::quit:
            {
                jassertfalse;
                break;
            }

No matter what I do, I can’t seem to make that jassertfalse fire on OS X. I haven’t tried on windows yet.

This definitely gets called when you press cmd-q on os x:

        static NSApplicationTerminateReply applicationShouldTerminate (id /*self*/, SEL, NSApplication*)
        {
            if (auto* app = JUCEApplicationBase::getInstance())
            {
                app->systemRequestedQuit(); // <<<<<<<

                if (! MessageManager::getInstance()->hasStopMessageBeenSent())
                    return NSTerminateCancel;
            }

            return NSTerminateNow;
        }

        static void applicationWillTerminate (id /*self*/, SEL, NSNotification*)
        {
            JUCEApplicationBase::appWillTerminateByForce();
        }

I’m starting to think that you can’t bypass the OS X’s handling of Cmd-Q other than via not calling quit() here:

void MyApplication::systemRequestedQuit()
{
    // This is called when the app is being asked to quit: you can ignore this
    // request and let the app carry on running, or call quit() to allow the app to close.
//    quit();
}

Any ideas how to make the ApplicationCommandManager be the only handler of Cmd-Q?

I think on OS X the convention is: ⌘Q ‘quits’ applications entirely, ⌘W closes a single ‘document’. It looks like that is the behaviour you currently have.

The corresponding standard key presses on Windows are alt+F4 and ctrl+F4. Although ctrl-Q and ctrl-W are commonly also implemented.

I think it is OK to have slightly different behaviour on the various platforms. It is better to be consistent with other apps on the same platform. Your users will be used to it.

Thanks Roeland, I got it working after all.