aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickmultipointtoucharea.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/quick/items/qquickmultipointtoucharea.cpp')
-rw-r--r--src/quick/items/qquickmultipointtoucharea.cpp144
1 files changed, 77 insertions, 67 deletions
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 642b5ca047..b0b99334a2 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -1,50 +1,14 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQuick module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qquickmultipointtoucharea_p.h"
#include <QtQuick/qquickwindow.h>
#include <private/qsgadaptationlayer_p.h>
-#include <private/qevent_p.h>
#include <private/qquickitem_p.h>
#include <private/qquickwindow_p.h>
#include <private/qguiapplication_p.h>
#include <QtGui/private/qevent_p.h>
+#include <QtGui/private/qeventpoint_p.h>
#include <QtGui/private/qpointingdevice_p.h>
#include <QEvent>
#include <QMouseEvent>
@@ -53,7 +17,7 @@
QT_BEGIN_NAMESPACE
-DEFINE_BOOL_CONFIG_OPTION(qmlVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
+DEFINE_BOOL_CONFIG_OPTION(qmlMptaVisualTouchDebugging, QML_VISUAL_TOUCH_DEBUGGING)
/*!
\qmltype TouchPoint
@@ -365,18 +329,39 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
If minimumTouchPoints is set to a value greater than one, this signal will not be emitted until the minimum number
of required touch points has been reached.
+
+ \note If you use the \c touchPoints argument in your signal handler code,
+ it's best to rename it in your formal parameter to avoid confusion with the
+ \c touchPoints property (see \l{QML Coding Conventions}):
+ \qml
+ onPressed: (points) => console.log("pressed", points.length)
+ \endqml
*/
/*!
\qmlsignal QtQuick::MultiPointTouchArea::updated(list<TouchPoint> touchPoints)
This signal is emitted when existing touch points are updated. \a touchPoints is a list of these updated points.
+
+ \note If you use the \c touchPoints argument in your signal handler code,
+ it's best to rename it in your formal parameter to avoid confusion with the
+ \c touchPoints property (see \l{QML Coding Conventions}):
+ \qml
+ onUpdated: (points) => console.log("updated", points.length)
+ \endqml
*/
/*!
\qmlsignal QtQuick::MultiPointTouchArea::released(list<TouchPoint> touchPoints)
This signal is emitted when existing touch points are removed. \a touchPoints is a list of these removed points.
+
+ \note If you use the \c touchPoints argument in your signal handler code,
+ it's best to rename it in your formal parameter to avoid confusion with the
+ \c touchPoints property (see \l{QML Coding Conventions}):
+ \qml
+ onReleased: (points) => console.log("released", points.length)
+ \endqml
*/
/*!
@@ -392,8 +377,17 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
\c canceled should be handled in addition to \l released.
\a touchPoints is the list of canceled points.
+
+ \note If you use the \c touchPoints argument in your signal handler code,
+ it's best to rename it in your formal parameter to avoid confusion with the
+ \c touchPoints property (see \l{QML Coding Conventions}):
+ \qml
+ onCanceled: (points) => console.log("canceled", points.length)
+ \endqml
*/
+// TODO Qt 7: remove the notes above about the signal touchPoints arguments
+
/*!
\qmlsignal QtQuick::MultiPointTouchArea::gestureStarted(GestureEvent gesture)
@@ -443,11 +437,11 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
{
setAcceptedMouseButtons(Qt::LeftButton);
setFiltersChildMouseEvents(true);
- if (qmlVisualTouchDebugging()) {
+ if (qmlMptaVisualTouchDebugging()) {
setFlag(QQuickItem::ItemHasContents);
}
setAcceptTouchEvents(true);
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
setAcceptHoverEvents(true); // needed to enable touch events on mouse hover.
#endif
}
@@ -455,7 +449,7 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
QQuickMultiPointTouchArea::~QQuickMultiPointTouchArea()
{
clearTouchLists();
- for (QObject *obj : qAsConst(_touchPoints)) {
+ for (QObject *obj : std::as_const(_touchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined())
delete dtp;
@@ -570,7 +564,7 @@ void QQuickMultiPointTouchArea::grabGesture(QPointingDevice *dev)
setKeepTouchGrab(true);
}
-void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
+void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints remap)
{
bool ended = false;
bool moved = false;
@@ -578,6 +572,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
clearTouchLists();
QList<QEventPoint> touchPoints;
+ bool touchPointsFromEvent = false;
QPointingDevice *dev = nullptr;
switch (event->type()) {
@@ -586,6 +581,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
case QEvent::TouchEnd: {
QTouchEvent* te = static_cast<QTouchEvent*>(event);
touchPoints = te->points();
+ touchPointsFromEvent = true;
dev = const_cast<QPointingDevice *>(te->pointingDevice());
break;
}
@@ -612,9 +608,9 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
break;
}
- int numTouchPoints = touchPoints.count();
+ int numTouchPoints = touchPoints.size();
//always remove released touches, and make sure we handle all releases before adds.
- for (const QEventPoint &p : qAsConst(touchPoints)) {
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
QEventPoint::State touchPointState = p.state();
int id = p.id();
if (touchPointState & QEventPoint::State::Released) {
@@ -630,6 +626,10 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
}
if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
for (QEventPoint &p : touchPoints) {
+ QPointF oldPos = p.position();
+ auto transformBack = qScopeGuard([&] { QMutableEventPoint::setPosition(p, oldPos); });
+ if (touchPointsFromEvent && remap == RemapEventPoints::ToLocal)
+ QMutableEventPoint::setPosition(p, mapFromScene(p.scenePosition()));
QEventPoint::State touchPointState = p.state();
int id = p.id();
if (touchPointState & QEventPoint::State::Released) {
@@ -657,7 +657,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
if (!_stealMouse /* !ignoring gesture*/) {
bool offerGrab = false;
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- for (const QEventPoint &p : qAsConst(touchPoints)) {
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
if (p.state() == QEventPoint::State::Released)
continue;
const QPointF &currentPos = p.scenePosition();
@@ -683,7 +683,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
emit released(_releasedTouchPoints);
if (moved)
emit updated(_movedTouchPoints);
- if (started)
+ if (started && !_pressedTouchPoints.isEmpty())
emit pressed(_pressedTouchPoints);
if (ended || moved || started) emit touchUpdated(_touchPoints.values());
}
@@ -691,7 +691,7 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
void QQuickMultiPointTouchArea::clearTouchLists()
{
- for (QObject *obj : qAsConst(_releasedTouchPoints)) {
+ for (QObject *obj : std::as_const(_releasedTouchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined()) {
_touchPoints.remove(dtp->pointId());
@@ -708,7 +708,7 @@ void QQuickMultiPointTouchArea::clearTouchLists()
void QQuickMultiPointTouchArea::addTouchPoint(const QEventPoint *p)
{
QQuickTouchPoint *dtp = nullptr;
- for (QQuickTouchPoint* tp : qAsConst(_touchPrototypes)) {
+ for (QQuickTouchPoint* tp : std::as_const(_touchPrototypes)) {
if (!tp->inUse()) {
tp->setInUse(true);
dtp = tp;
@@ -728,12 +728,15 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QEventPoint *p)
void QQuickMultiPointTouchArea::addTouchPoint(const QMouseEvent *e)
{
QQuickTouchPoint *dtp = nullptr;
- for (QQuickTouchPoint *tp : qAsConst(_touchPrototypes))
+ for (QQuickTouchPoint *tp : std::as_const(_touchPrototypes)) {
if (!tp->inUse()) {
tp->setInUse(true);
dtp = tp;
break;
+ } else if (_mouseTouchPoint == tp) {
+ return; // do not allow more than one touchpoint to react to the mouse (QTBUG-83662)
}
+ }
if (dtp == nullptr)
dtp = new QQuickTouchPoint(false);
@@ -744,17 +747,17 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QMouseEvent *e)
_mouseTouchPoint = dtp;
}
-#ifdef Q_OS_OSX
+#ifdef Q_OS_MACOS
void QQuickMultiPointTouchArea::hoverEnterEvent(QHoverEvent *event)
{
- Q_UNUSED(event);
- setTouchEventsEnabled(true);
+ setTouchEventsEnabled(isEnabled());
+ QQuickItem::hoverEnterEvent(event);
}
void QQuickMultiPointTouchArea::hoverLeaveEvent(QHoverEvent *event)
{
- Q_UNUSED(event);
setTouchEventsEnabled(false);
+ QQuickItem::hoverLeaveEvent(event);
}
void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable)
@@ -768,11 +771,18 @@ void QQuickMultiPointTouchArea::setTouchEventsEnabled(bool enable)
registerTouchWindow(window(), enable);
}
-#endif // Q_OS_OSX
+
+void QQuickMultiPointTouchArea::itemChange(ItemChange change, const ItemChangeData &data)
+{
+ if (change == ItemEnabledHasChanged)
+ setAcceptHoverEvents(data.boolValue);
+ QQuickItem::itemChange(change, data);
+}
+#endif // Q_OS_MACOS
void QQuickMultiPointTouchArea::addTouchPrototype(QQuickTouchPoint *prototype)
{
- int id = _touchPrototypes.count();
+ int id = _touchPrototypes.size();
prototype->setPointId(id);
_touchPrototypes.insert(id, prototype);
}
@@ -825,7 +835,7 @@ void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
if (event->source() != Qt::MouseEventNotSynthesized && event->source() != Qt::MouseEventSynthesizedByQt)
return;
- if (_touchPoints.count() >= _minimumTouchPoints - 1 && _touchPoints.count() < _maximumTouchPoints) {
+ if (_touchPoints.size() >= _minimumTouchPoints - 1 && _touchPoints.size() < _maximumTouchPoints) {
updateTouchData(event);
}
}
@@ -873,13 +883,13 @@ void QQuickMultiPointTouchArea::ungrab(bool normalRelease)
if (!normalRelease)
ungrabTouchPoints();
- if (_touchPoints.count()) {
- for (QObject *obj : qAsConst(_touchPoints))
+ if (_touchPoints.size()) {
+ for (QObject *obj : std::as_const(_touchPoints))
static_cast<QQuickTouchPoint*>(obj)->setPressed(false);
if (!normalRelease)
emit canceled(_touchPoints.values());
clearTouchLists();
- for (QObject *obj : qAsConst(_touchPoints)) {
+ for (QObject *obj : std::as_const(_touchPoints)) {
QQuickTouchPoint *dtp = static_cast<QQuickTouchPoint*>(obj);
if (!dtp->isQmlDefined())
delete dtp;
@@ -910,8 +920,8 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
bool stealThisEvent = _stealMouse;
if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
QMutableSinglePointEvent mouseEvent(*event);
- const auto oldPosition = mouseEvent.mutablePoint().position();
- mouseEvent.mutablePoint().setPosition(localPos);
+ const auto oldPosition = mouseEvent.position();
+ QMutableEventPoint::setPosition(mouseEvent.point(0), localPos);
mouseEvent.setSource(Qt::MouseEventSynthesizedByQt);
mouseEvent.setAccepted(false);
QMouseEvent *pmouseEvent = static_cast<QMouseEvent *>(static_cast<QSinglePointEvent *>(&mouseEvent));
@@ -933,7 +943,7 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
grabMouse();
- mouseEvent.mutablePoint().setPosition(oldPosition);
+ QMutableEventPoint::setPosition(mouseEvent.point(0), oldPosition);
return stealThisEvent;
}
if (event->type() == QEvent::MouseButtonRelease) {
@@ -971,12 +981,12 @@ bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEve
}
if (!shouldFilter(event))
return false;
- updateTouchData(event);
+ updateTouchData(event, RemapEventPoints::ToLocal);
return _stealMouse;
case QEvent::TouchEnd: {
if (!shouldFilter(event))
return false;
- updateTouchData(event);
+ updateTouchData(event, RemapEventPoints::ToLocal);
ungrab(true);
}
break;
@@ -1029,7 +1039,7 @@ QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePain
{
Q_UNUSED(data);
- if (!qmlVisualTouchDebugging())
+ if (!qmlMptaVisualTouchDebugging())
return nullptr;
QSGInternalRectangleNode *rectangle = static_cast<QSGInternalRectangleNode *>(oldNode);