diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2017-09-12 09:55:25 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2017-09-12 09:56:04 +0200 |
commit | 29316abe1ad363179cfc2eefe31d085131d1dfd7 (patch) | |
tree | 4f1248046acb0a87de7f8762ec98de3fbc9f47f1 /src | |
parent | bde8c3cd9583ed9f3bdfc36a8699f56db20a6928 (diff) | |
parent | 47b3b1b10246cad6709c0cd99f02208dbaf6b7c0 (diff) |
Merge remote-tracking branch 'origin/5.10' into wip/new-backend
Change-Id: Iccb35fab856c7d8ec4aaaf021b70a65cfaa564b3
Diffstat (limited to 'src')
-rw-r--r-- | src/imports/shapes/qquickshapegenericrenderer.cpp | 34 | ||||
-rw-r--r-- | src/imports/shapes/qquickshapegenericrenderer_p.h | 7 | ||||
-rw-r--r-- | src/qml/doc/src/cppintegration/data.qdoc | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 2 | ||||
-rw-r--r-- | src/qmltest/quicktest.cpp | 68 | ||||
-rw-r--r-- | src/quick/handlers/qquickdraghandler.cpp | 6 | ||||
-rw-r--r-- | src/quick/handlers/qquickmultipointhandler.cpp | 10 | ||||
-rw-r--r-- | src/quick/handlers/qquickpinchhandler.cpp | 2 | ||||
-rw-r--r-- | src/quick/handlers/qquickpointerhandler.cpp | 4 | ||||
-rw-r--r-- | src/quick/handlers/qquicksinglepointhandler.cpp | 14 | ||||
-rw-r--r-- | src/quick/handlers/qquicktaphandler.cpp | 6 | ||||
-rw-r--r-- | src/quick/items/qquickevents.cpp | 12 | ||||
-rw-r--r-- | src/quick/items/qquickevents_p_p.h | 18 | ||||
-rw-r--r-- | src/quick/items/qquickpathview_p_p.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 284 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 11 |
17 files changed, 228 insertions, 261 deletions
diff --git a/src/imports/shapes/qquickshapegenericrenderer.cpp b/src/imports/shapes/qquickshapegenericrenderer.cpp index 98ba89dc3d..8131f02f1a 100644 --- a/src/imports/shapes/qquickshapegenericrenderer.cpp +++ b/src/imports/shapes/qquickshapegenericrenderer.cpp @@ -75,38 +75,32 @@ static inline QQuickShapeGenericRenderer::Color4ub colorToColor4ub(const QColor } QQuickShapeGenericStrokeFillNode::QQuickShapeGenericStrokeFillNode(QQuickWindow *window) - : m_geometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)), - m_window(window), - m_material(nullptr) + : m_material(nullptr) { - setGeometry(m_geometry); - activateMaterial(MatSolidColor); + setFlag(QSGNode::OwnsGeometry, true); + setGeometry(new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), 0, 0)); + activateMaterial(window, MatSolidColor); #ifdef QSG_RUNTIME_DESCRIPTION qsgnode_set_description(this, QLatin1String("stroke-fill")); #endif } -QQuickShapeGenericStrokeFillNode::~QQuickShapeGenericStrokeFillNode() -{ - delete m_geometry; -} - -void QQuickShapeGenericStrokeFillNode::activateMaterial(Material m) +void QQuickShapeGenericStrokeFillNode::activateMaterial(QQuickWindow *window, Material m) { switch (m) { case MatSolidColor: // Use vertexcolor material. Items with different colors remain batchable // this way, at the expense of having to provide per-vertex color values. - m_material.reset(QQuickShapeGenericMaterialFactory::createVertexColor(m_window)); + m_material.reset(QQuickShapeGenericMaterialFactory::createVertexColor(window)); break; case MatLinearGradient: - m_material.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(m_window, this)); + m_material.reset(QQuickShapeGenericMaterialFactory::createLinearGradient(window, this)); break; case MatRadialGradient: - m_material.reset(QQuickShapeGenericMaterialFactory::createRadialGradient(m_window, this)); + m_material.reset(QQuickShapeGenericMaterialFactory::createRadialGradient(window, this)); break; case MatConicalGradient: - m_material.reset(QQuickShapeGenericMaterialFactory::createConicalGradient(m_window, this)); + m_material.reset(QQuickShapeGenericMaterialFactory::createConicalGradient(window, this)); break; default: qWarning("Unknown material %d", m); @@ -583,7 +577,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen QQuickShapeGenericStrokeFillNode *n = node->m_fillNode; updateShadowDataInNode(d, n); - QSGGeometry *g = n->m_geometry; + QSGGeometry *g = n->geometry(); if (d->fillVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { g->allocate(0, 0); @@ -607,7 +601,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen default: Q_UNREACHABLE(); } - n->activateMaterial(gradMat); + n->activateMaterial(m_item->window(), gradMat); if (d->effectiveDirty & DirtyFillGradient) { // Gradients are implemented via a texture-based material. n->markDirty(QSGNode::DirtyMaterial); @@ -616,7 +610,7 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen return; } } else { - n->activateMaterial(QQuickShapeGenericStrokeFillNode::MatSolidColor); + n->activateMaterial(m_item->window(), QQuickShapeGenericStrokeFillNode::MatSolidColor); // fast path for updating only color values when no change in vertex positions if ((d->effectiveDirty & DirtyColor) && !(d->effectiveDirty & DirtyFillGeom)) { ColoredVertex *vdst = reinterpret_cast<ColoredVertex *>(g->vertexData()); @@ -633,8 +627,6 @@ void QQuickShapeGenericRenderer::updateFillNode(ShapePathData *d, QQuickShapeGen g = new QSGGeometry(QSGGeometry::defaultAttributes_ColoredPoint2D(), d->fillVertices.count(), indexCount, d->indexType); n->setGeometry(g); - delete n->m_geometry; - n->m_geometry = g; } else { g->allocate(d->fillVertices.count(), indexCount); } @@ -653,7 +645,7 @@ void QQuickShapeGenericRenderer::updateStrokeNode(ShapePathData *d, QQuickShapeG return; QQuickShapeGenericStrokeFillNode *n = node->m_strokeNode; - QSGGeometry *g = n->m_geometry; + QSGGeometry *g = n->geometry(); if (d->strokeVertices.isEmpty()) { if (g->vertexCount() || g->indexCount()) { g->allocate(0, 0); diff --git a/src/imports/shapes/qquickshapegenericrenderer_p.h b/src/imports/shapes/qquickshapegenericrenderer_p.h index 32cec798ec..11070ae7dc 100644 --- a/src/imports/shapes/qquickshapegenericrenderer_p.h +++ b/src/imports/shapes/qquickshapegenericrenderer_p.h @@ -205,7 +205,6 @@ class QQuickShapeGenericStrokeFillNode : public QSGGeometryNode { public: QQuickShapeGenericStrokeFillNode(QQuickWindow *window); - ~QQuickShapeGenericStrokeFillNode(); enum Material { MatSolidColor, @@ -214,16 +213,12 @@ public: MatConicalGradient }; - void activateMaterial(Material m); - - QQuickWindow *window() const { return m_window; } + void activateMaterial(QQuickWindow *window, Material m); // shadow data for custom materials QQuickAbstractPathRenderer::GradientDesc m_fillGradient; private: - QSGGeometry *m_geometry; - QQuickWindow *m_window; QScopedPointer<QSGMaterial> m_material; friend class QQuickShapeGenericRenderer; diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc index 65559f640a..c748161ee8 100644 --- a/src/qml/doc/src/cppintegration/data.qdoc +++ b/src/qml/doc/src/cppintegration/data.qdoc @@ -347,6 +347,11 @@ them with default constructed values, do not use the indexed delete operator ("delete sequence[i]") but instead use the \c {splice} function ("sequence.splice(startIndex, deleteCount)"). +\section2 QByteArray to JavaScript ArrayBuffer + +The QML engine provides automatic type conversion between QByteArray values and +JavaScript \c ArrayBuffer objects. + \section2 Value Types Some value types in Qt such as QPoint are represented in JavaScript as objects diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 531bfa3737..d10fd78973 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -930,10 +930,13 @@ void ExecutionEngine::markObjects(MarkStack *markStack) } classPool->markObjects(markStack); + markStack->drain(); for (QSet<CompiledData::CompilationUnit*>::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd(); - it != end; ++it) + it != end; ++it) { (*it)->markObjects(markStack); + markStack->drain(); + } } ReturnedValue ExecutionEngine::throwError(const Value &value) diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 3dfdbf572a..a9464c9759 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -812,10 +812,10 @@ void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cach const QMetaObject *cppMetaObject = cache->firstCppMetaObject(); while (cache && cache->metaObject() != cppMetaObject) { - QStringHash<int> *scoped = new QStringHash<int>(); int count = cache->qmlEnumCount(); for (int ii = 0; ii < count; ++ii) { + QStringHash<int> *scoped = new QStringHash<int>(); QQmlEnumData *enumData = cache->qmlEnum(ii); for (int jj = 0; jj < enumData->values.count(); ++jj) { diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp index 8cf0d2918e..993a411013 100644 --- a/src/qmltest/quicktest.cpp +++ b/src/qmltest/quicktest.cpp @@ -87,7 +87,7 @@ public: static QTestRootObject *instance() { static QPointer<QTestRootObject> object = new QTestRootObject; if (!object) { - qWarning("A new test root object has been created, the behavior may be compromised"); + // QTestRootObject was deleted when previous test ended, create a new one object = new QTestRootObject; } return object; @@ -331,43 +331,45 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD // Register the test object qmlRegisterSingletonType<QTestRootObject>("Qt.test.qtestroot", 1, 0, "QTestRootObject", testRootObject); + // Scan through all of the "tst_*.qml" files and run each of them - // in turn with a QQuickView. - QQuickView *view = new QQuickView; - view->setFlags(Qt::Window | Qt::WindowSystemMenuHint - | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint - | Qt::WindowCloseButtonHint); - QEventLoop eventLoop; - QObject::connect(view->engine(), SIGNAL(quit()), - QTestRootObject::instance(), SLOT(quit())); - QObject::connect(view->engine(), SIGNAL(quit()), - &eventLoop, SLOT(quit())); - view->rootContext()->setContextProperty - (QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead - for (const QString &path : qAsConst(imports)) - view->engine()->addImportPath(path); - for (const QString &path : qAsConst(pluginPaths)) - view->engine()->addPluginPath(path); + // in turn with a separate QQuickView (for test isolation). for (const QString &file : qAsConst(files)) { const QFileInfo fi(file); if (!fi.exists()) continue; - view->setObjectName(fi.baseName()); - view->setTitle(view->objectName()); + QQuickView view ; + view.setFlags(Qt::Window | Qt::WindowSystemMenuHint + | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint + | Qt::WindowCloseButtonHint); + QEventLoop eventLoop; + QObject::connect(view.engine(), SIGNAL(quit()), + QTestRootObject::instance(), SLOT(quit())); + QObject::connect(view.engine(), SIGNAL(quit()), + &eventLoop, SLOT(quit())); + view.rootContext()->setContextProperty + (QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead + for (const QString &path : qAsConst(imports)) + view.engine()->addImportPath(path); + for (const QString &path : qAsConst(pluginPaths)) + view.engine()->addPluginPath(path); + + view.setObjectName(fi.baseName()); + view.setTitle(view.objectName()); QTestRootObject::instance()->init(); QString path = fi.absoluteFilePath(); if (path.startsWith(QLatin1String(":/"))) - view->setSource(QUrl(QLatin1String("qrc:") + path.midRef(2))); + view.setSource(QUrl(QLatin1String("qrc:") + path.midRef(2))); else - view->setSource(QUrl::fromLocalFile(path)); + view.setSource(QUrl::fromLocalFile(path)); if (QTest::printAvailableFunctions) continue; - while (view->status() == QQuickView::Loading) + while (view.status() == QQuickView::Loading) QTest::qWait(10); - if (view->status() == QQuickView::Error) { - handleCompileErrors(fi, view); + if (view.status() == QQuickView::Error) { + handleCompileErrors(fi, &view); continue; } if (!QTestRootObject::instance()->hasQuit) { @@ -376,21 +378,21 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD // an asynchronous test and we need to show the window // and wait for the first frame to be rendered // and then wait for quit indication. - view->setFramePosition(QPoint(50, 50)); - if (view->size().isEmpty()) { // Avoid hangs with empty windows. - view->resize(200, 200); + view.setFramePosition(QPoint(50, 50)); + if (view.size().isEmpty()) { // Avoid hangs with empty windows. + view.resize(200, 200); } - view->show(); - if (!QTest::qWaitForWindowExposed(view)) { + view.show(); + if (!QTest::qWaitForWindowExposed(&view)) { qWarning().nospace() << "Test '" << QDir::toNativeSeparators(path) << "' window not exposed after show()."; } - view->requestActivate(); - if (!QTest::qWaitForWindowActive(view)) { + view.requestActivate(); + if (!QTest::qWaitForWindowActive(&view)) { qWarning().nospace() << "Test '" << QDir::toNativeSeparators(path) << "' window not active after requestActivate()."; } - if (view->isExposed()) { + if (view.isExposed()) { QTestRootObject::instance()->setWindowShown(true); } else { qWarning().nospace() @@ -399,13 +401,11 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD } if (!QTestRootObject::instance()->hasQuit && QTestRootObject::instance()->hasTestCase()) eventLoop.exec(); - // view->hide(); Causes a crash in Qt 3D due to deletion of the GL context, see QTBUG-27696 } } // Flush the current logging stream. QuickTestResult::setProgramName(0); - delete view; delete app; // Return the number of failures as the exit code. diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 49b391c7d5..840459ba3e 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -97,7 +97,7 @@ void QQuickDragHandler::handleEventPoint(QQuickEventPoint *point) setPassiveGrab(point); break; case QQuickEventPoint::Updated: { - QPointF delta = point->scenePos() - point->scenePressPos(); + QPointF delta = point->scenePosition() - point->scenePressPosition(); if (!m_xAxis.enabled()) delta.setX(0); if (!m_yAxis.enabled()) @@ -151,10 +151,10 @@ void QQuickDragHandler::initializeTargetStartPos(QQuickEventPoint *point) { if (target() && target()->parentItem() && m_targetStartPos.isNull()) { // prefer the m_targetStartPos we got when it got Pressed. m_targetStartPos = target()->parentItem()->mapToScene(target()->position()); - if (!target()->contains(point->pos())) { + if (!target()->contains(point->position())) { // If pressed outside of target item, move the target item so that the touchpoint is in its center, // while still respecting the axis constraints. - const QPointF center = target()->parentItem()->mapFromScene(point->scenePos()); + const QPointF center = target()->parentItem()->mapFromScene(point->scenePosition()); const QPointF pointCenteredInItemPos = target()->parentItem()->mapToScene(center - QPointF(target()->width(), target()->height())/2); if (m_xAxis.enabled()) m_targetStartPos.setX(pointCenteredInItemPos.x()); diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index 66b6fdb4a6..6cc7747e3a 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -93,7 +93,7 @@ QVector<QQuickEventPoint *> QQuickMultiPointHandler::eligiblePoints(QQuickPointe if (exclusiveGrabber && exclusiveGrabber != this) continue; } - if (p->state() != QQuickEventPoint::Released && targetBounds.contains(p->scenePos())) + if (p->state() != QQuickEventPoint::Released && targetBounds.contains(p->scenePosition())) ret << p; } return ret; @@ -146,7 +146,7 @@ QPointF QQuickMultiPointHandler::touchPointCentroid() if (Q_UNLIKELY(m_currentPoints.size() == 0)) return ret; for (QQuickEventPoint *point : qAsConst(m_currentPoints)) - ret += point->scenePos(); + ret += point->scenePosition(); return ret / m_currentPoints.size(); } @@ -166,7 +166,7 @@ qreal QQuickMultiPointHandler::averageTouchPointDistance(const QPointF &ref) if (Q_UNLIKELY(m_currentPoints.size() == 0)) return ret; for (QQuickEventPoint *point : qAsConst(m_currentPoints)) - ret += QVector2D(point->scenePos() - ref).length(); + ret += QVector2D(point->scenePosition() - ref).length(); return ret / m_currentPoints.size(); } @@ -177,7 +177,7 @@ qreal QQuickMultiPointHandler::averageStartingDistance(const QPointF &ref) if (Q_UNLIKELY(m_currentPoints.size() == 0)) return ret; for (QQuickEventPoint *point : qAsConst(m_currentPoints)) - ret += QVector2D(point->sceneGrabPos() - ref).length(); + ret += QVector2D(point->sceneGrabPosition() - ref).length(); return ret / m_currentPoints.size(); } @@ -186,7 +186,7 @@ QVector<QQuickMultiPointHandler::PointData> QQuickMultiPointHandler::angles(cons QVector<PointData> angles; angles.reserve(m_currentPoints.count()); for (QQuickEventPoint *point : qAsConst(m_currentPoints)) { - qreal angle = QLineF(ref, point->scenePos()).angle(); + qreal angle = QLineF(ref, point->scenePosition()).angle(); angles.append(PointData(point->pointId(), -angle)); // convert to clockwise, to be consistent with QQuickItem::rotation } return angles; diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 4dd51e744d..92bcc643f3 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -225,7 +225,7 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) Q_UNUSED(event) if (Q_UNLIKELY(lcPinchHandler().isDebugEnabled())) { for (QQuickEventPoint *point : qAsConst(m_currentPoints)) - qCDebug(lcPinchHandler) << point->state() << point->sceneGrabPos() << "->" << point->scenePos(); + qCDebug(lcPinchHandler) << point->state() << point->sceneGrabPosition() << "->" << point->scenePosition(); } bool containsReleasedPoints = event->isReleaseEvent(); diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index bcccfac318..14ce8fea03 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -152,14 +152,14 @@ void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point) QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const { - return (target() ? target()->mapFromScene(point->scenePos()) : point->scenePos()); + return (target() ? target()->mapFromScene(point->scenePosition()) : point->scenePosition()); } bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const { if (point) { if (QQuickItem *par = parentItem()) - return par->contains(par->mapFromScene(point->scenePos())); + return par->contains(par->mapFromScene(point->scenePosition())); } return false; } diff --git a/src/quick/handlers/qquicksinglepointhandler.cpp b/src/quick/handlers/qquicksinglepointhandler.cpp index 8747f5023d..2588c4c180 100644 --- a/src/quick/handlers/qquicksinglepointhandler.cpp +++ b/src/quick/handlers/qquicksinglepointhandler.cpp @@ -135,15 +135,15 @@ void QQuickSinglePointHandler::handlePointerEventImpl(QQuickPointerEvent *event) m_pointInfo.m_pressure = event->buttons() ? 1 : 0; m_pointInfo.m_ellipseDiameters = QSizeF(); } - m_pointInfo.m_position = currentPoint->pos(); - m_pointInfo.m_scenePosition = currentPoint->scenePos(); + m_pointInfo.m_position = currentPoint->position(); + m_pointInfo.m_scenePosition = currentPoint->scenePosition(); if (currentPoint->state() == QQuickEventPoint::Updated) m_pointInfo.m_velocity = currentPoint->velocity(); handleEventPoint(currentPoint); switch (currentPoint->state()) { case QQuickEventPoint::Pressed: - m_pointInfo.m_pressPosition = currentPoint->pos(); - m_pointInfo.m_scenePressPosition = currentPoint->scenePos(); + m_pointInfo.m_pressPosition = currentPoint->position(); + m_pointInfo.m_scenePressPosition = currentPoint->scenePosition(); m_pointInfo.m_pressedButtons = event->buttons(); break; case QQuickEventPoint::Released: @@ -169,12 +169,12 @@ void QQuickSinglePointHandler::onGrabChanged(QQuickPointerHandler *grabber, QQui return; switch (stateChange) { case QQuickEventPoint::GrabExclusive: - m_pointInfo.m_sceneGrabPosition = point->sceneGrabPos(); + m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition(); setActive(true); QQuickPointerHandler::onGrabChanged(grabber, stateChange, point); break; case QQuickEventPoint::GrabPassive: - m_pointInfo.m_sceneGrabPosition = point->sceneGrabPos(); + m_pointInfo.m_sceneGrabPosition = point->sceneGrabPosition(); QQuickPointerHandler::onGrabChanged(grabber, stateChange, point); break; case QQuickEventPoint::OverrideGrabPassive: @@ -199,7 +199,7 @@ void QQuickSinglePointHandler::setIgnoreAdditionalPoints(bool v) void QQuickSinglePointHandler::moveTarget(QPointF pos, QQuickEventPoint *point) { target()->setPosition(pos); - m_pointInfo.m_scenePosition = point->scenePos(); + m_pointInfo.m_scenePosition = point->scenePosition(); m_pointInfo.m_position = target()->mapFromScene(m_pointInfo.m_scenePosition); } diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index b8d9754cde..f99f84bdb0 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -102,7 +102,7 @@ QQuickTapHandler::~QQuickTapHandler() static bool dragOverThreshold(QQuickEventPoint *point) { - QPointF delta = point->scenePos() - point->scenePressPos(); + QPointF delta = point->scenePosition() - point->scenePressPosition(); return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) || QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point)); } @@ -280,7 +280,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi // Assuming here that pointerEvent()->timestamp() is in ms. qreal ts = point->pointerEvent()->timestamp() / 1000.0; if (ts - m_lastTapTimestamp < m_multiTapInterval && - QVector2D(point->scenePos() - m_lastTapPos).lengthSquared() < + QVector2D(point->scenePosition() - m_lastTapPos).lengthSquared() < (point->pointerEvent()->device()->type() == QQuickPointerDevice::Mouse ? m_mouseMultiClickDistanceSquared : m_touchMultiTapDistanceSquared)) ++m_tapCount; @@ -290,7 +290,7 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi emit tapped(); emit tapCountChanged(); m_lastTapTimestamp = ts; - m_lastTapPos = point->scenePos(); + m_lastTapPos = point->scenePosition(); } else { qCDebug(lcTapHandler) << objectName() << "tap threshold" << longPressThreshold() << "exceeded:" << point->timeHeld(); } diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index d133729625..90e72ebde6 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -548,7 +548,7 @@ void QQuickEventPoint::reset(Qt::TouchPointState state, const QPointF &scenePos, void QQuickEventPoint::localizePosition(QQuickItem *target) { if (target) - m_pos = target->mapFromScene(scenePos()); + m_pos = target->mapFromScene(scenePosition()); else m_pos = QPointF(); } @@ -938,8 +938,8 @@ QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event) if (auto point = pointById(pid)) { preserves[i].pointId = pid; preserves[i].pressTimestamp = point->m_pressTimestamp; - preserves[i].scenePressPos = point->scenePressPos(); - preserves[i].sceneGrabPos = point->sceneGrabPos(); + preserves[i].scenePressPos = point->scenePressPosition(); + preserves[i].sceneGrabPos = point->sceneGrabPosition(); preserves[i].grabber = point->exclusiveGrabber(); preserves[i].passiveGrabbers = point->passiveGrabbers(); } @@ -1155,7 +1155,7 @@ QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() cons QVector<QPointF> points; for (int i = 0; i < pointCount(); ++i) { if (!point(i)->isAccepted() && point(i)->state() == QQuickEventPoint::Pressed) - points << point(i)->scenePos(); + points << point(i)->scenePosition(); } return points; } @@ -1277,7 +1277,7 @@ QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool i if (isGrabber) anyGrabber = true; // include points inside the bounds if no other item is the grabber or if the item is filtering - bool isInside = item->contains(item->mapFromScene(p->scenePos())); + bool isInside = item->contains(item->mapFromScene(p->scenePosition())); bool hasAnotherGrabber = p->exclusiveGrabber() && p->exclusiveGrabber() != item; // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item @@ -1395,7 +1395,7 @@ Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *eve dbg << "QQuickEventPoint(accepted:" << event->isAccepted() << " state:"; QtDebugUtils::formatQEnum(dbg, event->state()); - dbg << " scenePos:" << event->scenePos() << " id:" << hex << event->pointId() << dec + dbg << " scenePos:" << event->scenePosition() << " id:" << hex << event->pointId() << dec << " timeHeld:" << event->timeHeld() << ')'; return dbg; } diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 48c29f00de..2954695b1b 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -253,10 +253,10 @@ class Q_QUICK_PRIVATE_EXPORT QQuickEventPoint : public QObject { Q_OBJECT Q_PROPERTY(QQuickPointerEvent *event READ pointerEvent) - Q_PROPERTY(QPointF pos READ pos) - Q_PROPERTY(QPointF scenePos READ scenePos) - Q_PROPERTY(QPointF scenePressPos READ scenePressPos) - Q_PROPERTY(QPointF sceneGrabPos READ sceneGrabPos) + Q_PROPERTY(QPointF position READ position) + Q_PROPERTY(QPointF scenePosition READ scenePosition) + Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition) + Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition) Q_PROPERTY(State state READ state) Q_PROPERTY(int pointId READ pointId) Q_PROPERTY(qreal timeHeld READ timeHeld) @@ -288,14 +288,14 @@ public: QQuickEventPoint(QQuickPointerEvent *parent); - void reset(Qt::TouchPointState state, const QPointF &scenePos, int pointId, ulong timestamp, const QVector2D &velocity = QVector2D()); + void reset(Qt::TouchPointState state, const QPointF &scenePosition, int pointId, ulong timestamp, const QVector2D &velocity = QVector2D()); void localizePosition(QQuickItem *target); QQuickPointerEvent *pointerEvent() const; - QPointF pos() const { return m_pos; } - QPointF scenePos() const { return m_scenePos; } - QPointF scenePressPos() const { return m_scenePressPos; } - QPointF sceneGrabPos() const { return m_sceneGrabPos; } + QPointF position() const { return m_pos; } + QPointF scenePosition() const { return m_scenePos; } + QPointF scenePressPosition() const { return m_scenePressPos; } + QPointF sceneGrabPosition() const { return m_sceneGrabPos; } QVector2D velocity() const { return m_velocity; } State state() const { return m_state; } int pointId() const { return m_pointId; } diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h index d58c986d1a..274086ea7c 100644 --- a/src/quick/items/qquickpathview_p_p.h +++ b/src/quick/items/qquickpathview_p_p.h @@ -153,7 +153,6 @@ public: bool moving : 1; bool flicking : 1; bool dragging : 1; - bool requestedOnPath : 1; bool inRequest : 1; bool delegateValidated : 1; bool inRefill : 1; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 2d129f0823..bd1a5076fd 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -780,8 +780,8 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) if (oldGrabber) { QEvent e(QEvent::UngrabMouse); - QSet<QQuickItem *> hasFiltered; - if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered)) + hasFiltered.clear(); + if (!sendFilteredMouseEvent(&e, oldGrabber, oldGrabber->parentItem())) oldGrabber->mouseUngrabEvent(); } } @@ -1667,7 +1667,7 @@ QMouseEvent *QQuickWindowPrivate::cloneMouseEvent(QMouseEvent *event, QPointF *t void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent) { auto point = pointerEvent->point(0); - lastMousePosition = point->scenePos(); + lastMousePosition = point->scenePosition(); const bool mouseIsReleased = (point->state() == QQuickEventPoint::Released && pointerEvent->buttons() == Qt::NoButton); if (point->exclusiveGrabber()) { @@ -1722,7 +1722,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven } // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) { - QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePos(), false, false); + QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePosition(), false, false); for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); pointerEvent->localize(item); @@ -1757,10 +1757,9 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, hoverEvent.setTimestamp(timestamp); hoverEvent.setAccepted(accepted); - QSet<QQuickItem *> hasFiltered; - if (sendFilteredMouseEvent(item->parentItem(), item, &hoverEvent, &hasFiltered)) { + hasFiltered.clear(); + if (sendFilteredMouseEvent(&hoverEvent, item, item->parentItem())) return true; - } QCoreApplication::sendEvent(item, &hoverEvent); @@ -2233,6 +2232,7 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) // the usecase a bit evil, but we at least don't want to lose events. ++pointerEventRecursionGuard; + skipDelivery.clear(); if (event->asPointerMouseEvent()) { deliverMouseEvent(event->asPointerMouseEvent()); } else if (event->asPointerTouchEvent()) { @@ -2387,7 +2387,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve QQuickEventPoint *point = event->point(i); if (point->state() == QQuickEventPoint::Pressed) continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false, false); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2419,7 +2419,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, point->setAccepted(false); // because otherwise touchEventForItem will ignore it if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released) point->setGrabberPointerHandler(nullptr, true); - QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), !isTouchEvent, isTouchEvent); + QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), !isTouchEvent, isTouchEvent); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2427,24 +2427,19 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, } } - if (allowChildEventFiltering && !handlersOnly) - updateFilteringParentItems(targetItems); - - QVarLengthArray<QQuickItem *> filteredItems; for (QQuickItem *item : targetItems) { - if (sendFilteredPointerEvent(event, item)) { + if (!handlersOnly && sendFilteredPointerEvent(event, item)) { if (event->isAccepted()) { for (int i = 0; i < event->pointCount(); ++i) event->point(i)->setAccepted(); return true; } - while (!filteringParentItems.isEmpty() && filteringParentItems.first().first == item) - filteringParentItems.removeFirst(); - filteredItems << item; + skipDelivery.append(item); } - // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event - if (filteredItems.contains(item)) + // Do not deliverMatchingPointsTo any item for which the filtering parent already intercepted the event, + // nor to any item which already had a chance to filter. + if (skipDelivery.contains(item)) continue; deliverMatchingPointsToItem(item, event, handlersOnly); if (event->allPointsAccepted()) @@ -2486,7 +2481,7 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo // The only reason to already have a mouse grabber here is // synthetic events - flickable sends one when setPressDelay is used. auto oldMouseGrabber = q->mouseGrabberItem(); - QPointF localPos = item->mapFromScene(point->scenePos()); + QPointF localPos = item->mapFromScene(point->scenePosition()); Q_ASSERT(item->contains(localPos)); // transform is checked already QMouseEvent *me = event->asMouseEvent(localPos); me->accept(); @@ -2515,8 +2510,6 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo bool eventAccepted = false; // If any parent filters the event, we're done. - // updateFilteringParentItems was called when the press occurred, - // and we assume that the filtering relationships don't change between press and release. if (sendFilteredPointerEvent(pointerEvent, item)) return; @@ -2728,167 +2721,146 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF } #endif -void QQuickWindowPrivate::updateFilteringParentItems(const QVector<QQuickItem *> &targetItems) +bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent) { - filteringParentItems.clear(); - for (QQuickItem *item : targetItems) { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - bool acceptsTouchEvents = item->acceptTouchEvents(); -#else - // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true. - bool acceptsTouchEvents = false; -#endif - QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item); - // If the item neither handles events nor has handlers which do, then it will never be a receiver, so filtering is irrelevant. - if (!item->acceptedMouseButtons() && !acceptsTouchEvents && - !(itemPriv->extra.isAllocated() && !itemPriv->extra->pointerHandlers.isEmpty())) - continue; - QQuickItem *parent = item->parentItem(); - while (parent) { - if (parent->filtersChildMouseEvents()) { - bool foundParent = false; - for (const QPair<QQuickItem*,QQuickItem*> existingItemAndParent : filteringParentItems) - if (existingItemAndParent.second == parent) - foundParent = true; - if (!foundParent) - filteringParentItems.append(QPair<QQuickItem*,QQuickItem*>(item, parent)); - } - parent = parent->parentItem(); - } - } - if (Q_UNLIKELY(DBG_MOUSE_TARGET().isDebugEnabled())) { - QStringList l; - for (QPair<QQuickItem *,QQuickItem *> pair : filteringParentItems) - l << (QLatin1String(pair.first->metaObject()->className()) + QLatin1Char(' ') + pair.first->objectName() + - QLatin1String(" <- ") + pair.second->metaObject()->className()) + QLatin1Char(' ') + pair.second->objectName(); - qCDebug(DBG_MOUSE_TARGET) << "potential filtering parents:" << l; - } + hasFiltered.clear(); + return sendFilteredPointerEventImpl(event, receiver, filteringParent ? filteringParent : receiver->parentItem()); } -bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver) +bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent) { if (!allowChildEventFiltering) return false; - bool ret = false; - QVarLengthArray<QQuickItem *> filteringParentsToSkip; - if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) { - for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) { - QQuickItem *item = receiver ? receiver : itemAndParent.first; - QQuickItem *filteringParent = itemAndParent.second; - if (item == filteringParent) - continue; // a filtering item never needs to filter for itself - if (filteringParentsToSkip.contains(filteringParent)) - continue; - QPointF localPos = item->mapFromScene(pme->point(0)->scenePos()); - QMouseEvent *me = pme->asMouseEvent(localPos); - if (filteringParent->childMouseEventFilter(item, me)) - ret = true; - filteringParentsToSkip.append(filteringParent); - } - } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { - QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; - for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) { - QQuickItem *item = receiver ? receiver : itemAndParent.first; - if (item != itemAndParent.first) - continue; - if (!item->acceptTouchEvents() && !item->acceptedMouseButtons()) - continue; // if this item won't accept, parents don't need to filter the touch for it - QQuickItem *filteringParent = itemAndParent.second; - if (item == filteringParent) - continue; // a filtering item never needs to filter for itself - // get a touch event customized for delivery to filteringParent - QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(filteringParent, true)); - if (!filteringParentTouchEvent) - continue; // all points are stationary, or no touchpoints inside that parent - if (filteringParent->childMouseEventFilter(item, filteringParentTouchEvent.data())) { - qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; - for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) - event->pointById(point.id())->setAccepted(); - ret = true; - break; - } - // filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event. - for (int i = 0; i < filteringParentTouchEvent->touchPoints().size(); ++i) { - const QTouchEvent::TouchPoint &tp = filteringParentTouchEvent->touchPoints().at(i); - - QEvent::Type t; - switch (tp.state()) { - case Qt::TouchPointPressed: - t = QEvent::MouseButtonPress; - break; - case Qt::TouchPointReleased: - t = QEvent::MouseButtonRelease; - break; - case Qt::TouchPointStationary: - continue; - default: - t = QEvent::MouseMove; - break; + if (!filteringParent) + return false; + bool filtered = false; + if (filteringParent->filtersChildMouseEvents() && !hasFiltered.contains(filteringParent)) { + hasFiltered.append(filteringParent); + if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) { + if (receiver->acceptedMouseButtons()) { + QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition()); + QMouseEvent *me = pme->asMouseEvent(localPos); + if (filteringParent->childMouseEventFilter(receiver, me)) { + qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); + filtered = true; } - - bool touchMouseUnset = (touchMouseId == -1); - // Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId - if (touchMouseUnset || touchMouseId == tp.id()) { - // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.) - // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that - QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), item, false)); - // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should - // report the touchpoint's grabber. Whenever we send a synthetic mouse event, - // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed. - touchMouseId = tp.id(); - touchMouseDevice = event->device(); - if (filteringParent->childMouseEventFilter(item, mouseEvent.data())) { - qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent; - if (t != QEvent::MouseButtonRelease) { - qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent; - pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent); - touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set - filteringParent->grabMouse(); - auto pointerEventPoint = pte->pointById(tp.id()); + } + } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool acceptsTouchEvents = receiver->acceptTouchEvents(); +#else + // In versions prior to Qt 6, we can't trust item->acceptTouchEvents() here, because it defaults to true. + bool acceptsTouchEvents = false; +#endif + if (acceptsTouchEvents || receiver->acceptedMouseButtons()) { + // get a touch event customized for delivery to filteringParent + QScopedPointer<QTouchEvent> filteringParentTouchEvent(pte->touchEventForItem(filteringParent, true)); + if (filteringParentTouchEvent) { + QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; + if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) { + qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); + filteringParent->grabMouse(); + for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) { + auto pointerEventPoint = pte->pointById(point.id()); for (auto handler : pointerEventPoint->passiveGrabbers()) { QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint); if (!passiveGrabsToCancel.contains(grab)) passiveGrabsToCancel.append(grab); } + event->pointById(point.id())->setAccepted(); + } + return true; + } else { + // filteringParent didn't filter the touch event. Give it a chance to filter a synthetic mouse event. + for (int i = 0; i < filteringParentTouchEvent->touchPoints().size(); ++i) { + const QTouchEvent::TouchPoint &tp = filteringParentTouchEvent->touchPoints().at(i); + + QEvent::Type t; + switch (tp.state()) { + case Qt::TouchPointPressed: + t = QEvent::MouseButtonPress; + break; + case Qt::TouchPointReleased: + t = QEvent::MouseButtonRelease; + break; + case Qt::TouchPointStationary: + continue; + default: + t = QEvent::MouseMove; + break; + } + + bool touchMouseUnset = (touchMouseId == -1); + // Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId + if (touchMouseUnset || touchMouseId == tp.id()) { + // convert filteringParentTouchEvent (which is already transformed wrt local position, velocity, etc.) + // into a synthetic mouse event, and let childMouseEventFilter() have another chance with that + QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, filteringParentTouchEvent.data(), receiver, false)); + // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should + // report the touchpoint's grabber. Whenever we send a synthetic mouse event, + // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed. + touchMouseId = tp.id(); + touchMouseDevice = event->device(); + if (filteringParent->childMouseEventFilter(receiver, mouseEvent.data())) { + qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); + if (t != QEvent::MouseButtonRelease) { + qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent; + pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent); + touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set + filteringParent->grabMouse(); + auto pointerEventPoint = pte->pointById(tp.id()); + for (auto handler : pointerEventPoint->passiveGrabbers()) { + QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint); + if (!passiveGrabsToCancel.contains(grab)) + passiveGrabsToCancel.append(grab); + } + } + filtered = true; + } + if (touchMouseUnset) { + // Now that we're done sending a synth mouse event, and it wasn't grabbed, + // the touchpoint is no longer acting as a synthetic mouse. Restore previous state. + touchMouseId = -1; + touchMouseDevice = nullptr; + } + // Only one touchpoint can be treated as a synthetic mouse, so after childMouseEventFilter + // has been called once, we're done with this loop over the touchpoints. + break; + } } - ret = true; - } - if (touchMouseUnset) { - // Now that we're done sending a synth mouse event, and it wasn't grabbed, - // the touchpoint is no longer acting as a synthetic mouse. Restore previous state. - touchMouseId = -1; - touchMouseDevice = nullptr; } - // Only one touchpoint can be treated as a synthetic mouse, so after childMouseEventFilter - // has been called once, we're done with this loop over the touchpoints. - break; + for (auto grab : passiveGrabsToCancel) + grab.second->cancelPassiveGrab(grab.first); } } } - for (auto grab : passiveGrabsToCancel) - grab.second->cancelPassiveGrab(grab.first); } - return ret; + return sendFilteredPointerEventImpl(event, receiver, filteringParent->parentItem()) || filtered; } -bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event, QSet<QQuickItem *> *hasFiltered) +bool QQuickWindowPrivate::sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent) { - if (!target) + if (!filteringParent) return false; - QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target); - if (targetPrivate->replayingPressEvent) + QQuickItemPrivate *filteringParentPrivate = QQuickItemPrivate::get(filteringParent); + if (filteringParentPrivate->replayingPressEvent) return false; bool filtered = false; - if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) { - hasFiltered->insert(target); - if (target->childMouseEventFilter(item, event)) + if (filteringParentPrivate->filtersChildMouseEvents && !hasFiltered.contains(filteringParent)) { + hasFiltered.append(filteringParent); + if (filteringParent->childMouseEventFilter(receiver, event)) { filtered = true; - qCDebug(DBG_MOUSE_TARGET) << "for" << item << target << "childMouseEventFilter ->" << filtered; + skipDelivery.append(filteringParent); + } + qCDebug(DBG_MOUSE_TARGET) << "for" << receiver << filteringParent << "childMouseEventFilter ->" << filtered; } - return sendFilteredMouseEvent(target->parentItem(), item, event, hasFiltered) || filtered; + return sendFilteredMouseEvent(event, receiver, filteringParent->parentItem()) || filtered; } bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold) @@ -3038,8 +3010,8 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e) case QEvent::MouseButtonDblClick: case QEvent::MouseMove: { // XXX todo - should sendEvent be doing this? how does it relate to forwarded events? - QSet<QQuickItem *> hasFiltered; - if (!d->sendFilteredMouseEvent(item->parentItem(), item, e, &hasFiltered)) { + d->hasFiltered.clear(); + if (!d->sendFilteredMouseEvent(e, item, item->parentItem())) { // accept because qml items by default accept and have to explicitly opt out of accepting e->accept(); QCoreApplication::sendEvent(item, e); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 36b2c57e5c..0399b26f62 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -147,8 +147,9 @@ public: void removeGrabber(QQuickItem *grabber, bool mouse = true, bool touch = true); static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0); void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent); - bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet<QQuickItem *> *); - bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver); + bool sendFilteredMouseEvent(QEvent *event, QQuickItem *receiver, QQuickItem *filteringParent); + bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent = nullptr); + bool sendFilteredPointerEventImpl(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem *filteringParent); #if QT_CONFIG(wheelevent) bool deliverWheelEvent(QQuickItem *, QWheelEvent *); #endif @@ -178,7 +179,6 @@ public: QVector<QQuickItem *> pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons, bool checkAcceptsTouch) const; QVector<QQuickItem *> mergePointerTargets(const QVector<QQuickItem *> &list1, const QVector<QQuickItem *> &list2) const; - void updateFilteringParentItems(const QVector<QQuickItem *> &targetItems); // hover delivery bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted); @@ -227,7 +227,8 @@ public: QList<QSGNode *> cleanupNodeList; QVector<QQuickItem *> itemsToPolish; - QVector<QPair<QQuickItem *,QQuickItem *> > filteringParentItems; // item:parent pairs + QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called + QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary qreal devicePixelRatio; QMetaObject::Connection physicalDpiChangedConnection; @@ -298,7 +299,7 @@ public: static bool dragOverThreshold(const QQuickEventPoint *point) { - QPointF delta = point->scenePos() - point->scenePressPos(); + QPointF delta = point->scenePosition() - point->scenePressPosition(); return (QQuickWindowPrivate::dragOverThreshold(delta.x(), Qt::XAxis, point) || QQuickWindowPrivate::dragOverThreshold(delta.y(), Qt::YAxis, point)); } |