summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBalazs Egedi <egedib@inf.u-szeged.hu>2022-02-18 13:04:19 +0100
committerKirill Burtsev <kirill.burtsev@qt.io>2022-05-04 03:00:16 +0200
commit828ee197647a7462c10243c0261e7bced9bbcb65 (patch)
tree4c6bc198ea33a753e6af4efa736741ea10cea280
parent57a38f05d9a0898bffa077a5caaf48fde370cb02 (diff)
Quick: Add support for replacing touch handles with delegates
Task-number: QTBUG-85043 Change-Id: I1c87aff352e07eb309d5ba8747b9e50a191d478e Reviewed-by: Michal Klocek <michal.klocek@qt.io>
-rw-r--r--examples/webenginequick/CMakeLists.txt1
-rw-r--r--examples/webenginequick/customtouchhandle/CMakeLists.txt45
-rw-r--r--examples/webenginequick/customtouchhandle/customtouchhandle.pro10
-rw-r--r--examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpgbin0 -> 47646 bytes
-rw-r--r--examples/webenginequick/customtouchhandle/doc/src/customtouchhandle.qdoc66
-rw-r--r--examples/webenginequick/customtouchhandle/main.cpp66
-rw-r--r--examples/webenginequick/customtouchhandle/main.qml143
-rw-r--r--examples/webenginequick/customtouchhandle/qml.qrc5
-rw-r--r--examples/webenginequick/webenginequick.pro1
-rw-r--r--src/core/api/qwebenginepage_p.h5
-rw-r--r--src/core/render_widget_host_view_qt.cpp17
-rw-r--r--src/core/render_widget_host_view_qt.h2
-rw-r--r--src/core/touch_handle_drawable_client.h4
-rw-r--r--src/core/touch_handle_drawable_qt.cpp74
-rw-r--r--src/core/touch_handle_drawable_qt.h9
-rw-r--r--src/core/touch_selection_controller_client_qt.cpp21
-rw-r--r--src/core/touch_selection_controller_client_qt.h3
-rw-r--r--src/core/web_contents_adapter.cpp8
-rw-r--r--src/core/web_contents_adapter.h1
-rw-r--r--src/core/web_contents_adapter_client.h4
-rw-r--r--src/webenginequick/CMakeLists.txt1
-rw-r--r--src/webenginequick/api/qquickwebenginecustomtouchhandle.cpp83
-rw-r--r--src/webenginequick/api/qquickwebenginecustomtouchhandle_p.h89
-rw-r--r--src/webenginequick/api/qquickwebengineview.cpp71
-rw-r--r--src/webenginequick/api/qquickwebengineview_p.h7
-rw-r--r--src/webenginequick/api/qquickwebengineview_p_p.h11
-rw-r--r--src/webenginequick/doc/src/custom_touch_handle.qdoc52
-rw-r--r--src/webenginequick/doc/src/webengineview_lgpl.qdoc10
-rw-r--r--src/webenginequick/ui_delegates_manager.cpp2
-rw-r--r--src/webenginequick/ui_delegates_manager.h1
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp5
31 files changed, 735 insertions, 82 deletions
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
--- /dev/null
+++ b/examples/webenginequick/customtouchhandle/doc/images/customtouchhandle.jpg
Binary files 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 <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QtWebEngineQuick/qtwebenginequickglobal.h>
+
+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 @@
+<RCC>
+ <qresource prefix="/">
+ <file>main.qml</file>
+ </qresource>
+</RCC>
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<int, QImage> &) override { return nullptr; }
+ QtWebEngineCore::TouchHandleDrawableDelegate *
+ createTouchHandleDelegate(const QMap<int, QImage> &) 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::optional<vi
host()->SynchronizeVisualProperties();
}
+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<content::SyntheticGestureTarget> 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<viz::LocalSurfaceId> &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<int, QImage> images;
- for (int orientation = 0; orientation < static_cast<int>(ui::TouchHandleOrientation::UNDEFINED); ++orientation) {
- gfx::Image* image = GetHandleImage(static_cast<ui::TouchHandleOrientation>(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<int>(orientation));
+ m_delegate->setImage(static_cast<int>(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 <QtCore/QScopedPointer>
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<TouchHandleDrawableClient> m_client;
+ QScopedPointer<TouchHandleDrawableDelegate> 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<ui::TouchHandleDrawable> TouchSelectionControllerClientQt::CreateDrawable()
{
- return std::unique_ptr<ui::TouchHandleDrawable>(new TouchHandleDrawableQt(m_rwhv));
+ Q_ASSERT(m_rwhv);
+ Q_ASSERT(m_rwhv->adapterClient());
+ QMap<int, QImage> images;
+ for (int orientation = 0; orientation < static_cast<int>(ui::TouchHandleOrientation::UNDEFINED);
+ ++orientation) {
+ gfx::Image *image = TouchHandleDrawableQt::GetHandleImage(
+ static_cast<ui::TouchHandleOrientation>(orientation));
+ images.insert(orientation, toQImage(image->AsBitmap()));
+ }
+ auto delegate = m_rwhv->adapterClient()->createTouchHandleDelegate(images);
+ return std::unique_ptr<ui::TouchHandleDrawable>(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<ui::TouchHandleDrawable> 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<RenderWidgetHostViewQt *>(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<int, QImage> &images) = 0;
+ virtual TouchHandleDrawableDelegate * createTouchHandleDelegate(const QMap<int, QImage> &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 <QtQuick/qquickitem.h>
+
+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 <QtWebEngineQuick/qtwebenginequickglobal.h>
+#include <QtCore/qobject.h>
+#include <QtQml/qqmlregistration.h>
+#include <QtCore/qrect.h>
+
+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<QQuickItem> 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<int, QImage> &images)
+QtWebEngineCore::TouchHandleDrawableDelegate *
+QQuickWebEngineViewPrivate::createTouchHandleDelegate(const QMap<int, QImage> &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<QQuickItem *>(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<QQuickWebEngineTouchHandleProvider *>(
+ 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<int, QImage> &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<QQuickWebEngineTouchHandleProvider *>(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 <QtCore/qcompilerdetection.h>
@@ -153,7 +155,7 @@ public:
QObject *dragSource() const override;
bool isEnabled() const override;
void setToolTip(const QString &toolTipText) override;
- QtWebEngineCore::TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) override;
+ QtWebEngineCore::TouchHandleDrawableDelegate *createTouchHandleDelegate(const QMap<int, QImage> &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<QQuickWebEngineScriptCollection> m_scriptCollection;
QPointer<QQuickWebEngineFaviconProvider> 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<int, QImage> &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 <authentication_dialog_controller.h>
#include <color_chooser_controller.h>
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 <QtCore/qsharedpointer.h>
#include <QtCore/qstring.h>
#include <QtCore/qstringlist.h>
+#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"