I had very good recommendations how to do it using Objective-C here (unfortunately in Russian). Big thanks for list of such beautiful tricks to its author. But there was one inconvenience. I did not want to add Objective-C++ file (.mm) in my project.
And I found other very good article suite from Robin Mills.(See ObjCandCandC++.pdf)
As result I got the following working bunch of code WITHOUT usage Objective-C++ and it has allowed me to reach what I wanted.
The prototype in Objective-C was very short.
Main idea was as usual to write separate Objective-C class. It should be separate compilation unit and it can be available for the code in Qt/C++.
This is callback that should be declared and registered in order to handle a click on dock's icon .
void dockClickHandler(id self, SEL _cmd)
{
Q_UNUSED(self)
Q_UNUSED(_cmd)
MyPrivate::instance()->emitClick();
}
and registration of this callback in Objective-C.
MyPrivate::MyPrivate() :
QObject(NULL)
{
Class cls = [[[NSApplication sharedApplication] delegate] class];
if (!class_addMethod(cls,
@selector(applicationShouldHandleReopen:hasVisibleWindows:),
(IMP) dockClickHandler, "v@:"))
NSLog(@"MyPrivate::MyPrivate() : class_addMethod failed!");
}
void MyPrivate::emitClick()
{
emit dockClicked();
}
But as you remember I did not want to use Objective-C at all. I did not want to add new file in my project.as result I got the following:
The callback was declared in the top of my .cpp file there I declared my descendant from QApplication:
#ifdef Q_OS_MAC
#include <objc/objc.h>
#include <objc/message.h>
bool dockClickHandler(id self,SEL _cmd,...)
{
Q_UNUSED(self)
Q_UNUSED(_cmd)
((Application*)qApp)->onClickOnDock();
return true;
}
#endif
where Application is my descendant from QApplication.
and most interesting thing, we can register in runtime this function as new method for delegate class (NSApplicationDelegate):
#ifdef Q_OS_MAC
objc_object* cls = objc_getClass("NSApplication");
SEL sharedApplication = sel_registerName("sharedApplication");
objc_object* appInst = objc_msgSend(cls,sharedApplication);
if(appInst != NULL)
{
objc_object* delegate = objc_msgSend(appInst,
sel_registerName("delegate"));
objc_object* delegateClass = objc_msgSend(delegateClass,
sel_registerName("class"));
constchar* tst = class_getName(delegateClass->isa);
bool test = class_addMethod((objc_class*) delegateClass,
sel_registerName("applicationShouldHandleReopen:hasVisibleWindows:"),
(IMP)dockClickHandler,"B@:");
// "B@:" is quite tricky thing called Method Signature which allows to define C function to selector "applicationShouldHandleReopen:hasVisibleWindows:" and dockClickHandler function will be called as if it was written inside objective-c code.
if(test)
{
qDebug("Registration was successful");
}
}
#endif