Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-137354

MainWindow surface change when showing a QDialog with embedded QWebEngineView

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.8.3
    • None
    • Windows

    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

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            lagocs Laszlo Agocs
            roman_w Roman Woelker
            Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes