summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-04-30 17:15:57 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-06-03 02:40:25 +0200
commit82fe139dae5205a1683fb2b344c5dc867597c443 (patch)
treeeeae61e1f34ebbc8536ebc2681d43de8dfb6e475
parent5a0b312214ac182749040dac7ca09610c2124fbd (diff)
Move createWindow to a signal
Ports QQuickWebEngineNewViewRequest to QtWebEngineCore. [ChangeLog][QtWebEngineQuick][WebEngineView] WebEngineView::NewViewRequested is now handled with WebEngineView::acceptAsNewView() instead of with WebEngineNewViewRequest::openIn(). Task-number: QTBUG-74587 Change-Id: I9b27128948076e13f2c228458e1e7491df12153d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml14
-rw-r--r--src/core/api/CMakeLists.txt1
-rw-r--r--src/core/api/qwebenginenewwindowrequest.cpp206
-rw-r--r--src/core/api/qwebenginenewwindowrequest.h (renamed from src/webenginequick/api/qquickwebenginenewviewrequest_p.h)70
-rw-r--r--src/core/api/qwebenginepage.cpp195
-rw-r--r--src/core/api/qwebenginepage.h4
-rw-r--r--src/core/api/qwebenginepage_p.h2
-rw-r--r--src/webenginequick/CMakeLists.txt1
-rw-r--r--src/webenginequick/api/qquickwebenginenewviewrequest.cpp122
-rw-r--r--src/webenginequick/api/qquickwebengineview.cpp74
-rw-r--r--src/webenginequick/api/qquickwebengineview_p.h17
-rw-r--r--src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml4
-rw-r--r--src/webenginequick/doc/src/webengineview_lgpl.qdoc29
-rw-r--r--src/webenginequick/plugin/plugin.cpp5
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp2
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc13
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp23
-rw-r--r--tests/auto/quick/qmltests/data/tst_newViewRequest.qml16
-rw-r--r--tests/auto/quick/qmltests/data/tst_viewSource.qml6
-rw-r--r--tests/auto/util/testwindow.h2
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp45
21 files changed, 528 insertions, 323 deletions
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index 1b8915df2..2fa4019c1 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -518,19 +518,19 @@ ApplicationWindow {
onNewViewRequested: function(request) {
if (!request.userInitiated)
print("Warning: Blocked a popup window.");
- else if (request.destination === WebEngineView.NewViewInTab) {
+ else if (request.destination === WebEngineNewViewRequest.InNewTab) {
var tab = tabs.createEmptyTab(currentWebView.profile);
tabs.currentIndex = tabs.count - 1;
- request.openIn(tab.item);
- } else if (request.destination === WebEngineView.NewViewInBackgroundTab) {
+ tab.item.acceptAsNewView(request);
+ } else if (request.destination === WebEngineNewViewRequest.InNewBackgroundTab) {
var backgroundTab = tabs.createEmptyTab(currentWebView.profile);
- request.openIn(backgroundTab.item);
- } else if (request.destination === WebEngineView.NewViewInDialog) {
+ backgroundTab.item.acceptAsNewView(request);
+ } else if (request.destination === WebEngineNewViewRequest.InNewDialog) {
var dialog = applicationRoot.createDialog(currentWebView.profile);
- request.openIn(dialog.currentWebView);
+ dialog.currentWebView.acceptAsNewView(request);
} else {
var window = applicationRoot.createWindow(currentWebView.profile);
- request.openIn(window.currentWebView);
+ window.currentWebView.acceptAsNewView(request);
}
}
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index 5df3ba7b9..bf2008ebd 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -26,6 +26,7 @@ qt_internal_add_module(WebEngineCore
qwebenginehttprequest.cpp qwebenginehttprequest.h
qwebengineloadrequest.cpp qwebengineloadrequest.h
qwebenginemessagepumpscheduler.cpp qwebenginemessagepumpscheduler_p.h
+ qwebenginenewwindowrequest.cpp qwebenginenewwindowrequest.h
qwebenginenotification.cpp qwebenginenotification.h
qwebenginepage.cpp qwebenginepage.h qwebenginepage_p.h
qwebengineprofile.cpp qwebengineprofile.h qwebengineprofile_p.h
diff --git a/src/core/api/qwebenginenewwindowrequest.cpp b/src/core/api/qwebenginenewwindowrequest.cpp
new file mode 100644
index 000000000..7ef7601d7
--- /dev/null
+++ b/src/core/api/qwebenginenewwindowrequest.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebenginenewwindowrequest.h"
+
+#include "web_contents_adapter.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QWebEngineNewWindowRequestPrivate
+{
+ QWebEngineNewWindowRequest::DestinationType destination;
+ QRect requestedGeometry;
+ QUrl requestedUrl;
+ QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter;
+ bool isUserInitiated;
+ bool isRequestHandled = false;
+};
+
+/*!
+ \class QWebEngineNewWindowRequest
+ \brief A utility type for the QWebEnginePage::newPageRequested signal.
+ \since 6.2
+
+ \inmodule QtWebEngineCore
+
+ Contains information about a request to load a page in a separate web engine view.
+
+ \sa QWebEnginePage::newPageRequested
+*/
+
+/*!
+ \qmltype WebEngineNewViewRequest
+ \instantiates QWebEngineNewWindowRequest
+ \inqmlmodule QtWebEngine
+ \since QtWebEngine 1.1
+
+ \brief A utility type for the WebEngineView::newViewRequested signal.
+
+ Contains information about a request to load a page in a separate web engine view.
+
+ \sa WebEngineView::newViewRequested
+*/
+
+/*!
+ \enum QWebEngineNewWindowRequest::DestinationType
+
+ This enum describes the type of window requested:
+
+ \value InNewWindow
+ In a separate window.
+ \value InNewTab
+ In a tab of the same window.
+ \value InNewDialog
+ In a window without a tab bar, toolbar, or URL bar.
+ \value InNewBackgroundTab
+ In a tab of the same window, without hiding the currently visible web engine view.
+*/
+
+/*!
+ \qmlproperty enumeration WebEngineNewViewRequest::DestinationType
+
+ Describes how to open a new view:
+
+ \value WebEngineNewViewRequest.InNewWindow
+ In a separate window.
+ \value WebEngineNewViewRequest.InNewTab
+ In a tab of the same window.
+ \value WebEngineNewViewRequest.InNewDialog
+ In a window without a tab bar, toolbar, or URL bar.
+ \value WebEngineNewViewRequest.InNewBackgroundTab
+ In a tab of the same window, without hiding the currently visible web engine view.
+*/
+
+QWebEngineNewWindowRequest::QWebEngineNewWindowRequest(QWebEngineNewWindowRequest::DestinationType destination,
+ const QRect &geometry,
+ const QUrl &url,
+ bool userInitiated,
+ QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter,
+ QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QWebEngineNewWindowRequestPrivate{destination, geometry, url, adapter, userInitiated})
+{
+}
+
+QWebEngineNewWindowRequest::~QWebEngineNewWindowRequest()
+{
+}
+
+/*!
+ \property QWebEngineNewWindowRequest::destination
+ \brief The type of window that is requested.
+*/
+/*!
+ \qmlproperty WebEngineNewViewRequest::DestinationType WebEngineNewViewRequest::destination
+ \brief The type of window that is requested.
+*/
+QWebEngineNewWindowRequest::DestinationType QWebEngineNewWindowRequest::destination() const
+{
+ return d_ptr->destination;
+}
+
+/*!
+ \property QWebEngineNewWindowRequest::requestedUrl
+ \brief The URL that is requested for the new page.
+*/
+/*!
+ \qmlproperty QUrl WebEngineNewViewRequest::requestedUrl
+ \brief The URL that is requested for the new page.
+ \since QtWebEngine 1.5
+ */
+QUrl QWebEngineNewWindowRequest::requestedUrl() const
+{
+ return d_ptr->requestedUrl;
+}
+
+/*!
+ \property QWebEngineNewWindowRequest::requestedGeometry
+ \brief The size that is requested for the new page.
+*/
+/*!
+ \qmlproperty QRect WebEngineNewViewRequest::requestedGeometry
+ \brief The size that is requested for the new page.
+ \since QtWebEngine 2.0
+ */
+QRect QWebEngineNewWindowRequest::requestedGeometry() const
+{
+ return d_ptr->requestedGeometry;
+}
+
+/*!
+ \property QWebEngineNewWindowRequest::userInitiated
+ Whether this page request was directly triggered as the result of a keyboard or mouse event.
+
+ You can use this property to block automatic \e popups.
+*/
+/*!
+ \qmlproperty bool WebEngineNewViewRequest::userInitiated
+ Whether this window request was directly triggered as the result of a keyboard or mouse event.
+
+ You can use this property to block automatic \e popups.
+ */
+bool QWebEngineNewWindowRequest::isUserInitiated() const
+{
+ return d_ptr->isUserInitiated;
+}
+
+/*! \internal
+*/
+QSharedPointer<QtWebEngineCore::WebContentsAdapter> QWebEngineNewWindowRequest::adapter()
+{
+ return d_ptr->adapter;
+}
+
+/*! \internal
+*/
+bool QWebEngineNewWindowRequest::isHandled() const
+{
+ return d_ptr->isRequestHandled;
+}
+
+/*! \internal
+*/
+void QWebEngineNewWindowRequest::setHandled()
+{
+ d_ptr->isRequestHandled = true;
+ d_ptr->adapter.reset();
+}
+
+QT_END_NAMESPACE
diff --git a/src/webenginequick/api/qquickwebenginenewviewrequest_p.h b/src/core/api/qwebenginenewwindowrequest.h
index 57ec76f79..b419a0202 100644
--- a/src/webenginequick/api/qquickwebenginenewviewrequest_p.h
+++ b/src/core/api/qwebenginenewwindowrequest.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -37,22 +37,15 @@
**
****************************************************************************/
-#ifndef QQUICKWEBENGINENEWVIEWREQUEST_P_H
-#define QQUICKWEBENGINENEWVIEWREQUEST_P_H
+#ifndef QWEBENGINENEWWINDOWREQUEST_P_H
+#define QWEBENGINENEWWINDOWREQUEST_P_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtWebEngineQuick/private/qtwebengineglobal_p.h>
-#include "qquickwebengineview_p.h"
+#include <qtwebenginecoreglobal.h>
+#include <QtCore/QObject>
+#include <QtCore/QRect>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QUrl>
namespace QtWebEngineCore {
class WebContentsAdapter;
@@ -60,32 +53,47 @@ class WebContentsAdapter;
QT_BEGIN_NAMESPACE
-class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineNewViewRequest : public QObject {
+struct QWebEngineNewWindowRequestPrivate;
+
+class Q_WEBENGINECORE_EXPORT QWebEngineNewWindowRequest : public QObject
+{
Q_OBJECT
- Q_PROPERTY(QQuickWebEngineView::NewViewDestination destination READ destination CONSTANT FINAL)
- Q_PROPERTY(QUrl requestedUrl READ requestedUrl CONSTANT REVISION(1,1) FINAL)
+ Q_PROPERTY(DestinationType destination READ destination CONSTANT FINAL)
+ Q_PROPERTY(QUrl requestedUrl READ requestedUrl CONSTANT FINAL)
+ Q_PROPERTY(QRect requestedGeometry READ requestedGeometry CONSTANT FINAL)
Q_PROPERTY(bool userInitiated READ isUserInitiated CONSTANT FINAL)
public:
- ~QQuickWebEngineNewViewRequest();
+ ~QWebEngineNewWindowRequest();
+
+ enum DestinationType {
+ InNewWindow,
+ InNewTab,
+ InNewDialog,
+ InNewBackgroundTab
+ };
+ Q_ENUM(DestinationType)
- QQuickWebEngineView::NewViewDestination destination() const;
+ DestinationType destination() const;
QUrl requestedUrl() const;
+ QRect requestedGeometry() const;
bool isUserInitiated() const;
- Q_INVOKABLE void openIn(QQuickWebEngineView *view);
private:
- QQuickWebEngineNewViewRequest();
- QQuickWebEngineView::NewViewDestination m_destination;
- bool m_isUserInitiated;
- bool m_isRequestHandled = false;
- QSharedPointer<QtWebEngineCore::WebContentsAdapter> m_adapter;
- QUrl m_requestedUrl;
+ QWebEngineNewWindowRequest(DestinationType, const QRect &, const QUrl &, bool,
+ QSharedPointer<QtWebEngineCore::WebContentsAdapter>,
+ QObject * = nullptr);
+
+ QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter();
+ bool isHandled() const;
+ void setHandled();
+
+ QScopedPointer<QWebEngineNewWindowRequestPrivate> d_ptr;
+ friend class QWebEnginePage;
+ friend class QWebEnginePagePrivate;
friend class QQuickWebEngineView;
friend class QQuickWebEngineViewPrivate;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QQuickWebEngineNewViewRequest)
-
-#endif // QQUICKWEBENGINENEWVIEWREQUEST_P_H
+#endif // QWEBENGINENEWWINDOWREQUEST_P_H
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index e96763f5d..548457349 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -56,6 +56,7 @@
#include "qwebenginefullscreenrequest.h"
#include "qwebenginehistory.h"
#include "qwebenginehistory_p.h"
+#include "qwebenginenewwindowrequest.h"
#include "qwebenginenotification.h"
#include "qwebengineprofile.h"
#include "qwebengineprofile_p.h"
@@ -150,6 +151,22 @@ static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::Wind
}
}
+static QWebEngineNewWindowRequest::DestinationType toDestinationType(WebContentsAdapterClient::WindowOpenDisposition disposition)
+{
+ switch (disposition) {
+ case WebContentsAdapterClient::NewForegroundTabDisposition:
+ return QWebEngineNewWindowRequest::InNewTab;
+ case WebContentsAdapterClient::NewBackgroundTabDisposition:
+ return QWebEngineNewWindowRequest::InNewBackgroundTab;
+ case WebContentsAdapterClient::NewPopupDisposition:
+ return QWebEngineNewWindowRequest::InNewDialog;
+ case WebContentsAdapterClient::NewWindowDisposition:
+ return QWebEngineNewWindowRequest::InNewWindow;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
: adapter(QSharedPointer<WebContentsAdapter>::create())
, history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this)))
@@ -347,40 +364,93 @@ QWebEnginePagePrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebC
const QRect &initialGeometry, const QUrl &targetUrl)
{
Q_Q(QWebEnginePage);
- Q_UNUSED(userGesture);
- Q_UNUSED(targetUrl);
+ Q_ASSERT(newWebContents);
+ QWebEnginePage *newPage = q->createWindow(toWindowType(disposition));
+ if (newPage) {
+ if (!newWebContents->webContents())
+ return newPage->d_func()->adapter; // Reuse existing adapter
+
+ // Mark the new page as being in the process of being adopted, so that a second mouse move event
+ // sent by newWebContents->initialize() gets filtered in RenderWidgetHostViewQt::forwardEvent.
+ // The first mouse move event is being sent by q->createWindow(). This is necessary because
+ // Chromium does not get a mouse move acknowledgment message between the two events, and
+ // InputRouterImpl::ProcessMouseAck is not executed, thus all subsequent mouse move events
+ // get coalesced together, and don't get processed at all.
+ // The mouse move events are actually sent as a result of show() being called on
+ // RenderWidgetHostViewQtDelegateWidget, both when creating the window and when initialize is
+ // called.
+ newPage->d_func()->m_isBeingAdopted = true;
+
+ // Overwrite the new page's WebContents with ours.
+ newPage->d_func()->adapter = newWebContents;
+ newWebContents->setClient(newPage->d_func());
+
+ if (!initialGeometry.isEmpty())
+ emit newPage->geometryChangeRequested(initialGeometry);
+
+ return newWebContents;
+ }
+
+ QWebEngineNewWindowRequest request(toDestinationType(disposition), initialGeometry,
+ targetUrl, userGesture, newWebContents);
+
+ Q_EMIT q->newWindowRequested(request);
+
+ if (request.isHandled())
+ return newWebContents;
+ return nullptr;
+}
+void QWebEnginePagePrivate::createNewWindow(WindowOpenDisposition disposition, bool userGesture, const QUrl &targetUrl)
+{
+ Q_Q(QWebEnginePage);
QWebEnginePage *newPage = q->createWindow(toWindowType(disposition));
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- if (!newPage)
- return nullptr;
-#else
- if (!newPage)
- return adapter;
-#endif
+ if (newPage) {
+ newPage->setUrl(targetUrl);
+ return;
+ }
- if (!newWebContents->webContents())
- return newPage->d_func()->adapter; // Reuse existing adapter
+ QWebEngineNewWindowRequest request(toDestinationType(disposition), QRect(),
+ targetUrl, userGesture, nullptr);
- // Mark the new page as being in the process of being adopted, so that a second mouse move event
- // sent by newWebContents->initialize() gets filtered in RenderWidgetHostViewQt::forwardEvent.
- // The first mouse move event is being sent by q->createWindow(). This is necessary because
- // Chromium does not get a mouse move acknowledgment message between the two events, and
- // InputRouterImpl::ProcessMouseAck is not executed, thus all subsequent mouse move events
- // get coalesced together, and don't get processed at all.
- // The mouse move events are actually sent as a result of show() being called on
- // RenderWidgetHostViewQtDelegateWidget, both when creating the window and when initialize is
- // called.
- newPage->d_func()->m_isBeingAdopted = true;
+ Q_EMIT q->newWindowRequested(request);
+}
- // Overwrite the new page's WebContents with ours.
- newPage->d_func()->adapter = newWebContents;
- newWebContents->setClient(newPage->d_func());
+class WebContentsAdapterOwner : public QObject
+{
+public:
+ typedef QSharedPointer<QtWebEngineCore::WebContentsAdapter> AdapterPtr;
+ WebContentsAdapterOwner(const AdapterPtr &ptr)
+ : adapter(ptr)
+ {}
- if (!initialGeometry.isEmpty())
- emit newPage->geometryChangeRequested(initialGeometry);
+private:
+ AdapterPtr adapter;
+};
- return newWebContents;
+void QWebEnginePagePrivate::adoptWebContents(WebContentsAdapter *webContents)
+{
+ if (!webContents) {
+ qWarning("Trying to open an empty request, it was either already used or was invalidated."
+ "\nYou must complete the request synchronously within the newPageRequested signal handler."
+ " If a view hasn't been adopted before returning, the request will be invalidated.");
+ return;
+ }
+
+ if (webContents->profileAdapter() && profileAdapter() != webContents->profileAdapter()) {
+ qWarning("Can not adopt content from a different WebEngineProfile.");
+ return;
+ }
+
+ m_isBeingAdopted = true;
+
+ // This throws away the WebContentsAdapter that has been used until now.
+ // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter.
+ WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter->sharedFromThis());
+ adapterOwner->deleteLater();
+
+ adapter = webContents->sharedFromThis();
+ adapter->setClient(this);
}
bool QWebEnginePagePrivate::isBeingAdopted()
@@ -1299,25 +1369,19 @@ void QWebEnginePage::triggerAction(WebAction action, bool)
setUrl(d->view->lastContextMenuRequest()->filteredLinkUrl());
break;
case OpenLinkInNewWindow:
- if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid()) {
- QWebEnginePage *newPage = createWindow(WebBrowserWindow);
- if (newPage)
- newPage->setUrl(d->view->lastContextMenuRequest()->filteredLinkUrl());
- }
+ if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid())
+ d->createNewWindow(WebContentsAdapterClient::NewWindowDisposition, true,
+ d->view->lastContextMenuRequest()->filteredLinkUrl());
break;
case OpenLinkInNewTab:
- if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid()) {
- QWebEnginePage *newPage = createWindow(WebBrowserTab);
- if (newPage)
- newPage->setUrl(d->view->lastContextMenuRequest()->filteredLinkUrl());
- }
+ if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid())
+ d->createNewWindow(WebContentsAdapterClient::NewForegroundTabDisposition, true,
+ d->view->lastContextMenuRequest()->filteredLinkUrl());
break;
case OpenLinkInNewBackgroundTab:
- if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid()) {
- QWebEnginePage *newPage = createWindow(WebBrowserBackgroundTab);
- if (newPage)
- newPage->setUrl(d->view->lastContextMenuRequest()->filteredLinkUrl());
- }
+ if (d->view && d->view->lastContextMenuRequest()->filteredLinkUrl().isValid())
+ d->createNewWindow(WebContentsAdapterClient::NewBackgroundTabDisposition, true,
+ d->view->lastContextMenuRequest()->filteredLinkUrl());
break;
case CopyLinkToClipboard:
if (d->view && !d->view->lastContextMenuRequest()->linkUrl().isEmpty()) {
@@ -2313,6 +2377,53 @@ void QWebEnginePage::print(QPrinter *printer, const QWebEngineCallback<bool> &re
/*!
+ \fn void QWebEnginePage::newWindowRequested(WebEngineNewViewRequest &request)
+ \since 6.2
+
+ This signal is emitted when \a request is issued to load a page in a separate
+ web engine window. This can either be because the current page requested it explicitly
+ through a JavaScript call to \c window.open, or because the user clicked on a link
+ while holding Shift, Ctrl, or a built-in combination that triggers the page to open
+ in a new window.
+
+ The signal is handled by calling acceptAsNewWindow() on the destination page.
+ If this signal is not handled, the requested load will fail.
+
+ \note This signal is not emitted if \l createWindow() handled the request first.
+
+ \sa createWindow()
+*/
+
+/*!
+ Handles the newWindowRequested() signal by opening the \a request in this page.
+ \since 6.2
+ \sa newWindowRequested
+*/
+void QWebEnginePage::acceptAsNewWindow(QWebEngineNewWindowRequest &request)
+{
+ Q_D(QWebEnginePage);
+ auto adapter = request.adapter();
+ QUrl url = request.requestedUrl();
+ if ((!adapter && !url.isValid()) || request.isHandled()) {
+ qWarning("Trying to open an empty request, it was either already used or was invalidated."
+ "\nYou must complete the request synchronously within the newWindowRequested signal handler."
+ " If a view hasn't been adopted before returning, the request will be invalidated.");
+ return;
+ }
+
+ if (adapter)
+ d->adoptWebContents(adapter.data());
+ else
+ setUrl(url);
+
+ QRect geometry = request.requestedGeometry();
+ if (!geometry.isEmpty())
+ emit geometryChangeRequested(geometry);
+
+ request.setHandled();
+}
+
+/*!
\enum QWebEnginePage::LifecycleState
\since 5.14
diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h
index d1838e51c..c0c970207 100644
--- a/src/core/api/qwebenginepage.h
+++ b/src/core/api/qwebenginepage.h
@@ -64,6 +64,7 @@ class QWebEngineClientCertificateSelection;
class QWebEngineFindTextResult;
class QWebEngineFullScreenRequest;
class QWebEngineHistory;
+class QWebEngineNewWindowRequest;
class QWebEnginePage;
class QWebEnginePagePrivate;
class QWebEngineProfile;
@@ -320,6 +321,8 @@ public:
bool isVisible() const;
void setVisible(bool visible);
+ void acceptAsNewWindow(QWebEngineNewWindowRequest &request);
+
static QWebEnginePage* fromDownloadRequest(QWebEngineDownloadRequest * request);
Q_SIGNALS:
@@ -343,6 +346,7 @@ Q_SIGNALS:
void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode);
void certificateError(const QWebEngineCertificateError &certificateError);
+ void newWindowRequested(QWebEngineNewWindowRequest &request);
// Ex-QWebFrame signals
void titleChanged(const QString &title);
diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h
index 081287889..d2c246397 100644
--- a/src/core/api/qwebenginepage_p.h
+++ b/src/core/api/qwebenginepage_p.h
@@ -193,6 +193,8 @@ public:
void updateAction(QWebEnginePage::WebAction) const;
void _q_webActionTriggered(bool checked);
+ void createNewWindow(WindowOpenDisposition disposition, bool userGesture, const QUrl &targetUrl);
+ void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents);
QtWebEngineCore::WebContentsAdapter *webContents() { return adapter.data(); }
void recreateFromSerializedHistory(QDataStream &input);
diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt
index c00eb18fb..3dfa36dc0 100644
--- a/src/webenginequick/CMakeLists.txt
+++ b/src/webenginequick/CMakeLists.txt
@@ -15,7 +15,6 @@ qt_internal_add_module(WebEngineQuick
api/qquickwebenginefaviconprovider_p_p.h
api/qquickwebenginehistory.cpp api/qquickwebenginehistory_p.h
api/qquickwebenginenavigationrequest.cpp api/qquickwebenginenavigationrequest_p.h
- api/qquickwebenginenewviewrequest.cpp api/qquickwebenginenewviewrequest_p.h
api/qquickwebengineprofile.cpp api/qquickwebengineprofile.h api/qquickwebengineprofile_p.h
api/qquickwebenginescriptcollection.cpp api/qquickwebenginescriptcollection.h
api/qquickwebenginesettings.cpp api/qquickwebenginesettings_p.h
diff --git a/src/webenginequick/api/qquickwebenginenewviewrequest.cpp b/src/webenginequick/api/qquickwebenginenewviewrequest.cpp
deleted file mode 100644
index 78ae1622a..000000000
--- a/src/webenginequick/api/qquickwebenginenewviewrequest.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWebEngine module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickwebenginenewviewrequest_p.h"
-
-#include "qquickwebengineview_p_p.h"
-#include "web_contents_adapter.h"
-
-/*!
- \qmltype WebEngineNewViewRequest
- \instantiates QQuickWebEngineNewViewRequest
- \inqmlmodule QtWebEngine
- \since QtWebEngine 1.1
-
- \brief A utility type for the WebEngineView::newViewRequested signal.
-
- Contains information about a request to load a page in a separate web engine view.
-
- \sa WebEngineView::newViewRequested
-*/
-QQuickWebEngineNewViewRequest::QQuickWebEngineNewViewRequest()
-{
-}
-
-QQuickWebEngineNewViewRequest::~QQuickWebEngineNewViewRequest()
-{
-}
-
-/*!
- \qmlproperty WebEngineView::NewViewDestination WebEngineNewViewRequest::destination
- The type of the view that is requested by the page.
- */
-QQuickWebEngineView::NewViewDestination QQuickWebEngineNewViewRequest::destination() const
-{
- return m_destination;
-}
-
-/*!
- \qmlproperty QUrl WebEngineNewViewRequest::requestedUrl
- The URL that is requested by the page.
- \since QtWebEngine 1.5
- */
-QUrl QQuickWebEngineNewViewRequest::requestedUrl() const
-{
- return m_requestedUrl;
-}
-
-/*!
- \qmlproperty bool WebEngineNewViewRequest::userInitiated
- Whether this window request was directly triggered as the result of a keyboard or mouse event.
-
- Use this property to block possibly unwanted \e popups.
- */
-bool QQuickWebEngineNewViewRequest::isUserInitiated() const
-{
- return m_isUserInitiated;
-}
-
-/*!
- \qmlmethod WebEngineNewViewRequest::openIn(WebEngineView view)
-
- Opens the requested page in the new web engine view \a view. State and history of the
- view and the page possibly loaded in it will be lost.
-
- \sa WebEngineView::newViewRequested
- */
-void QQuickWebEngineNewViewRequest::openIn(QQuickWebEngineView *view)
-{
- if (!m_adapter && !m_requestedUrl.isValid()) {
- qWarning("Trying to open an empty request, it was either already used or was invalidated."
- "\nYou must complete the request synchronously within the newViewRequested signal handler."
- " If a view hasn't been adopted before returning, the request will be invalidated.");
- return;
- }
-
- if (!view) {
- qWarning("Trying to open a WebEngineNewViewRequest in an invalid WebEngineView.");
- return;
- }
- if (m_adapter)
- view->d_func()->adoptWebContents(m_adapter.data());
- else
- view->setUrl(m_requestedUrl);
- m_isRequestHandled = true;
- m_adapter.reset();
-}
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index 5847cb46f..4eaa5e28b 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -53,7 +53,6 @@
#include "qquickwebenginedialogrequests_p.h"
#include "qquickwebenginefaviconprovider_p_p.h"
#include "qquickwebenginenavigationrequest_p.h"
-#include "qquickwebenginenewviewrequest_p.h"
#include "qquickwebengineprofile_p.h"
#include "qquickwebenginesettings_p.h"
#include "qquickwebenginetouchhandleprovider_p_p.h"
@@ -61,6 +60,7 @@
#include "qwebenginefindtextresult.h"
#include "qwebenginefullscreenrequest.h"
#include "qwebengineloadrequest.h"
+#include "qwebenginenewwindowrequest.h"
#include "qwebenginequotarequest.h"
#include "qwebenginescriptcollection.h"
#include <QtWebEngineCore/private/qwebenginescriptcollection_p.h>
@@ -568,41 +568,37 @@ void QQuickWebEngineViewPrivate::unhandledKeyEvent(QKeyEvent *event)
QCoreApplication::sendEvent(q->parentItem(), event);
}
-QSharedPointer<WebContentsAdapter>
-QQuickWebEngineViewPrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents,
- WindowOpenDisposition disposition, bool userGesture,
- const QRect &, const QUrl &targetUrl)
+static QWebEngineNewWindowRequest::DestinationType toDestinationType(WebContentsAdapterClient::WindowOpenDisposition disposition)
{
- Q_Q(QQuickWebEngineView);
- Q_ASSERT(newWebContents);
- QQuickWebEngineNewViewRequest request;
- request.m_adapter = newWebContents;
- request.m_isUserInitiated = userGesture;
- request.m_requestedUrl = targetUrl;
-
switch (disposition) {
case WebContentsAdapterClient::NewForegroundTabDisposition:
- request.m_destination = QQuickWebEngineView::NewViewInTab;
- break;
+ return QWebEngineNewWindowRequest::InNewTab;
case WebContentsAdapterClient::NewBackgroundTabDisposition:
- request.m_destination = QQuickWebEngineView::NewViewInBackgroundTab;
- break;
+ return QWebEngineNewWindowRequest::InNewBackgroundTab;
case WebContentsAdapterClient::NewPopupDisposition:
- request.m_destination = QQuickWebEngineView::NewViewInDialog;
- break;
+ return QWebEngineNewWindowRequest::InNewDialog;
case WebContentsAdapterClient::NewWindowDisposition:
- request.m_destination = QQuickWebEngineView::NewViewInWindow;
- break;
+ return QWebEngineNewWindowRequest::InNewWindow;
default:
Q_UNREACHABLE();
}
+}
- Q_EMIT q->newViewRequested(&request);
+QSharedPointer<WebContentsAdapter>
+QQuickWebEngineViewPrivate::adoptNewWindow(QSharedPointer<WebContentsAdapter> newWebContents,
+ WindowOpenDisposition disposition, bool userGesture,
+ const QRect &geometry, const QUrl &targetUrl)
+{
+ Q_Q(QQuickWebEngineView);
+ Q_ASSERT(newWebContents);
+ QWebEngineNewWindowRequest request(toDestinationType(disposition), geometry,
+ targetUrl, userGesture, newWebContents);
- if (!request.m_isRequestHandled)
- return nullptr;
+ Q_EMIT q->newViewRequested(&request);
- return newWebContents;
+ if (request.isHandled())
+ return newWebContents;
+ return nullptr;
}
bool QQuickWebEngineViewPrivate::isBeingAdopted()
@@ -1723,6 +1719,24 @@ void QQuickWebEngineView::itemChange(ItemChange change, const ItemChangeData &va
QQuickItem::itemChange(change, value);
}
+void QQuickWebEngineView::acceptAsNewView(QWebEngineNewWindowRequest *request)
+{
+ Q_D(QQuickWebEngineView);
+ if (!request || (!request->adapter() && !request->requestedUrl().isValid()) || request->isHandled()) {
+ qWarning("Trying to open an empty request, it was either already used or was invalidated."
+ "\nYou must complete the request synchronously within the newViewRequested signal handler."
+ " If a view hasn't been adopted before returning, the request will be invalidated.");
+ return;
+ }
+
+ if (auto adapter = request->adapter())
+ d->adoptWebContents(adapter.data());
+ else
+ setUrl(request->requestedUrl());
+
+ request->setHandled();
+}
+
#if QT_CONFIG(draganddrop)
static QPointF mapToScreen(const QQuickItem *item, const QPointF &clientPos)
{
@@ -1812,19 +1826,15 @@ void QQuickWebEngineView::triggerWebAction(WebAction action)
break;
case OpenLinkInNewWindow:
if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) {
- QQuickWebEngineNewViewRequest request;
- request.m_requestedUrl = d->m_contextMenuRequest->filteredLinkUrl();
- request.m_isUserInitiated = true;
- request.m_destination = NewViewInWindow;
+ QWebEngineNewWindowRequest request(QWebEngineNewWindowRequest::InNewWindow, QRect(),
+ d->m_contextMenuRequest->filteredLinkUrl(), true, nullptr);
Q_EMIT newViewRequested(&request);
}
break;
case OpenLinkInNewTab:
if (d->m_contextMenuRequest->filteredLinkUrl().isValid()) {
- QQuickWebEngineNewViewRequest request;
- request.m_requestedUrl = d->m_contextMenuRequest->filteredLinkUrl();
- request.m_isUserInitiated = true;
- request.m_destination = NewViewInBackgroundTab;
+ QWebEngineNewWindowRequest request(QWebEngineNewWindowRequest::InNewBackgroundTab, QRect(),
+ d->m_contextMenuRequest->filteredLinkUrl(), true, nullptr);
Q_EMIT newViewRequested(&request);
}
break;
diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h
index aba641de8..3d83035bd 100644
--- a/src/webenginequick/api/qquickwebengineview_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p.h
@@ -76,17 +76,17 @@ class QQuickWebEngineHistory;
class QQuickWebEngineJavaScriptDialogRequest;
class QWebEngineLoadRequest;
class QQuickWebEngineNavigationRequest;
-class QQuickWebEngineNewViewRequest;
class QQuickWebEngineSettings;
class QQuickWebEngineTooltipRequest;
class QQuickWebEngineFormValidationMessageRequest;
class QQuickWebEngineViewPrivate;
class QWebEngineCertificateError;
+class QWebEngineContextMenuRequest;
class QWebEngineFindTextResult;
class QWebEngineFullScreenRequest;
+class QWebEngineNewWindowRequest;
class QWebEngineQuotaRequest;
class QWebEngineRegisterProtocolHandlerRequest;
-class QWebEngineContextMenuRequest;
class QQuickWebEngineScriptCollection;
#if QT_CONFIG(webenginequick_testsupport)
@@ -191,14 +191,6 @@ public:
};
Q_ENUM(ErrorDomain)
- enum NewViewDestination {
- NewViewInWindow,
- NewViewInTab,
- NewViewInDialog,
- NewViewInBackgroundTab
- };
- Q_ENUM(NewViewDestination)
-
enum Feature {
MediaAudioCapture,
MediaVideoCapture,
@@ -478,6 +470,8 @@ public:
void setWebChannelWorld(uint);
Q_REVISION(1,8) Q_INVOKABLE QQuickWebEngineAction *action(WebAction action);
+ Q_INVOKABLE void acceptAsNewView(QWebEngineNewWindowRequest *request);
+
bool isAudioMuted() const;
void setAudioMuted(bool muted);
bool recentlyAudible() const;
@@ -536,7 +530,7 @@ Q_SIGNALS:
Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request);
Q_REVISION(1,1) void isFullScreenChanged();
Q_REVISION(1,1) void featurePermissionRequested(const QUrl &securityOrigin, Feature feature);
- Q_REVISION(1,1) void newViewRequested(QQuickWebEngineNewViewRequest *request);
+ Q_REVISION(1,1) void newViewRequested(QWebEngineNewWindowRequest *request);
Q_REVISION(1,1) void zoomFactorChanged(qreal arg);
Q_REVISION(1,1) void profileChanged();
Q_REVISION(1,1) void webChannelChanged();
@@ -591,7 +585,6 @@ private:
friend class QtWebEngineCore::RenderWidgetHostViewQtDelegateQuick;
friend class QQuickContextMenuBuilder;
- friend class QQuickWebEngineNewViewRequest;
friend class QQuickWebEngineFaviconProvider;
#ifndef QT_NO_ACCESSIBILITY
friend class QQuickWebEngineViewAccessible;
diff --git a/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml b/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml
index e7e6790f2..0835c5246 100644
--- a/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml
+++ b/src/webenginequick/doc/snippets/qtwebengine_webengineview_newviewrequested.qml
@@ -50,7 +50,7 @@
import QtQuick 2.0
import QtQuick.Window 2.1
-import QtWebEngine 1.1
+import QtWebEngine 2.0
//! [0]
QtObject {
@@ -76,7 +76,7 @@ QtObject {
// use its WebEngineView as the destination of our request.
onNewViewRequested: function(request) {
var newWindow = windowComponent.createObject(windowParent);
- request.openIn(newWindow.webView);
+ newWindow.webView.acceptAsNewView(request);
}
}
}
diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
index 2be475903..04bf71550 100644
--- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc
+++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
@@ -583,13 +583,23 @@
while holding Shift, Ctrl, or a built-in combination that triggers the page to open
in a new window.
+ The signal is handled by calling acceptAsNewView() on the destination view.
If this signal is not handled, the requested load will fail.
An example implementation:
\snippet snippets/qtwebengine_webengineview_newviewrequested.qml 0
- \sa NewViewDestination, {WebEngine Quick Nano Browser}
+ \sa WebEngineNewViewRequest, {WebEngine Quick Nano Browser}
+*/
+
+/*!
+ \qmlmethod void WebEngineView::acceptAsNewView(QWebEngineNewWindowRequest *request)
+ \since QtWebEngine 2.0
+
+ Handle the newViewRequested signal by opening the \a request in this view.
+
+ \sa newViewRequested
*/
/*!
@@ -689,23 +699,6 @@
*/
/*!
- \qmlproperty enumeration WebEngineView::NewViewDestination
-
- Describes how to open a new view:
-
- \value WebEngineView.NewViewInWindow
- In a separate Window.
- \value WebEngineView.NewViewInTab
- In a tab of the same window.
- \value WebEngineView.NewViewInDialog
- In a Window without a tab bar, toolbar, or URL bar.
- \value WebEngineView.NewViewInBackgroundTab
- In a tab of the same window, without hiding the currently visible web engine view.
-
- \sa {WebEngineNewViewRequest::destination}{WebEngineNewViewRequest.destination}
-*/
-
-/*!
\qmlproperty enumeration WebEngineView::FindFlags
Describes the options available to the findText() function. The options
diff --git a/src/webenginequick/plugin/plugin.cpp b/src/webenginequick/plugin/plugin.cpp
index ead71694b..1e54dbd2f 100644
--- a/src/webenginequick/plugin/plugin.cpp
+++ b/src/webenginequick/plugin/plugin.cpp
@@ -45,7 +45,6 @@
#include <QtWebEngineQuick/private/qquickwebenginehistory_p.h>
#include <QtWebEngineQuick/private/qquickwebenginefaviconprovider_p_p.h>
#include <QtWebEngineQuick/private/qquickwebenginenavigationrequest_p.h>
-#include <QtWebEngineQuick/private/qquickwebenginenewviewrequest_p.h>
#include <QtWebEngineQuick/private/qquickwebenginesettings_p.h>
#include <QtWebEngineQuick/private/qquickwebenginesingleton_p.h>
#include <QtWebEngineQuick/private/qquickwebenginetouchhandleprovider_p_p.h>
@@ -55,6 +54,7 @@
#include <QtWebEngineCore/qwebenginefindtextresult.h>
#include <QtWebEngineCore/qwebenginefullscreenrequest.h>
#include <QtWebEngineCore/qwebengineloadrequest.h>
+#include <QtWebEngineCore/qwebenginenewwindowrequest.h>
#include <QtWebEngineCore/qwebenginenotification.h>
#include <QtWebEngineCore/qwebenginequotarequest.h>
#include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h>
@@ -113,8 +113,7 @@ public:
qmlRegisterUncreatableType<QWebEngineCertificateError>(uri, 1, 1, "WebEngineCertificateError", msgUncreatableType("WebEngineCertificateError"));
qmlRegisterUncreatableType<QWebEngineDownloadRequest>(uri, 1, 1, "WebEngineDownloadRequest",
msgUncreatableType("WebEngineDownloadRequest"));
- qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest>(uri, 1, 1, "WebEngineNewViewRequest", msgUncreatableType("WebEngineNewViewRequest"));
- qmlRegisterUncreatableType<QQuickWebEngineNewViewRequest, 1>(uri, 1, 5, "WebEngineNewViewRequest", tr("Cannot create separate instance of WebEngineNewViewRequest"));
+ qmlRegisterUncreatableType<QWebEngineNewWindowRequest>(uri, 1, 1, "WebEngineNewViewRequest", msgUncreatableType("WebEngineNewViewRequest"));
qmlRegisterUncreatableType<QQuickWebEngineSettings>(uri, 1, 1, "WebEngineSettings", msgUncreatableType("WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 1>(uri, 1, 2, "WebEngineSettings", msgUncreatableType("WebEngineSettings"));
qmlRegisterUncreatableType<QQuickWebEngineSettings, 2>(uri, 1, 3, "WebEngineSettings", msgUncreatableType("WebEngineSettings"));
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 96f1bd650..9ce954e06 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -705,7 +705,7 @@ void QWebEngineView::reload()
QWebEngineView *QWebEngineView::createWindow(QWebEnginePage::WebWindowType type)
{
Q_UNUSED(type);
- return 0;
+ return nullptr;
}
qreal QWebEngineView::zoomFactor() const
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 56a352979..f711c1960 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -133,11 +133,11 @@
\value OpenLinkInThisWindow Open the current link in the current window. (Added in Qt 5.6)
\value OpenLinkInNewWindow Open the current link in a new window. Requires implementation of
- \l createWindow(). (Added in Qt 5.6)
+ \l createWindow() or \l newWindowRequested() (Added in Qt 5.6)
\value OpenLinkInNewTab Open the current link in a new tab. Requires implementation of
- \l createWindow(). (Added in Qt 5.6)
+ \l createWindow() or \l newWindowRequested(). (Added in Qt 5.6)
\value OpenLinkInNewBackgroundTab Open the current link in a new background tab. Requires
- implementation of \l createWindow(). (Added in Qt 5.7)
+ implementation of \l createWindow() or \l newWindowRequested(). (Added in Qt 5.7)
\value CopyLinkToClipboard Copy the current link to the clipboard. (Added in Qt 5.6)
\value CopyImageToClipboard Copy the clicked image to the clipboard. (Added in Qt 5.6)
@@ -168,7 +168,7 @@
the web page on disk. Requires a slot for \l{QWebEngineProfile::}{downloadRequested()}.
(Added in Qt 5.7)
\value ViewSource Show the source of the current page in a new tab. Requires implementation of
- \l createWindow(). (Added in Qt 5.8)
+ \l createWindow() or \l newWindowRequested(). (Added in Qt 5.8)
\value ToggleBold
Toggles boldness for the selection or at the cursor position.
@@ -445,11 +445,14 @@
If the view associated with the web page is a QWebEngineView object, then the default implementation forwards
the request to QWebEngineView::createWindow(); otherwise it returns a null pointer.
+ If this call is not implemented or does not return a new page, \l newWindowRequested() is emitted to handle
+ the request.
+
\note In the cases when the window creation is being triggered by JavaScript, apart from
reimplementing this method the application must also set
QWebEngineSettings::JavascriptCanOpenWindows to \c true in order for the method to get called.
- \sa QWebEngineView::createWindow()
+ \sa QWebEngineView::createWindow(), newWindowRequested()
*/
/*!
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 87fa901c8..8a40325e0 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -37,6 +37,7 @@
#include <QtWebEngineCore/QWebEngineCertificateError>
#include <QtWebEngineCore/QWebEngineFindTextResult>
#include <QtWebEngineCore/QWebEngineFullScreenRequest>
+#include <QtWebEngineCore/QWebEngineNewWindowRequest>
#include <QtWebEngineCore/QWebEngineNotification>
#include <QtWebEngineCore/QWebEngineQuotaRequest>
#include <QtWebEngineCore/QWebEngineRegisterProtocolHandlerRequest>
@@ -50,7 +51,6 @@
#include <private/qquickwebenginedialogrequests_p.h>
#include <private/qquickwebenginehistory_p.h>
#include <private/qquickwebenginenavigationrequest_p.h>
-#include <private/qquickwebenginenewviewrequest_p.h>
#include <private/qquickwebenginesettings_p.h>
#include <private/qquickwebenginesingleton_p.h>
@@ -70,7 +70,6 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *
<< &QQuickWebEngineHistoryListModel::staticMetaObject
<< &QWebEngineLoadRequest::staticMetaObject
<< &QQuickWebEngineNavigationRequest::staticMetaObject
- << &QQuickWebEngineNewViewRequest::staticMetaObject
<< &QQuickWebEngineProfile::staticMetaObject
<< &QQuickWebEngineSettings::staticMetaObject
<< &QWebEngineFullScreenRequest::staticMetaObject
@@ -86,6 +85,7 @@ static const QList<const QMetaObject *> typesToCheck = QList<const QMetaObject *
<< &QWebEngineCertificateError::staticMetaObject
<< &QWebEngineQuotaRequest::staticMetaObject
<< &QWebEngineRegisterProtocolHandlerRequest::staticMetaObject
+ << &QWebEngineNewWindowRequest::staticMetaObject
<< &QWebEngineNotification::staticMetaObject
<< &QWebEngineFindTextResult::staticMetaObject
;
@@ -332,10 +332,14 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineNavigationRequest.isMainFrame --> bool"
<< "QQuickWebEngineNavigationRequest.navigationType --> QQuickWebEngineView::NavigationType"
<< "QQuickWebEngineNavigationRequest.url --> QUrl"
- << "QQuickWebEngineNewViewRequest.destination --> QQuickWebEngineView::NewViewDestination"
- << "QQuickWebEngineNewViewRequest.openIn(QQuickWebEngineView*) --> void"
- << "QQuickWebEngineNewViewRequest.requestedUrl --> QUrl"
- << "QQuickWebEngineNewViewRequest.userInitiated --> bool"
+ << "QWebEngineNewWindowRequest.destination --> QWebEngineNewWindowRequest::DestinationType"
+ << "QWebEngineNewWindowRequest.requestedUrl --> QUrl"
+ << "QWebEngineNewWindowRequest.requestedGeometry --> QRect"
+ << "QWebEngineNewWindowRequest.userInitiated --> bool"
+ << "QWebEngineNewWindowRequest.InNewBackgroundTab --> DestinationType"
+ << "QWebEngineNewWindowRequest.InNewDialog --> DestinationType"
+ << "QWebEngineNewWindowRequest.InNewTab --> DestinationType"
+ << "QWebEngineNewWindowRequest.InNewWindow --> DestinationType"
<< "QQuickWebEngineProfile.AllowPersistentCookies --> PersistentCookiesPolicy"
<< "QQuickWebEngineProfile.DiskHttpCache --> HttpCacheType"
<< "QQuickWebEngineProfile.ForcePersistentCookies --> PersistentCookiesPolicy"
@@ -622,10 +626,6 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.MediaVideoCapture --> Feature"
<< "QQuickWebEngineView.NPageSize --> PrintedPageSizeId"
<< "QQuickWebEngineView.NPaperSize --> PrintedPageSizeId"
- << "QQuickWebEngineView.NewViewInBackgroundTab --> NewViewDestination"
- << "QQuickWebEngineView.NewViewInDialog --> NewViewDestination"
- << "QQuickWebEngineView.NewViewInTab --> NewViewDestination"
- << "QQuickWebEngineView.NewViewInWindow --> NewViewDestination"
<< "QQuickWebEngineView.NoErrorDomain --> ErrorDomain"
<< "QQuickWebEngineView.Notifications --> Feature"
<< "QQuickWebEngineView.NoWebAction --> WebAction"
@@ -723,7 +723,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.loadingChanged(QWebEngineLoadRequest) --> void"
<< "QQuickWebEngineView.navigationHistory --> QQuickWebEngineHistory*"
<< "QQuickWebEngineView.navigationRequested(QQuickWebEngineNavigationRequest*) --> void"
- << "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void"
+ << "QQuickWebEngineView.newViewRequested(QWebEngineNewWindowRequest*) --> void"
<< "QQuickWebEngineView.pdfPrintingFinished(QString,bool) --> void"
<< "QQuickWebEngineView.printRequested() --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue) --> void"
@@ -776,6 +776,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.windowCloseRequested() --> void"
<< "QQuickWebEngineView.zoomFactor --> double"
<< "QQuickWebEngineView.zoomFactorChanged(double) --> void"
+ << "QQuickWebEngineView.acceptAsNewView(QWebEngineNewWindowRequest*) --> void"
<< "QWebEngineQuotaRequest.accept() --> void"
<< "QWebEngineQuotaRequest.origin --> QUrl"
<< "QWebEngineQuotaRequest.reject() --> void"
diff --git a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
index fd720befe..c79a3aee8 100644
--- a/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
+++ b/tests/auto/quick/qmltests/data/tst_newViewRequest.qml
@@ -52,7 +52,7 @@ TestWebEngineView {
signalName: "newViewRequested"
}
- onNewViewRequested: {
+ onNewViewRequested: function(request) {
newViewRequest = {
"destination": request.destination,
"userInitiated": request.userInitiated,
@@ -69,11 +69,9 @@ TestWebEngineView {
"}", webEngineView);
if (viewType === "dialog")
- request.openIn(dialog.webEngineView);
- else if (viewType === "null")
- request.openIn(0);
+ dialog.webEngineView.acceptAsNewView(request);
else if (viewType === "webEngineView")
- request.openIn(webEngineView);
+ webEngineView.acceptAsNewView(request);
}
TestCase {
@@ -118,7 +116,7 @@ TestWebEngineView {
verify(webEngineView.waitForLoadSucceeded());
tryCompare(newViewRequestedSpy, "count", 1);
- compare(newViewRequest.destination, WebEngineView.NewViewInTab);
+ compare(newViewRequest.destination, WebEngineNewViewRequest.InNewTab);
verify(!newViewRequest.userInitiated);
if (viewType === "dialog") {
@@ -139,7 +137,7 @@ TestWebEngineView {
verify(webEngineView.waitForLoadSucceeded());
tryCompare(newViewRequestedSpy, "count", 1);
- compare(newViewRequest.destination, WebEngineView.NewViewInDialog);
+ compare(newViewRequest.destination, WebEngineNewViewRequest.InNewDialog);
compare(newViewRequest.requestedUrl, url);
verify(!newViewRequest.userInitiated);
if (viewType === "dialog") {
@@ -163,7 +161,7 @@ TestWebEngineView {
tryCompare(newViewRequestedSpy, "count", 1);
compare(newViewRequest.requestedUrl, url);
- compare(newViewRequest.destination, WebEngineView.NewViewInDialog);
+ compare(newViewRequest.destination, WebEngineNewViewRequest.InNewDialog);
verify(newViewRequest.userInitiated);
if (viewType === "dialog") {
verify(dialog.webEngineView.waitForLoadSucceeded());
@@ -180,7 +178,7 @@ TestWebEngineView {
mouseClick(webEngineView, center.x, center.y, Qt.LeftButton, Qt.ControlModifier);
tryCompare(newViewRequestedSpy, "count", 1);
compare(newViewRequest.requestedUrl, Qt.resolvedUrl("test1.html"));
- compare(newViewRequest.destination, WebEngineView.NewViewInBackgroundTab);
+ compare(newViewRequest.destination, WebEngineNewViewRequest.InNewBackgroundTab);
verify(newViewRequest.userInitiated);
if (viewType === "" || viewType === "null") {
compare(loadRequestArray[0].status, WebEngineView.LoadStartedStatus);
diff --git a/tests/auto/quick/qmltests/data/tst_viewSource.qml b/tests/auto/quick/qmltests/data/tst_viewSource.qml
index 22c340c2b..0b5f6a7ab 100644
--- a/tests/auto/quick/qmltests/data/tst_viewSource.qml
+++ b/tests/auto/quick/qmltests/data/tst_viewSource.qml
@@ -55,7 +55,7 @@ TestWebEngineView {
"userInitiated": request.userInitiated
};
- request.openIn(webEngineView);
+ webEngineView.acceptAsNewView(request);
}
TestCase {
@@ -86,7 +86,7 @@ TestWebEngineView {
// The first titleChanged signal is emitted by adoptWebContents()
tryVerify(function() { return titleChangedSpy.count >= 2; });
- compare(viewRequest.destination, WebEngineView.NewViewInTab);
+ compare(viewRequest.destination, WebEngineNewViewRequest.InNewTab);
verify(viewRequest.userInitiated);
verify(!webEngineView.action(WebEngineView.ViewSource).enabled);
@@ -115,7 +115,7 @@ TestWebEngineView {
// The first titleChanged signal is emitted by adoptWebContents()
tryVerify(function() { return titleChangedSpy.count >= 2; });
- compare(viewRequest.destination, WebEngineView.NewViewInTab);
+ compare(viewRequest.destination, WebEngineNewViewRequest.InNewTab);
verify(viewRequest.userInitiated);
tryCompare(webEngineView, "url", "view-source:" + url.replace("user:passwd@", ""));
diff --git a/tests/auto/util/testwindow.h b/tests/auto/util/testwindow.h
index b57443c69..958381ff2 100644
--- a/tests/auto/util/testwindow.h
+++ b/tests/auto/util/testwindow.h
@@ -45,7 +45,7 @@ public:
QScopedPointer<QQuickItem> webEngineView;
protected:
- inline void resizeEvent(QResizeEvent*);
+ inline void resizeEvent(QResizeEvent *) override;
};
inline TestWindow::TestWindow(QQuickItem *webEngineView)
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index c376cbbb3..460e4369b 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -51,6 +51,7 @@
#include <qwebenginefindtextresult.h>
#include <qwebenginefullscreenrequest.h>
#include <qwebenginehistory.h>
+#include <qwebenginenewwindowrequest.h>
#include <qwebenginenotification.h>
#include <qwebenginepage.h>
#include <qwebengineprofile.h>
@@ -308,7 +309,7 @@ public:
bool m_acceptNavigationRequest;
protected:
- virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame)
+ bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override
{
Q_UNUSED(url);
Q_UNUSED(isMainFrame);
@@ -527,7 +528,8 @@ class TestPage : public QWebEnginePage {
public:
TestPage(QObject *parent = nullptr) : QWebEnginePage(parent)
{
- connect(this, SIGNAL(geometryChangeRequested(QRect)), this, SLOT(slotGeometryChangeRequested(QRect)));
+ connect(this, &QWebEnginePage::geometryChangeRequested, this, &TestPage::slotGeometryChangeRequested);
+ connect(this, &QWebEnginePage::newWindowRequested, this, &TestPage::slotNewWindowRequested);
}
struct Navigation {
@@ -537,7 +539,7 @@ public:
};
QList<Navigation> navigations;
- virtual bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame)
+ bool acceptNavigationRequest(const QUrl &url, NavigationType type, bool isMainFrame) override
{
Navigation n;
n.url = url;
@@ -548,12 +550,6 @@ public:
}
QList<TestPage*> createdWindows;
- virtual QWebEnginePage* createWindow(WebWindowType) {
- TestPage* page = new TestPage(this);
- createdWindows.append(page);
- emit windowCreated();
- return page;
- }
QRect requestedGeometry;
@@ -561,7 +557,16 @@ signals:
void windowCreated();
private Q_SLOTS:
- void slotGeometryChangeRequested(const QRect& geom) {
+ void slotNewWindowRequested(QWebEngineNewWindowRequest &request)
+ {
+ TestPage *page = new TestPage(this);
+ createdWindows.append(page);
+ emit windowCreated();
+ page->acceptAsNewWindow(request);
+ }
+
+ void slotGeometryChangeRequested(const QRect &geom)
+ {
requestedGeometry = geom;
}
};
@@ -3418,15 +3423,13 @@ void tst_QWebEnginePage::devTools()
void tst_QWebEnginePage::openLinkInDifferentProfile()
{
- class Page : public QWebEnginePage {
- public:
- QWebEnginePage *targetPage = nullptr;
- Page(QWebEngineProfile *profile) : QWebEnginePage(profile) {}
- private:
- QWebEnginePage *createWindow(WebWindowType) override { return targetPage; }
- };
+ QWebEnginePage *targetPage = nullptr;
QWebEngineProfile profile1, profile2;
- Page page1(&profile1), page2(&profile2);
+ QWebEnginePage page1(&profile1), page2(&profile2);
+ connect(&page1, &QWebEnginePage::newWindowRequested, [&](QWebEngineNewWindowRequest &request) {
+ if (targetPage)
+ targetPage->acceptAsNewWindow(request);
+ });
QWebEngineView view;
view.resize(500, 500);
view.setPage(&page1);
@@ -3438,7 +3441,7 @@ void tst_QWebEnginePage::openLinkInDifferentProfile()
"</body></html>");
QTRY_COMPARE(spy1.count(), 1);
QVERIFY(spy1.takeFirst().value(0).toBool());
- page1.targetPage = &page2;
+ targetPage = &page2;
QTest::mouseClick(view.focusProxy(), Qt::MiddleButton, {}, elementCenter(&page1, "link"));
QTRY_COMPARE(spy2.count(), 1);
QVERIFY(spy2.takeFirst().value(0).toBool());
@@ -3500,11 +3503,7 @@ void tst_QWebEnginePage::openLinkInNewPage_data()
// the disposition and performing the navigation request normally.
QTest::newRow("BlockPopup") << Decision::ReturnNull << Cause::TargetBlank << Effect::Blocked;
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QTest::newRow("IgnoreIntent") << Decision::ReturnNull << Cause::MiddleClick << Effect::Blocked;
-#else
- QTest::newRow("IgnoreIntent") << Decision::ReturnNull << Cause::MiddleClick << Effect::LoadInSelf;
-#endif
QTest::newRow("OverridePopup") << Decision::ReturnSelf << Cause::TargetBlank << Effect::LoadInSelf;
QTest::newRow("OverrideIntent") << Decision::ReturnSelf << Cause::MiddleClick << Effect::LoadInSelf;
QTest::newRow("AcceptPopup") << Decision::ReturnOther << Cause::TargetBlank << Effect::LoadInOther;