diff options
23 files changed, 384 insertions, 69 deletions
diff --git a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp index 965e5152c1..d963b6d1b4 100644 --- a/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp +++ b/examples/qml/tutorials/extending-qml/chapter4-customPropertyTypes/piechart.cpp @@ -41,7 +41,7 @@ #include "pieslice.h" PieChart::PieChart(QQuickItem *parent) - : QQuickItem(parent) + : QQuickItem(parent), m_pieSlice(0) { } diff --git a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp index ceb0041ec8..50c018e33e 100644 --- a/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp +++ b/examples/qml/tutorials/extending-qml/chapter5-listproperties/pieslice.cpp @@ -42,7 +42,7 @@ #include <QPainter> PieSlice::PieSlice(QQuickItem *parent) - : QQuickPaintedItem(parent) + : QQuickPaintedItem(parent), m_fromAngle(0), m_angleSpan(0) { } diff --git a/examples/quick/demos/demos.pro b/examples/quick/demos/demos.pro index 9aac7bf6f7..e6937683ab 100644 --- a/examples/quick/demos/demos.pro +++ b/examples/quick/demos/demos.pro @@ -5,9 +5,8 @@ SUBDIRS = samegame \ tweetsearch \ maroon \ photosurface \ + photoviewer \ stocqt qtHaveModule(xmlpatterns): SUBDIRS += rssnews -EXAMPLE_FILES = \ - photoviewer diff --git a/examples/quick/demos/photoviewer/deployment.pri b/examples/quick/demos/photoviewer/deployment.pri deleted file mode 100644 index 0d58a25c61..0000000000 --- a/examples/quick/demos/photoviewer/deployment.pri +++ /dev/null @@ -1,19 +0,0 @@ -android { - x86 { - target.path = /libs/x86 - } else: armeabi-v7a { - target.path = /libs/armeabi-v7a - } else { - target.path = /libs/armeabi - } - export(target.path) - INSTALLS += target -} else:unix { - isEmpty(target.path) { - target.path = /opt/$${TARGET}/bin - export(target.path) - } - INSTALLS += target -} - -export(INSTALLS) diff --git a/examples/quick/demos/photoviewer/photoviewer.pro b/examples/quick/demos/photoviewer/photoviewer.pro index 704e2ce003..4bfdb86f31 100644 --- a/examples/quick/demos/photoviewer/photoviewer.pro +++ b/examples/quick/demos/photoviewer/photoviewer.pro @@ -15,8 +15,5 @@ TRANSLATIONS += i18n/qml_fr.ts \ RESOURCES += qml.qrc -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - -# Default rules for deployment. -include(deployment.pri) +target.path = $$[QT_INSTALL_EXAMPLES]/quick/demos/photoviewer +INSTALLS += target diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index a5405dad0d..af359bc0d3 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -161,8 +161,8 @@ static void insertHoleIntoPropertyData(Object *object, int idx) static void removeFromPropertyData(Object *object, int idx, bool accessor = false) { int inlineSize = object->d()->inlineMemberSize; - int icSize = object->internalClass()->size; int delta = (accessor ? 2 : 1); + int oldSize = object->internalClass()->size + delta; int to = idx; int from = to + delta; if (from < inlineSize) { @@ -170,15 +170,15 @@ static void removeFromPropertyData(Object *object, int idx, bool accessor = fals to = inlineSize - delta; from = inlineSize; } - if (to < inlineSize && from < icSize) { + if (to < inlineSize && from < oldSize) { Q_ASSERT(from >= inlineSize); memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value)); to = inlineSize; from = inlineSize + delta; } - if (from < icSize + delta) { + if (from < oldSize) { Q_ASSERT(to >= inlineSize && from > to); - memmove(object->propertyData(to), object->d()->propertyData(from), (icSize + delta - to)*sizeof(Value)); + memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value)); } } diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 1bcc3cc0f9..f72923a0d5 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1590,13 +1590,13 @@ qreal QQuickFlickable::minXExtent() const qreal QQuickFlickable::maxXExtent() const { Q_D(const QQuickFlickable); - return qMin<qreal>(0, width() - vWidth() - d->hData.endMargin); + return qMin<qreal>(minXExtent(), width() - vWidth() - d->hData.endMargin); } /* returns -ve */ qreal QQuickFlickable::maxYExtent() const { Q_D(const QQuickFlickable); - return qMin<qreal>(0, height() - vHeight() - d->vData.endMargin); + return qMin<qreal>(minYExtent(), height() - vHeight() - d->vData.endMargin); } void QQuickFlickable::componentComplete() diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp index d5c0cc8180..5b337baac4 100644 --- a/src/quick/items/qquickshadereffect.cpp +++ b/src/quick/items/qquickshadereffect.cpp @@ -1060,7 +1060,7 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa bool geometryUsesTextureSubRect = false; if (m_supportsAtlasTextures && material->textureProviders.size() == 1) { QSGTextureProvider *provider = material->textureProviders.at(0); - if (provider->texture()) { + if (provider && provider->texture()) { srcRect = provider->texture()->normalizedTextureSubRect(); geometryUsesTextureSubRect = true; } diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index 5968028c26..9b23abc877 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -1456,8 +1456,8 @@ void QQuickTextEdit::setSelectByKeyboard(bool on) If true, the user can use the mouse to select text in some platform-specific way. Note that for some platforms this may - not be an appropriate interaction (eg. may conflict with how - the text needs to behave inside a Flickable. + not be an appropriate interaction; it may conflict with how + the text needs to behave inside a Flickable, for example. */ bool QQuickTextEdit::selectByMouse() const { diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 9ef651bffa..aedd586a4f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -706,10 +706,10 @@ bool QQuickWindowPrivate::translateTouchToMouse(QQuickItem *item, QTouchEvent *e lastMousePosition = me->windowPos(); bool accepted = me->isAccepted(); - bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), accepted); + bool delivered = deliverHoverEvent(contentItem, me->windowPos(), last, me->modifiers(), me->timestamp(), accepted); if (!delivered) { //take care of any exits - accepted = clearHover(); + accepted = clearHover(me->timestamp()); } me->setAccepted(accepted); break; @@ -1442,7 +1442,7 @@ QQuickItem *QQuickWindow::mouseGrabberItem() const } -bool QQuickWindowPrivate::clearHover() +bool QQuickWindowPrivate::clearHover(ulong timestamp) { Q_Q(QQuickWindow); if (hoverItems.isEmpty()) @@ -1452,7 +1452,7 @@ bool QQuickWindowPrivate::clearHover() bool accepted = false; foreach (QQuickItem* item, hoverItems) - accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), true) || accepted; + accepted = sendHoverEvent(QEvent::HoverLeave, item, pos, pos, QGuiApplication::keyboardModifiers(), timestamp, true) || accepted; hoverItems.clear(); return accepted; } @@ -1712,13 +1712,15 @@ void QQuickWindow::mouseDoubleClickEvent(QMouseEvent *event) bool QQuickWindowPrivate::sendHoverEvent(QEvent::Type type, QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos, - Qt::KeyboardModifiers modifiers, bool accepted) + Qt::KeyboardModifiers modifiers, ulong timestamp, + bool accepted) { Q_Q(QQuickWindow); const QTransform transform = QQuickItemPrivate::get(item)->windowToItemTransform(); //create copy of event QHoverEvent hoverEvent(type, transform.map(scenePos), transform.map(lastScenePos), modifiers); + hoverEvent.setTimestamp(timestamp); hoverEvent.setAccepted(accepted); QSet<QQuickItem *> hasFiltered; @@ -1756,10 +1758,10 @@ void QQuickWindow::mouseMoveEvent(QMouseEvent *event) d->lastMousePosition = event->windowPos(); bool accepted = event->isAccepted(); - bool delivered = d->deliverHoverEvent(d->contentItem, event->windowPos(), last, event->modifiers(), accepted); + bool delivered = d->deliverHoverEvent(d->contentItem, event->windowPos(), last, event->modifiers(), event->timestamp(), accepted); if (!delivered) { //take care of any exits - accepted = d->clearHover(); + accepted = d->clearHover(event->timestamp()); } event->setAccepted(accepted); return; @@ -1769,7 +1771,7 @@ void QQuickWindow::mouseMoveEvent(QMouseEvent *event) } bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &scenePos, const QPointF &lastScenePos, - Qt::KeyboardModifiers modifiers, bool &accepted) + Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted) { Q_Q(QQuickWindow); QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); @@ -1785,7 +1787,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce QQuickItem *child = children.at(ii); if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) continue; - if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted)) + if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, timestamp, accepted)) return true; } @@ -1794,7 +1796,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce if (item->contains(p)) { if (!hoverItems.isEmpty() && hoverItems[0] == item) { //move - accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted); + accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted); } else { QList<QQuickItem *> itemsToHover; QQuickItem* parent = item; @@ -1805,12 +1807,12 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce // Leaving from previous hovered items until we reach the item or one of its ancestors. while (!hoverItems.isEmpty() && !itemsToHover.contains(hoverItems[0])) { QQuickItem *hoverLeaveItem = hoverItems.takeFirst(); - sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, accepted); + sendHoverEvent(QEvent::HoverLeave, hoverLeaveItem, scenePos, lastScenePos, modifiers, timestamp, accepted); } if (!hoverItems.isEmpty() && hoverItems[0] == item){//Not entering a new Item // ### Shouldn't we send moves for the parent items as well? - accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, accepted); + accepted = sendHoverEvent(QEvent::HoverMove, item, scenePos, lastScenePos, modifiers, timestamp, accepted); } else { // Enter items that are not entered yet. int startIdx = -1; @@ -1829,7 +1831,7 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce // itemToHoverPrivate->window here prevents that case. if (itemToHoverPrivate->window == q && itemToHoverPrivate->hoverEnabled) { hoverItems.prepend(itemToHover); - sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, accepted); + sendHoverEvent(QEvent::HoverEnter, itemToHover, scenePos, lastScenePos, modifiers, timestamp, accepted); } } } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 9a768ab7dd..7d2b1af29b 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -161,14 +161,14 @@ public: bool deliverTouchCancelEvent(QTouchEvent *); void deliverDelayedTouchEvent(); void flushDelayedTouchEvent(); - bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted); + bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, ulong timestamp, bool &accepted); bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered); QTouchEvent *touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent); QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints); bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered); bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, - Qt::KeyboardModifiers modifiers, bool accepted); - bool clearHover(); + Qt::KeyboardModifiers modifiers, ulong timestamp, bool accepted); + bool clearHover(ulong timestamp = 0); #ifndef QT_NO_DRAGANDDROP void deliverDragEvent(QQuickDragGrabber *, QEvent *); bool deliverDragEvent(QQuickDragGrabber *, QQuickItem *, QDragMoveEvent *); diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp index 2f1c1d454c..ceab64478b 100644 --- a/src/quick/scenegraph/qsgdefaultlayer.cpp +++ b/src/quick/scenegraph/qsgdefaultlayer.cpp @@ -48,6 +48,29 @@ DEFINE_BOOL_CONFIG_OPTION(qmlFboOverlay, QML_FBO_OVERLAY) #endif DEFINE_BOOL_CONFIG_OPTION(qmlFboFlushBeforeDetach, QML_FBO_FLUSH_BEFORE_DETACH) + + +static QOpenGLFramebufferObject *createFramebuffer(const QSize &size, + QOpenGLFramebufferObjectFormat format) +{ +#ifdef Q_OS_MACOS + QOpenGLContext *context = QOpenGLContext::currentContext(); + if (context->hasExtension("GL_ARB_framebuffer_sRGB") + && context->hasExtension("GL_EXT_texture_sRGB") + && context->hasExtension("GL_EXT_texture_sRGB_decode")) + format.setInternalTextureFormat(GL_SRGB8_ALPHA8_EXT); +#endif + QOpenGLFramebufferObject *fbo = new QOpenGLFramebufferObject(size, format); +#ifdef Q_OS_MACOS + if (format.internalTextureFormat() == GL_SRGB8_ALPHA8_EXT) { + QOpenGLFunctions *funcs = context->functions(); + funcs->glBindTexture(GL_TEXTURE_2D, fbo->texture()); + funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT); + } +#endif + return fbo; +} + namespace { class BindableFbo : public QSGBindable @@ -330,7 +353,7 @@ void QSGDefaultLayer::grab() format.setInternalTextureFormat(m_format); format.setSamples(m_context->openglContext()->format().samples()); - m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format); + m_secondaryFbo = createFramebuffer(m_size, format); m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo); } else { QOpenGLFramebufferObjectFormat format; @@ -339,14 +362,14 @@ void QSGDefaultLayer::grab() if (m_recursive) { deleteFboLater = true; delete m_secondaryFbo; - m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format); + m_secondaryFbo = createFramebuffer(m_size, format); funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture()); updateBindOptions(true); m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo); } else { delete m_fbo; delete m_secondaryFbo; - m_fbo = new QOpenGLFramebufferObject(m_size, format); + m_fbo = createFramebuffer(m_size, format); m_secondaryFbo = 0; funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); updateBindOptions(true); @@ -360,7 +383,7 @@ void QSGDefaultLayer::grab() Q_ASSERT(m_fbo); Q_ASSERT(!m_multisampling); - m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format()); + m_secondaryFbo = createFramebuffer(m_size, m_fbo->format()); funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture()); updateBindOptions(true); } diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp index a93e7bbd30..27806c48ae 100644 --- a/src/quick/scenegraph/util/qsgatlastexture.cpp +++ b/src/quick/scenegraph/util/qsgatlastexture.cpp @@ -157,13 +157,13 @@ Atlas::Atlas(const QSize &size) wrongfullyReportsBgra8888Support = false; const char *ext = (const char *) QOpenGLContext::currentContext()->functions()->glGetString(GL_EXTENSIONS); - if (!wrongfullyReportsBgra8888Support + if (ext && !wrongfullyReportsBgra8888Support && (strstr(ext, "GL_EXT_bgra") || strstr(ext, "GL_EXT_texture_format_BGRA8888") || strstr(ext, "GL_IMG_texture_format_BGRA8888"))) { m_internalFormat = m_externalFormat = GL_BGRA; #if defined(Q_OS_DARWIN) && !defined(Q_OS_OSX) - } else if (strstr(ext, "GL_APPLE_texture_format_BGRA8888")) { + } else if (ext && strstr(ext, "GL_APPLE_texture_format_BGRA8888")) { m_internalFormat = GL_RGBA; m_externalFormat = GL_BGRA; #endif // IOS || TVOS diff --git a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp index 042f24c1d5..4f9088d67d 100644 --- a/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp +++ b/tests/auto/qml/debugger/qqmlprofilerservice/tst_qqmlprofilerservice.cpp @@ -588,11 +588,11 @@ void tst_QQmlProfilerService::scenegraphData() checkTraceReceived(); checkJsHeap(); - // check that at least one frame was rendered - // there should be a SGPolishAndSync + SGRendererFrame + SGRenderLoopFrame sequence - // (though we can't be sure to get the SGRenderLoopFrame in the threaded renderer) + // Check that at least one frame was rendered. + // There should be a SGContextFrame + SGRendererFrame + SGRenderLoopFrame sequence, + // but we can't be sure to get the SGRenderLoopFrame in the threaded renderer. // - // since the rendering happens in a different thread, there could be other unrelated events + // Since the rendering happens in a different thread, there could be other unrelated events // interleaved. Also, events could carry the same time stamps and be sorted in an unexpected way // if the clocks are acting up. qint64 contextFrameTime = -1; @@ -621,8 +621,13 @@ void tst_QQmlProfilerService::scenegraphData() foreach (const QQmlProfilerData &msg, m_client->asynchronousMessages) { if (msg.detailType == QQmlProfilerDefinitions::SceneGraphRenderLoopFrame) { - QVERIFY(msg.time >= renderFrameTime); - break; + if (msg.time >= contextFrameTime) { + // Make sure SceneGraphRenderLoopFrame is not between SceneGraphContextFrame and + // SceneGraphRendererFrame. A SceneGraphRenderLoopFrame before everything else is + // OK as the scene graph might decide to do an initial rendering. + QVERIFY(msg.time >= renderFrameTime); + break; + } } } } diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml new file mode 100644 index 0000000000..8f7d5f2a70 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_54589.qml @@ -0,0 +1,16 @@ +import QtQuick 2.0 + +QtObject { + function checkPropertyDeletion() { + var o = { + x: 1, + y: 2 + }; + o.z = 3 + delete o.y; + + return (o.x === 1 && o.y === undefined && o.z === 3) + } + + property bool result: checkPropertyDeletion() +} diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 29f81cd063..f185fea1d5 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -323,6 +323,7 @@ private slots: void switchExpression(); void qtbug_46022(); void qtbug_52340(); + void qtbug_54589(); private: // static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter); @@ -7915,6 +7916,16 @@ void tst_qqmlecmascript::qtbug_52340() QVERIFY(returnValue.toBool()); } +void tst_qqmlecmascript::qtbug_54589() +{ + QQmlComponent component(&engine, testFileUrl("qtbug_54589.qml")); + + QScopedPointer<QObject> obj(component.create()); + QVERIFY(obj != 0); + QCOMPARE(obj->property("result").toBool(), true); +} + + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc" diff --git a/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml new file mode 100644 index 0000000000..07bad683ee --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/ratios_smallContent.qml @@ -0,0 +1,19 @@ +import QtQuick 2.0 + +Flickable { + property double heightRatioIs: visibleArea.heightRatio + property double widthRatioIs: visibleArea.widthRatio + + width: 200 + height: 200 + contentWidth: item.width + contentHeight: item.height + topMargin: 20 + leftMargin: 40 + + Item { + id: item + width: 100 + height: 100 + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 006c55542a..96fe97f372 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -90,6 +90,7 @@ private slots: void movementFromProgrammaticFlick(); void cleanup(); void contentSize(); + void ratios_smallContent(); private: void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to); @@ -1812,6 +1813,33 @@ void tst_qquickflickable::contentSize() QCOMPARE(chspy.count(), 1); } +// QTBUG-53726 +void tst_qquickflickable::ratios_smallContent() +{ + QScopedPointer<QQuickView> window(new QQuickView); + window->setSource(testFileUrl("ratios_smallContent.qml")); + QTRY_COMPARE(window->status(), QQuickView::Ready); + QQuickViewTestUtil::centerOnScreen(window.data()); + QQuickViewTestUtil::moveMouseAway(window.data()); + window->setTitle(QTest::currentTestFunction()); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window.data())); + QQuickItem *root = window->rootObject(); + QVERIFY(root); + QQuickFlickable *obj = qobject_cast<QQuickFlickable*>(root); + QVERIFY(obj != 0); + + //doublecheck the item, as specified by contentWidth/Height, fits in the view + //use tryCompare to allow a bit of stabilization in component's properties + QTRY_COMPARE(obj->leftMargin() + obj->contentWidth() + obj->rightMargin() <= obj->width(), true); + QTRY_COMPARE(obj->topMargin() + obj->contentHeight() + obj->bottomMargin() <= obj->height(), true); + + //the whole item fits in the flickable, heightRatio should be 1 + QCOMPARE(obj->property("heightRatioIs").toDouble(), 1.); + QCOMPARE(obj->property("widthRatioIs").toDouble(), 1.); +} + + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp index b83edec996..bf9df7850d 100644 --- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp @@ -653,11 +653,9 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v #endif QList<FxViewItem *> visibleItems = QQuickItemViewPrivate::get(listview)->visibleItems; - for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt) - { + for (QList<FxViewItem *>::const_iterator itemIt = visibleItems.begin(); itemIt != visibleItems.end(); ++itemIt) { FxViewItem *item = *itemIt; - if (item->item->position().y() >= 0 && item->item->position().y() < listview->height()) - { + if (item->item->position().y() >= 0 && item->item->position().y() < listview->height()) { QVERIFY(!QQuickItemPrivate::get(item->item)->culled); } } diff --git a/tests/auto/quick/qquickshadereffect/data/MyIcon.qml b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml new file mode 100644 index 0000000000..b83da321f2 --- /dev/null +++ b/tests/auto/quick/qquickshadereffect/data/MyIcon.qml @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 + +Item { + id: root + + property alias source: image.source + property bool shaderActive: false + + implicitWidth: image.width + + Image { + id: image + objectName: "image" + anchors { top: parent.top; bottom: parent.bottom } + sourceSize.height: height + + visible: !shaderActive + } + + ShaderEffect { + id: colorizedImage + + anchors.fill: parent + visible: shaderActive && image.status == Image.Ready + supportsAtlasTextures: true + + property Image source: visible ? image : null + + fragmentShader: " + varying highp vec2 qt_TexCoord0; + uniform sampler2D source; + void main() { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + }" + } +} diff --git a/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml new file mode 100644 index 0000000000..d1292f74b8 --- /dev/null +++ b/tests/auto/quick/qquickshadereffect/data/twoImagesOneShaderEffect.qml @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Canonical Limited and/or its subsidiary(-ies). +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.4 + +Item { + width: 400 + height: 700 + + MyIcon { + id: icon + + height: 24 + source: "star.png" + shaderActive: true + } + + MyIcon { + anchors.top: icon.bottom + + height: 24 + source: "star.png" + } +} diff --git a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp index d0e718fb91..483cdf7a41 100644 --- a/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp +++ b/tests/auto/quick/qquickshadereffect/tst_qquickshadereffect.cpp @@ -76,6 +76,7 @@ private slots: void deleteSourceItem(); void deleteShaderEffectSource(); + void twoImagesOneShaderEffect(); private: enum PresenceFlags { @@ -302,6 +303,19 @@ void tst_qquickshadereffect::deleteShaderEffectSource() delete view; } +void tst_qquickshadereffect::twoImagesOneShaderEffect() +{ + // purely to ensure that deleting the sourceItem of a shader doesn't cause a crash + QQuickView *view = new QQuickView(0); + view->setSource(QUrl::fromLocalFile(testFile("twoImagesOneShaderEffect.qml"))); + view->show(); + QVERIFY(QTest::qWaitForWindowExposed(view)); + QVERIFY(view); + QObject *obj = view->rootObject(); + QVERIFY(obj); + delete view; +} + QTEST_MAIN(tst_qquickshadereffect) #include "tst_qquickshadereffect.moc" diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index 526f61ceb5..1365e8b751 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -367,6 +367,7 @@ private slots: void testRenderJob(); void testHoverChildMouseEventFilter(); + void testHoverTimestamp(); private: QTouchDevice *touchDevice; QTouchDevice *touchDeviceWithVelocity; @@ -2303,6 +2304,90 @@ void tst_qquickwindow::testHoverChildMouseEventFilter() QCOMPARE(middleItem->eventCount(QEvent::HoverEnter), 0); } +class HoverTimestampConsumer : public QQuickItem +{ + Q_OBJECT +public: + HoverTimestampConsumer(QQuickItem *parent = 0) + : QQuickItem(parent) + { + setAcceptHoverEvents(true); + } + + void hoverEnterEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); } + void hoverLeaveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); } + void hoverMoveEvent(QHoverEvent *event) { hoverTimestamps << event->timestamp(); } + + QList<ulong> hoverTimestamps; +}; + +// Checks that a QHoverEvent carries the timestamp of the QMouseEvent that caused it. +// QTBUG-54600 +void tst_qquickwindow::testHoverTimestamp() +{ + QQuickWindow window; + + window.resize(200, 200); + window.setPosition(100, 100); + window.setTitle(QTest::currentTestFunction()); + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + + HoverTimestampConsumer *hoverConsumer = new HoverTimestampConsumer(window.contentItem()); + hoverConsumer->setWidth(100); + hoverConsumer->setHeight(100); + hoverConsumer->setX(50); + hoverConsumer->setY(50); + + // First position, outside + { + QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(40, 40), QPointF(40, 40), QPointF(140, 140), + Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized); + mouseEvent.setTimestamp(10); + QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent)); + } + + // Enter + { + QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(50, 50), QPointF(50, 50), QPointF(150, 150), + Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized); + mouseEvent.setTimestamp(20); + QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent)); + } + QCOMPARE(hoverConsumer->hoverTimestamps.size(), 1); + QCOMPARE(hoverConsumer->hoverTimestamps.last(), 20UL); + + // Move + { + QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(60, 60), QPointF(60, 60), QPointF(160, 160), + Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized); + mouseEvent.setTimestamp(30); + QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent)); + } + QCOMPARE(hoverConsumer->hoverTimestamps.size(), 2); + QCOMPARE(hoverConsumer->hoverTimestamps.last(), 30UL); + + // Move + { + QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(100, 100), QPointF(100, 100), QPointF(200, 200), + Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized); + mouseEvent.setTimestamp(40); + QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent)); + } + QCOMPARE(hoverConsumer->hoverTimestamps.size(), 3); + QCOMPARE(hoverConsumer->hoverTimestamps.last(), 40UL); + + // Leave + { + QMouseEvent mouseEvent(QEvent::MouseMove, QPointF(160, 160), QPointF(160, 160), QPointF(260, 260), + Qt::NoButton, Qt::NoButton, Qt::NoModifier, Qt::MouseEventNotSynthesized); + mouseEvent.setTimestamp(5); + QVERIFY(QCoreApplication::sendEvent(&window, &mouseEvent)); + } + QCOMPARE(hoverConsumer->hoverTimestamps.size(), 4); + QCOMPARE(hoverConsumer->hoverTimestamps.last(), 5UL); +} + QTEST_MAIN(tst_qquickwindow) #include "tst_qquickwindow.moc" |