Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.8.3
-
None
Description
When popping up a QDialog with an embedded QWebEngineView the rhi surface type of the MainWindow is changed from raster to e.g. direct3d surface.
This happens when the MainWindow is passed as parent through the QDialog constructor, which is required when you want to center the dialog on the MainWindow or have proper minimize/maximize behavior with the dialog staying in front of the MainWindow.
The problem seems to occur due to the fact the QDialog doesn't have a platform window yet at the time the QWebEngineView is about to be parented into the QDialog's child hierarchy, with the result that closestParentWidgetWithWindowHandle() in:
void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) { ... QWidget *newParentWithWindow = d->closestParentWidgetWithWindowHandle();
returns the MainWindow as parent with a valid windowHandle and then doing the rhi surface change on it.
Since both windows MainWindow and QDialog are supposed to be toplevel windows, having their own platform window in the background, I wouldn't expect the render surface change on the MainWindow.
This worked in 6.5.3 and is unfortunately having bad side effects in our App due to the unexpected destruction of the App platform window.
Note that the workaround of explicitly setting the WA_NativeWindow flag on the webview isn't very applicable when creating the dialog with QtUiDesigner.
Sample Code to repro the issue:
#include <QtWidgets/QApplication> #include <QtWidgets/QtWidgets> #include <QWebEngineView> class SurfaceEventFilter : public QObject { public: SurfaceEventFilter(QObject* parent) : QObject(parent) {} protected: bool eventFilter(QObject* obj, QEvent* event) override { if (event->type() == QEvent::PlatformSurface) { auto surfaceEvent = static_cast<QPlatformSurfaceEvent*>(event); if (surfaceEvent->surfaceEventType() && QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) { qDebug() << "MainWindow SurfaceAboutToBeDestroyed!!!"; } } return __super::eventFilter(obj, event);; } }; class WebViewDialog : public QDialog { public: WebViewDialog(QWidget* parent) : QDialog(parent) { setWindowTitle("Webengine Dialog Host"); setAttribute(Qt::WA_DeleteOnClose, true); auto horzLayout = new QHBoxLayout(this); auto webView = new QWebEngineView(); horzLayout->addWidget(webView); webView->load(QUrl("https://qt-project.org/")); } }; int main( int argc, char *argv[] ) { QApplication app( argc, argv ); app.setQuitOnLastWindowClosed(true); // Create top level MainWindow auto mainWindow = new QMainWindow(); mainWindow->setAttribute(Qt::WA_DeleteOnClose); mainWindow->setWindowTitle(QString("TLW Surface Change Test - Qt%1.%2.%3").arg(QT_VERSION_MAJOR).arg(QT_VERSION_MINOR).arg(QT_VERSION_PATCH)); mainWindow->resize(800, 600); mainWindow->show(); // Add event filter to MainWindow's platform window to monitor original raster surface destruction mainWindow->windowHandle()->installEventFilter(new SurfaceEventFilter(mainWindow)); qDebug() << "MainWindow surfaceType before WebViewDialog:" << mainWindow->windowHandle()->surfaceType(); // Create a top level dialog that hosts a webview // Note that we pass in the mainWindow as parent here, so that the dialog pops up centered on the mainwindow // and the dialog is properly hiding/showing when e.g. minimizing/maximizing the mainwindow. // Passing mainWindow as parent here will change it's render surface type!! // Should not happen since both windows are supposed to be top level windows, having their own platform window in the background. auto dlg = new WebViewDialog(mainWindow); dlg->resize(640, 480); dlg->show(); qDebug() << "WebViewDialog surfaceType:" << dlg->windowHandle()->surfaceType(); qDebug() << "MainWindow surfaceType after WebViewDialog:" << mainWindow->windowHandle()->surfaceType(); // Run Qt message loop return app.exec(); }
qDebug printout of the code above:
MainWindow surfaceType before WebViewDialog: QSurface::RasterSurface MainWindow SurfaceAboutToBeDestroyed!!! WebViewDialog surfaceType: QSurface::Direct3DSurface MainWindow surfaceType after WebViewDialog: QSurface::Direct3DSurface