summaryrefslogtreecommitdiffstats
path: root/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp')
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp81
1 files changed, 42 insertions, 39 deletions
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
index c32e89f0c..7bbd85091 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -49,7 +49,7 @@
#include <QSGAbstractRenderer>
#include <QSGNode>
#include <QWindow>
-#include <private/qquickwindow_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
namespace QtWebEngineCore {
@@ -165,15 +165,28 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_AlwaysShowToolTips);
- if (parent) {
- // Unset the popup parent if the parent is being destroyed, thus making sure a double
- // delete does not happen.
- // Also in case the delegate is destroyed before its parent (when a popup is simply
- // dismissed), this connection will automatically be removed by ~QObject(), preventing
- // a use-after-free.
+ setContent(QUrl(), nullptr, m_rootItem.data());
+
+ connectRemoveParentBeforeParentDelete();
+}
+
+RenderWidgetHostViewQtDelegateWidget::~RenderWidgetHostViewQtDelegateWidget()
+{
+ QWebEnginePagePrivate::bindPageAndWidget(nullptr, this);
+}
+
+void RenderWidgetHostViewQtDelegateWidget::connectRemoveParentBeforeParentDelete()
+{
+ if (QWidget *parent = parentWidget())
connect(parent, &QObject::destroyed,
this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete);
- }
+}
+
+void RenderWidgetHostViewQtDelegateWidget::disconnectRemoveParentBeforeParentDelete()
+{
+ if (QWidget *parent = parentWidget())
+ disconnect(parent, &QObject::destroyed,
+ this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete);
}
void RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete()
@@ -188,29 +201,9 @@ void RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete()
close();
}
-void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient* container)
-{
- setContent(QUrl(), nullptr, m_rootItem.data());
-
- QWebEnginePagePrivate *pagePrivate = static_cast<QWebEnginePagePrivate *>(container);
- if (pagePrivate->view) {
- if (parentWidget())
- disconnect(parentWidget(), &QObject::destroyed,
- this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete);
- pagePrivate->view->layout()->addWidget(this);
- if (QWidget *focusProxy = pagePrivate->view->focusProxy())
- if (focusProxy != this)
- pagePrivate->view->layout()->removeWidget(focusProxy);
- pagePrivate->view->setFocusProxy(this);
- show();
- } else
- setParent(0);
-}
-
void RenderWidgetHostViewQtDelegateWidget::initAsPopup(const QRect& screenRect)
{
m_isPopup = true;
- setContent(QUrl(), nullptr, m_rootItem.data());
// The keyboard events are supposed to go to the parent RenderHostView
// so the WebUI popups should never have focus. Besides, if the parent view
@@ -249,20 +242,18 @@ QRectF RenderWidgetHostViewQtDelegateWidget::contentsRect() const
void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus()
{
- // If the corresponding window is inactive (for example, because of a popup),
- // the active focus cannot be set. Sync up with the Window System to try to
- // reactivate the window in time if the other window (possibly popup) which took
- // the focus is already closed.
- if (window() && !window()->isActive())
- QGuiApplication::sync();
+ // The root item always has focus within the root focus scope:
+ Q_ASSERT(m_rootItem->hasFocus());
- m_rootItem->forceActiveFocus();
setFocus();
}
bool RenderWidgetHostViewQtDelegateWidget::hasKeyboardFocus()
{
- return m_rootItem->hasActiveFocus();
+ // The root item always has focus within the root focus scope:
+ Q_ASSERT(m_rootItem->hasFocus());
+
+ return hasFocus();
}
void RenderWidgetHostViewQtDelegateWidget::lockMouse()
@@ -312,13 +303,13 @@ QSGLayer *RenderWidgetHostViewQtDelegateWidget::createLayer()
return renderContext->sceneGraphContext()->createLayer(renderContext);
}
-QSGInternalImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode()
+QSGInternalImageNode *RenderWidgetHostViewQtDelegateWidget::createInternalImageNode()
{
QSGRenderContext *renderContext = QQuickWindowPrivate::get(quickWindow())->context;
return renderContext->sceneGraphContext()->createInternalImageNode();
}
-QSGTextureNode *RenderWidgetHostViewQtDelegateWidget::createTextureNode()
+QSGImageNode *RenderWidgetHostViewQtDelegateWidget::createImageNode()
{
return quickWindow()->createImageNode();
}
@@ -403,7 +394,7 @@ void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event)
// We don't have a way to catch a top-level window change with QWidget
// but a widget will most likely be shown again if it changes, so do
// the reconnection at this point.
- foreach (const QMetaObject::Connection &c, m_windowConnections)
+ for (const QMetaObject::Connection &c : qAsConst(m_windowConnections))
disconnect(c);
m_windowConnections.clear();
if (QWindow *w = window()) {
@@ -424,6 +415,18 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event)
{
bool handled = false;
+ // Track parent to make sure we don't get deleted.
+ switch (event->type()) {
+ case QEvent::ParentAboutToChange:
+ disconnectRemoveParentBeforeParentDelete();
+ break;
+ case QEvent::ParentChange:
+ connectRemoveParentBeforeParentDelete();
+ break;
+ default:
+ break;
+ }
+
// Mimic QWidget::event() by ignoring mouse, keyboard, touch and tablet events if the widget is
// disabled.
if (!isEnabled()) {