summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2016-09-13 18:17:43 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2016-11-10 11:58:00 +0000
commit58467ed1950ee070d0907cbdabb8466aba277305 (patch)
tree476f9565958078738676dd57aba2b31d70107240 /src
parentff26fa899f095eff9b3265b462e97c7e48ab06f5 (diff)
Fix select tag interaction when the web view is inside a modal dialog
Previously when a QWebEngineView was inside a modal QDialog, trying to click on a select tag option did not properly select the option. It either focused the new option without closing the popup, or didn't focus it at all. Fix consists in making sure the newly created popup QWindow and RenderWidgetHostViewQtDelegateWidget are marked as children of the QWebEngineView, so that they are considered part of the current modal session by the OS, thus allowing user interaction with them. Because the ownership of the delegate widget should still be retained by its respective RenderWidgetHostViewQt instance, the QObject parent of the delegate is unset before the parent is destroyed. Also to make it work on macOS, the window attribute has to be set to Qt::Tool instead of Qt::ToolTip. Change-Id: I56d6f446254a624428a0c661ac3c49eb409c931e Task-number: QTBUG-54836 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp11
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp21
-rw-r--r--src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h1
3 files changed, 31 insertions, 2 deletions
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index df96f4c17..a9a908e13 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -144,7 +144,16 @@ QWebEnginePagePrivate::~QWebEnginePagePrivate()
RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client)
{
- return new RenderWidgetHostViewQtDelegateWidget(client);
+ // Set the QWebEngineView as the parent for a popup delegate, so that the new popup window
+ // responds properly to clicks in case the QWebEngineView is inside a modal QDialog. Setting the
+ // parent essentially notifies the OS that the popup window is part of the modal session, and
+ // should allow interaction.
+ // The new delegate will not be deleted by the parent view though, because we unset the parent
+ // when the parent is destroyed. The delegate will be destroyed by Chromium when the popup is
+ // dismissed.
+ // If the delegate is not for a popup, but for a newly created QWebEngineView, the parent is 0
+ // just like before.
+ return new RenderWidgetHostViewQtDelegateWidget(client, this->view);
}
void QWebEnginePagePrivate::titleChanged(const QString &title)
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 5bc1671df..a3ad898ad 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp
@@ -103,6 +103,21 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende
setAttribute(Qt::WA_AcceptTouchEvents);
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.
+ connect(parent, &QObject::destroyed,
+ this, &RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete);
+ }
+}
+
+void RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete()
+{
+ setParent(Q_NULLPTR);
}
void RenderWidgetHostViewQtDelegateWidget::initAsChild(WebContentsAdapterClient* container)
@@ -125,7 +140,11 @@ void RenderWidgetHostViewQtDelegateWidget::initAsPopup(const QRect& screenRect)
// to be destroyed.
setAttribute(Qt::WA_ShowWithoutActivating);
setFocusPolicy(Qt::NoFocus);
- setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
+
+ // macOS doesn't like Qt::ToolTip when QWebEngineView is inside a modal dialog, specifically by
+ // not forwarding click events to the popup. So we use Qt::Tool which behaves the same way, but
+ // works on macOS too.
+ setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
setGeometry(screenRect);
show();
diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
index ecf2d2d33..aa9495105 100644
--- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
+++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h
@@ -92,6 +92,7 @@ protected:
private slots:
void onWindowPosChanged();
+ void removeParentBeforeParentDelete();
private:
RenderWidgetHostViewQtDelegateClient *m_client;