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 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