diff options
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 9 | ||||
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 8 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp | 37 |
3 files changed, 54 insertions, 0 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 8e98958949..c94ea0922a 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1814,6 +1814,15 @@ void QWindowPrivate::destroy() q->setVisible(false); + // Let subclasses act, typically by doing graphics resource cleaup, when + // the window, to which graphics resource may be tied, is going away. + // + // NB! This is disfunctional when destroy() is invoked from the dtor since + // a reimplemented event() will not get called in the subclasses at that + // stage. However, the typical QWindow cleanup involves either close() or + // going through QWindowContainer, both of which will do an explicit, early + // destroy(), which is good here. + QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed); QGuiApplication::sendEvent(q, &e); diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index bb25a3a986..7ae63e54b3 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -241,6 +241,14 @@ QWindow *QWindowContainer::containedWindow() const QWindowContainer::~QWindowContainer() { Q_D(QWindowContainer); + + // Call destroy() explicitly first. The dtor would do this too, but + // QEvent::PlatformSurface delivery relies on virtuals. Getting + // SurfaceAboutToBeDestroyed can be essential for OpenGL, Vulkan, etc. + // QWindow subclasses in particular. Keep these working. + if (d->window) + d->window->destroy(); + delete d->window; } diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp index 5e3868ea8f..6ec1b754d0 100644 --- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp +++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp @@ -37,6 +37,7 @@ #include <qmainwindow.h> #include <qscreen.h> #include <qscopedpointer.h> +#include <qevent.h> class Window : public QWindow @@ -77,6 +78,7 @@ private slots: void testAncestorChange(); void testDockWidget(); void testNativeContainerParent(); + void testPlatformSurfaceEvent(); void cleanup(); private: @@ -343,6 +345,41 @@ void tst_QWindowContainer::testNativeContainerParent() QTRY_COMPARE(window->parent(), container->windowHandle()); } +class EventWindow : public QWindow +{ +public: + EventWindow(bool *surfaceDestroyFlag) : m_surfaceDestroyFlag(surfaceDestroyFlag) { } + bool event(QEvent *e) override; + +private: + bool *m_surfaceDestroyFlag; +}; + +bool EventWindow::event(QEvent *e) +{ + if (e->type() == QEvent::PlatformSurface) { + if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) + *m_surfaceDestroyFlag = true; + } + return QWindow::event(e); +} + +void tst_QWindowContainer::testPlatformSurfaceEvent() +{ + // Verify that SurfaceAboutToBeDestroyed is delivered and the + // window subclass still gets a chance to process it. + + bool ok = false; + QPointer<EventWindow> window(new EventWindow(&ok)); + window->create(); + QWidget *container = QWidget::createWindowContainer(window); + + delete container; + + QCOMPARE(window.data(), nullptr); + QVERIFY(ok); +} + QTEST_MAIN(tst_QWindowContainer) #include "tst_qwindowcontainer.moc" |