diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2014-03-03 15:40:24 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2014-03-03 15:40:43 +0100 |
commit | 1511dc39a62e9d14b6755d6c2335547c85331d49 (patch) | |
tree | 0b60c51b7597b2fe4ea16a432f4c615214efa0a7 /src/quick/items | |
parent | 75b191b31d9936b134ca9776f1e69e891d03be11 (diff) | |
parent | 915dcb6f8cb6207566f4838f641f434508336fa7 (diff) |
Merge remote-tracking branch 'origin/stable' into dev
This merge also removes the pin for qtbase.
Change-Id: If86998fb912d100cfad150d255ed41544ba1fb0c
Diffstat (limited to 'src/quick/items')
22 files changed, 279 insertions, 92 deletions
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp index ed5c8d7bcb..17adf1b66b 100644 --- a/src/quick/items/context2d/qquickcanvasitem.cpp +++ b/src/quick/items/context2d/qquickcanvasitem.cpp @@ -640,6 +640,8 @@ void QQuickCanvasItem::updatePolish() QQuickItem::updatePolish(); Q_D(QQuickCanvasItem); + if (!isVisible() && !(d->extra.isAllocated() && d->extra->effectRefCount>0)) + return; if (d->context && d->renderStrategy != QQuickCanvasItem::Cooperative) d->context->prepare(d->canvasSize.toSize(), d->tileSize, d->canvasWindow.toRect(), d->dirtyRect.toRect(), d->smooth, antialiasing()); diff --git a/src/quick/items/context2d/qquickcontext2dtexture.cpp b/src/quick/items/context2d/qquickcontext2dtexture.cpp index d3f2a956a3..ef1b65a04f 100644 --- a/src/quick/items/context2d/qquickcontext2dtexture.cpp +++ b/src/quick/items/context2d/qquickcontext2dtexture.cpp @@ -479,9 +479,9 @@ bool QQuickContext2DFBOTexture::doMultisampling() const static bool multisamplingSupported = false; if (!extensionsChecked) { - QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); - multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample") - && extensions.contains("GL_EXT_framebuffer_blit"); + const QSet<QByteArray> extensions = m_context->glContext()->extensions(); + multisamplingSupported = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample")) + && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit")); extensionsChecked = true; } diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp index 8d58ffbfae..57e500a150 100644 --- a/src/quick/items/qquickdroparea.cpp +++ b/src/quick/items/qquickdroparea.cpp @@ -109,9 +109,6 @@ QQuickDropAreaPrivate::~QQuickDropAreaPrivate() The \l drag.source property is communicated to the source of a drag event as the recipient of a drop on the drag target. - - The \l delegate property provides a means to specify a component to be - instantiated for each active drag over a drag target. */ QQuickDropArea::QQuickDropArea(QQuickItem *parent) @@ -308,7 +305,7 @@ void QQuickDropArea::dragLeaveEvent(QDragLeaveEvent *) /*! \qmlsignal QtQuick::DropArea::onDropped(DragEvent drop) - This handler is called when a drop event occurs within the bounds of a + This handler is called when a drop event occurs within the bounds of a DropArea. */ @@ -383,8 +380,8 @@ void QQuickDropArea::dropEvent(QDropEvent *event) The drop action may be one of: \list - \li Qt.CopyAction Copy the data to the target - \li Qt.MoveAction Move the data from the source to the target + \li Qt.CopyAction Copy the data to the target. + \li Qt.MoveAction Move the data from the source to the target. \li Qt.LinkAction Create a link from the source to the target. \li Qt.IgnoreAction Ignore the action (do nothing with the data). \endlist diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 789d1952c0..2f2c932db5 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1262,6 +1262,8 @@ void QQuickFlickable::wheelEvent(QWheelEvent *event) return; } + event->setAccepted(false); + int yDelta = event->angleDelta().y(); int xDelta = event->angleDelta().x(); if (yflick() && yDelta != 0) { diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index 8587da5ac3..f97229a76a 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -65,8 +65,8 @@ QT_BEGIN_NAMESPACE class FxGridItemSG : public FxViewItem { public: - FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, v, own), view(v) { - attached = static_cast<QQuickGridViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(item)); + FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, v, own, static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(i))), view(v) + { } qreal position() const { @@ -1283,7 +1283,8 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) \qmlattachedproperty GridView QtQuick::GridView::view This attached property holds the view that manages this delegate instance. - It is attached to each instance of the delegate. + It is attached to each instance of the delegate and also to the header, the footer + and the highlight delegates. \snippet qml/gridview/gridview.qml isCurrentItem */ @@ -2127,6 +2128,9 @@ void QQuickGridView::geometryChanged(const QRectF &newGeometry, const QRectF &ol void QQuickGridView::initItem(int index, QObject *obj) { QQuickItemView::initItem(index, obj); + + // setting the view from the FxViewItem wrapper is too late if the delegate + // needs access to the view in Component.onCompleted QQuickItem *item = qmlobject_cast<QQuickItem*>(obj); if (item) { QQuickGridViewAttached *attached = static_cast<QQuickGridViewAttached *>( diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h index 8f41f39919..ff0e2217fa 100644 --- a/src/quick/items/qquickgridview_p.h +++ b/src/quick/items/qquickgridview_p.h @@ -42,8 +42,6 @@ #ifndef QQUICKGRIDVIEW_P_H #define QQUICKGRIDVIEW_P_H -#include <QtCore/qpointer.h> - #include "qquickitemview_p.h" @@ -118,23 +116,8 @@ class QQuickGridViewAttached : public QQuickItemViewAttached Q_OBJECT public: QQuickGridViewAttached(QObject *parent) - : QQuickItemViewAttached(parent), m_view(0) {} + : QQuickItemViewAttached(parent) {} ~QQuickGridViewAttached() {} - - Q_PROPERTY(QQuickGridView *view READ view NOTIFY viewChanged) - QQuickGridView *view() { return m_view; } - void setView(QQuickGridView *view) { - if (view != m_view) { - m_view = view; - Q_EMIT viewChanged(); - } - } - -Q_SIGNALS: - void viewChanged(); - -public: - QPointer<QQuickGridView> m_view; }; diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index b6b8a2a39b..69a39d2396 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -676,6 +676,14 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) sourceRect.width() / d->pix.width(), sourceRect.height() / d->pix.height()); + if (targetRect.isEmpty() + || !qIsFinite(targetRect.width()) || !qIsFinite(targetRect.height()) + || nsrect.isEmpty() + || !qIsFinite(nsrect.width()) || !qIsFinite(nsrect.height())) { + delete node; + return 0; + } + if (d->pixmapChanged) { // force update the texture in the node to trigger reconstruction of // geometry and the likes when a atlas segment has changed. diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index 30d0619f7a..020d48613b 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -51,15 +51,17 @@ QT_BEGIN_NAMESPACE #define QML_VIEW_DEFAULTCACHEBUFFER 320 #endif -FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v, bool own) +FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v, bool own, QQuickItemViewAttached *attached) : item(i) , view(v) , transitionableItem(0) - , attached(0) + , attached(attached) , ownItem(own) , releaseAfterTransition(false) , trackGeom(false) { + if (attached) // can be null for default components (see createComponentItem) + attached->setView(view); } FxViewItem::~FxViewItem() diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index ad026a3152..57635d7780 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -43,6 +43,7 @@ #define QQUICKITEMVIEW_P_H #include "qquickflickable_p.h" +#include <qpointer.h> QT_BEGIN_NAMESPACE @@ -282,6 +283,7 @@ class Q_AUTOTEST_EXPORT QQuickItemViewAttached : public QObject { Q_OBJECT + Q_PROPERTY(QQuickItemView *view READ view NOTIFY viewChanged) Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged) Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged) @@ -294,6 +296,14 @@ public: : QObject(parent), m_isCurrent(false), m_delayRemove(false) {} ~QQuickItemViewAttached() {} + QQuickItemView *view() { return m_view; } + void setView(QQuickItemView *view) { + if (view != m_view) { + m_view = view; + Q_EMIT viewChanged(); + } + } + bool isCurrentItem() const { return m_isCurrent; } void setIsCurrentItem(bool c) { if (m_isCurrent != c) { @@ -353,6 +363,7 @@ public: void emitRemove() { Q_EMIT remove(); } Q_SIGNALS: + void viewChanged(); void currentItemChanged(); void delayRemoveChanged(); @@ -364,6 +375,7 @@ Q_SIGNALS: void nextSectionChanged(); public: + QPointer<QQuickItemView> m_view; bool m_isCurrent : 1; bool m_delayRemove : 1; diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index af7c23c02e..a0d17b3bf9 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -56,7 +56,7 @@ QT_BEGIN_NAMESPACE class FxViewItem { public: - FxViewItem(QQuickItem *, QQuickItemView *, bool own); + FxViewItem(QQuickItem *, QQuickItemView *, bool own, QQuickItemViewAttached *attached); virtual ~FxViewItem(); qreal itemX() const; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index 2dd61e386f..3ac28f438b 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -247,16 +247,14 @@ void QQuickViewSection::setLabelPositioning(int l) class FxListItemSG : public FxViewItem { public: - FxListItemSG(QQuickItem *i, QQuickListView *v, bool own) : FxViewItem(i, v, own), view(v) { - attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item)); + FxListItemSG(QQuickItem *i, QQuickListView *v, bool own) : FxViewItem(i, v, own, static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(i))), view(v) + { } inline QQuickItem *section() const { return attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : 0; } void setSection(QQuickItem *s) { - if (!attached) - attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item)); static_cast<QQuickListViewAttached*>(attached)->m_sectionItem = s; } @@ -972,6 +970,9 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString §ion) QQml_setParent_noEvent(sectionItem, contentItem); sectionItem->setParentItem(contentItem); } + // sections are not controlled by FxListItemSG, so apply attached properties here + QQuickItemViewAttached *attached = static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(sectionItem)); + attached->setView(q); } else { delete context; } @@ -1787,7 +1788,8 @@ QQuickListView::~QQuickListView() \qmlattachedproperty ListView QtQuick::ListView::view This attached property holds the view that manages this delegate instance. - It is attached to each instance of the delegate. + It is attached to each instance of the delegate and also to the header, the footer, + the section and the highlight delegates. */ /*! @@ -2855,6 +2857,9 @@ void QQuickListView::geometryChanged(const QRectF &newGeometry, const QRectF &ol void QQuickListView::initItem(int index, QObject *object) { QQuickItemView::initItem(index, object); + + // setting the view from the FxViewItem wrapper is too late if the delegate + // needs access to the view in Component.onCompleted QQuickItem *item = qmlobject_cast<QQuickItem*>(object); if (item) { QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>( diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h index b00501d274..2494e101cd 100644 --- a/src/quick/items/qquicklistview_p.h +++ b/src/quick/items/qquicklistview_p.h @@ -43,7 +43,6 @@ #define QQUICKLISTVIEW_P_H #include "qquickitemview_p.h" -#include <qpointer.h> QT_BEGIN_NAMESPACE @@ -175,23 +174,10 @@ class QQuickListViewAttached : public QQuickItemViewAttached public: QQuickListViewAttached(QObject *parent) - : QQuickItemViewAttached(parent), m_view(0), m_sectionItem(0) {} + : QQuickItemViewAttached(parent), m_sectionItem(0) {} ~QQuickListViewAttached() {} - Q_PROPERTY(QQuickListView *view READ view NOTIFY viewChanged) - QQuickListView *view() { return m_view; } - void setView(QQuickListView *view) { - if (view != m_view) { - m_view = view; - Q_EMIT viewChanged(); - } - } - -Q_SIGNALS: - void viewChanged(); - public: - QPointer<QQuickListView> m_view; QQuickItem *m_sectionItem; }; diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index 7e4335ba63..16ed6f0e10 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -114,9 +114,13 @@ void QQuickRenderControl::initialize(QOpenGLContext *gl) Q_D(QQuickRenderControl); if (!d->window) return; - bool current = gl->makeCurrent(d->window); - if (current) - QQuickWindowPrivate::get(d->window)->context->initialize(gl); + + // It is the caller's responsiblity to make a context/surface current. + // It cannot be done here since the surface to use may not be the + // surface belonging to window. In fact window may not have a native + // window/surface at all. + + QQuickWindowPrivate::get(d->window)->context->initialize(gl); } void QQuickRenderControl::invalidate() @@ -158,6 +162,26 @@ bool QQuickRenderControl::sync() } /*! + Stop rendering and release resources. This function is typically + called when the window is hidden. Requires a current context. + */ +void QQuickRenderControl::stop() +{ + Q_D(QQuickRenderControl); + if (!d->window) + return; + + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window); + cd->fireAboutToStop(); + cd->cleanupNodesOnShutdown(); + + if (!cd->persistentSceneGraph) { + d->rc->invalidate(); + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + } +} + +/*! Render the scenegraph using the current context. */ void QQuickRenderControl::render() diff --git a/src/quick/items/qquickrendercontrol_p.h b/src/quick/items/qquickrendercontrol_p.h index 7255a9ae0b..98dc946303 100644 --- a/src/quick/items/qquickrendercontrol_p.h +++ b/src/quick/items/qquickrendercontrol_p.h @@ -71,6 +71,7 @@ public: void polishItems(); void render(); bool sync(); + void stop(); QImage grab(); diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index 9a20703f18..e57b7abddc 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -478,6 +478,19 @@ void QQuickShaderEffectCommon::sourceDestroyed(QObject *object) } } +static bool qquick_uniqueInUniformData(QQuickItem *source, const QVector<QQuickShaderEffectMaterial::UniformData> *uniformData, int typeToSkip, int indexToSkip) +{ + for (int s=0; s<QQuickShaderEffectMaterialKey::ShaderTypeCount; ++s) { + for (int i=0; i<uniformData[s].size(); ++i) { + if (s == typeToSkip && i == indexToSkip) + continue; + const QQuickShaderEffectMaterial::UniformData &d = uniformData[s][i]; + if (d.specialType == QQuickShaderEffectMaterial::UniformData::Sampler && qvariant_cast<QObject *>(d.value) == source) + return false; + } + } + return true; +} void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId, bool *textureProviderChanged) @@ -490,7 +503,13 @@ void QQuickShaderEffectCommon::propertyChanged(QQuickItem *item, int mappedId, if (source) { if (item->window()) QQuickItemPrivate::get(source)->derefWindow(); - QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*))); + + // QObject::disconnect() will disconnect all matching connections. If the same + // source has been attached to two separate samplers, then changing one of them + // would trigger both to be disconnected. Without the connection we'll end up + // with a dangling pointer in the uniformData. + if (qquick_uniqueInUniformData(source, uniformData, shaderType, index)) + QObject::disconnect(source, SIGNAL(destroyed(QObject*)), item, SLOT(sourceDestroyed(QObject*))); } d.value = item->property(d.name.constData()); diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index 98203c51e5..ebeff599f4 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -353,9 +353,9 @@ void QQuickShaderEffectTexture::grab() if (m_context->openglContext()->format().samples() <= 1) { m_multisampling = false; } else { - QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); - m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample") - && extensions.contains("GL_EXT_framebuffer_blit"); + const QSet<QByteArray> extensions = m_context->openglContext()->extensions(); + m_multisampling = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample")) + && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit")); } m_multisamplingChecked = true; } @@ -622,6 +622,8 @@ void QQuickShaderEffectSource::ensureTexture() connect(m_texture, SIGNAL(scheduledUpdateCompleted()), this, SIGNAL(scheduledUpdateCompleted())); } +static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::WrapMode *hWrap, QSGTexture::WrapMode *vWrap); + QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const { const QQuickItemPrivate *d = QQuickItemPrivate::get(this); @@ -634,6 +636,10 @@ QSGTextureProvider *QQuickShaderEffectSource::textureProvider() const const_cast<QQuickShaderEffectSource *>(this)->m_provider = new QQuickShaderEffectSourceTextureProvider(); const_cast<QQuickShaderEffectSource *>(this)->ensureTexture(); connect(m_texture, SIGNAL(updateRequested()), m_provider, SIGNAL(textureChanged())); + + get_wrap_mode(m_wrapMode, &m_provider->horizontalWrap, &m_provider->verticalWrap); + m_provider->mipmapFiltering = mipmap() ? QSGTexture::Linear : QSGTexture::None; + m_provider->filtering = smooth() ? QSGTexture::Linear : QSGTexture::Nearest; m_provider->sourceTexture = m_texture; } return m_provider; diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 7ee1c937c6..ad79f0eadf 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -1710,6 +1710,8 @@ void QQuickTextInput::geometryChanged(const QRectF &newGeometry, if (!d->inLayout) { if (newGeometry.width() != oldGeometry.width()) d->updateLayout(); + else if (newGeometry.height() != oldGeometry.height() && d->vAlign != QQuickTextInput::AlignTop) + d->updateBaselineOffset(); updateCursorRectangle(); } QQuickImplicitSizeItem::geometryChanged(newGeometry, oldGeometry); @@ -2855,20 +2857,33 @@ void QQuickTextInputPrivate::updateLayout() else q->setImplicitHeight(height); + updateBaselineOffset(); + if (previousSize != contentSize) + emit q->contentSizeChanged(); +} + +/*! + \internal + \brief QQuickTextInputPrivate::updateBaselineOffset + + Assumes contentSize.height() is already calculated. + */ +void QQuickTextInputPrivate::updateBaselineOffset() +{ + Q_Q(QQuickTextInput); + if (!q->isComponentComplete()) + return; QFontMetricsF fm(font); qreal yoff = 0; if (q->heightValid()) { - const qreal itemHeight = q->height(); + const qreal surplusHeight = q->height() - contentSize.height(); if (vAlign == QQuickTextInput::AlignBottom) - yoff = itemHeight - height; + yoff = surplusHeight; else if (vAlign == QQuickTextInput::AlignVCenter) - yoff = (itemHeight - height)/2; + yoff = surplusHeight/2; } q->setBaselineOffset(fm.ascent() + yoff); - - if (previousSize != contentSize) - emit q->contentSizeChanged(); } #ifndef QT_NO_CLIPBOARD diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 240fc7a599..21bd1bd6d7 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -423,6 +423,7 @@ public: void setCursorBlinkPeriod(int msec); void updateLayout(); + void updateBaselineOffset(); qreal getImplicitWidth() const; diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index f035e87d99..bbc4e8b55c 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -216,9 +216,11 @@ void QQuickWindow::exposeEvent(QExposeEvent *) } /*! \reimp */ -void QQuickWindow::resizeEvent(QResizeEvent *) +void QQuickWindow::resizeEvent(QResizeEvent *ev) { Q_D(QQuickWindow); + if (d->contentItem) + d->contentItem->setSize(ev->size()); if (d->windowManager) d->windowManager->resize(this); } @@ -258,23 +260,16 @@ void QQuickWindowPrivate::polishItems() { int maxPolishCycles = 100000; - int removedItems; - do { - removedItems = 0; + while (!itemsToPolish.isEmpty() && --maxPolishCycles > 0) { QSet<QQuickItem *> itms = itemsToPolish; + itemsToPolish.clear(); for (QSet<QQuickItem *>::iterator it = itms.begin(); it != itms.end(); ++it) { QQuickItem *item = *it; - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - - if (item->isVisible() || (itemPrivate->extra.isAllocated() && itemPrivate->extra->effectRefCount>0)) { - itemPrivate->polishScheduled = false; - itemsToPolish.remove(item); - item->updatePolish(); - ++removedItems; - } + QQuickItemPrivate::get(item)->polishScheduled = false; + item->updatePolish(); } - } while (removedItems > 0 && --maxPolishCycles > 0); + } if (maxPolishCycles == 0) qWarning("QQuickWindow: possible QQuickItem::polish() loop"); @@ -360,6 +355,8 @@ void QQuickWindowPrivate::syncSceneGraph() renderer->setClearMode(mode); renderer->setCustomRenderMode(customRenderMode); + + emit q->afterSynchronizing(); context->endSync(); } @@ -368,6 +365,9 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) { QML_MEMORY_SCOPE_STRING("SceneGraph"); Q_Q(QQuickWindow); + if (!renderer) + return; + animationController->advance(); emit q->beforeRendering(); int fboId = 0; @@ -435,6 +435,7 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) contentItemPrivate->window = q; contentItemPrivate->windowRefCount = 1; contentItemPrivate->flags |= QQuickItem::ItemIsFocusScope; + contentItem->setSize(q->size()); customRenderMode = qgetenv("QSG_VISUALIZE"); renderControl = control; @@ -476,24 +477,12 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) QQmlListProperty<QObject> QQuickWindowPrivate::data() { - initContentItem(); return QQmlListProperty<QObject>(q_func(), 0, QQuickWindowPrivate::data_append, QQuickWindowPrivate::data_count, QQuickWindowPrivate::data_at, QQuickWindowPrivate::data_clear); } -void QQuickWindowPrivate::initContentItem() -{ - Q_Q(QQuickWindow); - q->connect(q, SIGNAL(widthChanged(int)), - contentItem, SLOT(setWidth(int))); - q->connect(q, SIGNAL(heightChanged(int)), - contentItem, SLOT(setHeight(int))); - contentItem->setWidth(q->width()); - contentItem->setHeight(q->height()); -} - static QMouseEvent *touchToMouseEvent(QEvent::Type type, const QTouchEvent::TouchPoint &p, QTouchEvent *event, QQuickItem *item, bool transformNeeded = true) { // The touch point local position and velocity are not yet transformed. @@ -2679,6 +2668,17 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item) } +bool QQuickWindowPrivate::emitError(QQuickWindow::SceneGraphError error, const QString &msg) +{ + Q_Q(QQuickWindow); + static const QMetaMethod errorSignal = QMetaMethod::fromSignal(&QQuickWindow::sceneGraphError); + if (q->isSignalConnected(errorSignal)) { + emit q->sceneGraphError(error, msg); + return true; + } + return false; +} + void QQuickWindow::maybeUpdate() { Q_D(QQuickWindow); @@ -2754,6 +2754,21 @@ QOpenGLContext *QQuickWindow::openglContext() const */ /*! + \fn void QQuickWindow::sceneGraphError(SceneGraphError error, const QString &message) + + This signal is emitted when an error occurred during scene graph initialization. + + Applications should connect to this signal if they wish to handle errors, + like OpenGL context creation failures, in a custom way. When no slot is + connected to the signal, the behavior will be different: Quick will print + the message, or show a message box, and terminate the application. + + This signal will be emitted from the gui thread. + + \since 5.3 + */ + +/*! \class QQuickCloseEvent \internal \since 5.1 @@ -2987,6 +3002,20 @@ QQmlIncubationController *QQuickWindow::incubationController() const */ /*! + \enum QQuickWindow::SceneGraphError + + This enum describes the error in a sceneGraphError() signal. + + \value ContextNotAvailable OpenGL context creation failed. This typically means that + no suitable OpenGL implementation was found, for example because no graphics drivers + are installed and so no OpenGL 2 support is present. On mobile and embedded boards + that use OpenGL ES such an error is likely to indicate issues in the windowing system + integration and possibly an incorrect configuration of Qt. + + \since 5.3 + */ + +/*! \fn void QQuickWindow::beforeSynchronizing() This signal is emitted before the scene graph is synchronized with the QML state. @@ -3006,6 +3035,27 @@ QQmlIncubationController *QQuickWindow::incubationController() const */ /*! + \fn void QQuickWindow::afterSynchronizing() + + This signal is emitted after the scene graph is synchronized with the QML state. + + This signal can be used to do preparation required after calls to + QQuickItem::updatePaintNode(), while the GUI thread is still locked. + + The GL context used for rendering the scene graph will be bound at this point. + + \warning This signal is emitted from the scene graph rendering thread. If your + slot function needs to finish before execution continues, you must make sure that + the connection is direct (see Qt::ConnectionType). + + \warning Make very sure that a signal handler for afterSynchronizing leaves the GL + context in the same state as it was when the signal handler was entered. Failing to + do so can result in the scene not rendering properly. + + \since 5.3 + */ + +/*! \fn void QQuickWindow::beforeRendering() This signal is emitted before the scene starts rendering. @@ -3044,6 +3094,60 @@ QQmlIncubationController *QQuickWindow::incubationController() const do so can result in the scene not rendering properly. */ +/*! + \fn void QQuickWindow::afterAnimating() + + This signal is emitted on the gui thread before requesting the render thread to + perform the synchronization of the scene graph. + + Unlike the other similar signals, this one is emitted on the gui thread instead + of the render thread. It can be used to synchronize external animation systems + with the QML content. + + \since 5.3 + */ + +/*! + \fn void QQuickWindow::openglContextCreated(QOpenGLContext *context) + + This signal is emitted on the gui thread when the OpenGL \a context + for this window is created, before it is made current. + + Some implementations will share the same OpenGL context between + multiple QQuickWindow instances. The openglContextCreated() signal + will in this case only be emitted for the first window, when the + OpenGL context is actually created. + + QQuickWindow::openglContext() will still return 0 for this window + until after the QQuickWindow::sceneGraphInitialize() has been + emitted. + + \since 5.3 + */ + +/*! + \fn void QQuickWindow::sceneGraphAboutToStop() + + This signal is emitted on the render thread when the scene graph is + about to stop rendering. This happens usually because the window + has been hidden. + + Applications may use this signal to release resources, but should be + prepared to reinstantiated them again fast. The scene graph and the + OpenGL context are not released at this time. + + \warning This signal is emitted from the scene graph rendering thread. If your + slot function needs to finish before execution continues, you must make sure that + the connection is direct (see Qt::ConnectionType). + + \warning Make very sure that a signal handler for afterRendering() leaves the GL + context in the same state as it was when the signal handler was entered. Failing to + do so can result in the scene not rendering properly. + + \sa scenegraphInvalidated() + + \since 5.3 + */ /*! diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h index 233340d6fa..2572f31375 100644 --- a/src/quick/items/qquickwindow.h +++ b/src/quick/items/qquickwindow.h @@ -79,6 +79,11 @@ public: Q_DECLARE_FLAGS(CreateTextureOptions, CreateTextureOption) + enum SceneGraphError { + ContextNotAvailable = 1 + }; + Q_ENUMS(SceneGraphError) + QQuickWindow(QWindow *parent = 0); virtual ~QQuickWindow(); @@ -133,14 +138,21 @@ public: Q_SIGNALS: void frameSwapped(); + Q_REVISION(2) void openglContextCreated(QOpenGLContext *context); void sceneGraphInitialized(); void sceneGraphInvalidated(); void beforeSynchronizing(); + Q_REVISION(2) void afterSynchronizing(); void beforeRendering(); void afterRendering(); + Q_REVISION(2) void afterAnimating(); + Q_REVISION(2) void sceneGraphAboutToStop(); + Q_REVISION(1) void closing(QQuickCloseEvent *close); void colorChanged(const QColor &); Q_REVISION(1) void activeFocusItemChanged(); + Q_REVISION(2) void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message); + public Q_SLOTS: void update(); diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 5f61403a40..8b6073c30a 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -105,7 +105,6 @@ public: virtual ~QQuickWindowPrivate(); void init(QQuickWindow *, QQuickRenderControl *control = 0); - void initContentItem();//Currently only used if items added in QML QQuickRootItem *contentItem; QSet<QQuickItem *> parentlessItems; @@ -184,6 +183,8 @@ public: bool isRenderable() const; + bool emitError(QQuickWindow::SceneGraphError error, const QString &msg); + QQuickItem::UpdatePaintNodeData updatePaintNodeData; QQuickItem *dirtyItemList; @@ -199,6 +200,8 @@ public: void updateDirtyNode(QQuickItem *); void fireFrameSwapped() { Q_EMIT q_func()->frameSwapped(); } + void fireOpenGLContextCreated(QOpenGLContext *context) { Q_EMIT q_func()->openglContextCreated(context); } + void fireAboutToStop() { Q_EMIT q_func()->sceneGraphAboutToStop(); } QSGRenderContext *context; QSGRenderer *renderer; diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp index 44a4bf3db6..f6c32dcac3 100644 --- a/src/quick/items/qquickwindowmodule.cpp +++ b/src/quick/items/qquickwindowmodule.cpp @@ -149,6 +149,7 @@ void QQuickWindowModule::defineModule() qmlRegisterType<QQuickWindow>(uri, 2, 0, "Window"); qmlRegisterRevision<QWindow,1>(uri, 2, 1); qmlRegisterRevision<QQuickWindow,1>(uri, 2, 1);//Type moved to a subclass, but also has new members + qmlRegisterRevision<QQuickWindow,2>(uri, 2, 2); qmlRegisterType<QQuickWindowQmlImpl>(uri, 2, 1, "Window"); qmlRegisterUncreatableType<QQuickScreen>(uri, 2, 0, "Screen", QStringLiteral("Screen can only be used via the attached property.")); } |