macOS: Guard against display on non-main threads

AppKit will in some cases ask our view to display on secondary threads if
we call APIs that are only supposed to be called on the main thread, such
as -[NSOpenGLContext setView:] or -[NSOpenGLContext update].

Forwarding this display-request is bad, as QtGui expects all window system
events to come on the main thread, and we can easily deadlock client code
such as the Qt Quick threaded renderer.

Change-Id: I1daeabf1dca6ca8ba908d3998b444a2089681e3a
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-05-10 16:06:47 +02:00 committed by Tor Arne Vestbø
parent 7eed1e40d4
commit 09504d484c

View File

@ -189,6 +189,15 @@
- (void)displayLayer:(CALayer *)layer - (void)displayLayer:(CALayer *)layer
{ {
if (!NSThread.isMainThread) {
// Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads,
// which we shouldn't do. This may result in AppKit (wrongly) triggering a display on
// the thread where we made the call, so block it here and defer to the main thread.
qCWarning(lcQpaDrawing) << "Display non non-main thread! Deferring to main thread";
dispatch_async(dispatch_get_main_queue(), ^{ self.needsDisplay = YES; });
return;
}
Q_ASSERT(layer == self.layer); Q_ASSERT(layer == self.layer);
if (!m_platformWindow) if (!m_platformWindow)