summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-07-30 14:22:24 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-08-03 22:50:22 +0000
commitf8b17a297e41f4c0d0656c58c25a0060f2555f97 (patch)
treefbf82289839cd9caee59aa471fe8fca11dd5c738 /src/plugins/platforms/cocoa
parent68f20bb8f4b74e313e1d44a7d7e78af6d8b5b3ea (diff)
macOS: Propagate [NSOpenGLContext setView:] failures
Instead of trying to mask situations where [NSOpenGLContext setView:] will fail (such as calling it for a view that's not part of a window yet, or part of a window that hasn't been shown), we report the error up through the API, so that QOpenGLContext::makeCurrent() will return false. This is documented to occur e.g. when "the surface is not exposed, or the graphics hardware is not available due to e.g. the application being suspended." QGLWidget was taught how to deal with this situation in cc27a50e. Other Qt APIs seem to handle it fine, but if regressions occur they should be fixable though the same logic as in cc27a50e. Change-Id: I92775fc165444696b6c5b44fa0e28ce3c4ad2190 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm32
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h6
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm32
5 files changed, 25 insertions, 55 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index c3640f56ab..74f3442c1d 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -75,7 +75,7 @@ public:
private:
static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format);
- void setActiveWindow(QWindow *window);
+ bool setActiveWindow(QWindow *window);
void updateSurfaceFormat();
NSOpenGLContext *m_context;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index d49f8d7bae..b84360b7ae 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -376,7 +376,10 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
return true;
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
- setActiveWindow(window);
+ if (!setActiveWindow(window)) {
+ qCDebug(lcQpaOpenGLContext) << "Failed to activate window, skipping makeCurrent";
+ return false;
+ }
// Disable high-resolution surfaces when using the software renderer, which has the
// problem that the system silently falls back to a to using a low-resolution buffer
@@ -397,23 +400,29 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
return true;
}
-void QCocoaGLContext::setActiveWindow(QWindow *window)
+bool QCocoaGLContext::setActiveWindow(QWindow *window)
{
if (window == m_currentWindow.data())
- return;
+ return true;
+
+ Q_ASSERT(window->handle());
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ NSView *view = cocoaWindow->view();
+
+ if ((m_context.view = view) != view) {
+ qCDebug(lcQpaOpenGLContext) << "Associating" << view << "with" << m_context << "failed";
+ return false;
+ }
+
+ qCDebug(lcQpaOpenGLContext) << m_context << "now associated with" << m_context.view;
if (m_currentWindow && m_currentWindow.data()->handle())
static_cast<QCocoaWindow *>(m_currentWindow.data()->handle())->setCurrentContext(0);
- Q_ASSERT(window->handle());
-
m_currentWindow = window;
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
cocoaWindow->setCurrentContext(this);
-
- Q_ASSERT(!cocoaWindow->isForeignWindow());
- [qnsview_cast(cocoaWindow->view()) setQCocoaGLContext:this];
+ return true;
}
// NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579)
@@ -431,7 +440,10 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
return; // Nothing to do
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
- setActiveWindow(window);
+ if (!setActiveWindow(window)) {
+ qCWarning(lcQpaOpenGLContext) << "Failed to activate window, skipping swapBuffers";
+ return;
+ }
QMutexLocker locker(&s_contextMutex);
[m_context flushBuffer];
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index 67debef7b8..b40dfe0d14 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -64,12 +64,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem));
@end
-@interface QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
-#ifndef QT_NO_OPENGL
-- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
-#endif
-@end
-
@interface QT_MANGLE_NAMESPACE(QNSView) (MouseAPI)
- (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent;
- (void)resetMouseButtons;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index dd9af3668a..9bd53ed334 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -122,10 +122,6 @@
bool m_dontOverrideCtrlLMB;
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers m_currentWheelModifiers;
-#ifndef QT_NO_OPENGL
- QCocoaGLContext *m_glContext;
- bool m_shouldSetGLContextinDrawRect;
-#endif
NSString *m_inputSource;
QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper;
bool m_resendKeyEvent;
@@ -143,10 +139,6 @@
m_acceptedMouseDowns = Qt::NoButton;
m_frameStrutButtons = Qt::NoButton;
m_sendKeyEvent = false;
-#ifndef QT_NO_OPENGL
- m_glContext = nullptr;
- m_shouldSetGLContextinDrawRect = false;
-#endif
m_sendUpAsRightButton = false;
m_inputSource = nil;
m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self];
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index 8ebe27f0c2..4f9d17504d 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -39,22 +39,6 @@
// This file is included from qnsview.mm, and only used to organize the code
-@implementation QT_MANGLE_NAMESPACE(QNSView) (DrawingAPI)
-
-#ifndef QT_NO_OPENGL
-- (void)setQCocoaGLContext:(QCocoaGLContext *)context
-{
- m_glContext = context;
- [m_glContext->nsOpenGLContext() setView:self];
- if (![m_glContext->nsOpenGLContext() view]) {
- //was unable to set view
- m_shouldSetGLContextinDrawRect = true;
- }
-}
-#endif
-
-@end
-
@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
- (BOOL)isOpaque
@@ -84,19 +68,7 @@
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
- [self updateRegion:exposedRegion];
-}
-
-- (void)updateRegion:(QRegion)dirtyRegion
-{
-#ifndef QT_NO_OPENGL
- if (m_glContext && m_shouldSetGLContextinDrawRect) {
- [m_glContext->nsOpenGLContext() setView:self];
- m_shouldSetGLContextinDrawRect = false;
- }
-#endif
-
- m_platformWindow->handleExposeEvent(dirtyRegion);
+ m_platformWindow->handleExposeEvent(exposedRegion);
}
- (BOOL)shouldUseMetalLayer
@@ -174,7 +146,7 @@
qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
- [self updateRegion:QRectF::fromCGRect(self.bounds).toRect()];
+ m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
}
- (void)viewDidChangeBackingProperties