diff options
Diffstat (limited to 'src/webenginewidgets')
18 files changed, 746 insertions, 165 deletions
diff --git a/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp new file mode 100644 index 000000000..667605c37 --- /dev/null +++ b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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 "qwebenginenotificationpresenter_p.h" + +#include <QApplication> +#include <QSystemTrayIcon> + +QT_BEGIN_NAMESPACE + +DefaultNotificationPresenter::DefaultNotificationPresenter(QObject *parent) : QObject(parent) +{ +#ifndef QT_NO_SYSTEMTRAYICON + m_systemTrayIcon = new QSystemTrayIcon(this); + connect(m_systemTrayIcon, &QSystemTrayIcon::messageClicked, this, &DefaultNotificationPresenter::messageClicked); +#endif +} + +DefaultNotificationPresenter::~DefaultNotificationPresenter() +{ +} + +void DefaultNotificationPresenter::show(std::unique_ptr<QWebEngineNotification> notification) +{ + Q_ASSERT(notification); + if (m_activeNotification) { + m_activeNotification->close(); + m_activeNotification->disconnect(this); + } + + m_activeNotification = std::move(notification); + +#ifndef QT_NO_SYSTEMTRAYICON + if (m_activeNotification && m_systemTrayIcon) { + m_systemTrayIcon->setIcon(qApp->windowIcon()); + m_systemTrayIcon->show(); + QImage notificationIconImage = m_activeNotification->icon(); + m_notificationIcon = QIcon(QPixmap::fromImage(std::move(notificationIconImage), Qt::NoFormatConversion)); + if (!m_notificationIcon.isNull()) + m_systemTrayIcon->showMessage(m_activeNotification->title(), m_activeNotification->message(), m_notificationIcon); + else + m_systemTrayIcon->showMessage(m_activeNotification->title(), m_activeNotification->message()); + m_activeNotification->show(); + connect(m_activeNotification.get(), &QWebEngineNotification::closed, this, &DefaultNotificationPresenter::closeNotification); + } +#endif +} + +void DefaultNotificationPresenter::messageClicked() +{ + if (m_activeNotification) + m_activeNotification->click(); +} + +void DefaultNotificationPresenter::closeNotification() +{ +#ifndef QT_NO_SYSTEMTRAYICON + const QWebEngineNotification *canceled = static_cast<const QWebEngineNotification *>(QObject::sender()); + if (m_systemTrayIcon && canceled->matches(m_activeNotification.get())) + m_systemTrayIcon->hide(); +#endif +} + +void defaultNotificationPresenter(std::unique_ptr<QWebEngineNotification> notification) +{ + static DefaultNotificationPresenter *presenter = nullptr; + if (!presenter) + presenter = new DefaultNotificationPresenter(); + presenter->show(std::move(notification)); +} + + +QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h b/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h new file mode 100644 index 000000000..49d774806 --- /dev/null +++ b/src/webenginewidgets/api/qwebenginenotificationpresenter_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 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$ +** +****************************************************************************/ + +#ifndef QWEBENGINENOTIFICATIONPRESENTER_P_H +#define QWEBENGINENOTIFICATIONPRESENTER_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 <QtWebEngineCore/QWebEngineNotification> + +#include <QtCore/QObject> +#include <QtGui/QIcon> + +#include <memory> + +QT_BEGIN_NAMESPACE + +class QSystemTrayIcon; + +class DefaultNotificationPresenter : public QObject { + Q_OBJECT +public: + DefaultNotificationPresenter(QObject *parent = nullptr); + virtual ~DefaultNotificationPresenter(); + + void show(std::unique_ptr<QWebEngineNotification> notification); + +private Q_SLOTS: + void messageClicked(); + void closeNotification(); + +private: + QSystemTrayIcon *m_systemTrayIcon; + QIcon m_notificationIcon; + std::unique_ptr<QWebEngineNotification> m_activeNotification; +}; + +void defaultNotificationPresenter(std::unique_ptr<QWebEngineNotification> notification); + +QT_END_NAMESPACE + +#endif // QWEBENGINENOTIFICATIONPRESENTER_P_H diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 35fe542e8..f252137ae 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -48,12 +48,13 @@ #include "file_picker_controller.h" #include "javascript_dialog_controller.h" #if QT_CONFIG(webengine_printing_and_pdf) -#include "printing/pdfium_document_wrapper_qt.h" +#include "printer_worker.h" #endif #include "qwebenginecertificateerror.h" #include "qwebenginefullscreenrequest.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" +#include "qwebenginenotification.h" #include "qwebengineprofile.h" #include "qwebengineprofile_p.h" #include "qwebenginequotarequest.h" @@ -62,6 +63,7 @@ #include "qwebenginesettings.h" #include "qwebengineview.h" #include "qwebengineview_p.h" +#include "user_notification_controller.h" #include "render_widget_host_view_qt_delegate_widget.h" #include "web_contents_adapter.h" #include "web_engine_settings.h" @@ -94,6 +96,7 @@ #include <QMimeData> #if QT_CONFIG(webengine_printing_and_pdf) #include <QPrinter> +#include <QThread> #endif #include <QStandardPaths> #include <QStyle> @@ -106,89 +109,6 @@ using namespace QtWebEngineCore; static const int MaxTooltipLength = 1024; -#if QT_CONFIG(webengine_printing_and_pdf) -static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer) -{ - if (!data.size()) { - qWarning("Failure to print on printer %ls: Print result data is empty.", - qUtf16Printable(printer.printerName())); - return false; - } - - QSize pageSize = printer.pageRect().size(); - PdfiumDocumentWrapperQt pdfiumWrapper(data.constData(), data.size(), pageSize); - - int toPage = printer.toPage(); - int fromPage = printer.fromPage(); - bool ascendingOrder = true; - - if (fromPage == 0 && toPage == 0) { - fromPage = 1; - toPage = pdfiumWrapper.pageCount(); - } - fromPage = qMax(1, fromPage); - toPage = qMin(pdfiumWrapper.pageCount(), toPage); - - if (printer.pageOrder() == QPrinter::LastPageFirst) { - qSwap(fromPage, toPage); - ascendingOrder = false; - } - - int pageCopies = 1; - int documentCopies = 1; - - if (!printer.supportsMultipleCopies()) - documentCopies = printer.copyCount(); - - if (printer.collateCopies()) { - pageCopies = documentCopies; - documentCopies = 1; - } - - QPainter painter; - if (!painter.begin(&printer)) { - qWarning("Failure to print on printer %ls: Could not open printer for painting.", - qUtf16Printable(printer.printerName())); - return false; - } - - for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { - int currentPageIndex = fromPage; - while (true) { - for (int printedPages = 0; printedPages < pageCopies; printedPages++) { - if (printer.printerState() == QPrinter::Aborted - || printer.printerState() == QPrinter::Error) - return false; - - QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1); - if (currentImage.isNull()) - return false; - - // Painting operations are automatically clipped to the bounds of the drawable part of the page. - painter.drawImage(QRect(0, 0, pageSize.width(), pageSize.height()), currentImage, currentImage.rect()); - if (printedPages < pageCopies - 1) - printer.newPage(); - } - - if (currentPageIndex == toPage) - break; - - if (ascendingOrder) - currentPageIndex++; - else - currentPageIndex--; - - printer.newPage(); - } - if (printedDocuments < documentCopies - 1) - printer.newPage(); - } - painter.end(); - - return true; -} -#endif // QT_CONFIG(webengine_printing_and_pdf) - static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { switch (disposition) { @@ -241,6 +161,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) , webChannelWorldId(QWebEngineScript::MainWorld) , defaultAudioMuted(false) , defaultZoomFactor(1.0) + , requestInterceptor(nullptr) #if QT_CONFIG(webengine_printing_and_pdf) , currentPrinter(nullptr) #endif @@ -262,6 +183,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) QWebEnginePagePrivate::~QWebEnginePagePrivate() { + if (requestInterceptor) + profile->d_ptr->profileAdapter()->removePageRequestInterceptor(); delete history; delete settings; profile->d_ptr->removeWebContentsAdapterClient(this); @@ -335,7 +258,7 @@ void QWebEnginePagePrivate::didUpdateTargetURL(const QUrl &hoveredUrl) void QWebEnginePagePrivate::selectionChanged() { Q_Q(QWebEnginePage); - Q_EMIT q->selectionChanged(); + QTimer::singleShot(0, q, &QWebEnginePage::selectionChanged); } void QWebEnginePagePrivate::recentlyAudibleChanged(bool recentlyAudible) @@ -349,11 +272,6 @@ QRectF QWebEnginePagePrivate::viewportRect() const return view ? view->rect() : QRectF(); } -qreal QWebEnginePagePrivate::dpiScale() const -{ - return 1.0; -} - QColor QWebEnginePagePrivate::backgroundColor() const { return m_backgroundColor; @@ -502,19 +420,35 @@ void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) m_callbacks.invoke(requestId, matchCount > 0); } -void QWebEnginePagePrivate::didPrintPage(quint64 requestId, const QByteArray &result) +void QWebEnginePagePrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) { #if QT_CONFIG(webengine_printing_and_pdf) + Q_Q(QWebEnginePage); + // If no currentPrinter is set that means that were printing to PDF only. if (!currentPrinter) { - m_callbacks.invoke(requestId, result); + if (!result.data()) + return; + m_callbacks.invoke(requestId, *(result.data())); return; } - bool printerResult = printPdfDataOnPrinter(result, *currentPrinter); + QThread *printerThread = new QThread; + QObject::connect(printerThread, &QThread::finished, printerThread, &QThread::deleteLater); + printerThread->start(); + + PrinterWorker *printerWorker = new PrinterWorker(result, currentPrinter); + QObject::connect(printerWorker, &PrinterWorker::resultReady, q, [requestId, this](bool success) { + currentPrinter = nullptr; + m_callbacks.invoke(requestId, success); + }); + + QObject::connect(printerWorker, &PrinterWorker::resultReady, printerThread, &QThread::quit); + QObject::connect(printerThread, &QThread::finished, printerWorker, &PrinterWorker::deleteLater); + + printerWorker->moveToThread(printerThread); + QMetaObject::invokeMethod(printerWorker, "print"); - currentPrinter = nullptr; - m_callbacks.invoke(requestId, printerResult); #else // we should never enter this branch, but just for safe-keeping... Q_UNUSED(result); @@ -551,7 +485,7 @@ void QWebEnginePagePrivate::authenticationRequired(QSharedPointer<Authentication void QWebEnginePagePrivate::releaseProfile() { - qDebug("Release of profile requested but WebEnginePage still not deleted. Expect troubles !"); + qWarning("Release of profile requested but WebEnginePage still not deleted. Expect troubles !"); // this is not the way to go, but might avoid the crash if user code does not make any calls to page. delete q_ptr->d_ptr.take(); } @@ -617,6 +551,12 @@ void QWebEnginePagePrivate::runRegisterProtocolHandlerRequest(QWebEngineRegister Q_EMIT q->registerProtocolHandlerRequested(request); } +void QWebEnginePagePrivate::runUserNotificationPermissionRequest(const QUrl &securityOrigin) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->featurePermissionRequested(securityOrigin, QWebEnginePage::Notifications); +} + QObject *QWebEnginePagePrivate::accessibilityParentObject() { return view; @@ -1902,6 +1842,40 @@ void QWebEnginePagePrivate::printRequested() }); } +/*! + \since 5.13 + + Registers the request interceptor \a interceptor to intercept URL requests. + + The page does not take ownership of the pointer. This interceptor is called + after any interceptors on the profile, and unlike profile interceptors, is run + on the UI thread, making it thread-safer. Only URL requests from this page are + intercepted. + + To unset the request interceptor, set a \c nullptr. + + \sa QWebEngineUrlRequestInfo, QWebEngineProfile::setRequestInterceptor() +*/ + +void QWebEnginePage::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + Q_D(QWebEnginePage); + bool hadInterceptorChanged = bool(d->requestInterceptor) != bool(interceptor); + d->requestInterceptor = interceptor; + if (hadInterceptorChanged) { + if (interceptor) + d->profile->d_ptr->profileAdapter()->addPageRequestInterceptor(); + else + d->profile->d_ptr->profileAdapter()->removePageRequestInterceptor(); + } +} + +void QWebEnginePagePrivate::interceptRequest(QWebEngineUrlRequestInfo &info) +{ + if (requestInterceptor) + requestInterceptor->interceptRequest(info); +} + #if QT_CONFIG(menu) QMenu *QWebEnginePage::createStandardContextMenu() { @@ -1960,6 +1934,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine d->adapter->grantMouseLockPermission(true); break; case Notifications: + d->adapter->runUserNotificationRequestCallback(securityOrigin, true); break; } } else { // if (policy == PermissionDeniedByUser) @@ -1978,6 +1953,7 @@ void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEngine d->adapter->grantMouseLockPermission(false); break; case Notifications: + d->adapter->runUserNotificationRequestCallback(securityOrigin, false); break; } } @@ -2490,10 +2466,7 @@ void QWebEnginePage::printToPdf(const QWebEngineCallback<const QByteArray&> &res It is the users responsibility to ensure the \a printer remains valid until \a resultCallback has been called. - \note The rendering of the current content into a temporary PDF document is asynchronous and does - not block the main thread. However, the subsequent rendering of PDF into \a printer runs on the - main thread and will therefore block the event loop. Moreover, printing runs on the browser - process, which is by default not sandboxed. + \note Printing runs on the browser process, which is by default not sandboxed. The \a resultCallback must take a boolean as parameter. If printing was successful, this boolean will have the value \c true, otherwise, its value will be \c false. diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 028f1a441..4956877a9 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -71,6 +71,7 @@ class QWebEngineQuotaRequest; class QWebEngineRegisterProtocolHandlerRequest; class QWebEngineScriptCollection; class QWebEngineSettings; +class QWebEngineUrlRequestInterceptor; class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject { Q_OBJECT @@ -184,9 +185,7 @@ public: Q_ENUM(NavigationType) enum Feature { -#ifndef Q_QDOC Notifications = 0, -#endif Geolocation = 1, MediaAudioCapture = 2, MediaVideoCapture, @@ -303,6 +302,8 @@ public: void setDevToolsPage(QWebEnginePage *page); QWebEnginePage *devToolsPage() const; + void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); + const QWebEngineContextMenuData &contextMenuData() const; Q_SIGNALS: diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index f8f67d341..dc0ead534 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -66,6 +66,8 @@ namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegate; class RenderWidgetHostViewQtDelegateWidget; +class TouchHandleDrawableClient; +class TouchSelectionMenuController; class WebContentsAdapter; } @@ -98,7 +100,6 @@ public: void selectionChanged() override; void recentlyAudibleChanged(bool recentlyAudible) override; QRectF viewportRect() const override; - qreal dpiScale() const override; QColor backgroundColor() const override; void loadStarted(const QUrl &provisionalUrl, bool isErrorPage = false) override; void loadCommitted() override { } @@ -124,7 +125,7 @@ public: void didFetchDocumentMarkup(quint64 requestId, const QString& result) override; void didFetchDocumentInnerText(quint64 requestId, const QString& result) override; void didFindText(quint64 requestId, int matchCount) override; - void didPrintPage(quint64 requestId, const QByteArray &result) override; + void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) override; void didPrintPageToPdf(const QString &filePath, bool success) override; bool passOnFocus(bool reverse) override; void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override; @@ -132,6 +133,7 @@ public: void releaseProfile() override; void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override; void runGeolocationPermissionRequest(const QUrl &securityOrigin) override; + void runUserNotificationPermissionRequest(const QUrl &securityOrigin) override; void runMouseLockPermissionRequest(const QUrl &securityOrigin) override; void runQuotaRequest(QWebEngineQuotaRequest) override; void runRegisterProtocolHandlerRequest(QWebEngineRegisterProtocolHandlerRequest) override; @@ -151,8 +153,12 @@ public: bool isEnabled() const override; void setToolTip(const QString &toolTipText) override; void printRequested() override; + QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &) override { return nullptr; } + void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override { } + void hideTouchSelectionMenu() override { } const QObject *holdingQObject() const override; ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; } + void interceptRequest(QWebEngineUrlRequestInfo &) override; void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidget) override; QtWebEngineCore::ProfileAdapter *profileAdapter() override; @@ -195,6 +201,7 @@ public: bool defaultAudioMuted; qreal defaultZoomFactor; QTimer wasShownTimer; + QWebEngineUrlRequestInterceptor *requestInterceptor; QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget *widget = nullptr; mutable QtWebEngineCore::CallbackDirectory m_callbacks; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 6644af3ff..f9fcc6136 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -43,6 +43,7 @@ #include "qwebenginecookiestore.h" #include "qwebenginedownloaditem.h" #include "qwebenginedownloaditem_p.h" +#include "qwebenginenotificationpresenter_p.h" #include "qwebenginepage.h" #include "qwebenginepage_p.h" #include "qwebenginesettings.h" @@ -140,6 +141,14 @@ using QtWebEngineCore::ProfileAdapter; Both session and persistent cookies are saved to and restored from disk. */ +void QWebEngineProfilePrivate::showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &controller) +{ + if (m_notificationPresenter) { + std::unique_ptr<QWebEngineNotification> notification(new QWebEngineNotification(controller)); + m_notificationPresenter(std::move(notification)); + } +} + /*! \fn QWebEngineProfile::downloadRequested(QWebEngineDownloadItem *download) @@ -379,6 +388,36 @@ void QWebEngineProfile::setPersistentStoragePath(const QString &path) } /*! + \since 5.13 + + The path to the location where the downloaded files are stored. + + \note By default, the download path is QStandardPaths::DownloadLocation. + + \sa setDownloadPath(), QStandardPaths::writableLocation() +*/ +QString QWebEngineProfile::downloadPath() const +{ + const Q_D(QWebEngineProfile); + return d->profileAdapter()->downloadPath(); +} + +/*! + \since 5.13 + + Overrides the default path used for download location, setting it to \a path. + + If set to the null string, the default path is restored. + + \sa downloadPath() +*/ +void QWebEngineProfile::setDownloadPath(const QString &path) +{ + Q_D(QWebEngineProfile); + d->profileAdapter()->setDownloadPath(path); +} + +/*! Returns the path used for caches. By default, this is below StandardPaths::CacheLocation in a QtWebengine/StorageName specific @@ -542,19 +581,45 @@ QWebEngineCookieStore* QWebEngineProfile::cookieStore() return d->profileAdapter()->cookieStore(); } - +#if QT_DEPRECATED_SINCE(5, 13) /*! Registers a request interceptor singleton \a interceptor to intercept URL requests. The profile does not take ownership of the pointer. + \obsolete + + Interceptors installed with this method will call + QWebEngineUrlRequestInterceptor::interceptRequest on the I/O thread. Therefore + the user has to provide thread-safe interaction with the other user classes. + Use setUrlRequestInterceptor instead. + \since 5.6 \sa QWebEngineUrlRequestInfo -*/ +*/ void QWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) { Q_D(QWebEngineProfile); + if (interceptor) + interceptor->setProperty("deprecated", true); + d->profileAdapter()->setRequestInterceptor(interceptor); + if (interceptor) + qDebug("Use of deprecated not thread-safe setter, use setUrlRequestInterceptor instead."); +} +#endif +/*! + Registers a request interceptor singleton \a interceptor to intercept URL requests. + + The profile does not take ownership of the pointer. + + \since 5.13 + \sa QWebEngineUrlRequestInfo QWebEngineUrlRequestInterceptor +*/ + +void QWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor) +{ + Q_D(QWebEngineProfile); d->profileAdapter()->setRequestInterceptor(interceptor); } @@ -603,6 +668,18 @@ QWebEngineScriptCollection *QWebEngineProfile::scripts() const } /*! + Sets the function \a notificationPresenter as responsible for presenting sent notifications. + + \since 5.13 + \sa QWebEngineNotification +*/ +void QWebEngineProfile::setNotificationPresenter(std::function<void(std::unique_ptr<QWebEngineNotification>)> notificationPresenter) +{ + Q_D(QWebEngineProfile); + d->m_notificationPresenter = std::move(notificationPresenter); +} + +/*! Returns the default profile. The default profile uses the storage name "Default". @@ -614,6 +691,8 @@ QWebEngineProfile *QWebEngineProfile::defaultProfile() static QWebEngineProfile* profile = new QWebEngineProfile( new QWebEngineProfilePrivate(ProfileAdapter::createDefaultProfileAdapter()), ProfileAdapter::globalQObjectRoot()); + if (!profile->d_ptr->m_notificationPresenter) + profile->setNotificationPresenter(&defaultNotificationPresenter); return profile; } @@ -689,7 +768,7 @@ QWebEngineSettings *QWebEngineProfile::settings() const const QWebEngineUrlSchemeHandler *QWebEngineProfile::urlSchemeHandler(const QByteArray &scheme) const { const Q_D(QWebEngineProfile); - return d->profileAdapter()->customUrlSchemeHandlers().value(scheme.toLower()); + return d->profileAdapter()->urlSchemeHandler(scheme); } /*! @@ -703,10 +782,7 @@ const QWebEngineUrlSchemeHandler *QWebEngineProfile::urlSchemeHandler(const QByt void QWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) { Q_D(QWebEngineProfile); - Q_ASSERT(handler); - if (!d->profileAdapter()->addCustomUrlSchemeHandler(scheme, handler)) - return; - connect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*))); + d->profileAdapter()->installUrlSchemeHandler(scheme, handler); } /*! @@ -719,10 +795,7 @@ void QWebEngineProfile::installUrlSchemeHandler(const QByteArray &scheme, QWebEn void QWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) { Q_D(QWebEngineProfile); - Q_ASSERT(handler); - if (!d->profileAdapter()->removeCustomUrlSchemeHandler(handler)) - return; - disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*))); + d->profileAdapter()->removeUrlSchemeHandler(handler); } /*! @@ -735,10 +808,7 @@ void QWebEngineProfile::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handl void QWebEngineProfile::removeUrlScheme(const QByteArray &scheme) { Q_D(QWebEngineProfile); - QWebEngineUrlSchemeHandler *handler = d->profileAdapter()->takeCustomUrlSchemeHandler(scheme); - if (!handler) - return; - disconnect(handler, SIGNAL(_q_destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*)), this, SLOT(destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler*))); + d->profileAdapter()->removeUrlScheme(scheme); } /*! @@ -749,12 +819,43 @@ void QWebEngineProfile::removeUrlScheme(const QByteArray &scheme) void QWebEngineProfile::removeAllUrlSchemeHandlers() { Q_D(QWebEngineProfile); - d->profileAdapter()->clearCustomUrlSchemeHandlers(); + d->profileAdapter()->removeAllUrlSchemeHandlers(); } -void QWebEngineProfile::destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj) +/*! + \since 5.13 + + Sets if this profile is to be used for downloading and caching when needed + during certificate verification, for instance for OCSP, CRLs, and AIA. + + Only one QWebEngineProfile can do this at a time, and it is recommended + that the profile fullfilling this role has a disk HTTP cache to avoid + needlessly re-downloading. If you set the option on a second profile, + it will be disabled on the profile it is currently set. + + Currently only affects Linux/NSS installations where it enables OCSP. + + As long as one profile has \a enabled set to \c true, all other profiles + will be able to use it for their certificate verification. + + \sa isUsedForGlobalCertificateVerification(), httpCacheType() +*/ +void QWebEngineProfile::setUseForGlobalCertificateVerification(bool enabled) { - removeUrlSchemeHandler(obj); + Q_D(QWebEngineProfile); + d->profileAdapter()->setUseForGlobalCertificateVerification(enabled); +} + +/*! + \since 5.13 + + Returns \c true if this profile is currently being used for global + certificate verification. +*/ +bool QWebEngineProfile::isUsedForGlobalCertificateVerification() const +{ + Q_D(const QWebEngineProfile); + return d->profileAdapter()->isUsedForGlobalCertificateVerification(); } /*! @@ -768,4 +869,19 @@ void QWebEngineProfile::clearHttpCache() d->profileAdapter()->clearHttpCache(); } +/*! + \since 5.13 + + Returns the profile's client certificate store. +*/ +QWebEngineClientCertificateStore *QWebEngineProfile::clientCertificateStore() +{ +#if QT_CONFIG(ssl) + Q_D(QWebEngineProfile); + return d->profileAdapter()->clientCertificateStore(); +#else + return nullptr; +#endif +} + QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h index f9a564cd2..794ba6279 100644 --- a/src/webenginewidgets/api/qwebengineprofile.h +++ b/src/webenginewidgets/api/qwebengineprofile.h @@ -46,12 +46,17 @@ #include <QtCore/qscopedpointer.h> #include <QtCore/qstring.h> +#include <functional> +#include <memory> + QT_BEGIN_NAMESPACE class QObject; class QUrl; +class QWebEngineClientCertificateStore; class QWebEngineCookieStore; class QWebEngineDownloadItem; +class QWebEngineNotification; class QWebEnginePage; class QWebEnginePagePrivate; class QWebEngineProfilePrivate; @@ -106,7 +111,10 @@ public: void setHttpCacheMaximumSize(int maxSize); QWebEngineCookieStore* cookieStore(); +#if QT_DEPRECATED_SINCE(5, 13) void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); +#endif + void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); void clearAllVisitedLinks(); void clearVisitedLinks(const QList<QUrl> &urls); @@ -128,19 +136,27 @@ public: void setSpellCheckEnabled(bool enabled); bool isSpellCheckEnabled() const; + void setUseForGlobalCertificateVerification(bool enabled = true); + bool isUsedForGlobalCertificateVerification() const; + + QString downloadPath() const; + void setDownloadPath(const QString &path); + + void setNotificationPresenter(std::function<void(std::unique_ptr<QWebEngineNotification>)> notificationPresenter); + + QWebEngineClientCertificateStore *clientCertificateStore(); + static QWebEngineProfile *defaultProfile(); Q_SIGNALS: void downloadRequested(QWebEngineDownloadItem *download); -private Q_SLOTS: - void destroyedUrlSchemeHandler(QWebEngineUrlSchemeHandler *obj); - private: Q_DISABLE_COPY(QWebEngineProfile) Q_DECLARE_PRIVATE(QWebEngineProfile) QWebEngineProfile(QWebEngineProfilePrivate *, QObject *parent = Q_NULLPTR); + friend class QWebEnginePage; friend class QWebEnginePagePrivate; friend class QWebEngineUrlSchemeHandler; QScopedPointer<QWebEngineProfilePrivate> d_ptr; diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h index cb43dace5..64e9500b0 100644 --- a/src/webenginewidgets/api/qwebengineprofile_p.h +++ b/src/webenginewidgets/api/qwebengineprofile_p.h @@ -60,6 +60,8 @@ #include <QScopedPointer> #include <QSharedPointer> +#include <functional> + namespace QtWebEngineCore { class ProfileAdapter; } @@ -68,6 +70,7 @@ QT_BEGIN_NAMESPACE class QWebEngineBrowserContext; class QWebEngineProfilePrivate; +class QWebEngineNotification; class QWebEngineSettings; class QWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClient { @@ -86,6 +89,8 @@ public: void downloadRequested(DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; + void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &) override; + void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override; @@ -95,6 +100,7 @@ private: QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter; QScopedPointer<QWebEngineScriptCollection> m_scriptCollection; QMap<quint32, QPointer<QWebEngineDownloadItem> > m_ongoingDownloads; + std::function<void(std::unique_ptr<QWebEngineNotification>)> m_notificationPresenter; }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp index d91eb3f97..d9fb3b000 100644 --- a/src/webenginewidgets/api/qwebenginesettings.cpp +++ b/src/webenginewidgets/api/qwebenginesettings.cpp @@ -109,7 +109,8 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web return WebEngineSettings::JavascriptCanPaste; case QWebEngineSettings::DnsPrefetchEnabled: return WebEngineSettings::DnsPrefetchEnabled; - + case QWebEngineSettings::PdfViewerEnabled: + return WebEngineSettings::PdfViewerEnabled; default: return WebEngineSettings::UnsupportedInCoreSettings; } diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h index 9100e32d5..d39291fed 100644 --- a/src/webenginewidgets/api/qwebenginesettings.h +++ b/src/webenginewidgets/api/qwebenginesettings.h @@ -96,6 +96,7 @@ public: WebRTCPublicInterfacesOnly, JavascriptCanPaste, DnsPrefetchEnabled, + PdfViewerEnabled, }; enum FontSize { diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 381f1385c..6c08df343 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -119,7 +119,7 @@ static QAccessibleInterface *webAccessibleFactory(const QString &, QObject *obje { if (QWebEngineView *v = qobject_cast<QWebEngineView*>(object)) return new QWebEngineViewAccessible(v); - return Q_NULLPTR; + return nullptr; } #endif // QT_NO_ACCESSIBILITY @@ -461,7 +461,7 @@ QAccessibleInterface *QWebEngineViewAccessible::child(int index) const { if (index == 0 && view() && view()->page()) return view()->page()->d_func()->adapter->browserAccessible(); - return Q_NULLPTR; + return nullptr; } int QWebEngineViewAccessible::indexOfChild(const QAccessibleInterface *c) const diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 2bf4d0413..e5c0c0c3e 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -287,6 +287,8 @@ This enum describes the platform feature access categories that the user may be asked to grant or deny access to: + \value Notifications + Web notifications for the end-user. \value Geolocation Location hardware or service. \value MediaAudioCapture diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index 88f6e05c2..ce75a4203 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -188,7 +188,9 @@ \value DnsPrefetchEnabled Specifies whether WebEngine will try to pre-fetch DNS entries to speed up browsing. Disabled by default. (Added in Qt 5.12) - + \value PdfViewerEnabled Specifies that PDF documents will be opened in the internal PDF viewer + instead of being downloaded. + Enabled by default. (Added in Qt 5.13) */ /*! diff --git a/src/webenginewidgets/printer_worker.cpp b/src/webenginewidgets/printer_worker.cpp new file mode 100644 index 000000000..94a862cda --- /dev/null +++ b/src/webenginewidgets/printer_worker.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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 "printer_worker.h" + +#include "printing/pdfium_document_wrapper_qt.h" + +#include <QPainter> +#include <QPrinter> + +namespace QtWebEngineCore { + +PrinterWorker::PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer) + : m_data(data) + , m_printer(printer) +{ +} + +PrinterWorker::~PrinterWorker() +{ +} + +void PrinterWorker::print() +{ + if (!m_data->size()) { + qWarning("Failure to print on printer %ls: Print result data is empty.", + qUtf16Printable(m_printer->printerName())); + Q_EMIT resultReady(false); + return; + } + + PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size()); + + int toPage = m_printer->toPage(); + int fromPage = m_printer->fromPage(); + bool ascendingOrder = true; + + if (fromPage == 0 && toPage == 0) { + fromPage = 1; + toPage = pdfiumWrapper.pageCount(); + } + fromPage = qMax(1, fromPage); + toPage = qMin(pdfiumWrapper.pageCount(), toPage); + + if (m_printer->pageOrder() == QPrinter::LastPageFirst) { + qSwap(fromPage, toPage); + ascendingOrder = false; + } + + int pageCopies = 1; + int documentCopies = 1; + + if (!m_printer->supportsMultipleCopies()) + documentCopies = m_printer->copyCount(); + + if (m_printer->collateCopies()) { + pageCopies = documentCopies; + documentCopies = 1; + } + + bool isLandscape = pdfiumWrapper.pageIsLandscape(0); + QPageLayout::Orientation prevOrientation = m_printer->pageLayout().orientation(); + m_printer->setPageOrientation(isLandscape ? QPageLayout::Landscape : QPageLayout::Portrait); + + QPainter painter; + if (!painter.begin(m_printer)) { + qWarning("Failure to print on printer %ls: Could not open printer for painting.", + qUtf16Printable(m_printer->printerName())); + Q_EMIT resultReady(false); + return; + } + + for (int printedDocuments = 0; printedDocuments < documentCopies; printedDocuments++) { + if (printedDocuments > 0) + m_printer->newPage(); + + int currentPageIndex = fromPage; + + for (int i = 0; true; i++) { + prevOrientation = m_printer->pageLayout().orientation(); + isLandscape = pdfiumWrapper.pageIsLandscape(currentPageIndex - 1); + m_printer->setPageOrientation(isLandscape ? QPageLayout::Landscape : QPageLayout::Portrait); + + QSize pageSize = m_printer->pageRect().size(); + + if (i > 0) + m_printer->newPage(); + + for (int printedPages = 0; printedPages < pageCopies; printedPages++) { + if (m_printer->printerState() == QPrinter::Aborted + || m_printer->printerState() == QPrinter::Error) { + Q_EMIT resultReady(false); + return; + } + + if (printedPages > 0) + m_printer->newPage(); + + QImage currentImage = pdfiumWrapper.pageAsQImage(currentPageIndex - 1); + if (currentImage.isNull()) { + Q_EMIT resultReady(false); + return; + } + + QRect targetRect = currentImage.rect(); + // Scale down currentImage by both width and height to fit into the drawable area of the page. + float scaleFactor = (float)pageSize.width() / (float)targetRect.width(); + targetRect = QRect(0, 0, targetRect.width() * scaleFactor, targetRect.height() * scaleFactor); + scaleFactor = (float)pageSize.height() / (float)targetRect.height(); + targetRect = QRect(0, 0, targetRect.width() * scaleFactor, targetRect.height() * scaleFactor); + + // Painting operations are automatically clipped to the bounds of the drawable part of the page. + painter.drawImage(targetRect, currentImage, currentImage.rect()); + } + + if (currentPageIndex == toPage) + break; + + if (ascendingOrder) + currentPageIndex++; + else + currentPageIndex--; + + m_printer->setPageOrientation(prevOrientation); + } + } + painter.end(); + + Q_EMIT resultReady(true); + return; +} + +} // namespace QtWebEngineCore diff --git a/src/webenginewidgets/printer_worker.h b/src/webenginewidgets/printer_worker.h new file mode 100644 index 000000000..96025c90e --- /dev/null +++ b/src/webenginewidgets/printer_worker.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2018 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$ +** +****************************************************************************/ + +// +// 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. +// + +#ifndef PRINTER_WORKER_H +#define PRINTER_WORKER_H + +#include "qtwebenginecoreglobal_p.h" + +#include <QSharedPointer> + +QT_BEGIN_NAMESPACE +class QPrinter; +QT_END_NAMESPACE + +namespace QtWebEngineCore { + +class PrinterWorker : public QObject +{ + Q_OBJECT +public: + PrinterWorker(QSharedPointer<QByteArray> data, QPrinter *printer); + virtual ~PrinterWorker(); + +public Q_SLOTS: + void print(); + +Q_SIGNALS: + void resultReady(bool success); + +private: + Q_DISABLE_COPY(PrinterWorker) + + QSharedPointer<QByteArray> m_data; + QPrinter *m_printer; +}; + +} // namespace QtWebEngineCore + +Q_DECLARE_METATYPE(QtWebEngineCore::PrinterWorker*) + +#endif // PRINTER_WORKER_H 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 18f1e97d0..88eb9843b 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -124,25 +124,31 @@ RenderWidgetHostViewQtDelegateWidget::RenderWidgetHostViewQtDelegateWidget(Rende "QSurfaceFormat before the QtGui application instance is created."); } #endif - - // Make sure the OpenGL profile of the QQuickWidget matches the shared context profile. - if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) { - int major; - int minor; - QSurfaceFormat::OpenGLContextProfile profile; - + int major; + int minor; + QSurfaceFormat::OpenGLContextProfile profile; #ifdef Q_OS_MACOS - // Due to QTBUG-63180, requesting the sharedFormat.majorVersion() on macOS will lead to - // a failed creation of QQuickWidget shared context. Thus make sure to request the - // major version specified in the defaultFormat instead. - major = defaultFormat.majorVersion(); - minor = defaultFormat.minorVersion(); - profile = defaultFormat.profile(); + // Due to QTBUG-63180, requesting the sharedFormat.majorVersion() on macOS will lead to + // a failed creation of QQuickWidget shared context. Thus make sure to request the + // major version specified in the defaultFormat instead. + major = defaultFormat.majorVersion(); + minor = defaultFormat.minorVersion(); + profile = defaultFormat.profile(); #else - major = sharedFormat.majorVersion(); - minor = sharedFormat.minorVersion(); - profile = sharedFormat.profile(); + major = sharedFormat.majorVersion(); + minor = sharedFormat.minorVersion(); + profile = sharedFormat.profile(); #endif + + // Make sure the OpenGL profile of the QQuickWidget matches the shared context profile. + // It covers the following cases: + // 1) Desktop OpenGL Core Profile. + // 2) Windows ANGLE OpenGL ES profile. + if (sharedFormat.profile() == QSurfaceFormat::CoreProfile +#ifdef Q_OS_WIN + || globalSharedContext->isOpenGLES() +#endif + ) { format.setMajorVersion(major); format.setMinorVersion(minor); format.setProfile(profile); @@ -183,7 +189,7 @@ void RenderWidgetHostViewQtDelegateWidget::removeParentBeforeParentDelete() { // Unset the parent, because parent is being destroyed, but the owner of this // RenderWidgetHostViewQtDelegateWidget is actually a RenderWidgetHostViewQt instance. - setParent(Q_NULLPTR); + setParent(nullptr); // If this widget represents a popup window, make sure to close it, so that if the popup was the // last visible top level window, the application event loop can quit if it deems it necessarry. @@ -219,15 +225,16 @@ void RenderWidgetHostViewQtDelegateWidget::closeEvent(QCloseEvent *event) m_client->closePopup(); } -QRectF RenderWidgetHostViewQtDelegateWidget::screenRect() const +QRectF RenderWidgetHostViewQtDelegateWidget::viewGeometry() const { - return QRectF(x(), y(), width(), height()); + return QRectF(mapToGlobal(pos()), size()); } -QRectF RenderWidgetHostViewQtDelegateWidget::contentsRect() const +QRect RenderWidgetHostViewQtDelegateWidget::windowGeometry() const { - QPointF pos = mapToGlobal(QPoint(0, 0)); - return QRectF(pos.x(), pos.y(), width(), height()); + if (!window()) + return QRect(); + return window()->frameGeometry(); } void RenderWidgetHostViewQtDelegateWidget::setKeyboardFocus() @@ -365,14 +372,7 @@ QVariant RenderWidgetHostViewQtDelegateWidget::inputMethodQuery(Qt::InputMethodQ void RenderWidgetHostViewQtDelegateWidget::resizeEvent(QResizeEvent *resizeEvent) { QQuickWidget::resizeEvent(resizeEvent); - - const QPoint globalPos = mapToGlobal(pos()); - if (globalPos != m_lastGlobalPos) { - m_lastGlobalPos = globalPos; - m_client->windowBoundsChanged(); - } - - m_client->notifyResize(); + m_client->visualPropertiesChanged(); } void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event) @@ -388,7 +388,7 @@ void RenderWidgetHostViewQtDelegateWidget::showEvent(QShowEvent *event) m_windowConnections.append(connect(w, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged()))); m_windowConnections.append(connect(w, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged()))); } - m_client->windowChanged(); + m_client->visualPropertiesChanged(); m_client->notifyShown(); } @@ -486,8 +486,7 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event) void RenderWidgetHostViewQtDelegateWidget::onWindowPosChanged() { - m_lastGlobalPos = mapToGlobal(pos()); - m_client->windowBoundsChanged(); + m_client->visualPropertiesChanged(); } } // namespace QtWebEngineCore 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 c1cd90093..7746c4405 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.h @@ -66,8 +66,8 @@ public: ~RenderWidgetHostViewQtDelegateWidget(); void initAsPopup(const QRect&) override; - QRectF screenRect() const override; - QRectF contentsRect() const override; + QRectF viewGeometry() const override; + QRect windowGeometry() const override; void setKeyboardFocus() override; bool hasKeyboardFocus() override; void lockMouse() override; @@ -111,7 +111,6 @@ private: QScopedPointer<QQuickItem> m_rootItem; bool m_isPopup; QColor m_clearColor; - QPoint m_lastGlobalPos; QList<QMetaObject::Connection> m_windowConnections; QWebEnginePage *m_page = nullptr; QMetaObject::Connection m_parentDestroyedConnection; diff --git a/src/webenginewidgets/webenginewidgets.pro b/src/webenginewidgets/webenginewidgets.pro index e61575d3a..d4fb40dc7 100644 --- a/src/webenginewidgets/webenginewidgets.pro +++ b/src/webenginewidgets/webenginewidgets.pro @@ -19,6 +19,7 @@ SOURCES = \ api/qwebenginedownloaditem.cpp \ api/qwebenginefullscreenrequest.cpp \ api/qwebenginehistory.cpp \ + api/qwebenginenotificationpresenter.cpp \ api/qwebenginepage.cpp \ api/qwebengineprofile.cpp \ api/qwebenginescript.cpp \ @@ -36,6 +37,7 @@ HEADERS = \ api/qwebenginedownloaditem_p.h \ api/qwebenginefullscreenrequest.h \ api/qwebenginehistory.h \ + api/qwebenginenotificationpresenter_p.h \ api/qwebenginepage.h \ api/qwebenginepage_p.h \ api/qwebengineprofile.h \ @@ -49,6 +51,9 @@ HEADERS = \ qtConfig(webengine-printing-and-pdf) { QT += printsupport + + SOURCES += printer_worker.cpp + HEADERS += printer_worker.h } load(qt_module) |