From 32063559d6232ec9af3c9004ea66fd57d2e690f5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 4 Aug 2017 11:28:25 +0200 Subject: shapes: Reduce stroke/fill node data Do not store the superfluous window and geometry pointers. Change-Id: Ib9cf4e62bdc6f32dc99cda25eddfebdfa05d579b Reviewed-by: Andy Nichols --- src/imports/shapes/qquickshapegenericrenderer.cpp | 34 +++++++++-------------- src/imports/shapes/qquickshapegenericrenderer_p.h | 7 +---- 2 files changed, 14 insertions(+), 27 deletions(-) (limited to 'src') 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(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 m_material; friend class QQuickShapeGenericRenderer; -- cgit v1.2.3 From be3559470ac934dcfed881996be0eeb1269e6f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 4 Sep 2017 17:42:35 +0200 Subject: qmltest: Run each test in a separate QQuickView for test isolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want the individual tests to affect each other by what state they leave the QQuickView (and corresponding QWindow and platform window) in when they finish. Task-number: QTBUG-62963 Change-Id: I90ad2364c8e9b769afc61eb762c4a604a567a856 Reviewed-by: Simon Hausmann Reviewed-by: Morten Johan Sørvig Reviewed-by: Mitch Curtis Reviewed-by: Shawn Rutledge --- src/qmltest/quicktest.cpp | 68 +++++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'src') 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 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("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. -- cgit v1.2.3 From 2617ac5b9df7dfdecf0cb02d5933c40df1a55bbc Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Sun, 3 Sep 2017 18:42:09 +0200 Subject: rename QQuickEventPoint pos properties to position MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For consistency we always spell it out, although it does make some of these properties inconveniently verbose. Change-Id: I64a08c3aa261c0ab89e09472dd47510abafbf7ca Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquickdraghandler.cpp | 6 +++--- src/quick/handlers/qquickmultipointhandler.cpp | 10 +++++----- src/quick/handlers/qquickpinchhandler.cpp | 2 +- src/quick/handlers/qquickpointerhandler.cpp | 4 ++-- src/quick/handlers/qquicksinglepointhandler.cpp | 14 +++++++------- src/quick/handlers/qquicktaphandler.cpp | 6 +++--- src/quick/items/qquickevents.cpp | 12 ++++++------ src/quick/items/qquickevents_p_p.h | 18 +++++++++--------- src/quick/items/qquickwindow.cpp | 12 ++++++------ src/quick/items/qquickwindow_p.h | 2 +- 10 files changed, 43 insertions(+), 43 deletions(-) (limited to 'src') 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 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::angles(cons QVector 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 QQuickPointerEvent::unacceptedPressedPointScenePositions() cons QVector 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/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 2d129f0823..eb90e92b96 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -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 targetItems = pointerTargets(contentItem, point->scenePos(), false, false); + QVector targetItems = pointerTargets(contentItem, point->scenePosition(), false, false); for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); pointerEvent->localize(item); @@ -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 targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false, false); + QVector 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 targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), !isTouchEvent, isTouchEvent); + QVector targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), !isTouchEvent, isTouchEvent); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); } else { @@ -2486,7 +2486,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(); @@ -2779,7 +2779,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ continue; // a filtering item never needs to filter for itself if (filteringParentsToSkip.contains(filteringParent)) continue; - QPointF localPos = item->mapFromScene(pme->point(0)->scenePos()); + QPointF localPos = item->mapFromScene(pme->point(0)->scenePosition()); QMouseEvent *me = pme->asMouseEvent(localPos); if (filteringParent->childMouseEventFilter(item, me)) ret = true; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 36b2c57e5c..0bd909603d 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -298,7 +298,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)); } -- cgit v1.2.3 From 0234e5c96417f451f8de279b8ff92734836badd4 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 5 Sep 2017 16:50:52 +0200 Subject: QByteArray gets mapped to ArrayBuffer Change-Id: I884e6c747af6dfffce23fa21fc320be53951a7d4 Reviewed-by: Simon Hausmann --- src/qml/doc/src/cppintegration/data.qdoc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') 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 -- cgit v1.2.3 From 19054b5449755e27d54793492c41095cc630cb91 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 29 Aug 2017 10:12:32 +0200 Subject: sendFilteredPointerEvent: go back to parent traversal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The filteringParentItems vector-of-pairs is getting more and more questionable: it needs to have more pairs than we thought, then we need to remove them to prevent multiple-filtering, and then we also need to keep track of which ones we removed plus which ones are actually filtering, in order to avoid direct delivery of pointer events to the same Item after it already filtered from its children. The overhead doesn't seem worthwhile anymore. So this conceptually reverts 9b5fc80af28580e9672792dd511d876a93947882 but with some improvements. Also, do not deliver events to child-filtering items which have already filtered. Change-Id: I9d4f977dba695de7eb78ab536e0e6e8fd6a253a7 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 231 +++++++++++++++++---------------------- src/quick/items/qquickwindow_p.h | 6 +- 2 files changed, 103 insertions(+), 134 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index eb90e92b96..21f06febde 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2427,25 +2427,24 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, } } - if (allowChildEventFiltering && !handlersOnly) - updateFilteringParentItems(targetItems); - QVarLengthArray 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; } // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event if (filteredItems.contains(item)) continue; + // Do not deliverMatchingPointsTo any item which already had a chance to filter + // e.g. if Flickable has filtered events from one of its children, it does not need normal delivery + if (hasFiltered.contains(item)) + continue; deliverMatchingPointsToItem(item, event, handlersOnly); if (event->allPointsAccepted()) break; @@ -2515,8 +2514,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,147 +2725,119 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF } #endif -void QQuickWindowPrivate::updateFilteringParentItems(const QVector &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 existingItemAndParent : filteringParentItems) - if (existingItemAndParent.second == parent) - foundParent = true; - if (!foundParent) - filteringParentItems.append(QPair(item, parent)); - } - parent = parent->parentItem(); - } - } - if (Q_UNLIKELY(DBG_MOUSE_TARGET().isDebugEnabled())) { - QStringList l; - for (QPair 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 filteringParentsToSkip; - if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) { - for (QPair 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)->scenePosition()); - QMouseEvent *me = pme->asMouseEvent(localPos); - if (filteringParent->childMouseEventFilter(item, me)) - ret = true; - filteringParentsToSkip.append(filteringParent); - } - } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { - QVarLengthArray, 32> passiveGrabsToCancel; - for (QPair 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 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; + 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)) + filtered = true; } - // 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 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 filteringParentTouchEvent(pte->touchEventForItem(filteringParent, true)); + if (filteringParentTouchEvent) { + QVarLengthArray, 32> passiveGrabsToCancel; + if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) { + qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; + filteringParent->grabMouse(); + for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) { + auto pointerEventPoint = pte->pointById(point.id()); for (auto handler : pointerEventPoint->passiveGrabbers()) { QPair 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 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; + 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 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 *hasFiltered) diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 0bd909603d..2a2507904b 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -148,7 +148,8 @@ public: static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0); void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent); bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet *); - bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver); + 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 pointerTargets(QQuickItem *, const QPointF &, bool checkMouseButtons, bool checkAcceptsTouch) const; QVector mergePointerTargets(const QVector &list1, const QVector &list2) const; - void updateFilteringParentItems(const QVector &targetItems); // hover delivery bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted); @@ -227,7 +227,7 @@ public: QList cleanupNodeList; QVector itemsToPolish; - QVector > filteringParentItems; // item:parent pairs + QVector hasFiltered; // during event delivery, the items for which childMouseEventFilter was already called qreal devicePixelRatio; QMetaObject::Connection physicalDpiChangedConnection; -- cgit v1.2.3 From e11fe4290c7f0c4a876113e5e440db37ecd91bcc Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 8 Sep 2017 12:52:14 +0200 Subject: Fix double-free in QQmlTypePrivate for enum values Reported by ASan. Change-Id: I8e5e6561e6e721ba7fe37a4658480d14b8c437ae Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlmetatype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 9bc35b3b52..bddbda5832 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -815,10 +815,10 @@ void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cach const QMetaObject *cppMetaObject = cache->firstCppMetaObject(); while (cache && cache->metaObject() != cppMetaObject) { - QStringHash *scoped = new QStringHash(); int count = cache->qmlEnumCount(); for (int ii = 0; ii < count; ++ii) { + QStringHash *scoped = new QStringHash(); QQmlEnumData *enumData = cache->qmlEnum(ii); for (int jj = 0; jj < enumData->values.count(); ++jj) { -- cgit v1.2.3 From 0167f5fc6115cbb52ecd1d882048c1f2cf70fc7f Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 8 Sep 2017 15:12:47 +0200 Subject: Drain the markStack while collecting roots This avoids overflows in the markStack for test cases where we have a huge amount of compilation units with many runtime strings that all want to get marked. Task-number: QTBUG-63063 Change-Id: I7c1df0fdb9afada1830f8c218a0e52ebcd093850 Reviewed-by: Simon Hausmann Reviewed-by: J-P Nurmi --- src/qml/jsruntime/qv4engine.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index caa6e8b7ac..8ca6b03950 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -982,10 +982,13 @@ void ExecutionEngine::markObjects(MarkStack *markStack) } classPool->markObjects(markStack); + markStack->drain(); for (QSet::ConstIterator it = compilationUnits.constBegin(), end = compilationUnits.constEnd(); - it != end; ++it) + it != end; ++it) { (*it)->markObjects(markStack); + markStack->drain(); + } } ReturnedValue ExecutionEngine::throwError(const Value &value) -- cgit v1.2.3 From 00adacd7934d7553eaea7c6d2b43bcb3df439e3e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 8 Sep 2017 14:37:41 +0200 Subject: Remove unused member variable And fix a valgrind warning about the other variables in the bitfield being used uninitialized. Change-Id: I1f3730873ef2b95e8298d0cb8f4014aa4a221dd3 Reviewed-by: Simon Hausmann --- src/quick/items/qquickpathview_p_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') 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; -- cgit v1.2.3 From 9549d1783c5f738dbcb06d11b06ce6cc5a3ee0ea Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 29 Aug 2017 13:00:41 +0200 Subject: refactor sendFilteredMouseEvent to match sendFilteredPointerEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit and eliminate more temporary QSets. Change-Id: I03b556295b75f919c2c22f8f8884b1d54d6654c0 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 31 +++++++++++++++---------------- src/quick/items/qquickwindow_p.h | 2 +- 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 21f06febde..023fa6f9f0 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 hasFiltered; - if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered)) + hasFiltered.clear(); + if (!sendFilteredMouseEvent(&e, oldGrabber, oldGrabber->parentItem())) oldGrabber->mouseUngrabEvent(); } } @@ -1757,10 +1757,9 @@ bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, hoverEvent.setTimestamp(timestamp); hoverEvent.setAccepted(accepted); - QSet hasFiltered; - if (sendFilteredMouseEvent(item->parentItem(), item, &hoverEvent, &hasFiltered)) { + hasFiltered.clear(); + if (sendFilteredMouseEvent(&hoverEvent, item, item->parentItem())) return true; - } QCoreApplication::sendEvent(item, &hoverEvent); @@ -2840,24 +2839,24 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event return sendFilteredPointerEventImpl(event, receiver, filteringParent->parentItem()) || filtered; } -bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem *item, QEvent *event, QSet *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; + 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) @@ -3007,8 +3006,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 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 2a2507904b..831c8c8d88 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -147,7 +147,7 @@ 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 *); + 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) -- cgit v1.2.3 From 47b3b1b10246cad6709c0cd99f02208dbaf6b7c0 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 11 Sep 2017 14:10:51 +0200 Subject: don't re-deliver events to an item which already filtered MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit That is, if the filtering parent intercepts an event (returns true from childMouseEventFilter), it does not also need direct delivery of the same event. Change-Id: I24003f72875b309fa10b2d316916c5f86702cb57 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 24 ++++++++++++++---------- src/quick/items/qquickwindow_p.h | 3 ++- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 023fa6f9f0..bd1a5076fd 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2232,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()) { @@ -2426,7 +2427,6 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, } } - QVarLengthArray filteredItems; for (QQuickItem *item : targetItems) { if (!handlersOnly && sendFilteredPointerEvent(event, item)) { if (event->isAccepted()) { @@ -2434,15 +2434,12 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, event->point(i)->setAccepted(); return true; } - filteredItems << item; + skipDelivery.append(item); } - // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event - if (filteredItems.contains(item)) - continue; - // Do not deliverMatchingPointsTo any item which already had a chance to filter - // e.g. if Flickable has filtered events from one of its children, it does not need normal delivery - if (hasFiltered.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()) @@ -2743,8 +2740,11 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event if (receiver->acceptedMouseButtons()) { QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition()); QMouseEvent *me = pme->asMouseEvent(localPos); - if (filteringParent->childMouseEventFilter(receiver, me)) + if (filteringParent->childMouseEventFilter(receiver, me)) { + qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); filtered = true; + } } } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -2760,6 +2760,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event QVarLengthArray, 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()); @@ -2804,6 +2805,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event 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); @@ -2851,8 +2853,10 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QEvent *event, QQuickItem *rece bool filtered = false; if (filteringParentPrivate->filtersChildMouseEvents && !hasFiltered.contains(filteringParent)) { hasFiltered.append(filteringParent); - if (filteringParent->childMouseEventFilter(receiver, event)) + if (filteringParent->childMouseEventFilter(receiver, event)) { filtered = true; + skipDelivery.append(filteringParent); + } qCDebug(DBG_MOUSE_TARGET) << "for" << receiver << filteringParent << "childMouseEventFilter ->" << filtered; } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 831c8c8d88..0399b26f62 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -227,7 +227,8 @@ public: QList cleanupNodeList; QVector itemsToPolish; - QVector hasFiltered; // during event delivery, the items for which childMouseEventFilter was already called + QVector hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called + QVector skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary qreal devicePixelRatio; QMetaObject::Connection physicalDpiChangedConnection; -- cgit v1.2.3