From 53d3a0779663285baaaf13a05afc4a7d11f6ed29 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 Nov 2017 09:48:57 +0100 Subject: Make deletion of transitions safe Task-number: QTBUG-63844 Change-Id: I65029e9039ea3db85152fc3cdefaac3deee0db6c Reviewed-by: Simon Hausmann --- src/quick/items/qquickitemviewtransition_p.h | 18 +++++++++-------- src/quick/util/qquicktransition.cpp | 29 ++++++++++++++++------------ src/quick/util/qquicktransition_p.h | 15 +++++++++++--- 3 files changed, 39 insertions(+), 23 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitemviewtransition_p.h b/src/quick/items/qquickitemviewtransition_p.h index 3d2f5361b1..29a62f7f10 100644 --- a/src/quick/items/qquickitemviewtransition_p.h +++ b/src/quick/items/qquickitemviewtransition_p.h @@ -58,6 +58,8 @@ QT_REQUIRE_CONFIG(quick_viewtransitions); #include #include #include +#include +#include QT_BEGIN_NAMESPACE @@ -115,14 +117,14 @@ public: QList moveTransitionTargets; QList removeTransitionTargets; - QQuickTransition *populateTransition; - QQuickTransition *addTransition; - QQuickTransition *addDisplacedTransition; - QQuickTransition *moveTransition; - QQuickTransition *moveDisplacedTransition; - QQuickTransition *removeTransition; - QQuickTransition *removeDisplacedTransition; - QQuickTransition *displacedTransition; + QQmlGuard populateTransition; + QQmlGuard addTransition; + QQmlGuard addDisplacedTransition; + QQmlGuard moveTransition; + QQmlGuard moveDisplacedTransition; + QQmlGuard removeTransition; + QQmlGuard removeDisplacedTransition; + QQmlGuard displacedTransition; private: friend class QQuickItemViewTransitionJob; diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp index 29690a4857..6ae89c4ed4 100644 --- a/src/quick/util/qquicktransition.cpp +++ b/src/quick/util/qquicktransition.cpp @@ -109,7 +109,7 @@ protected: void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; }; -class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener +class QQuickTransitionPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QQuickTransition) public: @@ -120,11 +120,8 @@ public: { } - void removeStateChangeListener(QAbstractAnimationJob *anim) - { - if (anim) - anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange); - } + static QQuickTransitionPrivate *get(QQuickTransition *q) { return q->d_func(); } + void animationStateChanged(QAbstractAnimationJob::State newState); QString fromState; QString toState; @@ -134,7 +131,6 @@ public: bool reversible; bool enabled; protected: - void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; static void append_animation(QQmlListProperty *list, QQuickAbstractAnimation *a); static int animation_count(QQmlListProperty *list); @@ -171,7 +167,16 @@ void QQuickTransitionPrivate::clear_animations(QQmlListPropertyanimationStateChanged(newState); +} + +void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob::State newState) { Q_Q(QQuickTransition); @@ -197,15 +202,16 @@ void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState } } -QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim) +QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim) : m_transition(transition) , m_anim(anim) { + anim->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange); } QQuickTransitionInstance::~QQuickTransitionInstance() { - m_transition->removeStateChangeListener(m_anim); + removeStateChangeListener(); delete m_anim; } @@ -270,8 +276,7 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward); - group->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange); - QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(d, group); + QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(this, group); return wrapper; } diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h index d6f365f99e..6d2e41fc9d 100644 --- a/src/quick/util/qquicktransition_p.h +++ b/src/quick/util/qquicktransition_p.h @@ -53,6 +53,7 @@ #include "qquickstate_p.h" #include +#include #include #include @@ -64,10 +65,10 @@ class QQuickTransitionPrivate; class QQuickTransitionManager; class QQuickTransition; -class QQuickTransitionInstance +class QQuickTransitionInstance : QAnimationJobChangeListener { public: - QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim); + QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim); ~QQuickTransitionInstance(); void start(); @@ -75,8 +76,16 @@ public: bool isRunning() const; +protected: + void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; + + void removeStateChangeListener() + { + m_anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange); + } + private: - QQuickTransitionPrivate *m_transition; + QQmlGuard m_transition; QAbstractAnimationJob *m_anim; friend class QQuickTransition; }; -- cgit v1.2.3 From 0c6e7aa125184f8a04c30019204d5ab1e8d3ef01 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 11 Dec 2017 10:18:55 +0100 Subject: Fix valgrind warning about uninitialized variable The flaky qmltest autotest triggered these warnings quite a bit, so maybe this helps stabilize that autotest. Change-Id: Ib03a9fbbbde376296e7bea4cbd4ba2422907fe44 Reviewed-by: Simon Hausmann --- src/quick/items/qquickflickable_p_p.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h index 1ceff22dfc..451146329c 100644 --- a/src/quick/items/qquickflickable_p_p.h +++ b/src/quick/items/qquickflickable_p_p.h @@ -106,9 +106,10 @@ public: , continuousFlickVelocity(0), velocityTime(), vTime(0) , smoothVelocity(fp), atEnd(false), atBeginning(true) , transitionToSet(false) - , fixingUp(false), inOvershoot(false), moving(false), flicking(false) + , fixingUp(false), inOvershoot(false), inRebound(false), moving(false), flicking(false) , dragging(false), extentsChanged(false) , explicitValue(false), minExtentDirty(true), maxExtentDirty(true) + , unused(0) {} ~AxisData(); @@ -168,6 +169,7 @@ public: bool explicitValue : 1; mutable bool minExtentDirty : 1; mutable bool maxExtentDirty : 1; + uint unused : 19; }; bool flickX(qreal velocity); -- cgit v1.2.3 From dd2657e30a42c269f47195d61a9fe8a5fff02912 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 23 Nov 2017 09:02:03 +0100 Subject: Handle the application state changes so items update appropriately When the application state is no longer active, then the items should be acting as if the window deactivated in this case. This allows MouseAreas for instance to ungrab the mouse when the application goes into the background on mobile devices. Task-number: QTBUG-53036 Change-Id: I5c9a56a5fd3ad3a2ef03ff114561c671874a9391 Reviewed-by: Shawn Rutledge Reviewed-by: Paul Olav Tvete --- src/quick/items/qquickwindow.cpp | 10 +++++++++- src/quick/items/qquickwindow.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index fbcfa84948..a483020439 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -567,13 +567,21 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) QObject::connect(q, SIGNAL(focusObjectChanged(QObject*)), q, SIGNAL(activeFocusItemChanged())); QObject::connect(q, SIGNAL(screenChanged(QScreen*)), q, SLOT(handleScreenChanged(QScreen*))); - + QObject::connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), + q, SLOT(handleApplicationStateChanged(Qt::ApplicationState))); QObject::connect(q, SIGNAL(frameSwapped()), q, SLOT(runJobsAfterSwap()), Qt::DirectConnection); if (QQmlInspectorService *service = QQmlDebugConnector::service()) service->addWindow(q); } +void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state) +{ + Q_D(QQuickWindow); + if (state != Qt::ApplicationActive && d->contentItem) + d->contentItem->windowDeactivateEvent(); +} + /*! \property QQuickWindow::data \internal diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 9c3e7277bc..cd27d48bc9 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -221,7 +221,7 @@ private Q_SLOTS: void handleScreenChanged(QScreen *screen); void setTransientParent_helper(QQuickWindow *window); void runJobsAfterSwap(); - + void handleApplicationStateChanged(Qt::ApplicationState state); private: friend class QQuickItem; friend class QQuickWidget; -- cgit v1.2.3 From ae01e0dbf50cb6da1967e10eb95d63313dc5aa7a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 11 Dec 2017 14:32:04 +0100 Subject: Flickable: don't jump after premature movementEnding due to timer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Followup to ef8c6f6a0bf5e4c9ee41306f2df59048ab96038f: we emit movementEnding for the benefit of the user, scrollbars, decorators etc. in case the ScrollEnd phase means that movement really ended (it means the user lifted his fingers from the trackpad, but momentum events can cause the movement to continue after that). But in case movement didn't end, we don't want to have a jump when it resumes. But scrollingPhase will be true after an event with ScrollBegin phase, and false after an event with ScrollEnd, also false if the mouse is an ordinary wheel mouse without phases. So when the timer fires, if the user has not yet lifted his fingers, scrollingPhase is true, and that means scrolling isn't really ending, so we should not set vMoved to false. Setting vMoved to false will cause the drag() function to reset vData.dragStartOffset to the current dy value, which ultimately causes the jump in contentY. It should be done only when scrolling really ends. If the timer fires and scrollingPhase is false, we can be sure it really ended. But if you flick, then rest your fingers, then lift them, there is no momentum, so the final event has scroll phase ScrollEnd, and we need to run the timer one more time to detect that there are no more updates and finish the transition back to the default state (set vMoved back to false, emit signals such as movementEnded, etc.) The ultimate solution is to add another Qt::ScrollPhase enum, such as ScrollMomentum, but we should not do that in the 5.9 series. Task-number: QTBUG-63026 Change-Id: I854c52a680028cb1d43b133be65653d87a05a0b1 Reviewed-by: Jan Arve Sæther --- src/quick/items/qquickflickable.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 3662827973..44612edc49 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1444,17 +1444,23 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) case Qt::ScrollUpdate: if (d->scrollingPhase) d->pressed = true; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS + // TODO eliminate this timer when ScrollMomentum has been added d->movementEndingTimer.start(MovementEndingTimerInterval, this); #endif break; case Qt::ScrollEnd: + // TODO most of this should be done at transition to ScrollMomentum phase, + // then do what the movementEndingTimer triggers at transition to ScrollEnd phase d->pressed = false; d->scrollingPhase = false; d->draggingEnding(); event->accept(); returnToBounds(); d->lastPosTime = -1; +#ifdef Q_OS_MACOS + d->movementEndingTimer.start(MovementEndingTimerInterval, this); +#endif return; } @@ -2671,13 +2677,15 @@ void QQuickFlickable::movementEnding(bool hMovementEnding, bool vMovementEnding) if (hMovementEnding && d->hData.moving && (!d->pressed && !d->stealMouse)) { d->hData.moving = false; - d->hMoved = false; + if (!d->scrollingPhase) + d->hMoved = false; emit movingHorizontallyChanged(); } if (vMovementEnding && d->vData.moving && (!d->pressed && !d->stealMouse)) { d->vData.moving = false; - d->vMoved = false; + if (!d->scrollingPhase) + d->vMoved = false; emit movingVerticallyChanged(); } if (wasMoving && !isMoving()) { -- cgit v1.2.3 From d7a4658475cfb460979d7af02de048a9405c123e Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 13 Dec 2017 08:08:18 +0100 Subject: remove unimplemented QQuickItemPrivate::_q_windowChanged declaration It was added in 4c5445ddb0e7388247783c868925c086bdd666f7 but never implemented. Change-Id: I748295b2a1d82ed19444c0e447e1d7e88baf34b1 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickitem_p.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index c0c9bd46bd..16b919b3e8 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -304,7 +304,6 @@ public: static void transform_clear(QQmlListProperty *list); void _q_resourceObjectDeleted(QObject *); - void _q_windowChanged(QQuickWindow *w); quint64 _q_createJSWrapper(QV4::ExecutionEngine *engine); enum ChangeType { -- cgit v1.2.3 From 243b819ff73f6aaa9dc068d43b8b918a98f53663 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 14 Dec 2017 10:10:27 +0100 Subject: Fix QSGTexture* leak in QQuickFramebufferObject Ownership is not taken by the node. The dtor already destroys the QSGTexture correctly so follow suit when recreating the FBO due to a resize. Task-number: QTBUG-65156 Change-Id: I13a9f0332bf75a4c624ea7dd24633625ca07c8d4 Reviewed-by: Paolo Angelelli Reviewed-by: Andy Nichols --- src/quick/items/qquickframebufferobject.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/quick') diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 042ee21aec..20ba067a6b 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -313,6 +313,7 @@ QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNode desiredFboSize *= n->devicePixelRatio; if (n->fbo && ((d->followsItemSize && n->fbo->size() != desiredFboSize) || n->invalidatePending)) { + delete n->texture(); delete n->fbo; n->fbo = 0; delete n->msDisplayFbo; -- cgit v1.2.3 From 2cacc1c07a1e361bb20411d3f19fdecb3009be12 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 15 Dec 2017 13:27:45 +0100 Subject: Add new logging category qt.quick.window.transient to monitor the increasing number of places from which the transient parent relationship can be detected; and a debug operator for QQuickWindow so that these log messages are more useful. [ChangeLog][QtQuick][QQuickWindow] added logging category qt.quick.window.transient to check detection of transient windows declared inside other Items and Windows Change-Id: Ic899af648765fcdc59b8da7dd1f1bed20db300f2 Reviewed-by: Frederik Gladhorn --- src/quick/items/qquickitem.cpp | 7 ++++-- src/quick/items/qquickitemsmodule.cpp | 6 +++++ src/quick/items/qquickloader.cpp | 2 ++ src/quick/items/qquickwindow.cpp | 40 +++++++++++++++++++++++++++++++++- src/quick/items/qquickwindow.h | 4 ++++ src/quick/items/qquickwindowmodule.cpp | 2 ++ 6 files changed, 58 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index bd37323ef9..4a44b1531a 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -86,6 +86,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET) Q_DECLARE_LOGGING_CATEGORY(DBG_HOVER_TRACE) +Q_DECLARE_LOGGING_CATEGORY(lcTransient) void debugFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1) { @@ -3248,11 +3249,13 @@ void QQuickItemPrivate::data_append(QQmlListProperty *prop, QObject *o) } if (thisWindow) { - if (itemWindow) + if (itemWindow) { + qCDebug(lcTransient) << thisWindow << "is transient for" << itemWindow; thisWindow->setTransientParent(itemWindow); - else + } else { QObject::connect(item, SIGNAL(windowChanged(QQuickWindow*)), thisWindow, SLOT(setTransientParent_helper(QQuickWindow*))); + } } o->setParent(that); } diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 489b1cbd03..b411e676c2 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -111,6 +111,10 @@ #include #include +QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcTransient) +QT_END_NAMESPACE + static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject *parent) { // When setting a parent (especially during dynamic object creation) in QML, @@ -125,6 +129,7 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject QQuickWindow *win = qmlobject_cast(obj); if (win) { // A Window inside an Item should be transient for that item's window + qCDebug(lcTransient) << win << "is transient for" << parentItem->window(); win->setTransientParent(parentItem->window()); return QQmlPrivate::Parented; } @@ -134,6 +139,7 @@ static QQmlPrivate::AutoParentResult qquickitem_autoParent(QObject *obj, QObject QQuickWindow *win = qmlobject_cast(obj); if (win) { // A Window inside a Window should be transient for it + qCDebug(lcTransient) << win << "is transient for" << parentWindow; win->setTransientParent(parentWindow); return QQmlPrivate::Parented; } else { diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp index 27afe5a5db..414103c63e 100644 --- a/src/quick/items/qquickloader.cpp +++ b/src/quick/items/qquickloader.cpp @@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcTransient) + static const QQuickItemPrivate::ChangeTypes watchedChanges = QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index a483020439..15ade6767c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -77,6 +77,9 @@ # include # include #endif +#ifndef QT_NO_DEBUG_STREAM +#include +#endif QT_BEGIN_NAMESPACE @@ -87,6 +90,7 @@ Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target") Q_LOGGING_CATEGORY(DBG_HOVER_TRACE, "qt.quick.hover.trace") Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus") Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty") +Q_LOGGING_CATEGORY(lcTransient, "qt.quick.window.transient") extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -2738,8 +2742,10 @@ void QQuickWindowPrivate::data_append(QQmlListProperty *property, QObje if (!o) return; QQuickWindow *that = static_cast(property->object); - if (QQuickWindow *window = qmlobject_cast(o)) + if (QQuickWindow *window = qmlobject_cast(o)) { + qCDebug(lcTransient) << window << "is transient for" << that; window->setTransientParent(that); + } QQmlListProperty itemProperty = QQuickItemPrivate::get(that->contentItem())->data(); itemProperty.append(&itemProperty, o); } @@ -3266,6 +3272,7 @@ void QQuickWindow::cleanupSceneGraph() void QQuickWindow::setTransientParent_helper(QQuickWindow *window) { + qCDebug(lcTransient) << this << "is transient for" << window; setTransientParent(window); disconnect(sender(), SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(setTransientParent_helper(QQuickWindow*))); @@ -4658,6 +4665,37 @@ QSGNinePatchNode *QQuickWindow::createNinePatchNode() const return isSceneGraphInitialized() ? d->context->sceneGraphContext()->createNinePatchNode() : nullptr; } +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug debug, const QQuickWindow *win) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + if (!win) { + debug << "QQuickWindow(0)"; + return debug; + } + + debug << win->metaObject()->className() << '(' << static_cast(win); + if (win->isActive()) + debug << " active"; + if (win->isExposed()) + debug << " exposed"; + debug << ", visibility=" << win->visibility() << ", flags=" << win->flags(); + if (!win->title().isEmpty()) + debug << ", title=" << win->title(); + if (!win->objectName().isEmpty()) + debug << ", name=" << win->objectName(); + if (win->parent()) + debug << ", parent=" << static_cast(win->parent()); + if (win->transientParent()) + debug << ", transientParent=" << static_cast(win->transientParent()); + debug << ", geometry="; + QtDebugUtils::formatQRect(debug, win->geometry()); + debug << ')'; + return debug; +} +#endif + #include "moc_qquickwindow.cpp" QT_END_NAMESPACE diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index cd27d48bc9..cc88300988 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -230,6 +230,10 @@ private: Q_DISABLE_COPY(QQuickWindow) }; +#ifndef QT_NO_DEBUG_STREAM +QDebug Q_QUICK_EXPORT operator<<(QDebug debug, const QQuickWindow *item); +#endif + QT_END_NAMESPACE Q_DECLARE_METATYPE(QQuickWindow *) diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index c1cc02568c..1981ed2f70 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcTransient) + class QQuickWindowQmlImplPrivate : public QQuickWindowPrivate { public: -- cgit v1.2.3 From 96ec0ab8f0b2e53eff6e1887aff7e51601821845 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 20 Nov 2017 14:01:12 +0100 Subject: QQuickList/GridViewPrivate::fixupPosition: don't set moveReason 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 when the sequence window->polishItems() -> QQIV::updatePolish() -> layout() -> fixupPosition() did its part of the work of moving down. Task-number: QTBUG-62864 Change-Id: I1021e2ea39265de9e1285e2ee17c5733189ab939 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickgridview.cpp | 1 - src/quick/items/qquicklistview.cpp | 3 --- 2 files changed, 4 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index c56cfd3005..5431663770 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -895,7 +895,6 @@ void QQuickGridViewPrivate::initializeCurrentItem() void QQuickGridViewPrivate::fixupPosition() { - moveReason = Other; if (flow == QQuickGridView::FlowLeftToRight) fixupY(); else diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 11eaf393ea..54dfbafaa2 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -1468,9 +1468,6 @@ void QQuickListViewPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometry void QQuickListViewPrivate::fixupPosition() { - if ((haveHighlightRange && highlightRange == QQuickListView::StrictlyEnforceRange) - || snapMode != QQuickListView::NoSnap) - moveReason = Other; if (orient == QQuickListView::Vertical) fixupY(); else -- cgit v1.2.3 From e8570bd1af74724b6fae1ac8a2d8bbdfee7a6504 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Wed, 13 Dec 2017 12:17:14 +0100 Subject: QQuickItemView: Clear pending changes when refilling Generally the bufferedChanges are an "extension" of the currentChanges, which can just not be applied at the moment because we are in a layout phase. If we regenerate or clear the whole view in the mean time, the bufferedChanges become just as invalid as the currentChanges. On top of that, refilling can trigger further changes, part of which will be applied during the refilling. As that leaves us in an inconsistent state, we need to loop the refilling until no further changes are generated. As the changes might affect items that are already visible, and therefore not subject to refilling, we need to clear all the items before refilling in this case. In QTBUG-46488 things are added in the onCompleted callback of the delegates (by expanding the tree view, which translates into adding rows to the list view). Depending on where you add the new items, the list view might pick them up when iterating the model on refill() or it might create delegates for the same model entry twice. So, if that happens we need to discard the result and refill again. Task-number: QTBUG-46488 Change-Id: Ie4e0a731f7feda6aa962b6cb9a6cd5c3bf90486e Reviewed-by: Richard Moe Gustavsen --- src/quick/items/qquickitemview.cpp | 76 ++++++++++++++++++++------------------ 1 file changed, 41 insertions(+), 35 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 10f6c63170..856070634c 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -1751,6 +1751,7 @@ void QQuickItemViewPrivate::updateCurrent(int modelIndex) void QQuickItemViewPrivate::clear() { currentChanges.reset(); + bufferedChanges.reset(); timeline.clear(); releaseVisibleItems(); @@ -1808,51 +1809,56 @@ void QQuickItemViewPrivate::refill(qreal from, qreal to) if (!isValid() || !q->isComponentComplete()) return; - bufferPause.stop(); - currentChanges.reset(); + do { + bufferPause.stop(); + if (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()) { + currentChanges.reset(); + bufferedChanges.reset(); + releaseVisibleItems(); + } - int prevCount = itemCount; - itemCount = model->count(); - qreal bufferFrom = from - buffer; - qreal bufferTo = to + buffer; - qreal fillFrom = from; - qreal fillTo = to; - - bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false); - bool removed = removeNonVisibleItems(bufferFrom, bufferTo); - - if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) { - if (added) { - // We've already created a new delegate this frame. - // Just schedule a buffer refill. - bufferPause.start(); - } else { - if (bufferMode & BufferAfter) - fillTo = bufferTo; - if (bufferMode & BufferBefore) - fillFrom = bufferFrom; - added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true); + int prevCount = itemCount; + itemCount = model->count(); + qreal bufferFrom = from - buffer; + qreal bufferTo = to + buffer; + qreal fillFrom = from; + qreal fillTo = to; + + bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false); + bool removed = removeNonVisibleItems(bufferFrom, bufferTo); + + if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) { + if (added) { + // We've already created a new delegate this frame. + // Just schedule a buffer refill. + bufferPause.start(); + } else { + if (bufferMode & BufferAfter) + fillTo = bufferTo; + if (bufferMode & BufferBefore) + fillFrom = bufferFrom; + added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true); + } } - } - if (added || removed) { - markExtentsDirty(); - updateBeginningEnd(); - visibleItemsChanged(); - updateHeader(); - updateFooter(); - updateViewport(); - } + if (added || removed) { + markExtentsDirty(); + updateBeginningEnd(); + visibleItemsChanged(); + updateHeader(); + updateFooter(); + updateViewport(); + } - if (prevCount != itemCount) - emit q->countChanged(); + if (prevCount != itemCount) + emit q->countChanged(); + } while (currentChanges.hasPendingChanges() || bufferedChanges.hasPendingChanges()); } void QQuickItemViewPrivate::regenerate(bool orientationChanged) { Q_Q(QQuickItemView); if (q->isComponentComplete()) { - currentChanges.reset(); if (orientationChanged) { delete header; header = 0; -- cgit v1.2.3 From 3bbf303403550e4e6f48b8778982d248651449ee Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 11 Dec 2017 15:47:49 +0100 Subject: Check the context matcher for isDestroyed() before assigning it Some code "resets" a custom context matcher on destruction. As destruction order of global objects is not defined, that may be after the context matcher has already been destroyed. Change-Id: I1d3869cb393c490ddb70b71a2d93578a03e2af79 Reviewed-by: Simon Hausmann Reviewed-by: J-P Nurmi --- src/quick/util/qquickshortcut.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index 58f7fc8439..78dc855326 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -122,7 +122,8 @@ Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher() Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher) { - *ctxMatcher() = matcher; + if (!ctxMatcher.isDestroyed()) + *ctxMatcher() = matcher; } QT_BEGIN_NAMESPACE -- cgit v1.2.3 From cbdbbe79ec141e66f3160a1332e49518f9682517 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Wed, 20 Dec 2017 13:48:07 +0100 Subject: Doc: correct Keys::shortcutOverride code snippet c4eefa4a added a snippet where an onEscapePressed handler had: event.accepted = true which is unnecessary, as the documentation says that handlers for specific key events set event.accepted to true by default. Change-Id: I1a40e6e82240a517ba5059a1d5d2217cc7968302 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 4a44b1531a..9adb993a2a 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -970,7 +970,7 @@ bool QQuickKeysAttached::isConnected(const char *signalName) const Keys.onEscapePressed: { console.log("escapeItem is handling escape"); - event.accepted = true; + // event.accepted is set to true by default for the specific key handlers } } -- cgit v1.2.3 From c7ebd4109a8c97164cfe8e1b8fca5a66a701cfa0 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Wed, 13 Dec 2017 18:39:44 +0100 Subject: Move setVisible into QQuickItemPrivate Change-Id: I6bda48f5e982d8e93b8d9a604c275bc0cc0434de Reviewed-by: Shawn Rutledge --- src/quick/items/qquickitem.cpp | 23 ++++++++++++++--------- src/quick/items/qquickitem_p.h | 2 ++ 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 9adb993a2a..2865661fc7 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -5771,19 +5771,24 @@ bool QQuickItem::isVisible() const return d->effectiveVisible; } -void QQuickItem::setVisible(bool v) +void QQuickItemPrivate::setVisible(bool visible) { - Q_D(QQuickItem); - if (v == d->explicitVisible) + if (visible == explicitVisible) return; - d->explicitVisible = v; - if (!v) - d->dirty(QQuickItemPrivate::Visible); + explicitVisible = visible; + if (!visible) + dirty(QQuickItemPrivate::Visible); + + const bool childVisibilityChanged = setEffectiveVisibleRecur(calcEffectiveVisible()); + if (childVisibilityChanged && parentItem) + emit parentItem->visibleChildrenChanged(); // signal the parent, not this! +} - const bool childVisibilityChanged = d->setEffectiveVisibleRecur(d->calcEffectiveVisible()); - if (childVisibilityChanged && d->parentItem) - emit d->parentItem->visibleChildrenChanged(); // signal the parent, not this! +void QQuickItem::setVisible(bool v) +{ + Q_D(QQuickItem); + d->setVisible(v); } /*! diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 16b919b3e8..ffb91e61eb 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -560,6 +560,8 @@ public: #endif void deliverShortcutOverrideEvent(QKeyEvent *); + virtual void setVisible(bool visible); + bool isTransparentForPositioner() const; void setTransparentForPositioner(bool trans); -- cgit v1.2.3 From 6c5b2c367d7cfc92563986b35c99f410f2ac42aa Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 14 Sep 2017 13:58:44 +0200 Subject: QQuickAnimatedImagePrivate::setMovie: check for re-assignment; cleanup There's no need to delete the movie if the same one is being re-assigned. Also, reorder, rename and clean up the variables. Followup to bb02a577f0fbf3bd2a273129e6cb57cfc9a338c8 Task-number: QTBUG-62913 Change-Id: I1fc57b411bfbd819b88be20f5933db8c13e9aba0 Reviewed-by: Kevin Krammer Reviewed-by: Shawn Rutledge --- src/quick/items/qquickanimatedimage.cpp | 114 ++++++++++++++---------------- src/quick/items/qquickanimatedimage_p_p.h | 21 +++--- 2 files changed, 64 insertions(+), 71 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 5bc5b0faff..2f76671b1a 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -54,26 +54,26 @@ QT_BEGIN_NAMESPACE QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine) { - if (!_movie) + if (!movie) return 0; - int current = _movie->currentFrameNumber(); + int current = movie->currentFrameNumber(); if (!frameMap.contains(current)) { QUrl requestedUrl; QQuickPixmap *pixmap = 0; - if (engine && !_movie->fileName().isEmpty()) { + if (engine && !movie->fileName().isEmpty()) { requestedUrl.setUrl(QString::fromUtf8("quickanimatedimage://%1#%2") - .arg(_movie->fileName()) + .arg(movie->fileName()) .arg(current)); } if (!requestedUrl.isEmpty()) { if (QQuickPixmap::isCached(requestedUrl, QSize(), QQuickImageProviderOptions())) pixmap = new QQuickPixmap(engine, requestedUrl); else - pixmap = new QQuickPixmap(requestedUrl, _movie->currentImage()); + pixmap = new QQuickPixmap(requestedUrl, movie->currentImage()); } else { pixmap = new QQuickPixmap; - pixmap->setImage(_movie->currentImage()); + pixmap->setImage(movie->currentImage()); } frameMap.insert(current, pixmap); } @@ -138,7 +138,7 @@ QQuickPixmap* QQuickAnimatedImagePrivate::infoForCurrentFrame(QQmlEngine *engine QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent) : QQuickImage(*(new QQuickAnimatedImagePrivate), parent) { - QObject::connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged); + connect(this, &QQuickImageBase::cacheChanged, this, &QQuickAnimatedImage::onCacheChanged); } QQuickAnimatedImage::~QQuickAnimatedImage() @@ -148,7 +148,7 @@ QQuickAnimatedImage::~QQuickAnimatedImage() if (d->reply) d->reply->deleteLater(); #endif - delete d->_movie; + delete d->movie; qDeleteAll(d->frameMap); d->frameMap.clear(); } @@ -164,9 +164,9 @@ QQuickAnimatedImage::~QQuickAnimatedImage() bool QQuickAnimatedImage::isPaused() const { Q_D(const QQuickAnimatedImage); - if (!d->_movie) + if (!d->movie) return d->paused; - return d->_movie->state()==QMovie::Paused; + return d->movie->state()==QMovie::Paused; } void QQuickAnimatedImage::setPaused(bool pause) @@ -174,11 +174,11 @@ void QQuickAnimatedImage::setPaused(bool pause) Q_D(QQuickAnimatedImage); if (pause == d->paused) return; - if (!d->_movie) { + if (!d->movie) { d->paused = pause; emit pausedChanged(); } else { - d->_movie->setPaused(pause); + d->movie->setPaused(pause); } } @@ -203,9 +203,9 @@ void QQuickAnimatedImage::setPaused(bool pause) bool QQuickAnimatedImage::isPlaying() const { Q_D(const QQuickAnimatedImage); - if (!d->_movie) + if (!d->movie) return d->playing; - return d->_movie->state()!=QMovie::NotRunning; + return d->movie->state()!=QMovie::NotRunning; } void QQuickAnimatedImage::setPlaying(bool play) @@ -213,15 +213,15 @@ void QQuickAnimatedImage::setPlaying(bool play) Q_D(QQuickAnimatedImage); if (play == d->playing) return; - if (!d->_movie) { + if (!d->movie) { d->playing = play; emit playingChanged(); return; } if (play) - d->_movie->start(); + d->movie->start(); else - d->_movie->stop(); + d->movie->stop(); } /*! @@ -237,27 +237,27 @@ void QQuickAnimatedImage::setPlaying(bool play) int QQuickAnimatedImage::currentFrame() const { Q_D(const QQuickAnimatedImage); - if (!d->_movie) - return d->preset_currentframe; - return d->_movie->currentFrameNumber(); + if (!d->movie) + return d->presetCurrentFrame; + return d->movie->currentFrameNumber(); } void QQuickAnimatedImage::setCurrentFrame(int frame) { Q_D(QQuickAnimatedImage); - if (!d->_movie) { - d->preset_currentframe = frame; + if (!d->movie) { + d->presetCurrentFrame = frame; return; } - d->_movie->jumpToFrame(frame); + d->movie->jumpToFrame(frame); } int QQuickAnimatedImage::frameCount() const { Q_D(const QQuickAnimatedImage); - if (!d->_movie) + if (!d->movie) return 0; - return d->_movie->frameCount(); + return d->movie->frameCount(); } void QQuickAnimatedImage::setSource(const QUrl &url) @@ -278,10 +278,7 @@ void QQuickAnimatedImage::setSource(const QUrl &url) d->frameMap.clear(); d->oldPlaying = isPlaying(); - if (d->_movie) { - d->setMovie(nullptr); - } - + d->setMovie(nullptr); d->url = url; emit sourceChanged(d->url); @@ -335,10 +332,8 @@ void QQuickAnimatedImage::load() req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); d->reply = qmlEngine(this)->networkAccessManager()->get(req); - QObject::connect(d->reply, SIGNAL(finished()), - this, SLOT(movieRequestFinished())); - QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), - this, SLOT(requestProgress(qint64,qint64))); + connect(d->reply, &QNetworkReply::finished, this, &QQuickAnimatedImage::movieRequestFinished); + connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); #endif } } @@ -369,7 +364,7 @@ void QQuickAnimatedImage::movieRequestFinished() } #endif - if (!d->_movie || !d->_movie->isValid()) { + if (!d->movie || !d->movie->isValid()) { qmlWarning(this) << "Error Reading Animated Image File " << d->url.toString(); d->setMovie(nullptr); d->setImage(QImage()); @@ -390,12 +385,10 @@ void QQuickAnimatedImage::movieRequestFinished() return; } - connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)), - this, SLOT(playingStatusChanged())); - connect(d->_movie, SIGNAL(frameChanged(int)), - this, SLOT(movieUpdate())); + connect(d->movie, &QMovie::stateChanged, this, &QQuickAnimatedImage::playingStatusChanged); + connect(d->movie, &QMovie::frameChanged, this, &QQuickAnimatedImage::movieUpdate); if (d->cache) - d->_movie->setCacheMode(QMovie::CacheAll); + d->movie->setCacheMode(QMovie::CacheAll); d->status = Ready; emit statusChanged(d->status); @@ -406,22 +399,21 @@ void QQuickAnimatedImage::movieRequestFinished() } bool pausedAtStart = d->paused; - if (d->playing) { - d->_movie->start(); - } + if (d->playing) + d->movie->start(); if (pausedAtStart) - d->_movie->setPaused(true); + d->movie->setPaused(true); if (d->paused || !d->playing) { - d->_movie->jumpToFrame(d->preset_currentframe); - d->preset_currentframe = 0; + d->movie->jumpToFrame(d->presetCurrentFrame); + d->presetCurrentFrame = 0; } d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this))); if (isPlaying() != d->oldPlaying) emit playingChanged(); - if (d->_movie) - d->currentSourceSize = d->_movie->currentPixmap().size(); + if (d->movie) + d->currentSourceSize = d->movie->currentPixmap().size(); else d->currentSourceSize = QSize(0, 0); @@ -440,7 +432,7 @@ void QQuickAnimatedImage::movieUpdate() d->frameMap.clear(); } - if (d->_movie) { + if (d->movie) { d->setPixmap(*d->infoForCurrentFrame(qmlEngine(this))); emit frameChanged(); } @@ -450,12 +442,12 @@ void QQuickAnimatedImage::playingStatusChanged() { Q_D(QQuickAnimatedImage); - if ((d->_movie->state() != QMovie::NotRunning) != d->playing) { - d->playing = (d->_movie->state() != QMovie::NotRunning); + if ((d->movie->state() != QMovie::NotRunning) != d->playing) { + d->playing = (d->movie->state() != QMovie::NotRunning); emit playingChanged(); } - if ((d->_movie->state() == QMovie::Paused) != d->paused) { - d->paused = (d->_movie->state() == QMovie::Paused); + if ((d->movie->state() == QMovie::Paused) != d->paused) { + d->paused = (d->movie->state() == QMovie::Paused); emit pausedChanged(); } } @@ -466,13 +458,11 @@ void QQuickAnimatedImage::onCacheChanged() if (!cache()) { qDeleteAll(d->frameMap); d->frameMap.clear(); - if (d->_movie) { - d->_movie->setCacheMode(QMovie::CacheNone); - } + if (d->movie) + d->movie->setCacheMode(QMovie::CacheNone); } else { - if (d->_movie) { - d->_movie->setCacheMode(QMovie::CacheAll); - } + if (d->movie) + d->movie->setCacheMode(QMovie::CacheAll); } } @@ -488,13 +478,15 @@ void QQuickAnimatedImage::componentComplete() load(); } -void QQuickAnimatedImagePrivate::setMovie(QMovie *movie) +void QQuickAnimatedImagePrivate::setMovie(QMovie *m) { + if (movie == m) + return; Q_Q(QQuickAnimatedImage); const int oldFrameCount = q->frameCount(); - delete _movie; - _movie = movie; + delete movie; + movie = m; if (oldFrameCount != q->frameCount()) emit q->frameCountChanged(); diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h index 68c4f2d359..85508459f9 100644 --- a/src/quick/items/qquickanimatedimage_p_p.h +++ b/src/quick/items/qquickanimatedimage_p_p.h @@ -70,28 +70,29 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate public: QQuickAnimatedImagePrivate() - : playing(true), paused(false), preset_currentframe(0), _movie(0), oldPlaying(false) + : playing(true), paused(false), oldPlaying(false), presetCurrentFrame(0) + , currentSourceSize(0, 0), movie(nullptr) #if QT_CONFIG(qml_network) - , reply(0), redirectCount(0) + , reply(nullptr), redirectCount(0) #endif - , currentSourceSize(0, 0) { } QQuickPixmap *infoForCurrentFrame(QQmlEngine *engine); + void setMovie(QMovie *movie); - bool playing; - bool paused; - int preset_currentframe; - QMovie *_movie; - bool oldPlaying; + bool playing : 1; + bool paused : 1; + bool oldPlaying : 1; + unsigned padding: 29; + int presetCurrentFrame; + QSize currentSourceSize; + QMovie *movie; #if QT_CONFIG(qml_network) QNetworkReply *reply; int redirectCount; #endif QMap frameMap; - QSize currentSourceSize; - void setMovie(QMovie *movie); }; QT_END_NAMESPACE -- cgit v1.2.3 From 76da60b5ad388b6873f496b07b2c3ccabe9c9490 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Fri, 5 Jan 2018 10:49:31 +0100 Subject: Doc: state that childrenRect is read-only Task-number: QTBUG-64115 Change-Id: I0246124a438328c062c37560b1b45c025078c681 Reviewed-by: J-P Nurmi --- src/quick/items/qquickitem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 2865661fc7..af60ab879b 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -3654,8 +3654,9 @@ QQmlListProperty QQuickItemPrivate::data() \qmlproperty real QtQuick::Item::childrenRect.y \qmlproperty real QtQuick::Item::childrenRect.width \qmlproperty real QtQuick::Item::childrenRect.height + \readonly - This property holds the collective position and size of the item's + This read-only property holds the collective position and size of the item's children. This property is useful if you need to access the collective geometry -- cgit v1.2.3 From cee8c21efada48c6f1ce9e0359170edbf334cec3 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Wed, 10 Jan 2018 10:41:09 +0100 Subject: Initialize member variable >>> CID 186477: Uninitialized members (UNINIT_CTOR) >>> Non-static class member "padding" is not initialized in this Change-Id: I1861a959ec8027b62321885de5d48e6e1df1ccc4 Coverity-Id: 186477 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickanimatedimage_p_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h index 85508459f9..e172962ee4 100644 --- a/src/quick/items/qquickanimatedimage_p_p.h +++ b/src/quick/items/qquickanimatedimage_p_p.h @@ -70,8 +70,8 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate public: QQuickAnimatedImagePrivate() - : playing(true), paused(false), oldPlaying(false), presetCurrentFrame(0) - , currentSourceSize(0, 0), movie(nullptr) + : playing(true), paused(false), oldPlaying(false), padding(0) + , presetCurrentFrame(0) , currentSourceSize(0, 0), movie(nullptr) #if QT_CONFIG(qml_network) , reply(nullptr), redirectCount(0) #endif -- cgit v1.2.3 From ddf495fb81ea89173af3310f50314b177bc866d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Wed, 13 Dec 2017 16:16:44 +0100 Subject: GridView: Fix an off-by-one offset of positioning of items The block for finding the position for the item *before* needs to be applied for the case where visibleItems is empty too, so we separate it out. Change-Id: I60a7e3a44d01a0087970e37bf4e73b94da5ebd48 Task-number: QTBUG-49218 Reviewed-by: Shawn Rutledge --- src/quick/items/qquickgridview.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 5431663770..2be64362b2 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -537,13 +537,12 @@ bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal if (visibleItems.count()) { FxGridItemSG *firstItem = static_cast(visibleItems.constFirst()); rowPos = firstItem->rowPos(); - colNum = qFloor((firstItem->colPos()+colSize()/2) / colSize()); - if (--colNum < 0) { - colNum = columns - 1; - rowPos -= rowSize(); - } - } else { - colNum = qFloor((colPos+colSize()/2) / colSize()); + colPos = firstItem->colPos(); + } + colNum = qFloor((colPos+colSize()/2) / colSize()); + if (--colNum < 0) { + colNum = columns - 1; + rowPos -= rowSize(); } // Prepend -- cgit v1.2.3 From ceba0c6b9a0ac3b50f460572ba95bbbedbbaccae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= Date: Wed, 10 Jan 2018 17:00:21 +0100 Subject: QSGSoftwarePixmapRenderer: Fix incorrect background coordinates The pixmap renderer sets up QPainter's window coordinates system but still positions the background node in device coordinates. If the window rectangle is QRect(x, y, w, h) then the background rectangle will be set to QRect(0, 0, w, h). As the rendering output is clipped to the background rectangle, this means that the image will be left with transparent bands of x pixels on the right and y pixels on the bottom. Task-number: QTBUG-62867 Change-Id: I3b2c18dafda4381b0daa64f849330f51bcc743b2 Reviewed-by: Andy Nichols --- .../adaptations/software/qsgabstractsoftwarerenderer.cpp | 10 +++++----- .../adaptations/software/qsgabstractsoftwarerenderer_p.h | 4 ++-- .../adaptations/software/qsgsoftwarepixmaprenderer.cpp | 2 +- .../scenegraph/adaptations/software/qsgsoftwarerenderer.cpp | 3 ++- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp index 30088846a6..4cec84646e 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer.cpp @@ -233,11 +233,11 @@ void QSGAbstractSoftwareRenderer::setBackgroundColor(const QColor &color) renderableNode(m_background)->markMaterialDirty(); } -void QSGAbstractSoftwareRenderer::setBackgroundSize(const QSize &size) +void QSGAbstractSoftwareRenderer::setBackgroundRect(const QRect &rect) { - if (m_background->rect().size().toSize() == size) + if (m_background->rect().toRect() == rect) return; - m_background->setRect(0.0f, 0.0f, size.width(), size.height()); + m_background->setRect(rect); renderableNode(m_background)->markGeometryDirty(); // Invalidate the whole scene when the background is resized markDirty(); @@ -248,9 +248,9 @@ QColor QSGAbstractSoftwareRenderer::backgroundColor() return m_background->color(); } -QSize QSGAbstractSoftwareRenderer::backgroundSize() +QRect QSGAbstractSoftwareRenderer::backgroundRect() { - return m_background->rect().size().toSize(); + return m_background->rect().toRect(); } void QSGAbstractSoftwareRenderer::nodeAdded(QSGNode *node) diff --git a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h index f20c2cf977..f6594d931a 100644 --- a/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h +++ b/src/quick/scenegraph/adaptations/software/qsgabstractsoftwarerenderer_p.h @@ -83,9 +83,9 @@ protected: QRegion optimizeRenderList(); void setBackgroundColor(const QColor &color); - void setBackgroundSize(const QSize &size); + void setBackgroundRect(const QRect &rect); QColor backgroundColor(); - QSize backgroundSize(); + QRect backgroundRect(); // only known after calling optimizeRenderList() bool isOpaque() const { return m_isOpaque; } diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp index 7824e53622..a56c126541 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp @@ -79,7 +79,7 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target) QElapsedTimer renderTimer; // Setup background item - setBackgroundSize(QSize(target->width(), target->height())); + setBackgroundRect(m_projectionRect); setBackgroundColor(clearColor()); renderTimer.start(); diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp index cad826fb27..ddc7ec5d4c 100644 --- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp +++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderer.cpp @@ -112,7 +112,8 @@ void QSGSoftwareRenderer::render() QElapsedTimer renderTimer; setBackgroundColor(clearColor()); - setBackgroundSize(QSize(m_paintDevice->width() / m_paintDevice->devicePixelRatio(), + setBackgroundRect(QRect(0, 0, + m_paintDevice->width() / m_paintDevice->devicePixelRatio(), m_paintDevice->height() / m_paintDevice->devicePixelRatio())); // Build Renderlist -- cgit v1.2.3 From 52874a0e6f739ce410c8401e19b0a9ef6d02cabf Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 15 Jan 2018 11:30:26 +0100 Subject: Optimizations for Repeater::clear() and ~QQmlItem() QQmlRepeater::clear() had quadratic complexity in the number of items, because the items where removed from the back. Fix this by searching the cache from the back as well as searching for child items to remove from the back. Change-Id: I92e491a8abf47cee9d382ef15cd2471f722fa6dd Reviewed-by: Simon Hausmann --- src/quick/items/qquickitem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index af60ab879b..54cb8be5da 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2375,9 +2375,8 @@ QQuickItem::~QQuickItem() else if (d->window) d->derefWindow(); - // XXX todo - optimize while (!d->childItems.isEmpty()) - d->childItems.constFirst()->setParentItem(0); + d->childItems.constLast()->setParentItem(0); if (!d->changeListeners.isEmpty()) { const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) @@ -2953,7 +2952,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) Q_ASSERT(child); Q_ASSERT(childItems.contains(child)); - childItems.removeOne(child); + int idx = childItems.lastIndexOf(child); + childItems.removeAt(idx); Q_ASSERT(!childItems.contains(child)); QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); -- cgit v1.2.3 From 187af5c7d2aab87545788f59eb8f8549e130c211 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 17 Jan 2018 11:37:14 +0100 Subject: Partially revert "Optimizations for Repeater::clear() and ~QQmlItem()" Reversing the destruction order in ~QQuickItem, and searching from the back in removeChild() wasn't such a good idea after all, as it breaks some assumptions people have about removing. We'll need to find a different solution for the quadratic behaviour coming from QQuickRepeater::clear(). This reverts parts of commit 52874a0e6f739ce410c8401e19b0a9ef6d02cabf. Change-Id: I5a6ff9f5ddd9f0f6667142dbcc568b6aba6f8ee9 Reviewed-by: Simon Hausmann --- src/quick/items/qquickitem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 54cb8be5da..af60ab879b 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2375,8 +2375,9 @@ QQuickItem::~QQuickItem() else if (d->window) d->derefWindow(); + // XXX todo - optimize while (!d->childItems.isEmpty()) - d->childItems.constLast()->setParentItem(0); + d->childItems.constFirst()->setParentItem(0); if (!d->changeListeners.isEmpty()) { const auto listeners = d->changeListeners; // NOTE: intentional copy (QTBUG-54732) @@ -2952,8 +2953,7 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) Q_ASSERT(child); Q_ASSERT(childItems.contains(child)); - int idx = childItems.lastIndexOf(child); - childItems.removeAt(idx); + childItems.removeOne(child); Q_ASSERT(!childItems.contains(child)); QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); -- cgit v1.2.3 From a161024a37da7eb6655c1ca42c581800214852b5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 17 Jan 2018 12:13:44 +0100 Subject: Fix quadratic behavior in QQuickRepeater::clear(), take 2 This amends 52874a0e6f739ce410c8401e19b0a9ef6d02cabf, to also fix the quadratic behavior when removing the repeaters item from their parent. Change-Id: I24ad7ca4f66a765a5e991846d65803ccf84c2cab Reviewed-by: Simon Hausmann --- src/quick/items/qquickrepeater.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp index 658a7de3d4..ba9460bf76 100644 --- a/src/quick/items/qquickrepeater.cpp +++ b/src/quick/items/qquickrepeater.cpp @@ -374,9 +374,12 @@ void QQuickRepeater::clear() if (complete) emit itemRemoved(i, item); d->model->release(item); - item->setParentItem(0); } } + for (QQuickItem *item : qAsConst(d->deletables)) { + if (item) + item->setParentItem(0); + } } d->deletables.clear(); d->itemCount = 0; -- cgit v1.2.3 From e4ffad84fecebb3c1fc554b3252fd5d059c0ff38 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 16 Jan 2018 09:29:59 +0100 Subject: Speed up PropertyChange state application Every time we decode a potential binding of a PropertyChanges{} object, we call qmlContext(this) and we go through a full QQmlProperty construction (which involves property name decoding by dots and property lookups), just to determine if we're doing a binding on a property or a signal. QQmlProperty::isSignalProperty() will only return true if the property is valid and if it's a "function" type. The QQmlProperty constructor on the other hand only constructs a valid regular property if it's _not_ a function type and a signal property _has_ to start with "on" followed by an upper case character. We can copy this shortcut out into decodeBinding() to avoid the QQmlProperty construction in the common case of plain property bindings. This is also legit in the scope of group properties, as signal bindings on group properties are not supported (we always use the state's target object for signal lookup, never the group object). In addition, avoid creating a public QQmlContext for the PropertyChange object by allowing for the construction of the QQmlProperty object via the QQmlContextData, as that's the only data structure we really need. These two changes used to be separate, but they need to go together to keep the tests passing, as the property validation and warning issuing is now moved from decodeBinding() into ::actions() itself. Shaves off 1.5% off delegates_item_states.qml Task-number: QTBUG-65708 Change-Id: I32a17d815bd3495a907a51068a971eb7cb69c6ef Reviewed-by: Lars Knoll --- src/quick/util/qquickpropertychanges.cpp | 33 +++++++++++++++++++------------- src/quick/util/qquickstate.cpp | 5 ++--- src/quick/util/qquickstate_p.h | 4 ++-- 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 61380b3ea0..aecb7115ea 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -281,15 +281,19 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, return; } - QQmlProperty prop = property(propertyName); //### better way to check for signal property? - - if (prop.type() & QQmlProperty::SignalProperty) { - QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler; - handler->property = prop; - handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), - QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); - signalReplacements << handler; - return; + if (propertyName.count() >= 3 && + propertyName.at(0) == QLatin1Char('o') && + propertyName.at(1) == QLatin1Char('n') && + propertyName.at(2).isUpper()) { + QQmlProperty prop = property(propertyName); + if (prop.isSignalProperty()) { + QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler; + handler->property = prop; + handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), + QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); + signalReplacements << handler; + return; + } } if (binding->type == QV4::CompiledData::Binding::Type_Script) { @@ -395,7 +399,10 @@ QQmlProperty QQuickPropertyChangesPrivate::property(const QString &property) { Q_Q(QQuickPropertyChanges); - QQmlProperty prop(object, property, qmlContext(q)); + QQmlContextData *context = nullptr; + if (QQmlData *ddata = QQmlData::get(q)) + context = ddata->outerContext; + QQmlProperty prop = QQmlPropertyPrivate::create(object, property, context); if (!prop.isValid()) { qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QQmlProperty(); @@ -415,9 +422,10 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() ActionList list; for (int ii = 0; ii < d->properties.count(); ++ii) { + QQmlProperty prop = d->property(d->properties.at(ii).first); - QQuickStateAction a(d->object, d->properties.at(ii).first, - qmlContext(this), d->properties.at(ii).second); + QQuickStateAction a(d->object, prop, d->properties.at(ii).first, + d->properties.at(ii).second); if (a.property.isValid()) { a.restore = restoreEntryValues(); @@ -426,7 +434,6 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() } for (int ii = 0; ii < d->signalReplacements.count(); ++ii) { - QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii); if (handler->property.isValid()) { diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp index 0a49d41491..ca8b7bbc2b 100644 --- a/src/quick/util/qquickstate.cpp +++ b/src/quick/util/qquickstate.cpp @@ -68,10 +68,9 @@ QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyNam fromValue = property.read(); } -QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyName, - QQmlContext *context, const QVariant &value) +QQuickStateAction::QQuickStateAction(QObject *target, const QQmlProperty &property, const QString &propertyName, const QVariant &value) : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), - property(target, propertyName, context), toValue(value), + property(property), toValue(value), fromBinding(0), event(0), specifiedObject(target), specifiedProperty(propertyName) { diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h index 7d22ca9f8c..3826daf283 100644 --- a/src/quick/util/qquickstate_p.h +++ b/src/quick/util/qquickstate_p.h @@ -69,8 +69,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateAction public: QQuickStateAction(); QQuickStateAction(QObject *, const QString &, const QVariant &); - QQuickStateAction(QObject *, const QString &, - QQmlContext *, const QVariant &); + QQuickStateAction(QObject *, const QQmlProperty &property, const QString &, + const QVariant &); bool restore:1; bool actionDone:1; -- cgit v1.2.3 From 89c171995b1e86d604809d97456d0f56c8a67416 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 16 Jan 2018 13:21:42 +0100 Subject: Doc: Improve "Qt Quick Scene Graph Renderer" Fix some typos and grammar errors. Change-Id: I9a3fa591ada5ec299ea1277386405944138c9ddc Reviewed-by: Martin Smith --- .../doc/src/concepts/visualcanvas/scenegraph.qdoc | 42 +++++++++++----------- 1 file changed, 21 insertions(+), 21 deletions(-) (limited to 'src/quick') diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc index 27576d488c..289e48aed8 100644 --- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc +++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc @@ -428,7 +428,7 @@ with multiple windows. \note Even in the case where every frame is unique and everything is uploaded from scratch, the default renderer will perform well. - The Qt Quick items in a QML scene populates a tree of QSGNode + The Qt Quick items in a QML scene populate a tree of QSGNode instances. Once created, this tree is a complete description of how a certain frame should be rendered. It does not contain any references back to the Qt Quick items at all and will on most @@ -441,11 +441,11 @@ with multiple windows. If needed, the renderer can be completely replaced using the internal scene graph back-end API. This is mostly interesting for platform vendors who wish to take advantage of non-standard hardware - features. For majority of use cases, the default renderer will be + features. For the majority of use cases, the default renderer will be sufficient. The default renderer focuses on two primary strategies to optimize - the rendering. Batching of draw calls and retention of geometry on + the rendering: Batching of draw calls, and retention of geometry on the GPU. \section1 Batching @@ -458,7 +458,7 @@ with multiple windows. \image visualcanvas_list.png - The simplest way of drawing this list is on a cell-by-cell basis. First + The simplest way of drawing this list is on a cell-by-cell basis. First, the background is drawn. This is a rectangle of a specific color. In OpenGL terms this means selecting a shader program to do solid color fills, setting up the fill color, setting the transformation matrix @@ -495,8 +495,8 @@ with multiple windows. batches. From Qt Quick core item set, this includes Rectangle items with opaque colors and fully opaque images, such as JPEGs or BMPs. - Another benefit of using opaque primitives, is that opaque - primitives does not require \c GL_BLEND to be enabled which can be + Another benefit of using opaque primitives is that opaque + primitives do not require \c GL_BLEND to be enabled, which can be quite costly, especially on mobile and embedded GPUs. Opaque primitives are rendered in a front-to-back manner with @@ -533,7 +533,7 @@ with multiple windows. and the two text elements in another call, as the texts only overlap a background which they are stacked in front of. In the right-most case, the background of "Item 4" overlaps the text of "Item 3" so in - this case, each of backgrounds and texts need to be drawn using + this case, each of backgrounds and texts needs to be drawn using separate calls. Z-wise, the alpha primitives are interleaved with the opaque nodes @@ -550,7 +550,7 @@ with multiple windows. The renderer modifies the vertex shader returned from QSGMaterialShader::vertexShader() and compresses the z values of the - vertex after the model-view and projection matrices has been applied + vertex after the model-view and projection matrices have been applied and then adds a small translation on the z to position it the correct z position. @@ -561,7 +561,7 @@ with multiple windows. The active texture is a unique OpenGL state, which means that multiple primitives using different OpenGL textures cannot be - batched. The Qt Quick scene graph for this reason allows multiple + batched. The Qt Quick scene graph, for this reason, allows multiple QSGTexture instances to be allocated as smaller sub-regions of a larger texture; a texture atlas. @@ -603,10 +603,10 @@ with multiple windows. Each Qt Quick Item inserts a QSGTransformNode into the scene graph tree to manage its x, y, scale or rotation. Child items will be populated under this transform node. The default renderer tracks - the state of transform nodes between frames, and will look at + the state of transform nodes between frames and will look at subtrees to decide if a transform node is a good candidate to become a root for a set of batches. A transform node which changes between - frames and which has a fairly complex subtree, can become a batch + frames and which has a fairly complex subtree can become a batch root. QSGGeometryNodes in the subtree of a batch root are pre-transformed @@ -621,7 +621,7 @@ with multiple windows. removed nodes when panning through a grid or list. Another benefit of identifying transform nodes as batch roots is - that it allows the renderer to retain the parts of the tree that has + that it allows the renderer to retain the parts of the tree that have not changed. For instance, say a UI consists of a list and a button row. When the list is being scrolled and delegates are being added and removed, the rest of the UI, the button row, is unchanged and @@ -684,7 +684,7 @@ with multiple windows. to either \c vertex or \c {msaa}. Vertex antialiasing can produce seams between edges of adjacent - primitives, even when the two edges are mathmatically the same. + primitives, even when the two edges are mathematically the same. Multisample antialiasing does not. @@ -722,7 +722,7 @@ with multiple windows. job when creating batches and can rely on early-z to avoid overdraw. When multisample antialiasing is used, content rendered into - framebuffer objects, need additional extensions to support multisampling + framebuffer objects need additional extensions to support multisampling of framebuffers. Typically \c GL_EXT_framebuffer_multisample and \c GL_EXT_framebuffer_blit. Most desktop chips have these extensions present, but they are less common in embedded chips. When framebuffer @@ -736,7 +736,7 @@ with multiple windows. As stated in the beginning, understanding the finer details of the renderer is not required to get good performance. It is written to optimize for common use cases and will perform quite well under - almost any circumstance. + almost any circumstances. \list @@ -744,7 +744,7 @@ with multiple windows. as possible of the geometry being uploaded again and again. By setting the environment variable \c {QSG_RENDERER_DEBUG=render}, the renderer will output statistics on how well the batching goes, how - many batches, which batches are retained and which are opaque and + many batches are used, which batches are retained and which are opaque and not. When striving for optimal performance, uploads should happen only when really needed, batches should be fewer than 10 and at least 3-4 of them should be opaque. @@ -772,16 +772,16 @@ with multiple windows. QQuickWindow::createTextureFromImage(), let the image have QImage::Format_RGB32, when possible. - \li Be aware of that overlapping compond items, like in the - illustration above, can not be batched. + \li Be aware of that overlapping compound items, like in the + illustration above, cannot be batched. \li Clipping breaks batching. Never use on a per-item basis, inside - tables cells, item delegates or similar. Instead of clipping text, + table cells, item delegates or similar. Instead of clipping text, use eliding. Instead of clipping an image, create a QQuickImageProvider that returns a cropped image. \li Batching only works for 16-bit indices. All built-in items use - 16-bit indices, but custom geometry is free to also use 32-bit + 16-bit indices, but a custom geometry is free to also use 32-bit indices. \li Some material flags prevent batching, the most limiting one @@ -792,7 +792,7 @@ with multiple windows. QQuickWindow::setColor() will be used in a call to \c glClear(), which is potentially faster. - \li Mipmapped Image items are not placed in global atlas and will + \li Mipmapped Image items are not placed in the global atlas and will not be batched. \endlist -- cgit v1.2.3 From 421a1c5cae9cd17a3fefb6133b0727b29f456eff Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 19 Jan 2018 09:53:26 +0100 Subject: Remove another call to QOpenGLContext::currentContext() .. by getting the context from the readily available state. Change-Id: Ie2819a112b31e080a865c657d0fc63cd1968e7a3 Reviewed-by: Lars Knoll --- src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp index ca91e5d85f..1c88e33b10 100644 --- a/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp +++ b/src/quick/scenegraph/qsgdistancefieldglyphnode_p.cpp @@ -181,7 +181,7 @@ void QSGDistanceFieldTextMaterialShader::updateState(const RenderState &state, Q updateTextureScale(QVector2D(1.0 / material->textureSize().width(), 1.0 / material->textureSize().height())); - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions *funcs = state.context()->functions(); funcs->glBindTexture(GL_TEXTURE_2D, material->texture()->textureId); if (updated) { -- cgit v1.2.3 From efeccb3f008c3463d333623cbefc8b77dd9db389 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 17 Jan 2018 13:42:21 +0100 Subject: Avoid repeated calls into thread local storage to get the animation timer Instead hold a direct pointer to the animation timer and make it's methods non static. Change-Id: I6382fd2a1c02464ddb573f0210a14c603fd932db Reviewed-by: Simon Hausmann Reviewed-by: J-P Nurmi Reviewed-by: Robin Burchell --- src/quick/util/qquickanimationcontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp index cebb0391ae..5e56460098 100644 --- a/src/quick/util/qquickanimationcontroller.cpp +++ b/src/quick/util/qquickanimationcontroller.cpp @@ -223,7 +223,7 @@ void QQuickAnimationController::updateProgress() d->animationInstance->setDisableUserControl(); d->animationInstance->start(); - QQmlAnimationTimer::unregisterAnimation(d->animationInstance); + QQmlAnimationTimer::instance()->unregisterAnimation(d->animationInstance); d->animationInstance->setCurrentTime(d->progress * d->animationInstance->duration()); } -- cgit v1.2.3 From 69221e4f21abb3fdd8b3f609a4a6cfe33f9140ec Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 19 Jan 2018 09:12:39 +0100 Subject: Doc: Rename Renderer page to 'Scene Graph OpenGL Renderer' While the architecture might be similar for e.g. the DirectX Renderer, the details are only valid for OpenGL backend. Make this explicit by renaming the page. Change-Id: I24bf82de35099ae14eb6bfb9d58b422b476636ac Reviewed-by: Laszlo Agocs --- src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/quick') diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc index 289e48aed8..99175ab94e 100644 --- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc +++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -176,8 +176,8 @@ attach application code. This can be used to add custom scene graph content or render raw OpenGL content. The integration points are defined by the render loop. -For detailed description of how the scene graph renderer works, see -\l {Qt Quick Scene Graph Renderer}. +For detailed description of how the scene graph renderer for OpenGL +works, see \l {Qt Quick Scene Graph OpenGL Renderer}. There are three render loop variants available: \c basic, \c windows, and \c threaded. Out of these, \c basic and \c windows are @@ -413,10 +413,11 @@ with multiple windows. */ /*! - \title Qt Quick Scene Graph Renderer + \title Qt Quick Scene Graph OpenGL Renderer \page qtquick-visualcanvas-scenegraph-renderer.html - This document explains how the scene graph renderer works internally + This document explains how the scene graph renderer for OpenGL + works internally so that one can write code that uses it in an optimal fashion, both performance-wise and feature-wise. -- cgit v1.2.3 From c46a780e95605bc80bbe8129302d09cec06ba454 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 12 Jan 2018 16:12:27 +0100 Subject: Doc: Do make 'Licenses and Attributions' valid for multiple Qt versions The Qt documentation is supposed to be valid for older Qt versions too. Anyhow, the generated attributions are only valid for the exact version the documentation was generated from, so make this explicit. Also mention since when the libraries are under LGPL3/GPL3. Change-Id: Iec8f67e5e43be456cc77283ca6d2a7ebe142f501 Reviewed-by: Leena Miettinen --- src/quick/doc/src/qtquick.qdoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/doc/src/qtquick.qdoc b/src/quick/doc/src/qtquick.qdoc index e2d4f16dae..ece66cb589 100644 --- a/src/quick/doc/src/qtquick.qdoc +++ b/src/quick/doc/src/qtquick.qdoc @@ -89,7 +89,8 @@ To find out more about using the QML language, see the \l{Qt QML} module documen \section1 Licenses and Attributions Qt Quick is available under commercial licenses from \l{The Qt Company}. -In addition, it is available under the +In addition, it is available under free software licenses. Since Qt 5.4, +these free software licenses are \l{GNU Lesser General Public License, version 3}, or the \l{GNU General Public License, version 2}. See \l{Qt Licensing} for further details. -- cgit v1.2.3 From 16cd1f8d24f011d30d3fc7baf7750700af14d9c5 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Fri, 26 Jan 2018 11:40:09 +0100 Subject: Fix uploading of compressed textures of ETC2_EAC type The call to glCompressedTexImage2D would fail since the code did not account for the fact that the ETC2_EAC scheme uses twice the number of bytes as other ETC schemes. Change-Id: I93502f5848b112cac2f798453a0d32a2c0a2a20b Reviewed-by: Laszlo Agocs --- src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp b/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp index bb8fce046d..62066a136a 100644 --- a/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp +++ b/src/quick/scenegraph/compressedtexture/qsgpkmhandler.cpp @@ -125,9 +125,10 @@ void QEtcTexture::bind() QOpenGLContext *ctx = QOpenGLContext::currentContext(); Q_ASSERT(ctx != 0); + const int compFactor = m_type == GL_COMPRESSED_RGBA8_ETC2_EAC ? 1 : 2; ctx->functions()->glCompressedTexImage2D(GL_TEXTURE_2D, 0, m_type, m_size.width(), m_size.height(), 0, - (m_paddedSize.width() * m_paddedSize.height()) / 2, + (m_paddedSize.width() * m_paddedSize.height()) / compFactor, m_data.data() + headerSize); #ifndef QT_NO_DEBUG -- cgit v1.2.3 From e6d4df156e9aec62054740dc99ab8ba2855eaafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Fri, 26 Jan 2018 16:23:10 +0100 Subject: Make sure we send the UngrabMouse event when clearing grabbers This caused a regression in QtLocation autotest declarative_ui\tst_map_mouse.qml where the sequence of tests test_basic_press_release() and test_enabled() caused test_enabled() to fail. Change-Id: I53621a9a18d0574163260674c11bdcb02c3e1218 Reviewed-by: Paolo Angelelli Reviewed-by: Shawn Rutledge --- src/quick/items/qquickwindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 8b8469f801..2d0f1218bf 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2284,6 +2284,7 @@ QQuickPointerEvent *QQuickWindowPrivate::pointerEventInstance(QEvent *event) con void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) { + Q_Q(QQuickWindow); // If users spin the eventloop as a result of event delivery, we disable // event compression and send events directly. This is because we consider // the usecase a bit evil, but we at least don't want to lose events. @@ -2293,8 +2294,11 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) if (event->asPointerMouseEvent()) { deliverMouseEvent(event->asPointerMouseEvent()); // failsafe: never allow any kind of grab to persist after release - if (event->isReleaseEvent() && event->buttons() == Qt::NoButton) + QQuickItem *grabber = q->mouseGrabberItem(); + if (event->isReleaseEvent() && event->buttons() == Qt::NoButton && grabber) { event->clearGrabbers(); + sendUngrabEvent(grabber, false); + } } else if (event->asPointerTouchEvent()) { deliverTouchEvent(event->asPointerTouchEvent()); } else { -- cgit v1.2.3