From 742e869afe2dbba6aae6302d20ba9c82f3ed99c6 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 26 Oct 2017 11:56:43 +0200 Subject: Fix crash with dangling context object pointers This is a regression introduced by commit e22b624d9ab1f36021adb9cdbfa9b37054282bb8, where the object that owns the QML context would destroy the context upon destruction. Now the context may live longer and thus the context->contextObject pointer would become a dangling pointer. Task-number: QTBUG-63733 Change-Id: Idc660116752d312917a0a149110b92a042ccfb17 Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlengine.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 5efebe28a2..d99bec4c52 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -891,6 +891,8 @@ void QQmlData::setQueuedForDeletion(QObject *object) if (ddata->ownContext) { Q_ASSERT(ddata->ownContext == ddata->context); ddata->context->emitDestruction(); + if (ddata->ownContext->contextObject == object) + ddata->ownContext->contextObject = nullptr; ddata->ownContext = 0; ddata->context = 0; } -- cgit v1.2.3 From f64ef7ede82260b8c2740930c85e224229855da3 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Oct 2017 11:42:00 +0200 Subject: Mark pixmaps without alpha channel as opaque in the SW renderer And help avoid that we draw the same pixel multiple times. Change-Id: I56dccfeffe6865d0aaa252c84ae693380c3bbb5b Reviewed-by: Eirik Aavitsland Reviewed-by: Volker Krause --- .../scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h | 2 +- .../scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h index f21667fdf7..5c95eb064a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h @@ -124,8 +124,8 @@ public: QRectF rect() const; -private: const QPixmap &pixmap() const; +private: QRectF m_targetRect; QRectF m_innerTargetRect; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index e5b9430236..b8b0972113 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -155,8 +155,7 @@ void QSGSoftwareRenderableNode::update() boundingRect = m_handle.simpleTextureNode->rect(); break; case QSGSoftwareRenderableNode::Image: - // There isn't a way to tell, so assume it's not - m_isOpaque = false; + m_isOpaque = !m_handle.imageNode->pixmap().hasAlphaChannel() && !m_transform.isRotating(); boundingRect = m_handle.imageNode->rect().toRect(); break; -- cgit v1.2.3 From 62e23e1ae6542b5ab837a2481d9257c81e484013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Wed, 1 Nov 2017 15:49:47 +0100 Subject: Avoid bogus "cancelGrab: no grabber" warning Should not alter any behavior except that the warning is gone. Change-Id: I684532ece7eddaeafd7ff26daa23a1c9968243f3 Task-number: QTBUG-62424 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 45c14f10a1..4210ba36ad 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -762,8 +762,11 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) auto point = pointerEventInstance(touchMouseDevice)->pointById(touchMouseId); if (point) { auto originalEvent = pointerEventInstance(point->pointerEvent()->device()); - for (int i = 0; i < originalEvent->pointCount(); ++i) - originalEvent->point(i)->cancelExclusiveGrab(); + for (int i = 0; i < originalEvent->pointCount(); ++i) { + QQuickEventPoint *pt = originalEvent->point(i); + if (pt->exclusiveGrabber()) + pt->cancelExclusiveGrab(); + } point->setGrabberItem(grabber); for (auto handler : point->passiveGrabbers()) point->cancelPassiveGrab(handler); -- cgit v1.2.3 From 0d84aaf05c7306c8e39bac7acd7c85dc04358b17 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Mon, 21 Nov 2016 22:35:37 +0300 Subject: QQuickItemView: avoid wrong repositioning of removed items If all the items currently in the view are being removed, lastVisibleIndex will be -1. This caused an unwanted repositioning of all the deleted items, which got moved to a wrong location. Therefore, when all visible items are removed, we should avoid recomputing any item's position. Task-number: QTBUG-57225 Change-Id: I9909748a9cccb5e6a3726306e250921ce69fcba9 Reviewed-by: J-P Nurmi Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemview.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 1d0d042839..9038f7cde4 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1934,8 +1934,9 @@ void QQuickItemViewPrivate::layout() if (transitioner) { // items added in the last refill() may need to be transitioned in - e.g. a remove // causes items to slide up into view - if (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false) - || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) { + if (lastIndexInView != -1 && + (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false) + || transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false))) { translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges); } -- cgit v1.2.3 From eb2265d4c89b64c571f276e628b751abac29f895 Mon Sep 17 00:00:00 2001 From: Alexandr Akulich Date: Thu, 16 Jun 2016 11:15:12 +0500 Subject: QQuickFlickable: Use QQuickItem::setSize() in resizeContent() Sequential call of setWidth() and setHeight() results in outdated height on widthChanged() signal. Use setSize() to set width and height at once. Change-Id: I013f5e1fcfc65a8606f9596ddc196b633873dc98 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickflickable.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index c75a682f4a..3462752370 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -2181,25 +2181,25 @@ qreal QQuickFlickable::originX() const void QQuickFlickable::resizeContent(qreal w, qreal h, QPointF center) { Q_D(QQuickFlickable); - if (w != d->hData.viewSize) { - qreal oldSize = d->hData.viewSize; - d->hData.viewSize = w; - d->contentItem->setWidth(w); + const qreal oldHSize = d->hData.viewSize; + const qreal oldVSize = d->vData.viewSize; + const bool needToUpdateWidth = w != oldHSize; + const bool needToUpdateHeight = h != oldVSize; + d->hData.viewSize = w; + d->vData.viewSize = h; + d->contentItem->setSize(QSizeF(w, h)); + if (needToUpdateWidth) emit contentWidthChanged(); - if (center.x() != 0) { - qreal pos = center.x() * w / oldSize; - setContentX(contentX() + pos - center.x()); - } - } - if (h != d->vData.viewSize) { - qreal oldSize = d->vData.viewSize; - d->vData.viewSize = h; - d->contentItem->setHeight(h); + if (needToUpdateHeight) emit contentHeightChanged(); - if (center.y() != 0) { - qreal pos = center.y() * h / oldSize; - setContentY(contentY() + pos - center.y()); - } + + if (center.x() != 0) { + qreal pos = center.x() * w / oldHSize; + setContentX(contentX() + pos - center.x()); + } + if (center.y() != 0) { + qreal pos = center.y() * h / oldVSize; + setContentY(contentY() + pos - center.y()); } d->updateBeginningEnd(); } -- cgit v1.2.3 From a7880a0c92323ccb2f297a39a993a87e20d65e9c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 1 Nov 2017 13:03:22 +0100 Subject: ListView: don't stop moving the highlight because of model updates In QQuickItemViewPrivate::applyModelChanges(), if moveReason = QQuickItemViewPrivate::Other, then QQuickItemView::trackedPositionChanged() will fail to call d->setPosition(pos), which is normally what keeps the Flickable moving for a while. Leave the reason as-is (it will be SetIndex in this case), so as not to forget that we were actually trying to move down. Updating the model was just a side-effect of that: either because some QML code was trying to append to the model or because fetchMore() was called. Task-number: QTBUG-61269 Task-number: QTBUG-62864 Change-Id: I3fd402469950d6c12e6a8d6e42be83ea4f54776a Reviewed-by: J-P Nurmi --- src/quick/items/qquickitemview.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 9038f7cde4..8f3fe9f0f2 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1979,7 +1979,6 @@ bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult } updateUnrequestedIndexes(); - moveReason = QQuickItemViewPrivate::Other; FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? *visibleItems.constBegin() : 0; int prevItemCount = itemCount; -- cgit v1.2.3 From 62b1bc426929c5f990f00bee7d3de8a0024ed7c5 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Mon, 21 Nov 2016 22:41:33 +0300 Subject: QQuickItemView: always honor the removeDisplaced animation The animation was not being performed if the delayRemove attached property was changed by the handler of the remove() attached signal. We need to run the delayed transitions not only if we have an animation for the target item, but also if we have an animation for the items being displaced. (The flag variables can safely be obtained outside of the for loop, given that their value should not change during the loop iteration) Task-number: QTBUG-57225 Change-Id: I8c138677d7dcdf63e0932ec5cf7738c0caeb2ab8 Reviewed-by: J-P Nurmi Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemview.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 8f3fe9f0f2..66438ee37d 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1246,16 +1246,26 @@ void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry void QQuickItemView::destroyRemoved() { Q_D(QQuickItemView); + + bool hasRemoveTransition = false; + bool hasRemoveTransitionAsTarget = false; + if (d->transitioner) { + hasRemoveTransition = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false); + hasRemoveTransitionAsTarget = d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true); + } + for (QList::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end();) { FxViewItem *item = *it; if (item->index == -1 && (!item->attached || item->attached->delayRemove() == false)) { - if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) { + if (hasRemoveTransitionAsTarget) { // don't remove from visibleItems until next layout() d->runDelayedRemoveTransition = true; QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved())); ++it; } else { + if (hasRemoveTransition) + d->runDelayedRemoveTransition = true; d->releaseItem(item); it = d->visibleItems.erase(it); } -- cgit v1.2.3 From ee00fa01dc41deaaedfa0d1d5cc6cd750bfe75f4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 21 Sep 2017 12:23:48 -0700 Subject: Update to new QRandomGenerator API Change-Id: I69f37f9304f24709a823fffd14e676c097712329 Reviewed-by: Erik Verbruggen --- src/particles/qquickangledirection.cpp | 4 ++-- src/particles/qquickcustomparticle.cpp | 2 +- src/particles/qquickellipseextruder.cpp | 4 ++-- src/particles/qquickimageparticle.cpp | 12 ++++++------ src/particles/qquicklineextruder.cpp | 4 ++-- src/particles/qquickmaskextruder.cpp | 2 +- src/particles/qquickparticleemitter.cpp | 4 ++-- src/particles/qquickparticleextruder.cpp | 4 ++-- src/particles/qquickpointdirection.cpp | 4 ++-- src/particles/qquickrectangleextruder.cpp | 14 +++++++------- src/particles/qquicktargetdirection.cpp | 6 +++--- src/particles/qquicktrailemitter.cpp | 4 ++-- src/particles/qquickwander.cpp | 12 ++++++------ src/qml/doc/src/cppintegration/definetypes.qdoc | 2 +- src/qml/jsruntime/qv4mathobject.cpp | 2 +- src/quick/items/qquicksprite.cpp | 4 ++-- src/quick/items/qquickspriteengine.cpp | 10 +++++----- src/quick/items/qquickspriteengine_p.h | 2 +- 18 files changed, 48 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/particles/qquickangledirection.cpp b/src/particles/qquickangledirection.cpp index 11a007ca09..34afd9ce84 100644 --- a/src/particles/qquickangledirection.cpp +++ b/src/particles/qquickangledirection.cpp @@ -108,8 +108,8 @@ QPointF QQuickAngleDirection::sample(const QPointF &from) { Q_UNUSED(from); QPointF ret; - qreal theta = m_angle*CONV - m_angleVariation*CONV + QRandomGenerator::getReal() * m_angleVariation*CONV * 2; - qreal mag = m_magnitude- m_magnitudeVariation + QRandomGenerator::getReal() * m_magnitudeVariation * 2; + qreal theta = m_angle*CONV - m_angleVariation*CONV + QRandomGenerator::global()->generateDouble() * m_angleVariation*CONV * 2; + qreal mag = m_magnitude- m_magnitudeVariation + QRandomGenerator::global()->generateDouble() * m_magnitudeVariation * 2; ret.setX(mag * qCos(theta)); ret.setY(mag * qSin(theta)); return ret; diff --git a/src/particles/qquickcustomparticle.cpp b/src/particles/qquickcustomparticle.cpp index a2bcd91167..e344fea1fa 100644 --- a/src/particles/qquickcustomparticle.cpp +++ b/src/particles/qquickcustomparticle.cpp @@ -425,7 +425,7 @@ void QQuickCustomParticle::buildData(QQuickOpenGLShaderEffectNode *rootNode) void QQuickCustomParticle::initialize(int gIdx, int pIdx) { QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx]; - datum->r = QRandomGenerator::getReal(); + datum->r = QRandomGenerator::global()->generateDouble(); } void QQuickCustomParticle::commit(int gIdx, int pIdx) diff --git a/src/particles/qquickellipseextruder.cpp b/src/particles/qquickellipseextruder.cpp index fbb11b34cc..52fccd6da9 100644 --- a/src/particles/qquickellipseextruder.cpp +++ b/src/particles/qquickellipseextruder.cpp @@ -68,8 +68,8 @@ QQuickEllipseExtruder::QQuickEllipseExtruder(QObject *parent) : QPointF QQuickEllipseExtruder::extrude(const QRectF & r) { - qreal theta = QRandomGenerator::bounded(2 * M_PI); - qreal mag = m_fill ? QRandomGenerator::getReal() : 1; + qreal theta = QRandomGenerator::global()->bounded(2 * M_PI); + qreal mag = m_fill ? QRandomGenerator::global()->generateDouble() : 1; return QPointF(r.x() + r.width()/2 + mag * (r.width()/2) * qCos(theta), r.y() + r.height()/2 + mag * (r.height()/2) * qSin(theta)); } diff --git a/src/particles/qquickimageparticle.cpp b/src/particles/qquickimageparticle.cpp index 8f809176a9..37bf323f42 100644 --- a/src/particles/qquickimageparticle.cpp +++ b/src/particles/qquickimageparticle.cpp @@ -1730,9 +1730,9 @@ void QQuickImageParticle::initialize(int gIdx, int pIdx) if (!datum->rotationOwner) datum->rotationOwner = this; rotation = - (m_rotation + (m_rotationVariation - 2*QRandomGenerator::bounded(m_rotationVariation)) ) * CONV; + (m_rotation + (m_rotationVariation - 2*QRandomGenerator::global()->bounded(m_rotationVariation)) ) * CONV; rotationVelocity = - (m_rotationVelocity + (m_rotationVelocityVariation - 2*QRandomGenerator::bounded(m_rotationVelocityVariation)) ) * CONV; + (m_rotationVelocity + (m_rotationVelocityVariation - 2*QRandomGenerator::global()->bounded(m_rotationVelocityVariation)) ) * CONV; autoRotate = m_autoRotation?1.0:0.0; if (datum->rotationOwner == this) { datum->rotation = rotation; @@ -1751,10 +1751,10 @@ void QQuickImageParticle::initialize(int gIdx, int pIdx) if (m_explicitColor) { if (!datum->colorOwner) datum->colorOwner = this; - color.r = m_color.red() * (1 - redVariation) + QRandomGenerator::bounded(256) * redVariation; - color.g = m_color.green() * (1 - greenVariation) + QRandomGenerator::bounded(256) * greenVariation; - color.b = m_color.blue() * (1 - blueVariation) + QRandomGenerator::bounded(256) * blueVariation; - color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + QRandomGenerator::bounded(256) * m_alphaVariation; + color.r = m_color.red() * (1 - redVariation) + QRandomGenerator::global()->bounded(256) * redVariation; + color.g = m_color.green() * (1 - greenVariation) + QRandomGenerator::global()->bounded(256) * greenVariation; + color.b = m_color.blue() * (1 - blueVariation) + QRandomGenerator::global()->bounded(256) * blueVariation; + color.a = m_alpha * m_color.alpha() * (1 - m_alphaVariation) + QRandomGenerator::global()->bounded(256) * m_alphaVariation; if (datum->colorOwner == this) datum->color = color; else diff --git a/src/particles/qquicklineextruder.cpp b/src/particles/qquicklineextruder.cpp index 6ebd728407..670e656b8e 100644 --- a/src/particles/qquicklineextruder.cpp +++ b/src/particles/qquicklineextruder.cpp @@ -69,10 +69,10 @@ QPointF QQuickLineExtruder::extrude(const QRectF &r) { qreal x,y; if (!r.height()){ - x = r.width() * QRandomGenerator::getReal(); + x = r.width() * QRandomGenerator::global()->generateDouble(); y = 0; }else{ - y = r.height() * QRandomGenerator::getReal(); + y = r.height() * QRandomGenerator::global()->generateDouble(); if (!r.width()){ x = 0; }else{ diff --git a/src/particles/qquickmaskextruder.cpp b/src/particles/qquickmaskextruder.cpp index 60c23c55a8..6ab6dcc6a4 100644 --- a/src/particles/qquickmaskextruder.cpp +++ b/src/particles/qquickmaskextruder.cpp @@ -103,7 +103,7 @@ QPointF QQuickMaskExtruder::extrude(const QRectF &r) ensureInitialized(r); if (!m_mask.count() || m_img.isNull()) return r.topLeft(); - const QPointF p = m_mask[QRandomGenerator::bounded(m_mask.count())]; + const QPointF p = m_mask[QRandomGenerator::global()->bounded(m_mask.count())]; //### Should random sub-pixel positioning be added? return p + r.topLeft(); } diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp index d18250d706..d4e6552d95 100644 --- a/src/particles/qquickparticleemitter.cpp +++ b/src/particles/qquickparticleemitter.cpp @@ -425,7 +425,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp) datum->t = pt; datum->lifeSpan = (m_particleDuration - + (QRandomGenerator::bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation)) + + (QRandomGenerator::global()->bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation)) / 1000.0; if (datum->lifeSpan >= m_system->maxLife){ @@ -462,7 +462,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp) // Particle size float sizeVariation = -m_particleSizeVariation - + QRandomGenerator::bounded(m_particleSizeVariation * 2); + + QRandomGenerator::global()->bounded(m_particleSizeVariation * 2); float size = qMax((qreal)0.0 , m_particleSize + sizeVariation); float endSize = qMax((qreal)0.0 , sizeAtEnd + sizeVariation); diff --git a/src/particles/qquickparticleextruder.cpp b/src/particles/qquickparticleextruder.cpp index 74b450921f..816ff34960 100644 --- a/src/particles/qquickparticleextruder.cpp +++ b/src/particles/qquickparticleextruder.cpp @@ -59,8 +59,8 @@ QQuickParticleExtruder::QQuickParticleExtruder(QObject *parent) : QPointF QQuickParticleExtruder::extrude(const QRectF &rect) { - return QPointF(QRandomGenerator::getReal() * rect.width() + rect.x(), - QRandomGenerator::getReal() * rect.height() + rect.y()); + return QPointF(QRandomGenerator::global()->generateDouble() * rect.width() + rect.x(), + QRandomGenerator::global()->generateDouble() * rect.height() + rect.y()); } bool QQuickParticleExtruder::contains(const QRectF &bounds, const QPointF &point) diff --git a/src/particles/qquickpointdirection.cpp b/src/particles/qquickpointdirection.cpp index 7b5c9bada1..f22eea2a76 100644 --- a/src/particles/qquickpointdirection.cpp +++ b/src/particles/qquickpointdirection.cpp @@ -78,8 +78,8 @@ QQuickPointDirection::QQuickPointDirection(QObject *parent) : QPointF QQuickPointDirection::sample(const QPointF &) { QPointF ret; - ret.setX(m_x - m_xVariation + QRandomGenerator::getReal() * m_xVariation * 2); - ret.setY(m_y - m_yVariation + QRandomGenerator::getReal() * m_yVariation * 2); + ret.setX(m_x - m_xVariation + QRandomGenerator::global()->generateDouble() * m_xVariation * 2); + ret.setY(m_y - m_yVariation + QRandomGenerator::global()->generateDouble() * m_yVariation * 2); return ret; } diff --git a/src/particles/qquickrectangleextruder.cpp b/src/particles/qquickrectangleextruder.cpp index 6474f61630..36e4871d29 100644 --- a/src/particles/qquickrectangleextruder.cpp +++ b/src/particles/qquickrectangleextruder.cpp @@ -60,21 +60,21 @@ QQuickRectangleExtruder::QQuickRectangleExtruder(QObject *parent) : QPointF QQuickRectangleExtruder::extrude(const QRectF &rect) { if (m_fill) - return QPointF(QRandomGenerator::getReal() * rect.width() + rect.x(), - QRandomGenerator::getReal() * rect.height() + rect.y()); - int side = QRandomGenerator::bounded(4); + return QPointF(QRandomGenerator::global()->generateDouble() * rect.width() + rect.x(), + QRandomGenerator::global()->generateDouble() * rect.height() + rect.y()); + int side = QRandomGenerator::global()->bounded(4); switch (side){//TODO: Doesn't this overlap the corners? case 0: return QPointF(rect.x(), - QRandomGenerator::getReal() * rect.height() + rect.y()); + QRandomGenerator::global()->generateDouble() * rect.height() + rect.y()); case 1: return QPointF(rect.width() + rect.x(), - QRandomGenerator::getReal() * rect.height() + rect.y()); + QRandomGenerator::global()->generateDouble() * rect.height() + rect.y()); case 2: - return QPointF(QRandomGenerator::getReal() * rect.width() + rect.x(), + return QPointF(QRandomGenerator::global()->generateDouble() * rect.width() + rect.x(), rect.y()); default: - return QPointF(QRandomGenerator::getReal() * rect.width() + rect.x(), + return QPointF(QRandomGenerator::global()->generateDouble() * rect.width() + rect.x(), rect.height() + rect.y()); } } diff --git a/src/particles/qquicktargetdirection.cpp b/src/particles/qquicktargetdirection.cpp index 96b78a53b4..a113b7c04a 100644 --- a/src/particles/qquicktargetdirection.cpp +++ b/src/particles/qquicktargetdirection.cpp @@ -118,10 +118,10 @@ QPointF QQuickTargetDirection::sample(const QPointF &from) targetX = m_targetX; targetY = m_targetY; } - targetX += 0 - from.x() - m_targetVariation + QRandomGenerator::getReal() * m_targetVariation*2; - targetY += 0 - from.y() - m_targetVariation + QRandomGenerator::getReal() * m_targetVariation*2; + targetX += 0 - from.x() - m_targetVariation + QRandomGenerator::global()->generateDouble() * m_targetVariation*2; + targetY += 0 - from.y() - m_targetVariation + QRandomGenerator::global()->generateDouble() * m_targetVariation*2; qreal theta = std::atan2(targetY, targetX); - qreal mag = m_magnitude + QRandomGenerator::getReal() * m_magnitudeVariation * 2 - m_magnitudeVariation; + qreal mag = m_magnitude + QRandomGenerator::global()->generateDouble() * m_magnitudeVariation * 2 - m_magnitudeVariation; if (m_proportionalMagnitude) mag *= std::sqrt(targetX * targetX + targetY * targetY); ret.setX(mag * std::cos(theta)); diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp index 14075f6b23..49ee728bfd 100644 --- a/src/particles/qquicktrailemitter.cpp +++ b/src/particles/qquicktrailemitter.cpp @@ -208,7 +208,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) datum->t = pt; datum->lifeSpan = (m_particleDuration - + (QRandomGenerator::bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation)) + + (QRandomGenerator::global()->bounded((m_particleDurationVariation*2) + 1) - m_particleDurationVariation)) / 1000.0; // Particle position @@ -241,7 +241,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp) // Particle size float sizeVariation = -m_particleSizeVariation - + QRandomGenerator::getReal() * m_particleSizeVariation * 2; + + QRandomGenerator::global()->generateDouble() * m_particleSizeVariation * 2; float size = qMax((qreal)0.0, m_particleSize + sizeVariation); float endSize = qMax((qreal)0.0, sizeAtEnd + sizeVariation); diff --git a/src/particles/qquickwander.cpp b/src/particles/qquickwander.cpp index cfdede440b..a78482ec84 100644 --- a/src/particles/qquickwander.cpp +++ b/src/particles/qquickwander.cpp @@ -103,8 +103,8 @@ WanderData* QQuickWanderAffector::getData(int idx) d->y_vel = 0; d->x_peak = m_xVariance; d->y_peak = m_yVariance; - d->x_var = m_pace * QRandomGenerator::getReal(); - d->y_var = m_pace * QRandomGenerator::getReal(); + d->x_var = m_pace * QRandomGenerator::global()->generateDouble(); + d->y_var = m_pace * QRandomGenerator::global()->generateDouble(); m_wanderData.insert(idx, d); return d; @@ -125,7 +125,7 @@ bool QQuickWanderAffector::affectParticle(QQuickParticleData* data, qreal dt) if (m_xVariance != 0.) { if ((d->x_vel > d->x_peak && d->x_var > 0.0) || (d->x_vel < -d->x_peak && d->x_var < 0.0)) { d->x_var = -d->x_var; - d->x_peak = m_xVariance + m_xVariance * QRandomGenerator::getReal(); + d->x_peak = m_xVariance + m_xVariance * QRandomGenerator::global()->generateDouble(); } d->x_vel += d->x_var * dt; } @@ -134,7 +134,7 @@ bool QQuickWanderAffector::affectParticle(QQuickParticleData* data, qreal dt) if (m_yVariance != 0.) { if ((d->y_vel > d->y_peak && d->y_var > 0.0) || (d->y_vel < -d->y_peak && d->y_var < 0.0)) { d->y_var = -d->y_var; - d->y_peak = m_yVariance + m_yVariance * QRandomGenerator::getReal(); + d->y_peak = m_yVariance + m_yVariance * QRandomGenerator::global()->generateDouble(); } d->y_vel += d->y_var * dt; } @@ -147,8 +147,8 @@ bool QQuickWanderAffector::affectParticle(QQuickParticleData* data, qreal dt) p->y += dy; return true; */ - qreal dx = dt * m_pace * (2 * QRandomGenerator::getReal() - 1); - qreal dy = dt * m_pace * (2 * QRandomGenerator::getReal() - 1); + qreal dx = dt * m_pace * (2 * QRandomGenerator::global()->generateDouble() - 1); + qreal dy = dt * m_pace * (2 * QRandomGenerator::global()->generateDouble() - 1); qreal newX, newY; switch (m_affectedParameter){ case Position: diff --git a/src/qml/doc/src/cppintegration/definetypes.qdoc b/src/qml/doc/src/cppintegration/definetypes.qdoc index afc76ce31d..027e4b9923 100644 --- a/src/qml/doc/src/cppintegration/definetypes.qdoc +++ b/src/qml/doc/src/cppintegration/definetypes.qdoc @@ -620,7 +620,7 @@ signals: private slots: void updateProperty() { - m_targetProperty.write(QRandomGenerator::bounded(m_maxValue)); + m_targetProperty.write(QRandomGenerator::global()->bounded(m_maxValue)); } private: diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 46230b5bc1..8782e6deae 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -275,7 +275,7 @@ void MathObject::method_pow(const BuiltinFunction *, Scope &scope, CallData *cal void MathObject::method_random(const BuiltinFunction *, Scope &scope, CallData *) { - RETURN_RESULT(Encode(QRandomGenerator::getReal())); + RETURN_RESULT(Encode(QRandomGenerator::global()->generateDouble())); } void MathObject::method_round(const BuiltinFunction *, Scope &scope, CallData *callData) diff --git a/src/quick/items/qquicksprite.cpp b/src/quick/items/qquicksprite.cpp index 8013c57938..42b8fb8174 100644 --- a/src/quick/items/qquicksprite.cpp +++ b/src/quick/items/qquicksprite.cpp @@ -237,12 +237,12 @@ int QQuickSprite::variedDuration() const //Deals with precedence when multiple d if (m_frameRate != unsetDuration) { qreal fpms = (m_frameRate - + (m_frameRateVariation * QRandomGenerator::getReal() * 2) + + (m_frameRateVariation * QRandomGenerator::global()->generateDouble() * 2) - m_frameRateVariation) / 1000.0; return qMax(qreal(0.0) , m_frames / fpms); } else if (m_frameDuration != unsetDuration) { int mspf = m_frameDuration - + (m_frameDurationVariation * QRandomGenerator::getReal() * 2) + + (m_frameDurationVariation * QRandomGenerator::global()->generateDouble() * 2) - m_frameDurationVariation; return qMax(0, m_frames * mspf); } else if (duration() >= 0) { diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 9deb223957..1fd15e61e3 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -544,7 +544,7 @@ void QQuickStochasticEngine::restart(int index) if (m_addAdvance) m_startTimes[index] += m_advanceTime.elapsed(); if (randomStart) - m_startTimes[index] -= QRandomGenerator::bounded(m_duration.at(index)); + m_startTimes[index] -= QRandomGenerator::global()->bounded(m_duration.at(index)); int time = m_duration.at(index) + m_startTimes.at(index); for (int i=0; iframeSync()) {//Manually advanced m_startTimes[index] = 0; if (randomStart && m_sprites.at(m_things.at(index))->m_generatedCount) - m_startTimes[index] += QRandomGenerator::bounded(m_sprites.at(m_things.at(index))->m_generatedCount); + m_startTimes[index] += QRandomGenerator::global()->bounded(m_sprites.at(m_things.at(index))->m_generatedCount); } else { m_startTimes[index] = m_timeOffset; if (m_addAdvance) m_startTimes[index] += m_advanceTime.elapsed(); if (randomStart) - m_startTimes[index] -= QRandomGenerator::bounded(m_duration.at(index)); + m_startTimes[index] -= QRandomGenerator::global()->bounded(m_duration.at(index)); int time = spriteDuration(index) + m_startTimes.at(index); if (randomStart) { int curTime = m_timeOffset + (m_addAdvance ? m_advanceTime.elapsed() : 0); @@ -630,7 +630,7 @@ int QQuickStochasticEngine::nextState(int curState, int curThing) int nextIdx = -1; int goalPath = goalSeek(curState, curThing); if (goalPath == -1){//Random - qreal r = QRandomGenerator::getReal(); + qreal r = QRandomGenerator::global()->generateDouble(); qreal total = 0.0; for (QVariantMap::const_iterator iter=m_states.at(curState)->m_to.constBegin(); iter!=m_states.at(curState)->m_to.constEnd(); ++iter) @@ -720,7 +720,7 @@ int QQuickStochasticEngine::goalSeek(int curIdx, int spriteIdx, int dist) if (options.count()==1) return *(options.begin()); int option = -1; - qreal r = QRandomGenerator::getReal(); + qreal r = QRandomGenerator::global()->generateDouble(); qreal total = 0; for (QSet::const_iterator iter=options.constBegin(); iter!=options.constEnd(); ++iter) diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h index 4e5458a938..4e0815f7e7 100644 --- a/src/quick/items/qquickspriteengine_p.h +++ b/src/quick/items/qquickspriteengine_p.h @@ -113,7 +113,7 @@ public: virtual int variedDuration() const { return qMax(qreal(0.0) , m_duration - + (m_durationVariation * QRandomGenerator::bounded(2.0)) + + (m_durationVariation * QRandomGenerator::global()->bounded(2.0)) - m_durationVariation); } -- cgit v1.2.3 From c143c790b7a6fceaac16492023090940c81acc42 Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Wed, 18 Oct 2017 12:59:36 +0200 Subject: Doc: Move the warning about manipulating QML objects from C++ Manipulating QML objects from C++ is not a best practice when integrating QML and C++, except for testing and prototying. So its apt to warn the reader about such an approach much earlier. Task-number: QTPM-425 Change-Id: Iebb93d099008ff3ebcefe6af25364afe379b7fcf Reviewed-by: Mitch Curtis --- src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc | 12 +----------- src/qml/doc/src/cppintegration/topic.qdoc | 2 ++ src/qml/doc/src/cppintegration/warning.qdocinc | 6 ++++++ 3 files changed, 9 insertions(+), 11 deletions(-) create mode 100644 src/qml/doc/src/cppintegration/warning.qdocinc (limited to 'src') diff --git a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc index 4dc32e3588..7c2ff703c6 100644 --- a/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc +++ b/src/qml/doc/src/cppintegration/interactqmlfromcpp.qdoc @@ -114,17 +114,7 @@ multiple children with the same \c objectName. In this case, QObject::findChildren() can be used to find all children with a matching \c objectName. -\warning While it is possible to use C++ to access and manipulate QML objects -deep into the object tree, we recommend that you do not take this approach -outside of application testing and prototyping. One strength of QML and C++ -integration is the ability to implement the QML user interface separately -from the C++ logic and dataset backend, and this strategy breaks if the C++ -side reaches deep into the QML components to manipulate them directly. This -would make it difficult to, for example, swap a QML view component for -another view, if the new component was missing a required \c objectName. It -is better for the C++ implementation to know as little as possible about the -QML user interface implementation and the composition of the QML object tree. - +\include warning.qdocinc \section1 Accessing Members of a QML Object Type from C++ diff --git a/src/qml/doc/src/cppintegration/topic.qdoc b/src/qml/doc/src/cppintegration/topic.qdoc index da06c195dc..6b6e308edf 100644 --- a/src/qml/doc/src/cppintegration/topic.qdoc +++ b/src/qml/doc/src/cppintegration/topic.qdoc @@ -190,6 +190,8 @@ invoke their methods and receive their signal notifications. This is possible du all QML object types are implemented using QObject-derived classes, enabling the QML engine to dynamically load and introspect objects through the Qt meta object system. +\include warning.qdocinc + For more information on accessing QML objects from C++, see the documentation on \l{qtqml-cppintegration-interactqmlfromcpp.html}{Interacting with QML Objects from C++}. diff --git a/src/qml/doc/src/cppintegration/warning.qdocinc b/src/qml/doc/src/cppintegration/warning.qdocinc new file mode 100644 index 0000000000..a5da22b2a7 --- /dev/null +++ b/src/qml/doc/src/cppintegration/warning.qdocinc @@ -0,0 +1,6 @@ +\warning Although it is possible to access QML objects from C++ and manipulate +them, it is not the recommended approach, except for testing and prototyping +purposes. One of the strengths of QML and C++ integration is the ability to +implement UIs in QML separate from the C++ logic and dataset backend, and this +fails if the C++ side starts manipulating QML directly. Such an approach also +makes changing the QML UI difficult without affecting its C++ counterpart. -- cgit v1.2.3 From 0821180dc833376a738742e33f728983b9ca6f84 Mon Sep 17 00:00:00 2001 From: Daniel d'Andrada Date: Mon, 9 Oct 2017 17:39:44 +0200 Subject: Fix bug preventing ungrabMouse() on TouchCancel The order matters. There won't be a mouseGrabberItem() after the cancelExclusiveGrabImpl() call. So ungrab the mouse before calling it, not after. Task-number: QTBUG-63680 Change-Id: I81e03e079362c865e13792feb8c3af8cb3abedc8 Reviewed-by: Qt CI Bot Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 4210ba36ad..143c76cb1b 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1976,15 +1976,16 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) qCDebug(DBG_TOUCH) << event; Q_Q(QQuickWindow); + if (q->mouseGrabberItem()) + q->mouseGrabberItem()->ungrabMouse(); + touchMouseId = -1; + touchMouseDevice = nullptr; + // A TouchCancel event will typically not contain any points. // Deliver it to all items and handlers that have active touches. QQuickPointerEvent *pointerEvent = pointerEventInstance(QQuickPointerDevice::touchDevice(event->device())); for (int i = 0; i < pointerEvent->pointCount(); ++i) pointerEvent->point(i)->cancelExclusiveGrabImpl(event); - touchMouseId = -1; - touchMouseDevice = nullptr; - if (q->mouseGrabberItem()) - q->mouseGrabberItem()->ungrabMouse(); // The next touch event can only be a TouchBegin, so clean up. pointerEvent->clearGrabbers(); -- cgit v1.2.3 From 0f043c594b559f2f936333c8cf9779283a480c7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Pet=C3=A4j=C3=A4j=C3=A4rvi?= Date: Fri, 20 Oct 2017 11:09:22 +0300 Subject: Fix providing correct velocity when using index based scrolling Index based scrolling does not enable moving and flicking properties. Task-number: QTBUG-34576 Change-Id: Ief06d37115ca389027670c97ce6c0457a74d4872 Reviewed-by: Qt CI Bot Reviewed-by: Shawn Rutledge --- src/quick/items/qquickflickable.cpp | 6 ++++-- src/quick/items/qquickitemview.cpp | 3 --- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 3462752370..e0f8b6de00 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -748,7 +748,8 @@ void QQuickFlickable::setContentX(qreal pos) d->hData.explicitValue = true; d->resetTimeline(d->hData); d->hData.vTime = d->timeline.time(); - movementEnding(true, false); + if (isMoving() || isFlicking()) + movementEnding(true, false); if (-pos != d->hData.move.value()) d->hData.move.setValue(-pos); } @@ -765,7 +766,8 @@ void QQuickFlickable::setContentY(qreal pos) d->vData.explicitValue = true; d->resetTimeline(d->vData); d->vData.vTime = d->timeline.time(); - movementEnding(false, true); + if (isMoving() || isFlicking()) + movementEnding(false, true); if (-pos != d->vData.move.value()) d->vData.move.setValue(-pos); } diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 66438ee37d..478499e209 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -926,7 +926,6 @@ void QQuickItemView::setDisplacedTransition(QQuickTransition *transition) void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) { - Q_Q(QQuickItemView); if (!isValid()) return; if (mode < QQuickItemView::Beginning || mode > QQuickItemView::SnapPosition) @@ -988,7 +987,6 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) qreal minExtent = calculatedMinExtent(); pos = qMax(pos, minExtent); moveReason = QQuickItemViewPrivate::Other; - q->cancelFlick(); setPosition(pos); if (highlight) { @@ -1394,7 +1392,6 @@ void QQuickItemView::trackedPositionChanged() pos = qMax(trackedPos, toItemPos); } if (viewPos != pos) { - cancelFlick(); d->calcVelocity = true; d->setPosition(pos); d->calcVelocity = false; -- cgit v1.2.3 From 047bdf90db4d00d0462b9faf2044070be4a0e682 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 3 Jul 2017 08:41:03 +0200 Subject: testlib: add key sequence function [ChangeLog][QtQuick][QtTest] Added keySequence() function in TestCase. Task-number: QTBUG-53381 Change-Id: Iea25410d40fc0745e16a10c1af35ec81c4c83668 Reviewed-by: Edward Welbourne Reviewed-by: Shawn Rutledge Reviewed-by: Mitch Curtis --- src/imports/testlib/TestCase.qml | 26 +++++++++++++++++++++++--- src/imports/testlib/main.cpp | 1 + src/qmltest/quicktestevent.cpp | 17 +++++++++++++++++ src/qmltest/quicktestevent_p.h | 2 ++ 4 files changed, 43 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml index 0e7e09c65c..4bcc95df89 100644 --- a/src/imports/testlib/TestCase.qml +++ b/src/imports/testlib/TestCase.qml @@ -39,7 +39,7 @@ import QtQuick 2.0 import QtQuick.Window 2.0 // used for qtest_verifyItem -import QtTest 1.1 +import QtTest 1.2 import "testlogger.js" as TestLogger import Qt.test.qtestroot 1.0 @@ -57,7 +57,7 @@ import Qt.test.qtestroot 1.0 \code import QtQuick 2.0 - import QtTest 1.0 + import QtTest 1.2 TestCase { name: "MathTests" @@ -108,7 +108,7 @@ import Qt.test.qtestroot 1.0 \code import QtQuick 2.0 - import QtTest 1.1 + import QtTest 1.2 TestCase { name: "DataTests" @@ -1211,6 +1211,26 @@ Item { } } + /*! + \since 5.10 + \qmlmethod TestCase::keySequence(keySequence) + + Simulates typing of \a keySequence. The key sequence can be set + to one of the \l{QKeySequence::StandardKey}{standard keyboard shortcuts}, or + it can be described with a string containing a sequence of up to four key + presses. + + Each event shall be sent to the TestCase window or, in case of multiple windows, + to the current active window. See \l QGuiApplication::focusWindow() for more details. + + \sa keyPress(), keyRelease(), {GNU Emacs Style Key Sequences}, + {QtQuick::Shortcut::sequence}{Shortcut.sequence} + */ + function keySequence(keySequence) { + if (!qtest_events.keySequence(keySequence)) + qtest_fail("window not shown", 2) + } + /*! \qmlmethod TestCase::mousePress(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1) diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index fc013d5afc..0967cf80ab 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -157,6 +157,7 @@ public: qmlRegisterType(uri,1,0,"TestResult"); qmlRegisterType(uri,1,1,"TestResult"); qmlRegisterType(uri,1,0,"TestEvent"); + qmlRegisterType(uri,1,2,"TestEvent"); qmlRegisterType(uri,1,0,"TestUtil"); qmlRegisterType(); } diff --git a/src/qmltest/quicktestevent.cpp b/src/qmltest/quicktestevent.cpp index 663d3c64e1..bf255e9cda 100644 --- a/src/qmltest/quicktestevent.cpp +++ b/src/qmltest/quicktestevent.cpp @@ -121,6 +121,23 @@ bool QuickTestEvent::keyClickChar(const QString &character, int modifiers, int d return true; } +// valueToKeySequence() is copied from qquickshortcut.cpp +static QKeySequence valueToKeySequence(const QVariant &value) +{ + if (value.type() == QVariant::Int) + return QKeySequence(static_cast(value.toInt())); + return QKeySequence::fromString(value.toString()); +} + +bool QuickTestEvent::keySequence(const QVariant &keySequence) +{ + QWindow *window = activeWindow(); + if (!window) + return false; + QTest::keySequence(window, valueToKeySequence(keySequence)); + return true; +} + namespace QtQuickTest { enum MouseAction { MousePress, MouseRelease, MouseClick, MouseDoubleClick, MouseMove, MouseDoubleClickSequence }; diff --git a/src/qmltest/quicktestevent_p.h b/src/qmltest/quicktestevent_p.h index 89065b8880..92477399bc 100644 --- a/src/qmltest/quicktestevent_p.h +++ b/src/qmltest/quicktestevent_p.h @@ -94,6 +94,8 @@ public Q_SLOTS: bool keyReleaseChar(const QString &character, int modifiers, int delay); bool keyClickChar(const QString &character, int modifiers, int delay); + Q_REVISION(2) bool keySequence(const QVariant &keySequence); + bool mousePress(QObject *item, qreal x, qreal y, int button, int modifiers, int delay); bool mouseRelease(QObject *item, qreal x, qreal y, int button, -- cgit v1.2.3 From e180ab18c1e5dabcbf5965325fb957bd745d4e97 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 30 Oct 2017 15:21:33 +0100 Subject: Mark layers in the SW rasterizer as opaque if possible If the content of a layer completely covers every pixel of it, mark that layer as opaque so that we can avoid alpha blending where possible. Change-Id: Ia0be4e7a96ecddd31a26f353509de976bcc9e397 Reviewed-by: Eirik Aavitsland Reviewed-by: Volker Krause --- .../software/qsgabstractsoftwarerenderer.cpp | 6 ++++++ .../software/qsgabstractsoftwarerenderer_p.h | 3 +++ .../adaptations/software/qsgsoftwarelayer.cpp | 3 --- .../software/qsgsoftwarepixmaprenderer.cpp | 20 +++++++++++++------- 4 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp index 02cf8209d1..30088846a6 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp @@ -193,6 +193,12 @@ QRegion QSGAbstractSoftwareRenderer::optimizeRenderList() } } + if (m_obscuredRegion.contains(m_background->rect().toAlignedRect())) { + m_isOpaque = true; + } else { + m_isOpaque = false; + } + // Empty dirtyRegion (for second pass) m_dirtyRegion = QRegion(); m_obscuredRegion = QRegion(); diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h index 04a17ea377..c68a933384 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h @@ -86,6 +86,8 @@ protected: void setBackgroundSize(const QSize &size); QColor backgroundColor(); QSize backgroundSize(); + // only known after calling optimizeRenderList() + bool isOpaque() const { return m_isOpaque; } private: void nodeAdded(QSGNode *node); @@ -102,6 +104,7 @@ private: QRegion m_dirtyRegion; QRegion m_obscuredRegion; + bool m_isOpaque; QSGSoftwareRenderableNodeUpdater *m_nodeUpdater; }; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp index bd5d8f72c0..9d30c43f87 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp @@ -229,9 +229,6 @@ void QSGSoftwareLayer::grab() if (m_pixmap.size() != m_size) { m_pixmap = QPixmap(m_size); m_pixmap.setDevicePixelRatio(m_device_pixel_ratio); - // This fill here is wasteful, but necessary because it is the only way - // to force a QImage based pixmap to have an alpha channel. - m_pixmap.fill(Qt::transparent); } // Render texture. diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp index f8c1a3d90b..7824e53622 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp @@ -82,13 +82,6 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target) setBackgroundSize(QSize(target->width(), target->height())); setBackgroundColor(clearColor()); - QPainter painter(target); - painter.setRenderHint(QPainter::Antialiasing); - painter.setWindow(m_projectionRect); - auto rc = static_cast(context()); - QPainter *prevPainter = rc->m_activePainter; - rc->m_activePainter = &painter; - renderTimer.start(); buildRenderList(); qint64 buildRenderListTime = renderTimer.restart(); @@ -101,6 +94,19 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target) optimizeRenderList(); qint64 optimizeRenderListTime = renderTimer.restart(); + if (!isOpaque() && target->devType() == QInternal::Pixmap) { + // This fill here is wasteful, but necessary because it is the only way + // to force a QImage based pixmap to have an alpha channel. + static_cast(target)->fill(Qt::transparent); + } + + QPainter painter(target); + painter.setRenderHint(QPainter::Antialiasing); + painter.setWindow(m_projectionRect); + auto rc = static_cast(context()); + QPainter *prevPainter = rc->m_activePainter; + rc->m_activePainter = &painter; + QRegion paintedRegion = renderNodes(&painter); qint64 renderTime = renderTimer.elapsed(); -- cgit v1.2.3 From 7d5fe797061c25d85ec4d7a91b9f827763c8851e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 31 Oct 2017 15:51:47 +0100 Subject: Clean up handling of opaqueness in the SW renderer And check whether nine patch pixmaps are opaque as well. Change-Id: I23f2cb675b923eace849a1c0ad71efe1446c86c4 Reviewed-by: Eirik Aavitsland Reviewed-by: Volker Krause --- .../software/qsgsoftwarepublicnodes_p.h | 2 ++ .../software/qsgsoftwarerenderablenode.cpp | 39 ++++++++-------------- 2 files changed, 15 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h index 9f1913205b..114137fb55 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepublicnodes_p.h @@ -133,6 +133,8 @@ public: QRectF bounds() const; + bool isOpaque() const { return !m_pixmap.hasAlphaChannel(); } + private: QPixmap m_pixmap; QRectF m_bounds; diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp index b8b0972113..781d565ce4 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderablenode.cpp @@ -134,72 +134,58 @@ void QSGSoftwareRenderableNode::update() { // Update the Node properties m_isDirty = true; + m_isOpaque = false; QRectF boundingRect; switch (m_nodeType) { case QSGSoftwareRenderableNode::SimpleRect: - if (m_handle.simpleRectNode->color().alpha() == 255 && !m_transform.isRotating()) + if (m_handle.simpleRectNode->color().alpha() == 255) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.simpleRectNode->rect(); break; case QSGSoftwareRenderableNode::SimpleTexture: - if (!m_handle.simpleTextureNode->texture()->hasAlphaChannel() && !m_transform.isRotating()) + if (!m_handle.simpleTextureNode->texture()->hasAlphaChannel()) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.simpleTextureNode->rect(); break; case QSGSoftwareRenderableNode::Image: - m_isOpaque = !m_handle.imageNode->pixmap().hasAlphaChannel() && !m_transform.isRotating(); + m_isOpaque = !m_handle.imageNode->pixmap().hasAlphaChannel(); boundingRect = m_handle.imageNode->rect().toRect(); break; case QSGSoftwareRenderableNode::Painter: - if (m_handle.painterNode->opaquePainting() && !m_transform.isRotating()) + if (m_handle.painterNode->opaquePainting()) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = QRectF(0, 0, m_handle.painterNode->size().width(), m_handle.painterNode->size().height()); break; case QSGSoftwareRenderableNode::Rectangle: - if (m_handle.rectangleNode->isOpaque() && !m_transform.isRotating()) + if (m_handle.rectangleNode->isOpaque()) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.rectangleNode->rect(); break; case QSGSoftwareRenderableNode::Glyph: // Always has alpha - m_isOpaque = false; - boundingRect = m_handle.glpyhNode->boundingRect(); break; case QSGSoftwareRenderableNode::NinePatch: - // Difficult to tell, assume non-opaque - m_isOpaque = false; + m_isOpaque = m_handle.ninePatchNode->isOpaque(); boundingRect = m_handle.ninePatchNode->bounds(); break; case QSGSoftwareRenderableNode::SimpleRectangle: - if (m_handle.simpleRectangleNode->color().alpha() == 255 && !m_transform.isRotating()) + if (m_handle.simpleRectangleNode->color().alpha() == 255) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.simpleRectangleNode->rect(); break; case QSGSoftwareRenderableNode::SimpleImage: - if (!m_handle.simpleImageNode->texture()->hasAlphaChannel() && !m_transform.isRotating()) + if (!m_handle.simpleImageNode->texture()->hasAlphaChannel()) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.simpleImageNode->rect(); break; @@ -210,10 +196,8 @@ void QSGSoftwareRenderableNode::update() break; #endif case QSGSoftwareRenderableNode::RenderNode: - if (m_handle.renderNode->flags().testFlag(QSGRenderNode::OpaqueRendering) && !m_transform.isRotating()) + if (m_handle.renderNode->flags().testFlag(QSGRenderNode::OpaqueRendering)) m_isOpaque = true; - else - m_isOpaque = false; boundingRect = m_handle.renderNode->rect(); break; @@ -221,6 +205,9 @@ void QSGSoftwareRenderableNode::update() break; } + if (m_transform.isRotating()) + m_isOpaque = false; + const QRectF transformedRect = m_transform.mapRect(boundingRect); m_boundingRectMin = toRectMin(transformedRect); m_boundingRectMax = toRectMax(transformedRect); -- cgit v1.2.3 From 87999238141588987b3cef6cd68ff62a7e3e8daa Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 23 Oct 2017 11:24:16 +0200 Subject: QQmlEngineDebugService: Check QML contexts for validity We should not operate on invalid QML contexts and once we have established a context to be valid we don't have to check the result of QQmlContextData::get anymore. Change-Id: I9106115ddf925c3572048f1fd334bdfd9a9cfca7 Reviewed-by: Lars Knoll --- .../qmldbg_debugger/qqmlenginedebugservice.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp index 3d08c4c809..d2cf7dc57f 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlenginedebugservice.cpp @@ -337,6 +337,9 @@ void QQmlEngineDebugServiceImpl::buildObjectList(QDataStream &message, QQmlContext *ctxt, const QList > &instances) { + if (!ctxt->isValid()) + return; + QQmlContextData *p = QQmlContextData::get(ctxt); QString ctxtName = ctxt->objectName(); @@ -399,11 +402,8 @@ QQmlEngineDebugServiceImpl::objectData(QObject *object) } QQmlContext *context = qmlContext(object); - if (context) { - QQmlContextData *cdata = QQmlContextData::get(context); - if (cdata) - rv.idString = cdata->findObjectId(object); - } + if (context && context->isValid()) + rv.idString = QQmlContextData::get(context)->findObjectId(object); rv.objectName = object->objectName(); rv.objectId = QQmlDebugService::idForObject(object); @@ -564,14 +564,14 @@ void QQmlEngineDebugServiceImpl::processMessage(const QByteArray &message) QObject *object = QQmlDebugService::objectForId(objectId); QQmlContext *context = qmlContext(object); - if (!context) { + if (!context || !context->isValid()) { QQmlEngine *engine = qobject_cast( QQmlDebugService::objectForId(engineId)); if (engine && m_engines.contains(engine)) context = engine->rootContext(); } QVariant result; - if (context) { + if (context && context->isValid()) { QQmlExpression exprObj(context, object, expr); bool undefined = false; QVariant value = exprObj.evaluate(&undefined); @@ -632,7 +632,7 @@ bool QQmlEngineDebugServiceImpl::setBinding(int objectId, QObject *object = objectForId(objectId); QQmlContext *context = qmlContext(object); - if (object && context) { + if (object && context && context->isValid()) { QQmlProperty property(object, propertyName, context); if (property.isValid()) { @@ -677,7 +677,7 @@ bool QQmlEngineDebugServiceImpl::resetBinding(int objectId, const QString &prope QObject *object = objectForId(objectId); QQmlContext *context = qmlContext(object); - if (object && context) { + if (object && context && context->isValid()) { QStringRef parentPropertyRef(&propertyName); const int idx = parentPropertyRef.indexOf(QLatin1Char('.')); if (idx != -1) @@ -732,11 +732,9 @@ bool QQmlEngineDebugServiceImpl::setMethodBody(int objectId, const QString &meth { QObject *object = objectForId(objectId); QQmlContext *context = qmlContext(object); - if (!object || !context || !context->engine()) + if (!object || !context || !context->isValid()) return false; QQmlContextData *contextData = QQmlContextData::get(context); - if (!contextData) - return false; QQmlPropertyData dummy; QQmlPropertyData *prop = -- cgit v1.2.3 From 2e64e9e3d4bff0d93dd2671ef4aee72c566c55e1 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 1 Nov 2017 12:48:12 +0100 Subject: Prevent the QML engine from registering circular dependencies Change-Id: Ic4fd2bde745e7dfaf0909e8cc575441bb04cefa3 Task-number: QTBUG-64017 Reviewed-by: Lars Knoll Reviewed-by: Marco Martin Reviewed-by: Bhushan Shah --- src/qml/qml/qqmltypeloader.cpp | 10 +++++++++- src/qml/qml/qqmltypeloader_p.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 193acb04be..d9d7c19312 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -316,7 +316,8 @@ Returns true if the status is WaitingForDependencies. */ bool QQmlDataBlob::isWaiting() const { - return status() == WaitingForDependencies; + return status() == WaitingForDependencies || + status() == ResolvingDependencies; } /*! @@ -608,6 +609,7 @@ The default implementation does nothing. */ void QQmlDataBlob::allDependenciesDone() { + m_data.setStatus(QQmlDataBlob::ResolvingDependencies); } /*! @@ -2499,6 +2501,8 @@ void QQmlTypeData::continueLoadFromIR() void QQmlTypeData::allDependenciesDone() { + QQmlTypeLoader::Blob::allDependenciesDone(); + if (!m_typesResolved) { // Check that all imports were resolved QList errors; @@ -2618,6 +2622,10 @@ void QQmlTypeData::resolveTypes() if (ref.type.isCompositeSingleton()) { ref.typeData = typeLoader()->getType(ref.type.sourceUrl()); + if (ref.typeData->status() == QQmlDataBlob::ResolvingDependencies) { + // TODO: give an error message? If so, we should record and show the path of the cycle. + continue; + } addDependency(ref.typeData); ref.prefix = csRef.prefix; diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index ef63e02b4f..22ac61968f 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -98,6 +98,7 @@ public: Null, // Prior to QQmlTypeLoader::load() Loading, // Prior to data being received and dataReceived() being called WaitingForDependencies, // While there are outstanding addDependency()s + ResolvingDependencies, // While resolving outstanding dependencies, to detect cycles Complete, // Finished Error // Error }; -- cgit v1.2.3 From 5fc892ef86870021ad11d0be6981aa9630c1c01c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 6 Nov 2017 08:22:03 +0100 Subject: Fix coverity reported warning The variable wasn't initialized in any constructor. This didn't cause issues in practice, as it always got set in optimizeRenderList(). Change-Id: I37459bb2d51bbe2bb881aaefffd6972a5345c75d Reviewed-by: Andy Nichols --- .../scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h index c68a933384..f20c2cf977 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h @@ -104,7 +104,7 @@ private: QRegion m_dirtyRegion; QRegion m_obscuredRegion; - bool m_isOpaque; + bool m_isOpaque = false; QSGSoftwareRenderableNodeUpdater *m_nodeUpdater; }; -- cgit v1.2.3 From 37d25a5112cdf13620715c03d6bdbd1bc3cde515 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 2 Dec 2015 09:51:35 +0100 Subject: QQuickWidget: pass enter and leave events to the offscreen window By passing the enter and leave events to the offscreen window it will enable mouse areas inside a QQuickWidget to know when the mouse has actually entered or left the area if it is covering the whole item. Task-number: QTBUG-45557 Change-Id: I670ebe30e367e919c73fed449bf2bed7ca42b5fd Reviewed-by: Gatis Paeglis --- src/quickwidgets/qquickwidget.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 4c4f5fa9f3..9e18ac2270 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -1398,6 +1398,7 @@ bool QQuickWidget::event(QEvent *e) switch (e->type()) { + case QEvent::Leave: case QEvent::TouchBegin: case QEvent::TouchEnd: case QEvent::TouchUpdate: @@ -1451,6 +1452,14 @@ bool QQuickWidget::event(QEvent *e) case QEvent::ShortcutOverride: return QCoreApplication::sendEvent(d->offscreenWindow, e); + case QEvent::Enter: { + QEnterEvent *enterEvent = static_cast(e); + QEnterEvent mappedEvent(enterEvent->localPos(), enterEvent->windowPos(), + enterEvent->screenPos()); + const bool ret = QCoreApplication::sendEvent(d->offscreenWindow, &mappedEvent); + e->setAccepted(mappedEvent.isAccepted()); + return ret; + } default: break; } -- cgit v1.2.3 From 75cc5fdc219c42ae26ec8497647eda5440c324f2 Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 6 Nov 2017 14:20:59 +0100 Subject: Never create pointer events from mouseGrabberItem() Normally, this was not a problem, but it is problematic during QQuickWindow destruction: The list of pointer event instances are destroyed, but later the grabber is removed (through call to removeGrabber()). This queries the mouseGrabberItem(), which would create a new pointer event instance. It also has the benefit that d->pointerEventInstances are now only populated due to actual incoming events. Task-number: QTBUG-61434 Change-Id: I4e7b6f5643f3b971138a1f7c7237ee734d29783c Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 38 +++++++++++++++++++++++--------------- src/quick/items/qquickwindow_p.h | 1 + 2 files changed, 24 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index b58caa061a..112a338920 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -823,12 +823,13 @@ void QQuickWindowPrivate::removeGrabber(QQuickItem *grabber, bool mouse, bool to if (Q_LIKELY(touch)) { const auto touchDevices = QQuickPointerDevice::touchDevices(); for (auto device : touchDevices) { - auto pointerEvent = pointerEventInstance(device); - for (int i = 0; i < pointerEvent->pointCount(); ++i) { - if (pointerEvent->point(i)->grabber() == grabber) { - pointerEvent->point(i)->setGrabber(nullptr); - // FIXME send ungrab event only once - grabber->touchUngrabEvent(); + if (auto pointerEvent = queryPointerEventInstance(device)) { + for (int i = 0; i < pointerEvent->pointCount(); ++i) { + if (pointerEvent->point(i)->grabber() == grabber) { + pointerEvent->point(i)->setGrabber(nullptr); + // FIXME send ungrab event only once + grabber->touchUngrabEvent(); + } } } } @@ -1492,14 +1493,15 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const Q_D(const QQuickWindow); if (d->touchMouseId != -1 && d->touchMouseDevice) { - QQuickPointerEvent *event = d->pointerEventInstance(d->touchMouseDevice); - auto point = event->pointById(d->touchMouseId); - return point ? point->grabber() : nullptr; + if (QQuickPointerEvent *event = d->queryPointerEventInstance(d->touchMouseDevice)) { + auto point = event->pointById(d->touchMouseId); + return point ? point->grabber() : nullptr; + } + } else if (QQuickPointerEvent *event = d->queryPointerEventInstance(QQuickPointerDevice::genericMouseDevice())) { + Q_ASSERT(event->pointCount()); + return event->point(0)->grabber(); } - - QQuickPointerEvent *event = d->pointerEventInstance(QQuickPointerDevice::genericMouseDevice()); - Q_ASSERT(event->pointCount()); - return event->point(0)->grabber(); + return nullptr; } @@ -2111,15 +2113,21 @@ void QQuickWindowPrivate::flushFrameSynchronousEvents() } } -QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const +QQuickPointerEvent *QQuickWindowPrivate::queryPointerEventInstance(QQuickPointerDevice *device) const { // the list of devices should be very small so a linear search should be ok for (QQuickPointerEvent *e: pointerEventInstances) { if (e->device() == device) return e; } + return nullptr; +} - QQuickPointerEvent *ev = nullptr; +QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QQuickPointerDevice *device) const +{ + QQuickPointerEvent *ev = queryPointerEventInstance(device); + if (ev) + return ev; QQuickWindow *q = const_cast(q_func()); switch (device->type()) { case QQuickPointerDevice::Mouse: diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index b3ff5a2b35..e47dde6464 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -164,6 +164,7 @@ public: // the device-specific event instances which are reused during event delivery mutable QVector pointerEventInstances; + QQuickPointerEvent *queryPointerEventInstance(QQuickPointerDevice *device) const; QQuickPointerEvent *pointerEventInstance(QQuickPointerDevice *device) const; // delivery of pointer events: -- cgit v1.2.3 From 4331ccd4b735d9d721a384193a3d42ee2ce6c805 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 14 Jul 2017 16:37:22 +0200 Subject: QQuickWindow: cleanup pointer event instances MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointer event instances are QObject-children of QQuickWindow, meaning that they remain alive after ~QQuickWindow(), until execution reaches ~QObject(). Make sure the pointer event instances are cleaned up in ~QQuickWindow() to avoid accessing them later during the destruction phase. Task-number: QTBUG-61434 Change-Id: Icd4576e7581524773a3eb33864fdd64df821e0e8 Reviewed-by: Jan Arve Sæther Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 112a338920..70c8590ae7 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1292,6 +1292,8 @@ QQuickWindow::~QQuickWindow() delete d->dragGrabber; d->dragGrabber = 0; #endif delete d->contentItem; d->contentItem = 0; + qDeleteAll(d->pointerEventInstances); + d->pointerEventInstances.clear(); d->renderJobMutex.lock(); qDeleteAll(d->beforeSynchronizingJobs); -- cgit v1.2.3 From 54f15f5df5cf545bf4d675ccbafecd482b4a2b0b Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Mon, 23 Oct 2017 13:51:43 +0300 Subject: Fix ListView::positionViewAtIndex with ListView.Contain mode Sticky headers and footers weren't accounted for when calculating new view position causing the requested item to be left behind them. Task-number: QTBUG-63974 Change-Id: Id69579643a942e8558960b2c8b0fee980fa86947 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitemview.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 478499e209..c203f389ae 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -952,11 +952,16 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) item = visibleItem(idx); } if (item) { + const bool stickyHeader = hasStickyHeader(); + const bool stickyFooter = hasStickyFooter(); + const qreal stickyHeaderSize = stickyHeader ? headerSize() : 0; + const qreal stickyFooterSize = stickyFooter ? footerSize() : 0; + const qreal itemPos = item->position(); switch (mode) { case QQuickItemView::Beginning: pos = itemPos; - if (header && (index < 0 || hasStickyHeader())) + if (header && (index < 0 || stickyHeader)) pos -= headerSize(); break; case QQuickItemView::Center: @@ -964,23 +969,23 @@ void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode) break; case QQuickItemView::End: pos = itemPos - viewSize + item->size(); - if (footer && (index >= modelCount || hasStickyFooter())) + if (footer && (index >= modelCount || stickyFooter)) pos += footerSize(); break; case QQuickItemView::Visible: - if (itemPos > pos + viewSize) - pos = itemPos - viewSize + item->size(); - else if (item->endPosition() <= pos) - pos = itemPos; + if (itemPos > pos + viewSize - stickyFooterSize) + pos = item->endPosition() - viewSize + stickyFooterSize; + else if (item->endPosition() <= pos - stickyHeaderSize) + pos = itemPos - stickyHeaderSize; break; case QQuickItemView::Contain: - if (item->endPosition() >= pos + viewSize) - pos = itemPos - viewSize + item->size(); - if (itemPos < pos) - pos = itemPos; + if (item->endPosition() >= pos + viewSize + stickyFooterSize) + pos = itemPos - viewSize + item->size() + stickyFooterSize; + if (itemPos - stickyHeaderSize < pos) + pos = itemPos - stickyHeaderSize; break; case QQuickItemView::SnapPosition: - pos = itemPos - highlightRangeStart; + pos = itemPos - highlightRangeStart - stickyHeaderSize; break; } pos = qMin(pos, maxExtent); -- cgit v1.2.3 From 34992750d7d35086e26067fba14098f24caca4d3 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 6 Nov 2017 13:20:09 -0600 Subject: Check for duplication with url rather than uri We might have duplicated uris with different paths. This comparison is meant to check for multiple imports of the same path. Change-Id: I2d99728d32116453ae92a152337d2627c2653b79 Task-number: QTBUG-64237 Reviewed-by: Tim Jenssen --- src/qml/qml/qqmlimport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index a85166da65..334bc8b28e 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1539,7 +1539,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix if (isImplicitImport) { for (QList::const_iterator it = nameSpace->imports.constBegin(); it != nameSpace->imports.constEnd(); ++it) { - if ((*it)->uri == importUri) { + if ((*it)->url == url) { (*it)->implicitlyImported = true; return true; } -- cgit v1.2.3 From 7853634a1134a2b4b470a6d2c8b5da1610105d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Tue, 7 Nov 2017 14:06:50 +0100 Subject: Remove deprecated grabber() We already have grabberItem() that serves the same purpose Change-Id: I137ebab8ecc2c3924e55015e28735eefc79c2ae8 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickevents_p_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickevents_p_p.h b/src/quick/items/qquickevents_p_p.h index 09a63febdc..af5857cf63 100644 --- a/src/quick/items/qquickevents_p_p.h +++ b/src/quick/items/qquickevents_p_p.h @@ -306,7 +306,6 @@ public: void setExclusiveGrabber(QObject *exclusiveGrabber); QQuickItem *grabberItem() const; - Q_DECL_DEPRECATED QQuickItem *grabber() const { return grabberItem(); } void setGrabberItem(QQuickItem *exclusiveGrabber); QQuickPointerHandler *grabberPointerHandler() const; -- cgit v1.2.3 From 9cb3bc655a42f386607316d228a64422d453b201 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 2 Nov 2017 13:56:52 +0100 Subject: docs and example: clarify the usage of Flickable contentX/contentY It's such a common mistake to observe that they normally go to zero at the top-left corner, but fail to realize that they won't always do that. Task-number: QTBUG-64219 Task-number: QTBUG-22894 Task-number: QTBUG-27884 Change-Id: I6bc81d4761debdaff8fb3366bf1e944241207157 Reviewed-by: J-P Nurmi --- src/quick/items/qquickflickable.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index e0f8b6de00..3662827973 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -734,7 +734,19 @@ QQuickFlickable::~QQuickFlickable() These properties hold the surface coordinate currently at the top-left corner of the Flickable. For example, if you flick an image up 100 pixels, - \c contentY will be 100. + \c contentY will increase by 100. + + \note If you flick back to the origin (the top-left corner), after the + rebound animation, \c contentX will settle to the same value as \c originX, + and \c contentY to \c originY. These are usually (0,0), however ListView + and GridView may have an arbitrary origin due to delegate size variation, + or item insertion/removal outside the visible region. So if you want to + implement something like a vertical scrollbar, one way is to use + \c {y: (contentY - originY) * (height / contentHeight)} + for the position; another way is to use the normalized values in + \l {QtQuick::Flickable::visibleArea}{visibleArea}. + + \sa originX, originY */ qreal QQuickFlickable::contentX() const { @@ -2153,6 +2165,8 @@ void QQuickFlickable::setRightMargin(qreal m) This is usually (0,0), however ListView and GridView may have an arbitrary origin due to delegate size variation, or item insertion/removal outside the visible region. + + \sa contentX, contentY */ qreal QQuickFlickable::originY() const -- cgit v1.2.3 From 05220b707b1bd901adb61ecae77177b88ed832ca Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Tue, 7 Nov 2017 13:06:34 +0100 Subject: Fix tst_qquickshadereffect The expected signal counts were not matching. Since the test has not been run in the CI, it went unnoticed. Furthermore, the test crashed due to a missing null pointer check. Change-Id: Iff80a2ea17832eb7bc531ac9eb2fc482f2c69e38 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickopenglshadereffect.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickopenglshadereffect.cpp b/src/quick/items/qquickopenglshadereffect.cpp index 4fcfe04b55..193478484e 100644 --- a/src/quick/items/qquickopenglshadereffect.cpp +++ b/src/quick/items/qquickopenglshadereffect.cpp @@ -890,7 +890,7 @@ QSGNode *QQuickOpenGLShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuic bool geometryUsesTextureSubRect = false; if (m_supportsAtlasTextures && material->textureProviders.size() == 1) { QSGTextureProvider *provider = material->textureProviders.at(0); - if (provider->texture()) { + if (provider && provider->texture()) { srcRect = provider->texture()->normalizedTextureSubRect(); geometryUsesTextureSubRect = true; } -- cgit v1.2.3 From 6990ae6c1bad32952e371fa72bee65a7af11c313 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 23 Oct 2017 15:03:05 +0200 Subject: Make sure we remove stopped animators from the list of roots Change-Id: I89b36ee7d03ac6b8d07b24c656d3311728e8f9c3 Reviewed-by: J-P Nurmi --- src/quick/util/qquickanimatorcontroller.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index 3f7347c01d..5cf8051922 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -123,8 +123,10 @@ static void qquickanimator_sync_before_start(QAbstractAnimationJob *job) void QQuickAnimatorController::beforeNodeSync() { - for (const QSharedPointer &toStop : qAsConst(m_rootsPendingStop)) + for (const QSharedPointer &toStop : qAsConst(m_rootsPendingStop)) { toStop->stop(); + m_animationRoots.remove(toStop.data()); + } m_rootsPendingStop.clear(); -- cgit v1.2.3 From 85fc49612816dcfc81c9dc265b146b0b90b0f184 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 8 Nov 2017 15:58:25 +0100 Subject: Prevent crashes when profiling translation bindings The m_v4Function member can now be a nullptr, which means we cannot use it as ID and we cannot retrieve the source location from it. Change-Id: Ibb49a3e68cf961f9ffe2a83b2a0b83f7d04e149e Reviewed-by: hjk Reviewed-by: Simon Hausmann --- src/qml/debugger/qqmlprofiler_p.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/qml/debugger/qqmlprofiler_p.h b/src/qml/debugger/qqmlprofiler_p.h index 88f8e94f25..6dc9859295 100644 --- a/src/qml/debugger/qqmlprofiler_p.h +++ b/src/qml/debugger/qqmlprofiler_p.h @@ -237,14 +237,19 @@ public: // Add 1 to the ID, to make it different from the IDs the V4 profiler produces. The +1 makes // the pointer point into the middle of the QV4::Function. Thus it still points to valid // memory but we cannot accidentally create a duplicate key from another object. - quintptr locationId(id(function) + 1); + // If there is no function, use a static but valid address: The profiler itself. + quintptr locationId = function ? id(function) + 1 : id(this); m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), (1 << RangeStart | 1 << RangeLocation), Binding, locationId)); RefLocation &location = m_locations[locationId]; - if (!location.isValid()) - location = RefLocation(function); + if (!location.isValid()) { + if (function) + location = RefLocation(function); + else // Make it valid without actually providing a location + location.locationType = Binding; + } } // Have toByteArrays() construct another RangeData event from the same QString later. -- cgit v1.2.3 From fdfb34c84ba01114d34259cd88a2b84fa22eb610 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 9 Nov 2017 10:43:42 +0100 Subject: Improve encapsulation of the the IR de-serialization from QtQuick Compiler The code used by QQC to deserialize the IR requires setting the javaScriptCompilationUnit member in order to connect the generated C++ code. Knowledge of the QmlIR::Document data structure layout on the side of the generated code (thus application) has its downsides though (see referenced bug). We can avoid that dependency easily by doing the entire de-serialization on the QtQml library side. The old "API" (load member function) is still around until the qqc change is also in. Task-number: QTBUG-63474 Change-Id: I239838afacc71474c86114b5b05679ff36e4c2e2 Reviewed-by: Lars Knoll --- src/qml/qml/qqmltypeloader.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index d9d7c19312..842cf74887 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2409,7 +2409,15 @@ void QQmlTypeData::dataReceived(const SourceCodeData &data) void QQmlTypeData::initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit *unit) { m_document.reset(new QmlIR::Document(isDebugging())); - unit->loadIR(m_document.data(), unit); + if (unit->loadIR) { + // old code path for older generated code + unit->loadIR(m_document.data(), unit); + } else { + // new code path + QmlIR::IRLoader loader(unit->qmlData, m_document.data()); + loader.load(); + m_document->javaScriptCompilationUnit.adopt(unit->createCompilationUnit()); + } continueLoadFromIR(); } -- cgit v1.2.3 From 447f8e399de2a68bdd92238523201e56d1929a0f Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Tue, 7 Nov 2017 12:31:05 +0100 Subject: Doc: Update the list of highlighted examples Update the list of highlighted examples for modules in qtdeclarative. Currently highlighted examples/demos for Qt Quick are in relatively good condition, so keep the highlighting for them. Add highlighting for 'Writing QML Extensions with C++' tutorial in Qt QML. Task-number: QTBUG-60629 Task-number: QTBUG-60630 Change-Id: If7fe8705cf8614d5a811d88f44a0c00ecf3348f0 Reviewed-by: Nico Vertriest --- src/qml/doc/qtqml.qdocconf | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/qml/doc/qtqml.qdocconf b/src/qml/doc/qtqml.qdocconf index 74b61fd6e1..6161760471 100644 --- a/src/qml/doc/qtqml.qdocconf +++ b/src/qml/doc/qtqml.qdocconf @@ -53,6 +53,8 @@ manifestmeta.thumbnail.names += "QtQml/Chapter 4*" \ "QtQml/Chapter 6*" \ "QtQml/C++ Extensions: *" +manifestmeta.highlighted.names = "QtQml/Writing QML Extensions with C++" + navigation.landingpage = "Qt QML" navigation.cppclassespage = "Qt QML C++ Classes" navigation.qmltypespage = "Qt QML QML Types" -- cgit v1.2.3 From 38a016c7b1337d83d77879f45b4a2e6fec11d049 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 24 Oct 2017 11:40:47 +0200 Subject: QQuickEventPoint: make ungrab/cancel notifications more consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setGrabberPointerHandler is now implemented more similarly to setGrabberItem. One improvement is that in tests/manual/pointer/pinchDragFlingMPTA.qml the MPTA deactivates when the PinchHandler takes over its touchpoint grabs. Change-Id: I0bd4f143b5f25f1b393839f86c2a7802f1fa1886 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickevents.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 8653d758de..35ace7592f 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -800,7 +800,7 @@ void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) m_grabberIsHandler = false; m_sceneGrabPos = m_scenePos; if (oldGrabberHandler) - oldGrabberHandler->onGrabChanged(oldGrabberHandler, CancelGrabExclusive, this); + oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this); else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent()) oldGrabberItem->touchUngrabEvent(); for (QPointer passiveGrabber : m_passiveGrabbers) @@ -837,26 +837,24 @@ void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, b } if (exclusive) { if (grabber != m_exclusiveGrabber.data()) { + QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler(); + QQuickItem *oldGrabberItem = grabberItem(); + m_exclusiveGrabber = QPointer(grabber); + m_grabberIsHandler = true; + m_sceneGrabPos = m_scenePos; if (grabber) { - // set variables before notifying the new grabber - m_exclusiveGrabber = QPointer(grabber); - m_grabberIsHandler = true; - m_sceneGrabPos = m_scenePos; grabber->onGrabChanged(grabber, GrabExclusive, this); for (QPointer passiveGrabber : m_passiveGrabbers) { if (passiveGrabber != grabber) passiveGrabber->onGrabChanged(grabber, OverrideGrabPassive, this); } - } else if (QQuickPointerHandler *oldGrabberPointerHandler = qmlobject_cast(m_exclusiveGrabber.data())) { - oldGrabberPointerHandler->onGrabChanged(oldGrabberPointerHandler, UngrabExclusive, this); - } else if (!m_exclusiveGrabber.isNull()) { - // If there is a previous grabber and it's not a PointerHandler, it must be an Item. - QQuickItem *oldGrabberItem = static_cast(m_exclusiveGrabber.data()); - // If this point came from a touchscreen, notify that previous grabber Item that it's losing its touch grab. - if (pointerEvent()->asPointerTouchEvent()) - oldGrabberItem->touchUngrabEvent(); } - // set variables after notifying the old grabber + if (oldGrabberHandler) + oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this); + else if (oldGrabberItem && pointerEvent()->asPointerTouchEvent()) + oldGrabberItem->touchUngrabEvent(); + // touchUngrabEvent() can result in the grabber being set to null (MPTA does that, for example). + // So set it again to ensure that final state is what we want. m_exclusiveGrabber = QPointer(grabber); m_grabberIsHandler = true; m_sceneGrabPos = m_scenePos; -- cgit v1.2.3 From a2e2c8a329768e783b205564e44b2f486b777d74 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 18 May 2017 11:23:25 +0200 Subject: Let passive-grabbing PointerHandlers see all point updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit even if all points are accepted or grabbed. A passive grab isn't much good if there are cases where the handler is prevented from monitoring. This enables e.g. the PinchHandler to steal the grab when the right number of touchpoints are present and have moved past the drag threshold, and enables completion of a couple of autotests. Change-Id: I78dc6fc585f80bfb3c13e0c6e757ef815fb94afe Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquickpinchhandler.cpp | 13 +++-- src/quick/items/qquickwindow.cpp | 90 +++++++++++++------------------ 2 files changed, 46 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 84c4e912d1..4db96d8a99 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -349,13 +349,18 @@ void QQuickPinchHandler::handlePointerEventImpl(QQuickPointerEvent *event) } } else { bool containsReleasedPoints = event->isReleaseEvent(); - if (!active() && !containsReleasedPoints) { + if (!active()) { // Verify that at least one of the points has moved beyond threshold needed to activate the handler for (QQuickEventPoint *point : qAsConst(m_currentPoints)) { - if (QQuickWindowPrivate::dragOverThreshold(point)) { - if (grabPoints(m_currentPoints)) - setActive(true); + if (!containsReleasedPoints && QQuickWindowPrivate::dragOverThreshold(point) && grabPoints(m_currentPoints)) { + setActive(true); break; + } else { + setPassiveGrab(point); + } + if (point->state() == QQuickEventPoint::Pressed) { + point->setAccepted(false); // don't stop propagation + setPassiveGrab(point); } } if (!active()) diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 73a594b281..4bee6dcd9a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -768,16 +768,12 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) pt->cancelExclusiveGrab(); } point->setGrabberItem(grabber); - for (auto handler : point->passiveGrabbers()) - point->cancelPassiveGrab(handler); } } else { QQuickPointerEvent *event = pointerEventInstance(QQuickPointerDevice::genericMouseDevice()); Q_ASSERT(event->pointCount() == 1); auto point = event->point(0); point->setGrabberItem(grabber); - for (auto handler : point->passiveGrabbers()) - point->cancelPassiveGrab(handler); } @@ -1745,6 +1741,7 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven if (mouseIsReleased) point->setGrabberPointerHandler(nullptr, true); } + deliverToPassiveGrabbers(point->passiveGrabbers(), pointerEvent); } else { bool delivered = false; if (pointerEvent->isPressEvent()) { @@ -2410,6 +2407,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event) // Deliver touch points to existing grabbers void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *event) { + bool done = false; const auto grabbers = event->exclusiveGrabbers(); for (auto grabber : grabbers) { // The grabber is guaranteed to be either an item or a handler. @@ -2419,52 +2417,52 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve QQuickPointerHandler *handler = static_cast(grabber); receiver = static_cast(grabber)->parentItem(); if (sendFilteredPointerEvent(event, receiver)) - return; + done = true; event->localize(receiver); handler->handlePointerEvent(event); if (event->allPointsAccepted()) - return; + done = true; } + if (done) + break; // If the grabber is an item or the grabbing handler didn't handle it, // then deliver the event to the item (which may have multiple handlers). deliverMatchingPointsToItem(receiver, event); } - // If some points weren't grabbed, deliver only to non-grabber PointerHandlers - if (!event->allPointsGrabbed()) { - int pointCount = event->pointCount(); + // Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once) + int pointCount = event->pointCount(); + for (int i = 0; i < pointCount; ++i) { + QQuickEventPoint *point = event->point(i); + deliverToPassiveGrabbers(point->passiveGrabbers(), event); + } + + if (done) + return; - // Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once) + // If some points weren't grabbed, deliver only to non-grabber PointerHandlers in reverse paint order + if (!event->allPointsGrabbed()) { + QVector targetItems; for (int i = 0; i < pointCount; ++i) { QQuickEventPoint *point = event->point(i); - deliverToPassiveGrabbers(point->passiveGrabbers(), event); - } - - // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order - if (!event->allPointsGrabbed()) { - QVector targetItems; - for (int i = 0; i < pointCount; ++i) { - 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->scenePosition(), false, false); - if (targetItems.count()) { - targetItems = mergePointerTargets(targetItems, targetItemsForPoint); - } else { - targetItems = targetItemsForPoint; - } - } - - for (QQuickItem *item: targetItems) { - if (grabbers.contains(item)) - continue; - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - event->localize(item); - itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers - if (event->allPointsGrabbed()) - break; + if (point->state() == QQuickEventPoint::Pressed) + continue; // presses were delivered earlier; not the responsibility of deliverUpdatedTouchPoints + QVector targetItemsForPoint = pointerTargets(contentItem, point->scenePosition(), false, false); + if (targetItems.count()) { + targetItems = mergePointerTargets(targetItems, targetItemsForPoint); + } else { + targetItems = targetItemsForPoint; } } + for (QQuickItem *item : targetItems) { + if (grabbers.contains(item)) + continue; + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); + event->localize(item); + itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers + if (event->allPointsGrabbed()) + break; + } } } @@ -2503,7 +2501,7 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, continue; deliverMatchingPointsToItem(item, event, handlersOnly); if (event->allPointsAccepted()) - break; + handlersOnly = true; } return event->allPointsAccepted(); @@ -2518,8 +2516,9 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo // Let the Item's handlers (if any) have the event first. // However, double click should never be delivered to handlers. if (!pointerEvent->isDoubleClickEvent()) { + bool wasAccepted = pointerEvent->allPointsAccepted(); itemPrivate->handlePointerEvent(pointerEvent); - allowDoubleClick = !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted()); + allowDoubleClick = wasAccepted || !(pointerEvent->asPointerMouseEvent() && pointerEvent->isPressEvent() && pointerEvent->allPointsAccepted()); } if (handlersOnly) return; @@ -2831,17 +2830,10 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event // get a touch event customized for delivery to filteringParent QScopedPointer filteringParentTouchEvent(pte->touchEventForItem(receiver, true)); if (filteringParentTouchEvent) { - QVarLengthArray, 32> passiveGrabsToCancel; if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) { qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; skipDelivery.append(filteringParent); 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); - } QQuickEventPoint *pt = event->pointById(point.id()); pt->setAccepted(); pt->setGrabberItem(filteringParent); @@ -2887,12 +2879,6 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set if (mouseEvent->isAccepted()) 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; } @@ -2908,8 +2894,6 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event } } } - for (auto grab : passiveGrabsToCancel) - grab.second->cancelPassiveGrab(grab.first); } } } -- cgit v1.2.3 From 3cc2148eab7f541bb8551087567b7580a2ea1822 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 9 Nov 2017 10:41:53 +0100 Subject: PointerHandler: add grabPermissions, enforce in setExclusiveGrab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As soon as we enable the concept that PointerHandlers can use passive grabs to lurk, monitor all movements, and then steal the passive grab, they can fight over the grab. For example if there are two items with PinchHandlers, and two or more touches occur within bounds for both, then each update event can cause the other PinchHandler to steal the grabs and become active. So we replace stealing with negotiation: the handler which wants to take over the grab checks its own flags to see whether that's allowed, and the handler which is about to lose its grab also has the right to approve or deny the takeover (just as QQuickItem has had keepMouseGrab and keepTouchGrab for a long time.) Additionally, if one handler wants to cancel another handler's grab without taking over (simply set the grabber to null), it must be approved. A single-point handler can simply call setExclusiveGrab, with the expectation that permission may be granted or denied. A multi-point handler only wants to grab all points if grabbing all of them will be allowed, otherwise grab none; so it calls canGrab on each point to check beforehand. Thus, when two handlers are competing for the same grabs, one or both can be prevented from stealing from each other, or from Handlers in general, or from Items, or some combination. Change-Id: I5c733b2b8995ce686da0be42244394eeee82a268 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquickmultipointhandler.cpp | 13 +-- src/quick/handlers/qquickpointerhandler.cpp | 130 +++++++++++++++++++++++-- src/quick/handlers/qquickpointerhandler_p.h | 28 +++++- src/quick/items/qquickevents.cpp | 8 +- 4 files changed, 160 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/quick/handlers/qquickmultipointhandler.cpp b/src/quick/handlers/qquickmultipointhandler.cpp index ff4914394c..b126b93211 100644 --- a/src/quick/handlers/qquickmultipointhandler.cpp +++ b/src/quick/handlers/qquickmultipointhandler.cpp @@ -298,17 +298,18 @@ void QQuickMultiPointHandler::acceptPoints(const QVector &po bool QQuickMultiPointHandler::grabPoints(QVector points) { - bool canGrab = true; + bool allowed = true; for (QQuickEventPoint* point : points) { - auto grabber = point->grabberItem(); - if (grabber && (grabber->keepMouseGrab() || grabber->keepTouchGrab())) - canGrab = false; + if (!canGrab(point)) { + allowed = false; + break; + } } - if (canGrab) { + if (allowed) { for (QQuickEventPoint* point : points) setExclusiveGrab(point); } - return canGrab; + return allowed; } QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp index faebdf3621..64bf1a8a8b 100644 --- a/src/quick/handlers/qquickpointerhandler.cpp +++ b/src/quick/handlers/qquickpointerhandler.cpp @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcPointerHandlerDispatch, "qt.quick.handler.dispatch") +Q_LOGGING_CATEGORY(lcPointerHandlerGrab, "qt.quick.handler.grab") Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active") /*! @@ -67,6 +68,7 @@ QQuickPointerHandler::QQuickPointerHandler(QObject *parent) , m_targetExplicitlySet(false) , m_hadKeepMouseGrab(false) , m_hadKeepTouchGrab(false) + , m_grabPermissions(CanTakeOverFromItems | CanTakeOverFromHandlersOfDifferentType | ApprovesTakeOverByAnything) { } @@ -94,7 +96,7 @@ QQuickPointerHandler::~QQuickPointerHandler() */ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point) { - qCDebug(lcPointerHandlerDispatch) << point << stateChange << grabber; + qCDebug(lcPointerHandlerGrab) << point << stateChange << grabber; Q_ASSERT(point); if (grabber == this) { bool wasCanceled = false; @@ -145,7 +147,7 @@ void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEv */ void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab) { - qCDebug(lcPointerHandlerDispatch) << point << grab; + qCDebug(lcPointerHandlerGrab) << point << grab; if (grab) { point->setGrabberPointerHandler(this, false); } else { @@ -153,14 +155,124 @@ void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab) } } -void QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab) +/*! + Check whether it's OK to take an exclusive grab of the \a point. + + The default implementation will call approveGrabTransition() to check this + handler's \l grabPermissions. If grabbing can be done only by taking over + the exclusive grab from an Item, approveGrabTransition() checks the Item's + \l keepMouseGrab or \l keepTouchGrab flags appropriately. If grabbing can + be done only by taking over another handler's exclusive grab, canGrab() + also calls approveGrabTransition() on the handler which is about to lose + its grab. Either one can deny the takeover. +*/ +bool QQuickPointerHandler::canGrab(QQuickEventPoint *point) { - // TODO m_hadKeepMouseGrab m_hadKeepTouchGrab - qCDebug(lcPointerHandlerDispatch) << point << grab; - // Don't allow one handler to cancel another's grab, unless it is stealing it for itself - if (!grab && point->grabberPointerHandler() != this) + QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler(); + return approveGrabTransition(point, this) && + (existingPhGrabber ? existingPhGrabber->approveGrabTransition(point, this) : true); +} + +/*! + Check this handler's rules to see if \l proposedGrabber will be allowed to take + the exclusive grab. This function may be called twice: once on the instance which + will take the grab, and once on the instance which would thereby lose its grab, + in case of a takeover scenario. +*/ +bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber) +{ + bool allowed = false; + if (proposedGrabber == this) { + QObject* existingGrabber = point->exclusiveGrabber(); + allowed = (existingGrabber == nullptr) || ((m_grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything); + if (existingGrabber) { + if (QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler()) { + if (!allowed && (m_grabPermissions & CanTakeOverFromHandlersOfDifferentType) && + existingPhGrabber->metaObject()->className() != metaObject()->className()) + allowed = true; + if (!allowed && (m_grabPermissions & CanTakeOverFromHandlersOfSameType) && + existingPhGrabber->metaObject()->className() == metaObject()->className()) + allowed = true; + } else if ((m_grabPermissions & CanTakeOverFromItems)) { + QQuickItem * existingItemGrabber = point->grabberItem(); + if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && point->pointerEvent()->asPointerMouseEvent()) || + (existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent()))) + allowed = true; + } + } + } else { + // proposedGrabber is different: that means this instance will lose its grab + if (proposedGrabber) { + if ((m_grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything) + allowed = true; + if (!allowed && (m_grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) && + proposedGrabber->metaObject()->className() != metaObject()->className()) + allowed = true; + if (!allowed && (m_grabPermissions & ApprovesTakeOverByHandlersOfSameType) && + proposedGrabber->metaObject()->className() == metaObject()->className()) + allowed = true; + if (!allowed && (m_grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem")) + allowed = true; + } else { + if (!allowed && (m_grabPermissions & ApprovesCancellation)) + allowed = true; + } + } + qCDebug(lcPointerHandlerGrab) << "point" << hex << point->pointId() << "permission" << + QMetaEnum::fromType().valueToKeys(grabPermissions()) << + ':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber; + return allowed; +} + +/*! + \qmlproperty bool QtQuick::PointerHandler::grabPermission + + This property specifies the permissions when this handler's logic decides + to take over the exclusive grab, or when it is asked to approve grab + takeover or cancellation by another handler. + + The default is + \c {CanTakeOverFromItems | CanTakeOverFromHandlersOfDifferentType | ApprovesTakeOverByAnything} + which allows most takeover scenarios but avoids e.g. two PinchHandlers fighting + over the same touchpoints. +*/ +void QQuickPointerHandler::setGrabPermissions(GrabPermissions grabPermission) +{ + if (m_grabPermissions == grabPermission) return; - point->setGrabberPointerHandler(grab ? this : nullptr, true); + + m_grabPermissions = grabPermission; + emit grabPermissionChanged(); +} + +/*! + \internal + Acquire or give up the exclusive grab of the given \a point, according to + the \a grab state, and subject to the rules: canGrab(), and the rule not to + relinquish another handler's grab. Returns true if permission is granted, + or if the exclusive grab has already been acquired or relinquished as + specified. Returns false if permission is denied either by this handler or + by the handler or item from which this handler would take over +*/ +bool QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab) +{ + if ((grab && point->exclusiveGrabber() == this) || (!grab && point->exclusiveGrabber() != this)) + return true; + // TODO m_hadKeepMouseGrab m_hadKeepTouchGrab + bool allowed = true; + if (grab) { + allowed = canGrab(point); + } else { + QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler(); + // Ask before allowing one handler to cancel another's grab + if (existingPhGrabber && existingPhGrabber != this && !existingPhGrabber->approveGrabTransition(point, nullptr)) + allowed = false; + } + qCDebug(lcPointerHandlerGrab) << point << (grab ? "grab" : "ungrab") << (allowed ? "allowed" : "forbidden") << + point->exclusiveGrabber() << "->" << (grab ? this : nullptr); + if (allowed) + point->setGrabberPointerHandler(grab ? this : nullptr, true); + return allowed; } /*! @@ -169,7 +281,7 @@ void QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab) */ void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point) { - qCDebug(lcPointerHandlerDispatch) << point; + qCDebug(lcPointerHandlerGrab) << point; point->cancelAllGrabs(this); } diff --git a/src/quick/handlers/qquickpointerhandler_p.h b/src/quick/handlers/qquickpointerhandler_p.h index 24a058275d..9a77dd714a 100644 --- a/src/quick/handlers/qquickpointerhandler_p.h +++ b/src/quick/handlers/qquickpointerhandler_p.h @@ -67,11 +67,27 @@ class Q_QUICK_PRIVATE_EXPORT QQuickPointerHandler : public QObject Q_PROPERTY(bool active READ active NOTIFY activeChanged) Q_PROPERTY(QQuickItem * target READ target WRITE setTarget NOTIFY targetChanged) Q_PROPERTY(QQuickItem * parent READ parentItem CONSTANT) + Q_PROPERTY(GrabPermissions grabPermissions READ grabPermissions WRITE setGrabPermissions NOTIFY grabPermissionChanged) public: explicit QQuickPointerHandler(QObject *parent = 0); virtual ~QQuickPointerHandler(); + enum GrabPermission { + TakeOverForbidden = 0x0, + CanTakeOverFromHandlersOfSameType = 0x01, + CanTakeOverFromHandlersOfDifferentType= 0x02, + CanTakeOverFromItems = 0x04, + CanTakeOverFromAnything = 0x0F, + ApprovesTakeOverByHandlersOfSameType = 0x10, + ApprovesTakeOverByHandlersOfDifferentType= 0x20, + ApprovesTakeOverByItems = 0x40, + ApprovesCancellation = 0x80, + ApprovesTakeOverByAnything = 0xF0 + }; + Q_DECLARE_FLAGS(GrabPermissions, GrabPermission) + Q_FLAG(GrabPermissions) + public: bool enabled() const { return m_enabled; } void setEnabled(bool enabled); @@ -85,11 +101,15 @@ public: void handlePointerEvent(QQuickPointerEvent *event); + GrabPermissions grabPermissions() const { return static_cast(m_grabPermissions); } + void setGrabPermissions(GrabPermissions grabPermissions); + Q_SIGNALS: void enabledChanged(); void activeChanged(); void targetChanged(); void grabChanged(QQuickEventPoint *point); + void grabPermissionChanged(); void canceled(QQuickEventPoint *point); protected: @@ -99,8 +119,10 @@ protected: void setActive(bool active); virtual void onActiveChanged() { } virtual void onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point); + virtual bool canGrab(QQuickEventPoint *point); + virtual bool approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber); void setPassiveGrab(QQuickEventPoint *point, bool grab = true); - void setExclusiveGrab(QQuickEventPoint *point, bool grab = true); + bool setExclusiveGrab(QQuickEventPoint *point, bool grab = true); void cancelAllGrabs(QQuickEventPoint *point); QPointF eventPos(const QQuickEventPoint *point) const; bool parentContains(const QQuickEventPoint *point) const; @@ -113,11 +135,15 @@ private: bool m_targetExplicitlySet : 1; bool m_hadKeepMouseGrab : 1; // some handlers override target()->setKeepMouseGrab(); this remembers previous state bool m_hadKeepTouchGrab : 1; // some handlers override target()->setKeepTouchGrab(); this remembers previous state + uint m_reserved : 19; + uint8_t m_grabPermissions : 8; friend class QQuickEventPoint; friend class QQuickWindowPrivate; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickPointerHandler::GrabPermissions) + QT_END_NAMESPACE QML_DECLARE_TYPE(QQuickPointerHandler) diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 35ace7592f..10b656d111 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -765,10 +765,12 @@ QObject *QQuickEventPoint::exclusiveGrabber() const */ void QQuickEventPoint::setExclusiveGrabber(QObject *grabber) { - if (QQuickPointerHandler *phGrabber = qmlobject_cast(grabber)) + if (QQuickPointerHandler *phGrabber = qmlobject_cast(grabber)) { setGrabberPointerHandler(phGrabber, true); - else - setGrabberItem(static_cast(grabber)); + } else if (QQuickPointerHandler *existingPhGrabber = grabberPointerHandler()) { + if (existingPhGrabber->approveGrabTransition(this, grabber)) + setGrabberItem(static_cast(grabber)); + } } /*! -- cgit v1.2.3 From d188cdd7378e0e8b384fa812b5907638075d1206 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 13 Nov 2017 13:56:09 +0100 Subject: Fix crash with dangling context object pointers This is a regression introduced by commit e22b624d9ab1f36021adb9cdbfa9b37054282bb8, where the object that owns the QML context would destroy the context upon destruction. Now the context may live longer and thus the context->contextObject pointer would become a dangling pointer. Task-number: QTBUG-64166 Change-Id: I1df631fa11187abdeff735d8891ad7907e8d4a3d Reviewed-by: Lars Knoll --- src/qml/types/qqmldelegatemodel.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp index 26e6a81418..e3906f2a7e 100644 --- a/src/qml/types/qqmldelegatemodel.cpp +++ b/src/qml/types/qqmldelegatemodel.cpp @@ -1979,6 +1979,8 @@ void QQmlDelegateModelItem::destroyObject() Q_ASSERT(data); if (data->ownContext) { data->ownContext->clearContext(); + if (data->ownContext->contextObject == object) + data->ownContext->contextObject = nullptr; data->ownContext = 0; data->context = 0; } -- cgit v1.2.3 From 5d0785d38adfbc8b6af3f4db5c201b67f5f811e9 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 14 Nov 2017 15:32:20 +0100 Subject: QQuickWindowPrivate::deliverToPassiveGrabbers: localize the event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Always localize the pointer event to the handler's parent's coordinate system before sending it to a handler. Change-Id: I3006329a07cc9439b472a475444bcd4a0336ad0c Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 4bee6dcd9a..e865a609a6 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1694,8 +1694,10 @@ void QQuickWindowPrivate::deliverToPassiveGrabbers(const QVector(par, alreadyFiltered); } - if (!alreadyFiltered) + if (!alreadyFiltered) { + pointerEvent->localize(handler->parentItem()); handler->handlePointerEvent(pointerEvent); + } } } } -- cgit v1.2.3 From 3ae8b478e334fe307ec4b5d6b3ae39eb984fe6b3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 10 Nov 2017 12:53:44 +0100 Subject: a PointerHandler can veto overtaking of grab by an Item MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to make sure of it, we have to do the permission check in the legacy call chain too: QQuickFlickable::filterMouseEvent() -> QQuickItem::grabMouse() -> QQuickWindowPrivate::setMouseGrabber() -> QQuickEventPoint::setGrabberItem() -> QQuickPointerHandler::approveGrabTransition() Change-Id: Ice3499bc56e7c89fb43b054ddcd0098fea94ba2a Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickevents.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickevents.cpp b/src/quick/items/qquickevents.cpp index 10b656d111..4a786d5569 100644 --- a/src/quick/items/qquickevents.cpp +++ b/src/quick/items/qquickevents.cpp @@ -765,12 +765,10 @@ QObject *QQuickEventPoint::exclusiveGrabber() const */ void QQuickEventPoint::setExclusiveGrabber(QObject *grabber) { - if (QQuickPointerHandler *phGrabber = qmlobject_cast(grabber)) { + if (QQuickPointerHandler *phGrabber = qmlobject_cast(grabber)) setGrabberPointerHandler(phGrabber, true); - } else if (QQuickPointerHandler *existingPhGrabber = grabberPointerHandler()) { - if (existingPhGrabber->approveGrabTransition(this, grabber)) - setGrabberItem(static_cast(grabber)); - } + else + setGrabberItem(static_cast(grabber)); } /*! @@ -792,15 +790,17 @@ QQuickItem *QQuickEventPoint::grabberItem() const void QQuickEventPoint::setGrabberItem(QQuickItem *grabber) { if (grabber != m_exclusiveGrabber.data()) { + QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler(); + if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber)) + return; if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) << ": grab" << m_exclusiveGrabber << "->" << grabber; } - QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler(); - QQuickItem *oldGrabberItem = grabberItem(); m_exclusiveGrabber = QPointer(grabber); m_grabberIsHandler = false; m_sceneGrabPos = m_scenePos; + QQuickItem *oldGrabberItem = grabberItem(); if (oldGrabberHandler) oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this); else if (oldGrabberItem && oldGrabberItem != grabber && grabber && pointerEvent()->asPointerTouchEvent()) -- cgit v1.2.3 From b59336e73aca6915d96bbdc673710693d27e1096 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 7 Mar 2017 10:01:23 +0100 Subject: add PointHandler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Iad9ba3f8121ff22136e85413ec610bc1ee361e37 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/handlers.pri | 2 + src/quick/handlers/qquickhandlersmodule.cpp | 2 + src/quick/handlers/qquickpointhandler.cpp | 134 ++++++++++++++++++++++++++++ src/quick/handlers/qquickpointhandler_p.h | 81 +++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 src/quick/handlers/qquickpointhandler.cpp create mode 100644 src/quick/handlers/qquickpointhandler_p.h (limited to 'src') diff --git a/src/quick/handlers/handlers.pri b/src/quick/handlers/handlers.pri index 9e32b9278c..8bd74d95da 100644 --- a/src/quick/handlers/handlers.pri +++ b/src/quick/handlers/handlers.pri @@ -5,6 +5,7 @@ HEADERS += \ $$PWD/qquickpinchhandler_p.h \ $$PWD/qquickpointerdevicehandler_p.h \ $$PWD/qquickpointerhandler_p.h \ + $$PWD/qquickpointhandler_p.h \ $$PWD/qquicksinglepointhandler_p.h \ $$PWD/qquicktaphandler_p.h \ @@ -15,6 +16,7 @@ SOURCES += \ $$PWD/qquickpinchhandler.cpp \ $$PWD/qquickpointerdevicehandler.cpp \ $$PWD/qquickpointerhandler.cpp \ + $$PWD/qquickpointhandler.cpp \ $$PWD/qquicksinglepointhandler.cpp \ $$PWD/qquicktaphandler.cpp \ diff --git a/src/quick/handlers/qquickhandlersmodule.cpp b/src/quick/handlers/qquickhandlersmodule.cpp index 8472c6a062..c9e08fe4f2 100644 --- a/src/quick/handlers/qquickhandlersmodule.cpp +++ b/src/quick/handlers/qquickhandlersmodule.cpp @@ -41,6 +41,7 @@ #include "qquickpointerhandler_p.h" #include "qquickdraghandler_p.h" #include "qquickpinchhandler_p.h" +#include "qquickpointhandler_p.h" #include "qquicktaphandler_p.h" static void initResources() @@ -82,6 +83,7 @@ static void qt_quickhandlers_defineModule(const char *uri, int major, int minor) qmlRegisterUncreatableType(uri,major,minor,"PointerHandler", QQuickPointerHandler::tr("PointerHandler is an abstract base class")); + qmlRegisterType(uri,major,minor,"PointHandler"); qmlRegisterType(uri,major,minor,"DragHandler"); qmlRegisterUncreatableType(uri, major, minor, "DragAxis", QQuickDragHandler::tr("DragAxis is only available as a grouped property of DragHandler")); diff --git a/src/quick/handlers/qquickpointhandler.cpp b/src/quick/handlers/qquickpointhandler.cpp new file mode 100644 index 0000000000..d40837c43e --- /dev/null +++ b/src/quick/handlers/qquickpointhandler.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpointhandler_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype PointHandler + \instantiates QQuickPointHandler + \inqmlmodule QtQuick + \ingroup qtquick-handlers + \brief Handler for reacting to a single touchpoint + + PointHandler can be used to show feedback about a touchpoint or the mouse + position, or to otherwise react to pointer events. By being only a passive + grabber, it has the ability to keep oversight of all movements, and its + grab cannot be stolen even when other gestures are detected and exclusive + grabs occur. + + If your goal is orthogonal surveillance of eventpoints, an older + alternative was QObject::installEventFilter(), but that has never been a + built-in QtQuick feature: it requires a custom C++ QQuickItem subclass. + PointHandler is more efficient than that, because only pointer events will + be delivered to it, during the course of normal event delivery in + QQuickWindow, whereas an event filter needs to filter all events of all + types, and thus sets itself up as a potential event delivery bottleneck. + + One possible use case is to add this handler to a transparent Item which is + on top of the rest of the scene, so that when a point is freshly pressed, + it will be delivered to that Item and its handlers first, providing the + opportunity to take the passive grab as early as possible. Then such an + item (like a pane of glass over the whole UI) also becomes a good parent + for other Items which visualize the kind of reactive feedback which must + always be on top; and likewise it can be the parent for popups, popovers, + dialogs and so on. For example, a declared Window can have an Item with a + high Z value so that it stays on top. It can also be helpful for your + main.cpp to use QQmlContext::setContextProperty() to make the "glass pane" + accessible by ID to the entire UI, so that other Items and PointHandlers + can be reparented to it. + + Inside a PointHandler you can declare a \l target Item, but PointHandler + will not automatically manipulate it in any way. The target Item can bind to + properties of the PointHandler. In this way it can follow a point's movements. + + \sa MultiPointTouchArea +*/ + +QQuickPointHandler::QQuickPointHandler(QObject *parent) + : QQuickSinglePointHandler(parent) +{ + setIgnoreAdditionalPoints(); +} + +QQuickPointHandler::~QQuickPointHandler() +{ +} + +bool QQuickPointHandler::wantsEventPoint(QQuickEventPoint *pt) +{ + // On press, we want it unless a sibling of the same type also does. + if (pt->state() == QQuickEventPoint::Pressed && QQuickSinglePointHandler::wantsEventPoint(pt)) { + for (const QQuickPointerHandler *grabber : pt->passiveGrabbers()) { + if (grabber && grabber->parent() == parent() && + grabber->metaObject()->className() == metaObject()->className()) + return false; + } + return true; + } + // If we've already been interested in a point, stay interested, even if it has strayed outside bounds. + return (pt->state() != QQuickEventPoint::Pressed && point().id() == pt->pointId()); +} + +void QQuickPointHandler::handleEventPoint(QQuickEventPoint *point) +{ + switch (point->state()) { + case QQuickEventPoint::Pressed: + setPassiveGrab(point); + setActive(true); + break; + case QQuickEventPoint::Released: + setActive(false); + break; + default: + break; + } + point->setAccepted(false); // Just lurking... don't interfere with propagation + emit translationChanged(); +} + +QVector2D QQuickPointHandler::translation() const +{ + return QVector2D(point().position() - point().pressPosition()); +} + +QT_END_NAMESPACE diff --git a/src/quick/handlers/qquickpointhandler_p.h b/src/quick/handlers/qquickpointhandler_p.h new file mode 100644 index 0000000000..5babab0c4d --- /dev/null +++ b/src/quick/handlers/qquickpointhandler_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPONTHANDLER_H +#define QQUICKPONTHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquicksinglepointhandler_p.h" + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QQuickPointHandler : public QQuickSinglePointHandler +{ + Q_OBJECT + Q_PROPERTY(QVector2D translation READ translation NOTIFY translationChanged) + +public: + explicit QQuickPointHandler(QObject *parent = 0); + ~QQuickPointHandler(); + + QVector2D translation() const; + +Q_SIGNALS: + void translationChanged(); + +protected: + bool wantsEventPoint(QQuickEventPoint *pt) override; + void handleEventPoint(QQuickEventPoint *point) override; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPointHandler) + +#endif // QQUICKPONTHANDLER_H -- cgit v1.2.3 From 11d53337cffffeaa185b1e7ec816a52e07355c9c Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 15 Nov 2017 16:29:18 +0100 Subject: Fix outdated BSD license header Change-Id: Ib1fe267c23ea9fce9bcc0a91ed61081260338460 Reviewed-by: Liang Qi --- src/quick/doc/snippets/pointerHandlers/dragHandler.qml | 14 ++++++++++++-- .../pointerHandlers/dragHandlerDifferentTarget.qml | 14 ++++++++++++-- .../doc/snippets/pointerHandlers/dragHandlerNullTarget.qml | 14 ++++++++++++-- src/quick/doc/snippets/pointerHandlers/pinchHandler.qml | 14 ++++++++++++-- .../pointerHandlers/pinchHandlerDifferentTarget.qml | 14 ++++++++++++-- .../snippets/pointerHandlers/pinchHandlerNullTarget.qml | 14 ++++++++++++-- src/quick/doc/snippets/qml/path/arcrotation.qml | 14 ++++++++++++-- 7 files changed, 84 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/quick/doc/snippets/pointerHandlers/dragHandler.qml b/src/quick/doc/snippets/pointerHandlers/dragHandler.qml index 349cdcb95f..78a7db5b0c 100644 --- a/src/quick/doc/snippets/pointerHandlers/dragHandler.qml +++ b/src/quick/doc/snippets/pointerHandlers/dragHandler.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/pointerHandlers/dragHandlerDifferentTarget.qml b/src/quick/doc/snippets/pointerHandlers/dragHandlerDifferentTarget.qml index e8f2a04e6a..4c4168de83 100644 --- a/src/quick/doc/snippets/pointerHandlers/dragHandlerDifferentTarget.qml +++ b/src/quick/doc/snippets/pointerHandlers/dragHandlerDifferentTarget.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/pointerHandlers/dragHandlerNullTarget.qml b/src/quick/doc/snippets/pointerHandlers/dragHandlerNullTarget.qml index e210ce0952..09429ec1d2 100644 --- a/src/quick/doc/snippets/pointerHandlers/dragHandlerNullTarget.qml +++ b/src/quick/doc/snippets/pointerHandlers/dragHandlerNullTarget.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/pointerHandlers/pinchHandler.qml b/src/quick/doc/snippets/pointerHandlers/pinchHandler.qml index 841e401da1..955047d115 100644 --- a/src/quick/doc/snippets/pointerHandlers/pinchHandler.qml +++ b/src/quick/doc/snippets/pointerHandlers/pinchHandler.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/pointerHandlers/pinchHandlerDifferentTarget.qml b/src/quick/doc/snippets/pointerHandlers/pinchHandlerDifferentTarget.qml index 211c370da6..a5255a64e3 100644 --- a/src/quick/doc/snippets/pointerHandlers/pinchHandlerDifferentTarget.qml +++ b/src/quick/doc/snippets/pointerHandlers/pinchHandlerDifferentTarget.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml b/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml index b0139d7194..7d21efcb84 100644 --- a/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml +++ b/src/quick/doc/snippets/pointerHandlers/pinchHandlerNullTarget.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2017 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are diff --git a/src/quick/doc/snippets/qml/path/arcrotation.qml b/src/quick/doc/snippets/qml/path/arcrotation.qml index c73d67ff17..985ac51d8a 100644 --- a/src/quick/doc/snippets/qml/path/arcrotation.qml +++ b/src/quick/doc/snippets/qml/path/arcrotation.qml @@ -1,12 +1,22 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: ** ** "Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are -- cgit v1.2.3 From 08778586413adad7b3af35c7cb97416757d599c0 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 16 Nov 2017 17:41:44 +0100 Subject: Fix crash when accessing pixmap on default QSGSoftwareInternalImageNode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-64562 Change-Id: I52e07b0d8b7a5d1cc960431dcbd1a90dd3e7e518 Reviewed-by: Jüri Valdmann Reviewed-by: Laszlo Agocs --- .../adaptations/software/qsgsoftwareinternalimagenode.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp index 10291b9cb5..8843b6450a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp @@ -490,12 +490,13 @@ QRectF QSGSoftwareInternalImageNode::rect() const const QPixmap &QSGSoftwareInternalImageNode::pixmap() const { - if (QSGSoftwarePixmapTexture *pt = qobject_cast(m_texture)) { + if (QSGSoftwarePixmapTexture *pt = qobject_cast(m_texture)) return pt->pixmap(); - } else { - QSGSoftwareLayer *layer = qobject_cast(m_texture); + if (QSGSoftwareLayer *layer = qobject_cast(m_texture)) return layer->pixmap(); - } + Q_ASSERT(m_texture == 0); + static const QPixmap nullPixmap; + return nullPixmap; } QT_END_NAMESPACE -- cgit v1.2.3 From 28893b5ab2ee0984d6caa813ac1bbecf6d9e583c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 16 Nov 2017 11:30:43 +0100 Subject: never skip updating passive grabbers, or ungrab, on mouse release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you drag a ListView with the right mouse button, it was reacting, but not rebounding after release. And if a PointHandler is used to show feedback about mouse position, it also did not get the release. This was due to returning early from deliverMouseEvent. Change-Id: I24b39e4769d6824d3bd1f400dbf1f973bb29fbb6 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickwindow.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index e865a609a6..2dc3caf430 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1712,24 +1712,27 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven if (point->exclusiveGrabber()) { if (auto grabber = point->grabberItem()) { + bool handled = false; if (sendFilteredPointerEvent(pointerEvent, grabber)) - return; + handled = true; // if the grabber is an Item: // if the update consists of changing button state, don't accept it unless // the button is one in which the grabber is interested Qt::MouseButtons acceptedButtons = grabber->acceptedMouseButtons(); - if (pointerEvent->button() != Qt::NoButton && acceptedButtons + if (!handled && pointerEvent->button() != Qt::NoButton && acceptedButtons && !(acceptedButtons & pointerEvent->button())) { pointerEvent->setAccepted(false); - return; + handled = true; } // send update - QPointF localPos = grabber->mapFromScene(lastMousePosition); - auto me = pointerEvent->asMouseEvent(localPos); - me->accept(); - QCoreApplication::sendEvent(grabber, me); - point->setAccepted(me->isAccepted()); + if (!handled) { + QPointF localPos = grabber->mapFromScene(lastMousePosition); + auto me = pointerEvent->asMouseEvent(localPos); + me->accept(); + QCoreApplication::sendEvent(grabber, me); + point->setAccepted(me->isAccepted()); + } // release event: ungrab if no buttons are pressed anymore if (mouseIsReleased) -- cgit v1.2.3 From c8ae30ef723423e78134e0a0373247a0d6df7bae Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 15 Nov 2017 23:31:45 +0100 Subject: PointHandler: fix and improve the docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qml module tag did not make it clear that it's in Qt.labs.handlers, not officially part of QtQuick yet. Some features needed better explanations. A snippet is helpful. Change-Id: Ie6a57510390bb376f20f5c1d98d8fc4c148af71b Reviewed-by: Jan Arve Sæther --- .../doc/snippets/pointerHandlers/pointHandler.qml | 79 ++++++++++++++++++++++ src/quick/handlers/qquickpointhandler.cpp | 77 ++++++++++++++------- 2 files changed, 131 insertions(+), 25 deletions(-) create mode 100644 src/quick/doc/snippets/pointerHandlers/pointHandler.qml (limited to 'src') diff --git a/src/quick/doc/snippets/pointerHandlers/pointHandler.qml b/src/quick/doc/snippets/pointerHandlers/pointHandler.qml new file mode 100644 index 0000000000..262eb607b6 --- /dev/null +++ b/src/quick/doc/snippets/pointerHandlers/pointHandler.qml @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +import QtQuick 2.10 +import QtQuick.Window 2.2 +import Qt.labs.handlers 1.0 + +Window { + width: 480 + height: 320 + visible: true + + Item { + id: glassPane + z: 10000 + anchors.fill: parent + + PointHandler { + id: handler + acceptedDevices: PointerDevice.TouchScreen | PointerDevice.TouchPad + target: Rectangle { + parent: glassPane + color: "red" + visible: handler.active + x: handler.point.position.x - width / 2 + y: handler.point.position.y - height / 2 + width: 20; height: width; radius: width / 2 + } + } + } +} +//![0] diff --git a/src/quick/handlers/qquickpointhandler.cpp b/src/quick/handlers/qquickpointhandler.cpp index d40837c43e..ed03685252 100644 --- a/src/quick/handlers/qquickpointhandler.cpp +++ b/src/quick/handlers/qquickpointhandler.cpp @@ -46,40 +46,67 @@ QT_BEGIN_NAMESPACE /*! \qmltype PointHandler \instantiates QQuickPointHandler - \inqmlmodule QtQuick + \inherits SinglePointHandler + \inqmlmodule Qt.labs.handlers \ingroup qtquick-handlers - \brief Handler for reacting to a single touchpoint + \brief Handler for reacting to a single touchpoint. PointHandler can be used to show feedback about a touchpoint or the mouse - position, or to otherwise react to pointer events. By being only a passive - grabber, it has the ability to keep oversight of all movements, and its - grab cannot be stolen even when other gestures are detected and exclusive - grabs occur. + position, or to otherwise react to pointer events. + + When a press event occurs, each instance of PointHandler chooses a single + point which is not yet "taken" at that moment: if the press occurs within + the bounds of the \l parent, and no sibling PointHandler within the same + \l parent has yet acquired a passive grab on that point, and if the other + constraints such as \l acceptedMouseButtons, \l acceptedDevices etc. are + satisfied, it's eligible, and the PointHandler then acquires a passive + grab. In this way, the \l parent acts like an exclusive group: there can be + multiple instances of PointHandler, and the set of pressed touchpoints will + be distributed among them. Each PointHandler which has chosen a point to + track has its \l active property \c true. It then continues to track its + chosen point until release: the properties of the \l point will be kept + up-to-date. Any Item can bind to these properties, and thereby follow the + point's movements. + + By being only a passive grabber, it has the ability to keep independent + oversight of all movements. The passive grab cannot be stolen or overridden + even when other gestures are detected and exclusive grabs occur. If your goal is orthogonal surveillance of eventpoints, an older alternative was QObject::installEventFilter(), but that has never been a - built-in QtQuick feature: it requires a custom C++ QQuickItem subclass. - PointHandler is more efficient than that, because only pointer events will - be delivered to it, during the course of normal event delivery in - QQuickWindow, whereas an event filter needs to filter all events of all + built-in QtQuick feature: it requires some C++ code, such as a QQuickItem + subclass. PointHandler is more efficient than that, because only pointer + events will be delivered to it, during the course of normal event delivery + in QQuickWindow; whereas an event filter needs to filter all QEvents of all types, and thus sets itself up as a potential event delivery bottleneck. One possible use case is to add this handler to a transparent Item which is - on top of the rest of the scene, so that when a point is freshly pressed, - it will be delivered to that Item and its handlers first, providing the - opportunity to take the passive grab as early as possible. Then such an - item (like a pane of glass over the whole UI) also becomes a good parent - for other Items which visualize the kind of reactive feedback which must - always be on top; and likewise it can be the parent for popups, popovers, - dialogs and so on. For example, a declared Window can have an Item with a - high Z value so that it stays on top. It can also be helpful for your - main.cpp to use QQmlContext::setContextProperty() to make the "glass pane" - accessible by ID to the entire UI, so that other Items and PointHandlers - can be reparented to it. - - Inside a PointHandler you can declare a \l target Item, but PointHandler - will not automatically manipulate it in any way. The target Item can bind to - properties of the PointHandler. In this way it can follow a point's movements. + on top of the rest of the scene (by having a high \l z value), so that when + a point is freshly pressed, it will be delivered to that Item and its + handlers first, providing the opportunity to take the passive grab as early + as possible. Such an item (like a pane of glass over the whole UI) can be a + convenient parent for other Items which visualize the kind of reactive + feedback which must always be on top; and likewise it can be the parent for + popups, popovers, dialogs and so on. If it will be used in that way, it can + be helpful for your main.cpp to use QQmlContext::setContextProperty() to + make the "glass pane" accessible by ID to the entire UI, so that other + Items and PointHandlers can be reparented to it. + + \snippet pointerHandlers/pointHandler.qml 0 + + Like all pointer handlers, a PointHandler has a \l target property, which + may be used as a convenient place to put a point-tracking Item; but + PointHandler will not automatically manipulate the \c target item in any way. + You need to use bindings to make it react to the \l point. + + \note On macOS, PointHandler does not react to the trackpad by default. + That is because macOS can provide either native gesture recognition, or raw + touchpoints, but not both. We prefer to use the native gesture event in + PinchHandler, so we do not want to disable it by enabling touch. However + MultiPointTouchArea does enable touch, thus disabling native gesture + recognition within the entire window; so it's an alternative if you only + want to react to all the touchpoints but do not require the smooth + native-gesture experience. \sa MultiPointTouchArea */ -- cgit v1.2.3 From 2f91b0f25fff560de27632ec9d947c890426664e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 22 Nov 2017 14:13:53 +0100 Subject: prepend PointerHandler children of Items so the last is visited first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps with overriding behavior: when a QML control implementation has handlers encapsulated inside, but the user tries to override behavior by declaring more handler instances in instances of the control, the user's handlers must be visited before the encapsulated handlers. Likewise, this reverse-ordering corresponds to intuition after having used MouseHandlers: the one which is declared last inside an Item will have a higher effective Z order, and thus will be visited first during event delivery. Task-number: QTBUG-64692 Change-Id: I9bf18218a1887d0297c71ebf81dde0956394b72a Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ccc4e90abf..54fcbfbbf2 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3253,7 +3253,7 @@ void QQuickItemPrivate::data_append(QQmlListProperty *prop, QObject *o) // because there can be multiple handlers... that->setAcceptedMouseButtons(Qt::AllButtons); QQuickItemPrivate *p = QQuickItemPrivate::get(that); - p->extra.value().pointerHandlers.append(pointerHandler); + p->extra.value().pointerHandlers.prepend(pointerHandler); } else { QQuickWindow *thisWindow = qmlobject_cast(o); QQuickItem *item = that; -- cgit v1.2.3 From 6eabb3edf27e3b73205fa70e4497ce7ec1201adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Thu, 23 Nov 2017 10:56:06 +0100 Subject: Fix a bug with calculation of translation in DragHandler The problem was that the start position of the target item (m_targetStartPos) was not always updated. In combination with several handlers (this bug was observed with PinchHandler and DragHandler as siblings) it is quite likely that the DragHandler will get a press, but not activate (because the PinchHandler might activate instead). It would therefore not deactivate (so it would not reset m_targetStartPos), and as a consequence the m_targetStartPos was not updated to its correct value the next time we initiated a drag because m_targetStartPos wasn't null. Change-Id: Icf3089fc685cfbcbcfba638966a2e8ad1c8c089f Reviewed-by: Shawn Rutledge --- src/quick/handlers/qquickdraghandler.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/quick/handlers/qquickdraghandler.cpp b/src/quick/handlers/qquickdraghandler.cpp index 12f1a29bca..d4a8f06db8 100644 --- a/src/quick/handlers/qquickdraghandler.cpp +++ b/src/quick/handlers/qquickdraghandler.cpp @@ -93,8 +93,9 @@ bool QQuickDragHandler::wantsEventPoint(QQuickEventPoint *point) void QQuickDragHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabState stateChange, QQuickEventPoint *point) { - if (grabber == this && stateChange == QQuickEventPoint::GrabExclusive) - // In case the grab got handled over from another grabber, we might not get the Press + if (grabber == this && stateChange == QQuickEventPoint::GrabExclusive && m_targetStartPos.isNull()) + // In case the grab got handled over from another grabber, we might not get the Press. + // Therefore, prefer the m_targetStartPos we got when it got Pressed. initializeTargetStartPos(point); enforceConstraints(); QQuickSinglePointHandler::onGrabChanged(grabber, stateChange, point); @@ -167,7 +168,7 @@ void QQuickDragHandler::enforceAxisConstraints(QPointF *localPos) void QQuickDragHandler::initializeTargetStartPos(QQuickEventPoint *point) { - if (target() && target()->parentItem() && m_targetStartPos.isNull()) { // prefer the m_targetStartPos we got when it got Pressed. + if (target() && target()->parentItem()) { m_targetStartPos = target()->parentItem()->mapToScene(target()->position()); if (!target()->contains(point->position())) { // If pressed outside of target item, move the target item so that the touchpoint is in its center, -- cgit v1.2.3 From cc46992fbb94f1775ac22aa23b42d76f810a5913 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Tue, 21 Nov 2017 12:18:56 -0600 Subject: Fix issue with circular singleton instantiations While a recursion check exists and works, it can lead to instanting the same singleton multiple times (leaking all but one copy). Change-Id: Icf342aad71c5cb225488262341517d95786e1f84 Reviewed-by: Erik Verbruggen Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlmetatype.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index 8e6be538ef..0f388cf7b7 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -274,8 +274,10 @@ void QQmlType::SingletonInstanceInfo::init(QQmlEngine *e) QQmlData::ensurePropertyCache(e, o); } else if (!url.isEmpty() && !qobjectApi(e)) { QQmlComponent component(e, url, QQmlComponent::PreferSynchronous); - QObject *o = component.create(); + QObject *o = component.beginCreate(e->rootContext()); setQObjectApi(e, o); + if (o) + component.completeCreate(); } v4->popContext(); } -- cgit v1.2.3 From dac71f3d6f6bc4f159f6107c792bc70cfe7c308e Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 30 Nov 2017 13:49:46 +0100 Subject: Fix QQmlImportsPrivate::resolvedUri() Qt Quick Controls 2 styles have a version in the middle of the path/URI (e.g. qml/QtQuick/Controls.2/Material). The resolvedUri() helper method, which is used by addFileImport() for implicit imports, was never taught to deal with this type of versioning. It was only attempting to remove the version from the end. Change-Id: Ibdf23dc6c3b0794527d5f9330602858291c23e01 Task-number: QTBUG-64868 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll --- src/qml/qml/qqmlimport.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 334bc8b28e..a7cafa1a93 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -1231,10 +1231,12 @@ QString QQmlImportsPrivate::resolvedUri(const QString &dir_arg, QQmlImportDataba stableRelativePath.replace(Backslash, Slash); // remove optional versioning in dot notation from uri - int lastSlash = stableRelativePath.lastIndexOf(Slash); - if (lastSlash >= 0) { - int versionDot = stableRelativePath.indexOf(Dot, lastSlash); - if (versionDot >= 0) + int versionDot = stableRelativePath.lastIndexOf(Dot); + if (versionDot >= 0) { + int nextSlash = stableRelativePath.indexOf(Slash, versionDot); + if (nextSlash >= 0) + stableRelativePath.remove(versionDot, nextSlash - versionDot); + else stableRelativePath = stableRelativePath.left(versionDot); } -- cgit v1.2.3 From f98e83d66c4315e58f777150e129e25fdaa4312f Mon Sep 17 00:00:00 2001 From: Jan Arve Saether Date: Mon, 20 Nov 2017 11:42:39 +0100 Subject: Document when anchors.fill can and can not be used It seems to be a common mistake to manipulate the geometry of child items. Be more explicit about it in the documentation. Task-number: QTBUG-63303 Change-Id: I80fd4f1d194c9b001b76e0fb88877c7c0cf488da Reviewed-by: Venugopal Shivashankar --- src/quick/doc/snippets/qml/layout-simple.qml | 74 ++++++++++++++++++++++ .../concepts/layouts/qtquicklayouts-overview.qdoc | 25 +++++++- 2 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 src/quick/doc/snippets/qml/layout-simple.qml (limited to 'src') diff --git a/src/quick/doc/snippets/qml/layout-simple.qml b/src/quick/doc/snippets/qml/layout-simple.qml new file mode 100644 index 0000000000..6afdbe3ec9 --- /dev/null +++ b/src/quick/doc/snippets/qml/layout-simple.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import QtQuick.Layouts 1.2 +import QtQuick.Window 2.2 + +//! [1] +Window { + RowLayout { + anchors.fill: parent + //! [spacing] + spacing: 6 + //! [spacing] + Rectangle { + color: 'azure' + Layout.preferredWidth: 100 + Layout.preferredHeight: 150 + } + Rectangle { + color: "plum" + Layout.fillWidth: true + Layout.fillHeight: true + } + } +} +//! [1] diff --git a/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc b/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc index 05e4465f2a..06ebe2d3d1 100644 --- a/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc +++ b/src/quick/doc/src/concepts/layouts/qtquicklayouts-overview.qdoc @@ -74,8 +74,31 @@ \endlist + \section1 A Simple Layout + + \snippet qml/layout-simple.qml 1 + + As the intention of using a layout is to rearrange its children whenever the layout changes + size, the application should make sure that the layout gets resized. In the above snippet the + RowLayout ensures that by specifying \c{anchors.fill: parent}. However, it can also be by other + means, such as directly specifying \l{Item::width}{width} and \l{Item::height}{height} + properties. In the same snippet, the \c azure Rectangle has a fixed size of \c{(100, 150)} + pixels, and the \c plum Rectangle will expand to occupy all the space it gets allocated. + + \note A layout is responsible for its children's geometry. You should + therefore not specify \l{Item::width}{width}, \l{Item::height}{height}, \l{Item::x}{x}, + \l{Item::y}{y} or any other properties that might influence those properties (such as + \l{Item::anchors}{anchors}) on those items. Otherwise there would be a conflict of interest, + and the result is undefined. This is also the case if the child item is a layout. Therefore, + only layouts with no parent layout can have \c{anchors.fill: parent}. + + All items in the layout will have 6 pixels of spacing between them: + + \snippet qml/layout-simple.qml spacing + + + \section2 Size Constraints - \section1 Size Constraints Since an item can be resized by its layout, the layout needs to know the \l{Layout::minimumWidth}{minimum}, \l{Layout::preferredWidth}{preferred}, and \l{Layout::maximumWidth}{maximum} sizes of all items where \l{Layout::fillWidth}{Layout.fillWidth} or -- cgit v1.2.3 From 92b17fd766205c18f692be4f58a31d76d57758ae Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 6 Dec 2017 13:31:40 +0100 Subject: TapHandler: emit canceled when a gesturePolicy constrait is violated MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If gesturePolicy is DragThreshold and the threshold is exceeded or if gesturePolicy is withinBounds and you drag outside the bounds, that means any pending tap gesture is canceled, so the canceled signal should be emitted. It should not depend on a grab or an event to be canceled. QQuickTapHandler::setPressed(press, cancel, point) should take care of it when cancel is true. Task-number: QTBUG-65003 Change-Id: I2018695f5fc4438e68df3b34cf258251dbd5f198 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquicktaphandler.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/quick/handlers/qquicktaphandler.cpp b/src/quick/handlers/qquicktaphandler.cpp index e5b728db0f..8313b415bf 100644 --- a/src/quick/handlers/qquicktaphandler.cpp +++ b/src/quick/handlers/qquicktaphandler.cpp @@ -301,6 +301,8 @@ void QQuickTapHandler::setPressed(bool press, bool cancel, QQuickEventPoint *poi // on release, ungrab after emitting changed signals setExclusiveGrab(point, press); } + if (cancel) + emit canceled(point); } } -- cgit v1.2.3 From 52f7ab28172cea3710a16775b7a512fce821fc77 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 13 Nov 2017 14:43:54 +0100 Subject: fix bugs in native gesture event delivery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1) always use Item-localized coordinates when testing Item.contains() 2) QQuickPinchHandler::wantsPointerEvent() was returning true for all native gestures, so in the manual test with two PinchHandlers, it was possible to pinch them both at the same time. Task-number: QTBUG-64848 Change-Id: Ia146aaf03f9982696ae2986249f8d4650a7bf727 Reviewed-by: Jan Arve Sæther --- src/quick/handlers/qquickpinchhandler.cpp | 6 ++++-- src/quick/items/qquickwindow.cpp | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/quick/handlers/qquickpinchhandler.cpp b/src/quick/handlers/qquickpinchhandler.cpp index 4db96d8a99..155822197f 100644 --- a/src/quick/handlers/qquickpinchhandler.cpp +++ b/src/quick/handlers/qquickpinchhandler.cpp @@ -248,8 +248,8 @@ bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event) if (!QQuickMultiPointHandler::wantsPointerEvent(event)) return false; - if (minimumPointCount() == 2) { - if (const auto gesture = event->asPointerNativeGestureEvent()) { + if (const auto gesture = event->asPointerNativeGestureEvent()) { + if (minimumPointCount() == 2) { switch (gesture->type()) { case Qt::BeginNativeGesture: case Qt::EndNativeGesture: @@ -259,6 +259,8 @@ bool QQuickPinchHandler::wantsPointerEvent(QQuickPointerEvent *event) default: return false; } + } else { + return false; } } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 2dc3caf430..530d165850 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1938,7 +1938,8 @@ bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGes { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(event->localPos())) + QPointF p = item->mapFromScene(event->windowPos()); + if ((itemPrivate->flags & QQuickItem::ItemClipsChildrenToShape) && !item->contains(p)) return false; QList children = itemPrivate->paintOrderChildItems(); @@ -1961,7 +1962,6 @@ bool QQuickWindowPrivate::deliverNativeGestureEvent(QQuickItem *item, QNativeGes } // If still not accepted, try direct delivery to the item - QPointF p = item->mapFromScene(event->localPos()); if (item->contains(p)) { QNativeGestureEvent copy(event->gestureType(), event->device(), p, event->windowPos(), event->screenPos(), event->value(), 0L, 0L); // TODO can't copy things I can't access -- cgit v1.2.3 From 7b0a9e6a01b49f911ab7e98873731050380e9242 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 4 Dec 2017 15:06:08 +0100 Subject: Add optional timing logs for Shape triangulation Follow the scenegraph's approach with qt.scenegraph.time.* categories and add qt.shape.time.sync. When enabled, this will print a line for each sync() that had something to process. For asynchronous items this includes all the time from requesting the backend to start the work right up to the finished callback, and thus can be somewhat misleading. Task-number: QTBUG-64951 Change-Id: Ib51a9d4adba4cdc7d692eb7ff14627a5d0e548cf Reviewed-by: Paolo Angelelli Reviewed-by: Andy Nichols --- src/imports/shapes/qquickshape.cpp | 27 ++++++++++++++++++++++++--- src/imports/shapes/qquickshape_p_p.h | 7 +++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/imports/shapes/qquickshape.cpp b/src/imports/shapes/qquickshape.cpp index 6a76743242..c749357cc5 100644 --- a/src/imports/shapes/qquickshape.cpp +++ b/src/imports/shapes/qquickshape.cpp @@ -46,9 +46,12 @@ #include #include #include +#include QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(QQSHAPE_LOG_TIME_DIRTY_SYNC, "qt.shape.time.sync") + /*! \qmlmodule QtQuick.Shapes 1.0 \title Qt Quick Shapes QML Types @@ -968,18 +971,26 @@ QSGNode *QQuickShapePrivate::createNode() return node; } -static void q_asyncShapeReady(void *data) +void QQuickShapePrivate::asyncShapeReady(void *data) { QQuickShapePrivate *self = static_cast(data); self->setStatus(QQuickShape::Ready); + if (self->syncTimingActive) + qDebug("[Shape %p] [%d] [dirty=0x%x] async update took %lld ms", + self->q_func(), self->syncTimeCounter, self->syncTimingTotalDirty, self->syncTimer.elapsed()); } void QQuickShapePrivate::sync() { + syncTimingTotalDirty = 0; + syncTimingActive = QQSHAPE_LOG_TIME_DIRTY_SYNC().isDebugEnabled(); + if (syncTimingActive) + syncTimer.start(); + const bool useAsync = async && renderer->flags().testFlag(QQuickAbstractPathRenderer::SupportsAsync); if (useAsync) { setStatus(QQuickShape::Processing); - renderer->setAsyncCallback(q_asyncShapeReady, this); + renderer->setAsyncCallback(asyncShapeReady, this); } const int count = sp.count(); @@ -988,6 +999,7 @@ void QQuickShapePrivate::sync() for (int i = 0; i < count; ++i) { QQuickShapePath *p = sp[i]; int &dirty(QQuickShapePathPrivate::get(p)->dirty); + syncTimingTotalDirty |= dirty; if (dirty & QQuickShapePathPrivate::DirtyPath) renderer->setPath(i, p); @@ -1011,10 +1023,19 @@ void QQuickShapePrivate::sync() dirty = 0; } + if (syncTimingTotalDirty) + ++syncTimeCounter; + else + syncTimingActive = false; + renderer->endSync(useAsync); - if (!useAsync) + if (!useAsync) { setStatus(QQuickShape::Ready); + if (syncTimingActive) + qDebug("[Shape %p] [%d] [dirty=0x%x] update took %lld ms", + q_func(), syncTimeCounter, syncTimingTotalDirty, syncTimer.elapsed()); + } } // ***** gradient support ***** diff --git a/src/imports/shapes/qquickshape_p_p.h b/src/imports/shapes/qquickshape_p_p.h index bbe9a81d4a..f43831516a 100644 --- a/src/imports/shapes/qquickshape_p_p.h +++ b/src/imports/shapes/qquickshape_p_p.h @@ -56,6 +56,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -167,6 +168,8 @@ public: static QQuickShapePrivate *get(QQuickShape *item) { return item->d_func(); } + static void asyncShapeReady(void *data); + bool spChanged; QQuickShape::RendererType rendererType; bool async; @@ -174,6 +177,10 @@ public: QQuickAbstractPathRenderer *renderer; QVector sp; bool enableVendorExts; + bool syncTimingActive = false; + int syncTimingTotalDirty; + int syncTimeCounter = 0; + QElapsedTimer syncTimer; }; #if QT_CONFIG(opengl) -- cgit v1.2.3 From 50692eb148f9fca8befa14adc0b942a782a1d767 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 14 Dec 2017 11:15:12 +0100 Subject: Rename Shapes plugin's qrc to something more unique shapes.qrc conflicted with the shapes example's shapes.qrc. The Q_INIT_RESOURCE was probably calling the example's initResource, leading to not finding the plugin's files in the resource system at runtime in static builds. Task-number: QTBUG-65173 Change-Id: Ic9187c818119b1984c3748bb032d98b3716733a9 Reviewed-by: Shawn Rutledge --- src/imports/shapes/plugin.cpp | 2 +- src/imports/shapes/qtquickshapesplugin.qrc | 20 ++++++++++++++++++++ src/imports/shapes/shapes.pro | 2 +- src/imports/shapes/shapes.qrc | 20 -------------------- 4 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 src/imports/shapes/qtquickshapesplugin.qrc delete mode 100644 src/imports/shapes/shapes.qrc (limited to 'src') diff --git a/src/imports/shapes/plugin.cpp b/src/imports/shapes/plugin.cpp index 239ef78e55..545cfda0e4 100644 --- a/src/imports/shapes/plugin.cpp +++ b/src/imports/shapes/plugin.cpp @@ -47,7 +47,7 @@ static void initResources() #ifdef QT_STATIC Q_INIT_RESOURCE(qmake_QtQuick_Shapes); #endif - Q_INIT_RESOURCE(shapes); + Q_INIT_RESOURCE(qtquickshapesplugin); } QT_BEGIN_NAMESPACE diff --git a/src/imports/shapes/qtquickshapesplugin.qrc b/src/imports/shapes/qtquickshapesplugin.qrc new file mode 100644 index 0000000000..f139861693 --- /dev/null +++ b/src/imports/shapes/qtquickshapesplugin.qrc @@ -0,0 +1,20 @@ + + + shaders/blit.vert + shaders/blit.frag + shaders/blit_core.frag + shaders/blit_core.vert + shaders/lineargradient.vert + shaders/lineargradient.frag + shaders/lineargradient_core.vert + shaders/lineargradient_core.frag + shaders/radialgradient.vert + shaders/radialgradient.frag + shaders/radialgradient_core.vert + shaders/radialgradient_core.frag + shaders/conicalgradient.vert + shaders/conicalgradient.frag + shaders/conicalgradient_core.vert + shaders/conicalgradient_core.frag + + diff --git a/src/imports/shapes/shapes.pro b/src/imports/shapes/shapes.pro index 4406474c3f..99bad8ba6e 100644 --- a/src/imports/shapes/shapes.pro +++ b/src/imports/shapes/shapes.pro @@ -28,6 +28,6 @@ qtConfig(opengl) { qquickshapenvprrenderer.cpp } -RESOURCES += shapes.qrc +RESOURCES += qtquickshapesplugin.qrc load(qml_plugin) diff --git a/src/imports/shapes/shapes.qrc b/src/imports/shapes/shapes.qrc deleted file mode 100644 index f139861693..0000000000 --- a/src/imports/shapes/shapes.qrc +++ /dev/null @@ -1,20 +0,0 @@ - - - shaders/blit.vert - shaders/blit.frag - shaders/blit_core.frag - shaders/blit_core.vert - shaders/lineargradient.vert - shaders/lineargradient.frag - shaders/lineargradient_core.vert - shaders/lineargradient_core.frag - shaders/radialgradient.vert - shaders/radialgradient.frag - shaders/radialgradient_core.vert - shaders/radialgradient_core.frag - shaders/conicalgradient.vert - shaders/conicalgradient.frag - shaders/conicalgradient_core.vert - shaders/conicalgradient_core.frag - - -- cgit v1.2.3 From 61fd2b3d2a8b838e55d6560050ddf5ba7de3cee5 Mon Sep 17 00:00:00 2001 From: Marco Benelli Date: Thu, 14 Dec 2017 09:47:28 +0100 Subject: QmlJs: update plugins.qmltypes Change-Id: I3df1210088f877d4fe1d7953982e0fd2fa6ad3db Reviewed-by: Erik Verbruggen --- src/imports/builtins/builtins.qmltypes | 5 ++++- src/imports/qtquick2/plugins.qmltypes | 13 +++++++++++-- src/imports/shapes/plugins.qmltypes | 24 ++++++++++++++++++++++++ src/imports/testlib/plugins.qmltypes | 12 +++++++++--- src/imports/window/plugins.qmltypes | 33 ++++++++++++++++++++++++++++++--- 5 files changed, 78 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/imports/builtins/builtins.qmltypes b/src/imports/builtins/builtins.qmltypes index c2f8f5b521..5fb68d15d9 100644 --- a/src/imports/builtins/builtins.qmltypes +++ b/src/imports/builtins/builtins.qmltypes @@ -461,7 +461,10 @@ Module { "AA_CompressHighFrequencyEvents": 25, "AA_DontCheckOpenGLContextThreadAffinity": 26, "AA_DisableShaderDiskCache": 27, - "AA_AttributeCount": 28 + "AA_DontShowShortcutsInContextMenus": 28, + "AA_CompressTabletEvents": 29, + "AA_DisableWindowContextHelpButton": 30, + "AA_AttributeCount": 31 } } Enum { diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes index d23d6cc311..0fce98a212 100644 --- a/src/imports/qtquick2/plugins.qmltypes +++ b/src/imports/qtquick2/plugins.qmltypes @@ -1808,6 +1808,7 @@ Module { Property { name: "wordSpacing"; type: "double" } Property { name: "hintingPreference"; type: "HintingPreference" } Property { name: "kerning"; type: "bool" } + Property { name: "preferShaping"; type: "bool" } Method { name: "toString"; type: "string" } } Component { @@ -3994,12 +3995,13 @@ Module { prototype: "QQuickImplicitSizeItem" exports: [ "QtQuick/Text 2.0", + "QtQuick/Text 2.10", "QtQuick/Text 2.2", "QtQuick/Text 2.3", "QtQuick/Text 2.6", "QtQuick/Text 2.9" ] - exportMetaObjectRevisions: [0, 2, 3, 6, 9] + exportMetaObjectRevisions: [0, 10, 2, 3, 6, 9] Enum { name: "HAlignment" values: { @@ -4185,12 +4187,13 @@ Module { exports: [ "QtQuick/TextEdit 2.0", "QtQuick/TextEdit 2.1", + "QtQuick/TextEdit 2.10", "QtQuick/TextEdit 2.2", "QtQuick/TextEdit 2.3", "QtQuick/TextEdit 2.6", "QtQuick/TextEdit 2.7" ] - exportMetaObjectRevisions: [0, 1, 2, 3, 6, 7] + exportMetaObjectRevisions: [0, 1, 10, 2, 3, 6, 7] Enum { name: "HAlignment" values: { @@ -4292,6 +4295,7 @@ Module { Property { name: "rightPadding"; revision: 6; type: "double" } Property { name: "bottomPadding"; revision: 6; type: "double" } Property { name: "preeditText"; revision: 7; type: "string"; isReadonly: true } + Property { name: "tabStopDistance"; revision: 10; type: "double" } Signal { name: "preeditTextChanged"; revision: 7 } Signal { name: "contentSizeChanged" } Signal { @@ -4374,6 +4378,11 @@ Module { Signal { name: "leftPaddingChanged"; revision: 6 } Signal { name: "rightPaddingChanged"; revision: 6 } Signal { name: "bottomPaddingChanged"; revision: 6 } + Signal { + name: "tabStopDistanceChanged" + revision: 10 + Parameter { name: "distance"; type: "double" } + } Method { name: "selectAll" } Method { name: "selectWord" } Method { diff --git a/src/imports/shapes/plugins.qmltypes b/src/imports/shapes/plugins.qmltypes index b8a7c532e0..39aab42401 100644 --- a/src/imports/shapes/plugins.qmltypes +++ b/src/imports/shapes/plugins.qmltypes @@ -36,6 +36,17 @@ Module { Property { name: "vendorExtensionsEnabled"; type: "bool" } Property { name: "status"; type: "Status"; isReadonly: true } Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } + Signal { name: "rendererChanged" } + } + Component { + name: "QQuickShapeConicalGradient" + defaultProperty: "stops" + prototype: "QQuickShapeGradient" + exports: ["QtQuick.Shapes/ConicalGradient 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "centerX"; type: "double" } + Property { name: "centerY"; type: "double" } + Property { name: "angle"; type: "double" } } Component { name: "QQuickShapeGradient" @@ -114,4 +125,17 @@ Module { Property { name: "fillGradient"; type: "QQuickShapeGradient"; isPointer: true } Signal { name: "shapePathChanged" } } + Component { + name: "QQuickShapeRadialGradient" + defaultProperty: "stops" + prototype: "QQuickShapeGradient" + exports: ["QtQuick.Shapes/RadialGradient 1.0"] + exportMetaObjectRevisions: [0] + Property { name: "centerX"; type: "double" } + Property { name: "centerY"; type: "double" } + Property { name: "centerRadius"; type: "double" } + Property { name: "focalX"; type: "double" } + Property { name: "focalY"; type: "double" } + Property { name: "focalRadius"; type: "double" } + } } diff --git a/src/imports/testlib/plugins.qmltypes b/src/imports/testlib/plugins.qmltypes index 5d7ca51adc..7f3140d86b 100644 --- a/src/imports/testlib/plugins.qmltypes +++ b/src/imports/testlib/plugins.qmltypes @@ -7,7 +7,7 @@ import QtQuick.tooling 1.2 // 'qmlplugindump -nonrelocatable -noforceqtquick QtTest 1.2' Module { - dependencies: ["QtQuick 2.0"] + dependencies: ["QtQuick 2.0", "QtQuick.Window 2.0"] Component { name: "QQuickTouchEventSequence" prototype: "QObject" @@ -45,8 +45,8 @@ Module { Component { name: "QuickTestEvent" prototype: "QObject" - exports: ["QtTest/TestEvent 1.0"] - exportMetaObjectRevisions: [0] + exports: ["QtTest/TestEvent 1.0", "QtTest/TestEvent 1.2"] + exportMetaObjectRevisions: [0, 0] Property { name: "defaultMouseDelay"; type: "int"; isReadonly: true } Method { name: "keyPress" @@ -90,6 +90,12 @@ Module { Parameter { name: "modifiers"; type: "int" } Parameter { name: "delay"; type: "int" } } + Method { + name: "keySequence" + revision: 2 + type: "bool" + Parameter { name: "keySequence"; type: "QVariant" } + } Method { name: "mousePress" type: "bool" diff --git a/src/imports/window/plugins.qmltypes b/src/imports/window/plugins.qmltypes index cea2a910a7..4ae23a093e 100644 --- a/src/imports/window/plugins.qmltypes +++ b/src/imports/window/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtQuick.Window 2.3' +// 'qmlplugindump -nonrelocatable QtQuick.Window 2.10' Module { dependencies: ["QtQuick 2.8"] @@ -43,10 +43,16 @@ Module { Component { name: "QQuickScreenInfo" prototype: "QObject" - exports: ["QtQuick.Window/ScreenInfo 2.3"] + exports: [ + "QtQuick.Window/ScreenInfo 2.10", + "QtQuick.Window/ScreenInfo 2.3" + ] isCreatable: false - exportMetaObjectRevisions: [2] + exportMetaObjectRevisions: [10, 2] Property { name: "name"; type: "string"; isReadonly: true } + Property { name: "manufacturer"; revision: 10; type: "string"; isReadonly: true } + Property { name: "model"; revision: 10; type: "string"; isReadonly: true } + Property { name: "serialNumber"; revision: 10; type: "string"; isReadonly: true } Property { name: "width"; type: "int"; isReadonly: true } Property { name: "height"; type: "int"; isReadonly: true } Property { name: "desktopAvailableWidth"; type: "int"; isReadonly: true } @@ -58,6 +64,9 @@ Module { Property { name: "orientation"; type: "Qt::ScreenOrientation"; isReadonly: true } Property { name: "virtualX"; revision: 1; type: "int"; isReadonly: true } Property { name: "virtualY"; revision: 1; type: "int"; isReadonly: true } + Signal { name: "manufacturerChanged"; revision: 10 } + Signal { name: "modelChanged"; revision: 10 } + Signal { name: "serialNumberChanged"; revision: 10 } Signal { name: "desktopGeometryChanged" } Signal { name: "virtualXChanged"; revision: 1 } Signal { name: "virtualYChanged"; revision: 1 } @@ -74,6 +83,13 @@ Module { "ContextNotAvailable": 1 } } + Enum { + name: "TextRenderType" + values: { + "QtTextRendering": 0, + "NativeTextRendering": 1 + } + } Property { name: "data"; type: "QObject"; isList: true; isReadonly: true } Property { name: "color"; type: "QColor" } Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true } @@ -295,6 +311,17 @@ Module { name: "setHeight" Parameter { name: "arg"; type: "int" } } + Method { + name: "setGeometry" + Parameter { name: "posx"; type: "int" } + Parameter { name: "posy"; type: "int" } + Parameter { name: "w"; type: "int" } + Parameter { name: "h"; type: "int" } + } + Method { + name: "setGeometry" + Parameter { name: "rect"; type: "QRect" } + } Method { name: "setMinimumWidth" Parameter { name: "w"; type: "int" } -- cgit v1.2.3 From 4fff2bb14e55484eacec0a1b49a2b02958f75eca Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 15 Dec 2017 13:53:55 +0100 Subject: Fix QQml_setParent_noEvent not to print undefined behavior errors When building Qt with -fsanitize undefined, the usage of QQml_setParent_noEvent caused the following error message: "qqmlglobal_p.h:233:5: runtime error: downcast of address 0x60300061bf10 which does not point to an object of type 'QQmlGraphics_DerivedObject'". Instead of casting to the referred type, use QObjectPrivate::get to access the d_ptr. Change-Id: I2f2224bdb20a8d2e35a3291961378231f03c4ba2 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlglobal_p.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h index a6c113f5a7..5c46da0ea4 100644 --- a/src/qml/qml/qqmlglobal_p.h +++ b/src/qml/qml/qqmlglobal_p.h @@ -193,16 +193,6 @@ do { \ return QObjectPrivate::get(sender)->isSignalConnected(signalIdx); \ } while (0) -struct QQmlGraphics_DerivedObject : public QObject -{ - void setParent_noEvent(QObject *parent) { - bool sce = d_ptr->sendChildEvents; - d_ptr->sendChildEvents = false; - setParent(parent); - d_ptr->sendChildEvents = sce; - } -}; - /*! Returns true if the case of \a fileName is equivalent to the file case of \a fileName on disk, and false otherwise. @@ -230,7 +220,11 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int length = -1); */ inline void QQml_setParent_noEvent(QObject *object, QObject *parent) { - static_cast(object)->setParent_noEvent(parent); + QObjectPrivate *d_ptr = QObjectPrivate::get(object); + bool sce = d_ptr->sendChildEvents; + d_ptr->sendChildEvents = false; + object->setParent(parent); + d_ptr->sendChildEvents = sce; } class Q_QML_PRIVATE_EXPORT QQmlValueTypeProvider -- cgit v1.2.3