macOS: Handle platform window destroy and create in backingstore

We observe changes to the NSWindow to pick up color space changes,
so we need to track when the platform window is destroyed and created
to match our observer with the recreated NSWindow.

This does not handle the fact that we're internally recreating the
NSWindow if certain window flag changes requires so, without letting
clients know via surface events.

Task-number: QTBUG-85915
Pick-to: 5.15
Change-Id: I7a7d728c742def79adebaadc985cedd86ea0d581
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Tor Arne Vestbø 2020-08-06 16:57:44 +02:00
parent abb985a403
commit b4f6fdf575
2 changed files with 39 additions and 19 deletions

View File

@ -96,6 +96,9 @@ public:
QPlatformGraphicsBuffer *graphicsBuffer() const override;
private:
void observeBackingPropertiesChanges();
bool eventFilter(QObject *watched, QEvent *event) override;
QSize m_requestedSize;
QRegion m_paintedRegion;

View File

@ -340,31 +340,39 @@ QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window;
m_buffers.resize(1);
// Ideally this would be plumbed from the platform layer to QtGui, and
// the QBackingStore would be recreated, but we don't have that code yet,
// so at least make sure we update our backingstore when the backing
// properties (color space e.g.) are changed.
NSView *view = static_cast<QCocoaWindow *>(window->handle())->view();
m_backingPropertiesObserver = QMacNotificationObserver(view.window,
NSWindowDidChangeBackingPropertiesNotification, [this]() {
if (!this->window()->handle()) {
// The platform window has been destroyed, but the backingstore
// is still alive, as that's tied to a QWindow. The original
// NSWindow we were observing is also likely gone. FIXME:
// We should listen for surface events from the QWindow and
// remove and re-attach our observer based on those.
return;
}
qCDebug(lcQpaBackingStore) << "Backing properties for"
<< this->window() << "did change";
backingPropertiesChanged();
});
observeBackingPropertiesChanges();
window->installEventFilter(this);
}
QCALayerBackingStore::~QCALayerBackingStore()
{
}
void QCALayerBackingStore::observeBackingPropertiesChanges()
{
Q_ASSERT(window()->handle());
NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
m_backingPropertiesObserver = QMacNotificationObserver(view.window,
NSWindowDidChangeBackingPropertiesNotification, [this]() {
backingPropertiesChanged();
});
}
bool QCALayerBackingStore::eventFilter(QObject *watched, QEvent *event)
{
Q_ASSERT(watched == window());
if (event->type() == QEvent::PlatformSurface) {
auto *surfaceEvent = static_cast<QPlatformSurfaceEvent*>(event);
if (surfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated)
observeBackingPropertiesChanges();
else
m_backingPropertiesObserver = QMacNotificationObserver();
}
return false;
}
void QCALayerBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
@ -662,6 +670,15 @@ QImage QCALayerBackingStore::toImage() const
void QCALayerBackingStore::backingPropertiesChanged()
{
// Ideally this would be plumbed from the platform layer to QtGui, and
// the QBackingStore would be recreated, but we don't have that code yet,
// so at least make sure we update our backingstore when the backing
// properties (color space e.g.) are changed.
Q_ASSERT(window()->handle());
qCDebug(lcQpaBackingStore) << "Backing properties for" << window() << "did change";
qCDebug(lcQpaBackingStore) << "Updating color space of existing buffers";
for (auto &buffer : m_buffers) {
if (buffer)