summaryrefslogtreecommitdiffstats
path: root/src/webenginewidgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/webenginewidgets')
-rw-r--r--src/webenginewidgets/CMakeLists.txt13
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp207
-rw-r--r--src/webenginewidgets/api/qwebengineview_p.h13
-rw-r--r--src/webenginewidgets/doc/snippets/push-notifications/commands19
-rw-r--r--src/webenginewidgets/doc/snippets/qtwebengine_qwebengineview_snippet.cpp2
-rw-r--r--src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc7
-rw-r--r--src/webenginewidgets/doc/snippets/simple/main.cpp11
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc1
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc5
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc10
-rw-r--r--src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc36
-rw-r--r--src/webenginewidgets/plugins/qwebengineview/CMakeLists.txt3
-rw-r--r--src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp8
-rw-r--r--src/webenginewidgets/qwebengine_accessible.cpp6
-rw-r--r--src/webenginewidgets/qwebengine_accessible_p.h (renamed from src/webenginewidgets/qwebengine_accessible.h)18
-rw-r--r--src/webenginewidgets/ui/autofillpopupwidget.cpp40
-rw-r--r--src/webenginewidgets/ui/autofillpopupwidget_p.h40
-rw-r--r--src/webenginewidgets/ui/touchhandlewidget.cpp59
-rw-r--r--src/webenginewidgets/ui/touchhandlewidget_p.h50
-rw-r--r--src/webenginewidgets/ui/touchselectionmenuwidget.cpp117
-rw-r--r--src/webenginewidgets/ui/touchselectionmenuwidget_p.h52
21 files changed, 523 insertions, 194 deletions
diff --git a/src/webenginewidgets/CMakeLists.txt b/src/webenginewidgets/CMakeLists.txt
index 97bde6b56..ff043b45a 100644
--- a/src/webenginewidgets/CMakeLists.txt
+++ b/src/webenginewidgets/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
if(TARGET Qt::Designer)
add_subdirectory(plugins/qwebengineview)
else()
@@ -8,13 +11,15 @@ qt_internal_add_module(WebEngineWidgets
api/qtwebenginewidgetsglobal.h
api/qwebenginenotificationpresenter.cpp api/qwebenginenotificationpresenter_p.h
api/qwebengineview.cpp api/qwebengineview.h api/qwebengineview_p.h
- qwebengine_accessible.cpp qwebengine_accessible.h
ui/autofillpopupwidget.cpp ui/autofillpopupwidget_p.h
+ ui/touchhandlewidget.cpp ui/touchhandlewidget_p.h
+ ui/touchselectionmenuwidget.cpp ui/touchselectionmenuwidget_p.h
DEFINES
QT_BUILD_WEBENGINEWIDGETS_LIB
INCLUDE_DIRECTORIES
../core
api
+ ui
LIBRARIES
Qt::CorePrivate
Qt::GuiPrivate
@@ -27,6 +32,12 @@ qt_internal_add_module(WebEngineWidgets
Qt::Gui
Qt::Widgets
Qt::WebEngineCore
+ NO_GENERATE_CPP_EXPORTS
+)
+
+qt_internal_extend_target(WebEngineWidgets CONDITION QT_FEATURE_accessibility
+ SOURCES
+ qwebengine_accessible.cpp qwebengine_accessible_p.h
)
qt_internal_extend_target(WebEngineWidgets CONDITION QT_FEATURE_webengine_printing_and_pdf
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 1703135be..5b47d67bf 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -1,13 +1,15 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#include "qapplication.h"
#include "qwebenginenotificationpresenter_p.h"
#include "qwebengineview.h"
#include "qwebengineview_p.h"
#include "render_widget_host_view_qt_delegate_client.h"
#include "render_widget_host_view_qt_delegate_item.h"
-#include "qwebengine_accessible.h"
#include "ui/autofillpopupwidget_p.h"
+#include "touchhandlewidget_p.h"
+#include "touchselectionmenuwidget_p.h"
#include <QtWebEngineCore/private/qwebenginepage_p.h>
#include <QtWebEngineCore/qwebenginecontextmenurequest.h>
@@ -17,6 +19,7 @@
#include "autofill_popup_controller.h"
#include "color_chooser_controller.h"
+#include "touch_selection_menu_controller.h"
#include "web_contents_adapter.h"
#include <QContextMenuEvent>
@@ -28,6 +31,10 @@
#include <QGuiApplication>
#include <QQuickWidget>
+#if QT_CONFIG(accessibility)
+#include "qwebengine_accessible_p.h"
+#endif
+
#if QT_CONFIG(action)
#include <QAction>
#endif
@@ -57,10 +64,19 @@
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/printer_worker.h"
+#include <QPrintEngine>
#include <QPrinter>
#include <QThread>
#endif
+QT_BEGIN_NAMESPACE
+class QSpontaneKeyEvent
+{
+public:
+ static inline void makeSpontaneous(QEvent *ev) { ev->setSpontaneous(); }
+};
+QT_END_NAMESPACE
+
namespace QtWebEngineCore {
class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate
{
@@ -78,7 +94,6 @@ public:
QQuickItem *root = new QQuickItem(); // Indirection so we don't delete m_contentItem
setContent(QUrl(), nullptr, root);
root->setFlags(QQuickItem::ItemHasContents);
- root->setFocus(true);
root->setVisible(true);
m_contentItem->setParentItem(root);
@@ -142,6 +157,7 @@ public:
}
void SetClearColor(const QColor &color) override
{
+ setUpdatesEnabled(false);
QQuickWidget::setClearColor(color);
// QQuickWidget is usually blended by punching holes into widgets
// above it to simulate the visual stacking order. If we want it to be
@@ -150,7 +166,8 @@ public:
bool isTranslucent = color.alpha() < 255;
setAttribute(Qt::WA_AlwaysStackOnTop, isTranslucent);
setAttribute(Qt::WA_OpaquePaintEvent, !isTranslucent);
- update();
+ setUpdatesEnabled(true);
+ window()->update();
}
void MoveWindow(const QPoint &screenPos) override
{
@@ -166,6 +183,14 @@ public:
return root->windowHandle();
return nullptr;
}
+ void unhandledWheelEvent(QWheelEvent *ev) override
+ {
+ auto parentWidget = QQuickWidget::parentWidget();
+ if (parentWidget) {
+ QSpontaneKeyEvent::makeSpontaneous(ev);
+ qApp->notify(parentWidget, ev);
+ }
+ }
protected:
void closeEvent(QCloseEvent *event) override
@@ -185,7 +210,7 @@ protected:
// We don't have a way to catch a top-level window change with QWidget
// but a widget will most likely be shown again if it changes, so do
// the reconnection at this point.
- for (const QMetaObject::Connection &c : qAsConst(m_windowConnections))
+ for (const QMetaObject::Connection &c : std::as_const(m_windowConnections))
disconnect(c);
m_windowConnections.clear();
if (QWindow *w = Window()) {
@@ -419,6 +444,8 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget
#endif
q->layout()->addWidget(newWidget);
q->setFocusProxy(newWidget);
+ if (oldWidget && oldWidget == QApplication::focusWidget())
+ newWidget->setFocus();
newWidget->show();
}
}
@@ -438,7 +465,7 @@ void QWebEngineViewPrivate::contextMenuRequested(QWebEngineContextMenuRequest *r
Q_EMIT q_ptr->customContextMenuRequested(request->position());
return;
case Qt::ActionsContextMenu:
- if (q_ptr->actions().count()) {
+ if (q_ptr->actions().size()) {
QContextMenuEvent event(QContextMenuEvent::Mouse, request->position(),
q_ptr->mapToGlobal(request->position()));
QMenu::exec(q_ptr->actions(), event.globalPos(), 0, q_ptr);
@@ -531,8 +558,10 @@ bool QWebEngineViewPrivate::showAuthorizationDialog(const QString &title, const
{
#if QT_CONFIG(messagebox)
Q_Q(QWebEngineView);
- return QMessageBox::question(q, title, message, QMessageBox::Yes, QMessageBox::No)
- == QMessageBox::Yes;
+ QMessageBox msgBox(QMessageBox::Question, title, message, QMessageBox::Yes | QMessageBox::No,
+ q, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+ msgBox.setTextFormat(Qt::PlainText);
+ return msgBox.exec() == QMessageBox::Yes;
#else
return false;
#endif // QT_CONFIG(messagebox)
@@ -542,8 +571,12 @@ void QWebEngineViewPrivate::javaScriptAlert(const QUrl &url, const QString &msg)
{
#if QT_CONFIG(messagebox)
Q_Q(QWebEngineView);
- QMessageBox::information(q, QStringLiteral("Javascript Alert - %1").arg(url.toString()),
- msg.toHtmlEscaped());
+ QMessageBox msgBox(QMessageBox::Information,
+ QStringLiteral("Javascript Alert - %1").arg(url.toString()),
+ msg, QMessageBox::Ok, q,
+ Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+ msgBox.setTextFormat(Qt::PlainText);
+ msgBox.exec();
#else
Q_UNUSED(msg);
#endif // QT_CONFIG(messagebox)
@@ -553,10 +586,12 @@ bool QWebEngineViewPrivate::javaScriptConfirm(const QUrl &url, const QString &ms
{
#if QT_CONFIG(messagebox)
Q_Q(QWebEngineView);
- return (QMessageBox::information(q,
- QStringLiteral("Javascript Confirm - %1").arg(url.toString()),
- msg.toHtmlEscaped(), QMessageBox::Ok, QMessageBox::Cancel)
- == QMessageBox::Ok);
+ QMessageBox msgBox(QMessageBox::Information,
+ QStringLiteral("Javascript Confirm - %1").arg(url.toString()),
+ msg, QMessageBox::Ok | QMessageBox::Cancel, q,
+ Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+ msgBox.setTextFormat(Qt::PlainText);
+ return msgBox.exec() == QMessageBox::Ok;
#else
Q_UNUSED(msg);
return false;
@@ -569,10 +604,16 @@ bool QWebEngineViewPrivate::javaScriptPrompt(const QUrl &url, const QString &msg
#if QT_CONFIG(inputdialog)
Q_Q(QWebEngineView);
bool ret = false;
+
+ // Workaround: Do not interpret text as Qt::RichText
+ // QInputDialog uses Qt::AutoText that interprets the text string as
+ // Qt::RichText if Qt::mightBeRichText() returns true, otherwise as Qt::PlainText.
+ const QString message = Qt::mightBeRichText(msg) ? msg.toHtmlEscaped() : msg;
+
if (result)
*result = QInputDialog::getText(
q, QStringLiteral("Javascript Prompt - %1").arg(url.toString()),
- msg.toHtmlEscaped(), QLineEdit::Normal, defaultValue.toHtmlEscaped(), &ret);
+ message, QLineEdit::Normal, defaultValue, &ret);
return ret;
#else
Q_UNUSED(msg);
@@ -698,11 +739,19 @@ void QWebEngineViewPrivate::bindPageAndWidget(QWebEnginePagePrivate *pagePrivate
// Change pointers first.
- if (oldPagePrivate && oldPagePrivate != pagePrivate)
- oldPagePrivate->delegateItem = nullptr;
+ if (widget && oldPagePrivate != pagePrivate) {
+ if (oldPagePrivate)
+ oldPagePrivate->delegateItem = nullptr;
+ if (widget->m_contentItem)
+ widget->m_contentItem->m_adapterClient = pagePrivate;
+ }
- if (pagePrivate && oldWidget != widget)
- pagePrivate->delegateItem = widget->m_contentItem;
+ if (pagePrivate && oldWidget != widget) {
+ if (oldWidget && oldWidget->m_contentItem)
+ oldWidget->m_contentItem->m_adapterClient = nullptr;
+ if (widget)
+ pagePrivate->delegateItem = widget->m_contentItem;
+ }
// Then notify.
@@ -717,9 +766,9 @@ void QWebEngineViewPrivate::bindPageAndWidget(QWebEnginePagePrivate *pagePrivate
}
}
-QIcon QWebEngineViewPrivate::webActionIcon(QWebEnginePage::WebAction action)
+QIcon QWebEngineViewPrivate::webActionIcon(QWebEnginePage::WebAction action) const
{
- Q_Q(QWebEngineView);
+ Q_Q(const QWebEngineView);
QIcon icon;
QStyle *style = q->style();
@@ -800,7 +849,11 @@ void QWebEngineViewPrivate::didPrintPage(QPrinter *&currentPrinter, QSharedPoint
printerWorker->m_documentCopies = currentPrinter->copyCount();
printerWorker->m_collateCopies = currentPrinter->collateCopies();
- QObject::connect(printerWorker, &QtWebEngineCore::PrinterWorker::resultReady, q, [q, &currentPrinter](bool success) {
+ int oldCopyCount = currentPrinter->copyCount();
+ currentPrinter->printEngine()->setProperty(QPrintEngine::PPK_CopyCount, 1);
+
+ QObject::connect(printerWorker, &QtWebEngineCore::PrinterWorker::resultReady, q, [q, &currentPrinter, oldCopyCount](bool success) {
+ currentPrinter->printEngine()->setProperty(QPrintEngine::PPK_CopyCount, oldCopyCount);
currentPrinter = nullptr;
Q_EMIT q->printFinished(success);
});
@@ -1087,7 +1140,16 @@ QString QWebEngineView::selectedText() const
#if QT_CONFIG(action)
QAction* QWebEngineView::pageAction(QWebEnginePage::WebAction action) const
{
- return page()->action(action);
+ Q_D(const QWebEngineView);
+ QAction *pageAction = page()->action(action);
+
+ if (pageAction->icon().isNull()) {
+ auto icon = d->webActionIcon(action);
+ if (!icon.isNull())
+ pageAction->setIcon(icon);
+ }
+
+ return pageAction;
}
#endif
@@ -1361,7 +1423,8 @@ void QWebEngineView::printToPdf(const std::function<void(const QByteArray&)> &re
\fn void QWebEngineView::printRequested()
\since 6.2
- This signal is emitted when the JavaScript \c{window.print()} method is called.
+ This signal is emitted when the JavaScript \c{window.print()} method is called or the user pressed the print
+ button of PDF viewer plugin.
Typically, the signal handler can simply call print().
\sa print()
@@ -1390,6 +1453,9 @@ void QWebEngineView::printToPdf(const std::function<void(const QByteArray&)> &re
\note Printing runs on the browser process, which is by default not sandboxed.
+ \note The data generation step of printing can be interrupted for a short period of time using
+ the \l QWebEnginePage::Stop web action.
+
\note This function rasterizes the result when rendering onto \a printer. Please consider raising
the default resolution of \a printer to at least 300 DPI or using printToPdf() to produce
PDF file output more effectively.
@@ -1441,82 +1507,82 @@ void QContextMenuBuilder::addMenuItem(ContextMenuItem menuItem)
switch (menuItem) {
case ContextMenuItem::Back:
- action = thisRef->action(QWebEnginePage::Back);
+ action = m_view->pageAction(QWebEnginePage::Back);
break;
case ContextMenuItem::Forward:
- action = thisRef->action(QWebEnginePage::Forward);
+ action = m_view->pageAction(QWebEnginePage::Forward);
break;
case ContextMenuItem::Reload:
- action = thisRef->action(QWebEnginePage::Reload);
+ action = m_view->pageAction(QWebEnginePage::Reload);
break;
case ContextMenuItem::Cut:
- action = thisRef->action(QWebEnginePage::Cut);
+ action = m_view->pageAction(QWebEnginePage::Cut);
break;
case ContextMenuItem::Copy:
- action = thisRef->action(QWebEnginePage::Copy);
+ action = m_view->pageAction(QWebEnginePage::Copy);
break;
case ContextMenuItem::Paste:
- action = thisRef->action(QWebEnginePage::Paste);
+ action = m_view->pageAction(QWebEnginePage::Paste);
break;
case ContextMenuItem::Undo:
- action = thisRef->action(QWebEnginePage::Undo);
+ action = m_view->pageAction(QWebEnginePage::Undo);
break;
case ContextMenuItem::Redo:
- action = thisRef->action(QWebEnginePage::Redo);
+ action = m_view->pageAction(QWebEnginePage::Redo);
break;
case ContextMenuItem::SelectAll:
- action = thisRef->action(QWebEnginePage::SelectAll);
+ action = m_view->pageAction(QWebEnginePage::SelectAll);
break;
case ContextMenuItem::PasteAndMatchStyle:
- action = thisRef->action(QWebEnginePage::PasteAndMatchStyle);
+ action = m_view->pageAction(QWebEnginePage::PasteAndMatchStyle);
break;
case ContextMenuItem::OpenLinkInNewWindow:
- action = thisRef->action(QWebEnginePage::OpenLinkInNewWindow);
+ action = m_view->pageAction(QWebEnginePage::OpenLinkInNewWindow);
break;
case ContextMenuItem::OpenLinkInNewTab:
- action = thisRef->action(QWebEnginePage::OpenLinkInNewTab);
+ action = m_view->pageAction(QWebEnginePage::OpenLinkInNewTab);
break;
case ContextMenuItem::CopyLinkToClipboard:
- action = thisRef->action(QWebEnginePage::CopyLinkToClipboard);
+ action = m_view->pageAction(QWebEnginePage::CopyLinkToClipboard);
break;
case ContextMenuItem::DownloadLinkToDisk:
- action = thisRef->action(QWebEnginePage::DownloadLinkToDisk);
+ action = m_view->pageAction(QWebEnginePage::DownloadLinkToDisk);
break;
case ContextMenuItem::CopyImageToClipboard:
- action = thisRef->action(QWebEnginePage::CopyImageToClipboard);
+ action = m_view->pageAction(QWebEnginePage::CopyImageToClipboard);
break;
case ContextMenuItem::CopyImageUrlToClipboard:
- action = thisRef->action(QWebEnginePage::CopyImageUrlToClipboard);
+ action = m_view->pageAction(QWebEnginePage::CopyImageUrlToClipboard);
break;
case ContextMenuItem::DownloadImageToDisk:
- action = thisRef->action(QWebEnginePage::DownloadImageToDisk);
+ action = m_view->pageAction(QWebEnginePage::DownloadImageToDisk);
break;
case ContextMenuItem::CopyMediaUrlToClipboard:
- action = thisRef->action(QWebEnginePage::CopyMediaUrlToClipboard);
+ action = m_view->pageAction(QWebEnginePage::CopyMediaUrlToClipboard);
break;
case ContextMenuItem::ToggleMediaControls:
- action = thisRef->action(QWebEnginePage::ToggleMediaControls);
+ action = m_view->pageAction(QWebEnginePage::ToggleMediaControls);
break;
case ContextMenuItem::ToggleMediaLoop:
- action = thisRef->action(QWebEnginePage::ToggleMediaLoop);
+ action = m_view->pageAction(QWebEnginePage::ToggleMediaLoop);
break;
case ContextMenuItem::DownloadMediaToDisk:
- action = thisRef->action(QWebEnginePage::DownloadMediaToDisk);
+ action = m_view->pageAction(QWebEnginePage::DownloadMediaToDisk);
break;
case ContextMenuItem::InspectElement:
- action = thisRef->action(QWebEnginePage::InspectElement);
+ action = m_view->pageAction(QWebEnginePage::InspectElement);
break;
case ContextMenuItem::ExitFullScreen:
- action = thisRef->action(QWebEnginePage::ExitFullScreen);
+ action = m_view->pageAction(QWebEnginePage::ExitFullScreen);
break;
case ContextMenuItem::SavePage:
- action = thisRef->action(QWebEnginePage::SavePage);
+ action = m_view->pageAction(QWebEnginePage::SavePage);
break;
case ContextMenuItem::ViewSource:
- action = thisRef->action(QWebEnginePage::ViewSource);
+ action = m_view->pageAction(QWebEnginePage::ViewSource);
break;
case ContextMenuItem::SpellingSuggestions:
- for (int i = 0; i < m_contextData->spellCheckerSuggestions().count() && i < 4; i++) {
+ for (int i = 0; i < m_contextData->spellCheckerSuggestions().size() && i < 4; i++) {
action = new QAction(m_menu);
QString replacement = m_contextData->spellCheckerSuggestions().at(i);
QObject::connect(action, &QAction::triggered, [thisRef, replacement] {
@@ -1584,6 +1650,49 @@ bool QContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem)
}
#endif // QT_CONFIG(action)
+QtWebEngineCore::TouchHandleDrawableDelegate *
+QWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &images)
+{
+ Q_Q(QWebEngineView);
+ return new QtWebEngineWidgetUI::TouchHandleWidget(q, images);
+}
+
+void QWebEngineViewPrivate::hideTouchSelectionMenu()
+{
+ if (m_touchSelectionMenu)
+ m_touchSelectionMenu->close();
+}
+
+void QWebEngineViewPrivate::showTouchSelectionMenu(
+ QtWebEngineCore::TouchSelectionMenuController *controller, const QRect &selectionBounds)
+{
+ Q_ASSERT(m_touchSelectionMenu == nullptr);
+ Q_Q(QWebEngineView);
+
+ // Do not show outside of view
+ QSize parentSize = q->nativeParentWidget() ? q->nativeParentWidget()->size() : q->size();
+ if (selectionBounds.x() < 0 || selectionBounds.x() > parentSize.width()
+ || selectionBounds.y() < 0 || selectionBounds.y() > parentSize.height())
+ return;
+
+ m_touchSelectionMenu = new QtWebEngineWidgetUI::TouchSelectionMenuWidget(q, controller);
+
+ const int kSpacingBetweenButtons = 2;
+ const int kMenuButtonMinWidth = 80;
+ const int kMenuButtonMinHeight = 40;
+
+ int buttonCount = controller->buttonCount();
+ int width = (kSpacingBetweenButtons * (buttonCount + 1)) + (kMenuButtonMinWidth * buttonCount);
+ int height = kMenuButtonMinHeight + kSpacingBetweenButtons;
+ int x = (selectionBounds.x() + selectionBounds.x() + selectionBounds.width() - width) / 2;
+ int y = selectionBounds.y() - height - 2;
+
+ QPoint pos = q->mapToGlobal(QPoint(x, y));
+
+ m_touchSelectionMenu->setGeometry(pos.x(), pos.y(), width, height);
+ m_touchSelectionMenu->show();
+}
+
QT_END_NAMESPACE
#include "moc_qwebengineview.cpp"
diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h
index 7855f9ef3..aa330ac23 100644
--- a/src/webenginewidgets/api/qwebengineview_p.h
+++ b/src/webenginewidgets/api/qwebengineview_p.h
@@ -19,16 +19,21 @@
#include "render_view_context_menu_qt.h"
+#include <QtCore/qpointer.h>
+
namespace QtWebEngineCore {
class AutofillPopupController;
class QWebEngineContextMenuRequest;
class WebEngineQuickWidget;
class RenderWidgetHostViewQtDelegate;
class RenderWidgetHostViewQtDelegateClient;
+class TouchSelectionMenuController;
}
namespace QtWebEngineWidgetUI {
class AutofillPopupWidget;
+class TouchHandleDrawableDelegate;
+class TouchSelectionMenuWidget;
}
QT_BEGIN_NAMESPACE
@@ -71,13 +76,18 @@ public:
void showAutofillPopup(QtWebEngineCore::AutofillPopupController *controller,
const QRect &bounds, bool autoselectFirstSuggestion) override;
void hideAutofillPopup() override;
+ QtWebEngineCore::TouchHandleDrawableDelegate *
+ createTouchHandleDelegate(const QMap<int, QImage> &images) override;
+ void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *,
+ const QRect &) override;
+ void hideTouchSelectionMenu() override;
QWebEngineViewPrivate();
virtual ~QWebEngineViewPrivate();
static void bindPageAndView(QWebEnginePage *page, QWebEngineView *view);
static void bindPageAndWidget(QWebEnginePagePrivate *pagePrivate,
QtWebEngineCore::WebEngineQuickWidget *widget);
- QIcon webActionIcon(QWebEnginePage::WebAction action);
+ QIcon webActionIcon(QWebEnginePage::WebAction action) const;
void unhandledKeyEvent(QKeyEvent *event) override;
void focusContainer() override;
bool passOnFocus(bool reverse) override;
@@ -90,6 +100,7 @@ public:
mutable bool m_ownsPage;
QWebEngineContextMenuRequest *m_contextRequest;
QScopedPointer<QtWebEngineWidgetUI::AutofillPopupWidget> m_autofillPopupWidget;
+ QPointer<QtWebEngineWidgetUI::TouchSelectionMenuWidget> m_touchSelectionMenu;
};
class QContextMenuBuilder : public QtWebEngineCore::RenderViewContextMenuQt
diff --git a/src/webenginewidgets/doc/snippets/push-notifications/commands b/src/webenginewidgets/doc/snippets/push-notifications/commands
new file mode 100644
index 000000000..aee9761c1
--- /dev/null
+++ b/src/webenginewidgets/doc/snippets/push-notifications/commands
@@ -0,0 +1,19 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+//! [0]
+npm init -y
+npm install web-push express
+//! [0]
+
+//! [1]
+"start": "node server.js"
+//! [1]
+
+//! [2]
+./node_odules/.bin/web-push generate-vapid-keys
+//! [2]
+
+//! [3]
+npm start
+//! [3]
diff --git a/src/webenginewidgets/doc/snippets/qtwebengine_qwebengineview_snippet.cpp b/src/webenginewidgets/doc/snippets/qtwebengine_qwebengineview_snippet.cpp
index c12490ec1..64531cf3a 100644
--- a/src/webenginewidgets/doc/snippets/qtwebengine_qwebengineview_snippet.cpp
+++ b/src/webenginewidgets/doc/snippets/qtwebengine_qwebengineview_snippet.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
void wrapInFunction()
{
diff --git a/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
index e732bbeed..f11f550ff 100644
--- a/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
+++ b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
@@ -5,12 +5,7 @@
QT += webenginewidgets
//! [0]
-
-//! [1]
-#include <QtWebEngineWidgets>
-//! [1]
-
//! [2]
find_package(Qt6 REQUIRED COMPONENTS WebEngineWidgets)
-target_link_libraries(target PRIVATE Qt::WebEngineWidgets)
+target_link_libraries(target PRIVATE Qt6::WebEngineWidgets)
//! [2]
diff --git a/src/webenginewidgets/doc/snippets/simple/main.cpp b/src/webenginewidgets/doc/snippets/simple/main.cpp
index f887aabaa..08613906b 100644
--- a/src/webenginewidgets/doc/snippets/simple/main.cpp
+++ b/src/webenginewidgets/doc/snippets/simple/main.cpp
@@ -1,18 +1,19 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+//! [Minimal Example]
#include <QApplication>
-#include <QUrl>
#include <QWebEngineView>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- QWidget *parent = nullptr;
//! [Using QWebEngineView]
- QWebEngineView *view = new QWebEngineView(parent);
- view->load(QUrl("http://qt-project.org/"));
- view->show();
+ QWebEngineView view;
+ view.load(QUrl("https://qt-project.org/"));
+ view.resize(1024, 750);
+ view.show();
//! [Using QWebEngineView]
return app.exec();
}
+//! [Minimal Example]
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
index 15f6d08f4..c9bd76bf4 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
@@ -5,7 +5,6 @@
\group webengine-widgetexamples
\title Qt WebEngine Widgets Examples
\brief Examples demonstrating the \QWE Widgets usage.
- \ingroup all-examples
Qt provides an integrated Web browser component based on Chromium, the popular
open source browser engine.
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
index a80400c60..8eb28b797 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-index.qdoc
@@ -10,11 +10,6 @@
\section1 Getting Started
- To include the definitions of the module's classes, use the
- following directive:
-
- \snippet qtwebenginewidgets_build_snippet.qdoc 1
-
To link against the module, add this line to your qmake project file:
\snippet qtwebenginewidgets_build_snippet.qdoc 0
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
index b88d7af36..ef5a1c4b5 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-module.qdoc
@@ -13,11 +13,6 @@
The \QWE Widgets module provides a web browser engine as well as C++ classes to render
and interact with web content.
- To include the definitions of the module's classes, use the
- following directive:
-
- \snippet qtwebenginewidgets_build_snippet.qdoc 1
-
\if !defined(qtforpython)
To link against the module using build with qmake,
add the following QT variable to your qmake .pro file:
@@ -29,4 +24,9 @@
\snippet qtwebenginewidgets_build_snippet.qdoc 2
\endif
+
+ The minimum amount of code needed to load and display an HTML page requires just
+ implementing the \c QWebEngineView class.
+
+ \snippet simple/main.cpp Minimal Example
*/
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 34aa53278..3153ec952 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -1,24 +1,8 @@
-/*
- Copyright (C) 2019 The Qt Company Ltd.
- Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- Copyright (C) 2008 Holger Hans Peter Freyther
- Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
+// Copyright (C) 2019 The Qt Company Ltd.
+// Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+// Copyright (C) 2008 Holger Hans Peter Freyther
+// Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
// The documentation in this file was imported from QtWebKit and is thus constrained
// by its LGPL license. Documentation written from scratch for new methods should be
@@ -77,7 +61,7 @@
new windows, such as pop-up windows, you can subclass QWebEngineView and
reimplement the createWindow() function.
- \sa {WebEngine Widgets Simple Browser Example}, {WebEngine Content Manipulation Example}, {WebEngine Markdown Editor Example}
+ \sa {WebEngine Widgets Simple Browser Example}, {WebEngine Content Manipulation Example}
*/
@@ -124,9 +108,8 @@
\fn void QWebEngineView::setHtml(const QString &html, const QUrl &baseUrl)
Sets the content of the web view to the specified \a html content.
- External objects, such as stylesheets or images referenced in the HTML
- document, are located relative to \a baseUrl. For external objects to
- be loaded, \c baseUrl cannot be empty. For example, if \a html
+ \a baseUrl is optional and used to resolve relative URLs in the document,
+ such as referenced images or stylesheets. For example, if \a html
is retrieved from \c http://www.example.com/documents/overview.html, which
is the base URL, then an image referenced with the relative URL, \c diagram.png,
should be at \c{http://www.example.com/documents/diagram.png}.
@@ -160,7 +143,7 @@
is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}.
External objects referenced in the content are located relative to \a baseUrl.
- For external objects to be loaded, \c baseUrl cannot be empty.
+ For external objects with relative URLs to be loaded, \c baseUrl cannot be empty.
The data is loaded immediately; external objects are loaded asynchronously.
@@ -226,6 +209,7 @@
/*!
\fn QAction *QWebEngineView::pageAction(QWebEnginePage::WebAction action) const
Returns a pointer to a QAction that encapsulates the specified web action \a action.
+ This function will also set a default styled icon to the QAction if it lacks one.
*/
/*!
diff --git a/src/webenginewidgets/plugins/qwebengineview/CMakeLists.txt b/src/webenginewidgets/plugins/qwebengineview/CMakeLists.txt
index 3e6f324da..0e7644bf7 100644
--- a/src/webenginewidgets/plugins/qwebengineview/CMakeLists.txt
+++ b/src/webenginewidgets/plugins/qwebengineview/CMakeLists.txt
@@ -1,3 +1,6 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
qt_internal_add_plugin(QWebEngineViewPlugin
OUTPUT_NAME qwebengineview
PLUGIN_TYPE designer
diff --git a/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp b/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
index 2ff1de169..6ba64a178 100644
--- a/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
+++ b/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
@@ -79,14 +79,6 @@ void QWebEngineViewPlugin::initialize(QDesignerFormEditorInterface * /*core*/)
QString QWebEngineViewPlugin::domXml() const
{
- const auto graphicsApi = QQuickWindow::graphicsApi();
- if (graphicsApi != QSGRendererInterface::OpenGLRhi
- && graphicsApi != QSGRendererInterface::Software) {
- qWarning("Qt Designer: The QWebEngineView custom widget plugin is disabled because it requires OpenGL/Software RHI (current: %d).",
- int(graphicsApi));
- return {};
- }
-
return QStringLiteral("\
<ui language=\"c++\">\
<widget class=\"QWebEngineView\" name=\"webEngineView\">\
diff --git a/src/webenginewidgets/qwebengine_accessible.cpp b/src/webenginewidgets/qwebengine_accessible.cpp
index 53a812604..cbdd90104 100644
--- a/src/webenginewidgets/qwebengine_accessible.cpp
+++ b/src/webenginewidgets/qwebengine_accessible.cpp
@@ -1,15 +1,13 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include "qwebengine_accessible.h"
+#include "qwebengine_accessible_p.h"
#include "qwebengineview.h"
#include "qwebengineview_p.h"
#include "web_contents_adapter.h"
-#if QT_CONFIG(accessibility)
-
QT_BEGIN_NAMESPACE
QWebEngineViewAccessible::QWebEngineViewAccessible(QWebEngineView *o) : QAccessibleWidget(o)
@@ -102,5 +100,3 @@ QWebEngineViewAccessible *RenderWidgetHostViewQtDelegateWidgetAccessible::viewAc
}
} // namespace QtWebEngineCore
-
-#endif // QT_CONFIG(accessibility)
diff --git a/src/webenginewidgets/qwebengine_accessible.h b/src/webenginewidgets/qwebengine_accessible_p.h
index ac87bb343..99604d90d 100644
--- a/src/webenginewidgets/qwebengine_accessible.h
+++ b/src/webenginewidgets/qwebengine_accessible_p.h
@@ -4,10 +4,19 @@
#ifndef QWEBENGINE_ACCESSIBLE_H
#define QWEBENGINE_ACCESSIBLE_H
-#include <QAccessibleWidget>
-#include <QPointer>
-
-#if QT_CONFIG(accessibility)
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QPointer>
+#include <QtWidgets/QAccessibleWidget>
QT_BEGIN_NAMESPACE
class QWebEngineView;
@@ -47,6 +56,5 @@ private:
QPointer<QWebEngineView> m_view;
};
} // namespace QtWebEngineCore
-#endif // QT_CONFIG(accessibility)
#endif // QWEBENGINE_ACCESSIBLE_H
diff --git a/src/webenginewidgets/ui/autofillpopupwidget.cpp b/src/webenginewidgets/ui/autofillpopupwidget.cpp
index 579869d9e..a4dc31beb 100644
--- a/src/webenginewidgets/ui/autofillpopupwidget.cpp
+++ b/src/webenginewidgets/ui/autofillpopupwidget.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "autofillpopupwidget_p.h"
#include "qwebengineview.h"
diff --git a/src/webenginewidgets/ui/autofillpopupwidget_p.h b/src/webenginewidgets/ui/autofillpopupwidget_p.h
index 064c4f824..79decc6ab 100644
--- a/src/webenginewidgets/ui/autofillpopupwidget_p.h
+++ b/src/webenginewidgets/ui/autofillpopupwidget_p.h
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2022 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$
-**
-****************************************************************************/
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef AUTOFILLPOPUPWIDGET_P_H
#define AUTOFILLPOPUPWIDGET_P_H
diff --git a/src/webenginewidgets/ui/touchhandlewidget.cpp b/src/webenginewidgets/ui/touchhandlewidget.cpp
new file mode 100644
index 000000000..88af0ff36
--- /dev/null
+++ b/src/webenginewidgets/ui/touchhandlewidget.cpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "touchhandlewidget_p.h"
+#include "qwebengineview.h"
+
+#include <QBoxLayout>
+#include <QGraphicsOpacityEffect>
+#include <QLabel>
+#include <QWidget>
+
+namespace QtWebEngineWidgetUI {
+TouchHandleWidget::TouchHandleWidget(QWebEngineView *view, const QMap<int, QImage> &images)
+ : m_widget(new QWidget(view))
+ , m_label(new QLabel(m_widget))
+ , m_opacityEffect(new QGraphicsOpacityEffect(m_widget))
+ , m_images(images)
+{
+ m_widget->setAttribute(Qt::WA_AcceptTouchEvents, true);
+ m_widget->setAttribute(Qt::WA_TransparentForMouseEvents, true);
+}
+
+TouchHandleWidget::~TouchHandleWidget()
+{
+}
+
+void TouchHandleWidget::setImage(int orientation)
+{
+ const QImage &img = m_images[orientation];
+ m_label->setPixmap(QPixmap::fromImage(img));
+ m_label->setFrameStyle(QFrame::NoFrame);
+ m_label->resize(img.size());
+ m_label->setVisible(true);
+
+ QVBoxLayout layout;
+ layout.setSpacing(0);
+ layout.setContentsMargins(QMargins());
+ layout.addWidget(m_label);
+ layout.setParent(m_widget);
+ m_widget->setLayout(&layout);
+ m_widget->resize(img.size());
+}
+
+void TouchHandleWidget::setBounds(const QRect &bounds)
+{
+ m_widget->setGeometry(bounds);
+}
+
+void TouchHandleWidget::setVisible(bool visible)
+{
+ m_widget->setVisible(visible);
+}
+
+void TouchHandleWidget::setOpacity(float opacity)
+{
+ m_opacityEffect->setOpacity(opacity);
+ m_widget->setGraphicsEffect(m_opacityEffect);
+}
+} // namespace QtWebEngineWidgetUI
diff --git a/src/webenginewidgets/ui/touchhandlewidget_p.h b/src/webenginewidgets/ui/touchhandlewidget_p.h
new file mode 100644
index 000000000..9f181c935
--- /dev/null
+++ b/src/webenginewidgets/ui/touchhandlewidget_p.h
@@ -0,0 +1,50 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef TOUCHHANDLEWIDGET_P_H
+#define TOUCHHANDLEWIDGET_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 "touch_handle_drawable_client.h"
+
+#include <QImage>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+class QGraphicsOpacityEffect;
+class QLabel;
+class QWebEngineView;
+class QWidget;
+QT_END_NAMESPACE
+
+namespace QtWebEngineWidgetUI {
+class TouchHandleWidget : public QtWebEngineCore::TouchHandleDrawableDelegate
+{
+public:
+ TouchHandleWidget(QWebEngineView *view, const QMap<int, QImage> &images);
+ ~TouchHandleWidget();
+
+ void setImage(int orientation) override;
+ void setBounds(const QRect &bounds) override;
+ void setVisible(bool visible) override;
+ void setOpacity(float opacity) override;
+
+private:
+ QWidget *m_widget;
+ QLabel *m_label;
+ QGraphicsOpacityEffect *m_opacityEffect;
+ QMap<int, QImage> m_images;
+};
+} // namespace QtWebEngineWidgetUI
+
+#endif // TOUCHHANDLEWIDGET_P_H
diff --git a/src/webenginewidgets/ui/touchselectionmenuwidget.cpp b/src/webenginewidgets/ui/touchselectionmenuwidget.cpp
new file mode 100644
index 000000000..ff69fe84b
--- /dev/null
+++ b/src/webenginewidgets/ui/touchselectionmenuwidget.cpp
@@ -0,0 +1,117 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "touchselectionmenuwidget_p.h"
+#include "qwebengineview.h"
+
+#include "touch_selection_menu_controller.h"
+
+#include <QBoxLayout>
+#include <QEvent>
+
+namespace QtWebEngineWidgetUI {
+namespace {
+// The Widgets module is built with rtti in developer-build while Core is not.
+// The MOC will throw "undefined reference to typeinfo..." errors if we connect slots
+// from QtWebEngineCore via function pointers, because it expects rtti on them.
+// To workaround this we use lambdas.
+void connectButton(TouchSelectionMenuWidget::TouchButton *button, std::function<void()> callback)
+{
+ QObject::connect(button, &QPushButton::clicked, std::move(callback));
+}
+} // namespace
+
+TouchSelectionMenuWidget::TouchButton::TouchButton(QString name, QWidget *parent)
+ : QPushButton(name, parent)
+{
+ setAttribute(Qt::WA_AcceptTouchEvents, true);
+}
+
+TouchSelectionMenuWidget::TouchButton::~TouchButton()
+{
+}
+
+bool TouchSelectionMenuWidget::TouchButton::event(QEvent *ev)
+{
+ switch (ev->type()) {
+ case QEvent::TouchBegin:
+ ev->accept();
+ return true;
+ case QEvent::TouchEnd:
+ Q_EMIT clicked();
+ ev->accept();
+ return true;
+ default:
+ break;
+ }
+
+ return QPushButton::event(ev);
+}
+
+TouchSelectionMenuWidget::TouchSelectionMenuWidget(
+ QWebEngineView *view, QtWebEngineCore::TouchSelectionMenuController *controller)
+ : QWidget(view,
+ Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint
+ | Qt::WindowDoesNotAcceptFocus)
+{
+ setAttribute(Qt::WA_AcceptTouchEvents, true);
+ setAttribute(Qt::WA_TransparentForMouseEvents, true);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+
+ bool cutEnabled =
+ controller->isCommandEnabled(QtWebEngineCore::TouchSelectionMenuController::Cut);
+ bool copyEnabled =
+ controller->isCommandEnabled(QtWebEngineCore::TouchSelectionMenuController::Copy);
+ bool pasteEnabled =
+ controller->isCommandEnabled(QtWebEngineCore::TouchSelectionMenuController::Paste);
+
+ QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ QHBoxLayout *layout = new QHBoxLayout();
+
+ if (cutEnabled) {
+ TouchButton *button = new TouchButton(tr("Cut"), this);
+ button->setSizePolicy(policy);
+ layout->addWidget(button);
+ connectButton(button, [controller]() { controller->cut(); });
+ }
+
+ if (copyEnabled) {
+ TouchButton *button = new TouchButton(tr("Copy"), this);
+ button->setSizePolicy(policy);
+ layout->addWidget(button);
+ connectButton(button, [controller]() { controller->copy(); });
+ }
+
+ if (pasteEnabled) {
+ TouchButton *button = new TouchButton(tr("Paste"), this);
+ button->setSizePolicy(policy);
+ layout->addWidget(button);
+ connectButton(button, [controller]() { controller->paste(); });
+ }
+
+ TouchButton *button = new TouchButton(tr("..."), this);
+ button->setSizePolicy(policy);
+ layout->addWidget(button);
+ connectButton(button, [controller]() { controller->runContextMenu(); });
+
+ layout->setSpacing(2);
+ layout->setSizeConstraint(QLayout::SetMinimumSize);
+ layout->setContentsMargins(0, 0, 0, 0);
+ setLayout(layout);
+
+ nativeParentWidget()->installEventFilter(this);
+}
+
+TouchSelectionMenuWidget::~TouchSelectionMenuWidget()
+{
+}
+
+bool TouchSelectionMenuWidget::eventFilter(QObject *obj, QEvent *ev)
+{
+ // Close the menu if the window is moved
+ if (ev->type() == QEvent::Move)
+ close();
+
+ return QWidget::eventFilter(obj, ev);
+}
+} // QtWebEngineWidgetUI
diff --git a/src/webenginewidgets/ui/touchselectionmenuwidget_p.h b/src/webenginewidgets/ui/touchselectionmenuwidget_p.h
new file mode 100644
index 000000000..1f822023b
--- /dev/null
+++ b/src/webenginewidgets/ui/touchselectionmenuwidget_p.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef TOUCHSELECTIONMENUWIDGET_P_H
+#define TOUCHSELECTIONMENUWIDGET_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 <QPushButton>
+#include <QWidget>
+
+namespace QtWebEngineCore {
+class TouchSelectionMenuController;
+}
+
+QT_BEGIN_NAMESPACE
+class QWebEngineView;
+QT_END_NAMESPACE
+
+namespace QtWebEngineWidgetUI {
+class TouchSelectionMenuWidget : public QWidget
+{
+public:
+ class TouchButton : public QPushButton
+ {
+ public:
+ TouchButton(QString name, QWidget *parent);
+ ~TouchButton();
+
+ protected:
+ bool event(QEvent *ev) override;
+ };
+
+ TouchSelectionMenuWidget(QWebEngineView *view,
+ QtWebEngineCore::TouchSelectionMenuController *controller);
+ ~TouchSelectionMenuWidget();
+
+protected:
+ bool eventFilter(QObject *obj, QEvent *ev) override;
+};
+} // namespace QtWebEngineWidgetUI
+
+#endif // TOUCHSELECTIONMENUWIDGET_P_H