Quitting a Qt application from the Mac OS X dock

So for some weird reason my application was not closable from the Mac OS X dock – it quit properly when you selected “Quit” from the application menu or hit the Cmd-Q shortcut – but the dock menu’s quit action was completely ignored.

While debugging the issue I hooked into `QApplication::notify(QObject *, QEvent *)` and noted that a `QCloseEvent` was send to my application… wait, what? A `QCloseEvent`? Yes, I also thought that these kinds of events would only be send to widgets, namely, top level widgets, but I got one for my application, and Qt plainly ignored it. So I went further ahead and tried to quit the application directly when the event occured, similar to this

bool MyApp::event(QEvent * ev)
    bool eaten = false;
    switch (ev->type())
        // other stuff ...
#ifdef Q_WS_MAC:
        case QEvent::Close:
            eaten = true;
            eaten = QCoreApplication::event(ev);
    return eaten;

but this didn’t work out so nicely: while the application quitted correctly, the `quit()` slot was apparently called twice in a row. My guess is that Qt ignores the `quitOnLastWindowClosed` property – which I’ve set to false – and since I close all windows in the quit slot it executes quit again, or something else, so I decided to just close all open windows when the `QCloseEvent` arrived – without calling `quit()` directly, and tada, my application quitted and the slot was also only called once. (This was a mistake on my side because I missed a break.)

3 thoughts on “Quitting a Qt application from the Mac OS X dock”

  1. I was searching for the answer how to get the quit event for my app so I can do my close routine there and finally I found exactly what I needed. Thanks!
    One issue found: if you derive your class from QApplication it’s better to do
    QApplication::event(ev); – this will close all top level windows
    instead of
    QCoreApplication::event(ev); – this will not close any top level window.

  2. you don’t break in case QEvent::Close, thus it calls it twice, reaching the default as well

Comments are closed.