summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2017-08-15 17:33:25 +0200
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2017-08-21 10:18:12 +0000
commit0a7eb034f402637e139072dc19579775a416e2a8 (patch)
treea1b0b5f4d25c9d47e98035e3970b920807419e75 /src/plugins/platforms
parent23697466cae8f1a49537fed1e60db8cea79207b4 (diff)
macOS: Restore support for layered mode
After 871966 we now do drawing as a result of drawRect calls, but layer backed mode was not taken into account. This restores support for both pull and push-mode drawing in layer-backed mode. Change-Id: I35039ee9eb4486206f9f92f8230df104473368c9 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm35
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm16
3 files changed, 55 insertions, 2 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 7e8f4beedd..002e5b40a8 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -42,6 +42,8 @@
#include <QtGraphicsSupport/private/qrasterbackingstore_p.h>
+#include <private/qcore_mac_p.h>
+
QT_BEGIN_NAMESPACE
class QCocoaBackingStore : public QRasterBackingStore
@@ -50,12 +52,16 @@ public:
QCocoaBackingStore(QWindow *window);
~QCocoaBackingStore();
+ void beginPaint(const QRegion &) override;
+ void endPaint() override;
+
void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE;
private:
bool windowHasUnifiedToolbar() const;
QImage::Format format() const Q_DECL_OVERRIDE;
void redrawRoundedBottomCorners(CGRect) const;
+ QCFType<CGImageRef> m_cgImage;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index b684435823..61f44e37d1 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -48,6 +48,7 @@ Q_LOGGING_CATEGORY(lcCocoaBackingStore, "qt.qpa.cocoa.backingstore");
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
: QRasterBackingStore(window)
+ , m_cgImage(nullptr)
{
}
@@ -69,6 +70,18 @@ QImage::Format QCocoaBackingStore::format() const
return QRasterBackingStore::format();
}
+void QCocoaBackingStore::beginPaint(const QRegion &region)
+{
+ m_cgImage = nullptr;
+ QRasterBackingStore::beginPaint(region);
+}
+
+void QCocoaBackingStore::endPaint()
+{
+ QRasterBackingStore::endPaint();
+ m_cgImage = m_image.toCGImage();
+}
+
#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
@@ -107,6 +120,25 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
qCDebug(lcCocoaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
}
+ if (view.layer) {
+ // In layer-backed mode, locking focus on a view does not give the right
+ // view transformation, and doesn't give us a graphics context to render
+ // via when drawing outside of the display cycle. Instead we tell AppKit
+ // that we want to update the layer's content, via [NSView wantsUpdateLayer],
+ // which result in AppKit not creating a backingstore for each layer, and
+ // we then directly set the layer's backingstore (content) to our backingstore,
+ // masked to the part of the subview that is relevant.
+ // FIXME: Figure out if there's a way to do partial updates
+ view.layer.contents = (__bridge id)static_cast<CGImageRef>(m_cgImage);
+ if (view != topLevelView) {
+ view.layer.contentsRect = CGRectApplyAffineTransform(
+ [view convertRect:view.bounds toView:topLevelView],
+ // The contentsRect is in unit coordinate system
+ CGAffineTransformMakeScale(1.0 / m_image.width(), 1.0 / m_image.height()));
+ }
+ return;
+ }
+
// 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,
@@ -156,8 +188,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
"Focusing the view should give us a current graphics context");
// Create temporary image to use for blitting, without copying image data
- NSImage *backingStoreImage = [[[NSImage alloc]
- initWithCGImage:QCFType<CGImageRef>(m_image.toCGImage()) size:NSZeroSize] autorelease];
+ NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:m_cgImage size:NSZeroSize] autorelease];
if ([topLevelView hasMask]) {
// FIXME: Implement via NSBezierPath and addClip
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 4c485dc807..8d3cb6cc05 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -384,6 +384,22 @@ static QTouchDevice *touchDevice = 0;
m_platformWindow->handleExposeEvent(exposedRegion);
}
+- (BOOL)wantsUpdateLayer
+{
+ return YES;
+}
+
+- (void)updateLayer
+{
+ if (!m_platformWindow)
+ return;
+
+ qCDebug(lcQpaCocoaWindow) << "[QNSView updateLayer]" << m_platformWindow->window();
+
+ // FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
+ m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
+}
+
- (BOOL)isFlipped
{
return YES;