I could not get the original answer for proper compilation due to dismissal warnings (post-OS X 10.5) and type error; I changed a few type names and got it for compilation, but the code still didn't work.
It turns out that newer versions of Qt (4.8.7+, including 5.x; I use 5.4.1) implement the method we want to add, and class_addMethod fails if this method already exists. See this QTBUG .
Note: the above error report contains a slightly different solution (I found it after fixing the problem myself).
One solution that works for me is to check if a method exists. If this happens, we will replace it. If not, we just add it.
I have not tested this code on older versions of Qt, but it uses OPs logic, so it should work.
Here is my code. As with OPs, all code is in the .cpp file of the QApplication subclass.
#ifdef Q_OS_MAC #include <objc/objc.h> #include <objc/message.h> void setupDockClickHandler(); bool dockClickHandler(id self,SEL _cmd,...); #endif
The subclass constructor of QQpplication contains
#ifdef Q_OS_MAC setupDockClickHandler(); #endif
And finally, somewhere in the same file (below, in my case):
#ifdef Q_OS_MAC void setupDockClickHandler() { Class cls = objc_getClass("NSApplication"); objc_object *appInst = objc_msgSend((objc_object*)cls, sel_registerName("sharedApplication")); if(appInst != NULL) { objc_object* delegate = objc_msgSend(appInst, sel_registerName("delegate")); Class delClass = (Class)objc_msgSend(delegate, sel_registerName("class")); SEL shouldHandle = sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"); if (class_getInstanceMethod(delClass, shouldHandle)) { if (class_replaceMethod(delClass, shouldHandle, (IMP)dockClickHandler, " B@ :")) qDebug() << "Registered dock click handler (replaced original method)"; else qWarning() << "Failed to replace method for dock click handler"; } else { if (class_addMethod(delClass, shouldHandle, (IMP)dockClickHandler," B@ :")) qDebug() << "Registered dock click handler"; else qWarning() << "Failed to register dock click handler"; } } } bool dockClickHandler(id self,SEL _cmd,...) { Q_UNUSED(self) Q_UNUSED(_cmd) // Do something fun here! qDebug() << "Dock icon clicked!"; // Return NO (false) to suppress the default OS X actions return false; }
Also see Apple documentation on applicationShouldHandleRopen: hasVisibleWindows: method .
To compile this, you also need to bundle some additional frameworks.
Using qmake, I added the following to the .pro file:
LIBS += -framework CoreFoundation -framework Carbon -lobjc
These flags, of course, are exactly what you should add to the C ++ or clang ++ command line if you compile manually.
That should be all that is required.