From 0d31aa1617c96ed3e3624d77332ea6f13aba1492 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 23 Apr 2015 15:01:24 +0200 Subject: Avoid calling potentially pure virtual method In Qt 5.4 screenChanged is called indirectly from the destructor of QPlatformScreen. By comparing new values against the oldScreen we call call virtual methods of QPlatformScreen from it's own destructor which results in a crash. This patch simply emits change signals whenever a screen change regardless of whether the value differs from the previous screen. Arguably less efficient, but better than crashing. This fix is not needed in Qt 5.5 where the QPA architecture has changed. Task-number: QTBUG-45753 Change-Id: Ic155906928855a377add9b21bff9e72b31f4667e Reviewed-by: Alan Alpert --- src/quick/items/qquickscreen.cpp | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp index c4d1407697..0900adbb4b 100644 --- a/src/quick/items/qquickscreen.cpp +++ b/src/quick/items/qquickscreen.cpp @@ -347,24 +347,15 @@ void QQuickScreenAttached::screenChanged(QScreen *screen) emit orientationUpdateMaskChanged(); } - if (!oldScreen || screen->size() != oldScreen->size()) { - emit widthChanged(); - emit heightChanged(); - } - if (!oldScreen || screen->name() != oldScreen->name()) - emit nameChanged(); - if (!oldScreen || screen->orientation() != oldScreen->orientation()) - emit orientationChanged(); - if (!oldScreen || screen->primaryOrientation() != oldScreen->primaryOrientation()) - emit primaryOrientationChanged(); - if (!oldScreen || screen->availableVirtualGeometry() != oldScreen->availableVirtualGeometry()) - emit desktopGeometryChanged(); - if (!oldScreen || screen->logicalDotsPerInch() != oldScreen->logicalDotsPerInch()) - emit logicalPixelDensityChanged(); - if (!oldScreen || screen->physicalDotsPerInch() != oldScreen->physicalDotsPerInch()) - emit pixelDensityChanged(); - if (!oldScreen || screen->devicePixelRatio() != oldScreen->devicePixelRatio()) - emit devicePixelRatioChanged(); + emit widthChanged(); + emit heightChanged(); + emit nameChanged(); + emit orientationChanged(); + emit primaryOrientationChanged(); + emit desktopGeometryChanged(); + emit logicalPixelDensityChanged(); + emit pixelDensityChanged(); + emit devicePixelRatioChanged(); connect(screen, SIGNAL(geometryChanged(QRect)), this, SIGNAL(widthChanged())); -- cgit v1.2.3 From e3f56a8b8d749f9eb4816ee7f6355f59dac173e6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 16 Apr 2015 15:56:33 +0200 Subject: Fix rendercontrol example for screens with different dpr renderWindow() was not reimplemented in the example. This is pretty bad since renderWindowFor() fails to find a window and thus falls back to using the default device pixel ratio (which is the highest dpr present in the system). The result is broken content from Quick because it operates with a dpr of 2 any time a retina screen is connected, even when the example's own QWindow is placed on a normal screen. Add also a note to the QQuickRenderControl docs because it is easy to overlook. Task-number: QTBUG-45613 Change-Id: I31bf92ec285f3d9867a5604a4b4e3bea73791932 Reviewed-by: Gunnar Sletta --- src/quick/items/qquickrendercontrol.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp index e1ca662277..fd4787be98 100644 --- a/src/quick/items/qquickrendercontrol.cpp +++ b/src/quick/items/qquickrendercontrol.cpp @@ -367,6 +367,11 @@ void QQuickRenderControlPrivate::maybeUpdate() If \a offset in non-null, it is set to the offset of the control inside the window. + + \note While not mandatory, reimplementing this function becomes essential for + supporting multiple screens with different device pixel ratios and properly positioning + popup windows opened from QML. Therefore providing it in subclasses is highly + recommended. */ /*! -- cgit v1.2.3 From e38f5e9cb1430c2bd1095f566ed752d36eed0029 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Mon, 27 Apr 2015 13:23:05 +0200 Subject: Doc: Fix linking issues in Item QML type documentation Use explicit link commands as QDoc cannot create links to single-word QML type names automatically. Task-number: QTBUG-45827 Change-Id: I048300728356d3ae9901c5c57febc683137ce090 Reviewed-by: Martin Smith --- src/quick/items/qquickitem.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 4d1bb696fa..07d7636abf 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4244,7 +4244,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const This method sets focus on the item and ensures that all ancestor FocusScope objects in the object hierarchy are also given \l focus. - The reason for the focus change will be \a Qt::OtherFocusReason. Use + The reason for the focus change will be \l [CPP] Qt::OtherFocusReason. Use the overloaded method to specify the focus reason to enable better handling of the focus change. @@ -6105,7 +6105,7 @@ qreal QQuickItem::implicitWidth() const Defines the natural width or height of the Item if no \l width or \l height is specified. The default implicit size for most items is 0x0, however some items have an inherent - implicit size which cannot be overridden, e.g. Image, Text. + implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text. Setting the implicit size is useful for defining components that have a preferred size based on their content, for example: @@ -6129,7 +6129,7 @@ qreal QQuickItem::implicitWidth() const } \endqml - \b Note: using implicitWidth of Text or TextEdit and setting the width explicitly + \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly incurs a performance penalty as the text must be laid out twice. */ /*! @@ -6139,7 +6139,7 @@ qreal QQuickItem::implicitWidth() const Defines the natural width or height of the Item if no \l width or \l height is specified. The default implicit size for most items is 0x0, however some items have an inherent - implicit size which cannot be overridden, e.g. Image, Text. + implicit size which cannot be overridden, for example, \l [QML] Image and \l [QML] Text. Setting the implicit size is useful for defining components that have a preferred size based on their content, for example: @@ -6163,7 +6163,7 @@ qreal QQuickItem::implicitWidth() const } \endqml - \b Note: using implicitWidth of Text or TextEdit and setting the width explicitly + \note Using implicitWidth of \l [QML] Text or \l [QML] TextEdit and setting the width explicitly incurs a performance penalty as the text must be laid out twice. */ void QQuickItem::setImplicitWidth(qreal w) -- cgit v1.2.3 From a6fb18f1865aff8b96dfba1e341019371b5fa9f2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 28 Apr 2015 16:53:37 +0200 Subject: Fix uninitialized variables/data * Initialize the indexOfRootObject member * When creating the QV4::CompiledData::String objects, don't include the one ushort _beyond_ the QString, which is random data. Change-Id: I8fe8a465e2713a385504f217b367a62b70ee5fdf Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 1 + src/qml/compiler/qv4compileddata_p.h | 2 +- src/qml/compiler/qv4compiler.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index e5d97341b9..c645a29b15 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -290,6 +290,7 @@ void Document::removeScriptPragmas(QString &script) Document::Document(bool debugMode) : jsModule(debugMode) , program(0) + , indexOfRootObject(0) , jsGenerator(&jsModule) , unitFlags(0) { diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index f46e27fe98..48324fbbc4 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -135,7 +135,7 @@ struct String // uint16 strdata[] static int calculateSize(const QString &str) { - return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7; + return (sizeof(String) + str.length() * sizeof(quint16) + 7) & ~0x7; } }; diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 285c0070ef..450889c275 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -78,7 +78,7 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit) QV4::CompiledData::String *s = (QV4::CompiledData::String*)(stringData); s->flags = 0; // ### s->size = qstr.length(); - memcpy(s + 1, qstr.constData(), (qstr.length() + 1)*sizeof(ushort)); + memcpy(s + 1, qstr.constData(), qstr.length()*sizeof(ushort)); stringData += QV4::CompiledData::String::calculateSize(qstr); } -- cgit v1.2.3 From 2fdb6eba0a58b629db32f9eefec2f26df08d3d2e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 30 Apr 2015 13:20:43 +0200 Subject: Fix passing of locals as function arguments with side-effects Commit 75c22465cf8fe262edfe6178bb9ca19661fb710e regressed in allowing locals and arguments to be passed directly as further arguments to function calls, but that's incorrect when considering var i = 2; testFunction(i, i += 2) where it is instrumental to place the first argument into a temp (making a copy) instead of passing it directly. Change-Id: Iffcf6c6eda92a8fb665982cda1db0b96359cd092 Task-number: QTBUG-45879 Reviewed-by: Lars Knoll --- src/qml/compiler/qv4codegen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index a7b5326861..260db0f0dd 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -538,7 +538,7 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index) IR::Expr *Codegen::argument(IR::Expr *expr) { - if (expr && !expr->asTemp() && !expr->asArgLocal()) { + if (expr && !expr->asTemp()) { const unsigned t = _block->newTemp(); move(_block->TEMP(t), expr); expr = _block->TEMP(t); -- cgit v1.2.3 From b999aaaf4e3f4069fb57e016cfa7461eb15e0992 Mon Sep 17 00:00:00 2001 From: Jan Arne Petersen Date: Tue, 13 Jan 2015 11:23:10 +0100 Subject: Create QOpenGLContext with the correct screen Change-Id: I91169e719ac97b8e32805e08d6a1f43caa897f73 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index 26a0e78254..f9f973fe2a 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -906,6 +906,7 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) if (qt_gl_global_share_context()) w->thread->gl->setShareContext(qt_gl_global_share_context()); w->thread->gl->setFormat(w->window->requestedFormat()); + w->thread->gl->setScreen(w->window->screen()); if (!w->thread->gl->create()) { const bool isEs = w->thread->gl->isOpenGLES(); delete w->thread->gl; -- cgit v1.2.3 From 6c1d99c2490e1af5c42d03cf10e8fe4d2e30c025 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 28 Apr 2015 16:03:07 +0200 Subject: Fix default value for XMLHttpRequest.response property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default value for responseType is the empty string, for which the expected data type for the response property is a string - same as when the response type is set to "text". In other words: By default the response property should contain the string representation of the data. Task-number: QTBUG-45862 Change-Id: I563160e5cdfbf93aca7e283e455d77a6b9deceb4 Reviewed-by: Pasi Keränen Reviewed-by: Valery Kotov Reviewed-by: Lars Knoll --- src/qml/qml/qqmlxmlhttprequest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index a2c5f09061..2a3ede6a22 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -1982,7 +1982,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx) return QV4::Encode(scope.engine->newString(QString())); const QString& responseType = r->responseType(); - if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0) { + if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) { return QV4::Encode(scope.engine->newString(r->responseBody())); } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) { return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody())); -- cgit v1.2.3 From 38621d841cfa75b1d849b0e88b38c2f18a0611ac Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 28 Apr 2015 07:45:28 +0200 Subject: Avoid QQuickItem in materials's compare() on the render thread Task-number: QTBUG-44664 Change-Id: I4438e666b75fdf2e8d4353e64454d4c665a24350 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickshadereffectnode.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index e593112ef5..6415c0ad22 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -381,11 +381,10 @@ bool QQuickShaderEffectMaterial::UniformData::operator == (const UniformData &ot return false; if (specialType == UniformData::Sampler) { - QQuickItem *source = qobject_cast(qvariant_cast(value)); - QQuickItem *otherSource = qobject_cast(qvariant_cast(other.value)); - if (!source || !otherSource || !source->isTextureProvider() || !otherSource->isTextureProvider()) - return false; - return source->textureProvider()->texture()->textureId() == otherSource->textureProvider()->texture()->textureId(); + // We can't check the source objects as these live in the GUI thread, + // so return true here and rely on the textureProvider check for + // equality of these.. + return true; } else { return value == other.value; } @@ -402,6 +401,23 @@ int QQuickShaderEffectMaterial::compare(const QSGMaterial *o) const if (uniforms[shaderType] != other->uniforms[shaderType]) return 1; } + + // Check the texture providers.. + if (textureProviders.size() != other->textureProviders.size()) + return 1; + for (int i=0; itextureProviders.at(i); + if (!tp1 || !tp2) + return tp1 == tp2 ? 0 : 1; + QSGTexture *t1 = tp1->texture(); + QSGTexture *t2 = tp2->texture(); + if (!t1 || !t2) + return t1 == t2 ? 0 : 1; + // Check texture id's as textures may be in the same atlas. + if (t1->textureId() != t2->textureId()) + return 1; + } return 0; } -- cgit v1.2.3 From 705c2bf4e5c71e4d31a387ed85e205962a344580 Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 23 Apr 2015 21:29:47 +1000 Subject: Fix implicitHeight for Text items bindings dependent on implicitWidth. Recalculate the implicitHeight on the second layout if the width changes after setting the implicitWidth, and potentially do another layout if the updating the implicitHeight changes the height. Change-Id: Ib6a637452013b56dba7ae8a6862cd92156386578 Task-number: QTBUG-45546 Reviewed-by: Michael Brasser Reviewed-by: Albert Astals Cid Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/items/qquicktext.cpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index c1794697a5..456ec25edd 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -749,6 +749,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) : largeFont; int scaledFontSize = largeFont; + bool widthChanged = false; widthExceeded = q->width() <= 0 && (singlelineElide || canWrap || horizontalFit); heightExceeded = q->height() <= 0 && (multilineElide || verticalFit); @@ -945,6 +946,7 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) if ((lineWidth < qMin(oldWidth, naturalWidth) || (widthExceeded && lineWidth > oldWidth)) && (singlelineElide || multilineElide || canWrap || horizontalFit || q->effectiveHAlign() != QQuickText::AlignLeft)) { + widthChanged = true; widthExceeded = false; heightExceeded = false; continue; @@ -966,6 +968,39 @@ QRectF QQuickTextPrivate::setupTextLayout(qreal *const baseline) heightExceeded = false; continue; } + } else if (widthChanged) { + widthChanged = false; + if (line.isValid()) { + for (int lineCount = layout.lineCount(); lineCount < maxLineCount; ++lineCount) { + line = layout.createLine(); + if (!line.isValid()) + break; + setLineGeometry(line, lineWidth, naturalHeight); + } + } + layout.endLayout(); + + bool wasInLayout = internalWidthUpdate; + internalWidthUpdate = true; + q->setImplicitHeight(naturalHeight); + internalWidthUpdate = wasInLayout; + + multilineElide = elideMode == QQuickText::ElideRight + && q->widthValid() + && (q->heightValid() || maximumLineCountValid); + verticalFit = fontSizeMode() & QQuickText::VerticalFit + && (q->heightValid() || (maximumLineCountValid && canWrap)); + + const qreal oldHeight = maxHeight; + maxHeight = q->heightValid() ? q->height() : FLT_MAX; + // If the height of the item has changed and it's possible the result of eliding, + // line count truncation or scaling has changed, do another layout. + if ((maxHeight < qMin(oldHeight, naturalHeight) || (heightExceeded && maxHeight > oldHeight)) + && (multilineElide || (canWrap && maximumLineCountValid))) { + widthExceeded = false; + heightExceeded = false; + continue; + } } else { layout.endLayout(); } -- cgit v1.2.3 From b59e605b4d2f3c17b8bee0322ba156f990403d2d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 5 May 2015 09:36:31 +0200 Subject: QQuickWindow: Replace assert() on unreleased touch points by warning. Output a warning message and clear QQuickWindowPrivate::itemForTouchPointId should unreleased touch points exist when QEvent::TouchEnd is received. Task-number: QTBUG-45856 Change-Id: I8a05220e4258c0ca401f79a2c32ec4f1d43fa444 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickwindow.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index bccebb1a14..0b1c79567f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1989,7 +1989,12 @@ void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event) } if (event->type() == QEvent::TouchEnd) { - Q_ASSERT(itemForTouchPointId.isEmpty()); + if (!itemForTouchPointId.isEmpty()) { + qWarning() << "No release received for" << itemForTouchPointId.size() + << "touch points over" << itemForTouchPointId.begin().value() + << "on touch end."; + itemForTouchPointId.clear(); + } } --touchRecursionGuard; -- cgit v1.2.3 From 45212181e0510eb94f67329731fd6574a6abe3f5 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 5 May 2015 11:45:31 +0200 Subject: Enhance QQuickFramebufferObject docs regarding the state Add a note about resetOpenGLState() and the initial state to render(). This tries to tackle the common issue of forgetting to set or reset the state the custom OpenGL code relies on. Change-Id: I706b2b1eac76468a9b35cfb7cd99bd5483f2912c Reviewed-by: Gunnar Sletta --- src/quick/items/qquickframebufferobject.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/quick/items/qquickframebufferobject.cpp b/src/quick/items/qquickframebufferobject.cpp index 758727ed9e..c3e5b97baf 100644 --- a/src/quick/items/qquickframebufferobject.cpp +++ b/src/quick/items/qquickframebufferobject.cpp @@ -386,6 +386,17 @@ QOpenGLFramebufferObject *QQuickFramebufferObject::Renderer::framebufferObject() * the FBO size. * * The FBO will be automatically unbound after the function returns. + * + * \note Do not assume that the OpenGL state is all set to the defaults when + * this function is invoked, or that it is maintained between calls. Both the Qt + * Quick renderer and the custom rendering code uses the same OpenGL + * context. This means that the state might have been modified by Quick before + * invoking this function. + * + * \note It is recommended to call QQuickWindow::resetOpenGLState() before + * returning. This resets OpenGL state used by the Qt Quick renderer and thus + * avoids interference from the state changes made by the rendering code in this + * function. */ /*! -- cgit v1.2.3 From d0dc7cec78e182f04726c5a2adade80dc2983bcf Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Thu, 6 Nov 2014 11:30:45 -0800 Subject: BorderImage support for @2x assets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Despite being a subclass of QQuickImageBase, BorderImage components did not support using @2x assets like Image components. The 9 patch image logic now accounts for device pixel ratio when needed. Manual tests added for stretch, repeat and round tiling modes. [ChangeLog][BorderImage] Add support for @2x HiDPI border images. This means, no more need to multiply the border sizes by the device pixel ratio. Change-Id: I79958739929964c816ba5dacedd9eaf93a60a183 Reviewed-by: Gabriel de Dietrich Reviewed-by: Morten Johan Sørvig --- src/quick/items/qquickborderimage.cpp | 71 +++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index fc3548053c..f345a77e15 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -321,7 +322,13 @@ void QQuickBorderImage::load() if (d->cache) options |= QQuickPixmap::Cache; d->pix.clear(this); - d->pix.load(qmlEngine(this), d->url, options); + + const qreal targetDevicePixelRatio = (window() ? window()->effectiveDevicePixelRatio() : qGuiApp->devicePixelRatio()); + d->devicePixelRatio = 1.0; + + QUrl loadUrl = d->url; + resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio); + d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options); if (d->pix.isLoading()) { if (d->progress != 0.0) { @@ -329,8 +336,19 @@ void QQuickBorderImage::load() emit progressChanged(d->progress); } d->status = Loading; - d->pix.connectFinished(this, SLOT(requestFinished())); - d->pix.connectDownloadProgress(this, SLOT(requestProgress(qint64,qint64))); + + static int thisRequestProgress = -1; + static int thisRequestFinished = -1; + if (thisRequestProgress == -1) { + thisRequestProgress = + QQuickImageBase::staticMetaObject.indexOfSlot("requestProgress(qint64,qint64)"); + thisRequestFinished = + QQuickImageBase::staticMetaObject.indexOfSlot("requestFinished()"); + } + d->pix.connectFinished(this, thisRequestFinished); + d->pix.connectDownloadProgress(this, thisRequestProgress); + + update(); //pixmap may have invalidated texture, updatePaintNode needs to be called before the next repaint } else { requestFinished(); return; @@ -495,7 +513,7 @@ void QQuickBorderImage::requestFinished() } } - setImplicitSize(impsize.width(), impsize.height()); + setImplicitSize(impsize.width() / d->devicePixelRatio, impsize.height() / d->devicePixelRatio); emit statusChanged(d->status); if (sourceSize() != d->oldSourceSize) { d->oldSourceSize = sourceSize(); @@ -569,40 +587,29 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat QRectF innerTargetRect = targetRect; if (d->border) { const QQuickScaleGrid *border = d->getScaleGrid(); - innerSourceRect = QRectF(border->left() / qreal(d->pix.width()), - border->top() / qreal(d->pix.height()), - qMax(0, d->pix.width() - border->right() - border->left()) / d->pix.width(), - qMax(0, d->pix.height() - border->bottom() - border->top()) / d->pix.height()); + innerSourceRect = QRectF(border->left() * d->devicePixelRatio / qreal(d->pix.width()), + border->top() * d->devicePixelRatio / qreal(d->pix.height()), + qMax(0, d->pix.width() - (border->right() + border->left()) * d->devicePixelRatio) / d->pix.width(), + qMax(0, d->pix.height() - (border->bottom() + border->top()) * d->devicePixelRatio) / d->pix.height()); innerTargetRect = QRectF(border->left(), border->top(), - qMax(0, width() - border->right() - border->left()), - qMax(0, height() - border->bottom() - border->top())); + qMax(0, width() - (border->right() + border->left())), + qMax(0, height() - (border->bottom() + border->top()))); } qreal hTiles = 1; qreal vTiles = 1; - if (innerSourceRect.width() != 0) { - switch (d->horizontalTileMode) { - case QQuickBorderImage::Repeat: - hTiles = innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width()); - break; - case QQuickBorderImage::Round: - hTiles = qCeil(innerTargetRect.width() / qreal(innerSourceRect.width() * d->pix.width())); - break; - default: - break; - } + const QSizeF innerTargetSize = innerTargetRect.size() * d->devicePixelRatio; + if (innerSourceRect.width() != 0 + && d->horizontalTileMode != QQuickBorderImage::Stretch) { + hTiles = innerTargetSize.width() / qreal(innerSourceRect.width() * d->pix.width()); + if (d->horizontalTileMode == QQuickBorderImage::Round) + hTiles = qCeil(hTiles); } - if (innerSourceRect.height() != 0) { - switch (d->verticalTileMode) { - case QQuickBorderImage::Repeat: - vTiles = innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height()); - break; - case QQuickBorderImage::Round: - vTiles = qCeil(innerTargetRect.height() / qreal(innerSourceRect.height() * d->pix.height())); - break; - default: - break; - } + if (innerSourceRect.height() != 0 + && d->verticalTileMode != QQuickBorderImage::Stretch) { + vTiles = innerTargetSize.height() / qreal(innerSourceRect.height() * d->pix.height()); + if (d->verticalTileMode == QQuickBorderImage::Round) + vTiles = qCeil(vTiles); } node->setTargetRect(targetRect); -- cgit v1.2.3 From 3b5d37ce3841c4bfdf1c629d33f0e33b881b47fb Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 28 Apr 2015 15:38:09 +0200 Subject: Fix memory corruption when multiple QML engines have JavaScript wrappers for the same QObject It's possible that the same QObject is exposed to multiple JavaScript environments, for which we have this "extra" hack in the form of a QMap. The common case is that QQmlData has a QV4::WeakValue that points to the JS wrapper for the object. However in the rare case of multiple exposure, a map in the other engines stores those references. That map was erroneously storing pointers to temporary values on the JS stack instead of heap pointers. Change-Id: I8587f9921a9b4f9efd288326d00cebc25ad0bc12 Task-number: QTBUG-45051 Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4mm.cpp | 2 +- src/qml/jsruntime/qv4qobjectwrapper.cpp | 22 +++++++++++++--------- src/qml/jsruntime/qv4qobjectwrapper_p.h | 18 +++++++++--------- src/qml/qml/qqmldata_p.h | 4 ++-- 4 files changed, 25 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp index 07408a343c..d5576b400a 100644 --- a/src/qml/jsruntime/qv4mm.cpp +++ b/src/qml/jsruntime/qv4mm.cpp @@ -390,7 +390,7 @@ void MemoryManager::sweep(bool lastSweep) if (MultiplyWrappedQObjectMap *multiplyWrappedQObjects = m_d->engine->m_multiplyWrappedQObjects) { for (MultiplyWrappedQObjectMap::Iterator it = multiplyWrappedQObjects->begin(); it != multiplyWrappedQObjects->end();) { - if (!it.value()->markBit()) + if (!it.value().isNullOrUndefined()) it = multiplyWrappedQObjects->erase(it); else ++it; diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 50efff001d..353f4023ca 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -589,7 +589,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) } else if (ddata->jsWrapper.isUndefined() && (ddata->jsEngineId == engine->m_engineId || // We own the QObject ddata->jsEngineId == 0 || // No one owns the QObject - !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted + !ddata->hasTaintedV4Object)) { // Someone else has used the QObject, but it isn't tainted QV4::ScopedValue rv(scope, create(engine, object)); ddata->jsWrapper.set(scope.engine, rv); @@ -600,11 +600,11 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) // If this object is tainted, we have to check to see if it is in our // tainted object list ScopedObject alternateWrapper(scope, (Object *)0); - if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV8Object) + if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object) alternateWrapper = engine->m_multiplyWrappedQObjects->value(object); // If our tainted handle doesn't exist or has been collected, and there isn't - // a handle in the ddata, we can assume ownership of the ddata->v8object + // a handle in the ddata, we can assume ownership of the ddata->jsWrapper if (ddata->jsWrapper.isUndefined() && !alternateWrapper) { QV4::ScopedValue result(scope, create(engine, object)); ddata->jsWrapper.set(scope.engine, result); @@ -616,8 +616,8 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) alternateWrapper = create(engine, object); if (!engine->m_multiplyWrappedQObjects) engine->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap; - engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper); - ddata->hasTaintedV8Object = true; + engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper->d()); + ddata->hasTaintedV4Object = true; } return alternateWrapper.asReturnedValue(); @@ -1908,16 +1908,20 @@ Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject * DEFINE_OBJECT_VTABLE(QmlSignalHandler); -void MultiplyWrappedQObjectMap::insert(QObject *key, Object *value) +void MultiplyWrappedQObjectMap::insert(QObject *key, Heap::Object *value) { - QHash::insert(key, value); + QV4::WeakValue v; + v.set(value->internalClass->engine, value); + QHash::insert(key, v); connect(key, SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*))); } + + MultiplyWrappedQObjectMap::Iterator MultiplyWrappedQObjectMap::erase(MultiplyWrappedQObjectMap::Iterator it) { disconnect(it.key(), SIGNAL(destroyed(QObject*)), this, SLOT(removeDestroyedObject(QObject*))); - return QHash::erase(it); + return QHash::erase(it); } void MultiplyWrappedQObjectMap::remove(QObject *key) @@ -1930,7 +1934,7 @@ void MultiplyWrappedQObjectMap::remove(QObject *key) void MultiplyWrappedQObjectMap::removeDestroyedObject(QObject *object) { - QHash::remove(object); + QHash::remove(object); } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 1b41ca65c1..5d2378018c 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -173,20 +173,20 @@ struct QmlSignalHandler : public QV4::Object }; class MultiplyWrappedQObjectMap : public QObject, - private QHash + private QHash { Q_OBJECT public: - typedef QHash::ConstIterator ConstIterator; - typedef QHash::Iterator Iterator; + typedef QHash::ConstIterator ConstIterator; + typedef QHash::Iterator Iterator; - ConstIterator begin() const { return QHash::constBegin(); } - Iterator begin() { return QHash::begin(); } - ConstIterator end() const { return QHash::constEnd(); } - Iterator end() { return QHash::end(); } + ConstIterator begin() const { return QHash::constBegin(); } + Iterator begin() { return QHash::begin(); } + ConstIterator end() const { return QHash::constEnd(); } + Iterator end() { return QHash::end(); } - void insert(QObject *key, Object *value); - Object *value(QObject *key) const { return QHash::value(key, 0); } + void insert(QObject *key, Heap::Object *value); + ReturnedValue value(QObject *key) const { return QHash::value(key).value(); } Iterator erase(Iterator it); void remove(QObject *key); diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h index c7654be545..04c42b638d 100644 --- a/src/qml/qml/qqmldata_p.h +++ b/src/qml/qml/qqmldata_p.h @@ -74,7 +74,7 @@ class Q_QML_PRIVATE_EXPORT QQmlData : public QAbstractDeclarativeData public: QQmlData() : ownedByQml1(false), ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false), - hasTaintedV8Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), + hasTaintedV4Object(false), isQueuedForDeletion(false), rootObjectInCreation(false), hasVMEMetaObject(false), parentFrozen(false), bindingBitsSize(0), bindingBits(0), notifyList(0), context(0), outerContext(0), bindings(0), signalHandlers(0), nextContextObject(0), prevContextObject(0), lineNumber(0), columnNumber(0), jsEngineId(0), compiledData(0), deferredData(0), @@ -112,7 +112,7 @@ public: quint32 ownContext:1; quint32 indestructible:1; quint32 explicitIndestructibleSet:1; - quint32 hasTaintedV8Object:1; + quint32 hasTaintedV4Object:1; quint32 isQueuedForDeletion:1; /* * rootObjectInCreation should be true only when creating top level CPP and QML objects, -- cgit v1.2.3 From c415e6972b371acc288cd835f5635936215c615f Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 5 May 2015 10:52:34 +0200 Subject: Fix memory corruption in array handling SimpleArrayData's markObjects() implementation did not mark the entries correctly. When the dequeue offset was non-zero, we would end up marking values that may have been garbage collected earlier. Task-number: QTBUG-45888 Change-Id: Iacec350ccc76399ad4d16138af50acf22b2809db Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4arraydata.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 737c891f9b..afcfa00905 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -216,9 +216,8 @@ void ArrayData::ensureAttributes(Object *o) void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e) { Heap::SimpleArrayData *dd = static_cast(d); - uint l = dd->len; - for (uint i = 0; i < l; ++i) - dd->arrayData[i].mark(e); + for (uint i = 0; i < dd->len; ++i) + dd->arrayData[dd->mappedIndex(i)].mark(e); } ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index) -- cgit v1.2.3 From c31d6e946d700bb404fdcadaba11ac45c714d60d Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 5 May 2015 13:14:36 +0200 Subject: Avoid uninitialized bytes in QV4::CompiledData When populating the QV4::CompiledData for a JS unit, we memset the malloc'ed data to zero. We should do the same when creating a unit for QML files. We do write all the fields that we use, but due to padding we may end up with bytes that are neither used nor written but still uninitialized. Consequently they should be zero'ed, otherwise serialization will write garbage. Change-Id: I0b093e4dde6789d7236247507221f4f3476ba89d Reviewed-by: Lars Knoll --- src/qml/compiler/qqmlirbuilder.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index c645a29b15..63833504f1 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -1319,6 +1319,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output) const int totalSize = unitSize + importSize + objectOffsetTableSize + objectsSize + output.jsGenerator.stringTable.sizeOfTableAndData(); char *data = (char*)malloc(totalSize); memcpy(data, jsUnit, unitSize); + memset(data + unitSize, 0, totalSize - unitSize); if (jsUnit != compilationUnit->data) free(jsUnit); jsUnit = 0; -- cgit v1.2.3 From 889f717fc57ea9881ca250b8230742633c1ed5a2 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 7 May 2015 16:22:24 +0200 Subject: Fix memory corruption when sharing QObjects between different QML engines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When marking the JS wrappers for QObject manually, we cannot use ddata->jsWrapper directly but we must respect the case where the same object is exposed to different engines and then we must mark the wrapper that belongs to the engine that is currently collecting garbage. Change-Id: If82883c762ccaf3431e7074243ff2ff703234d66 Task-number: QTBUG-44895 Reviewed-by: Marco Martin Reviewed-by: Jan Kundrát Reviewed-by: Lars Knoll Reviewed-by: Aleix Pol Gonzalez --- src/qml/jsruntime/qv4qobjectwrapper.cpp | 27 ++++++++++++++++++++++++--- src/qml/jsruntime/qv4qobjectwrapper_p.h | 2 ++ src/qml/qml/qqmlvmemetaobject.cpp | 13 +++++++------ src/quick/items/qquickitem.cpp | 4 +--- 4 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 353f4023ca..1e4718c208 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -624,6 +624,21 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object) } } +void QObjectWrapper::markWrapper(QObject *object, ExecutionEngine *engine) +{ + if (QQmlData::wasDeleted(object)) + return; + + QQmlData *ddata = QQmlData::get(object); + if (!ddata) + return; + + if (ddata->jsEngineId == engine->m_engineId) + ddata->jsWrapper.markOnce(engine); + else if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV4Object) + engine->m_multiplyWrappedQObjects->mark(object, engine); +} + ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired) { if (QQmlData::wasDeleted(object)) @@ -993,9 +1008,7 @@ static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine * QObject *child = children.at(i); if (!child) continue; - QQmlData *ddata = QQmlData::get(child, /*create*/false); - if (ddata) - ddata->jsWrapper.markOnce(e); + QObjectWrapper::markWrapper(child, e); markChildQObjectsRecursively(child, e); } } @@ -1932,6 +1945,14 @@ void MultiplyWrappedQObjectMap::remove(QObject *key) erase(it); } +void MultiplyWrappedQObjectMap::mark(QObject *key, ExecutionEngine *engine) +{ + Iterator it = find(key); + if (it == end()) + return; + it->markOnce(engine); +} + void MultiplyWrappedQObjectMap::removeDestroyedObject(QObject *object) { QHash::remove(object); diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index 5d2378018c..24e8b29e08 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -110,6 +110,7 @@ struct Q_QML_EXPORT QObjectWrapper : public Object static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const Value &value); static ReturnedValue wrap(ExecutionEngine *engine, QObject *object); + static void markWrapper(QObject *object, ExecutionEngine *engine); using Object::get; @@ -189,6 +190,7 @@ public: ReturnedValue value(QObject *key) const { return QHash::value(key).value(); } Iterator erase(Iterator it); void remove(QObject *key); + void mark(QObject *key, ExecutionEngine *engine); private Q_SLOTS: void removeDestroyedObject(QObject*); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 37ff696579..5b1be15869 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -1227,6 +1227,11 @@ void QQmlVMEMetaObject::ensureQObjectWrapper() void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) { + QQmlEnginePrivate *ep = (ctxt == 0 || ctxt->engine == 0) ? 0 : QQmlEnginePrivate::get(ctxt->engine); + QV4::ExecutionEngine *v4 = (ep == 0) ? 0 : ep->v4engine(); + if (v4 != e) + return; + varProperties.markOnce(e); // add references created by VMEVariant properties @@ -1234,12 +1239,8 @@ void QQmlVMEMetaObject::mark(QV4::ExecutionEngine *e) for (int ii = 0; ii < maxDataIdx; ++ii) { // XXX TODO: optimize? if (data[ii].dataType() == QMetaType::QObjectStar) { // possible QObject reference. - QObject *ref = data[ii].asQObject(); - if (ref) { - QQmlData *ddata = QQmlData::get(ref); - if (ddata) - ddata->jsWrapper.markOnce(e); - } + if (QObject *ref = data[ii].asQObject()) + QV4::QObjectWrapper::markWrapper(ref, e); } } diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 07d7636abf..3d0f550d14 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -6740,9 +6740,7 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e) { Q_Q(QQuickItem); - QQmlData *ddata = QQmlData::get(q); - if (ddata) - ddata->jsWrapper.markOnce(e); + QV4::QObjectWrapper::markWrapper(q, e); foreach (QQuickItem *child, childItems) QQuickItemPrivate::get(child)->markObjects(e); -- cgit v1.2.3 From a690648c215128d6e0ffe709be08a334f39554e0 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 8 May 2015 12:34:53 +0200 Subject: Add protection against "wrong" marking in debug builds To protect against situations where we accidentally mark an object that belongs to a different engine - there are many possible entry points - this patch adds an assertion in debug builds for this situation. When it happens, it will point more or less directly to the code that tries to push an object to the wrong JS stack for marking. This helped in the investigation of QTBUG-44895 Change-Id: I311b9ff6d282d52e725044b03a62cd77085536be Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4engine.cpp | 9 +++++++++ src/qml/jsruntime/qv4engine_p.h | 7 +++++++ 2 files changed, 16 insertions(+) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index a247f85761..92993259ec 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1623,6 +1623,15 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) return 0; } +#ifndef QT_NO_DEBUG +void ExecutionEngine::assertObjectBelongsToEngine(const Value &v) +{ + if (!v.isObject()) + return; + Q_ASSERT(v.objectValue()->engine() == this); +} +#endif + // Converts a JS value to a meta-type. // data must point to a place that can store a value of the given type. // Returns true if conversion succeeded, false otherwise. diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index f01579be71..277cbdf1f5 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -340,6 +340,10 @@ public: bool metaTypeFromJS(const Value &value, int type, void *data); QV4::ReturnedValue metaTypeToJS(int type, const void *data); +#ifndef QT_NO_DEBUG + void assertObjectBelongsToEngine(const Value &v); +#endif + private: QmlExtensions *m_qmlExtensions; }; @@ -381,6 +385,9 @@ void Managed::mark(QV4::ExecutionEngine *engine) Q_ASSERT(inUse()); if (markBit()) return; +#ifndef QT_NO_DEBUG + engine->assertObjectBelongsToEngine(*this); +#endif d()->setMarkBit(); engine->pushForGC(d()); } -- cgit v1.2.3 From 0f61aa5efe1c12337f3ab753c08e70d6eaf6c2ab Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 11 May 2015 11:34:08 +0200 Subject: Add QtQuick::Text::font.weight enum values Followup to 517da68893be9e6d97c7993922c573de9560604d in qtbase: make all possible font weights available in QML. Task-number: QTBUG-38482 Change-Id: I4f821d2fadbcd42fbb237903be474d67a0a5a7c9 Reviewed-by: Konstantin Ritt Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/quick/doc/src/qmltypereference.qdoc | 12 ++++++++++++ src/quick/items/qquicktext.cpp | 4 ++++ src/quick/items/qquicktextedit.cpp | 4 ++++ src/quick/items/qquicktextinput.cpp | 4 ++++ src/quick/util/qquickvaluetypes_p.h | 14 +++++++++----- 5 files changed, 33 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/quick/doc/src/qmltypereference.qdoc b/src/quick/doc/src/qmltypereference.qdoc index 0dbc342baa..e3641f2d76 100644 --- a/src/quick/doc/src/qmltypereference.qdoc +++ b/src/quick/doc/src/qmltypereference.qdoc @@ -184,18 +184,30 @@ available when you import \c QtQuick. and 99 is extremely black. The following values are supported: \table + \row + \li \c Font.Thin + \li 0 + \row + \li \c Font.ExtraLight + \li 12 \row \li \c Font.Light \li 25 \row \li \c Font.Normal \li 50 + \row + \li \c Font.Medium + \li 57 \row \li \c Font.DemiBold \li 63 \row \li \c Font.Bold \li 75 + \row + \li \c Font.ExtraBold + \li 81 \row \li \c Font.Black \li 87 diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index 456ec25edd..dd4f57bfdb 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -1372,10 +1372,14 @@ QQuickText::~QQuickText() The weight can be one of: \list + \li Font.Thin \li Font.Light + \li Font.ExtraLight \li Font.Normal - the default + \li Font.Medium \li Font.DemiBold \li Font.Bold + \li Font.ExtraBold \li Font.Black \endlist diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index c3315878f2..2f2fc0d4c1 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -211,10 +211,14 @@ QString QQuickTextEdit::text() const The weight can be one of: \list + \li Font.Thin \li Font.Light + \li Font.ExtraLight \li Font.Normal - the default + \li Font.Medium \li Font.DemiBold \li Font.Bold + \li Font.ExtraBold \li Font.Black \endlist diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 5c8c0cf823..54da9a40d0 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -234,10 +234,14 @@ QString QQuickTextInputPrivate::realText() const The weight can be one of: \list + \li Font.Thin \li Font.Light + \li Font.ExtraLight \li Font.Normal - the default + \li Font.Medium \li Font.DemiBold \li Font.Bold + \li Font.ExtraBold \li Font.Black \endlist diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 75ed2bce01..f62306ed01 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -283,11 +283,15 @@ class QQuickFontValueType Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing FINAL) public: - enum FontWeight { Light = QFont::Light, - Normal = QFont::Normal, - DemiBold = QFont::DemiBold, - Bold = QFont::Bold, - Black = QFont::Black }; + enum FontWeight { Thin = QFont::Thin, + ExtraLight = QFont::ExtraLight, + Light = QFont::Light, + Normal = QFont::Normal, + Medium = QFont::Medium, + DemiBold = QFont::DemiBold, + Bold = QFont::Bold, + ExtraBold = QFont::ExtraBold, + Black = QFont::Black }; enum Capitalization { MixedCase = QFont::MixedCase, AllUppercase = QFont::AllUppercase, AllLowercase = QFont::AllLowercase, -- cgit v1.2.3 From 4e944555aa1b9efa30b07ebb5bc5191c2ea6c130 Mon Sep 17 00:00:00 2001 From: Santtu Lakkala Date: Thu, 16 Apr 2015 16:51:45 +0300 Subject: Hide cursor when text fields becomes read only Clear the cursor node in TextEdit if field is read only. Otherwise the cursor stays visible indefinitely, if it were at the moment the flag was set. Task-number: QTBUG-44735 Change-Id: Ib39138260ad8a4d7e5ed2185b8a04c577ee1eff0 Reviewed-by: Alan Alpert --- src/quick/items/qquicktextedit.cpp | 12 +++++++++--- src/quick/items/qquicktextinput.cpp | 9 ++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 2f2fc0d4c1..8237ad10e4 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1436,6 +1436,11 @@ void QQuickTextEdit::setReadOnly(bool r) emit readOnlyChanged(r); if (!d->selectByKeyboardSet) emit selectByKeyboardChanged(!r); + if (r) { + setCursorVisible(false); + } else if (hasActiveFocus()) { + setCursorVisible(true); + } } bool QQuickTextEdit::isReadOnly() const @@ -1937,9 +1942,9 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData * std::sort(d->textNodeMap.begin(), d->textNodeMap.end(), &comesBefore); } - if (d->cursorComponent == 0 && !isReadOnly()) { + if (d->cursorComponent == 0) { QSGRectangleNode* cursor = 0; - if (d->cursorVisible && d->control->cursorOn()) + if (!isReadOnly() && d->cursorVisible && d->control->cursorOn()) cursor = d->sceneGraphContext()->createRectangleNode(d->control->cursorRect(), d->color); rootNode->resetCursorNode(cursor); } @@ -2408,7 +2413,8 @@ void QQuickTextEditPrivate::handleFocusEvent(QFocusEvent *event) { Q_Q(QQuickTextEdit); bool focus = event->type() == QEvent::FocusIn; - q->setCursorVisible(focus); + if (!q->isReadOnly()) + q->setCursorVisible(focus); control->processEvent(event, QPointF(-xoff, -yoff)); if (focus) { q->q_updateAlignment(); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index 54da9a40d0..a4c61209f2 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -662,6 +662,12 @@ void QQuickTextInput::setReadOnly(bool ro) q_canPasteChanged(); d->emitUndoRedoChanged(); emit readOnlyChanged(ro); + if (ro) { + setCursorVisible(false); + } else if (hasActiveFocus()) { + setCursorVisible(true); + } + update(); } /*! @@ -2606,7 +2612,8 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event) { Q_Q(QQuickTextInput); bool focus = event->gotFocus(); - q->setCursorVisible(focus); + if (!m_readOnly) + q->setCursorVisible(focus); if (focus) { q->q_updateAlignment(); #ifndef QT_NO_IM -- cgit v1.2.3 From d76921e3082cd311207cd4c822ef2d357519b12f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 11 May 2015 10:16:37 +0200 Subject: QML: fix mixed debug/release build on OSX. Dyld will take the debug library and link it against the release versions of the frameworks. (Using the debug versions is an option to dyld when starting an application.) This requires all symbols in both debug and release libraries in frameworks to be the same. Change-Id: I6d96bcdf8577f1dffc63c508cb7adc0db2acc486 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 6 +----- src/qml/jsruntime/qv4engine_p.h | 2 -- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 92993259ec..3b89851d81 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1623,14 +1623,10 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) return 0; } -#ifndef QT_NO_DEBUG void ExecutionEngine::assertObjectBelongsToEngine(const Value &v) { - if (!v.isObject()) - return; - Q_ASSERT(v.objectValue()->engine() == this); + Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this); } -#endif // Converts a JS value to a meta-type. // data must point to a place that can store a value of the given type. diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 277cbdf1f5..c0c88abaa5 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -340,9 +340,7 @@ public: bool metaTypeFromJS(const Value &value, int type, void *data); QV4::ReturnedValue metaTypeToJS(int type, const void *data); -#ifndef QT_NO_DEBUG void assertObjectBelongsToEngine(const Value &v); -#endif private: QmlExtensions *m_qmlExtensions; -- cgit v1.2.3 From 66be8fcc05f0e51f12c215af3d5ab74d729386ba Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 7 May 2015 19:09:39 +0200 Subject: Create contexts and pbuffers with the correct screen in QQuickWidget Change-Id: I8e9db998eee0af5f62c1384f2dcb2028254cc642 Reviewed-by: Gunnar Sletta --- src/quickwidgets/qquickwidget.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index 38dde806ed..f0a2a3183b 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -691,8 +691,10 @@ void QQuickWidgetPrivate::createContext() context = new QOpenGLContext; context->setFormat(offscreenWindow->requestedFormat()); - if (qt_gl_global_share_context()) + if (qt_gl_global_share_context()) { context->setShareContext(qt_gl_global_share_context()); + context->setScreen(context->shareContext()->screen()); + } if (!context->create()) { const bool isEs = context->isOpenGLES(); @@ -707,6 +709,7 @@ void QQuickWidgetPrivate::createContext() // contains a QSurfaceFormat representing the _actual_ format of the underlying // configuration. This is essential to get a surface that is compatible with the context. offscreenSurface->setFormat(context->format()); + offscreenSurface->setScreen(context->screen()); offscreenSurface->create(); } @@ -742,7 +745,14 @@ void QQuickWidget::createFramebufferObject() if (context->shareContext() != QWidgetPrivate::get(window())->shareContext()) { context->setShareContext(QWidgetPrivate::get(window())->shareContext()); - context->create(); + context->setScreen(context->shareContext()->screen()); + if (!context->create()) + qWarning("QQuickWidget: Failed to recreate context"); + // The screen may be different so we must recreate the offscreen surface too. + // Unlike QOpenGLContext, QOffscreenSurface's create() does not recreate so have to destroy() first. + d->offscreenSurface->destroy(); + d->offscreenSurface->setScreen(context->screen()); + d->offscreenSurface->create(); } context->makeCurrent(d->offscreenSurface); -- cgit v1.2.3 From 30aa0a1cc9812bd2a9ead91e3f412808ebe7daff Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 7 Mar 2015 14:42:59 -0800 Subject: QtQuick: Fix const correctness in old style casts Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c9589afabc7ade Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> Reviewed-by: Simon Hausmann --- src/quick/items/qquickshadereffectnode.cpp | 2 +- src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 8 ++++---- src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 7 ++++++- src/quick/scenegraph/coreapi/qsgnode.cpp | 14 +++++++------- src/quick/scenegraph/qsgcontext.cpp | 10 +++++----- src/quick/scenegraph/qsgrenderloop.cpp | 2 +- src/quick/util/qquickanimation.cpp | 4 ++-- src/quick/util/qquicksmoothedanimation.cpp | 2 +- src/quick/util/qquickspringanimation.cpp | 2 +- src/quick/util/qquicktimeline.cpp | 2 +- 10 files changed, 29 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp index 6415c0ad22..de6cae0ea6 100644 --- a/src/quick/items/qquickshadereffectnode.cpp +++ b/src/quick/items/qquickshadereffectnode.cpp @@ -341,7 +341,7 @@ bool QQuickShaderEffectMaterialKey::operator != (const QQuickShaderEffectMateria uint qHash(const QQuickShaderEffectMaterialKey &key) { - uint hash = qHash((void *)key.className); + uint hash = qHash((const void *)key.className); typedef QQuickShaderEffectMaterialKey Key; for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) hash = hash * 31337 + qHash(key.sourceCode[shaderType]); diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index 886e614620..63938d50a9 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -1693,8 +1693,8 @@ void Renderer::uploadMergedElement(Element *e, int vaOffset, char **vertexData, if (((const QMatrix4x4_Accessor &) localx).flagBits == 1) { for (int i=0; ix += ((QMatrix4x4_Accessor &) localx).m[3][0]; - p->y += ((QMatrix4x4_Accessor &) localx).m[3][1]; + p->x += ((const QMatrix4x4_Accessor &) localx).m[3][0]; + p->y += ((const QMatrix4x4_Accessor &) localx).m[3][1]; vdata += vSize; } } else if (((const QMatrix4x4_Accessor &) localx).flagBits > 1) { @@ -1935,11 +1935,11 @@ void Renderer::uploadBatch(Batch *b) if (attr.isVertexCoordinate) dump << "* "; for (int t=0; tgeometry(); @@ -1508,7 +1508,7 @@ QDebug operator<<(QDebug d, const QSGClipNode *n) d << "ClipNode(null)"; return d; } - d << "ClipNode(" << hex << (void *) n << dec; + d << "ClipNode(" << hex << (const void *) n << dec; if (n->childCount()) d << "children=" << n->childCount(); @@ -1531,7 +1531,7 @@ QDebug operator<<(QDebug d, const QSGTransformNode *n) } const QMatrix4x4 m = n->matrix(); d << "TransformNode("; - d << hex << (void *) n << dec; + d << hex << (const void *) n << dec; if (m.isIdentity()) d << "identity"; else if (m.determinant() == 1 && m(0, 0) == 1 && m(1, 1) == 1 && m(2, 2) == 1) @@ -1553,7 +1553,7 @@ QDebug operator<<(QDebug d, const QSGOpacityNode *n) return d; } d << "OpacityNode("; - d << hex << (void *) n << dec; + d << hex << (const void *) n << dec; d << "opacity=" << n->opacity() << "combined=" << n->combinedOpacity() << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); @@ -1571,7 +1571,7 @@ QDebug operator<<(QDebug d, const QSGRootNode *n) d << "RootNode(null)"; return d; } - d << "RootNode" << hex << (void *) n << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); + d << "RootNode" << hex << (const void *) n << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QSG_RUNTIME_DESCRIPTION d << QSGNodePrivate::description(n); #endif @@ -1604,7 +1604,7 @@ QDebug operator<<(QDebug d, const QSGNode *n) d << static_cast(n); break; case QSGNode::RenderNodeType: - d << "RenderNode(" << hex << (void *) n << dec + d << "RenderNode(" << hex << (const void *) n << dec << "flags=" << (int) n->flags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QSG_RUNTIME_DESCRIPTION @@ -1613,7 +1613,7 @@ QDebug operator<<(QDebug d, const QSGNode *n) d << ')'; break; default: - d << "Node(" << hex << (void *) n << dec + d << "Node(" << hex << (const void *) n << dec << "flags=" << (int) n->flags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : ""); #ifdef QSG_RUNTIME_DESCRIPTION diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index dd071d757e..418d571ae6 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -315,11 +315,11 @@ QSGContext::QSGContext(QObject *parent) : // Adds compatibility with Qt 5.3 and earlier's QSG_RENDER_TIMING if (qEnvironmentVariableIsSet("QSG_RENDER_TIMING")) { - ((QLoggingCategory &) QSG_LOG_TIME_GLYPH()).setEnabled(QtDebugMsg, true); - ((QLoggingCategory &) QSG_LOG_TIME_TEXTURE()).setEnabled(QtDebugMsg, true); - ((QLoggingCategory &) QSG_LOG_TIME_RENDERER()).setEnabled(QtDebugMsg, true); - ((QLoggingCategory &) QSG_LOG_TIME_RENDERLOOP()).setEnabled(QtDebugMsg, true); - ((QLoggingCategory &) QSG_LOG_TIME_COMPILATION()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_TIME_GLYPH()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_TIME_TEXTURE()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_TIME_RENDERER()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_TIME_RENDERLOOP()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_TIME_COMPILATION()).setEnabled(QtDebugMsg, true); } } diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index b7a6475c23..781e82fbc4 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -152,7 +152,7 @@ QSGRenderLoop *QSGRenderLoop::instance() // For compatibility with 5.3 and earlier's QSG_INFO environment variables if (qEnvironmentVariableIsSet("QSG_INFO")) - ((QLoggingCategory &) QSG_LOG_INFO()).setEnabled(QtDebugMsg, true); + const_cast(QSG_LOG_INFO()).setEnabled(QtDebugMsg, true); s_instance = QSGContext::createWindowManager(); diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp index a39d734de3..3a0c19e3d2 100644 --- a/src/quick/util/qquickanimation.cpp +++ b/src/quick/util/qquickanimation.cpp @@ -867,7 +867,7 @@ void QActionAnimation::updateState(State newState, State oldState) void QActionAnimation::debugAnimation(QDebug d) const { - d << "ActionAnimation(" << hex << (void *) this << dec << ")"; + d << "ActionAnimation(" << hex << (const void *) this << dec << ")"; if (animAction) { int indentLevel = 1; @@ -1960,7 +1960,7 @@ void QQuickBulkValueAnimator::topLevelAnimationLoopChanged() void QQuickBulkValueAnimator::debugAnimation(QDebug d) const { - d << "BulkValueAnimation(" << hex << (void *) this << dec << ")" << "duration:" << duration(); + d << "BulkValueAnimation(" << hex << (const void *) this << dec << ")" << "duration:" << duration(); if (animValue) { int indentLevel = 1; diff --git a/src/quick/util/qquicksmoothedanimation.cpp b/src/quick/util/qquicksmoothedanimation.cpp index 71dacfcb1d..6d585d38a7 100644 --- a/src/quick/util/qquicksmoothedanimation.cpp +++ b/src/quick/util/qquicksmoothedanimation.cpp @@ -307,7 +307,7 @@ void QSmoothedAnimation::init() void QSmoothedAnimation::debugAnimation(QDebug d) const { - d << "SmoothedAnimationJob(" << hex << (void *) this << dec << ")" << "duration:" << userDuration + d << "SmoothedAnimationJob(" << hex << (const void *) this << dec << ")" << "duration:" << userDuration << "velocity:" << velocity << "target:" << target.object() << "property:" << target.name() << "to:" << to << "current velocity:" << trackVelocity; } diff --git a/src/quick/util/qquickspringanimation.cpp b/src/quick/util/qquickspringanimation.cpp index b68afbecdd..125d6f5ef6 100644 --- a/src/quick/util/qquickspringanimation.cpp +++ b/src/quick/util/qquickspringanimation.cpp @@ -313,7 +313,7 @@ void QSpringAnimation::updateState(QAbstractAnimationJob::State newState, QAbstr void QSpringAnimation::debugAnimation(QDebug d) const { - d << "SpringAnimationJob(" << hex << (void *) this << dec << ")" << "velocity:" << maxVelocity + d << "SpringAnimationJob(" << hex << (const void *) this << dec << ")" << "velocity:" << maxVelocity << "spring:" << spring << "damping:" << damping << "epsilon:" << epsilon << "modulus:" << modulus << "mass:" << mass << "target:" << target.object() << "property:" << target.name() << "to:" << to << "current velocity:" << velocity; diff --git a/src/quick/util/qquicktimeline.cpp b/src/quick/util/qquicktimeline.cpp index 8cd9b349d8..74754a0bfb 100644 --- a/src/quick/util/qquicktimeline.cpp +++ b/src/quick/util/qquicktimeline.cpp @@ -717,7 +717,7 @@ void QQuickTimeLine::updateCurrentTime(int v) void QQuickTimeLine::debugAnimation(QDebug d) const { - d << "QuickTimeLine(" << hex << (void *) this << dec << ")"; + d << "QuickTimeLine(" << hex << (const void *) this << dec << ")"; } bool operator<(const QPair &lhs, -- cgit v1.2.3 From 2cb2c8f9e12fe72bab6e0a627e34d89d9d2689b2 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 19 May 2015 09:16:44 +0200 Subject: MSVC: Fix compiler warning Fix compiler warning introduced in commit d76921e3082cd31: jsruntime\qv4engine.cpp(1626) : warning C4100: 'v' : unreferenced formal parameter Change-Id: I1f2b74f8e3fb14019f6e28b407d0336b0812c573 Reviewed-by: Friedemann Kleint --- src/qml/jsruntime/qv4engine.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 3b89851d81..33559d8e69 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1625,6 +1625,7 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) void ExecutionEngine::assertObjectBelongsToEngine(const Value &v) { + Q_UNUSED(v); Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this); } -- cgit v1.2.3 From bf935a5359227066ac066b9e3d96bc48870bc4e7 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 19 May 2015 11:07:43 +0200 Subject: Fix MSVC warning about unused variable Change-Id: I9b2f21dd7cfc82a9da9aa3e4c60d47fa07fdceaf Reviewed-by: Lars Knoll --- src/qml/jsruntime/qv4engine.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 33559d8e69..5e450859ec 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1627,6 +1627,7 @@ void ExecutionEngine::assertObjectBelongsToEngine(const Value &v) { Q_UNUSED(v); Q_ASSERT(!v.isObject() || v.objectValue()->engine() == this); + Q_UNUSED(v); } // Converts a JS value to a meta-type. -- cgit v1.2.3 From f19904953538bc33897b3f65f439069d453e756f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 18 May 2015 12:05:19 +0200 Subject: Fix render loop warning about invalid geometry of exposed windows. Do the screen check only for toplevel windows and make warning more verbose. Change-Id: Ie25271fe34c72c1410022afe8a1a9bdccdf7a12f Task-number: QTCREATORBUG-10814 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgthreadedrenderloop.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp index f9f973fe2a..56637387df 100644 --- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp +++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp @@ -885,9 +885,11 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window) w->thread->window = window; if (w->window->width() <= 0 || w->window->height() <= 0 - || !w->window->geometry().intersects(w->window->screen()->availableGeometry())) { + || (w->window->isTopLevel() && !w->window->geometry().intersects(w->window->screen()->availableGeometry()))) { #ifndef QT_NO_DEBUG - qWarning("QSGThreadedRenderLoop: expose event received for window with invalid geometry."); + qWarning().noquote().nospace() << "QSGThreadedRenderLoop: expose event received for window " + << w->window << " with invalid geometry: " << w->window->geometry() + << " on " << w->window->screen(); #endif } -- cgit v1.2.3 From 0ace63da65a222873ecf4e966afe88afb89a25f8 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 19 May 2015 11:35:12 +0200 Subject: WinRT: fix warnings Change-Id: If11db499d743cbe79959145ecfcbcfec896a6845 Reviewed-by: Kai Koehne Reviewed-by: Oliver Wolff --- src/3rdparty/masm/stubs/ExecutableAllocator.h | 3 +++ src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp | 2 +- src/imports/folderlistmodel/fileinfothread.cpp | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h index f937f93025..5f7d5678ab 100644 --- a/src/3rdparty/masm/stubs/ExecutableAllocator.h +++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h @@ -114,6 +114,9 @@ struct ExecutableAllocator { #if !OS(WINRT) DWORD oldProtect; VirtualProtect(reinterpret_cast(roundAddr), size + (iaddr - roundAddr), PAGE_EXECUTE_READWRITE, &oldProtect); +#else + (void)size; // suppress unused parameter warning + (void)roundAddr; // suppress unused parameter warning #endif #else int mode = PROT_READ | PROT_EXEC; diff --git a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp index ba251d2ecf..d684367ec6 100644 --- a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp +++ b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp @@ -55,7 +55,7 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo return reserveUncommitted(bytes, usage, writable, executable); } -void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable) +void OSAllocator::commit(void*, size_t, bool, bool) { CRASH(); // Unimplemented } diff --git a/src/imports/folderlistmodel/fileinfothread.cpp b/src/imports/folderlistmodel/fileinfothread.cpp index b085233f01..e1db7834ec 100644 --- a/src/imports/folderlistmodel/fileinfothread.cpp +++ b/src/imports/folderlistmodel/fileinfothread.cpp @@ -86,6 +86,8 @@ void FileInfoThread::removePath(const QString &path) #ifndef QT_NO_FILESYSTEMWATCHER if (!path.startsWith(QLatin1Char(':'))) watcher->removePath(path); +#else + Q_UNUSED(path); #endif currentPath.clear(); } -- cgit v1.2.3 From 07882f73e8028577d9223b65a5abd6ffed5d2b35 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 18 May 2015 10:13:48 +0200 Subject: Optionally apply orientation on images Adds the option to follow EXIF orientation. This was previuosly automatically applied to TIFF images, but not JPEGs except in Qt 5.4.1. [ChangeLog][Image] An autoTransform property has been added to control whether metadata image transforms such as EXIF orientation are automatically applied. By default it enabled for TIFF images and disabled for JPEG. Change-Id: I8a4cf204985b2a7d158a0e046e52db7cda970d20 Task-number: QTBUG-37946 Reviewed-by: Gunnar Sletta --- src/quick/items/qquickimage.cpp | 11 ++++ src/quick/items/qquickimage_p.h | 2 + src/quick/items/qquickimagebase.cpp | 27 ++++++++- src/quick/items/qquickimagebase_p.h | 4 ++ src/quick/items/qquickimagebase_p_p.h | 6 +- src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/util/qquickimageprovider.h | 6 ++ src/quick/util/qquickpixmapcache.cpp | 104 ++++++++++++++++++++++------------ src/quick/util/qquickpixmapcache_p.h | 8 +++ 9 files changed, 131 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index a278fb72a2..f0f17551b7 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -152,6 +152,7 @@ QQuickImagePrivate::QQuickImagePrivate() QQuickImage::QQuickImage(QQuickItem *parent) : QQuickImageBase(*(new QQuickImagePrivate), parent) { + connect(this, SIGNAL(autoTransformBaseChanged()), SIGNAL(autoTransformChanged())); } QQuickImage::QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent) @@ -820,4 +821,14 @@ void QQuickImage::setMipmap(bool use) update(); } +/*! + \qmlproperty bool QtQuick::Image::autoTransform + \since 5.5 + + This property holds whether the image should automatically apply + image transformation metadata such as EXIF orientation. + + By default, this property is set to false. + */ + QT_END_NAMESPACE diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index efe83e7026..5b1aea5940 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -53,6 +53,7 @@ class Q_AUTOTEST_EXPORT QQuickImage : public QQuickImageBase Q_PROPERTY(HAlignment horizontalAlignment READ horizontalAlignment WRITE setHorizontalAlignment NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ verticalAlignment WRITE setVerticalAlignment NOTIFY verticalAlignmentChanged) Q_PROPERTY(bool mipmap READ mipmap WRITE setMipmap NOTIFY mipmapChanged REVISION 1) + Q_PROPERTY(bool autoTransform READ autoTransform WRITE setAutoTransform NOTIFY autoTransformChanged REVISION 2) public: QQuickImage(QQuickItem *parent=0); @@ -93,6 +94,7 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); Q_REVISION(1) void mipmapChanged(bool); + Q_REVISION(2) void autoTransformChanged(); private Q_SLOTS: void invalidateSceneGraph(); diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index b54c34765f..8fba6e3d12 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -195,6 +195,10 @@ void QQuickImageBase::load() d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); } + if (autoTransform() != d->oldAutoTransform) { + d->oldAutoTransform = autoTransform(); + emit autoTransformBaseChanged(); + } update(); } else { @@ -223,7 +227,7 @@ void QQuickImageBase::load() resolve2xLocalFile(d->url, targetDevicePixelRatio, &loadUrl, &d->devicePixelRatio); } - d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options); + d->pix.load(qmlEngine(this), loadUrl, d->sourcesize * d->devicePixelRatio, options, d->autoTransform); if (d->pix.isLoading()) { if (d->progress != 0.0) { @@ -278,6 +282,10 @@ void QQuickImageBase::requestFinished() d->oldSourceSize = sourceSize(); emit sourceSizeChanged(); } + if (autoTransform() != d->oldAutoTransform) { + d->oldAutoTransform = autoTransform(); + emit autoTransformBaseChanged(); + } update(); } @@ -368,4 +376,21 @@ void QQuickImageBase::resolve2xLocalFile(const QUrl &url, qreal targetDevicePixe *sourceDevicePixelRatio = qreal(2.0); } +bool QQuickImageBase::autoTransform() const +{ + Q_D(const QQuickImageBase); + if (d->autoTransform == UsePluginDefault) + return d->pix.autoTransform() == ApplyTransform; + return d->autoTransform == ApplyTransform; +} + +void QQuickImageBase::setAutoTransform(bool transform) +{ + Q_D(QQuickImageBase); + if (d->autoTransform != UsePluginDefault && transform == (d->autoTransform == ApplyTransform)) + return; + d->autoTransform = transform ? ApplyTransform : DoNotApplyTransform; + emit autoTransformBaseChanged(); +} + QT_END_NAMESPACE diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h index 978004f8fd..d43822bebe 100644 --- a/src/quick/items/qquickimagebase_p.h +++ b/src/quick/items/qquickimagebase_p.h @@ -78,6 +78,9 @@ public: virtual void setMirror(bool mirror); bool mirror() const; + virtual void setAutoTransform(bool transform); + bool autoTransform() const; + void resolve2xLocalFile(const QUrl &url, qreal targetDevicePixelRatio, QUrl *sourceUrl, qreal *sourceDevicePixelRatio); Q_SIGNALS: @@ -88,6 +91,7 @@ Q_SIGNALS: void asynchronousChanged(); void cacheChanged(); void mirrorChanged(); + void autoTransformBaseChanged(); protected: virtual void load(); diff --git a/src/quick/items/qquickimagebase_p_p.h b/src/quick/items/qquickimagebase_p_p.h index ebdf352e4e..cffe709116 100644 --- a/src/quick/items/qquickimagebase_p_p.h +++ b/src/quick/items/qquickimagebase_p_p.h @@ -62,9 +62,11 @@ public: : status(QQuickImageBase::Null), progress(0.0), devicePixelRatio(1.0), + autoTransform(UsePluginDefault), async(false), cache(true), - mirror(false) + mirror(false), + oldAutoTransform(false) { } @@ -75,9 +77,11 @@ public: QSize sourcesize; QSize oldSourceSize; qreal devicePixelRatio; + AutoTransform autoTransform; bool async : 1; bool cache : 1; bool mirror: 1; + bool oldAutoTransform : 1; }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index 6c342cc491..8b4723f340 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -267,6 +267,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterUncreatableType(uri, 2, 4,"OpenGLInfo", QQuickOpenGLInfo::tr("OpenGLInfo is only available via attached properties")); qmlRegisterType(uri, 2, 5,"PinchArea"); + qmlRegisterType(uri, 2, 5,"Image"); } static void initResources() diff --git a/src/quick/util/qquickimageprovider.h b/src/quick/util/qquickimageprovider.h index 095dd09a01..a2b510f606 100644 --- a/src/quick/util/qquickimageprovider.h +++ b/src/quick/util/qquickimageprovider.h @@ -67,9 +67,15 @@ public: ImageType imageType() const; Flags flags() const; +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); + virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize, bool requestedAutoTransform); + virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize, bool requestedAutoTransform); +#else virtual QImage requestImage(const QString &id, QSize *size, const QSize& requestedSize); virtual QPixmap requestPixmap(const QString &id, QSize *size, const QSize& requestedSize); virtual QQuickTextureFactory *requestTexture(const QString &id, QSize *size, const QSize &requestedSize); +#endif private: QQuickImageProviderPrivate *d; diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index eabbda1cdf..ddf2ae2393 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -142,15 +142,17 @@ public: QUrl url; bool loading; + AutoTransform autoTransform; int redirectCount; class Event : public QEvent { public: - Event(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory); + Event(ReadError, const QString &, const QSize &, AutoTransform, QQuickTextureFactory *factory); ReadError error; QString errorString; QSize implicitSize; + AutoTransform autoTransform; QQuickTextureFactory *textureFactory; }; void postReply(ReadError, const QString &, const QSize &, QQuickTextureFactory *factory); @@ -203,7 +205,7 @@ protected: private: friend class QQuickPixmapReaderThreadObject; void processJobs(); - void processJob(QQuickPixmapReply *, const QUrl &, const QSize &); + void processJob(QQuickPixmapReply *, const QUrl &, const QSize &, AutoTransform); void networkRequestDone(QNetworkReply *); QList jobs; @@ -232,25 +234,32 @@ public: class QQuickPixmapData { public: - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, const QString &e) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &s, AutoTransform transform, const QString &e) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Error), - url(u), errorString(e), requestSize(s), textureFactory(0), reply(0), prevUnreferenced(0), + url(u), errorString(e), requestSize(s), + requestedTransform(transform), appliedTransform(UsePluginDefault), + textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { declarativePixmaps.insert(pixmap); } - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, const QSize &r, AutoTransform rTransform, AutoTransform aTransform) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Loading), - url(u), requestSize(r), textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), + url(u), requestSize(r), + requestedTransform(rTransform), appliedTransform(aTransform), + textureFactory(0), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { declarativePixmaps.insert(pixmap); } - QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *texture, const QSize &s, const QSize &r) + QQuickPixmapData(QQuickPixmap *pixmap, const QUrl &u, QQuickTextureFactory *texture, + const QSize &s, const QSize &r, AutoTransform rTransform, AutoTransform aTransform) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready), - url(u), implicitSize(s), requestSize(r), textureFactory(texture), reply(0), prevUnreferenced(0), + url(u), implicitSize(s), requestSize(r), + requestedTransform(rTransform), appliedTransform(aTransform), + textureFactory(texture), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { declarativePixmaps.insert(pixmap); @@ -258,6 +267,7 @@ public: QQuickPixmapData(QQuickPixmap *pixmap, QQuickTextureFactory *texture) : refCount(1), inCache(false), pixmapStatus(QQuickPixmap::Ready), + requestedTransform(UsePluginDefault), appliedTransform(UsePluginDefault), textureFactory(texture), reply(0), prevUnreferenced(0), prevUnreferencedPtr(0), nextUnreferenced(0) { @@ -291,6 +301,8 @@ public: QString errorString; QSize implicitSize; QSize requestSize; + AutoTransform requestedTransform; + AutoTransform appliedTransform; QQuickTextureFactory *textureFactory; @@ -319,11 +331,11 @@ void QQuickPixmapReply::postReply(ReadError error, const QString &errorString, const QSize &implicitSize, QQuickTextureFactory *factory) { loading = false; - QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, factory)); + QCoreApplication::postEvent(this, new Event(error, errorString, implicitSize, autoTransform, factory)); } -QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, QQuickTextureFactory *factory) - : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), textureFactory(factory) +QQuickPixmapReply::Event::Event(ReadError e, const QString &s, const QSize &iSize, AutoTransform iTransformed, QQuickTextureFactory *factory) + : QEvent(QEvent::User), error(e), errorString(s), implicitSize(iSize), autoTransform(iTransformed), textureFactory(factory) { } @@ -360,9 +372,13 @@ static void maybeRemoveAlpha(QImage *image) } static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, - const QSize &requestSize) + const QSize &requestSize, AutoTransform &autoTransform) { QImageReader imgio(dev); + if (autoTransform != UsePluginDefault) + imgio.setAutoTransform(autoTransform == ApplyTransform); + else + autoTransform = imgio.autoTransform() ? ApplyTransform : DoNotApplyTransform; const bool force_scale = imgio.format() == "svg" || imgio.format() == "svgz"; @@ -472,7 +488,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) QByteArray all = reply->readAll(); QBuffer buff(&all); buff.open(QIODevice::ReadOnly); - if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize)) + if (!readImage(reply->url(), &buff, &image, &errorString, &readSize, job->requestSize, job->autoTransform)) error = QQuickPixmapReply::Decoding; } // send completion event to the QQuickPixmapReply @@ -562,8 +578,9 @@ void QQuickPixmapReader::processJobs() PIXMAP_PROFILE(pixmapStateChanged(url)); QSize requestSize = runningJob->requestSize; + AutoTransform autoTransform = runningJob->autoTransform; locker.unlock(); - processJob(runningJob, url, requestSize); + processJob(runningJob, url, requestSize, autoTransform); locker.relock(); } } @@ -575,7 +592,7 @@ void QQuickPixmapReader::processJobs() } void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &url, - const QSize &requestSize) + const QSize &requestSize, AutoTransform autoTransform) { // fetch if (url.scheme() == QLatin1String("image")) { @@ -646,7 +663,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QFile f(lf); QSize readSize; if (f.open(QIODevice::ReadOnly)) { - if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize)) + if (!readImage(url, &f, &image, &errorStr, &readSize, requestSize, autoTransform)) errorCode = QQuickPixmapReply::Loading; } else { errorStr = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); @@ -745,16 +762,17 @@ class QQuickPixmapKey public: const QUrl *url; const QSize *size; + AutoTransform autoTransform; }; inline bool operator==(const QQuickPixmapKey &lhs, const QQuickPixmapKey &rhs) { - return *lhs.size == *rhs.size && *lhs.url == *rhs.url; + return *lhs.size == *rhs.size && *lhs.url == *rhs.url && lhs.autoTransform == rhs.autoTransform; } inline uint qHash(const QQuickPixmapKey &key) { - return qHash(*key.url) ^ key.size->width() ^ key.size->height(); + return qHash(*key.url) ^ (key.size->width()*7) ^ (key.size->height()*17) ^ (key.autoTransform * 0x5c5c5c5c); } class QSGContext; @@ -924,7 +942,7 @@ void QQuickPixmap::purgeCache() } QQuickPixmapReply::QQuickPixmapReply(QQuickPixmapData *d) -: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), redirectCount(0) +: data(d), engineForReader(0), requestSize(d->requestSize), url(d->url), loading(false), autoTransform(d->appliedTransform), redirectCount(0) { if (finishedIndex == -1) { finishedIndex = QMetaMethod::fromSignal(&QQuickPixmapReply::finished).methodIndex(); @@ -948,6 +966,7 @@ bool QQuickPixmapReply::event(QEvent *event) if (data->pixmapStatus == QQuickPixmap::Ready) { data->textureFactory = de->textureFactory; data->implicitSize = de->implicitSize; + data->appliedTransform = de->autoTransform; PIXMAP_PROFILE(pixmapLoadingFinished(data->url, data->textureFactory != 0 && data->textureFactory->textureSize().isValid() ? data->textureFactory->textureSize() : @@ -1018,7 +1037,7 @@ void QQuickPixmapData::release() void QQuickPixmapData::addToCache() { if (!inCache) { - QQuickPixmapKey key = { &url, &requestSize }; + QQuickPixmapKey key = { &url, &requestSize, requestedTransform }; pixmapStore()->m_cache.insert(key, this); inCache = true; PIXMAP_PROFILE(pixmapCountChanged( @@ -1029,7 +1048,7 @@ void QQuickPixmapData::addToCache() void QQuickPixmapData::removeFromCache() { if (inCache) { - QQuickPixmapKey key = { &url, &requestSize }; + QQuickPixmapKey key = { &url, &requestSize, requestedTransform }; pixmapStore()->m_cache.remove(key); inCache = false; PIXMAP_PROFILE(pixmapCountChanged( @@ -1037,7 +1056,7 @@ void QQuickPixmapData::removeFromCache() } } -static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, bool *ok) +static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, QQmlEngine *engine, const QUrl &url, const QSize &requestSize, AutoTransform autoTransform, bool *ok) { if (url.scheme() == QLatin1String("image")) { QSize readSize; @@ -1049,14 +1068,14 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q switch (imageType) { case QQuickImageProvider::Invalid: - return new QQuickPixmapData(declarativePixmap, url, requestSize, + return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, QQuickPixmap::tr("Invalid image provider: %1").arg(url.toString())); case QQuickImageProvider::Texture: { QQuickTextureFactory *texture = provider->requestTexture(imageId(url), &readSize, requestSize); if (texture) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize); + return new QQuickPixmapData(declarativePixmap, url, texture, readSize, requestSize, autoTransform, UsePluginDefault); } } @@ -1065,7 +1084,7 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QImage image = provider->requestImage(imageId(url), &readSize, requestSize); if (!image.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize); + return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, UsePluginDefault); } } case QQuickImageProvider::Pixmap: @@ -1073,13 +1092,13 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q QPixmap pixmap = provider->requestPixmap(imageId(url), &readSize, requestSize); if (!pixmap.isNull()) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(pixmap.toImage()), readSize, requestSize); + return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(pixmap.toImage()), readSize, requestSize, autoTransform, UsePluginDefault); } } } // provider has bad image type, or provider returned null image - return new QQuickPixmapData(declarativePixmap, url, requestSize, + return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, QQuickPixmap::tr("Failed to get image from provider: %1").arg(url.toString())); } @@ -1093,17 +1112,17 @@ static QQuickPixmapData* createPixmapDataSync(QQuickPixmap *declarativePixmap, Q if (f.open(QIODevice::ReadOnly)) { QImage image; - - if (readImage(url, &f, &image, &errorString, &readSize, requestSize)) { + AutoTransform appliedTransform = autoTransform; + if (readImage(url, &f, &image, &errorString, &readSize, requestSize, appliedTransform)) { *ok = true; - return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize); + return new QQuickPixmapData(declarativePixmap, url, textureFactoryForImage(image), readSize, requestSize, autoTransform, appliedTransform); } errorString = QQuickPixmap::tr("Invalid image data: %1").arg(url.toString()); } else { errorString = QQuickPixmap::tr("Cannot open: %1").arg(url.toString()); } - return new QQuickPixmapData(declarativePixmap, url, requestSize, errorString); + return new QQuickPixmapData(declarativePixmap, url, requestSize, autoTransform, errorString); } @@ -1132,7 +1151,7 @@ QQuickPixmap::QQuickPixmap(QQmlEngine *engine, const QUrl &url, const QSize &siz QQuickPixmap::QQuickPixmap(const QUrl &url, const QImage &image) { - d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize()); + d = new QQuickPixmapData(this, url, new QQuickDefaultTextureFactory(image), image.size(), QSize(), UsePluginDefault, UsePluginDefault); d->addToCache(); } @@ -1205,6 +1224,14 @@ const QSize &QQuickPixmap::requestSize() const return nullPixmap()->size; } +AutoTransform QQuickPixmap::autoTransform() const +{ + if (d) + return d->appliedTransform; + else + return UsePluginDefault; +} + QQuickTextureFactory *QQuickPixmap::textureFactory() const { if (d) @@ -1279,6 +1306,11 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &size) } void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options) +{ + load(engine, url, requestSize, options, UsePluginDefault); +} + +void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &requestSize, QQuickPixmap::Options options, AutoTransform requestAutoTransform) { if (d) { d->declarativePixmaps.remove(this); @@ -1286,7 +1318,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques d = 0; } - QQuickPixmapKey key = { &url, &requestSize }; + QQuickPixmapKey key = { &url, &requestSize, requestAutoTransform }; QQuickPixmapStore *store = pixmapStore(); QHash::Iterator iter = store->m_cache.end(); @@ -1312,7 +1344,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques if (!(options & QQuickPixmap::Asynchronous)) { bool ok = false; PIXMAP_PROFILE(pixmapStateChanged(url)); - d = createPixmapDataSync(this, engine, url, requestSize, &ok); + d = createPixmapDataSync(this, engine, url, requestSize, requestAutoTransform, &ok); if (ok) { PIXMAP_PROFILE(pixmapLoadingFinished(url, QSize(width(), height()))); if (options & QQuickPixmap::Cache) @@ -1328,7 +1360,7 @@ void QQuickPixmap::load(QQmlEngine *engine, const QUrl &url, const QSize &reques if (!engine) return; - d = new QQuickPixmapData(this, url, requestSize); + d = new QQuickPixmapData(this, url, requestSize, requestAutoTransform, requestAutoTransform); if (options & QQuickPixmap::Cache) d->addToCache(); @@ -1364,7 +1396,7 @@ void QQuickPixmap::clear(QObject *obj) bool QQuickPixmap::isCached(const QUrl &url, const QSize &requestSize) { - QQuickPixmapKey key = { &url, &requestSize }; + QQuickPixmapKey key = { &url, &requestSize, UsePluginDefault }; QQuickPixmapStore *store = pixmapStore(); return store->m_cache.contains(key); diff --git a/src/quick/util/qquickpixmapcache_p.h b/src/quick/util/qquickpixmapcache_p.h index 50a9e1254c..482a2e5653 100644 --- a/src/quick/util/qquickpixmapcache_p.h +++ b/src/quick/util/qquickpixmapcache_p.h @@ -49,6 +49,12 @@ class QQmlEngine; class QQuickPixmapData; class QQuickTextureFactory; +enum AutoTransform { + UsePluginDefault = -1, + ApplyTransform = 0, + DoNotApplyTransform = 1 +}; + class QQuickDefaultTextureFactory : public QQuickTextureFactory { Q_OBJECT @@ -92,6 +98,7 @@ public: const QUrl &url() const; const QSize &implicitSize() const; const QSize &requestSize() const; + AutoTransform autoTransform() const; QImage image() const; void setImage(const QImage &); void setPixmap(const QQuickPixmap &other); @@ -106,6 +113,7 @@ public: void load(QQmlEngine *, const QUrl &, QQuickPixmap::Options options); void load(QQmlEngine *, const QUrl &, const QSize &); void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options); + void load(QQmlEngine *, const QUrl &, const QSize &, QQuickPixmap::Options options, AutoTransform autoTransform); void clear(); void clear(QObject *); -- cgit v1.2.3 From 65a28bb1cd871d9332bc0734bc0a2f1a1e1bbeab Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Thu, 12 Mar 2015 14:26:00 +0100 Subject: Fix null pointer dereference in QQmlImportNamespace Change-Id: Iaf61f38790b0dfddb924043e0a25eb8a882571c8 Reviewed-by: Simon Hausmann --- src/qml/qml/qqmlimport.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp index 906e073cab..5a54609e12 100644 --- a/src/qml/qml/qqmlimport.cpp +++ b/src/qml/qml/qqmlimport.cpp @@ -653,9 +653,10 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, } if (candidate != end) { + QQmlType *returnType = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0); if (type_return) - *type_return = getTypeForUrl(componentUrl, type, isCompositeSingleton, 0); - return (*type_return != 0); + *type_return = returnType; + return returnType != 0; } } else if (!isLibrary) { QString qmlUrl; @@ -679,9 +680,10 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader, if (typeRecursionDetected) *typeRecursionDetected = true; } else { + QQmlType *returnType = getTypeForUrl(qmlUrl, type, false, 0); if (type_return) - *type_return = getTypeForUrl(qmlUrl, type, false, 0); - return (*type_return) != 0; + *type_return = returnType; + return returnType != 0; } } } -- cgit v1.2.3 From eb2ea7098512bdc241b7fdabf5c21c229d56fc07 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 7 May 2015 19:14:23 +0200 Subject: Fix basic and windows render loops to use the correct screen GLX, and potentially other platforms too, require that compatible contexts and surfaces are created with the same screen. This makes Quick functional on X.org configurations where each physical screen represents a separate X screen on the same X display. Change-Id: I03c87819e1aee148c880a3caca13d4a0c5409056 Reviewed-by: Gunnar Sletta --- src/quick/scenegraph/qsgrenderloop.cpp | 1 + src/quick/scenegraph/qsgwindowsrenderloop.cpp | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index 781e82fbc4..ec9c3c39f9 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -320,6 +320,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window) if (!gl) { gl = new QOpenGLContext(); gl->setFormat(window->requestedFormat()); + gl->setScreen(window->screen()); if (qt_gl_global_share_context()) gl->setShareContext(qt_gl_global_share_context()); if (!gl->create()) { diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp index 309e877dae..c571e60018 100644 --- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp +++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp @@ -162,6 +162,7 @@ void QSGWindowsRenderLoop::show(QQuickWindow *window) RLDEBUG(" - creating GL context"); m_gl = new QOpenGLContext(); m_gl->setFormat(window->requestedFormat()); + m_gl->setScreen(window->screen()); if (qt_gl_global_share_context()) m_gl->setShareContext(qt_gl_global_share_context()); bool created = m_gl->create(); -- cgit v1.2.3 From b8db3a1c6036e6d8ab68b5f1c01a00c289a67ab8 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Tue, 19 May 2015 11:20:12 +0200 Subject: qquickwindow: ensure we delete the correct delayed touch event after delivery Delivering a delayed touch event from QQuickWindow can cause the event loop to recurse (e.g if it starts a drag'n'drop). This again can cause new touch events to be delivered to QQuickWindow, and new delayed touch events to be stored. This results in the following: (1) Receive new touch press event in QQuickWindow, and set delayedTouch to be a copy of it (2) Deliver delayedTouch to items. This can cause an event loop recursion. (3) While inside the recursion, QQuickWindow receives another new touch press event. We then redeliver and delete the current delayedTouch event created in (1), and set delayedTouch to be a copy of the new event. (4) Later we return back from (2), and try to access delayedTouch (or actually a reference to the touchpoints inside it, qquickwindow.cpp:1958). Since the event was deleted in (3), we have a crash. This patch will ensure that we set delayedTouch to 0 before delivering it (so it cannot be redelivered), and that we safely delete it afterwards when it goes out of scope. By converting delayedTouch to a QScopedPointer we also ensure that the event is not leaked upon destruction. Task-number: QTBUG-45877 Change-Id: Ic372a39a0eb127abfd12cec2d51b3743ad83194d Reviewed-by: Simon Hausmann --- src/quick/items/qquickwindow.cpp | 30 +++++++++++++++--------------- src/quick/items/qquickwindow_p.h | 3 ++- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 0b1c79567f..84b585e3b5 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -467,8 +467,6 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control) animationController = new QQuickAnimatorController(q); - delayedTouch = 0; - QObject::connect(context, SIGNAL(initialized()), q, SIGNAL(sceneGraphInitialized()), Qt::DirectConnection); QObject::connect(context, SIGNAL(invalidated()), q, SIGNAL(sceneGraphInvalidated()), Qt::DirectConnection); QObject::connect(context, SIGNAL(invalidated()), q, SLOT(cleanupSceneGraph()), Qt::DirectConnection); @@ -1835,6 +1833,15 @@ bool QQuickWindowPrivate::deliverTouchCancelEvent(QTouchEvent *event) return true; } +void QQuickWindowPrivate::deliverDelayedTouchEvent() +{ + // Deliver and delete delayedTouch. + // Set delayedTouch to 0 before delivery to avoid redelivery in case of + // event loop recursions (e.g if it the touch starts a dnd session). + QScopedPointer e(delayedTouch.take()); + reallyDeliverTouchEvent(e.data()); +} + static bool qquickwindow_no_touch_compression = qEnvironmentVariableIsSet("QML_NO_TOUCH_COMPRESSION"); // check what kind of touch we have (begin/update) and @@ -1854,7 +1861,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event) && ((states & (Qt::TouchPointPressed | Qt::TouchPointReleased)) == 0)) { // we can only compress something that isn't a press or release if (!delayedTouch) { - delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints()); + delayedTouch.reset(new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints())); delayedTouch->setTimestamp(event->timestamp()); if (renderControl) QQuickRenderControlPrivate::get(renderControl)->maybeUpdate(); @@ -1900,19 +1907,14 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event) } // merging wasn't possible, so deliver the delayed event first, and then delay this one - reallyDeliverTouchEvent(delayedTouch); - delete delayedTouch; - delayedTouch = new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints()); + deliverDelayedTouchEvent(); + delayedTouch.reset(new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints())); delayedTouch->setTimestamp(event->timestamp()); return; } } else { - if (delayedTouch) { - // deliver the delayed touch first - reallyDeliverTouchEvent(delayedTouch); - delete delayedTouch; - delayedTouch = 0; - } + if (delayedTouch) + deliverDelayedTouchEvent(); reallyDeliverTouchEvent(event); } } @@ -1920,9 +1922,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event) void QQuickWindowPrivate::flushDelayedTouchEvent() { if (delayedTouch) { - reallyDeliverTouchEvent(delayedTouch); - delete delayedTouch; - delayedTouch = 0; + deliverDelayedTouchEvent(); // Touch events which constantly start animations (such as a behavior tracking // the mouse point) need animations to start. diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index a61c0b0346..605a36fb1d 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -151,6 +151,7 @@ public: void deliverTouchEvent(QTouchEvent *); void reallyDeliverTouchEvent(QTouchEvent *); bool deliverTouchCancelEvent(QTouchEvent *); + void deliverDelayedTouchEvent(); void flushDelayedTouchEvent(); bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted); bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet *acceptedNewPoints, const QSet &matchingNewPoints, const QList &matchingPoints, QSet *filtered); @@ -219,7 +220,7 @@ public: QSGRenderLoop *windowManager; QQuickRenderControl *renderControl; QQuickAnimatorController *animationController; - QTouchEvent *delayedTouch; + QScopedPointer delayedTouch; int touchRecursionGuard; QQuickCustomRenderStage *customRenderStage; -- cgit v1.2.3 From 1ebee6e995541554aa9250ccf3326d2579c237c6 Mon Sep 17 00:00:00 2001 From: Jocelyn Turcotte Date: Wed, 20 May 2015 16:29:45 +0200 Subject: Fix the implicitSize of SVG Images on retina display If the user relies on the Image implicitSize to do the layout but still sets sourceSize to the image, the sourceSize might be (0, 0) instead of (-1, -1). readImage checks that the size is > 0 to use the requestedSize and this would cause us not to use the requestedSize, but still divide by the devicePixelRatio in QQuickImageBase::pixmapChange, which would give a different implicitSize on retina display. Make sure that we get the same implicitSize on both by only keeping the targetDevicePixelRatio if sourceSize is > (0, 0) like readImage does. Task-number: QTBUG-38991 Change-Id: Ib93f57efa47d096f88883845985b44f62db4ad74 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/quick/items/qquickimagebase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quick/items/qquickimagebase.cpp b/src/quick/items/qquickimagebase.cpp index 8fba6e3d12..0e2134842b 100644 --- a/src/quick/items/qquickimagebase.cpp +++ b/src/quick/items/qquickimagebase.cpp @@ -219,7 +219,7 @@ void QQuickImageBase::load() // QQuickImageProvider and SVG can generate a high resolution image when // sourceSize is set. If sourceSize is not set then the provider default size // will be used, as usual. - if (d->sourcesize.isValid()) + if (!d->sourcesize.isEmpty()) d->devicePixelRatio = targetDevicePixelRatio; } else { // (possible) local file: loadUrl and d->devicePixelRatio will be modified if -- cgit v1.2.3 From dad48f0e9cca10528fcaab7ec7d08f678e81b1a9 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Sat, 23 May 2015 14:10:36 +0200 Subject: Makes it possible to extract all data from a QML DropArea There's many types that aren't being covered by DropArea API, such as images. getDataAsString is not acceptable, since fromUtf8 chokes on reading non-utf8. This patch introduces getDataAsArrayBuffer method that won't try to convert the data into a QString and simply pass a QV4::ArrayBuffer, that internally keeps a QByteArray. Change-Id: I65411b3d365ee6c5e13effd9167156771ee08a05 Reviewed-by: Simon Hausmann --- src/qml/jsruntime/qv4engine.cpp | 2 ++ src/quick/items/qquickdroparea.cpp | 20 ++++++++++++++++++++ src/quick/items/qquickdroparea_p.h | 1 + 3 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 5e450859ec..ba6f5a3b79 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1266,6 +1266,8 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return ld->d()->locale; if (QV4::DateObject *d = value.asDateObject()) return d->toQDateTime(); + if (QV4::ArrayBuffer *d = value.as()) + return d->asByteArray(); // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)! QV4::ScopedObject o(scope, value); diff --git a/src/quick/items/qquickdroparea.cpp b/src/quick/items/qquickdroparea.cpp index 217b455d43..e46d546a16 100644 --- a/src/quick/items/qquickdroparea.cpp +++ b/src/quick/items/qquickdroparea.cpp @@ -36,6 +36,7 @@ #include "qquickitem_p.h" #include "qquickwindow.h" +#include #include #ifndef QT_NO_DRAGANDDROP @@ -496,6 +497,14 @@ void QQuickDropArea::dropEvent(QDropEvent *event) Returns the data for the given \a format converted to a string. \a format should be one contained in the \l formats property. */ +/*! + \qmlmethod string QtQuick::DragEvent::getDataAsArrayBuffer(string format) + \since 5.5 + + Returns the data for the given \a format into an ArrayBuffer, which can + easily be translated into a QByteArray. \a format should be one contained in the \l formats property. +*/ + QObject *QQuickDropEvent::source() { if (const QQuickDragMimeData *dragMime = qobject_cast(event->mimeData())) @@ -566,6 +575,17 @@ void QQuickDropEvent::getDataAsString(QQmlV4Function *args) } } +void QQuickDropEvent::getDataAsArrayBuffer(QQmlV4Function *args) +{ + if (args->length() != 0) { + QV4::ExecutionEngine *v4 = args->v4engine(); + QV4::Scope scope(v4); + QV4::ScopedValue v(scope, (*args)[0]); + const QString format = v->toQString(); + args->setReturnValue(v4->newArrayBuffer(event->mimeData()->data(format))->asReturnedValue()); + } +} + void QQuickDropEvent::acceptProposedAction(QQmlV4Function *) { event->acceptProposedAction(); diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h index e35ec40757..3223f4203b 100644 --- a/src/quick/items/qquickdroparea_p.h +++ b/src/quick/items/qquickdroparea_p.h @@ -96,6 +96,7 @@ public: QStringList formats() const; Q_INVOKABLE void getDataAsString(QQmlV4Function *); + Q_INVOKABLE void getDataAsArrayBuffer(QQmlV4Function *); Q_INVOKABLE void acceptProposedAction(QQmlV4Function *); Q_INVOKABLE void accept(QQmlV4Function *); -- cgit v1.2.3 From 4d722de834da30715b344db712ee12054fabe8b6 Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Thu, 28 May 2015 11:07:19 +0200 Subject: Purge use of VisualDataModel from docs where DelegateModel is required MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are the same types except that VisualDataModel is deprecated and uses a different import statement. Now, references to VisualDataModel are only used where we explicitly refer to the replacement/deprecation. Change-Id: I1e68eb5784235a00233b3882c3d91e21e32af7d1 Reviewed-by: Topi Reiniö --- src/qml/doc/snippets/delegatemodel/visualdatagroup.qml | 11 ++++++----- src/qml/doc/snippets/delegatemodel/visualdatamodel.qml | 3 ++- .../snippets/delegatemodel/visualdatamodel_rootindex/view.qml | 3 ++- src/qml/types/qquickpackage.cpp | 4 ++-- 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/qml/doc/snippets/delegatemodel/visualdatagroup.qml b/src/qml/doc/snippets/delegatemodel/visualdatagroup.qml index ca72e16b35..85ac83ae52 100644 --- a/src/qml/doc/snippets/delegatemodel/visualdatagroup.qml +++ b/src/qml/doc/snippets/delegatemodel/visualdatagroup.qml @@ -39,11 +39,12 @@ ****************************************************************************/ //![0] import QtQuick 2.0 +import QtQml.Models 2.2 Rectangle { width: 200; height: 100 - VisualDataModel { + DelegateModel { id: visualModel model: ListModel { ListElement { name: "Apple" } @@ -51,7 +52,7 @@ Rectangle { } groups: [ - VisualDataGroup { name: "selected" } + DelegateModelGroup { name: "selected" } ] delegate: Rectangle { @@ -61,14 +62,14 @@ Rectangle { Text { text: { var text = "Name: " + name - if (item.VisualDataModel.inSelected) - text += " (" + item.VisualDataModel.selectedIndex + ")" + if (item.DelegateModel.inSelected) + text += " (" + item.DelegateModel.selectedIndex + ")" return text; } } MouseArea { anchors.fill: parent - onClicked: item.VisualDataModel.inSelected = !item.VisualDataModel.inSelected + onClicked: item.DelegateModel.inSelected = !item.DelegateModel.inSelected } } } diff --git a/src/qml/doc/snippets/delegatemodel/visualdatamodel.qml b/src/qml/doc/snippets/delegatemodel/visualdatamodel.qml index cf6b5aafb9..438eafeed1 100644 --- a/src/qml/doc/snippets/delegatemodel/visualdatamodel.qml +++ b/src/qml/doc/snippets/delegatemodel/visualdatamodel.qml @@ -39,11 +39,12 @@ ****************************************************************************/ //![0] import QtQuick 2.0 +import QtQml.Models 2.2 Rectangle { width: 200; height: 100 - VisualDataModel { + DelegateModel { id: visualModel model: ListModel { ListElement { name: "Apple" } diff --git a/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml b/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml index f4e18f6ac0..719d16ff7d 100644 --- a/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml +++ b/src/qml/doc/snippets/delegatemodel/visualdatamodel_rootindex/view.qml @@ -39,13 +39,14 @@ ****************************************************************************/ //![0] import QtQuick 2.0 +import QtQml.Models 2.2 ListView { id: view width: 300 height: 400 - model: VisualDataModel { + model: DelegateModel { model: dirModel delegate: Rectangle { diff --git a/src/qml/types/qquickpackage.cpp b/src/qml/types/qquickpackage.cpp index 5fe73ec0e0..69bf058e6f 100644 --- a/src/qml/types/qquickpackage.cpp +++ b/src/qml/types/qquickpackage.cpp @@ -45,8 +45,8 @@ QT_BEGIN_NAMESPACE \ingroup qtquick-views \brief Specifies a collection of named items - The Package class is used in conjunction with - VisualDataModel to enable delegates with a shared context + The Package type is used in conjunction with + DelegateModel to enable delegates with a shared context to be provided to multiple views. Any item within a Package may be assigned a name via the -- cgit v1.2.3 From 3404e1b4af63517f8158b38d59d8287dc24c5434 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 27 May 2015 15:39:18 +0200 Subject: Document the render loops a bit more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-42699 Change-Id: Ib8a1690bfe38bd0686799fac390207c26e5a6812 Reviewed-by: Topi Reiniö Reviewed-by: Friedemann Kleint --- .../doc/src/concepts/visualcanvas/scenegraph.qdoc | 35 ++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc index ec6e0e93d5..8ef77dac4c 100644 --- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc +++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc @@ -173,8 +173,26 @@ defined by the render loop. For detailed description of how the scene graph renderer works, see \l {Qt Quick Scene Graph Renderer}. - -\section2 Threaded Render Loop +There are three render loop variants available: \c basic, \c windows, +and \c threaded. Out of these, \c basic and \c windows are +single-threaded, while \c threaded performs scene graph rendering on a +dedicated thread. Qt attempts to choose a suitable loop based on the +platform and possibly the graphics drivers in use. When this is not +satisfactory, or for testing purposes, the environment variable +\c QSG_RENDER_LOOP can be used to force the usage of a given loop. To +verify which render loop is in use, launch the application with +\c QSG_INFO set to \c 1. + +\note The \c threaded and \c windows render loops rely on the OpenGL +implementation for throttling by requesting a swap interval of 1. Some +graphics drivers allow users to override this setting and turn it off, +ignoring Qt's request. Without blocking in the swap buffers operation +(or elsewhere), the render loop will run animations too fast and spin +the CPU at 100%. If a system is known to be unable to provide +vsync-based throttling, use the \c basic render loop instead by +setting \c {QSG_RENDER_LOOP=basic} in the environment. + +\section2 Threaded Render Loop ("threaded") On many configurations, the scene graph rendering will happen on a dedicated render thread. This is done to increase parallelism of @@ -245,11 +263,12 @@ animations, process events, etc. \endlist The threaded renderer is currently used by default on Windows with -opengl32.dll, Linux with non-Mesa based drivers, OS X and EGLFS but -this is subject to change. It is possible to force use of the threaded -renderer by setting \c {QSG_RENDER_LOOP=threaded} in the environment. +opengl32.dll, Linux with non-Mesa based drivers, OS X, mobile +platforms, and Embedded Linux with EGLFS but this is subject to +change. It is possible to force use of the threaded renderer by +setting \c {QSG_RENDER_LOOP=threaded} in the environment. -\section2 Non-threaded Render Loop +\section2 Non-threaded Render Loops ("basic" and "windows") The non-threaded render loop is currently used by default on Windows with ANGLE or a non-default opengl32 implementation and Linux with @@ -259,6 +278,10 @@ been tested. At the same time implementations like ANGLE or Mesa llvmpipe are not able to function properly with threaded rendering at all so not using threaded rendering is essential for these. +By default \c windows is used for non-threaded rendering on Windows +with ANGLE, while \c basic is used for all other platforms when +non-threaded rendering is needed. + Even when using the non-threaded render loop, you should write your code as if you are using the threaded renderer, as failing to do so will make the code non-portable. -- cgit v1.2.3 From db525935ccd64d2c5c674f8a66dbe7096d754e9f Mon Sep 17 00:00:00 2001 From: Joni Poikelin Date: Fri, 29 May 2015 08:13:58 +0300 Subject: Fix flickering when QQuickWidget becomes visible QQuickWidget used short delay before rendering. This caused black area to flash on the widget briefly. Instead of scheduling redraw, render scene immediately. Task-number: QTBUG-46387 Change-Id: I342d96a1aaef3244190221807b0d816815697623 Reviewed-by: Gunnar Sletta Reviewed-by: Laszlo Agocs --- src/quickwidgets/qquickwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index f0a2a3183b..608c5f93f5 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -1065,7 +1065,7 @@ void QQuickWidget::showEvent(QShowEvent *) Q_D(QQuickWidget); d->updatePending = false; d->createContext(); - triggerUpdate(); + d->render(true); } /*! \reimp */ -- cgit v1.2.3