summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qwindow.cpp9
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp8
-rw-r--r--tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp37
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"