From 828ee197647a7462c10243c0261e7bced9bbcb65 Mon Sep 17 00:00:00 2001 From: Balazs Egedi Date: Fri, 18 Feb 2022 13:04:19 +0100 Subject: Quick: Add support for replacing touch handles with delegates Task-number: QTBUG-85043 Change-Id: I1c87aff352e07eb309d5ba8747b9e50a191d478e Reviewed-by: Michal Klocek --- examples/webenginequick/CMakeLists.txt | 1 + .../customtouchhandle/CMakeLists.txt | 45 +++++++ .../customtouchhandle/customtouchhandle.pro | 10 ++ .../doc/images/customtouchhandle.jpg | Bin 0 -> 47646 bytes .../doc/src/customtouchhandle.qdoc | 66 ++++++++++ examples/webenginequick/customtouchhandle/main.cpp | 66 ++++++++++ examples/webenginequick/customtouchhandle/main.qml | 143 +++++++++++++++++++++ examples/webenginequick/customtouchhandle/qml.qrc | 5 + examples/webenginequick/webenginequick.pro | 1 + src/core/api/qwebenginepage_p.h | 5 +- src/core/render_widget_host_view_qt.cpp | 17 ++- src/core/render_widget_host_view_qt.h | 2 + src/core/touch_handle_drawable_client.h | 4 +- src/core/touch_handle_drawable_qt.cpp | 74 +++++------ src/core/touch_handle_drawable_qt.h | 9 +- src/core/touch_selection_controller_client_qt.cpp | 21 ++- src/core/touch_selection_controller_client_qt.h | 3 + src/core/web_contents_adapter.cpp | 8 ++ src/core/web_contents_adapter.h | 1 + src/core/web_contents_adapter_client.h | 4 +- src/webenginequick/CMakeLists.txt | 1 + .../api/qquickwebenginecustomtouchhandle.cpp | 83 ++++++++++++ .../api/qquickwebenginecustomtouchhandle_p.h | 89 +++++++++++++ src/webenginequick/api/qquickwebengineview.cpp | 71 +++++++--- src/webenginequick/api/qquickwebengineview_p.h | 7 + src/webenginequick/api/qquickwebengineview_p_p.h | 11 +- .../doc/src/custom_touch_handle.qdoc | 52 ++++++++ src/webenginequick/doc/src/webengineview_lgpl.qdoc | 10 ++ src/webenginequick/ui_delegates_manager.cpp | 2 +- src/webenginequick/ui_delegates_manager.h | 1 + tests/auto/quick/publicapi/tst_publicapi.cpp | 5 +- 31 files changed, 735 insertions(+), 82 deletions(-) create mode 100644 examples/webenginequick/customtouchhandle/CMakeLists.txt create mode 100644 examples/webenginequick/customtouchhandle/customtouchhandle.pro create mode 100644 examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpg create mode 100644 examples/webenginequick/customtouchhandle/doc/src/customtouchhandle.qdoc create mode 100644 examples/webenginequick/customtouchhandle/main.cpp create mode 100644 examples/webenginequick/customtouchhandle/main.qml create mode 100644 examples/webenginequick/customtouchhandle/qml.qrc create mode 100644 src/webenginequick/api/qquickwebenginecustomtouchhandle.cpp create mode 100644 src/webenginequick/api/qquickwebenginecustomtouchhandle_p.h create mode 100644 src/webenginequick/doc/src/custom_touch_handle.qdoc diff --git a/examples/webenginequick/CMakeLists.txt b/examples/webenginequick/CMakeLists.txt index 8105b6c9a..dc42b3dfe 100644 --- a/examples/webenginequick/CMakeLists.txt +++ b/examples/webenginequick/CMakeLists.txt @@ -1,4 +1,5 @@ qt_internal_add_example(customdialogs) +qt_internal_add_example(customtouchhandle) qt_internal_add_example(lifecycle) qt_internal_add_example(minimal) qt_internal_add_example(quicknanobrowser) diff --git a/examples/webenginequick/customtouchhandle/CMakeLists.txt b/examples/webenginequick/customtouchhandle/CMakeLists.txt new file mode 100644 index 000000000..5062e5d53 --- /dev/null +++ b/examples/webenginequick/customtouchhandle/CMakeLists.txt @@ -0,0 +1,45 @@ +cmake_minimum_required(VERSION 3.16) +project(customtouchhandle LANGUAGES CXX) + +set(CMAKE_AUTOMOC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginequick/customtouchhandle") + +find_package(Qt6 COMPONENTS Core Gui WebEngineQuick) + +qt_add_executable(customtouchhandle + main.cpp +) + +set_target_properties(customtouchhandle PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) + +target_link_libraries(customtouchhandle PUBLIC + Qt::Core + Qt::Gui + Qt::WebEngineQuick +) + +# Resources: +set(qml_resource_files + "main.qml" +) + +qt6_add_resources(customtouchhandle "qml" + PREFIX + "/" + FILES + ${qml_resource_files} +) + +install(TARGETS customtouchhandle + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/webenginequick/customtouchhandle/customtouchhandle.pro b/examples/webenginequick/customtouchhandle/customtouchhandle.pro new file mode 100644 index 000000000..a74ef3146 --- /dev/null +++ b/examples/webenginequick/customtouchhandle/customtouchhandle.pro @@ -0,0 +1,10 @@ +TEMPLATE = app + +QT += webenginequick + +SOURCES += main.cpp + +RESOURCES += qml.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginequick/customtouchhandle +INSTALLS += target diff --git a/examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpg b/examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpg new file mode 100644 index 000000000..bd65c083d Binary files /dev/null and b/examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpg differ diff --git a/examples/webenginequick/customtouchhandle/doc/src/customtouchhandle.qdoc b/examples/webenginequick/customtouchhandle/doc/src/customtouchhandle.qdoc new file mode 100644 index 000000000..5b39e7973 --- /dev/null +++ b/examples/webenginequick/customtouchhandle/doc/src/customtouchhandle.qdoc @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webenginequick/customtouchhandle + \title WebEngine Qt Quick Custom Touch Handle Example + \ingroup webengine-examples + \brief Shows custom touch handles upon touch selection events. + + \image customtouchhandle.jpg + + \e {WebEngine Qt Quick Touch Handle Example} demonstrates how to use + custom touch handles when a touch selection event happens. It shows the + minimum amount of code needed to use custom touch handle delegates, and + can be used as a basis for further experimentation. + + \section1 Custom Touch Handle + + In \c main.qml we create the custom touch handle delegate. + + \quotefromfile webenginequick/customtouchhandle/main.qml + \skipto WebEngineView + \printuntil /^\ {4}\}/ + + \section1 QML Code + + In \c main.qml we create the top level window filled by a + \l{WebEngineView} item loading the \l{Qt Homepage}. + To display custom touch handles, a QML item should be delegated to + \l{WebEngineView::touchHandleDelegate}. + + The touch handle's position, opacity, and visibility is automatically updated. + + \note If no delegate is provided, Chromium's default touch handles will appear. + + \section1 Requirements + + The example requires a working internet connection to render the + \l{Qt Homepage} and a touch-enabled input device to trigger touch + events. + An optional system proxy should be picked up automatically. +*/ diff --git a/examples/webenginequick/customtouchhandle/main.cpp b/examples/webenginequick/customtouchhandle/main.cpp new file mode 100644 index 000000000..2739e1ad0 --- /dev/null +++ b/examples/webenginequick/customtouchhandle/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication::setOrganizationName("QtExamples"); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + QtWebEngineQuick::initialize(); + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); +} diff --git a/examples/webenginequick/customtouchhandle/main.qml b/examples/webenginequick/customtouchhandle/main.qml new file mode 100644 index 000000000..478b59a0e --- /dev/null +++ b/examples/webenginequick/customtouchhandle/main.qml @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** 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. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Window +import QtWebEngine +import QtQuick.Layouts +import QtQuick.Controls + +ApplicationWindow { + width: 1024 + height: 750 + visible: true + header: ToolBar { + RowLayout { + anchors.fill: parent + + ToolButton { + property int itemAction: WebEngineView.Back + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: WebEngineView.Forward + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + ToolButton { + property int itemAction: webEngineView.loading ? WebEngineView.Stop : WebEngineView.Reload + text: webEngineView.action(itemAction).text + enabled: webEngineView.action(itemAction).enabled + onClicked: webEngineView.action(itemAction).trigger() + icon.name: webEngineView.action(itemAction).iconName + display: AbstractButton.TextUnderIcon + } + + TextField { + Layout.fillWidth: true + text: webEngineView.url + selectByMouse: true + onEditingFinished: webEngineView.url = text + } + + Label { text: 'Handle: ' } + ComboBox { + model: [ 'Default', 'Circle', 'Square' ] + + onCurrentValueChanged: { + if (currentValue == 'Circle') + webEngineView.touchHandleDelegate = circleTouchHandle + else if (currentValue == 'Square') + webEngineView.touchHandleDelegate = rectTouchHandle + else + webEngineView.touchHandleDelegate = null + } + + Component.onCompleted: currentIndex = indexOfValue('Square') + } + } + } + + Component { + id: circleTouchHandle + Rectangle { + color: "blue" + border.color: "black" + border.width: 2 + radius: 50 + } + } + + Component { + id: rectTouchHandle + Rectangle { + border.color: "black" + border.width: 2 + radius: 2 + onVisibleChanged: if (visible) { color = 'yellow'; cAnim.restart(); } + ColorAnimation on color { id: cAnim; to: 'red'; duration: 1000 } + } + } + + WebEngineView { + anchors.fill: parent + id: webEngineView + url: "https://www.qt.io" + } +} diff --git a/examples/webenginequick/customtouchhandle/qml.qrc b/examples/webenginequick/customtouchhandle/qml.qrc new file mode 100644 index 000000000..5f6483ac3 --- /dev/null +++ b/examples/webenginequick/customtouchhandle/qml.qrc @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/examples/webenginequick/webenginequick.pro b/examples/webenginequick/webenginequick.pro index 058868395..edf4315a0 100644 --- a/examples/webenginequick/webenginequick.pro +++ b/examples/webenginequick/webenginequick.pro @@ -2,6 +2,7 @@ TEMPLATE=subdirs SUBDIRS += \ customdialogs \ + customtouchhandle \ minimal \ quicknanobrowser \ webengineaction diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h index 4862763aa..e82f22af9 100644 --- a/src/core/api/qwebenginepage_p.h +++ b/src/core/api/qwebenginepage_p.h @@ -64,7 +64,7 @@ namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegate; class RenderWidgetHostViewQtDelegateWidget; class RenderWidgetHostViewQtDelegateClient; -class TouchHandleDrawableClient; +class TouchHandleDrawableDelegate; class TouchSelectionMenuController; class WebContentsAdapter; } @@ -183,7 +183,8 @@ public: bool isEnabled() const override; void setToolTip(const QString &toolTipText) override; void printRequested() override; - QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap &) override { return nullptr; } + QtWebEngineCore::TouchHandleDrawableDelegate * + createTouchHandleDelegate(const QMap &) override { return nullptr; } void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override { } void hideTouchSelectionMenu() override { } const QObject *holdingQObject() const override; diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index c56894983..572468bc8 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -226,11 +226,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget m_cursorManager.reset(new content::CursorManager(this)); m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this)); - ui::TouchSelectionController::Config config; - config.max_tap_duration = base::Milliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); - config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); - config.enable_longpress_drag_selection = false; - m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); + resetTouchSelectionController(); host()->render_frame_metadata_provider()->AddObserver(this); host()->render_frame_metadata_provider()->ReportAllFrameSubmissionsForTesting(true); @@ -1071,6 +1067,17 @@ void RenderWidgetHostViewQt::synchronizeVisualProperties(const absl::optionalSynchronizeVisualProperties(); } +void RenderWidgetHostViewQt::resetTouchSelectionController() +{ + Q_ASSERT(m_touchSelectionControllerClient); + m_touchSelectionControllerClient->resetControls(); + ui::TouchSelectionController::Config config; + config.max_tap_duration = base::Milliseconds(ui::GestureConfiguration::GetInstance()->long_press_time_in_ms()); + config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); + config.enable_longpress_drag_selection = false; + m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); +} + std::unique_ptr RenderWidgetHostViewQt::CreateSyntheticGestureTarget() { return nullptr; diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 5105d6621..e8da6785a 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -211,6 +211,8 @@ public: void synchronizeVisualProperties( const absl::optional &childSurfaceId); + void resetTouchSelectionController(); + private: friend class DelegatedFrameHostClientQt; friend class WebContentsAccessibilityQt; diff --git a/src/core/touch_handle_drawable_client.h b/src/core/touch_handle_drawable_client.h index d7db78f02..168bf4afc 100644 --- a/src/core/touch_handle_drawable_client.h +++ b/src/core/touch_handle_drawable_client.h @@ -45,9 +45,9 @@ namespace QtWebEngineCore { -class Q_WEBENGINECORE_PRIVATE_EXPORT TouchHandleDrawableClient { +class Q_WEBENGINECORE_PRIVATE_EXPORT TouchHandleDrawableDelegate { public: - virtual ~TouchHandleDrawableClient() { } + virtual ~TouchHandleDrawableDelegate() { } virtual void setImage(int orientation) = 0; virtual void setBounds(const QRect &bounds) = 0; diff --git a/src/core/touch_handle_drawable_qt.cpp b/src/core/touch_handle_drawable_qt.cpp index 66b1cf40e..24171b272 100644 --- a/src/core/touch_handle_drawable_qt.cpp +++ b/src/core/touch_handle_drawable_qt.cpp @@ -49,7 +49,6 @@ #include "type_conversion.h" #include "web_contents_adapter_client.h" -#include "ui/gfx/image/image.h" #include "ui/base/resource/resource_bundle.h" #include "ui/resources/grit/ui_resources.h" @@ -68,27 +67,6 @@ const int kSelectionHandlePadding = 0; // Epsilon value used to compare float values to zero. const float kEpsilon = 1e-8f; -// Returns the appropriate handle image based on the handle orientation. -gfx::Image* GetHandleImage(ui::TouchHandleOrientation orientation) -{ - int resource_id = 0; - switch (orientation) { - case ui::TouchHandleOrientation::LEFT: - resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT; - break; - case ui::TouchHandleOrientation::CENTER: - resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER; - break; - case ui::TouchHandleOrientation::RIGHT: - resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT; - break; - case ui::TouchHandleOrientation::UNDEFINED: - NOTREACHED() << "Invalid touch handle bound type."; - return nullptr; - }; - return &ui::ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); -} - bool IsNearlyZero(float value) { return std::abs(value) < kEpsilon; @@ -96,21 +74,12 @@ bool IsNearlyZero(float value) } // namespace -TouchHandleDrawableQt::TouchHandleDrawableQt(RenderWidgetHostViewQt *rwhv) - : m_rwhv(rwhv) +TouchHandleDrawableQt::TouchHandleDrawableQt(TouchHandleDrawableDelegate *delegate) + : m_delegate(delegate) , m_enabled(false) , m_alpha(0) , m_orientation(ui::TouchHandleOrientation::UNDEFINED) { - QMap images; - for (int orientation = 0; orientation < static_cast(ui::TouchHandleOrientation::UNDEFINED); ++orientation) { - gfx::Image* image = GetHandleImage(static_cast(orientation)); - images.insert(orientation, toQImage(image->AsBitmap())); - } - - Q_ASSERT(m_rwhv); - Q_ASSERT(m_rwhv->adapterClient()); - m_client.reset(m_rwhv->adapterClient()->createTouchHandle(images)); } TouchHandleDrawableQt::~TouchHandleDrawableQt() @@ -119,12 +88,12 @@ TouchHandleDrawableQt::~TouchHandleDrawableQt() void TouchHandleDrawableQt::UpdateBounds() { - if (!m_client) + if (!m_delegate) return; gfx::RectF newBounds = m_relativeBounds; newBounds.Offset(m_originPosition.x(), m_originPosition.y()); - m_client->setBounds(toQt(gfx::ToEnclosingRect(newBounds))); + m_delegate->setBounds(toQt(gfx::ToEnclosingRect(newBounds))); } bool TouchHandleDrawableQt::IsVisible() const @@ -134,19 +103,19 @@ bool TouchHandleDrawableQt::IsVisible() const void TouchHandleDrawableQt::SetEnabled(bool enabled) { - if (!m_client) + if (!m_delegate) return; if (enabled == m_enabled) return; m_enabled = enabled; - m_client->setVisible(enabled); + m_delegate->setVisible(enabled); } void TouchHandleDrawableQt::SetOrientation(ui::TouchHandleOrientation orientation, bool mirror_vertical, bool mirror_horizontal) { - if (!m_client) + if (!m_delegate) return; // TODO: Implement adaptive handle orientation logic @@ -157,7 +126,7 @@ void TouchHandleDrawableQt::SetOrientation(ui::TouchHandleOrientation orientatio return; m_orientation = orientation; gfx::Image* image = GetHandleImage(orientation); - m_client->setImage(static_cast(orientation)); + m_delegate->setImage(static_cast(orientation)); // Calculate the relative bounds. gfx::Size image_size = image->Size(); @@ -178,15 +147,15 @@ void TouchHandleDrawableQt::SetOrigin(const gfx::PointF& position) void TouchHandleDrawableQt::SetAlpha(float alpha) { - if (!m_client) + if (!m_delegate) return; if (alpha == m_alpha) return; m_alpha = alpha; - m_client->setOpacity(m_alpha); - m_client->setVisible(IsVisible()); + m_delegate->setOpacity(m_alpha); + m_delegate->setVisible(IsVisible()); } gfx::RectF TouchHandleDrawableQt::GetVisibleBounds() const @@ -208,4 +177,25 @@ float TouchHandleDrawableQt::GetDrawableHorizontalPaddingRatio() const return 0.0; } +// Returns the appropriate handle image based on the handle orientation. +gfx::Image *TouchHandleDrawableQt::GetHandleImage(ui::TouchHandleOrientation orientation) +{ + int resource_id = 0; + switch (orientation) { + case ui::TouchHandleOrientation::LEFT: + resource_id = IDR_TEXT_SELECTION_HANDLE_LEFT; + break; + case ui::TouchHandleOrientation::CENTER: + resource_id = IDR_TEXT_SELECTION_HANDLE_CENTER; + break; + case ui::TouchHandleOrientation::RIGHT: + resource_id = IDR_TEXT_SELECTION_HANDLE_RIGHT; + break; + case ui::TouchHandleOrientation::UNDEFINED: + NOTREACHED() << "Invalid touch handle bound type."; + return nullptr; + }; + return &ui::ResourceBundle::GetSharedInstance().GetImageNamed(resource_id); +} + } // namespace QtWebEngineCore diff --git a/src/core/touch_handle_drawable_qt.h b/src/core/touch_handle_drawable_qt.h index 580b56018..f81d1b978 100644 --- a/src/core/touch_handle_drawable_qt.h +++ b/src/core/touch_handle_drawable_qt.h @@ -42,19 +42,20 @@ #include "ui/touch_selection/touch_handle.h" #include "ui/touch_selection/touch_handle_orientation.h" +#include "ui/gfx/image/image.h" #include namespace QtWebEngineCore { -class RenderWidgetHostViewQt; -class TouchHandleDrawableClient; +class TouchHandleDrawableDelegate; class TouchHandleDrawableQt : public ui::TouchHandleDrawable { public: - explicit TouchHandleDrawableQt(RenderWidgetHostViewQt *rwhv); + explicit TouchHandleDrawableQt(TouchHandleDrawableDelegate *delegate); ~TouchHandleDrawableQt() override; + static gfx::Image *GetHandleImage(ui::TouchHandleOrientation orientation); private: void UpdateBounds(); @@ -71,7 +72,7 @@ private: float GetDrawableHorizontalPaddingRatio() const override; RenderWidgetHostViewQt *m_rwhv; - QScopedPointer m_client; + QScopedPointer m_delegate; bool m_enabled; float m_alpha; diff --git a/src/core/touch_selection_controller_client_qt.cpp b/src/core/touch_selection_controller_client_qt.cpp index 2e9f56a5f..b85d301f6 100644 --- a/src/core/touch_selection_controller_client_qt.cpp +++ b/src/core/touch_selection_controller_client_qt.cpp @@ -39,6 +39,7 @@ #include "render_widget_host_view_qt.h" #include "touch_handle_drawable_qt.h" +#include "touch_handle_drawable_client.h" #include "touch_selection_controller_client_qt.h" #include "touch_selection_menu_controller.h" #include "type_conversion.h" @@ -293,13 +294,31 @@ void TouchSelectionControllerClientQt::OnDragUpdate(const ui::TouchSelectionDrag std::unique_ptr TouchSelectionControllerClientQt::CreateDrawable() { - return std::unique_ptr(new TouchHandleDrawableQt(m_rwhv)); + Q_ASSERT(m_rwhv); + Q_ASSERT(m_rwhv->adapterClient()); + QMap images; + for (int orientation = 0; orientation < static_cast(ui::TouchHandleOrientation::UNDEFINED); + ++orientation) { + gfx::Image *image = TouchHandleDrawableQt::GetHandleImage( + static_cast(orientation)); + images.insert(orientation, toQImage(image->AsBitmap())); + } + auto delegate = m_rwhv->adapterClient()->createTouchHandleDelegate(images); + return std::unique_ptr(new TouchHandleDrawableQt(delegate)); } void TouchSelectionControllerClientQt::DidScroll() { } +void TouchSelectionControllerClientQt::resetControls() +{ + if (m_menuShowing) { + hideMenu(); + GetTouchSelectionController()->HideAndDisallowShowingAutomatically(); + } +} + void TouchSelectionControllerClientQt::showMenu() { gfx::RectF rect = GetTouchSelectionController()->GetRectBetweenBounds(); diff --git a/src/core/touch_selection_controller_client_qt.h b/src/core/touch_selection_controller_client_qt.h index 16d581ba8..a054824a6 100644 --- a/src/core/touch_selection_controller_client_qt.h +++ b/src/core/touch_selection_controller_client_qt.h @@ -51,6 +51,7 @@ namespace QtWebEngineCore { class RenderWidgetHostViewQt; class TouchSelectionMenuController; +class TouchHandleDrawableDelegate; class TouchSelectionControllerClientQt : public ui::TouchSelectionControllerClient @@ -98,6 +99,8 @@ public: std::unique_ptr CreateDrawable() override; void DidScroll() override; + void resetControls(); + private: void showMenu(); void hideMenu(); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 6206d846f..45dfd1017 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1787,6 +1787,14 @@ void WebContentsAdapter::resetSelection() } } +void WebContentsAdapter::resetTouchSelectionController() +{ + CHECK_INITIALIZED(); + unselect(); + if (auto rwhv = static_cast(m_webContents->GetRenderWidgetHostView())) + rwhv->resetTouchSelectionController(); +} + WebContentsAdapterClient::RenderProcessTerminationStatus WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) { auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 9066e7a72..612c4c585 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -236,6 +236,7 @@ public: bool isFindTextInProgress() const; bool hasFocusedFrame() const; void resetSelection(); + void resetTouchSelectionController(); // meant to be used within WebEngineCore only void initialize(content::SiteInstance *site); diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index ddc371fa3..14745cbb9 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -88,7 +88,7 @@ class JavaScriptDialogController; class RenderWidgetHostViewQt; class RenderWidgetHostViewQtDelegate; class RenderWidgetHostViewQtDelegateClient; -class TouchHandleDrawableClient; +class TouchHandleDrawableDelegate; class TouchSelectionMenuController; class WebContentsAdapter; class WebContentsDelegateQt; @@ -238,7 +238,7 @@ public: virtual void setToolTip(const QString& toolTipText) = 0; virtual ClientType clientType() = 0; virtual void printRequested() = 0; - virtual TouchHandleDrawableClient *createTouchHandle(const QMap &images) = 0; + virtual TouchHandleDrawableDelegate * createTouchHandleDelegate(const QMap &images) = 0; virtual void showTouchSelectionMenu(TouchSelectionMenuController *menuController, const QRect &bounds, const QSize &handleSize) = 0; virtual void hideTouchSelectionMenu() = 0; virtual void findTextFinished(const QWebEngineFindTextResult &result) = 0; diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt index 255874721..47407f881 100644 --- a/src/webenginequick/CMakeLists.txt +++ b/src/webenginequick/CMakeLists.txt @@ -22,6 +22,7 @@ qt_internal_add_qml_module(WebEngineQuick api/qquickwebenginesingleton.cpp api/qquickwebenginesingleton_p.h api/qquickwebenginetouchhandleprovider.cpp api/qquickwebenginetouchhandleprovider_p_p.h + api/qquickwebenginecustomtouchhandle.cpp api/qquickwebenginecustomtouchhandle_p.h api/qquickwebenginetouchselectionmenurequest.cpp api/qquickwebenginetouchselectionmenurequest_p.h api/qquickwebenginetouchselectionmenurequest_p_p.h diff --git a/src/webenginequick/api/qquickwebenginecustomtouchhandle.cpp b/src/webenginequick/api/qquickwebenginecustomtouchhandle.cpp new file mode 100644 index 000000000..5bd12e6d6 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginecustomtouchhandle.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** 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 "qquickwebenginecustomtouchhandle_p.h" +#include "web_contents_adapter_client.h" +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QQuickWebEngineCustomTouchHandle + \since 6.4 + \brief The QQuickWebEngineCustomTouchHandle class provides information about the touch handle. + \inmodule QtWebEngineQuick + QQuickWebEngineCustomTouchHandle is returned after a touch selection event, + and contains information about the touch handle. +*/ + +QQuickWebEngineCustomTouchHandle::QQuickWebEngineCustomTouchHandle() + : QObject(nullptr) +{ +} + +void QQuickWebEngineCustomTouchHandle::setBounds(const QRect &bounds) +{ + item->setX(bounds.x()); + item->setY(bounds.y()); + item->setWidth(bounds.width()); + item->setHeight(bounds.height()); +} + +void QQuickWebEngineCustomTouchHandle::setOpacity(float opacity) +{ + item->setOpacity(opacity); +} + +void QQuickWebEngineCustomTouchHandle::setImage(int orientation) +{ + Q_UNUSED(orientation); +} + +void QQuickWebEngineCustomTouchHandle::setVisible(bool visible) +{ + item->setVisible(visible); +} + +QT_END_NAMESPACE diff --git a/src/webenginequick/api/qquickwebenginecustomtouchhandle_p.h b/src/webenginequick/api/qquickwebenginecustomtouchhandle_p.h new file mode 100644 index 000000000..a2adcea94 --- /dev/null +++ b/src/webenginequick/api/qquickwebenginecustomtouchhandle_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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 QQUICKWEBENGINECUSTOMTOUCHHANDLE_P_H +#define QQUICKWEBENGINECUSTOMTOUCHHANDLE_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 +#include +#include +#include + +namespace QtWebEngineCore { +class WebContentsAdapterClient; +} + +QT_BEGIN_NAMESPACE + +class QQuickItem; + +class QQuickWebEngineCustomTouchHandle + : public QObject + , public QtWebEngineCore::TouchHandleDrawableDelegate +{ + Q_OBJECT + QML_NAMED_ELEMENT(CustomTouchHandle) + QML_ADDED_IN_VERSION(6, 4) + +public: + QQuickWebEngineCustomTouchHandle(); + + QScopedPointer item; + + void setBounds(const QRect &bounds) override; + void setVisible(bool visible) override; + void setOpacity(float opacity) override; + void setImage(int orientation) override; +}; + +QT_END_NAMESPACE + +#endif // QQUICKWEBENGINECUSTOMTOUCHHANDLE_P_H diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp index 3aca79672..96b79a5b7 100644 --- a/src/webenginequick/api/qquickwebengineview.cpp +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -49,6 +49,7 @@ #include "qquickwebenginescriptcollection_p_p.h" #include "qquickwebenginesettings_p.h" #include "qquickwebenginetouchhandleprovider_p_p.h" +#include "qquickwebenginecustomtouchhandle_p.h" #include "qquickwebenginetouchselectionmenurequest_p.h" #include "qquickwebengineview_p.h" #include "qquickwebengineview_p_p.h" @@ -168,6 +169,7 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_zoomFactor(1.0) , m_profileInitialized(false) , m_contextMenuRequest(nullptr) + , m_touchHandleDelegate(nullptr) { memset(actions, 0, sizeof(actions)); @@ -1260,9 +1262,35 @@ void QQuickWebEngineViewPrivate::setToolTip(const QString &toolTipText) ui()->showToolTip(toolTipText); } -QtWebEngineCore::TouchHandleDrawableClient *QQuickWebEngineViewPrivate::createTouchHandle(const QMap &images) +QtWebEngineCore::TouchHandleDrawableDelegate * +QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap &images) { - return new QQuickWebEngineTouchHandle(ui(), images); + Q_Q(QQuickWebEngineView); + if (m_touchHandleDelegate) { + // lifecycle managed by Chromium's TouchHandleDrawable + QQmlContext *qmlContext = QQmlEngine::contextForObject(q); + QQuickWebEngineCustomTouchHandle *handle = new QQuickWebEngineCustomTouchHandle(); + QQmlContext *context = new QQmlContext(qmlContext, handle); + context->setContextObject(handle); + QObject *delegate = m_touchHandleDelegate->create(context); + Q_ASSERT(delegate); + QQuickItem *item = qobject_cast(delegate); + item->setParentItem(q); + handle->item.reset(item); + return handle; + } else { + QQuickItem *item = ui()->createTouchHandle(); + Q_ASSERT(item); + QQmlEngine *engine = qmlEngine(item); + Q_ASSERT(engine); + QQuickWebEngineTouchHandleProvider *touchHandleProvider = + static_cast( + engine->imageProvider(QQuickWebEngineTouchHandleProvider::identifier())); + Q_ASSERT(touchHandleProvider); + touchHandleProvider->init(images); + return new QQuickWebEngineTouchHandle(item); + } + return nullptr; } void QQuickWebEngineViewPrivate::showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *menuController, const QRect &selectionBounds, const QSize &handleSize) @@ -2383,18 +2411,9 @@ bool QQuickContextMenuBuilder::isMenuItemEnabled(ContextMenuItem menuItem) Q_UNREACHABLE(); } - -QQuickWebEngineTouchHandle::QQuickWebEngineTouchHandle(QtWebEngineCore::UIDelegatesManager *ui, const QMap &images) +QQuickWebEngineTouchHandle::QQuickWebEngineTouchHandle(QQuickItem *item) : m_item(item) { - Q_ASSERT(ui); - m_item.reset(ui->createTouchHandle()); - - QQmlEngine *engine = qmlEngine(m_item.data()); - Q_ASSERT(engine); - QQuickWebEngineTouchHandleProvider *touchHandleProvider = - static_cast(engine->imageProvider(QQuickWebEngineTouchHandleProvider::identifier())); - Q_ASSERT(touchHandleProvider); - touchHandleProvider->init(images); + m_item->setProperty("visible", false); } void QQuickWebEngineTouchHandle::setImage(int orientation) @@ -2405,20 +2424,34 @@ void QQuickWebEngineTouchHandle::setImage(int orientation) void QQuickWebEngineTouchHandle::setBounds(const QRect &bounds) { - m_item->setProperty("x", bounds.x()); - m_item->setProperty("y", bounds.y()); - m_item->setProperty("width", bounds.width()); - m_item->setProperty("height", bounds.height()); + m_item->setX(bounds.x()); + m_item->setY(bounds.y()); + m_item->setWidth(bounds.width()); + m_item->setHeight(bounds.height()); } void QQuickWebEngineTouchHandle::setVisible(bool visible) { - m_item->setProperty("visible", visible); + m_item->setVisible(visible); } void QQuickWebEngineTouchHandle::setOpacity(float opacity) { - m_item->setProperty("opacity", opacity); + m_item->setOpacity(opacity); +} + +void QQuickWebEngineView::setTouchHandleDelegate(QQmlComponent *delegate) +{ + if (d_ptr->m_touchHandleDelegate != delegate) { + d_ptr->m_touchHandleDelegate = delegate; + d_ptr->webContentsAdapter()->resetTouchSelectionController(); + emit touchHandleDelegateChanged(); + } +} + +QQmlComponent *QQuickWebEngineView::touchHandleDelegate() const +{ + return d_ptr->m_touchHandleDelegate; } QT_END_NAMESPACE diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h index 1a42726e4..867e37d06 100644 --- a/src/webenginequick/api/qquickwebengineview_p.h +++ b/src/webenginequick/api/qquickwebengineview_p.h @@ -64,6 +64,7 @@ class RenderWidgetHostViewQtDelegateQuick; QT_BEGIN_NAMESPACE class QQmlWebChannel; +class QQmlComponent; class QQuickContextMenuBuilder; class QQuickWebEngineAction; class QQuickWebEngineAuthenticationDialogRequest; @@ -123,6 +124,8 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem { Q_PROPERTY(LifecycleState recommendedState READ recommendedState NOTIFY recommendedStateChanged REVISION(1,10) FINAL) Q_PROPERTY(qint64 renderProcessPid READ renderProcessPid NOTIFY renderProcessPidChanged FINAL REVISION(1,11)) + Q_PROPERTY(QQmlComponent *touchHandleDelegate READ touchHandleDelegate WRITE + setTouchHandleDelegate NOTIFY touchHandleDelegateChanged REVISION(0) FINAL) QML_NAMED_ELEMENT(WebEngineView) QML_ADDED_IN_VERSION(1, 0) QML_EXTRA_VERSION(2, 0) @@ -496,6 +499,9 @@ QT_WARNING_POP LifecycleState recommendedState() const; + QQmlComponent *touchHandleDelegate() const; + void setTouchHandleDelegate(QQmlComponent *delegagte); + public Q_SLOTS: void runJavaScript(const QString&, const QJSValue & = QJSValue()); Q_REVISION(1,3) void runJavaScript(const QString&, quint32 worldId, const QJSValue & = QJSValue()); @@ -565,6 +571,7 @@ Q_SIGNALS: Q_REVISION(1,11) void canGoForwardChanged(); Q_REVISION(1,12) void newWindowRequested(QQuickWebEngineNewWindowRequest *request); Q_REVISION(6,3) void touchSelectionMenuRequested(QQuickWebEngineTouchSelectionMenuRequest *request); + Q_REVISION(6,4) void touchHandleDelegateChanged(); protected: void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h index a10c12481..8194dd897 100644 --- a/src/webenginequick/api/qquickwebengineview_p_p.h +++ b/src/webenginequick/api/qquickwebengineview_p_p.h @@ -51,9 +51,11 @@ // We mean it. // +#include "qquickwebenginecustomtouchhandle_p.h" #include "qquickwebengineview_p.h" #include "render_view_context_menu_qt.h" #include "touch_handle_drawable_client.h" +#include "ui_delegates_manager.h" #include "web_contents_adapter_client.h" #include @@ -153,7 +155,7 @@ public: QObject *dragSource() const override; bool isEnabled() const override; void setToolTip(const QString &toolTipText) override; - QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap &images) override; + QtWebEngineCore::TouchHandleDrawableDelegate *createTouchHandleDelegate(const QMap &images) override; void showTouchSelectionMenu(QtWebEngineCore::TouchSelectionMenuController *, const QRect &, const QSize &) override; void hideTouchSelectionMenu() override; const QObject *holdingQObject() const override; @@ -209,6 +211,7 @@ private: QWebEngineContextMenuRequest *m_contextMenuRequest; QScopedPointer m_scriptCollection; QPointer m_faviconProvider; + QQmlComponent *m_touchHandleDelegate; }; #ifndef QT_NO_ACCESSIBILITY @@ -249,9 +252,11 @@ private: QObject *m_menu; }; -class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineTouchHandle : public QtWebEngineCore::TouchHandleDrawableClient { +class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineTouchHandle + : public QtWebEngineCore::TouchHandleDrawableDelegate +{ public: - QQuickWebEngineTouchHandle(QtWebEngineCore::UIDelegatesManager *ui, const QMap &images); + QQuickWebEngineTouchHandle(QQuickItem *item = nullptr); void setImage(int orientation) override; void setBounds(const QRect &bounds) override; diff --git a/src/webenginequick/doc/src/custom_touch_handle.qdoc b/src/webenginequick/doc/src/custom_touch_handle.qdoc new file mode 100644 index 000000000..8ef193d16 --- /dev/null +++ b/src/webenginequick/doc/src/custom_touch_handle.qdoc @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \qmltype CustomTouchHandle + \inqmlmodule QtWebEngine + \since QtWebEngine 6.4 + + \brief Data class for representing the touch handle QML delegate. + + The handle's position, opacity, and visibility are updated automatically. + The delegate should be a QML Item or any QML type which inherits it. + + The following code uses a custom touch handle delegate: + + \code + WebEngineView { + // ... + touchHandleDelegate: Rectangle { + color: "red" + } + // ... + } + \endcode + + \note The bounding box which propagates the touch event is provided by + Chromium and the text selection can be moved even if there is no handle drawn. +*/ diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc index 7de68f243..ae3ea1c23 100644 --- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -1491,3 +1491,13 @@ \sa TouchSelectionMenuRequest */ + +/*! + \qmlproperty CustomTouchHandle WebEngineView::touchHandleDelegate + \since QtWebEngine 6.4 + + If a QML Item is set, the default touch handles will not be shown and + this item will be displayed as touch handles. + + \sa {WebEngine Qt Quick Custom Touch Handle Example} +*/ diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp index 492494240..5a01ea2f0 100644 --- a/src/webenginequick/ui_delegates_manager.cpp +++ b/src/webenginequick/ui_delegates_manager.cpp @@ -40,7 +40,7 @@ #include "ui_delegates_manager.h" #include "api/qquickwebengineaction_p.h" -#include "api/qquickwebengineview_p.h" +#include "api/qquickwebengineview_p_p.h" #include #include diff --git a/src/webenginequick/ui_delegates_manager.h b/src/webenginequick/ui_delegates_manager.h index 0f515d4be..1632a9568 100644 --- a/src/webenginequick/ui_delegates_manager.h +++ b/src/webenginequick/ui_delegates_manager.h @@ -46,6 +46,7 @@ #include #include #include +#include "api/qquickwebenginecustomtouchhandle_p.h" #define FOR_EACH_COMPONENT_TYPE(F, SEPARATOR) \ F(Menu, menu) SEPARATOR \ diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index e6357ebc2..c22176265 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -106,7 +106,8 @@ static const QStringList hardcodedTypes = QStringList() << "const QQuickWebEngineContextMenuData*" << "QWebEngineCookieStore*" << "Qt::LayoutDirection" - << "QQuickWebEngineScriptCollection*"; + << "QQuickWebEngineScriptCollection*" + << "QQmlComponent*"; static const QStringList expectedAPI = QStringList() << "QQuickWebEngineAction.text --> QString" @@ -773,6 +774,8 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineView.title --> QString" << "QQuickWebEngineView.titleChanged() --> void" << "QQuickWebEngineView.tooltipRequested(QQuickWebEngineTooltipRequest*) --> void" + << "QQuickWebEngineView.touchHandleDelegate --> QQmlComponent*" + << "QQuickWebEngineView.touchHandleDelegateChanged() --> void" << "QQuickWebEngineView.touchSelectionMenuRequested(QQuickWebEngineTouchSelectionMenuRequest*) --> void" << "QQuickWebEngineView.triggerWebAction(WebAction) --> void" << "QQuickWebEngineView.url --> QUrl" -- cgit v1.2.3