summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-08-05 11:07:45 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2020-08-18 00:35:21 +0200
commit1fc7ca091b3fdda52381a383318a3a752ec21132 (patch)
treebc794ba56de848a543c9167856fe9cf60b938de2 /src/plugins
parentd1111632e29124531d5b4512e0492314caaae396 (diff)
macOS: Remove support for surface-backed views
Our deployment target is 10.14, which enables layer-backing by default, and our layer-backing support nowadays is stable enough that we don't need to maintain any of the old code paths for compatibility. The wantsBestResolutionOpenGLSurface property on NSView is only relevant for surface-backed views, so we no longer need to deal with it. Change-Id: I8aef4ac99371113d463ac35eee648a8a2fd1ea72 Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h15
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm270
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm58
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm29
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm61
8 files changed, 32 insertions, 416 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 4a5b3886f2..b96bb1e3dc 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -58,21 +58,6 @@ protected:
QCFType<CGColorSpaceRef> colorSpace() const;
};
-class QNSWindowBackingStore : public QCocoaBackingStore
-{
-public:
- QNSWindowBackingStore(QWindow *window);
- ~QNSWindowBackingStore();
-
- void resize(const QSize &size, const QRegion &staticContents) override;
- void flush(QWindow *, const QRegion &, const QPoint &) override;
-
-private:
- bool windowHasUnifiedToolbar() const;
- QImage::Format format() const override;
- void redrawRoundedBottomCorners(CGRect) const;
-};
-
class QCALayerBackingStore : public QObject, public QCocoaBackingStore
{
Q_OBJECT
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 9ee6ab5b4f..01787da1af 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -64,276 +64,6 @@ QCFType<CGColorSpaceRef> QCocoaBackingStore::colorSpace() const
// ----------------------------------------------------------------------------
-QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window)
- : QCocoaBackingStore(window)
-{
- // Choose an appropriate window depth based on the requested surface format.
- // On deep color displays the default bit depth is 16-bit, so unless we need
- // that level of precision we opt out of it (and the expensive RGB32 -> RGB64
- // conversions that come with it if our backingstore depth does not match).
-
- NSWindow *nsWindow = static_cast<QCocoaWindow *>(window->handle())->view().window;
- auto colorSpaceName = NSColorSpaceFromDepth(nsWindow.depthLimit);
-
- static const int kDefaultBitDepth = 8;
- auto surfaceFormat = window->requestedFormat();
- auto bitsPerSample = qMax(kDefaultBitDepth, qMax(surfaceFormat.redBufferSize(),
- qMax(surfaceFormat.greenBufferSize(), surfaceFormat.blueBufferSize())));
-
- // NSBestDepth does not seem to guarantee a window depth deep enough for the
- // given bits per sample, even if documented as such. For example, requesting
- // 10 bits per sample will not give us a 16-bit format, even if that's what's
- // available. Work around this by manually bumping the bit depth.
- bitsPerSample = !(bitsPerSample & (bitsPerSample - 1))
- ? bitsPerSample : qNextPowerOfTwo(bitsPerSample);
-
- auto bestDepth = NSBestDepth(colorSpaceName, bitsPerSample, 0, NO, nullptr);
-
- // Disable dynamic depth limit, otherwise our depth limit will be overwritten
- // by AppKit if the window moves to a screen with a different depth. We call
- // this before setting the depth limit, as the call will reset the depth to 0.
- [nsWindow setDynamicDepthLimit:NO];
-
- qCDebug(lcQpaBackingStore) << "Using" << NSBitsPerSampleFromDepth(bestDepth)
- << "bit window depth for" << nsWindow;
-
- nsWindow.depthLimit = bestDepth;
-}
-
-QNSWindowBackingStore::~QNSWindowBackingStore()
-{
-}
-
-bool QNSWindowBackingStore::windowHasUnifiedToolbar() const
-{
- Q_ASSERT(window()->handle());
- return static_cast<QCocoaWindow *>(window()->handle())->m_drawContentBorderGradient;
-}
-
-QImage::Format QNSWindowBackingStore::format() const
-{
- if (windowHasUnifiedToolbar())
- return QImage::Format_ARGB32_Premultiplied;
-
- return QRasterBackingStore::format();
-}
-
-void QNSWindowBackingStore::resize(const QSize &size, const QRegion &staticContents)
-{
- qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
- QRasterBackingStore::resize(size, staticContents);
-
- // The window shadow rendered by AppKit is based on the shape/content of the
- // NSWindow surface. Technically any flush of the backingstore can result in
- // a potentially new shape of the window, and would need a shadow invalidation,
- // but this is likely too expensive to do at every flush for the few cases where
- // clients change the shape dynamically. One case where we do know that the shadow
- // likely needs invalidation, if the window has partially transparent content,
- // is after a resize, where AppKit's default shadow may be based on the previous
- // window content.
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
- if (cocoaWindow->isContentView() && !cocoaWindow->isOpaque())
- cocoaWindow->m_needsInvalidateShadow = true;
-}
-
-/*!
- Flushes the given \a region from the specified \a window onto the
- screen.
-
- The \a window is the top level window represented by this backingstore,
- or a non-transient child of that window.
-
- If the \a window is a child window, the \a region will be in child window
- coordinates, and the \a offset will be the child window's offset in relation
- to the backingstore's top level window.
-*/
-void QNSWindowBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
-{
- if (m_image.isNull())
- return;
-
- // Use local pool so that any stale image references are cleaned up after flushing
- QMacAutoReleasePool pool;
-
- const QWindow *topLevelWindow = this->window();
-
- Q_ASSERT(topLevelWindow->handle() && window->handle());
- Q_ASSERT(!topLevelWindow->handle()->isForeignWindow() && !window->handle()->isForeignWindow());
-
- QNSView *topLevelView = qnsview_cast(static_cast<QCocoaWindow *>(topLevelWindow->handle())->view());
- QNSView *view = qnsview_cast(static_cast<QCocoaWindow *>(window->handle())->view());
-
- if (lcQpaBackingStore().isDebugEnabled()) {
- QString targetViewDescription;
- if (view != topLevelView) {
- QDebug targetDebug(&targetViewDescription);
- targetDebug << "onto" << topLevelView << "at" << offset;
- }
- qCDebug(lcQpaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
- }
-
- // Normally a NSView is drawn via drawRect, as part of the display cycle in the
- // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
- // individual view, starting with the top level and then traversing any subviews,
- // calling drawRect for each of them. This pull model results in expose events
- // sent to Qt, which result in drawing to the backingstore and flushing it.
- // Qt may also decide to paint and flush the backingstore via e.g. timers,
- // or other events such as mouse events, in which case we're in a push model.
- // If there is no focused view, it means we're in the latter case, and need
- // to manually flush the NSWindow after drawing to its graphic context.
- const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
-
- // We also need to ensure the flushed view has focus, so that the graphics
- // context is set up correctly (coordinate system, clipping, etc). Outside
- // of the normal display cycle there is no focused view, as explained above,
- // so we have to handle it manually. There's also a corner case inside the
- // normal display cycle due to way QWidgetRepaintManager composits native child
- // widgets, where we'll get a flush of a native child during the drawRect of
- // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
- // In this case we also need to lock and unlock focus manually.
- const bool shouldHandleViewLockManually = [NSView focusView] != view;
- if (shouldHandleViewLockManually && !QT_IGNORE_DEPRECATIONS([view lockFocusIfCanDraw])) {
- qWarning() << "failed to lock focus of" << view;
- return;
- }
-
- const qreal devicePixelRatio = m_image.devicePixelRatio();
-
- // If the flushed window is a content view, and we're filling the drawn area
- // completely, or it doesn't have a window background we need to preserve,
- // we can get away with copying instead of blending the backing store.
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
- && (cocoaWindow->isOpaque() || view.window.backgroundColor == NSColor.clearColor)
- ? NSCompositingOperationCopy : NSCompositingOperationSourceOver;
-
-#ifdef QT_DEBUG
- static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
- boolForKey:@"QtCocoaDebugBackingStoreFlush"];
-#endif
-
- // -------------------------------------------------------------------------
-
- // The current contexts is typically a NSWindowGraphicsContext, but can be
- // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
- // If we need to distinguish things here in the future, we can use e.g.
- // [NSGraphicsContext drawingToScreen], or the attributes of the context.
- NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
- Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
- "Focusing the view should give us a current graphics context");
-
- // Tag backingstore image with color space based on the window.
- // Note: This does not copy the underlying image data.
- QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace(
- QCFType<CGImageRef>(m_image.toCGImage()), colorSpace());
-
- // Create temporary image to use for blitting, without copying image data
- NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
-
- QRegion clippedRegion = region;
- for (QWindow *w = window; w; w = w->parent()) {
- if (!w->mask().isEmpty()) {
- clippedRegion &= w == window ? w->mask()
- : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0))));
- }
- }
-
- for (const QRect &viewLocalRect : clippedRegion) {
- QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
- QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
- if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
- backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
-
- CGRect viewRect = viewLocalRect.toCGRect();
-
- [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
- operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
-
-#ifdef QT_DEBUG
- if (Q_UNLIKELY(debugBackingStoreFlush)) {
- [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
- [NSBezierPath fillRect:viewRect];
-
- if (drawingOutsideOfDisplayCycle) {
- [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
- [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
- toPoint:viewLocalRect.bottomRight().toCGPoint()];
- }
- }
-#endif
- }
-
- // -------------------------------------------------------------------------
-
- if (shouldHandleViewLockManually)
- QT_IGNORE_DEPRECATIONS([view unlockFocus]);
-
- if (drawingOutsideOfDisplayCycle) {
- redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
- QT_IGNORE_DEPRECATIONS([view.window flushWindow]);
- }
-
- // Done flushing to NSWindow backingstore
-
- QCocoaWindow *topLevelCocoaWindow = static_cast<QCocoaWindow *>(topLevelWindow->handle());
- if (Q_UNLIKELY(topLevelCocoaWindow->m_needsInvalidateShadow)) {
- qCDebug(lcQpaBackingStore) << "Invalidating window shadow for" << topLevelCocoaWindow;
- [topLevelView.window invalidateShadow];
- topLevelCocoaWindow->m_needsInvalidateShadow = false;
- }
-}
-
-/*
- When drawing outside of the display cycle, which Qt Widget does a lot,
- we end up drawing over the NSThemeFrame, losing the rounded corners of
- windows in the process.
-
- To work around this, until we've enabled updates via setNeedsDisplay and/or
- enabled layer-backed views, we ask the NSWindow to redraw the bottom corners
- if they intersect with the flushed region.
-
- This is the same logic used internally by e.g [NSView displayIfNeeded],
- [NSRulerView _scrollToMatchContentView], and [NSClipView _immediateScrollToPoint:],
- as well as the workaround used by WebKit to fix a similar bug:
-
- https://trac.webkit.org/changeset/85376/webkit
-*/
-void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
-{
-#if !defined(QT_APPLE_NO_PRIVATE_APIS)
- Q_ASSERT(this->window()->handle());
- NSWindow *window = static_cast<QCocoaWindow *>(this->window()->handle())->nativeWindow();
-
- static SEL intersectBottomCornersWithRect = NSSelectorFromString(
- [NSString stringWithFormat:@"_%s%s:", "intersectBottomCorners", "WithRect"]);
- if (NSMethodSignature *signature = [window methodSignatureForSelector:intersectBottomCornersWithRect]) {
- NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
- invocation.target = window;
- invocation.selector = intersectBottomCornersWithRect;
- [invocation setArgument:&windowRect atIndex:2];
- [invocation invoke];
-
- NSRect cornerOverlap = NSZeroRect;
- [invocation getReturnValue:&cornerOverlap];
- if (!NSIsEmptyRect(cornerOverlap)) {
- static SEL maskRoundedBottomCorners = NSSelectorFromString(
- [NSString stringWithFormat:@"_%s%s:", "maskRounded", "BottomCorners"]);
- if ((signature = [window methodSignatureForSelector:maskRoundedBottomCorners])) {
- invocation = [NSInvocation invocationWithMethodSignature:signature];
- invocation.target = window;
- invocation.selector = maskRoundedBottomCorners;
- [invocation setArgument:&cornerOverlap atIndex:2];
- [invocation invoke];
- }
- }
- }
-#else
- Q_UNUSED(windowRect);
-#endif
-}
-
-// ----------------------------------------------------------------------------
-
QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
: QCocoaBackingStore(window)
{
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 9dbd1a11bf..ab8e9d3012 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -81,7 +81,6 @@ private:
static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format);
bool setDrawable(QPlatformSurface *surface);
- void prepareDrawable(QCocoaWindow *platformWindow);
void updateSurfaceFormat();
NSOpenGLContext *m_context = nil;
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index c2fcb6cdbc..7b0cc3fac3 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -393,8 +393,6 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
if (view == QT_IGNORE_DEPRECATIONS(m_context.view))
return true;
- prepareDrawable(cocoaWindow);
-
// Setting the drawable may happen on a separate thread as a result of
// a call to makeCurrent, so we need to set up the observers before we
// associate the view with the context. That way we will guarantee that
@@ -410,12 +408,8 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
m_updateObservers.clear();
- if (view.layer) {
- m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback));
- m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
- } else {
- m_updateObservers.append(QMacNotificationObserver(view, QT_IGNORE_DEPRECATIONS(NSViewGlobalFrameDidChangeNotification), updateCallback));
- }
+ m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback));
+ m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
m_updateObservers.append(QMacNotificationObserver([NSApplication sharedApplication],
NSApplicationDidChangeScreenParametersNotification, updateCallback));
@@ -437,30 +431,6 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
return true;
}
-void QCocoaGLContext::prepareDrawable(QCocoaWindow *platformWindow)
-{
- // We generally want high-DPI GL surfaces, unless the user has explicitly disabled them
- bool prefersBestResolutionOpenGLSurface = qt_mac_resolveOption(YES,
- platformWindow->window(), "_q_mac_wantsBestResolutionOpenGLSurface",
- "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
-
- auto *view = platformWindow->view();
-
- // The only case we have to opt out ourselves is when using the Apple software renderer
- // in combination with surface-backed views, as these together do not support high-DPI.
- if (prefersBestResolutionOpenGLSurface) {
- int rendererID = 0;
- [m_context getValues:&rendererID forParameter:NSOpenGLContextParameterCurrentRendererID];
- bool isSoftwareRenderer = (rendererID & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID;
- if (isSoftwareRenderer && !view.layer) {
- qCInfo(lcQpaOpenGLContext) << "Disabling high resolution GL surface due to software renderer";
- prefersBestResolutionOpenGLSurface = false;
- }
- }
-
- QT_IGNORE_DEPRECATIONS(view.wantsBestResolutionOpenGLSurface) = prefersBestResolutionOpenGLSurface;
-}
-
// NSOpenGLContext is not re-entrant. Even when using separate contexts per thread,
// view, and window, calls into the API will still deadlock. For more information
// see https://openradar.appspot.com/37064579
@@ -494,19 +464,17 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
return;
}
- if (QT_IGNORE_DEPRECATIONS(m_context.view).layer) {
- // Flushing an NSOpenGLContext will hit the screen immediately, ignoring
- // any Core Animation transactions in place. This may result in major
- // visual artifacts if the flush happens out of sync with the size
- // of the layer, view, and window reflected by other parts of the UI,
- // e.g. if the application flushes in the resize event or a timer during
- // window resizing, instead of in the expose event.
- auto *cocoaWindow = static_cast<QCocoaWindow *>(surface);
- if (cocoaWindow->geometry().size() != cocoaWindow->m_exposedRect.size()) {
- qCInfo(lcQpaOpenGLContext) << "Window exposed size does not match geometry (yet)."
- << "Skipping flush to avoid visual artifacts.";
- return;
- }
+ // Flushing an NSOpenGLContext will hit the screen immediately, ignoring
+ // any Core Animation transactions in place. This may result in major
+ // visual artifacts if the flush happens out of sync with the size
+ // of the layer, view, and window reflected by other parts of the UI,
+ // e.g. if the application flushes in the resize event or a timer during
+ // window resizing, instead of in the expose event.
+ auto *cocoaWindow = static_cast<QCocoaWindow *>(surface);
+ if (cocoaWindow->geometry().size() != cocoaWindow->m_exposedRect.size()) {
+ qCInfo(lcQpaOpenGLContext) << "Window exposed size does not match geometry (yet)."
+ << "Skipping flush to avoid visual artifacts.";
+ return;
}
QMutexLocker locker(&s_reentrancyMutex);
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 4f4373fbac..250d9fc6e5 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -259,8 +259,8 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
// AppKit expects rendering to happen on the main thread, and we can
// easily end up in situations where rendering on secondary threads
// will result in visual artifacts, bugs, or even deadlocks, when
- // building with SDK 10.14 or higher which enbles view layer-backing.
- return QMacVersion::buildSDK() < QOperatingSystemVersion(QOperatingSystemVersion::MacOSMojave);
+ // layer-backed.
+ return false;
case OpenGL:
case BufferQueueingOpenGL:
#endif
@@ -333,13 +333,7 @@ QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *wi
return nullptr;
}
- QPlatformBackingStore *backingStore = nullptr;
- if (platformWindow->view().layer)
- backingStore = new QCALayerBackingStore(window);
- else
- backingStore = new QNSWindowBackingStore(window);
-
- return backingStore;
+ return new QCALayerBackingStore(window);
}
QAbstractEventDispatcher *QCocoaIntegration::createEventDispatcher() const
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 927c3bd751..d7c4a66514 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -261,8 +261,6 @@ public: // for QNSView
bool m_inSetStyleMask;
QCocoaMenuBar *m_menubar;
- bool m_needsInvalidateShadow;
-
bool m_frameStrutEventsEnabled;
QRect m_exposedRect;
int m_registerTouchCount;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 9a6555ca8c..b07844819d 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -145,7 +145,6 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
, m_inSetGeometry(false)
, m_inSetStyleMask(false)
, m_menubar(nullptr)
- , m_needsInvalidateShadow(false)
, m_frameStrutEventsEnabled(false)
, m_registerTouchCount(0)
, m_resizableTransientParent(false)
@@ -1056,27 +1055,15 @@ void QCocoaWindow::setMask(const QRegion &region)
{
qCDebug(lcQpaWindow) << "QCocoaWindow::setMask" << window() << region;
- if (m_view.layer) {
- if (!region.isEmpty()) {
- QCFType<CGMutablePathRef> maskPath = CGPathCreateMutable();
- for (const QRect &r : region)
- CGPathAddRect(maskPath, nullptr, r.toCGRect());
- CAShapeLayer *maskLayer = [CAShapeLayer layer];
- maskLayer.path = maskPath;
- m_view.layer.mask = maskLayer;
- } else {
- m_view.layer.mask = nil;
- }
+ if (!region.isEmpty()) {
+ QCFType<CGMutablePathRef> maskPath = CGPathCreateMutable();
+ for (const QRect &r : region)
+ CGPathAddRect(maskPath, nullptr, r.toCGRect());
+ CAShapeLayer *maskLayer = [CAShapeLayer layer];
+ maskLayer.path = maskPath;
+ m_view.layer.mask = maskLayer;
} else {
- if (isContentView()) {
- // Setting the mask requires invalidating the NSWindow shadow, but that needs
- // to happen after the backingstore has been redrawn, so that AppKit can pick
- // up the new window shape based on the backingstore content. Doing a display
- // directly here is not an option, as the window might not be exposed at this
- // time, and so would not result in an updated backingstore.
- m_needsInvalidateShadow = true;
- [m_view setNeedsDisplay:YES];
- }
+ m_view.layer.mask = nil;
}
}
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index 2b9cffa714..1b4178d4a3 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -43,7 +43,13 @@
- (void)initDrawing
{
- [self updateLayerBacking];
+ if (qt_mac_resolveOption(-1, m_platformWindow->window(),
+ "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER") != -1) {
+ qCWarning(lcQpaDrawing) << "Layer-backing is always enabled."
+ << " QT_MAC_WANTS_LAYER/_q_mac_wantsLayer has no effect.";
+ }
+
+ self.wantsLayer = YES;
}
- (BOOL)isOpaque
@@ -60,40 +66,6 @@
// ----------------------- Layer setup -----------------------
-- (void)updateLayerBacking
-{
- self.wantsLayer = [self layerEnabledByMacOS]
- || [self layerExplicitlyRequested]
- || [self shouldUseMetalLayer];
-}
-
-- (BOOL)layerEnabledByMacOS
-{
- // AppKit has its own logic for this, but if we rely on that, our layers are created
- // by AppKit at a point where we've already set up other parts of the platform plugin
- // based on the presence of layers or not. Once we've rewritten these parts to support
- // dynamically picking up layer enablement we can let AppKit do its thing.
- return QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave
- && QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave;
-}
-
-- (BOOL)layerExplicitlyRequested
-{
- static bool wantsLayer = [&]() {
- int wantsLayer = qt_mac_resolveOption(-1, m_platformWindow->window(),
- "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
-
- if (wantsLayer != -1 && [self layerEnabledByMacOS]) {
- qCWarning(lcQpaDrawing) << "Layer-backing cannot be explicitly controlled on 10.14 when built against the 10.14 SDK";
- return true;
- }
-
- return wantsLayer == 1;
- }();
-
- return wantsLayer;
-}
-
- (BOOL)shouldUseMetalLayer
{
// MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK)
@@ -146,8 +118,7 @@
{
qCDebug(lcQpaDrawing) << "Making" << self
<< (self.wantsLayer ? "layer-backed" : "layer-hosted")
- << "with" << layer << "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
- : [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
+ << "with" << layer;
if (layer.delegate && layer.delegate != self) {
qCWarning(lcQpaDrawing) << "Layer already has delegate" << layer.delegate
@@ -244,22 +215,6 @@
{
Q_ASSERT_X(!self.layer, "QNSView",
"The drawRect code path should not be hit when we are layer backed");
-
- if (!m_platformWindow)
- return;
-
- QRegion exposedRegion;
- const NSRect *dirtyRects;
- NSInteger numDirtyRects;
- [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
- for (int i = 0; i < numDirtyRects; ++i)
- exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
-
- if (exposedRegion.isEmpty())
- exposedRegion = QRectF::fromCGRect(dirtyBoundingRect).toRect();
-
- qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
- m_platformWindow->handleExposeEvent(exposedRegion);
}
/*