diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/core/api/qwebenginepage.cpp | 58 | ||||
-rw-r--r-- | src/core/api/qwebenginepage_p.h | 10 | ||||
-rw-r--r-- | src/core/render_widget_host_view_qt.cpp | 2 | ||||
-rw-r--r-- | src/core/render_widget_host_view_qt_delegate.h | 2 | ||||
-rw-r--r-- | src/core/render_widget_host_view_qt_delegate_item.cpp | 442 | ||||
-rw-r--r-- | src/core/render_widget_host_view_qt_delegate_item.h | 161 | ||||
-rw-r--r-- | src/core/web_contents_delegate_qt.cpp | 4 |
8 files changed, 627 insertions, 53 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e9951d187..18078ba5a 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -160,6 +160,7 @@ foreach(arch ${archs}) render_widget_host_view_qt.cpp render_widget_host_view_qt.h render_widget_host_view_qt_delegate.h render_widget_host_view_qt_delegate_client.cpp render_widget_host_view_qt_delegate_client.h + render_widget_host_view_qt_delegate_item.cpp render_widget_host_view_qt_delegate_item.h renderer/content_renderer_client_qt.cpp renderer/content_renderer_client_qt.h renderer/content_settings_observer_qt.cpp renderer/content_settings_observer_qt.h renderer/render_configuration.cpp renderer/render_configuration.h diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 0b3cba785..a893d5a80 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -67,6 +67,7 @@ #include "render_view_context_menu_qt.h" #include "render_widget_host_view_qt_delegate.h" #include "render_widget_host_view_qt_delegate_client.h" +#include "render_widget_host_view_qt_delegate_item.h" #include "web_contents_adapter.h" #include <QAction> @@ -84,51 +85,6 @@ QT_BEGIN_NAMESPACE using namespace QtWebEngineCore; -// add temporary dummy code to cover the case when page is loading and there is no view -class DummyDelegate : public QObject, public QtWebEngineCore::RenderWidgetHostViewQtDelegate -{ -public: - DummyDelegate(RenderWidgetHostViewQtDelegateClient *client) : m_delegateClient(client) {}; - ~DummyDelegate() = default; - void initAsPopup(const QRect &) override { Q_UNREACHABLE(); } - QRectF viewGeometry() const override { return QRectF(m_pos, m_size); } - void setKeyboardFocus() override { } - bool hasKeyboardFocus() override { return false; } - void lockMouse() override { Q_UNREACHABLE(); } - void unlockMouse() override { Q_UNREACHABLE(); } - void show() override { m_delegateClient->notifyShown(); } - void hide() override { m_delegateClient->notifyHidden(); } - bool isVisible() const override { Q_UNREACHABLE(); } - QWindow *window() const override { return nullptr; } - void updateCursor(const QCursor &cursor) override - { - Q_UNUSED(cursor); - /*setCursor(cursor);*/ - } - void resize(int width, int height) override - { - m_size = QSize(width, height); - m_delegateClient->visualPropertiesChanged(); - } - void move(const QPoint &) override { Q_UNREACHABLE(); } - void inputMethodStateChanged(bool, bool) override { } - void setInputMethodHints(Qt::InputMethodHints) override { } - void setClearColor(const QColor &) override { } - void adapterClientChanged(WebContentsAdapterClient *) override { } - bool copySurface(const QRect &, const QSize &, QImage &) - { - Q_UNREACHABLE(); - return false; - } - QRect windowGeometry() const override { return QRect(m_pos, m_size); } - bool forwardEvent(QEvent *ev) { return m_delegateClient->forwardEvent(ev); } - -private: - RenderWidgetHostViewQtDelegateClient *m_delegateClient; - QPoint m_pos; - QSize m_size; -}; - static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) { switch (disposition) { @@ -202,6 +158,14 @@ QWebEnginePagePrivate::~QWebEnginePagePrivate() RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client) { + item = view + ? (QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *)view->CreateRenderWidgetHostViewQtDelegate(client) + : new QtWebEngineCore::RenderWidgetHostViewQtDelegateItem(client, false); + return item; +} + +RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegateForPopup(RenderWidgetHostViewQtDelegateClient *client) +{ // Set the QWebEngineView as the parent for a popup delegate, so that the new popup window // responds properly to clicks in case the QWebEngineView is inside a modal QDialog. Setting the // parent essentially notifies the OS that the popup window is part of the modal session, and @@ -209,7 +173,9 @@ RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostVie // The new delegate will not be deleted by the parent view though, because we unset the parent // when the parent is destroyed. The delegate will be destroyed by Chromium when the popup is // dismissed. - return view ? view->CreateRenderWidgetHostViewQtDelegate(client) : new DummyDelegate(client); + return view + ? view->CreateRenderWidgetHostViewQtDelegateForPopup(client) + : new QtWebEngineCore::RenderWidgetHostViewQtDelegateItem(client, true); } void QWebEnginePagePrivate::initializationFinished() diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 785930127..2b76795b5 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -62,11 +62,12 @@ namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegate; -class RenderWidgetHostViewQtDelegateWidget; class RenderWidgetHostViewQtDelegateClient; +class RenderWidgetHostViewQtDelegateItem; class TouchHandleDrawableDelegate; class TouchSelectionMenuController; class WebContentsAdapter; +class WidgetDelegate; } QT_BEGIN_NAMESPACE @@ -94,6 +95,8 @@ public: virtual void setToolTip(const QString &toolTipText) = 0; virtual QtWebEngineCore::RenderWidgetHostViewQtDelegate *CreateRenderWidgetHostViewQtDelegate( QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) = 0; + virtual QtWebEngineCore::RenderWidgetHostViewQtDelegate *CreateRenderWidgetHostViewQtDelegateForPopup( + QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) = 0; virtual QWebEngineContextMenuRequest *lastContextMenuRequest() const = 0; virtual QWebEnginePage *createPageForWindow(QWebEnginePage::WebWindowType type) = 0; virtual bool isEnabled() const = 0; @@ -118,7 +121,7 @@ public: ~QWebEnginePagePrivate(); QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegate(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; - QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override { return CreateRenderWidgetHostViewQtDelegate(client); } + QtWebEngineCore::RenderWidgetHostViewQtDelegate* CreateRenderWidgetHostViewQtDelegateForPopup(QtWebEngineCore::RenderWidgetHostViewQtDelegateClient *client) override; void initializationFinished() override; void lifecycleStateChanged(LifecycleState state) override; void recommendedStateChanged(LifecycleState state) override; @@ -227,7 +230,8 @@ public: bool defaultAudioMuted; qreal defaultZoomFactor; QTimer wasShownTimer; - QtWebEngineCore::RenderWidgetHostViewQtDelegateWidget *widget = nullptr; + QtWebEngineCore::WidgetDelegate *widget = nullptr; + QtWebEngineCore::RenderWidgetHostViewQtDelegateItem *item = nullptr; #if QT_CONFIG(webengine_printing_and_pdf) QPrinter *currentPrinter = nullptr; #endif diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 572468bc8..d15381d66 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -894,7 +894,7 @@ bool RenderWidgetHostViewQt::isPopup() const bool RenderWidgetHostViewQt::updateScreenInfo() { display::ScreenInfo oldScreenInfo = m_screenInfo; - QScreen *screen = m_delegate->window() ? m_delegate->window()->screen() : nullptr; + QScreen *screen = m_delegate->Window() ? m_delegate->Window()->screen() : nullptr; m_screenInfo = screenInfoFromQScreen(screen); return (m_screenInfo != oldScreenInfo); diff --git a/src/core/render_widget_host_view_qt_delegate.h b/src/core/render_widget_host_view_qt_delegate.h index 1df1322c7..66a9d7161 100644 --- a/src/core/render_widget_host_view_qt_delegate.h +++ b/src/core/render_widget_host_view_qt_delegate.h @@ -78,7 +78,7 @@ public: virtual void show() = 0; virtual void hide() = 0; virtual bool isVisible() const = 0; - virtual QWindow* window() const = 0; + virtual QWindow *Window() const = 0; virtual void updateCursor(const QCursor &) = 0; virtual void resize(int width, int height) = 0; virtual void move(const QPoint &) = 0; diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp new file mode 100644 index 000000000..75ed57271 --- /dev/null +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -0,0 +1,442 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "render_widget_host_view_qt_delegate_item.h" + +#include "render_widget_host_view_qt_delegate_client.h" + +#include <QGuiApplication> +#include <QMouseEvent> +#include <QSGImageNode> +#include <QWindow> + +namespace QtWebEngineCore { + +RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) + : m_client(client) + , m_isPopup(isPopup) +{ + setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + setAcceptHoverEvents(true); + setAcceptTouchEvents(true); + if (!isPopup) { + setFocus(true); + setActiveFocusOnTab(true); + } + bind(client->compositorId()); +} + +RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem() +{ + if (m_widgetDelegate) { + m_widgetDelegate->Unbind(); + m_widgetDelegate->Destroy(); + } +} + +void RenderWidgetHostViewQtDelegateItem::initAsPopup(const QRect &screenRect) +{ + Q_ASSERT(m_isPopup); + setSize(screenRect.size()); + if (m_widgetDelegate) + m_widgetDelegate->InitAsPopup(screenRect); +} + +QRectF RenderWidgetHostViewQtDelegateItem::viewGeometry() const +{ + // Transform the entire rect to find the correct top left corner. + const QPointF p1 = mapToGlobal(mapFromScene(QPointF(0, 0))); + const QPointF p2 = mapToGlobal(mapFromScene(QPointF(width(), height()))); + QRectF geometry = QRectF(p1, p2).normalized(); + // But keep the size untransformed to behave like other QQuickItems. + geometry.setSize(size()); + return geometry; +} + +QRect RenderWidgetHostViewQtDelegateItem::windowGeometry() const +{ + if (!Window()) + return QRect(); + return Window()->frameGeometry(); +} + +void RenderWidgetHostViewQtDelegateItem::setKeyboardFocus() +{ + setFocus(true); +} + +bool RenderWidgetHostViewQtDelegateItem::hasKeyboardFocus() +{ + return hasActiveFocus(); +} + +void RenderWidgetHostViewQtDelegateItem::lockMouse() +{ + grabMouse(); +} + +void RenderWidgetHostViewQtDelegateItem::unlockMouse() +{ + ungrabMouse(); +} + +void RenderWidgetHostViewQtDelegateItem::show() +{ + if (isVisible()) + m_client->notifyShown(); + else + setVisible(true); +} + +void RenderWidgetHostViewQtDelegateItem::hide() +{ + if (isVisible()) + setVisible(false); + else + m_client->notifyHidden(); +} + +bool RenderWidgetHostViewQtDelegateItem::isVisible() const +{ + return QQuickItem::isVisible(); +} + +QWindow *RenderWidgetHostViewQtDelegateItem::Window() const +{ + if (m_widgetDelegate) { + if (auto *window = m_widgetDelegate->Window()) + return window; + } + return QQuickItem::window(); +} + +void RenderWidgetHostViewQtDelegateItem::readyToSwap() +{ + // Call update() on UI thread. + QMetaObject::invokeMethod(this, &QQuickItem::update, Qt::QueuedConnection); +} + +void RenderWidgetHostViewQtDelegateItem::updateCursor(const QCursor &cursor) +{ + setCursor(cursor); +} + +void RenderWidgetHostViewQtDelegateItem::resize(int width, int height) +{ + setSize(QSizeF(width, height)); + if (m_widgetDelegate) + m_widgetDelegate->Resize(width, height); +} + +void RenderWidgetHostViewQtDelegateItem::move(const QPoint &point) +{ + if (m_widgetDelegate && m_isPopup) + m_widgetDelegate->MoveWindow(point); +} + +void RenderWidgetHostViewQtDelegateItem::inputMethodStateChanged(bool editorVisible, bool passwordInput) +{ + setFlag(QQuickItem::ItemAcceptsInputMethod, editorVisible && !passwordInput); + + if (parentItem()) + parentItem()->setFlag(QQuickItem::ItemAcceptsInputMethod, editorVisible && !passwordInput); + + if (m_widgetDelegate) + m_widgetDelegate->SetInputMethodEnabled(editorVisible && !passwordInput); + + qApp->inputMethod()->update(Qt::ImQueryInput | Qt::ImEnabled | Qt::ImHints); + if (qApp->inputMethod()->isVisible() != editorVisible) + qApp->inputMethod()->setVisible(editorVisible); +} + +void RenderWidgetHostViewQtDelegateItem::setWidgetDelegate(WidgetDelegate *delegate) +{ + Q_ASSERT(!m_widgetDelegate || !delegate); + m_widgetDelegate = delegate; + if (m_widgetDelegate) { + if (m_inputMethodHints) + m_widgetDelegate->SetInputMethodHints(m_inputMethodHints); + if (m_clearColor.isValid()) + m_widgetDelegate->SetClearColor(m_clearColor); + if (flags().testFlag(QQuickItem::ItemAcceptsInputMethod)) + m_widgetDelegate->SetInputMethodEnabled(true); + if (m_adapterClient) + m_widgetDelegate->Bind(m_adapterClient); + } +} + +void RenderWidgetHostViewQtDelegateItem::setInputMethodHints(Qt::InputMethodHints hints) +{ + m_inputMethodHints = hints; + if (m_widgetDelegate) + m_widgetDelegate->SetInputMethodHints(hints); +} + +void RenderWidgetHostViewQtDelegateItem::setClearColor(const QColor &color) +{ + m_clearColor = color; + if (m_widgetDelegate) + m_widgetDelegate->SetClearColor(color); +} + +bool RenderWidgetHostViewQtDelegateItem::event(QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) + return m_client->forwardEvent(event); + +#if QT_CONFIG(gestures) + if (event->type() == QEvent::NativeGesture) + return m_client->forwardEvent(event); +#endif + + return QQuickItem::event(event); +} + +void RenderWidgetHostViewQtDelegateItem::focusInEvent(QFocusEvent *event) +{ +#if QT_CONFIG(accessibility) + if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(this)) { + if (auto *focusChild = iface->focusChild()) { + QAccessibleEvent focusEvent(focusChild, QAccessible::Focus); + QAccessible::updateAccessibility(&focusEvent); + } + } +#endif // QT_CONFIG(accessibility) + + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::focusOutEvent(QFocusEvent *event) +{ + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::mousePressEvent(QMouseEvent *event) +{ + if (!m_isPopup && m_widgetDelegate) { + if (m_widgetDelegate->ActiveFocusOnPress()) { + forceActiveFocus(); + } else { + event->ignore(); + return; + } + } + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::mouseMoveEvent(QMouseEvent *event) +{ + if (!m_isPopup && m_widgetDelegate && !m_widgetDelegate->ActiveFocusOnPress()) { + event->ignore(); + return; + } + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::mouseReleaseEvent(QMouseEvent *event) +{ + if (!m_isPopup && m_widgetDelegate && !m_widgetDelegate->ActiveFocusOnPress()) { + event->ignore(); + return; + } + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::keyPressEvent(QKeyEvent *event) +{ + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::keyReleaseEvent(QKeyEvent *event) +{ + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::wheelEvent(QWheelEvent *event) +{ + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::touchEvent(QTouchEvent *event) +{ + if (!m_isPopup && m_widgetDelegate) { + if (event->type() == QEvent::TouchBegin && m_widgetDelegate->ActiveFocusOnPress()) + forceActiveFocus(); + + if (!m_widgetDelegate->ActiveFocusOnPress()) { + event->ignore(); + return; + } + } + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::hoverMoveEvent(QHoverEvent *event) +{ + if ((!m_isPopup && m_widgetDelegate && !m_widgetDelegate->ActiveFocusOnPress()) + || event->position() == event->oldPosF()) { + event->ignore(); + return; + } + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::hoverLeaveEvent(QHoverEvent *event) +{ + m_client->forwardEvent(event); +} + +QVariant RenderWidgetHostViewQtDelegateItem::inputMethodQuery(Qt::InputMethodQuery query) const +{ + return m_client->inputMethodQuery(query); +} + +void RenderWidgetHostViewQtDelegateItem::inputMethodEvent(QInputMethodEvent *event) +{ + m_client->forwardEvent(event); +} + +void RenderWidgetHostViewQtDelegateItem::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) +{ + QQuickItem::geometryChange(newGeometry, oldGeometry); + m_client->visualPropertiesChanged(); +} + +void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const ItemChangeData &value) +{ + QQuickItem::itemChange(change, value); + if (change == QQuickItem::ItemSceneChange) { + for (const QMetaObject::Connection &c : qAsConst(m_windowConnections)) + disconnect(c); + m_windowConnections.clear(); + if (value.window) { + m_windowConnections.append(connect(value.window, &QQuickWindow::beforeRendering, + this, &RenderWidgetHostViewQtDelegateItem::onBeforeRendering, Qt::DirectConnection)); + m_windowConnections.append(connect(value.window, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged()))); + m_windowConnections.append(connect(value.window, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged()))); + if (!m_isPopup) + m_windowConnections.append(connect(value.window, SIGNAL(closing(QQuickCloseEvent *)), SLOT(onHide()))); + } + m_client->visualPropertiesChanged(); + } else if (change == QQuickItem::ItemVisibleHasChanged) { + if (value.boolValue) { + m_client->notifyShown(); + } else { + m_client->notifyHidden(); + if (!m_isPopup) + onHide(); + } + } +} + +QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + auto comp = compositor(); + if (!comp) + return nullptr; + + QQuickWindow *win = QQuickItem::window(); + + // Delete old node before swapFrame to decrement refcount of + // QImage in software mode. + delete oldNode; + QSGImageNode *node = win->createImageNode(); + node->setOwnsTexture(true); + + comp->swapFrame(); + + QSize texSize = comp->size(); + QSizeF texSizeInDips = QSizeF(texSize) / comp->devicePixelRatio(); + node->setRect(QRectF(QPointF(0, 0), texSizeInDips)); + + if (comp->type() == Compositor::Type::Software) { + QImage image = comp->image(); + node->setTexture(win->createTextureFromImage(image)); +#if QT_CONFIG(opengl) + } else if (comp->type() == Compositor::Type::OpenGL) { + QQuickWindow::CreateTextureOptions texOpts; + if (comp->hasAlphaChannel()) + texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel); + int texId = comp->textureId(); + node->setTexture(QNativeInterface::QSGOpenGLTexture::fromNative(texId, win, texSize, texOpts)); + node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically); +#endif + } else { + Q_UNREACHABLE(); + } + + return node; +} + +void RenderWidgetHostViewQtDelegateItem::onBeforeRendering() +{ + auto comp = compositor(); + if (!comp || comp->type() != Compositor::Type::OpenGL) + return; + comp->waitForTexture(); +} + +void RenderWidgetHostViewQtDelegateItem::onWindowPosChanged() +{ + m_client->visualPropertiesChanged(); +} + +void RenderWidgetHostViewQtDelegateItem::onHide() +{ + QFocusEvent event(QEvent::FocusOut, Qt::OtherFocusReason); + m_client->forwardEvent(&event); +} + +void RenderWidgetHostViewQtDelegateItem::adapterClientChanged(WebContentsAdapterClient *client) +{ + m_adapterClient = client; + if (m_widgetDelegate) + m_widgetDelegate->Bind(client); +} + +void RenderWidgetHostViewQtDelegateItem::unhandledWheelEvent(QWheelEvent *ev) +{ + if (QWindow *w = Window()) { + if (QWindow *p = w->parent()) + qApp->sendEvent(p, ev); + } +} + +} // namespace QtWebEngineCore diff --git a/src/core/render_widget_host_view_qt_delegate_item.h b/src/core/render_widget_host_view_qt_delegate_item.h new file mode 100644 index 000000000..515f2b28c --- /dev/null +++ b/src/core/render_widget_host_view_qt_delegate_item.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_ITEM_H +#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_ITEM_H + +#include "compositor/compositor.h" +#include "render_widget_host_view_qt_delegate.h" + +#include <QtQuick/QQuickItem> + +QT_BEGIN_NAMESPACE +class QQuickWebEngineView; +class QQuickWebEngineViewPrivate; +class QWebEnginePage; +class QWebEngineViewPrivate; +QT_END_NAMESPACE + +namespace QtWebEngineCore { + +class RenderWidgetHostViewQtDelegateClient; +class WebContentsAdapterClient; +class WebEngineQuickWidget; + +class WidgetDelegate +{ +public: + virtual ~WidgetDelegate() = default; + virtual void InitAsPopup(const QRect &screenRect) = 0; + virtual void SetInputMethodEnabled(bool) { } + virtual void SetInputMethodHints(Qt::InputMethodHints) { } + virtual void SetClearColor(const QColor &) { } + virtual bool ActiveFocusOnPress() = 0; + virtual void MoveWindow(const QPoint & ) { } + virtual void Bind(WebContentsAdapterClient *) = 0; + virtual void Unbind() = 0; + virtual void Destroy() = 0; + virtual void Resize(int, int) { } + virtual QWindow *Window() { return nullptr; } +}; + +// Useful information keyboard and mouse QEvent propagation. +// A RenderWidgetHostViewQtDelegateItem instance initialized as a popup will receive +// no keyboard focus (so all keyboard QEvents will be sent to the parent RWHVQD instance), +// but will still receive mouse input (all mouse QEvent moves and clicks will be given to the popup +// RWHVQD instance, and the mouse interaction area covers the surface of the whole parent +// QWebEngineView, and not only the smaller surface that an HTML select popup would occupy). +class Q_WEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegateItem + : public QQuickItem + , public RenderWidgetHostViewQtDelegate + , public Compositor::Observer +{ + Q_OBJECT +public: + RenderWidgetHostViewQtDelegateItem(RenderWidgetHostViewQtDelegateClient *client, bool isPopup); + ~RenderWidgetHostViewQtDelegateItem(); + + void initAsPopup(const QRect&) override; + QRectF viewGeometry() const override; + QRect windowGeometry() const override; + void setKeyboardFocus() override; + bool hasKeyboardFocus() override; + void lockMouse() override; + void unlockMouse() override; + void show() override; + void hide() override; + bool isVisible() const override; + QWindow *Window() const override; + void updateCursor(const QCursor &) override; + void resize(int width, int height) override; + void move(const QPoint &screenPos) override; + void inputMethodStateChanged(bool editorVisible, bool passwordInput) override; + void setInputMethodHints(Qt::InputMethodHints) override; + void setClearColor(const QColor &color) override; + void unhandledWheelEvent(QWheelEvent *ev) override; + + void readyToSwap() override; + + void setWidgetDelegate(WidgetDelegate *delegate); + +protected: + bool event(QEvent *event) override; + void focusInEvent(QFocusEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; + void keyReleaseEvent(QKeyEvent *event) override; + void wheelEvent(QWheelEvent *event) override; + void touchEvent(QTouchEvent *event) override; + void hoverMoveEvent(QHoverEvent *event) override; + void hoverLeaveEvent(QHoverEvent *event) override; + QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; + void inputMethodEvent(QInputMethodEvent *event) override; + void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; + void itemChange(ItemChange change, const ItemChangeData &value) override; + QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) override; + + void adapterClientChanged(WebContentsAdapterClient *client) override; + +private Q_SLOTS: + void onBeforeRendering(); + void onWindowPosChanged(); + void onHide(); + +private: + friend QWebEngineViewPrivate; + friend QQuickWebEngineViewPrivate; + friend WebEngineQuickWidget; + + RenderWidgetHostViewQtDelegateClient *m_client; + bool m_isPopup; + QColor m_clearColor; + Qt::InputMethodHints m_inputMethodHints = {}; + QList<QMetaObject::Connection> m_windowConnections; + WebContentsAdapterClient *m_adapterClient = nullptr; + QWebEnginePage *m_page = nullptr; + QQuickWebEngineView *m_view = nullptr; + WidgetDelegate *m_widgetDelegate = nullptr; +}; + +} // namespace QtWebEngineCore + +#endif // RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_ITEM_H diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 292043f78..bbd15a35d 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -629,8 +629,8 @@ void WebContentsDelegateQt::SetContentsBounds(content::WebContents *source, cons QRect frameGeometry(toQt(bounds)); QRect geometry; if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView())) { - if (rwhv->delegate() && rwhv->delegate()->window()) - geometry = frameGeometry.marginsRemoved(rwhv->delegate()->window()->frameMargins()); + if (rwhv->delegate() && rwhv->delegate()->Window()) + geometry = frameGeometry.marginsRemoved(rwhv->delegate()->Window()->frameMargins()); } m_viewClient->requestGeometryChange(geometry, frameGeometry); } |