It's not possible using only Qt. There's another question that details the issues. It boils down to:
Installing an event filter on QApplication will let you receive mouse events while the cursor is over any application window, but not outside of it. That's not helpful in your case.
If a widget grabs the mouse using grabMouse(), it will receive all mouse events globally, but interaction with other applications becomes impossible.
So, you'll need to resort to using platform-specific APIs to do this - that means Cocoa and writing in Objective C/C++. There's a question with excellent answers that provides almost everything we need but Qt integration.
The missing part, shown below, is integrating the stand-alone code with Qt. This code shows an empty widget just to demonstrate that we correctly handle mouse events for both our application, and outside of it.
This is a complete, working example, using Cocoa. It needs to go into a .mm file; don't forget to add it to OBJECTIVE_SOURCES in your qmake project file (not to SOURCES!).
Unfortunately, there's isn't a single function/method that would translate from NSEvent to QMouseEvent. The best one can do is copy&paste some code from qnsview.mm. This is unfortunate but results from the design of Qt platform abstraction: the platform code ends up calling QWindowSystemInterface::handleMouseEvent(....) to post the event to the application.
#include
#include
#include
#include
#include
#import
QTextStream out(stdout);
class MyEventFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) {
Q_UNUSED(eventType) Q_UNUSED(result)
NSEvent * event = (NSEvent*)message;
switch ([event type]) {
case NSLeftMouseDown:
out << "Lv"; break;
case NSLeftMouseUp:
out << "L^"; break;
case NSRightMouseDown:
out << "Rv"; break;
case NSRightMouseUp:
out << "R^"; break;
case NSOtherMouseDown:
out << [event buttonNumber] << "v"; break;
case NSOtherMouseUp:
out << [event buttonNumber] << "^"; break;
default:
return false;
}
out << endl;
return false;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSharedPointer filter(new MyEventFilter);
const int mask =
NSLeftMouseDownMask | NSLeftMouseUpMask |
NSRightMouseDownMask | NSRightMouseUpMask |
NSOtherMouseDownMask | NSOtherMouseUpMask;
// The global monitoring handler is *not* called for events sent to our application
id monitorId = [NSEvent addGlobalMonitorForEventsMatchingMask:mask handler:^(NSEvent* event) {
filter->nativeEventFilter("NSEvent", event, 0);
}];
// We also need to handle events coming to our application
a.installNativeEventFilter(filter.data());
QWidget w;
w.show();
int rc = a.exec();
[NSEvent removeMonitor:monitorId];
return rc;
}