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.cpp347
1 files changed, 176 insertions, 171 deletions
diff --git a/src/quick/items/qquickmultipointtoucharea.cpp b/src/quick/items/qquickmultipointtoucharea.cpp
index 3eca535a67..b0b99334a2 100644
--- a/src/quick/items/qquickmultipointtoucharea.cpp
+++ b/src/quick/items/qquickmultipointtoucharea.cpp
@@ -1,47 +1,15 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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/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>
#include <QDebug>
@@ -49,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
@@ -86,20 +54,18 @@ void QQuickTouchPoint::setPointId(int id)
These properties hold the current position of the touch point.
*/
-void QQuickTouchPoint::setX(qreal x)
+void QQuickTouchPoint::setPosition(QPointF p)
{
- if (_x == x)
+ bool xch = (_x != p.x());
+ bool ych = (_y != p.y());
+ if (!xch && !ych)
return;
- _x = x;
- emit xChanged();
-}
-
-void QQuickTouchPoint::setY(qreal y)
-{
- if (_y == y)
- return;
- _y = y;
- emit yChanged();
+ _x = p.x();
+ _y = p.y();
+ if (xch)
+ emit xChanged();
+ if (ych)
+ emit yChanged();
}
/*!
@@ -149,7 +115,7 @@ void QQuickTouchPoint::setPressure(qreal pressure)
positive angle means it's rotated to the right. Most touchscreens do not
detect rotation, so zero is the most common value.
- \sa QTouchEvent::TouchPoint::rotation()
+ \sa QEventPoint::rotation()
*/
void QQuickTouchPoint::setRotation(qreal r)
{
@@ -267,7 +233,7 @@ void QQuickTouchPoint::setSceneY(qreal sceneY)
}
/*!
- \qmlproperty PointingDeviceUniqueId QtQuick::TouchPoint::uniqueId
+ \qmlproperty pointingDeviceUniqueId QtQuick::TouchPoint::uniqueId
\since 5.9
This property holds the unique ID of the touch point or token.
@@ -364,7 +330,12 @@ 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.
- The corresponding handler is \c onPressed.
+ \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
*/
/*!
@@ -372,7 +343,12 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
This signal is emitted when existing touch points are updated. \a touchPoints is a list of these updated points.
- The corresponding handler is \c onUpdated.
+ \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
*/
/*!
@@ -380,7 +356,12 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
This signal is emitted when existing touch points are removed. \a touchPoints is a list of these removed points.
- The corresponding handler is \c onReleased.
+ \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
*/
/*!
@@ -397,9 +378,16 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
\a touchPoints is the list of canceled points.
- The corresponding handler is \c onCanceled.
+ \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)
@@ -410,9 +398,7 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
area should grab the current touch points. By default they will not be grabbed; to grab them call \c gesture.grab(). If the
gesture is not grabbed, the nesting Flickable, for example, would also have an opportunity to grab.
- The gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
-
- The corresponding handler is \c onGestureStarted.
+ The \a gesture object also includes information on the current set of \c touchPoints and the \c dragThreshold.
*/
/*!
@@ -421,8 +407,6 @@ void QQuickTouchPoint::setUniqueId(const QPointingDeviceUniqueId &id)
This signal is emitted when the touch points handled by the MultiPointTouchArea change. This includes adding new touch points,
removing or canceling previous touch points, as well as updating current touch point data. \a touchPoints is the list of all current touch
points.
-
- The corresponding handler is \c onTouchUpdated.
*/
/*!
@@ -447,16 +431,17 @@ QQuickMultiPointTouchArea::QQuickMultiPointTouchArea(QQuickItem *parent)
: QQuickItem(parent),
_minimumTouchPoints(0),
_maximumTouchPoints(INT_MAX),
+ _touchMouseDevice(nullptr),
_stealMouse(false),
_mouseEnabled(true)
{
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
}
@@ -464,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;
@@ -551,7 +536,7 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
updateTouchData(event);
if (event->type() == QEvent::TouchEnd)
- ungrab();
+ ungrab(true);
break;
}
case QEvent::TouchCancel:
@@ -563,60 +548,59 @@ void QQuickMultiPointTouchArea::touchEvent(QTouchEvent *event)
}
}
-void QQuickMultiPointTouchArea::grabGesture()
+void QQuickMultiPointTouchArea::grabGesture(QPointingDevice *dev)
{
_stealMouse = true;
grabMouse();
setKeepMouseGrab(true);
- QVector<int> ids;
- ids.reserve(_touchPoints.size());
+ QPointingDevicePrivate *devPriv = QPointingDevicePrivate::get(dev);
for (auto it = _touchPoints.keyBegin(), end = _touchPoints.keyEnd(); it != end; ++it) {
if (*it != -1) // -1 might be the mouse-point, but we already grabbed the mouse above.
- ids.append(*it);
+ if (auto pt = devPriv->queryPointById(*it))
+ pt->exclusiveGrabber = this;
}
- grabTouchPoints(ids);
setKeepTouchGrab(true);
}
-void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
+void QQuickMultiPointTouchArea::updateTouchData(QEvent *event, RemapEventPoints remap)
{
bool ended = false;
bool moved = false;
bool started = false;
- bool isMouseEvent = false;
clearTouchLists();
- QList<QTouchEvent::TouchPoint> touchPoints;
+ QList<QEventPoint> touchPoints;
+ bool touchPointsFromEvent = false;
+ QPointingDevice *dev = nullptr;
switch (event->type()) {
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
- touchPoints = static_cast<QTouchEvent*>(event)->touchPoints();
+ case QEvent::TouchEnd: {
+ QTouchEvent* te = static_cast<QTouchEvent*>(event);
+ touchPoints = te->points();
+ touchPointsFromEvent = true;
+ dev = const_cast<QPointingDevice *>(te->pointingDevice());
break;
- case QEvent::MouseButtonPress:
+ }
+ case QEvent::MouseButtonPress: {
+ auto da = QQuickItemPrivate::get(this)->deliveryAgentPrivate();
+ _mouseQpaTouchPoint = QEventPoint(da->touchMouseId);
+ _touchMouseDevice = da->touchMouseDevice;
+ Q_FALLTHROUGH();
+ }
case QEvent::MouseMove:
case QEvent::MouseButtonRelease: {
QMouseEvent *me = static_cast<QMouseEvent*>(event);
- _mouseQpaTouchPoint.setPos(me->localPos());
- _mouseQpaTouchPoint.setScenePos(me->windowPos());
- _mouseQpaTouchPoint.setScreenPos(me->screenPos());
- if (event->type() == QEvent::MouseMove)
- _mouseQpaTouchPoint.setState(Qt::TouchPointMoved);
- else if (event->type() == QEvent::MouseButtonRelease)
- _mouseQpaTouchPoint.setState(Qt::TouchPointReleased);
- else { // QEvent::MouseButtonPress
+ _mouseQpaTouchPoint = me->points().first();
+ dev = const_cast<QPointingDevice *>(me->pointingDevice());
+ if (event->type() == QEvent::MouseButtonPress) {
addTouchPoint(me);
started = true;
- _mouseQpaTouchPoint.setStartPos(me->localPos());
- _mouseQpaTouchPoint.setStartScenePos(me->windowPos());
- _mouseQpaTouchPoint.setStartScreenPos(me->screenPos());
- _mouseQpaTouchPoint.setState(Qt::TouchPointPressed);
}
touchPoints << _mouseQpaTouchPoint;
- isMouseEvent = true;
break;
}
default:
@@ -624,17 +608,12 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
break;
}
- if (!isMouseEvent && _mouseTouchPoint) {
- QQuickWindow *c = window();
- if (c && c->mouseGrabberItem() == this)
- touchPoints << _mouseQpaTouchPoint;
- }
- int numTouchPoints = touchPoints.count();
+ int numTouchPoints = touchPoints.size();
//always remove released touches, and make sure we handle all releases before adds.
- for (const QTouchEvent::TouchPoint &p : qAsConst(touchPoints)) {
- Qt::TouchPointState touchPointState = p.state();
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
+ QEventPoint::State touchPointState = p.state();
int id = p.id();
- if (touchPointState & Qt::TouchPointReleased) {
+ if (touchPointState & QEventPoint::State::Released) {
QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
if (!dtp)
continue;
@@ -646,16 +625,22 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
}
}
if (numTouchPoints >= _minimumTouchPoints && numTouchPoints <= _maximumTouchPoints) {
- for (const QTouchEvent::TouchPoint &p : qAsConst(touchPoints)) {
- Qt::TouchPointState touchPointState = p.state();
+ 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 & Qt::TouchPointReleased) {
+ if (touchPointState & QEventPoint::State::Released) {
//handled above
} else if (!_touchPoints.contains(id)) { //could be pressed, moved, or stationary
// (we may have just obtained enough points to start tracking them -- in that case moved or stationary count as newly pressed)
addTouchPoint(&p);
started = true;
- } else if (touchPointState & Qt::TouchPointMoved) {
+ } else if ((touchPointState & QEventPoint::State::Updated) ||
+ (touchPointState & QEventPoint::State::Stationary)) {
+ // React to a stationary point as if the point moved. (QTBUG-77142)
QQuickTouchPoint* dtp = static_cast<QQuickTouchPoint*>(_touchPoints.value(id));
Q_ASSERT(dtp);
_movedTouchPoints.append(dtp);
@@ -672,11 +657,11 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
if (!_stealMouse /* !ignoring gesture*/) {
bool offerGrab = false;
const int dragThreshold = QGuiApplication::styleHints()->startDragDistance();
- for (const QTouchEvent::TouchPoint &p : qAsConst(touchPoints)) {
- if (p.state() == Qt::TouchPointReleased)
+ for (const QEventPoint &p : std::as_const(touchPoints)) {
+ if (p.state() == QEventPoint::State::Released)
continue;
- const QPointF &currentPos = p.scenePos();
- const QPointF &startPos = p.startScenePos();
+ const QPointF &currentPos = p.scenePosition();
+ const QPointF &startPos = p.scenePressPosition();
if (qAbs(currentPos.x() - startPos.x()) > dragThreshold)
offerGrab = true;
else if (qAbs(currentPos.y() - startPos.y()) > dragThreshold)
@@ -689,8 +674,8 @@ void QQuickMultiPointTouchArea::updateTouchData(QEvent *event)
QQuickGrabGestureEvent event;
event._touchPoints = _touchPoints.values();
emit gestureStarted(&event);
- if (event.wantsGrab())
- grabGesture();
+ if (event.wantsGrab() && dev)
+ grabGesture(dev);
}
}
@@ -698,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());
}
@@ -706,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());
@@ -720,10 +705,10 @@ void QQuickMultiPointTouchArea::clearTouchLists()
_movedTouchPoints.clear();
}
-void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *p)
+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;
@@ -743,33 +728,36 @@ void QQuickMultiPointTouchArea::addTouchPoint(const QTouchEvent::TouchPoint *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);
updateTouchPoint(dtp, e);
dtp->setPressed(true);
- _touchPoints.insert(-1, dtp);
+ _touchPoints.insert(_mouseQpaTouchPoint.id(), dtp);
_pressedTouchPoints.append(dtp);
_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)
@@ -783,47 +771,54 @@ 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);
}
-void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QTouchEvent::TouchPoint *p)
+void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QEventPoint *p)
{
//TODO: if !qmlDefined, could bypass setters.
// also, should only emit signals after all values have been set
dtp->setUniqueId(p->uniqueId());
- dtp->setX(p->pos().x());
- dtp->setY(p->pos().y());
+ dtp->setPosition(p->position());
dtp->setEllipseDiameters(p->ellipseDiameters());
dtp->setPressure(p->pressure());
dtp->setRotation(p->rotation());
dtp->setVelocity(p->velocity());
- dtp->setArea(p->rect());
- dtp->setStartX(p->startPos().x());
- dtp->setStartY(p->startPos().y());
- dtp->setPreviousX(p->lastPos().x());
- dtp->setPreviousY(p->lastPos().y());
- dtp->setSceneX(p->scenePos().x());
- dtp->setSceneY(p->scenePos().y());
+ QRectF area(QPointF(), p->ellipseDiameters());
+ area.moveCenter(p->position());
+ dtp->setArea(area);
+ dtp->setStartX(p->pressPosition().x());
+ dtp->setStartY(p->pressPosition().y());
+ dtp->setPreviousX(p->lastPosition().x());
+ dtp->setPreviousY(p->lastPosition().y());
+ dtp->setSceneX(p->scenePosition().x());
+ dtp->setSceneY(p->scenePosition().y());
}
void QQuickMultiPointTouchArea::updateTouchPoint(QQuickTouchPoint *dtp, const QMouseEvent *e)
{
dtp->setPreviousX(dtp->x());
dtp->setPreviousY(dtp->y());
- dtp->setX(e->localPos().x());
- dtp->setY(e->localPos().y());
+ dtp->setPosition(e->position());
if (e->type() == QEvent::MouseButtonPress) {
- dtp->setStartX(e->localPos().x());
- dtp->setStartY(e->localPos().y());
+ dtp->setStartX(e->position().x());
+ dtp->setStartY(e->position().y());
}
- dtp->setSceneX(e->windowPos().x());
- dtp->setSceneY(e->windowPos().y());
+ dtp->setSceneX(e->scenePosition().x());
+ dtp->setSceneY(e->scenePosition().y());
}
void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
@@ -836,12 +831,11 @@ void QQuickMultiPointTouchArea::mousePressEvent(QMouseEvent *event)
_stealMouse = false;
setKeepMouseGrab(false);
event->setAccepted(true);
- _mousePos = event->localPos();
-
- if (event->source() != Qt::MouseEventNotSynthesized)
+ _mousePos = event->position();
+ 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);
}
}
@@ -853,7 +847,7 @@ void QQuickMultiPointTouchArea::mouseMoveEvent(QMouseEvent *event)
return;
}
- if (event->source() != Qt::MouseEventNotSynthesized)
+ if (event->source() != Qt::MouseEventNotSynthesized && event->source() != Qt::MouseEventSynthesizedByQt)
return;
_movedTouchPoints.clear();
@@ -868,7 +862,7 @@ void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
return;
}
- if (event->source() != Qt::MouseEventNotSynthesized)
+ if (event->source() != Qt::MouseEventNotSynthesized && event->source() != Qt::MouseEventSynthesizedByQt)
return;
if (_mouseTouchPoint) {
@@ -878,25 +872,24 @@ void QQuickMultiPointTouchArea::mouseReleaseEvent(QMouseEvent *event)
_mouseTouchPoint = nullptr;
}
- QQuickWindow *c = window();
- if (c && c->mouseGrabberItem() == this)
- ungrabMouse();
setKeepMouseGrab(false);
}
-void QQuickMultiPointTouchArea::ungrab()
+void QQuickMultiPointTouchArea::ungrab(bool normalRelease)
{
_stealMouse = false;
setKeepMouseGrab(false);
setKeepTouchGrab(false);
- ungrabTouchPoints();
+ 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);
- emit canceled(_touchPoints.values());
+ 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;
@@ -920,29 +913,28 @@ void QQuickMultiPointTouchArea::touchUngrabEvent()
bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
{
- QPointF localPos = mapFromScene(event->windowPos());
+ const QPointF localPos = mapFromScene(event->scenePosition());
QQuickWindow *c = window();
QQuickItem *grabber = c ? c->mouseGrabberItem() : nullptr;
bool stealThisEvent = _stealMouse;
if ((stealThisEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
- QMouseEvent mouseEvent(event->type(), localPos, event->windowPos(), event->screenPos(),
- event->button(), event->buttons(), event->modifiers());
+ QMutableSinglePointEvent mouseEvent(*event);
+ const auto oldPosition = mouseEvent.position();
+ QMutableEventPoint::setPosition(mouseEvent.point(0), localPos);
+ mouseEvent.setSource(Qt::MouseEventSynthesizedByQt);
mouseEvent.setAccepted(false);
- QGuiApplicationPrivate::setMouseEventCapsAndVelocity(&mouseEvent,
- QGuiApplicationPrivate::mouseEventCaps(event),
- QGuiApplicationPrivate::mouseEventVelocity(event));
- QGuiApplicationPrivate::setMouseEventSource(&mouseEvent, Qt::MouseEventSynthesizedByQt);
+ QMouseEvent *pmouseEvent = static_cast<QMouseEvent *>(static_cast<QSinglePointEvent *>(&mouseEvent));
switch (mouseEvent.type()) {
case QEvent::MouseMove:
- mouseMoveEvent(&mouseEvent);
+ mouseMoveEvent(pmouseEvent);
break;
case QEvent::MouseButtonPress:
- mousePressEvent(&mouseEvent);
+ mousePressEvent(pmouseEvent);
break;
case QEvent::MouseButtonRelease:
- mouseReleaseEvent(&mouseEvent);
+ mouseReleaseEvent(pmouseEvent);
break;
default:
break;
@@ -951,6 +943,7 @@ bool QQuickMultiPointTouchArea::sendMouseEvent(QMouseEvent *event)
if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this)
grabMouse();
+ QMutableEventPoint::setPosition(mouseEvent.point(0), oldPosition);
return stealThisEvent;
}
if (event->type() == QEvent::MouseButtonRelease) {
@@ -967,22 +960,34 @@ bool QQuickMultiPointTouchArea::childMouseEventFilter(QQuickItem *receiver, QEve
if (!isEnabled() || !isVisible())
return QQuickItem::childMouseEventFilter(receiver, event);
switch (event->type()) {
- case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonPress: {
+ auto da = QQuickItemPrivate::get(this)->deliveryAgentPrivate();
+ // If we already got a chance to filter the touchpoint that generated this synth-mouse-press,
+ // and chose not to filter it, ignore it now, too.
+ if (static_cast<QMouseEvent *>(event)->source() == Qt::MouseEventSynthesizedByQt &&
+ _lastFilterableTouchPointIds.contains(da->touchMouseId))
+ return false;
+ } Q_FALLTHROUGH();
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
return sendMouseEvent(static_cast<QMouseEvent *>(event));
- break;
case QEvent::TouchBegin:
+ _lastFilterableTouchPointIds.clear();
+ Q_FALLTHROUGH();
case QEvent::TouchUpdate:
+ for (const auto &tp : static_cast<QTouchEvent*>(event)->points()) {
+ if (tp.state() == QEventPoint::State::Pressed)
+ _lastFilterableTouchPointIds << tp.id();
+ }
if (!shouldFilter(event))
return false;
- updateTouchData(event);
+ updateTouchData(event, RemapEventPoints::ToLocal);
return _stealMouse;
case QEvent::TouchEnd: {
if (!shouldFilter(event))
return false;
- updateTouchData(event);
- ungrab();
+ updateTouchData(event, RemapEventPoints::ToLocal);
+ ungrab(true);
}
break;
default:
@@ -1004,15 +1009,15 @@ bool QQuickMultiPointTouchArea::shouldFilter(QEvent *event)
case QEvent::MouseMove:
case QEvent::MouseButtonRelease: {
QMouseEvent *me = static_cast<QMouseEvent*>(event);
- containsPoint = contains(mapFromScene(me->windowPos()));
+ containsPoint = contains(mapFromScene(me->scenePosition()));
}
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd: {
QTouchEvent *te = static_cast<QTouchEvent*>(event);
- for (const QTouchEvent::TouchPoint &point : te->touchPoints()) {
- if (contains(mapFromScene(point.scenePos()))) {
+ for (const QEventPoint &point : te->points()) {
+ if (contains(mapFromScene(point.scenePosition()))) {
containsPoint = true;
break;
}
@@ -1034,7 +1039,7 @@ QSGNode *QQuickMultiPointTouchArea::updatePaintNode(QSGNode *oldNode, UpdatePain
{
Q_UNUSED(data);
- if (!qmlVisualTouchDebugging())
+ if (!qmlMptaVisualTouchDebugging())
return nullptr;
QSGInternalRectangleNode *rectangle = static_cast<QSGInternalRectangleNode *>(oldNode);