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>
This commit is contained in:
parent
23697466ca
commit
0a7eb034f4
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
#include <QtGraphicsSupport/private/qrasterbackingstore_p.h>
|
#include <QtGraphicsSupport/private/qrasterbackingstore_p.h>
|
||||||
|
|
||||||
|
#include <private/qcore_mac_p.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QCocoaBackingStore : public QRasterBackingStore
|
class QCocoaBackingStore : public QRasterBackingStore
|
||||||
@ -50,12 +52,16 @@ public:
|
|||||||
QCocoaBackingStore(QWindow *window);
|
QCocoaBackingStore(QWindow *window);
|
||||||
~QCocoaBackingStore();
|
~QCocoaBackingStore();
|
||||||
|
|
||||||
|
void beginPaint(const QRegion &) override;
|
||||||
|
void endPaint() override;
|
||||||
|
|
||||||
void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE;
|
void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool windowHasUnifiedToolbar() const;
|
bool windowHasUnifiedToolbar() const;
|
||||||
QImage::Format format() const Q_DECL_OVERRIDE;
|
QImage::Format format() const Q_DECL_OVERRIDE;
|
||||||
void redrawRoundedBottomCorners(CGRect) const;
|
void redrawRoundedBottomCorners(CGRect) const;
|
||||||
|
QCFType<CGImageRef> m_cgImage;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -48,6 +48,7 @@ Q_LOGGING_CATEGORY(lcCocoaBackingStore, "qt.qpa.cocoa.backingstore");
|
|||||||
|
|
||||||
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
|
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
|
||||||
: QRasterBackingStore(window)
|
: QRasterBackingStore(window)
|
||||||
|
, m_cgImage(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,6 +70,18 @@ QImage::Format QCocoaBackingStore::format() const
|
|||||||
return QRasterBackingStore::format();
|
return QRasterBackingStore::format();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QCocoaBackingStore::beginPaint(const QRegion ®ion)
|
||||||
|
{
|
||||||
|
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)
|
#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
|
||||||
static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
|
static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
|
||||||
static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
|
static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
|
||||||
@ -107,6 +120,25 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo
|
|||||||
qCDebug(lcCocoaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
|
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
|
// 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
|
// main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
|
||||||
// individual view, starting with the top level and then traversing any subviews,
|
// individual view, starting with the top level and then traversing any subviews,
|
||||||
@ -156,8 +188,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo
|
|||||||
"Focusing the view should give us a current graphics context");
|
"Focusing the view should give us a current graphics context");
|
||||||
|
|
||||||
// Create temporary image to use for blitting, without copying image data
|
// Create temporary image to use for blitting, without copying image data
|
||||||
NSImage *backingStoreImage = [[[NSImage alloc]
|
NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:m_cgImage size:NSZeroSize] autorelease];
|
||||||
initWithCGImage:QCFType<CGImageRef>(m_image.toCGImage()) size:NSZeroSize] autorelease];
|
|
||||||
|
|
||||||
if ([topLevelView hasMask]) {
|
if ([topLevelView hasMask]) {
|
||||||
// FIXME: Implement via NSBezierPath and addClip
|
// FIXME: Implement via NSBezierPath and addClip
|
||||||
|
@ -384,6 +384,22 @@ static QTouchDevice *touchDevice = 0;
|
|||||||
m_platformWindow->handleExposeEvent(exposedRegion);
|
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
|
- (BOOL)isFlipped
|
||||||
{
|
{
|
||||||
return YES;
|
return YES;
|
||||||
|
Loading…
Reference in New Issue
Block a user